summaryrefslogtreecommitdiff
path: root/test/date/test_date_attr.rb
AgeCommit message (Expand)Author
2018-12-11test/date: removed unnecessaruy `__send__`nobu
2017-11-10Do not define test method instead of skip when Calendar class is not defined.hsbt
2017-01-27{ext,test}/date: Specify frozen_string_literal: true.kazu
2015-12-16Add frozen_string_literal: false for all filesnaruse
2014-08-01* test/date/test_date.rb: remove commented-out code.hsbt
2012-02-22 * reverted 34739 for test/date.tadf
2012-02-22* test/date, test/rdoc: exclude tests dependent on unbundled libraries.nobu
2011-05-08 * test/ruby/test_{complex2,complexrational}.rb: use skip.tadf
2011-05-08 * test/date/*.rb: NEVER SKIP.tadf
2011-05-08 * test/date/*.rb: reverted 31432.tadf
2011-05-08 * test/date/*.rb: reverted 31483.tadf
2011-05-08Revert r31478.naruse
2011-05-08 * test/date/*.rb: use skip /w messages.tadf
2011-04-26 * ext/date/date_core.c: modified validation methods.tadf
2011-03-01 * test/date/{test_date.rb,test_date_attr.rb}: [ruby-dev:43280]tadf
2008-11-24 * lib/date.rb (inspect): changed again.tadf
2008-11-11 * lib/date.rb (inspect): reverted the previous change.tadf
2008-11-10 * lib/date.rb (inspect): changed the format.tadf
2008-09-28 * test/date/*.rb: imported a date test suite ruby 1.9 limited ed.tadf
ight'>27
-rw-r--r--.github/workflows/check_misc.yml97
-rw-r--r--.github/workflows/codeql-analysis.yml48
-rw-r--r--.github/workflows/compilers.yml303
-rw-r--r--.github/workflows/macos.yml113
-rw-r--r--.github/workflows/mingw.yml51
-rw-r--r--.github/workflows/mjit-bindgen.yml104
-rw-r--r--.github/workflows/mjit.yml50
-rw-r--r--.github/workflows/publish.yml18
-rw-r--r--.github/workflows/scorecards.yml72
-rw-r--r--.github/workflows/spec_guards.yml50
-rw-r--r--.github/workflows/ubuntu.yml66
-rw-r--r--.github/workflows/wasm.yml56
-rw-r--r--.github/workflows/windows.yml89
-rw-r--r--.github/workflows/yjit-ubuntu.yml115
-rw-r--r--.github/workflows/yjit_asm_tests.yml38
-rw-r--r--.gitignore17
-rw-r--r--.indent.pro32
-rw-r--r--.travis.yml234
-rw-r--r--CONTRIBUTING.md6
-rw-r--r--LEGAL10
-rw-r--r--NEWS.md770
-rw-r--r--README.ja.md1
-rw-r--r--README.md141
-rw-r--r--addr2line.c457
-rw-r--r--array.c3119
-rw-r--r--ast.c64
-rw-r--r--ast.rb110
-rw-r--r--benchmark/README.md8
-rw-r--r--benchmark/array_sort_int.yml15
-rw-r--r--benchmark/buffer_each.yml27
-rw-r--r--benchmark/buffer_get.yml32
-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/io_write.rb22
-rw-r--r--benchmark/lib/benchmark_driver/runner/mjit.rb2
-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/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_parse.yml2
-rw-r--r--benchmark/vm_const.yml6
-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_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.c1170
-rwxr-xr-xbin/gem19
-rwxr-xr-xbootstraptest/runner.rb94
-rw-r--r--bootstraptest/test_attr.rb16
-rw-r--r--bootstraptest/test_constant_cache.rb187
-rw-r--r--bootstraptest/test_io.rb3
-rw-r--r--bootstraptest/test_ractor.rb56
-rw-r--r--bootstraptest/test_yjit.rb749
-rw-r--r--bootstraptest/test_yjit_rust_port.rb422
-rw-r--r--builtin.h77
-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.c720
-rw-r--r--common.mk1376
-rw-r--r--compar.c36
-rw-r--r--compile.c7570
-rw-r--r--complex.c793
-rw-r--r--configure.ac668
-rw-r--r--cont.c984
-rw-r--r--coroutine/amd64/Context.h25
-rw-r--r--coroutine/arm64/Context.h25
-rw-r--r--coroutine/asyncify/Context.h8
-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.in35
-rw-r--r--darray.h67
-rw-r--r--debug.c363
-rw-r--r--debug_counter.c36
-rw-r--r--debug_counter.h45
-rw-r--r--defs/gmake.mk201
-rw-r--r--defs/id.def6
-rw-r--r--defs/keywords2
-rw-r--r--defs/lex.c.src2
-rw-r--r--dir.c1760
-rw-r--r--dir.rb86
-rw-r--r--dln.c181
-rw-r--r--dln_find.c246
-rw-r--r--dmyenc.c2
-rw-r--r--doc/.document3
-rw-r--r--doc/ChangeLog-0.60_to_1.12
-rw-r--r--doc/ChangeLog-1.9.32
-rw-r--r--doc/ChangeLog-2.0.08
-rw-r--r--doc/ChangeLog-2.3.015
-rw-r--r--doc/NEWS/NEWS-3.0.0.md12
-rw-r--r--doc/case_mapping.rdoc4
-rw-r--r--doc/command_injection.rdoc2
-rw-r--r--doc/contributing.md12
-rw-r--r--doc/contributing.rdoc402
-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.rdoc327
-rw-r--r--doc/encodings.rdoc (renamed from doc/encoding.rdoc)13
-rw-r--r--doc/examples/files.rdoc26
-rw-r--r--doc/extension.ja.rdoc25
-rw-r--r--doc/extension.rdoc16
-rw-r--r--doc/format_specifications.rdoc348
-rw-r--r--doc/hacking.md104
-rw-r--r--doc/implicit_conversion.rdoc23
-rw-r--r--doc/maintainers.rdoc10
-rw-r--r--doc/make_cheatsheet.md124
-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/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/creates_option.rdoc4
-rw-r--r--doc/optparse/option_params.rdoc4
-rw-r--r--doc/optparse/tutorial.rdoc2
-rw-r--r--doc/packed_data.rdoc590
-rw-r--r--doc/rdoc/markup_reference.rb1257
-rw-r--r--doc/regexp.rdoc62
-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/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_char.rdoc17
-rw-r--r--doc/string/each_codepoint.rdoc18
-rw-r--r--doc/string/each_grapheme_cluster.rdoc12
-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.rdoc66
-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.rdoc2
-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/control_expressions.rdoc26
-rw-r--r--doc/syntax/literals.rdoc83
-rw-r--r--doc/syntax/modules_and_classes.rdoc4
-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.rdoc2
-rw-r--r--doc/yjit/yjit.md328
-rw-r--r--enc/Makefile.in4
-rw-r--r--enc/ascii.c6
-rw-r--r--enc/cesu_8.c23
-rw-r--r--enc/depend1
-rw-r--r--enc/encdb.c2
-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/unicode/15.0.0/casefold.h (renamed from enc/unicode/14.0.0/casefold.h)8
-rw-r--r--enc/unicode/15.0.0/name2ctype.h (renamed from enc/unicode/14.0.0/name2ctype.h)3097
-rw-r--r--enc/utf_16_32.h2
-rw-r--r--encindex.h6
-rw-r--r--encoding.c752
-rw-r--r--enum.c1015
-rw-r--r--enumerator.c983
-rw-r--r--error.c877
-rw-r--r--eval.c828
-rw-r--r--eval_error.c442
-rw-r--r--eval_intern.h6
-rw-r--r--eval_jump.c38
-rw-r--r--ext/-test-/abi/extconf.rb1
-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-/debug/inspector.c14
-rw-r--r--ext/-test-/debug/profile_frames.c27
-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/enumerator_kw.c3
-rw-r--r--ext/-test-/eval/eval.c13
-rw-r--r--ext/-test-/eval/extconf.rb2
-rw-r--r--ext/-test-/file/fs.c14
-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-/marshal/internal_ivar/internal_ivar.c5
-rw-r--r--ext/-test-/memory_status/memory_status.c12
-rw-r--r--ext/-test-/num2int/num2int.c26
-rw-r--r--ext/-test-/printf/printf.c64
-rw-r--r--ext/-test-/proc/super.c2
-rw-r--r--ext/-test-/random/bad_version.c135
-rw-r--r--ext/-test-/random/depend160
-rw-r--r--ext/-test-/random/loop.c1
-rw-r--r--ext/-test-/rational/depend1
-rw-r--r--ext/-test-/rb_call_super_kw/rb_call_super_kw.c3
-rw-r--r--ext/-test-/st/foreach/foreach.c100
-rw-r--r--ext/-test-/st/numhash/numhash.c16
-rw-r--r--ext/-test-/st/update/update.c12
-rw-r--r--ext/-test-/string/coderange.c8
-rw-r--r--ext/-test-/string/cstr.c16
-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/member.c2
-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-/tracepoint/gc_hook.c26
-rw-r--r--ext/-test-/tracepoint/tracepoint.c54
-rw-r--r--ext/-test-/typeddata/typeddata.c2
-rw-r--r--ext/-test-/vm/at_exit.c12
-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.c1378
-rw-r--r--ext/bigdecimal/bigdecimal.gemspec4
-rw-r--r--ext/bigdecimal/bigdecimal.h48
-rw-r--r--ext/bigdecimal/extconf.rb4
-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/escape.c353
-rw-r--r--ext/coverage/coverage.c216
-rw-r--r--ext/coverage/depend6
-rw-r--r--ext/date/date.gemspec24
-rw-r--r--ext/date/date_core.c1964
-rw-r--r--ext/date/date_parse.c72
-rw-r--r--ext/date/date_strptime.c105
-rw-r--r--ext/date/lib/date.rb6
-rw-r--r--ext/date/zonetab.h4
-rw-r--r--ext/date/zonetab.list2
-rw-r--r--ext/digest/bubblebabble/bubblebabble.c2
-rw-r--r--ext/digest/digest.c12
-rw-r--r--ext/digest/digest.h2
-rw-r--r--ext/digest/digest_conf.rb2
-rw-r--r--ext/digest/lib/digest/version.rb2
-rw-r--r--ext/digest/md5/depend1
-rw-r--r--ext/digest/sha1/depend1
-rw-r--r--ext/digest/sha2/depend1
-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/etc.c104
-rwxr-xr-xext/extmk.rb137
-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/extconf.rb30
-rw-r--r--ext/fiddle/extlibs13
-rw-r--r--ext/fiddle/fiddle.c214
-rw-r--r--ext/fiddle/fiddle.gemspec3
-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/version.rb2
-rw-r--r--ext/io/console/console.c40
-rw-r--r--ext/io/console/depend2
-rw-r--r--ext/io/console/io-console.gemspec2
-rw-r--r--ext/io/console/win32_vk.inc327
-rw-r--r--ext/io/console/win32_vk.list2
-rw-r--r--ext/io/nonblock/io-nonblock.gemspec16
-rw-r--r--ext/io/nonblock/nonblock.c67
-rw-r--r--ext/io/wait/extconf.rb2
-rw-r--r--ext/io/wait/io-wait.gemspec22
-rw-r--r--ext/io/wait/wait.c167
-rw-r--r--ext/json/VERSION2
-rw-r--r--ext/json/generator/generator.c4
-rw-r--r--ext/json/lib/json/version.rb2
-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/nkf/nkf-utf8/nkf.c14
-rw-r--r--ext/nkf/nkf.c88
-rw-r--r--ext/nkf/nkf.gemspec2
-rw-r--r--ext/objspace/depend24
-rw-r--r--ext/objspace/lib/objspace.rb97
-rw-r--r--ext/objspace/object_tracing.c167
-rw-r--r--ext/objspace/objspace.c377
-rw-r--r--ext/objspace/objspace_dump.c269
-rw-r--r--ext/openssl/History.md105
-rw-r--r--ext/openssl/extconf.rb111
-rw-r--r--ext/openssl/lib/openssl/pkey.rb20
-rw-r--r--ext/openssl/lib/openssl/ssl.rb5
-rw-r--r--ext/openssl/lib/openssl/version.rb2
-rw-r--r--ext/openssl/openssl.gemspec2
-rw-r--r--ext/openssl/ossl.h10
-rw-r--r--ext/openssl/ossl_asn1.c21
-rw-r--r--ext/openssl/ossl_bn.c36
-rw-r--r--ext/openssl/ossl_cipher.c3
-rw-r--r--ext/openssl/ossl_hmac.c8
-rw-r--r--ext/openssl/ossl_kdf.c6
-rw-r--r--ext/openssl/ossl_ocsp.c4
-rw-r--r--ext/openssl/ossl_pkey.c52
-rw-r--r--ext/openssl/ossl_pkey.h2
-rw-r--r--ext/openssl/ossl_pkey_dh.c12
-rw-r--r--ext/openssl/ossl_pkey_dsa.c14
-rw-r--r--ext/openssl/ossl_pkey_ec.c68
-rw-r--r--ext/openssl/ossl_pkey_rsa.c12
-rw-r--r--ext/openssl/ossl_ssl.c261
-rw-r--r--ext/openssl/ossl_ssl_session.c4
-rw-r--r--ext/openssl/ossl_x509cert.c6
-rw-r--r--ext/openssl/ossl_x509crl.c6
-rw-r--r--ext/openssl/ossl_x509req.c6
-rw-r--r--ext/openssl/ossl_x509revoked.c6
-rw-r--r--ext/pathname/lib/pathname.rb15
-rw-r--r--ext/pathname/pathname.c19
-rw-r--r--ext/pathname/pathname.gemspec2
-rw-r--r--ext/psych/.gitignore1
-rw-r--r--ext/psych/depend59
-rw-r--r--ext/psych/extconf.rb70
-rw-r--r--ext/psych/lib/psych.rb2
-rw-r--r--ext/psych/lib/psych/exception.rb14
-rw-r--r--ext/psych/lib/psych/parser.rb13
-rw-r--r--ext/psych/lib/psych/scalar_scanner.rb6
-rw-r--r--ext/psych/lib/psych/versions.rb4
-rw-r--r--ext/psych/lib/psych/visitors/to_ruby.rb8
-rw-r--r--ext/psych/lib/psych/visitors/yaml_tree.rb16
-rw-r--r--ext/psych/psych.gemspec3
-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/depend1
-rw-r--r--ext/pty/extconf.rb6
-rw-r--r--ext/pty/lib/expect.rb16
-rw-r--r--ext/pty/pty.c151
-rw-r--r--ext/racc/cparse/cparse.c4
-rw-r--r--ext/readline/readline-ext.gemspec6
-rw-r--r--ext/readline/readline.c4
-rw-r--r--ext/ripper/depend9
-rw-r--r--ext/ripper/eventids2.c19
-rw-r--r--ext/ripper/lib/ripper/lexer.rb9
-rw-r--r--ext/ripper/tools/preproc.rb2
-rw-r--r--ext/socket/addrinfo.h36
-rw-r--r--ext/socket/ancdata.c262
-rw-r--r--ext/socket/basicsocket.c76
-rw-r--r--ext/socket/constants.c6
-rw-r--r--ext/socket/depend15
-rw-r--r--ext/socket/extconf.rb23
-rw-r--r--ext/socket/getaddrinfo.c898
-rw-r--r--ext/socket/getnameinfo.c226
-rw-r--r--ext/socket/ifaddr.c8
-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.rb7
-rw-r--r--ext/socket/option.c98
-rw-r--r--ext/socket/raddrinfo.c264
-rw-r--r--ext/socket/rubysocket.h24
-rw-r--r--ext/socket/socket.c456
-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/stringio.c378
-rw-r--r--ext/stringio/stringio.gemspec17
-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/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.c168
-rw-r--r--ext/win32ole/win32ole.gemspec2
-rw-r--r--ext/win32ole/win32ole_event.c18
-rw-r--r--ext/win32ole/win32ole_typelib.c16
-rw-r--r--ext/zlib/extconf.rb2
-rw-r--r--ext/zlib/win32/zlib-1.2.11-mswin.patch95
-rw-r--r--ext/zlib/zlib.c30
-rw-r--r--file.c3212
-rw-r--r--gc.c5991
-rw-r--r--gc.h28
-rw-r--r--gc.rb142
-rw-r--r--gem_prelude.rb7
-rw-r--r--gems/bundled_gems30
-rw-r--r--gems/lib/core_assertions.rb1
-rw-r--r--gems/lib/envutil.rb1
-rw-r--r--gems/lib/rake/extensiontask.rb (renamed from tool/dummy-rake-compiler/rake/extensiontask.rb)5
-rw-r--r--goruby.c32
-rw-r--r--hash.c1114
-rw-r--r--hrtime.h59
-rw-r--r--id_table.c138
-rw-r--r--id_table.h5
-rw-r--r--include/ruby/assert.h2
-rw-r--r--include/ruby/debug.h35
-rw-r--r--include/ruby/fiber/scheduler.h92
-rw-r--r--include/ruby/internal/abi.h13
-rw-r--r--include/ruby/internal/anyargs.h37
-rw-r--r--include/ruby/internal/arithmetic.h3
-rw-r--r--include/ruby/internal/arithmetic/long.h2
-rw-r--r--include/ruby/internal/attr/nodiscard.h2
-rw-r--r--include/ruby/internal/attr/nonstring.h32
-rw-r--r--include/ruby/internal/config.h2
-rw-r--r--include/ruby/internal/core/rarray.h45
-rw-r--r--include/ruby/internal/core/rclass.h49
-rw-r--r--include/ruby/internal/core/robject.h61
-rw-r--r--include/ruby/internal/encoding/ctype.h101
-rw-r--r--include/ruby/internal/encoding/encoding.h10
-rw-r--r--include/ruby/internal/encoding/transcode.h18
-rw-r--r--include/ruby/internal/eval.h33
-rw-r--r--include/ruby/internal/fl_type.h19
-rw-r--r--include/ruby/internal/gc.h13
-rw-r--r--include/ruby/internal/intern/array.h6
-rw-r--r--include/ruby/internal/intern/class.h12
-rw-r--r--include/ruby/internal/intern/cont.h22
-rw-r--r--include/ruby/internal/intern/file.h2
-rw-r--r--include/ruby/internal/intern/gc.h4
-rw-r--r--include/ruby/internal/intern/hash.h11
-rw-r--r--include/ruby/internal/intern/object.h4
-rw-r--r--include/ruby/internal/intern/select/posix.h2
-rw-r--r--include/ruby/internal/intern/vm.h7
-rw-r--r--include/ruby/internal/memory.h12
-rw-r--r--include/ruby/internal/scan_args.h2
-rw-r--r--include/ruby/internal/special_consts.h87
-rw-r--r--include/ruby/io.h138
-rw-r--r--include/ruby/io/buffer.h29
-rw-r--r--include/ruby/memory_view.h2
-rw-r--r--include/ruby/onigmo.h15
-rw-r--r--include/ruby/random.h63
-rw-r--r--include/ruby/ruby.h38
-rw-r--r--include/ruby/st.h2
-rw-r--r--include/ruby/thread.h44
-rw-r--r--include/ruby/util.h4
-rw-r--r--include/ruby/version.h3
-rw-r--r--include/ruby/win32.h33
-rw-r--r--inits.c8
-rw-r--r--insns.def186
-rw-r--r--internal.h10
-rw-r--r--internal/array.h54
-rw-r--r--internal/basic_operators.h64
-rw-r--r--internal/class.h68
-rw-r--r--internal/cmdlineopt.h6
-rw-r--r--internal/compar.h32
-rw-r--r--internal/cont.h10
-rw-r--r--internal/encoding.h4
-rw-r--r--internal/eval.h1
-rw-r--r--internal/fixnum.h2
-rw-r--r--internal/gc.h9
-rw-r--r--internal/hash.h1
-rw-r--r--internal/imemo.h7
-rw-r--r--internal/numeric.h8
-rw-r--r--internal/object.h24
-rw-r--r--internal/parse.h2
-rw-r--r--internal/ractor.h6
-rw-r--r--internal/string.h8
-rw-r--r--internal/symbol.h1
-rw-r--r--internal/thread.h3
-rw-r--r--internal/time.h5
-rw-r--r--internal/variable.h15
-rw-r--r--internal/vm.h3
-rw-r--r--io.c6178
-rw-r--r--io_buffer.c2501
-rw-r--r--iseq.c2051
-rw-r--r--iseq.h102
-rw-r--r--lex.c.blt2
-rw-r--r--lib/English.gemspec2
-rw-r--r--lib/abbrev.gemspec2
-rw-r--r--lib/benchmark/version.rb2
-rw-r--r--lib/bundler.rb117
-rw-r--r--lib/bundler/build_metadata.rb2
-rw-r--r--lib/bundler/bundler.gemspec18
-rw-r--r--lib/bundler/cli.rb62
-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.rb4
-rw-r--r--lib/bundler/cli/console.rb4
-rw-r--r--lib/bundler/cli/doctor.rb10
-rw-r--r--lib/bundler/cli/gem.rb102
-rw-r--r--lib/bundler/cli/info.rb4
-rw-r--r--lib/bundler/cli/init.rb8
-rw-r--r--lib/bundler/cli/install.rb14
-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.rb12
-rw-r--r--lib/bundler/cli/show.rb2
-rw-r--r--lib/bundler/cli/viz.rb2
-rw-r--r--lib/bundler/compact_index_client/cache.rb2
-rw-r--r--lib/bundler/compact_index_client/updater.rb92
-rw-r--r--lib/bundler/constants.rb2
-rw-r--r--lib/bundler/current_ruby.rb24
-rw-r--r--lib/bundler/definition.rb450
-rw-r--r--lib/bundler/dep_proxy.rb55
-rw-r--r--lib/bundler/dependency.rb87
-rw-r--r--lib/bundler/digest.rb2
-rw-r--r--lib/bundler/dsl.rb33
-rw-r--r--lib/bundler/endpoint_specification.rb12
-rw-r--r--lib/bundler/env.rb4
-rw-r--r--lib/bundler/environment_preserver.rb5
-rw-r--r--lib/bundler/errors.rb30
-rw-r--r--lib/bundler/feature_flag.rb2
-rw-r--r--lib/bundler/fetcher.rb40
-rw-r--r--lib/bundler/fetcher/base.rb14
-rw-r--r--lib/bundler/fetcher/compact_index.rb24
-rw-r--r--lib/bundler/fetcher/dependency.rb8
-rw-r--r--lib/bundler/fetcher/downloader.rb9
-rw-r--r--lib/bundler/fetcher/index.rb3
-rw-r--r--lib/bundler/force_platform.rb18
-rw-r--r--lib/bundler/friendly_errors.rb28
-rw-r--r--lib/bundler/gem_helper.rb7
-rw-r--r--lib/bundler/gem_helpers.rb11
-rw-r--r--lib/bundler/gem_version_promoter.rb151
-rw-r--r--lib/bundler/graph.rb6
-rw-r--r--lib/bundler/index.rb64
-rw-r--r--lib/bundler/injector.rb13
-rw-r--r--lib/bundler/inline.rb30
-rw-r--r--lib/bundler/installer.rb63
-rw-r--r--lib/bundler/installer/gem_installer.rb15
-rw-r--r--lib/bundler/installer/parallel_installer.rb38
-rw-r--r--lib/bundler/installer/standalone.rb53
-rw-r--r--lib/bundler/lazy_specification.rb109
-rw-r--r--lib/bundler/lockfile_generator.rb6
-rw-r--r--lib/bundler/lockfile_parser.rb37
-rw-r--r--lib/bundler/man/bundle-add.118
-rw-r--r--lib/bundler/man/bundle-add.1.ronn14
-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.142
-rw-r--r--lib/bundler/man/bundle-config.1.ronn41
-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.135
-rw-r--r--lib/bundler/man/bundle-install.1.ronn35
-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.122
-rw-r--r--lib/bundler/man/bundle-outdated.1.ronn21
-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.12
-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.5188
-rw-r--r--lib/bundler/man/gemfile.5.ronn190
-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.rb4
-rw-r--r--lib/bundler/plugin/api/source.rb12
-rw-r--r--lib/bundler/plugin/index.rb10
-rw-r--r--lib/bundler/plugin/installer.rb7
-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/remote_specification.rb19
-rw-r--r--lib/bundler/resolver.rb638
-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.rb112
-rw-r--r--lib/bundler/ruby_dsl.rb8
-rw-r--r--lib/bundler/ruby_version.rb29
-rw-r--r--lib/bundler/rubygems_ext.rb156
-rw-r--r--lib/bundler/rubygems_gem_installer.rb52
-rw-r--r--lib/bundler/rubygems_integration.rb50
-rw-r--r--lib/bundler/runtime.rb9
-rw-r--r--lib/bundler/safe_marshal.rb31
-rw-r--r--lib/bundler/settings.rb18
-rw-r--r--lib/bundler/setup.rb5
-rw-r--r--lib/bundler/shared_helpers.rb24
-rw-r--r--lib/bundler/source.rb9
-rw-r--r--lib/bundler/source/git.rb99
-rw-r--r--lib/bundler/source/git/git_proxy.rb316
-rw-r--r--lib/bundler/source/metadata.rb5
-rw-r--r--lib/bundler/source/path.rb14
-rw-r--r--lib/bundler/source/path/installer.rb23
-rw-r--r--lib/bundler/source/rubygems.rb213
-rw-r--r--lib/bundler/source_list.rb10
-rw-r--r--lib/bundler/spec_set.rb96
-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/gems.rb5
-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.tt10
-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.tt12
-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.tt13
-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.rb47
-rw-r--r--lib/bundler/ui/silent.rb26
-rw-r--r--lib/bundler/uri_normalizer.rb23
-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/shell/basic.rb2
-rw-r--r--lib/bundler/vendor/tmpdir/lib/tmpdir.rb154
-rw-r--r--lib/bundler/vendor/tsort/lib/tsort.rb637
-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_molinillo.rb4
-rw-r--r--lib/bundler/vendored_persistent.rb34
-rw-r--r--lib/bundler/vendored_pub_grub.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.rb2
-rw-r--r--lib/cgi/cgi.gemspec19
-rw-r--r--lib/cgi/cookie.rb49
-rw-r--r--lib/cgi/core.rb45
-rw-r--r--lib/cgi/util.rb53
-rw-r--r--lib/csv.rb489
-rw-r--r--lib/csv/fields_converter.rb5
-rw-r--r--lib/csv/input_record_separator.rb15
-rw-r--r--lib/csv/parser.rb293
-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.rb10
-rw-r--r--lib/delegate.rb2
-rw-r--r--lib/did_you_mean/core_ext/name_error.rb55
-rw-r--r--lib/did_you_mean/formatters/verbose_formatter.rb3
-rw-r--r--lib/did_you_mean/spell_checkers/method_name_checker.rb7
-rw-r--r--lib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb2
-rw-r--r--lib/did_you_mean/version.rb2
-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.rb72
-rw-r--r--lib/error_highlight/version.rb2
-rw-r--r--lib/fileutils.rb1705
-rw-r--r--lib/forwardable.rb4
-rw-r--r--lib/getoptlong.rb573
-rw-r--r--lib/ipaddr.rb6
-rw-r--r--lib/irb.rb155
-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.rb6
-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/help.rb14
-rw-r--r--lib/irb/cmd/info.rb31
-rw-r--r--lib/irb/cmd/irb_info.rb37
-rw-r--r--lib/irb/cmd/load.rb34
-rw-r--r--lib/irb/cmd/ls.rb13
-rw-r--r--lib/irb/cmd/measure.rb3
-rw-r--r--lib/irb/cmd/next.rb17
-rw-r--r--lib/irb/cmd/nop.rb24
-rw-r--r--lib/irb/cmd/pushws.rb9
-rw-r--r--lib/irb/cmd/show_cmds.rb39
-rw-r--r--lib/irb/cmd/show_source.rb103
-rw-r--r--lib/irb/cmd/step.rb17
-rw-r--r--lib/irb/cmd/subirb.rb38
-rw-r--r--lib/irb/cmd/whereami.rb3
-rw-r--r--lib/irb/color.rb76
-rw-r--r--lib/irb/color_printer.rb3
-rw-r--r--lib/irb/completion.rb136
-rw-r--r--lib/irb/context.rb74
-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.rb123
-rw-r--r--lib/irb/init.rb48
-rw-r--r--lib/irb/input-method.rb28
-rw-r--r--lib/irb/inspector.rb12
-rw-r--r--lib/irb/irb.gemspec6
-rw-r--r--lib/irb/lc/error.rb5
-rw-r--r--lib/irb/lc/help-message96
-rw-r--r--lib/irb/lc/ja/error.rb5
-rw-r--r--lib/irb/lc/ja/help-message12
-rw-r--r--lib/irb/ruby-lex.rb119
-rw-r--r--lib/irb/version.rb4
-rw-r--r--lib/irb/workspace.rb19
-rw-r--r--lib/logger.rb772
-rw-r--r--lib/logger/errors.rb2
-rw-r--r--lib/logger/formatter.rb5
-rw-r--r--lib/logger/log_device.rb6
-rw-r--r--lib/logger/logger.gemspec1
-rw-r--r--lib/logger/version.rb2
-rw-r--r--lib/mkmf.rb64
-rw-r--r--lib/mutex_m.rb2
-rw-r--r--lib/net/http.rb2071
-rw-r--r--lib/net/http/backward.rb2
-rw-r--r--lib/net/http/exceptions.rb55
-rw-r--r--lib/net/http/generic_request.rb109
-rw-r--r--lib/net/http/header.rb791
-rw-r--r--lib/net/http/net-http.gemspec13
-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/protocol.rb75
-rw-r--r--lib/open-uri.gemspec4
-rw-r--r--lib/open-uri.rb37
-rw-r--r--lib/open3/version.rb2
-rw-r--r--lib/optparse.rb120
-rw-r--r--lib/ostruct.rb17
-rw-r--r--lib/pp.gemspec2
-rw-r--r--lib/pp.rb20
-rw-r--r--lib/pstore.rb578
-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.rb62
-rw-r--r--lib/rdoc/any_method.rb4
-rw-r--r--lib/rdoc/cross_reference.rb8
-rw-r--r--lib/rdoc/generator/markup.rb2
-rw-r--r--lib/rdoc/generator/template/darkfish/_head.rhtml20
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml6
-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/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/known_classes.rb9
-rw-r--r--lib/rdoc/markdown.rb500
-rw-r--r--lib/rdoc/markdown/literals.rb109
-rw-r--r--lib/rdoc/markup.rb633
-rw-r--r--lib/rdoc/markup/attribute_manager.rb36
-rw-r--r--lib/rdoc/markup/parser.rb18
-rw-r--r--lib/rdoc/markup/to_html.rb30
-rw-r--r--lib/rdoc/markup/to_rdoc.rb23
-rw-r--r--lib/rdoc/options.rb12
-rw-r--r--lib/rdoc/parser.rb17
-rw-r--r--lib/rdoc/parser/c.rb50
-rw-r--r--lib/rdoc/parser/ruby.rb10
-rw-r--r--lib/rdoc/rd/block_parser.rb20
-rw-r--r--lib/rdoc/rdoc.gemspec18
-rw-r--r--lib/rdoc/rdoc.rb16
-rw-r--r--lib/rdoc/ri/driver.rb83
-rw-r--r--lib/rdoc/store.rb45
-rw-r--r--lib/rdoc/version.rb2
-rw-r--r--lib/reline.rb68
-rw-r--r--lib/reline/ansi.rb2
-rw-r--r--lib/reline/config.rb10
-rw-r--r--lib/reline/general_io.rb6
-rw-r--r--lib/reline/line_editor.rb20
-rw-r--r--lib/reline/reline.gemspec2
-rw-r--r--lib/reline/version.rb2
-rw-r--r--lib/resolv-replace.gemspec2
-rw-r--r--lib/resolv.gemspec2
-rw-r--r--lib/resolv.rb6
-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.rb175
-rw-r--r--lib/rubygems/available_set.rb7
-rw-r--r--lib/rubygems/basic_specification.rb9
-rw-r--r--lib/rubygems/bundler_version_finder.rb4
-rw-r--r--lib/rubygems/command.rb73
-rw-r--r--lib/rubygems/command_manager.rb52
-rw-r--r--lib/rubygems/commands/build_command.rb20
-rw-r--r--lib/rubygems/commands/cert_command.rb67
-rw-r--r--lib/rubygems/commands/check_command.rb41
-rw-r--r--lib/rubygems/commands/cleanup_command.rb35
-rw-r--r--lib/rubygems/commands/contents_command.rb27
-rw-r--r--lib/rubygems/commands/dependency_command.rb33
-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.rb19
-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.rb53
-rw-r--r--lib/rubygems/commands/list_command.rb7
-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.rb84
-rw-r--r--lib/rubygems/commands/push_command.rb17
-rw-r--r--lib/rubygems/commands/query_command.rb17
-rw-r--r--lib/rubygems/commands/rdoc_command.rb40
-rw-r--r--lib/rubygems/commands/search_command.rb7
-rw-r--r--lib/rubygems/commands/server_command.rb7
-rw-r--r--lib/rubygems/commands/setup_command.rb208
-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.rb29
-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.rb118
-rw-r--r--lib/rubygems/commands/which_command.rb15
-rw-r--r--lib/rubygems/commands/yank_command.rb23
-rw-r--r--lib/rubygems/config_file.rb76
-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.rb51
-rw-r--r--lib/rubygems/dependency.rb26
-rw-r--r--lib/rubygems/dependency_installer.rb75
-rw-r--r--lib/rubygems/dependency_list.rb13
-rw-r--r--lib/rubygems/deprecate.rb5
-rw-r--r--lib/rubygems/doctor.rb37
-rw-r--r--lib/rubygems/errors.rb7
-rw-r--r--lib/rubygems/exceptions.rb24
-rw-r--r--lib/rubygems/ext.rb14
-rw-r--r--lib/rubygems/ext/build_error.rb3
-rw-r--r--lib/rubygems/ext/builder.rb66
-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.rb21
-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.rb111
-rw-r--r--lib/rubygems/installer.rb108
-rw-r--r--lib/rubygems/installer_uninstaller_utils.rb4
-rw-r--r--lib/rubygems/local_remote_options.rb41
-rw-r--r--lib/rubygems/mock_gem_ui.rb5
-rw-r--r--lib/rubygems/name_tuple.rb9
-rw-r--r--lib/rubygems/optparse.rb2
-rw-r--r--lib/rubygems/optparse/lib/optparse.rb112
-rw-r--r--lib/rubygems/optparse/lib/optparse/ac.rb2
-rw-r--r--lib/rubygems/optparse/lib/optparse/date.rb2
-rw-r--r--lib/rubygems/optparse/lib/optparse/kwargs.rb2
-rw-r--r--lib/rubygems/optparse/lib/optparse/shellwords.rb2
-rw-r--r--lib/rubygems/optparse/lib/optparse/time.rb2
-rw-r--r--lib/rubygems/optparse/lib/optparse/uri.rb2
-rw-r--r--lib/rubygems/package.rb112
-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.rb17
-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.rb1
-rw-r--r--lib/rubygems/platform.rb132
-rw-r--r--lib/rubygems/psych_additions.rb10
-rw-r--r--lib/rubygems/psych_tree.rb3
-rw-r--r--lib/rubygems/query_utils.rb72
-rw-r--r--lib/rubygems/rdoc.rb5
-rw-r--r--lib/rubygems/remote_fetcher.rb45
-rw-r--r--lib/rubygems/request.rb49
-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.rb39
-rw-r--r--lib/rubygems/request_set/gem_dependency_api.rb246
-rw-r--r--lib/rubygems/request_set/lockfile.rb11
-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.rb29
-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.rb32
-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.rb2
-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.rb1
-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.rb18
-rw-r--r--lib/rubygems/safe_yaml.rb6
-rw-r--r--lib/rubygems/security.rb72
-rw-r--r--lib/rubygems/security/policies.rb95
-rw-r--r--lib/rubygems/security/policy.rb37
-rw-r--r--lib/rubygems/security/signer.rb11
-rw-r--r--lib/rubygems/security/trust_dir.rb9
-rw-r--r--lib/rubygems/security_option.rb11
-rw-r--r--lib/rubygems/shellwords.rb3
-rw-r--r--lib/rubygems/source.rb43
-rw-r--r--lib/rubygems/source/git.rb49
-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.rb6
-rw-r--r--lib/rubygems/spec_fetcher.rb23
-rw-r--r--lib/rubygems/specification.rb309
-rw-r--r--lib/rubygems/specification_policy.rb53
-rw-r--r--lib/rubygems/stub_specification.rb20
-rw-r--r--lib/rubygems/text.rb4
-rw-r--r--lib/rubygems/tsort.rb2
-rw-r--r--lib/rubygems/tsort/lib/tsort.rb618
-rw-r--r--lib/rubygems/uninstaller.rb37
-rw-r--r--lib/rubygems/update_suggestion.rb69
-rw-r--r--lib/rubygems/uri.rb75
-rw-r--r--lib/rubygems/uri_formatter.rb2
-rw-r--r--lib/rubygems/user_interaction.rb58
-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.rb28
-rw-r--r--lib/rubygems/version_option.rb7
-rw-r--r--lib/securerandom.gemspec2
-rw-r--r--lib/set.rb86
-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.rb145
-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.rb24
-rw-r--r--lib/tsort.gemspec2
-rw-r--r--lib/tsort.rb20
-rw-r--r--lib/un.gemspec2
-rw-r--r--lib/un.rb8
-rw-r--r--lib/unicode_normalize/tables.rb77
-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/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.rb2
-rw-r--r--lib/yaml/yaml.gemspec2
-rwxr-xr-xlibexec/bundle21
-rwxr-xr-xlibexec/bundler2
-rwxr-xr-xlibexec/erb12
-rwxr-xr-xlibexec/syntax_suggest7
-rw-r--r--load.c743
-rw-r--r--localeinit.c12
-rw-r--r--main.c38
-rw-r--r--man/irb.125
-rw-r--r--man/ruby.140
-rw-r--r--marshal.c1803
-rw-r--r--math.c650
-rw-r--r--memory_view.c14
-rw-r--r--method.h13
-rw-r--r--mini_builtin.c2
-rwxr-xr-xmisc/lldb_cruby.py77
-rw-r--r--misc/lldb_disasm.py23
-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
-rwxr-xr-xmisc/test_yjit_asm.sh10
-rw-r--r--misc/yjit_asm_tests.c443
-rw-r--r--missing/dtoa.c3
-rw-r--r--missing/flock.c8
-rw-r--r--mjit.c1784
-rw-r--r--mjit.h158
-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.c596
-rw-r--r--mjit_worker.c1522
-rw-r--r--node.c1440
-rw-r--r--node.h36
-rw-r--r--numeric.c1907
-rw-r--r--numeric.rb91
-rw-r--r--object.c1622
-rw-r--r--pack.c2268
-rw-r--r--pack.rb300
-rw-r--r--parse.y1205
-rw-r--r--probes_helper.h14
-rw-r--r--proc.c1026
-rw-r--r--process.c1771
-rw-r--r--ractor.c202
-rw-r--r--ractor.rb8
-rw-r--r--ractor_core.h116
-rw-r--r--random.c530
-rw-r--r--range.c792
-rw-r--r--rational.c795
-rw-r--r--re.c2783
-rw-r--r--regcomp.c19
-rw-r--r--regenc.c15
-rw-r--r--regenc.h14
-rw-r--r--regexec.c832
-rw-r--r--regint.h55
-rw-r--r--regparse.c13
-rw-r--r--ruby-runner.c56
-rw-r--r--ruby.c2126
-rw-r--r--rubystub.c29
-rw-r--r--sample/coverage.rb2
-rw-r--r--sample/drb/README.rdoc2
-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/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.c413
-rw-r--r--shape.c825
-rw-r--r--shape.h232
-rw-r--r--signal.c507
-rw-r--r--siphash.c90
-rw-r--r--sparc.c4
-rw-r--r--spec/README.md32
-rw-r--r--spec/bundler/bundler/bundler_spec.rb197
-rw-r--r--spec/bundler/bundler/cli_spec.rb46
-rw-r--r--spec/bundler/bundler/definition_spec.rb45
-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.rb11
-rw-r--r--spec/bundler/bundler/dsl_spec.rb14
-rw-r--r--spec/bundler/bundler/endpoint_specification_spec.rb25
-rw-r--r--spec/bundler/bundler/env_spec.rb8
-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.rb30
-rw-r--r--spec/bundler/bundler/friendly_errors_spec.rb14
-rw-r--r--spec/bundler/bundler/gem_helper_spec.rb5
-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_spec.rb22
-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.rb11
-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.rb53
-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.rb12
-rw-r--r--spec/bundler/cache/git_spec.rb77
-rw-r--r--spec/bundler/commands/add_spec.rb15
-rw-r--r--spec/bundler/commands/binstubs_spec.rb61
-rw-r--r--spec/bundler/commands/cache_spec.rb2
-rw-r--r--spec/bundler/commands/check_spec.rb6
-rw-r--r--spec/bundler/commands/clean_spec.rb15
-rw-r--r--spec/bundler/commands/config_spec.rb60
-rw-r--r--spec/bundler/commands/doctor_spec.rb2
-rw-r--r--spec/bundler/commands/exec_spec.rb39
-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.rb18
-rw-r--r--spec/bundler/commands/init_spec.rb38
-rw-r--r--spec/bundler/commands/inject_spec.rb2
-rw-r--r--spec/bundler/commands/install_spec.rb156
-rw-r--r--spec/bundler/commands/lock_spec.rb739
-rw-r--r--spec/bundler/commands/newgem_spec.rb201
-rw-r--r--spec/bundler/commands/open_spec.rb60
-rw-r--r--spec/bundler/commands/outdated_spec.rb209
-rw-r--r--spec/bundler/commands/platform_spec.rb (renamed from spec/bundler/other/platform_spec.rb)99
-rw-r--r--spec/bundler/commands/pristine_spec.rb4
-rw-r--r--spec/bundler/commands/remove_spec.rb36
-rw-r--r--spec/bundler/commands/show_spec.rb6
-rw-r--r--spec/bundler/commands/update_spec.rb304
-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.rb125
-rw-r--r--spec/bundler/install/gemfile/force_ruby_platform_spec.rb118
-rw-r--r--spec/bundler/install/gemfile/gemspec_spec.rb151
-rw-r--r--spec/bundler/install/gemfile/git_spec.rb127
-rw-r--r--spec/bundler/install/gemfile/path_spec.rb111
-rw-r--r--spec/bundler/install/gemfile/platform_spec.rb125
-rw-r--r--spec/bundler/install/gemfile/ruby_spec.rb14
-rw-r--r--spec/bundler/install/gemfile/sources_spec.rb211
-rw-r--r--spec/bundler/install/gemfile/specific_platform_spec.rb735
-rw-r--r--spec/bundler/install/gemfile_spec.rb2
-rw-r--r--spec/bundler/install/gems/compact_index_spec.rb58
-rw-r--r--spec/bundler/install/gems/dependency_api_spec.rb42
-rw-r--r--spec/bundler/install/gems/flex_spec.rb71
-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.rb308
-rw-r--r--spec/bundler/install/gems/standalone_spec.rb106
-rw-r--r--spec/bundler/install/gems/sudo_spec.rb205
-rw-r--r--spec/bundler/install/gemspecs_spec.rb3
-rw-r--r--spec/bundler/install/git_spec.rb80
-rw-r--r--spec/bundler/install/global_cache_spec.rb6
-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.rb143
-rw-r--r--spec/bundler/lock/git_spec.rb127
-rw-r--r--spec/bundler/lock/lockfile_spec.rb273
-rw-r--r--spec/bundler/other/ext_spec.rb4
-rw-r--r--spec/bundler/other/major_deprecation_spec.rb11
-rw-r--r--spec/bundler/plugins/install_spec.rb30
-rw-r--r--spec/bundler/plugins/source/example_spec.rb14
-rw-r--r--spec/bundler/quality_es_spec.rb4
-rw-r--r--spec/bundler/quality_spec.rb26
-rw-r--r--spec/bundler/realworld/dependency_api_spec.rb10
-rw-r--r--spec/bundler/realworld/edgecases_spec.rb369
-rw-r--r--spec/bundler/realworld/ffi_spec.rb2
-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.rb10
-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/inline_spec.rb218
-rw-r--r--spec/bundler/runtime/platform_spec.rb149
-rw-r--r--spec/bundler/runtime/require_spec.rb2
-rw-r--r--spec/bundler/runtime/self_management_spec.rb2
-rw-r--r--spec/bundler/runtime/setup_spec.rb117
-rw-r--r--spec/bundler/spec_helper.rb32
-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_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.rb33
-rw-r--r--spec/bundler/support/artifice/windows.rb7
-rw-r--r--spec/bundler/support/builders.rb50
-rw-r--r--spec/bundler/support/bundle.rb2
-rw-r--r--spec/bundler/support/filters.rb9
-rw-r--r--spec/bundler/support/hax.rb29
-rw-r--r--spec/bundler/support/helpers.rb53
-rw-r--r--spec/bundler/support/indexes.rb37
-rw-r--r--spec/bundler/support/matchers.rb16
-rw-r--r--spec/bundler/support/path.rb44
-rw-r--r--spec/bundler/support/platforms.rb42
-rw-r--r--spec/bundler/support/rubygems_ext.rb24
-rw-r--r--spec/bundler/support/rubygems_version_manager.rb2
-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.rb14
-rwxr-xr-xspec/mspec/lib/mspec/commands/mkspec.rb16
-rw-r--r--spec/mspec/lib/mspec/expectations/expectations.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/ruby_exe.rb13
-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/runner/actions/leakchecker.rb3
-rw-r--r--spec/mspec/lib/mspec/runner/actions/timeout.rb19
-rw-r--r--spec/mspec/lib/mspec/runner/context.rb1
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/base.rb8
-rw-r--r--spec/mspec/lib/mspec/runner/mspec.rb6
-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.rb4
-rw-r--r--spec/mspec/lib/mspec/utils/script.rb1
-rw-r--r--spec/mspec/spec/commands/mkspec_spec.rb2
-rw-r--r--spec/mspec/spec/helpers/ruby_exe_spec.rb12
-rw-r--r--spec/mspec/spec/utils/script_spec.rb5
-rwxr-xr-xspec/mspec/tool/tag_from_output.rb26
-rw-r--r--spec/ruby/.mspec.constants2
-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.md21
-rw-r--r--spec/ruby/command_line/dash_upper_w_spec.rb33
-rw-r--r--spec/ruby/command_line/dash_w_spec.rb6
-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/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/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/c_spec.rb14
-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.rb66
-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/w_spec.rb14
-rw-r--r--spec/ruby/core/array/pack/x_spec.rb1
-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.rb86
-rw-r--r--spec/ruby/core/array/shared/slice.rb168
-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/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/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.rb22
-rw-r--r--spec/ruby/core/comparable/clamp_spec.rb78
-rw-r--r--spec/ruby/core/complex/comparison_spec.rb36
-rw-r--r--spec/ruby/core/complex/polar_spec.rb16
-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.rb1
-rw-r--r--spec/ruby/core/dir/foreach_spec.rb12
-rw-r--r--spec/ruby/core/dir/glob_spec.rb2
-rw-r--r--spec/ruby/core/dir/home_spec.rb43
-rw-r--r--spec/ruby/core/dir/mkdir_spec.rb18
-rw-r--r--spec/ruby/core/dir/shared/chroot.rb9
-rw-r--r--spec/ruby/core/dir/shared/glob.rb20
-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/compact_spec.rb11
-rw-r--r--spec/ruby/core/enumerable/each_cons_spec.rb6
-rw-r--r--spec/ruby/core/enumerable/each_slice_spec.rb6
-rw-r--r--spec/ruby/core/enumerable/filter_map_spec.rb34
-rw-r--r--spec/ruby/core/enumerable/group_by_spec.rb10
-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.rb17
-rw-r--r--spec/ruby/core/enumerable/tally_spec.rb48
-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.rb10
-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/exception/frozen_error_spec.rb28
-rw-r--r--spec/ruby/core/exception/full_message_spec.rb40
-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.rb17
-rw-r--r--spec/ruby/core/fiber/raise_spec.rb148
-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.rb8
-rw-r--r--spec/ruby/core/file/shared/path.rb14
-rw-r--r--spec/ruby/core/file/utime_spec.rb38
-rw-r--r--spec/ruby/core/float/comparison_spec.rb35
-rw-r--r--spec/ruby/core/float/divide_spec.rb4
-rw-r--r--spec/ruby/core/float/divmod_spec.rb2
-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/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/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/to_a_spec.rb12
-rw-r--r--spec/ruby/core/integer/chr_spec.rb57
-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/io/advise_spec.rb14
-rw-r--r--spec/ruby/core/io/fixtures/classes.rb26
-rw-r--r--spec/ruby/core/io/gets_spec.rb52
-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/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.rb10
-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/write_nonblock_spec.rb10
-rw-r--r--spec/ruby/core/io/write_spec.rb10
-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.rb7
-rw-r--r--spec/ruby/core/kernel/define_singleton_method_spec.rb15
-rw-r--r--spec/ruby/core/kernel/fixtures/Complex.rb5
-rw-r--r--spec/ruby/core/kernel/fixtures/warn_core_method.rb2
-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.rb6
-rw-r--r--spec/ruby/core/kernel/method_spec.rb24
-rw-r--r--spec/ruby/core/kernel/p_spec.rb6
-rw-r--r--spec/ruby/core/kernel/proc_spec.rb10
-rw-r--r--spec/ruby/core/kernel/remove_instance_variable_spec.rb13
-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.rb85
-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/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/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/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.rb94
-rw-r--r--spec/ruby/core/matchdata/allocate_spec.rb8
-rw-r--r--spec/ruby/core/matchdata/element_reference_spec.rb21
-rw-r--r--spec/ruby/core/matchdata/post_match_spec.rb18
-rw-r--r--spec/ruby/core/matchdata/pre_match_spec.rb18
-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/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/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/append_features_spec.rb14
-rw-r--r--spec/ruby/core/module/autoload_spec.rb50
-rw-r--r--spec/ruby/core/module/class_variables_spec.rb8
-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_source_location_spec.rb333
-rw-r--r--spec/ruby/core/module/define_method_spec.rb43
-rw-r--r--spec/ruby/core/module/deprecate_constant_spec.rb20
-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.rb4
-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/name_spec.rb26
-rw-r--r--spec/ruby/core/module/prepend_features_spec.rb14
-rw-r--r--spec/ruby/core/module/prepend_spec.rb12
-rw-r--r--spec/ruby/core/module/refine_spec.rb126
-rw-r--r--spec/ruby/core/module/ruby2_keywords_spec.rb355
-rw-r--r--spec/ruby/core/module/shared/class_eval.rb21
-rw-r--r--spec/ruby/core/nil/to_s_spec.rb12
-rw-r--r--spec/ruby/core/objectspace/define_finalizer_spec.rb22
-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/new_spec.rb39
-rw-r--r--spec/ruby/core/proc/parameters_spec.rb2
-rw-r--r--spec/ruby/core/proc/ruby2_keywords_spec.rb114
-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.rb30
-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/rand_spec.rb5
-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.rb4
-rw-r--r--spec/ruby/core/range/each_spec.rb6
-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.rb2
-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.rb16
-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/refinement/import_methods_spec.rb34
-rw-r--r--spec/ruby/core/refinement/include_spec.rb27
-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/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/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/element_set_spec.rb28
-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/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.rb50
-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.rb22
-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.rb28
-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.rb22
-rw-r--r--spec/ruby/core/string/rstrip_spec.rb54
-rw-r--r--spec/ruby/core/string/scan_spec.rb46
-rw-r--r--spec/ruby/core/string/scrub_spec.rb15
-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.rb4
-rw-r--r--spec/ruby/core/string/shared/partition.rb15
-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.rb4
-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.rb2
-rw-r--r--spec/ruby/core/string/slice_spec.rb85
-rw-r--r--spec/ruby/core/string/split_spec.rb156
-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.rb18
-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.rb28
-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.rb12
-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/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.rb17
-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.rb27
-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/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.rb30
-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.rb13
-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.rb28
-rw-r--r--spec/ruby/core/warning/element_set_spec.rb48
-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_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.rb4
-rw-r--r--spec/ruby/language/comment_spec.rb16
-rw-r--r--spec/ruby/language/def_spec.rb33
-rw-r--r--spec/ruby/language/defined_spec.rb14
-rw-r--r--spec/ruby/language/delegation_spec.rb61
-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.rb15
-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.rb310
-rw-r--r--spec/ruby/language/module_spec.rb15
-rw-r--r--spec/ruby/language/numbered_parameters_spec.rb184
-rw-r--r--spec/ruby/language/optional_assignments_spec.rb38
-rw-r--r--spec/ruby/language/pattern_matching_spec.rb2246
-rw-r--r--spec/ruby/language/precedence_spec.rb78
-rw-r--r--spec/ruby/language/predefined_spec.rb428
-rw-r--r--spec/ruby/language/proc_spec.rb15
-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/escapes_spec.rb84
-rw-r--r--spec/ruby/language/regexp_spec.rb21
-rw-r--r--spec/ruby/language/rescue_spec.rb10
-rw-r--r--spec/ruby/language/return_spec.rb61
-rw-r--r--spec/ruby/language/safe_spec.rb94
-rw-r--r--spec/ruby/language/send_spec.rb18
-rw-r--r--spec/ruby/language/string_spec.rb22
-rw-r--r--spec/ruby/language/variables_spec.rb18
-rw-r--r--spec/ruby/language/yield_spec.rb12
-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.rb54
-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/shared/valid_jd.rb20
-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/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/logger/device/close_spec.rb4
-rw-r--r--spec/ruby/library/logger/device/write_spec.rb4
-rw-r--r--spec/ruby/library/objectspace/fixtures/trace.rb5
-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/glob_spec.rb16
-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/rbconfig/unicode_emoji_version_spec.rb22
-rw-r--r--spec/ruby/library/rbconfig/unicode_version_spec.rb22
-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/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/socket/addrinfo/initialize_spec.rb2
-rw-r--r--spec/ruby/library/socket/shared/pack_sockaddr.rb7
-rw-r--r--spec/ruby/library/socket/tcpsocket/shared/new.rb10
-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/write_nonblock_spec.rb6
-rw-r--r--spec/ruby/library/stringscanner/check_spec.rb14
-rw-r--r--spec/ruby/library/stringscanner/scan_spec.rb44
-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/peek.rb10
-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.rb65
-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/gc_spec.c35
-rw-r--r--spec/ruby/optional/capi/ext/globals_spec.c34
-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.c21
-rw-r--r--spec/ruby/optional/capi/ext/regexp_spec.c7
-rw-r--r--spec/ruby/optional/capi/ext/rubyspec.h30
-rw-r--r--spec/ruby/optional/capi/ext/string_spec.c21
-rw-r--r--spec/ruby/optional/capi/ext/symbol_spec.c11
-rw-r--r--spec/ruby/optional/capi/ext/thread_spec.c8
-rw-r--r--spec/ruby/optional/capi/ext/util_spec.c21
-rw-r--r--spec/ruby/optional/capi/fixtures/class.rb10
-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.rb122
-rw-r--r--spec/ruby/optional/capi/proc_spec.rb28
-rw-r--r--spec/ruby/optional/capi/rbasic_spec.rb1
-rw-r--r--spec/ruby/optional/capi/regexp_spec.rb16
-rw-r--r--spec/ruby/optional/capi/shared/rbasic.rb36
-rw-r--r--spec/ruby/optional/capi/spec_helper.rb8
-rw-r--r--spec/ruby/optional/capi/string_spec.rb156
-rw-r--r--spec/ruby/optional/capi/symbol_spec.rb8
-rw-r--r--spec/ruby/optional/capi/util_spec.rb24
-rw-r--r--spec/ruby/security/cve_2018_16396_spec.rb14
-rw-r--r--spec/ruby/security/cve_2019_8321_spec.rb30
-rw-r--r--spec/ruby/security/cve_2019_8322_spec.rb32
-rw-r--r--spec/ruby/security/cve_2019_8323_spec.rb54
-rw-r--r--spec/ruby/security/cve_2019_8325_spec.rb62
-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/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.c1366
-rw-r--r--st.c714
-rw-r--r--strftime.c7
-rw-r--r--string.c7693
-rw-r--r--string.rb552
-rw-r--r--struct.c1095
-rw-r--r--symbol.c427
-rw-r--r--symbol.h20
-rw-r--r--symbol.rb15
-rw-r--r--template/Doxyfile.tmpl1
-rw-r--r--template/GNUmakefile.in15
-rw-r--r--template/Makefile.in99
-rw-r--r--template/configure-ext.mk.tmpl2
-rw-r--r--template/extinit.c.tmpl2
-rw-r--r--template/exts.mk.tmpl7
-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.tmpl107
-rw-r--r--test/-ext-/arith_seq/test_arith_seq_beg_len_step.rb52
-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.rb11
-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-/funcall/test_funcall.rb11
-rw-r--r--test/-ext-/funcall/test_passing_block.rb5
-rw-r--r--test/-ext-/string/test_cstr.rb6
-rw-r--r--test/-ext-/string/test_fstring.rb8
-rw-r--r--test/-ext-/string/test_set_len.rb29
-rw-r--r--test/-ext-/symbol/test_type.rb14
-rw-r--r--test/-ext-/test_abi.rb8
-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/bigdecimal/test_bigdecimal.rb14
-rw-r--r--test/cgi/test_cgi_cookie.rb85
-rw-r--r--test/cgi/test_cgi_header.rb8
-rw-r--r--test/cgi/test_cgi_util.rb68
-rw-r--r--test/coverage/autostart.rb2
-rw-r--r--test/coverage/main.rb1
-rw-r--r--test/coverage/test_coverage.rb71
-rw-r--r--test/csv/interface/test_read.rb18
-rw-r--r--test/csv/interface/test_write.rb9
-rw-r--r--test/csv/parse/test_convert.rb55
-rw-r--r--test/csv/parse/test_general.rb82
-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_liberal_parsing.rb11
-rw-r--r--test/csv/parse/test_read.rb27
-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.rb73
-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.rb7
-rw-r--r--test/date/test_date_ractor.rb2
-rw-r--r--test/date/test_date_strptime.rb9
-rw-r--r--test/did_you_mean/core_ext/test_name_error_extension.rb16
-rw-r--r--test/did_you_mean/helper.rb10
-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.rb2
-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/digest/test_digest_extend.rb13
-rw-r--r--test/digest/test_ractor.rb6
-rw-r--r--test/drb/drbtest.rb2
-rw-r--r--test/drb/test_drb.rb5
-rw-r--r--test/drb/test_drbssl.rb8
-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.rb103
-rw-r--r--test/fiber/autoload.rb3
-rw-r--r--test/fiber/scheduler.rb111
-rw-r--r--test/fiber/test_address_resolve.rb2
-rw-r--r--test/fiber/test_enumerator.rb14
-rw-r--r--test/fiber/test_io.rb73
-rw-r--r--test/fiber/test_io_buffer.rb33
-rw-r--r--test/fiber/test_mutex.rb22
-rw-r--r--test/fiber/test_process.rb21
-rw-r--r--test/fiber/test_queue.rb54
-rw-r--r--test/fiber/test_scheduler.rb119
-rw-r--r--test/fiber/test_storage.rb115
-rw-r--r--test/fiber/test_thread.rb22
-rw-r--r--test/fiddle/helper.rb10
-rw-r--r--test/fiddle/test_closure.rb111
-rw-r--r--test/fiddle/test_fiddle.rb41
-rw-r--r--test/fiddle/test_func.rb36
-rw-r--r--test/fiddle/test_function.rb28
-rw-r--r--test/fiddle/test_handle.rb7
-rw-r--r--test/fiddle/test_import.rb23
-rw-r--r--test/fiddle/test_pack.rb37
-rw-r--r--test/fiddle/test_pointer.rb3
-rw-r--r--test/fileutils/clobber.rb5
-rw-r--r--test/fileutils/test_dryrun.rb2
-rw-r--r--test/fileutils/test_fileutils.rb91
-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.rb31
-rw-r--r--test/io/wait/test_io_wait.rb36
-rw-r--r--test/io/wait/test_io_wait_uncommon.rb1
-rw-r--r--test/io/wait/test_ractor.rb1
-rw-r--r--test/irb/helper.rb76
-rw-r--r--test/irb/test_cmd.rb862
-rw-r--r--test/irb/test_color.rb84
-rw-r--r--test/irb/test_color_printer.rb5
-rw-r--r--test/irb/test_completion.rb359
-rw-r--r--test/irb/test_context.rb335
-rw-r--r--test/irb/test_debug_cmd.rb303
-rw-r--r--test/irb/test_history.rb68
-rw-r--r--test/irb/test_init.rb81
-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.rb10
-rw-r--r--test/irb/test_ruby_lex.rb130
-rw-r--r--test/irb/test_workspace.rb5
-rw-r--r--test/irb/yamatanooroti/test_rendering.rb23
-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.rb39
-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_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.rb98
-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.rb116
-rw-r--r--test/net/http/test_httpheader.rb27
-rw-r--r--test/net/http/test_httpresponse.rb287
-rw-r--r--test/net/http/test_https.rb16
-rw-r--r--test/net/protocol/test_protocol.rb37
-rw-r--r--test/objspace/test_objspace.rb178
-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.rb22
-rw-r--r--test/openssl/test_bn.rb6
-rw-r--r--test/openssl/test_cipher.rb6
-rw-r--r--test/openssl/test_hmac.rb9
-rw-r--r--test/openssl/test_ns_spki.rb2
-rw-r--r--test/openssl/test_ocsp.rb2
-rw-r--r--test/openssl/test_pair.rb2
-rw-r--r--test/openssl/test_pkey.rb5
-rw-r--r--test/openssl/test_pkey_dsa.rb23
-rw-r--r--test/openssl/test_pkey_ec.rb36
-rw-r--r--test/openssl/test_pkey_rsa.rb23
-rw-r--r--test/openssl/test_ssl.rb190
-rw-r--r--test/openssl/test_ssl_session.rb2
-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/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.rb2
-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/pathname/test_pathname.rb19
-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_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_yaml.rb2
-rw-r--r--test/racc/case.rb5
-rw-r--r--test/rdoc/support/test_case.rb4
-rw-r--r--test/rdoc/test_rdoc_any_method.rb14
-rw-r--r--test/rdoc/test_rdoc_cross_reference.rb14
-rw-r--r--test/rdoc/test_rdoc_generator_darkfish.rb70
-rw-r--r--test/rdoc/test_rdoc_generator_json_index.rb14
-rw-r--r--test/rdoc/test_rdoc_markdown.rb22
-rw-r--r--test/rdoc/test_rdoc_markup_attribute_manager.rb2
-rw-r--r--test/rdoc/test_rdoc_markup_to_html.rb101
-rw-r--r--test/rdoc/test_rdoc_options.rb11
-rw-r--r--test/rdoc/test_rdoc_parser_c.rb145
-rw-r--r--test/rdoc/test_rdoc_parser_ruby.rb8
-rw-r--r--test/rdoc/test_rdoc_rd_block_parser.rb21
-rw-r--r--test/rdoc/test_rdoc_rdoc.rb42
-rw-r--r--test/rdoc/test_rdoc_ri_driver.rb49
-rw-r--r--test/rdoc/test_rdoc_store.rb3
-rw-r--r--test/readline/test_readline.rb7
-rw-r--r--test/reline/test_config.rb1
-rw-r--r--test/reline/test_key_actor_vi.rb8
-rw-r--r--test/reline/test_reline.rb6
-rw-r--r--test/reline/yamatanooroti/termination_checker.rb4
-rw-r--r--test/resolv/test_dns.rb7
-rw-r--r--test/rinda/test_rinda.rb78
-rw-r--r--test/ripper/test_lexer.rb86
-rw-r--r--test/ripper/test_parser_events.rb55
-rw-r--r--test/ripper/test_ripper.rb22
-rw-r--r--test/ripper/test_scanner_events.rb13
-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.rb115
-rw-r--r--test/ruby/test_argf.rb12
-rw-r--r--test/ruby/test_array.rb130
-rw-r--r--test/ruby/test_assignment.rb10
-rw-r--r--test/ruby/test_ast.rb516
-rw-r--r--test/ruby/test_autoload.rb104
-rw-r--r--test/ruby/test_bignum.rb9
-rw-r--r--test/ruby/test_call.rb7
-rw-r--r--test/ruby/test_class.rb41
-rw-r--r--test/ruby/test_clone.rb53
-rw-r--r--test/ruby/test_complex.rb119
-rw-r--r--test/ruby/test_data.rb249
-rw-r--r--test/ruby/test_dir.rb67
-rw-r--r--test/ruby/test_dup.rb110
-rw-r--r--test/ruby/test_encoding.rb21
-rw-r--r--test/ruby/test_enum.rb2
-rw-r--r--test/ruby/test_enumerator.rb117
-rw-r--r--test/ruby/test_env.rb72
-rw-r--r--test/ruby/test_exception.rb73
-rw-r--r--test/ruby/test_file.rb44
-rw-r--r--test/ruby/test_file_exhaustive.rb46
-rw-r--r--test/ruby/test_float.rb35
-rw-r--r--test/ruby/test_frozen.rb30
-rw-r--r--test/ruby/test_gc.rb71
-rw-r--r--test/ruby/test_gc_compact.rb329
-rw-r--r--test/ruby/test_hash.rb106
-rw-r--r--test/ruby/test_inlinecache.rb2
-rw-r--r--test/ruby/test_integer.rb50
-rw-r--r--test/ruby/test_io.rb152
-rw-r--r--test/ruby/test_io_buffer.rb300
-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.rb52
-rw-r--r--test/ruby/test_keyword.rb263
-rw-r--r--test/ruby/test_lazy_enumerator.rb20
-rw-r--r--test/ruby/test_m17n.rb54
-rw-r--r--test/ruby/test_marshal.rb30
-rw-r--r--test/ruby/test_method.rb237
-rw-r--r--test/ruby/test_mjit.rb (renamed from test/ruby/test_jit.rb)374
-rw-r--r--test/ruby/test_mjit_debug.rb (renamed from test/ruby/test_jit_debug.rb)8
-rw-r--r--test/ruby/test_module.rb120
-rw-r--r--test/ruby/test_numeric.rb3
-rw-r--r--test/ruby/test_object.rb31
-rw-r--r--test/ruby/test_objectspace.rb5
-rw-r--r--test/ruby/test_optimization.rb14
-rw-r--r--test/ruby/test_pack.rb60
-rw-r--r--test/ruby/test_parse.rb72
-rw-r--r--test/ruby/test_pattern_matching.rb36
-rw-r--r--test/ruby/test_proc.rb131
-rw-r--r--test/ruby/test_process.rb157
-rw-r--r--test/ruby/test_rand.rb8
-rw-r--r--test/ruby/test_range.rb108
-rw-r--r--test/ruby/test_rational.rb2
-rw-r--r--test/ruby/test_refinement.rb35
-rw-r--r--test/ruby/test_regexp.rb403
-rw-r--r--test/ruby/test_require.rb69
-rw-r--r--test/ruby/test_rubyoptions.rb52
-rw-r--r--test/ruby/test_rubyvm.rb2
-rw-r--r--test/ruby/test_rubyvm_mjit.rb (renamed from test/ruby/test_rubyvm_jit.rb)38
-rw-r--r--test/ruby/test_settracefunc.rb349
-rw-r--r--test/ruby/test_shapes.rb441
-rw-r--r--test/ruby/test_sprintf.rb29
-rw-r--r--test/ruby/test_string.rb76
-rw-r--r--test/ruby/test_struct.rb14
-rw-r--r--test/ruby/test_super.rb29
-rw-r--r--test/ruby/test_symbol.rb13
-rw-r--r--test/ruby/test_syntax.rb128
-rw-r--r--test/ruby/test_thread.rb93
-rw-r--r--test/ruby/test_thread_queue.rb55
-rw-r--r--test/ruby/test_time.rb123
-rw-r--r--test/ruby/test_time_tz.rb36
-rw-r--r--test/ruby/test_transcode.rb14
-rw-r--r--test/ruby/test_variable.rb25
-rw-r--r--test/ruby/test_vm_dump.rb2
-rw-r--r--test/ruby/test_weakmap.rb46
-rw-r--r--test/ruby/test_yjit.rb772
-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/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.rb362
-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_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.rb1034
-rw-r--r--test/rubygems/test_gem_available_set.rb43
-rw-r--r--test/rubygems/test_gem_bundler_version_finder.rb10
-rw-r--r--test/rubygems/test_gem_command.rb89
-rw-r--r--test/rubygems/test_gem_command_manager.rb134
-rw-r--r--test/rubygems/test_gem_commands_build_command.rb137
-rw-r--r--test/rubygems/test_gem_commands_cert_command.rb197
-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.rb75
-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.rb288
-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.rb9
-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.rb5
-rw-r--r--test/rubygems/test_gem_commands_setup_command.rb219
-rw-r--r--test/rubygems/test_gem_commands_signin_command.rb179
-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.rb180
-rw-r--r--test/rubygems/test_gem_commands_unpack_command.rb63
-rw-r--r--test/rubygems/test_gem_commands_update_command.rb239
-rw-r--r--test/rubygems/test_gem_commands_which_command.rb13
-rw-r--r--test/rubygems/test_gem_commands_yank_command.rb205
-rw-r--r--test/rubygems/test_gem_config_file.rb175
-rw-r--r--test/rubygems/test_gem_dependency.rb149
-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.rb33
-rw-r--r--test/rubygems/test_gem_installer.rb728
-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.rb478
-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.rb29
-rw-r--r--test/rubygems/test_gem_platform.rb550
-rw-r--r--test/rubygems/test_gem_rdoc.rb29
-rw-r--r--test/rubygems/test_gem_remote_fetcher.rb315
-rw-r--r--test/rubygems/test_gem_request.rb122
-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.rb266
-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.rb115
-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.rb137
-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_silent_ui.rb71
-rw-r--r--test/rubygems/test_gem_source.rb89
-rw-r--r--test/rubygems/test_gem_source_fetch_problem.rb19
-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.rb1022
-rw-r--r--test/rubygems/test_gem_stream_ui.rb75
-rw-r--r--test/rubygems/test_gem_stub_specification.rb65
-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.rb10
-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.rb40
-rw-r--r--test/rubygems/test_gem_version_option.rb31
-rw-r--r--test/rubygems/test_kernel.rb91
-rw-r--r--test/rubygems/test_project_sanity.rb35
-rw-r--r--test/rubygems/test_remote_fetch_error.rb15
-rw-r--r--test/rubygems/test_require.rb249
-rw-r--r--test/rubygems/test_rubygems.rb37
-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.rb132
-rw-r--r--test/rubygems/wrong_key_cert.pem30
-rw-r--r--test/rubygems/wrong_key_cert_32.pem30
-rw-r--r--test/runner.rb12
-rw-r--r--test/socket/test_addrinfo.rb4
-rw-r--r--test/socket/test_nonblock.rb4
-rw-r--r--test/socket/test_socket.rb2
-rw-r--r--test/socket/test_tcp.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_pp.rb9
-rw-r--r--test/test_pstore.rb32
-rw-r--r--test/test_rbconfig.rb9
-rw-r--r--test/test_set.rb2
-rw-r--r--test/test_time.rb9
-rw-r--r--test/test_timeout.rb46
-rw-r--r--test/test_tmpdir.rb18
-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_ldap.rb6
-rw-r--r--test/uri/test_parser.rb38
-rw-r--r--test/uri/test_wss.rb71
-rw-r--r--test/yaml/test_store.rb2
-rw-r--r--test/zlib/test_zlib.rb6
-rw-r--r--thread.c1567
-rw-r--r--thread_none.c24
-rw-r--r--thread_none.h7
-rw-r--r--thread_pthread.c973
-rw-r--r--thread_pthread.h92
-rw-r--r--thread_sync.c415
-rw-r--r--thread_sync.rb68
-rw-r--r--thread_win32.c407
-rw-r--r--thread_win32.h20
-rw-r--r--time.c2183
-rw-r--r--timev.h11
-rw-r--r--timev.rb277
-rw-r--r--tool/annocheck/Dockerfile4
-rw-r--r--tool/annocheck/Dockerfile-copy7
-rw-r--r--tool/bundler/dev_gems.rb17
-rw-r--r--tool/bundler/dev_gems.rb.lock66
-rw-r--r--tool/bundler/rubocop_gems.rb1
-rw-r--r--tool/bundler/rubocop_gems.rb.lock62
-rw-r--r--tool/bundler/standard_gems.rb1
-rw-r--r--tool/bundler/standard_gems.rb.lock72
-rw-r--r--tool/bundler/test_gems.rb2
-rw-r--r--tool/bundler/test_gems.rb.lock13
-rwxr-xr-xtool/checksum.rb4
-rw-r--r--tool/downloader.rb84
-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.rb10
-rwxr-xr-xtool/fetch-bundled_gems.rb2
-rwxr-xr-xtool/file2lastrev.rb91
-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.rb90
-rw-r--r--tool/lib/envutil.rb18
-rw-r--r--tool/lib/leakchecker.rb9
-rw-r--r--tool/lib/output.rb57
-rw-r--r--tool/lib/test/unit.rb80
-rw-r--r--tool/lib/test/unit/assertions.rb20
-rw-r--r--tool/lib/vcs.rb156
-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_prog_makedirs.m49
-rw-r--r--tool/m4/ruby_replace_funcs.m44
-rw-r--r--tool/m4/ruby_require_funcs.m413
-rw-r--r--tool/m4/ruby_thread.m451
-rw-r--r--tool/m4/ruby_universal_arch.m46
-rw-r--r--tool/m4/ruby_wasm_tools.m413
-rwxr-xr-xtool/make-snapshot42
-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.rb67
-rwxr-xr-xtool/mkconfig.rb15
-rwxr-xr-xtool/mkrunnable.rb4
-rwxr-xr-xtool/outdate-bundled-gems.rb135
-rwxr-xr-xtool/pure_parser.rb24
-rwxr-xr-xtool/rbinstall.rb273
-rw-r--r--tool/rbs_skip_tests11
-rwxr-xr-xtool/redmine-backporter.rb158
-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/scripts/insns2vm.rb12
-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/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.rb15
-rwxr-xr-xtool/sync_default_gems.rb1257
-rwxr-xr-xtool/test-annocheck.sh33
-rw-r--r--tool/test-bundled-gems.rb86
-rwxr-xr-xtool/test/test_sync_default_gems.rb76
-rw-r--r--tool/test/testunit/test_assertion.rb24
-rw-r--r--tool/test/webrick/test_filehandler.rb4
-rw-r--r--tool/test/webrick/test_httprequest.rb2
-rw-r--r--tool/transcode-tblgen.rb2
-rw-r--r--tool/transform_mjit_header.rb14
-rw-r--r--tool/update-NEWS-refs.rb37
-rwxr-xr-xtool/update-bundled_gems.rb5
-rwxr-xr-xtool/update-deps7
-rw-r--r--trace_point.rb62
-rw-r--r--transcode.c576
-rw-r--r--transcode_data.h32
-rw-r--r--transient_heap.c6
-rw-r--r--util.c172
-rw-r--r--variable.c2591
-rw-r--r--variable.h10
-rw-r--r--version.c62
-rw-r--r--version.h58
-rw-r--r--vm.c1626
-rw-r--r--vm_args.c639
-rw-r--r--vm_backtrace.c479
-rw-r--r--vm_callinfo.h84
-rw-r--r--vm_core.h552
-rw-r--r--vm_debug.h19
-rw-r--r--vm_dump.c1047
-rw-r--r--vm_eval.c679
-rw-r--r--vm_exec.c28
-rw-r--r--vm_exec.h6
-rw-r--r--vm_insnhelper.c2962
-rw-r--r--vm_insnhelper.h21
-rw-r--r--vm_method.c1029
-rw-r--r--vm_sync.c10
-rw-r--r--vm_trace.c521
-rw-r--r--wasm/README.md13
-rw-r--r--wasm/machine.c6
-rw-r--r--wasm/machine.h5
-rw-r--r--win32/Makefile.sub203
-rwxr-xr-xwin32/configure.bat27
-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.mak25
-rw-r--r--win32/win32.c5918
-rw-r--r--win32/winmain.c4
-rw-r--r--yjit.c1253
-rw-r--r--yjit.h81
-rw-r--r--yjit.rb391
-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
-rw-r--r--yjit_asm.c1834
-rw-r--r--yjit_asm.h408
-rw-r--r--yjit_codegen.c5124
-rw-r--r--yjit_codegen.h23
-rw-r--r--yjit_core.c1366
-rw-r--r--yjit_core.h307
-rw-r--r--yjit_iface.c1311
-rw-r--r--yjit_iface.h38
-rw-r--r--yjit_utils.c109
2843 files changed, 227354 insertions, 124699 deletions
diff --git a/.appveyor.yml b/.appveyor.yml
index 1f179143c8..05ff204541 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -11,23 +11,24 @@ clone_depth: 10
platform:
- x64
skip_commits:
- message: /^\[DOC\]/
+ 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 2015
- 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: "UTF-8"
@@ -47,8 +48,9 @@ for:
- 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 libffi libyaml readline zlib
+ - 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%'
@@ -68,9 +70,6 @@ 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
@@ -78,6 +77,7 @@ for:
- attrib +r /s /d
- mkdir %Platform%-mswin_%vs%
build_script:
+ - set HAVE_GIT=no
- cd %APPVEYOR_BUILD_FOLDER%
- cd %Platform%-mswin_%vs%
- >-
@@ -94,7 +94,7 @@ for:
- nmake -l "TESTOPTS=-v -q" btest
- nmake -l "TESTOPTS=-v -q" test-basic
- >-
- nmake -l "TESTOPTS=-v --timeout-scale=3.0
+ nmake -l "TESTOPTS=--timeout-scale=3.0
--excludes=../test/excludes/_appveyor -j%JOBS%
--exclude win32ole
--exclude test_bignum
@@ -105,7 +105,7 @@ for:
# separately execute tests without -j which may crash worker with -j.
- >-
nmake -l
- "TESTOPTS=-v --timeout-scale=3.0 --excludes=../test/excludes/_appveyor"
+ "TESTOPTS=--timeout-scale=3.0 --excludes=../test/excludes/_appveyor"
TESTS="
../test/win32ole
../test/ruby/test_bignum.rb
@@ -123,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/.cirrus.yml b/.cirrus.yml
deleted file mode 100644
index c8fb326c89..0000000000
--- a/.cirrus.yml
+++ /dev/null
@@ -1,64 +0,0 @@
-# This CI is used to test Arm cases. We can set the maximum 16 tasks.
-# The entire testing design is inspired from .github/workflows/compilers.yml.
-
-# By default, Cirrus mounts an empty volume to `/tmp`
-# which triggers all sorts of warnings like "system temporary path is world-writable: /tmp".
-# Lets workaround it by specifying a custom volume mount point.
-env:
- CIRRUS_VOLUME: /cirrus-ci-volume
- LANG: C.UTF-8
-
-task:
- name: Arm64 Graviton2 / $CC
- skip: "changesIncludeOnly('doc/**', '**.{md,rdoc}')"
- arm_container:
- # We use the arm64 images at http://ghcr.io/ruby/ruby-ci-image .
- image: ghcr.io/ruby/ruby-ci-image:$CC
- # Define the used cpu core in each matrix task. We can use total 16 cpu
- # cores in entire matrix. [cpu] = [total cpu: 16] / [number of tasks]
- cpu: 8
- # We can request maximum 4 GB per cpu.
- # [memory per task] = [memory per cpu: 4 GB] * [cpu]
- memory: 32G
- env:
- CIRRUS_CLONE_DEPTH: 50
- optflags: '-O1'
- debugflags: '-ggdb3'
- RUBY_PREFIX: /tmp/ruby-prefix
- RUBY_DEBUG: ci rgengc
- RUBY_TESTOPTS: >-
- -q
- --color=always
- --tty=no
- matrix:
- CC: clang-12
- CC: gcc-11
- id_script: id
- set_env_script:
- # Set `GNUMAKEFLAGS`, because the flags are GNU make specific. Note using
- # the `make` environment variable used in compilers.yml causes some rubygems
- # tests to fail.
- # https://github.com/rubygems/rubygems/issues/4921
- - echo "GNUMAKEFLAGS=-s -j$((1 + $CIRRUS_CPU))" >> $CIRRUS_ENV
- print_env_script:
- - echo "GNUMAKEFLAGS=$GNUMAKEFLAGS"
- # Arm containers are executed in AWS's EKS, and it's not yet supporting IPv6
- # See https://github.com/aws/containers-roadmap/issues/835
- disable_ipv6_script: sudo ./tool/disable_ipv6.sh
- autogen_script: ./autogen.sh
- configure_script: >-
- ./configure -C
- --enable-debug-env
- --disable-install-doc
- --with-ext=-test-/cxxanyargs,+
- --prefix="$RUBY_PREFIX"
- make_extract-extlibs_script: make extract-extlibs
- make_incs_script: make incs
- make_script: make
- make_leaked-globals_script: make leaked-globals
- make_test_script: make test
- make_install_script: make install
- install_gems_for_test_script: $RUBY_PREFIX/bin/gem install --no-doc timezone tzinfo
- make_test-tool_script: make test-tool
- make_test-all_script: make test-all
- make_test-spec_script: make test-spec
diff --git a/.document b/.document
index 6e08f42698..3a6b0c238c 100644
--- a/.document
+++ b/.document
@@ -18,13 +18,18 @@ 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
@@ -40,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/CODEOWNERS b/.github/CODEOWNERS
deleted file mode 100644
index 15abc79af6..0000000000
--- a/.github/CODEOWNERS
+++ /dev/null
@@ -1,10 +0,0 @@
-# Lines starting with '#' are comments.
-# Each line is a file pattern followed by one or more owners.
-# Code owners will be automatically tagged as reviewers when a pull request is opened
-
-# YJIT sources and tests
-yjit* @maximecb @xrxr @tenderlove
-doc/yjit/* @maximecb @xrxr @tenderlove
-bootstraptest/test_yjit* @maximecb @xrxr @tenderlove
-test/ruby/test_yjit* @maximecb @xrxr @tenderlove
-.github/workflows/yjit* @maximecb @xrxr @tenderlove
diff --git a/.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 4930028db0..ebaafe3bf0 100644
--- a/.github/workflows/baseruby.yml
+++ b/.github/workflows/baseruby.yml
@@ -4,23 +4,37 @@ 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
- if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ runs-on: ubuntu-22.04
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
strategy:
matrix:
ruby:
@@ -34,24 +48,24 @@ jobs:
- ruby-3.1
steps:
- - uses: actions/checkout@v2
- - uses: actions/cache@v2
+ - 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@v1
+ - uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0
with:
ruby-version: ${{ matrix.ruby }}
bundler: none
- run: echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV
- - run: sudo apt-get install build-essential autoconf bison
+ - run: 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
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
with:
payload: |
{
@@ -59,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
index 2a8e6c244c..070c0fa1dd 100644
--- a/.github/workflows/bundled_gems.yml
+++ b/.github/workflows/bundled_gems.yml
@@ -2,18 +2,31 @@ 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
@@ -28,9 +41,9 @@ jobs:
echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV
echo "TODAY=$(date +%F)" >> $GITHUB_ENV
- - uses: actions/checkout@v2
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- - uses: actions/cache@v2
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: .downloaded-cache
key: downloaded-cache-${{ github.sha }}
@@ -50,6 +63,7 @@ jobs:
- name: Maintain updated gems list in NEWS
run: |
+ #!ruby
require 'json'
news = File.read("NEWS.md")
prev = news[/since the \*+(\d+\.\d+\.\d+)\*+/, 1]
@@ -67,14 +81,14 @@ jobs:
[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} * "
+ 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} * "
+ 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 if added
+ end or next unless added.empty?
File.write("NEWS.md", news)
end
shell: ruby {0}
@@ -100,6 +114,11 @@ jobs:
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
@@ -131,3 +150,17 @@ jobs:
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 6c7e8e5787..79b2916feb 100644
--- a/.github/workflows/check_dependencies.yml
+++ b/.github/workflows/check_dependencies.yml
@@ -3,26 +3,40 @@ 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]
+ os: [ubuntu-22.04]
fail-fast: true
runs-on: ${{ matrix.os }}
- if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
steps:
- name: Install libraries
run: |
@@ -32,15 +46,14 @@ 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/cache@v2
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: .downloaded-cache
key: downloaded-cache
@@ -50,7 +63,7 @@ jobs:
- 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: |
{
@@ -58,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 2872c96ffd..0000000000
--- a/.github/workflows/check_misc.yml
+++ /dev/null
@@ -1,97 +0,0 @@
-name: Miscellaneous checks
-on: [push, pull_request]
-
-concurrency:
- group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
- cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
-
-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
-
- - uses: actions/cache@v2
- with:
- path: .downloaded-cache
- key: downloaded-cache-${{ github.sha }}
- restore-keys: |
- downloaded-cache
-
- - name: Download previous gems list
- run: |
- data=default_gems.json
- mkdir -p .downloaded-cache
- ln -s .downloaded-cache/$data .
- curl -O -R -z ./$data https://stdgems.org/$data
-
- - name: Make default gems list
- run: |
- require 'rubygems'
- $:.unshift "lib"
- rgver = File.foreach("lib/rubygems.rb") do |line|
- break $1 if /^\s*VERSION\s*=\s*"([^"]+)"/ =~ line
- end
- gems = Dir.glob("{ext,lib}/**/*.gemspec").map do |f|
- spec = Gem::Specification.load(f)
- "#{spec.name} #{spec.version}"
- end.sort
- File.open("gems/default_gems", "w") do |f|
- f.puts "RubyGems #{rgver}"
- f.puts gems
- end
- shell: ruby --disable=gems {0}
-
- - name: Maintain updated gems list in NEWS
- run: |
- require 'json'
- news = File.read("NEWS.md")
- prev = news[/since the \*+(\d+\.\d+\.\d+)\*+/, 1]
- prevs = [prev, prev.sub(/\.\d+\z/, '')]
- %W[default].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
- news.sub!(/^\*( +)The following #{type} gems? are updated\.\n\K(?: \1\* .*\n)*/) do
- mark = "#{$1} * "
- changed.map {|g, v|"#{mark}#{g} #{v}\n"}.join("")
- end or next
- File.write("NEWS.md", news)
- end
- shell: ruby {0}
-
- - name: Check diffs
- id: diff
- run: |
- git diff --color --no-ext-diff --ignore-submodules --exit-code NEWS.md
- continue-on-error: true
- - name: Commit
- run: |
- git pull --ff-only origin ${GITHUB_REF#refs/heads/}
- git commit --message="Update default gems list at ${GITHUB_SHA:0:30} [ci skip]" NEWS.md
- git push origin ${GITHUB_REF#refs/heads/}
- env:
- EMAIL: svn-admin@ruby-lang.org
- GIT_AUTHOR_NAME: git
- GIT_COMMITTER_NAME: git
- if: ${{ github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull') && steps.diff.outcome == 'failure' }}
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index f81c79902d..8dba76fbe2 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -1,29 +1,42 @@
name: "Code scanning - action"
on:
- push:
- paths-ignore:
- - 'doc/**'
- - '**.md'
- - '**.rdoc'
- pull_request:
- paths-ignore:
- - 'doc/**'
- - '**.md'
- - '**.rdoc'
+ # 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
- if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ # 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
@@ -36,9 +49,9 @@ 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@v2
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: .downloaded-cache
key: downloaded-cache
@@ -47,15 +60,16 @@ jobs:
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 bb414f7de6..caf12cc0f4 100644
--- a/.github/workflows/compilers.yml
+++ b/.github/workflows/compilers.yml
@@ -4,28 +4,36 @@ on:
push:
paths-ignore:
- 'doc/**'
+ - '**/man'
- '**.md'
- '**.rdoc'
+ - '**/.document'
pull_request:
paths-ignore:
- 'doc/**'
- - '**.md'
+ - '**/man'
+ - '**.rdoc'
+ - '**/.document'
+ merge_group:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man'
- '**.rdoc'
+ - '**/.document'
concurrency:
group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
-# Github actions does not support YAML anchors. This creative use of
+# 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-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'
@@ -55,143 +63,160 @@ 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
- shared: '--disable-shared'
+ - { 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-15, value: clang-15, container: clang-15 }
- - { key: default_cc, name: clang-14, value: clang-14, container: clang-14 }
- - { key: default_cc, name: clang-13, value: clang-13, container: clang-13 }
- - { key: default_cc, name: clang-12, value: clang-12, container: clang-12 }
- - { key: default_cc, name: clang-11, value: clang-11, container: clang-11 }
- - { key: default_cc, name: clang-10, value: clang-10, container: clang-10 }
- - { key: default_cc, name: clang-9, value: clang-9, container: clang-9 }
- - { key: default_cc, name: clang-8, value: clang-8, container: clang-8 }
- - { key: default_cc, name: clang-7, value: clang-7, container: clang-7 }
- - { key: default_cc, name: clang-6.0, value: clang-6.0, container: clang-6.0 }
- - { key: default_cc, name: clang-5.0, value: clang-5.0, container: clang-5.0 }
- - { key: default_cc, name: clang-4.0, value: clang-4.0, container: clang-4.0 }
- - { key: default_cc, name: clang-3.9, value: clang-3.9, container: clang-3.9 }
- - key: default_cc
- name: 'clang-14 LTO'
- value: 'clang-14 -O2 -flto=auto'
- container: clang-14
- shared: '--disable-shared'
+ - { 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: USE_RVARGC=0, value: '-DUSE_RVARGC=0' }
-# - { key: cppflags, name: USE_RVARGC=1, value: '-DUSE_RVARGC=1' }
-
- - { key: cppflags, name: DEBUG_FIND_TIME_NUMGUESS, value: '-DDEBUG_FIND_TIME_NUMGUESS' }
- - { key: cppflags, name: DEBUG_INTEGER_PACK, value: '-DDEBUG_INTEGER_PACK' }
-# - { key: cppflags, name: ENABLE_PATH_CHECK, value: '-DENABLE_PATH_CHECK' }
-
- - { key: cppflags, name: GC_DEBUG_STRESS_TO_CLASS, value: '-DGC_DEBUG_STRESS_TO_CLASS' }
-# - { key: cppflags, name: GC_ENABLE_LAZY_SWEEP=0, value: '-DGC_ENABLE_LAZY_SWEEP=0' }
-# - { key: cppflags, name: GC_PROFILE_DETAIL_MEMOTY, value: '-DGC_PROFILE_DETAIL_MEMOTY' }
-# - { key: cppflags, name: GC_PROFILE_MORE_DETAIL, value: '-DGC_PROFILE_MORE_DETAIL' }
-
-# - { key: cppflags, name: CALC_EXACT_MALLOC_SIZE, value: '-DCALC_EXACT_MALLOC_SIZE' }
-# - { key: cppflags, name: MALLOC_ALLOCATED_SIZE_CHECK, value: '-DMALLOC_ALLOCATED_SIZE_CHECK' }
-
-# - { key: cppflags, name: IBF_ISEQ_ENABLE_LOCAL_BUFFER, value: '-DIBF_ISEQ_ENABLE_LOCAL_BUFFER' }
-
-# - { key: cppflags, name: RGENGC_ESTIMATE_OLDMALLOC, value: '-DRGENGC_ESTIMATE_OLDMALLOC' }
-# - { key: cppflags, name: RGENGC_FORCE_MAJOR_GC, value: '-DRGENGC_FORCE_MAJOR_GC' }
-# - { key: cppflags, name: RGENGC_OBJ_INFO, value: '-DRGENGC_OBJ_INFO' }
-# - { key: cppflags, name: RGENGC_OLD_NEWOBJ_CHECK, value: '-DRGENGC_OLD_NEWOBJ_CHECK' }
-# - { key: cppflags, name: RGENGC_PROFILE, value: '-DRGENGC_PROFILE' }
-
-# - { key: cppflags, name: VM_DEBUG_BP_CHECK, value: '-DVM_DEBUG_BP_CHECK' }
-# - { key: cppflags, name: VM_DEBUG_VERIFY_METHOD_CACHE, value: '-DVM_DEBUG_VERIFY_METHOD_CACHE' }
-
- - { key: cppflags, name: MJIT_FORCE_ENABLE, value: '-DMJIT_FORCE_ENABLE' }
- - { key: cppflags, name: YJIT_FORCE_ENABLE, value: '-DYJIT_FORCE_ENABLE' }
+# - { name: 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:
- image: ghcr.io/ruby/ruby-ci-image:${{ matrix.entry.container || 'clang-15' }}
+ image: ghcr.io/ruby/ruby-ci-image:${{ matrix.entry.container || matrix.entry.env.default_cc || 'clang-15' }}
options: --user root
- if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ 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:
@@ -199,12 +224,11 @@ jobs:
working-directory:
- name: setenv
run: |
- echo "${{ matrix.entry.key }}=${{ matrix.entry.value }}" >> $GITHUB_ENV
echo "GNUMAKEFLAGS=-sj$((1 + $(nproc --all)))" >> $GITHUB_ENV
- - uses: actions/checkout@v2
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: src
- - uses: actions/cache@v2
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: src/.downloaded-cache
key: downloaded-cache
@@ -213,25 +237,32 @@ jobs:
- name: Run configure
run: >
../src/configure -C ${default_configure} ${append_configure}
- ${{ matrix.entry.key == 'crosshost' && '--host="${crosshost}"' || '--with-gcc="${default_cc} ${append_cc}"' }}
- ${{ matrix.entry.shared || '--enable-shared' }}
+ --${{
+ 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: make prepare-gems
- if: ${{ matrix.entry.check }}
- run: make test-tool
if: ${{ matrix.entry.check }}
- run: make test-all TESTS='-- ruby -ext-'
if: ${{ matrix.entry.check }}
- run: make test-spec
+ 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: |
{
@@ -239,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
new file mode 100644
index 0000000000..d8dc58b119
--- /dev/null
+++ b/.github/workflows/macos.yml
@@ -0,0 +1,113 @@
+name: macOS
+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:
+ - 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:
+ - 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: Install libraries
+ run: |
+ brew install gmp libffi openssl@1.1 zlib autoconf automake libtool readline bison
+ working-directory: src
+ - name: Set ENV
+ run: |
+ 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 incs
+ - run: make prepare-gems
+ if: ${{ matrix.test_task == 'test-bundled-gems' }}
+ - run: make
+ - run: make leaked-globals
+ if: ${{ matrix.test_task == 'check' }}
+ - 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"
+ 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": "${{ 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/mingw.yml b/.github/workflows/mingw.yml
index 3c531625e1..0df917d3d8 100644
--- a/.github/workflows/mingw.yml
+++ b/.github/workflows/mingw.yml
@@ -3,18 +3,32 @@ 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
#
@@ -26,23 +40,22 @@ jobs:
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:
include:
- - msystem: "MINGW64"
- base_ruby: 2.6
- test_task: "check" # to make job names consistent
+ # To mitigate flakiness of MinGW CI, we test only one runtime that newer MSYS2 uses.
- msystem: "UCRT64"
base_ruby: head
- test_task: "check" # to make job names consistent
+ test_task: "check"
+ test-all-opts: "--name=!/TestObjSpace#test_reachable_objects_during_iteration/"
fail-fast: false
- if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ if: ${{ !contains(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
steps:
- run: mkdir build
working-directory:
@@ -52,21 +65,20 @@ 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@v2
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: src/.downloaded-cache
key: downloaded-cache
- name: Set up Ruby & MSYS2
- uses: ruby/setup-ruby@v1
+ uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0
with:
ruby-version: ${{ matrix.base_ruby }}
- name: set env
run: |
echo "GNUMAKEFLAGS=-j$((2 * NUMBER_OF_PROCESSORS))" >> $GITHUB_ENV
- echo "TEST_JOBS=$((15 * NUMBER_OF_PROCESSORS / 10))" >> $GITHUB_ENV
- name: where check
run: |
@@ -112,7 +124,7 @@ jobs:
make update-gems
- name: make all
- timeout-minutes: 20
+ timeout-minutes: 30
run: |
make
@@ -126,23 +138,28 @@ jobs:
timeout-minutes: 5
run: |
make test
+ if: ${{matrix.test_task == 'check' || matrix.test_task == 'test'}}
- name: test-all
timeout-minutes: 45
run: |
# Actions uses UTF8, causes test failures, similar to normal OS setup
chcp.com 437
- make test-all
+ make ${{ StartsWith(matrix.test_task, 'test/') && matrix.test_task || 'test-all' }}
env:
- RUBY_TESTOPTS: -j${{env.TEST_JOBS}} --retry --job-status=normal --show-skip --timeout-scale=1.5
+ 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
run: |
- make test-spec
+ 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: |
{
@@ -150,7 +167,7 @@ jobs:
"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
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 75e5b1088c..6f7181489a 100644
--- a/.github/workflows/mjit.yml
+++ b/.github/workflows/mjit.yml
@@ -3,30 +3,47 @@ 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: [ "--mjit", "--mjit-wait" ]
+ test_task: [check] # to make job names consistent
+ mjit_opts: [--mjit-wait]
fail-fast: false
runs-on: ubuntu-latest
- if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ 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 }} --mjit-debug=-ggdb3'
+ RUN_OPTS: '--disable-gems ${{ matrix.mjit_opts }} --mjit-debug=-ggdb3'
GITPULLOPTIONS: --no-tags origin ${{github.ref}}
steps:
- run: mkdir build
@@ -40,10 +57,10 @@ 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@v2
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: src/.downloaded-cache
key: downloaded-cache
@@ -62,31 +79,30 @@ jobs:
- run: make incs
- run: make
- run: sudo make -s install
- - run: sudo apt-get install gdb # used by test / test-all failure
- name: Run test
run: |
- ulimit -c unlimited
+ 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-all
+ # run: |
+ # ulimit -c unlimited
+ # make -s test-all RUN_OPTS="$RUN_OPTS"
+ # timeout-minutes: 60
- name: Run test-spec
run: |
- ulimit -c unlimited
+ 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 06987a6cff..4521195a2b 100644
--- a/.github/workflows/spec_guards.yml
+++ b/.github/workflows/spec_guards.yml
@@ -2,43 +2,61 @@ name: Rubyspec Version Guards Check
on:
push:
- paths-ignore:
- - 'doc/**'
- - '**.md'
- - '**.rdoc'
+ paths:
+ - 'spec/**'
+ - '!spec/*.md'
pull_request:
- paths-ignore:
- - 'doc/**'
- - '**.md'
- - '**.rdoc'
+ 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
- if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+
+ 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.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: |
{
@@ -46,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 c01db1cc6c..4fbca1170e 100644
--- a/.github/workflows/ubuntu.yml
+++ b/.github/workflows/ubuntu.yml
@@ -3,55 +3,69 @@ 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: "check"
- configure: "--host=i686-$OSTYPE"
- - test_task: "check"
+ - test_task: check
+ - test_task: check
+ arch: i686
+ configure: '' # test without -DRUBY_DEBUG as well
+ - test_task: check
configure: "--enable-shared --enable-load-relative"
- skipped_tests: "TestGem#test_.*_from_binstubs.*"
- continue-on-skipped_tests: true
- - test_task: "test-all TESTS=--repeat-count=2"
+ - 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 || 'ubuntu-20.04' }}
- if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ 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
- env:
- configure: ${{matrix.configure}}
run: |
echo "GNUMAKEFLAGS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV
- arch=`echo " $configure" | sed '/.* --host=/!d;s///;s/[- ].*//'`
- echo "SETARCH=${arch:+setarch $arch}" >> $GITHUB_ENV
- name: Install libraries
+ env:
+ arch: ${{matrix.arch}}
run: |
set -x
- arch="${SETARCH##* }"
arch=${arch:+:${arch/i[3-6]86/i386}}
${arch:+sudo dpkg --add-architecture ${arch#:}}
sudo apt-get update -q || :
@@ -65,10 +79,10 @@ 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@v2
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: src/.downloaded-cache
key: downloaded-cache
@@ -84,13 +98,13 @@ jobs:
arch: ${{matrix.arch}}
run: >-
$SETARCH ../src/configure -C --disable-install-doc ${{ matrix.configure }}
- ${arch:+--target=$arch-$OSTYPE}
+ ${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' }}
- - run: $SETARCH make prepare-gems
- if: ${{ matrix.test_task == 'check' }}
- name: Create dummy files in build dir
run: |
$SETARCH ./miniruby -e '(("a".."z").to_a+("A".."Z").to_a+("0".."9").to_a+%w[foo bar test zzz]).each{|basename|File.write("#{basename}.rb", "raise %(do not load #{basename}.rb)")}'
@@ -113,15 +127,15 @@ jobs:
TESTS: ${{ matrix.skipped_tests }}
if: ${{ matrix.test_task == 'check' && matrix.skipped_tests != '' }}
continue-on-error: ${{ matrix.continue-on-skipped_tests || false }}
- - uses: k0kubun/action-slack@v2.0.0
+ - 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
index 4860b0d35e..27920b5821 100644
--- a/.github/workflows/wasm.yml
+++ b/.github/workflows/wasm.yml
@@ -3,18 +3,32 @@ 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:
@@ -34,11 +48,10 @@ jobs:
GITPULLOPTIONS: --no-tags origin ${{github.ref}}
WASI_SDK_VERSION_MAJOR: 14
WASI_SDK_VERSION_MINOR: 0
- # Use older version, which uses glibc instead of musl, to avoid https://github.com/WebAssembly/binaryen/issues/4401
- BINARYEN_VERSION: 91
+ BINARYEN_VERSION: 109
WASMTIME_VERSION: v0.33.0
- runs-on: ubuntu-20.04
- if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ 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:
@@ -46,7 +59,7 @@ 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
- name: Install libraries
@@ -67,10 +80,10 @@ jobs:
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-linux.tar.gz"
+ 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}/wasm-opt" /usr/local/bin/wasm-opt
+ sudo ln -fs "$PWD/binaryen-version_${BINARYEN_VERSION}/bin/wasm-opt" /usr/local/bin/wasm-opt
working-directory: src
- name: Set ENV
run: |
@@ -78,6 +91,18 @@ jobs:
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 \
@@ -91,7 +116,8 @@ jobs:
debugflags="${{ matrix.entry.debugflags }}" \
wasmoptflags="${{ matrix.entry.wasmoptflags }} ${{ matrix.entry.debugflags }}"
- - run: make ruby
+ # 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
@@ -101,6 +127,20 @@ jobs:
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 1a61f5562d..c2bd4881c2 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -3,108 +3,107 @@ 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:
- - vs: 2019
- vs: 2022
+ vcvers: -vcvars_ver=14.2
fail-fast: false
- runs-on: windows-${{ matrix.vs < 2022 && '2019' || matrix.vs }}
- if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ 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}}
PATCH: C:\msys64\usr\bin\patch.exe
- OS_VER: windows-${{ matrix.vs < 2022 && '2019' || matrix.vs }}
+ OS_VER: windows-${{ matrix.vs }}
steps:
- run: md build
working-directory:
- - uses: msys2/setup-msys2@v2
+ - uses: msys2/setup-msys2@61f9e5e925871ba6c9e3e8da24ede83ea27fa91f # v2.27.0
id: setup-msys2
with:
update: true
- install: >-
- patch
- if: ${{ env.OS_VER != 'windows-2019' }}
+ 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@v2
- with:
- path: C:\vcpkg\downloads
- key: ${{ runner.os }}-vcpkg-download-${{ env.OS_VER }}-${{ github.sha }}
- restore-keys: |
- ${{ runner.os }}-vcpkg-download-${{ env.OS_VER }}-
- ${{ runner.os }}-vcpkg-download-
- - uses: actions/cache@v2
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: C:\vcpkg\installed
- key: ${{ runner.os }}-vcpkg-installed-${{ matrix.os }}-${{ github.sha }}
+ key: ${{ runner.os }}-vcpkg-installed-windows-${{ matrix.vs }}-${{ github.sha }}
restore-keys: |
- ${{ runner.os }}-vcpkg-installed-${{ matrix.os }}-
- ${{ runner.os }}-vcpkg-installed-
+ ${{ runner.os }}-vcpkg-installed-windows-${{ matrix.vs }}-
+ ${{ runner.os }}-vcpkg-installed-windows-
- name: Install libraries with vcpkg
run: |
+ 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
- - uses: actions/cache@v2
- with:
- path: C:\Users\runneradmin\AppData\Local\Temp\chocolatey
- key: ${{ runner.os }}-chocolatey-${{ env.OS_VER }}-${{ github.sha }}
- restore-keys: |
- ${{ runner.os }}-chocolatey-${{ env.OS_VER }}-
- ${{ runner.os }}-chocolatey-
- - name: Install libraries with chocolatey
- run: |
- # Using Choco-Install for retries, but it doesn't detect failures properly
- # if you pass multiple package names in a single command.
- Choco-Install -PackageName winflexbison3
- shell: pwsh
+ 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
- - uses: actions/cache@v2
+ - 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: |
- set VS=${{ matrix.vs }}
- set VCVARS=${{ matrix.vcvars }}
+ set Path=D:/a/_temp/msys64/usr/bin;%Path%
if not "%VCVARS%" == "" goto :vcset
- set VCVARS="C:\Program Files (x86)\Microsoft Visual Studio\%VS%\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
- if not exist %VCVARS% set VCVARS="C:\Program Files\Microsoft Visual Studio\%VS%\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
+ 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%
+ call %VCVARS% ${{ matrix.vcvers || ''}}
set TMP=%USERPROFILE%\AppData\Local\Temp
set TEMP=%USERPROFILE%\AppData\Local\Temp
set /a TEST_JOBS=(15 * %NUMBER_OF_PROCESSORS% / 10) > nul
set | C:\msys64\usr\bin\sort > new.env
C:\msys64\usr\bin\comm -13 old.env new.env >> %GITHUB_ENV%
del *.env
+ - name: compiler version
+ run: cl
- name: link libraries
run: |
for %%I in (C:\vcpkg\installed\x64-windows\bin\*.dll) do (
@@ -121,18 +120,16 @@ jobs:
- run: nmake extract-extlibs
- run: nmake
env:
- YACC: win_bison
+ 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
- continue-on-error: ${{ matrix.continue-on-error || false }}
- - run: nmake test-spec
- timeout-minutes: 10
- continue-on-error: ${{ matrix.continue-on-error || false }}
- - uses: k0kubun/action-slack@v2.0.0
+ - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1
with:
payload: |
{
@@ -140,7 +137,7 @@ jobs:
"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
index b6fda32a54..0b7b9046e9 100644
--- a/.github/workflows/yjit-ubuntu.yml
+++ b/.github/workflows/yjit-ubuntu.yml
@@ -3,47 +3,90 @@ 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:
- test_task: ["check"] # "test-bundler-parallel",
- os:
- - ubuntu-20.04
-# - ubuntu-18.04
- yjit_opts: [
- "--yjit",
- "--yjit --yjit-call-threshold=1",
- ]
- configure: ["", "cppflags=-DRUBY_DEBUG"]
include:
+ - test_task: '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"
- os: ubuntu-20.04
- configure: ""
- yjit_enable_env: RUBY_YJIT_ENABLE
+ configure: "--enable-yjit=dev"
+
- test_task: "test-bundled-gems"
- os: ubuntu-20.04
- configure: "cppflags=-DRUBY_DEBUG"
- yjit_enable_env: RUBY_YJIT_ENABLE
- fail-fast: false
+ 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
- runs-on: ${{ matrix.os }}
- if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
+ 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:
@@ -52,14 +95,17 @@ jobs:
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@v2
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: src
- - uses: actions/cache@v2
+ - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: src/.downloaded-cache
key: downloaded-cache
@@ -74,12 +120,12 @@ jobs:
- run: ./autogen.sh
working-directory: src
- name: Run configure
- run: ../src/configure -C --disable-install-doc ${{ matrix.configure }}
+ run: ../src/configure -C --disable-install-doc --prefix=$(pwd)/install ${{ matrix.configure }}
- run: make incs
- - run: make
- - run: make leaked-globals
- if: ${{ matrix.test_task == 'check' }}
- 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: |
@@ -87,22 +133,33 @@ jobs:
if: ${{ matrix.test_task == 'check' }}
- name: Enable YJIT through ENV
run: echo "RUBY_YJIT_ENABLE=1" >> $GITHUB_ENV
- if: ${{ matrix.yjit_enable_env }}
- - run: make -s ${{ matrix.test_task }} RUN_OPTS="$RUN_OPTS"
+ # 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"
- - uses: k0kubun/action-slack@v2.0.0
+ 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": "${{ matrix.os }} / ${{ matrix.test_task }}${{ matrix.configure }}",
+ "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 }}".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_asm_tests.yml b/.github/workflows/yjit_asm_tests.yml
deleted file mode 100644
index 8a9052dd41..0000000000
--- a/.github/workflows/yjit_asm_tests.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-name: YJIT x86 assembler tests
-
-on:
- push:
- paths-ignore:
- - 'doc/**'
- - '**.md'
- - '**.rdoc'
- pull_request:
- paths-ignore:
- - 'doc/**'
- - '**.md'
- - '**.rdoc'
-
-concurrency:
- group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
- cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
-
-jobs:
- test:
- runs-on: ubuntu-latest
- if: ${{ !startsWith(github.event.head_commit.message, '[DOC]') && !contains(github.event.pull_request.labels.*.name, 'Documentation') }}
- steps:
- - name: Install dependencies
- run: |
- set -x
- sudo apt-get update -q || :
- sudo apt-get install --no-install-recommends -q -y build-essential
- - name: git config
- run: |
- git config --global advice.detachedHead 0
- git config --global init.defaultBranch garbage
- - uses: actions/checkout@v2
- with:
- path: src
- - name: Run ASM tests
- run: ./misc/test_yjit_asm.sh
- working-directory: src
diff --git a/.gitignore b/.gitignore
index 675020fa91..99d32a1825 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,6 +14,7 @@
*.inc
*.log
*.o
+*.o.tmp
*.obj
*.old
*.orig
@@ -25,6 +26,7 @@
*.sav
*.sl
*.so
+*.so.*
*.swp
*.yarb
*~
@@ -127,6 +129,7 @@ lcov*.info
/ruby-runner
/ruby-runner.h
/ruby-man.rd.gz
+/rubyspec_temp
/run.gdb
/sizes.c
/static-ruby
@@ -144,6 +147,8 @@ lcov*.info
/bin/*.exe
/bin/*.dll
+/bin/goruby
+/bin/ruby
# /benchmark/
/benchmark/bm_require.data
@@ -218,6 +223,9 @@ lcov*.info
/lib/ruby/[1-9]*.*
/lib/ruby/vendor_ruby
+# /misc/
+/misc/**/__pycache__
+
# /spec/bundler
/.rspec_status
@@ -229,9 +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/.travis.yml b/.travis.yml
deleted file mode 100644
index a34d3692af..0000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,234 +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
-
-if: commit_message !~ /^\[DOC\]/
-
-dist: focal
-
-git:
- quiet: true
-
-cache:
- ccache: true
- directories:
- - $HOME/config_2nd
- - $HOME/.downloaded-cache
-
-env:
- global:
- # The tests skipped in `make test-all`.
- - TEST_ALL_SKIPPED_TESTS=
- # The tests executed separately by `make test-all`.
- - TEST_ALL_SEPARATED_TESTS=
- # Reset timestamps early
- - _=$(touch NEWS && find . -type f -exec touch -r NEWS {} +)
- - CONFIGURE_TTY=no
- - CCACHE_COMPILERCHECK=none
- - CCACHE_NOCOMPRESS=1
- - CCACHE_MAXSIZE=512Mi
- - NPROC="`nproc`"
- # JOBS and SETARCH are overridden when necessary; see below.
- - JOBS=-j$((1+${NPROC}))
- - SETARCH=
- - RUBY_PREFIX=/tmp/ruby-prefix
- - GEMS_FOR_TEST='timezone tzinfo'
- # 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
- 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'
- # The "TestReadline#test_interrupt_in_other_thread" started failing on arm32
- # from https://www.travis-ci.com/github/ruby/ruby/jobs/529005145
- - TEST_ALL_SKIPPED_TESTS=test_interrupt_in_other_thread
- before_install:
- - sudo dpkg --add-architecture armhf
- - tool/travis_retry.sh sudo bash -c "rm -rf '${TRAVIS_ROOT}/var/lib/apt/lists/'* && exec apt-get update -yq"
- - >-
- tool/travis_retry.sh sudo -E apt-get $travis_apt_get_options install
- ccache
- crossbuild-essential-armhf
- libc6:armhf
- libstdc++-10-dev:armhf
- libffi-dev:armhf
- libncurses-dev:armhf
- libncursesw5-dev:armhf
- libreadline-dev:armhf
- libssl-dev:armhf
- linux-libc-dev:armhf
- zlib1g-dev:armhf
-
-matrix:
- include:
- # Build every commit (Allowed Failures):
- - <<: *arm32-linux
- # Comment out as the 2nd arm64 pipeline is unstable.
- # - <<: *arm64-linux
- - <<: *ppc64le-linux
- - <<: *s390x-linux
- allow_failures:
- # We see multiple errors indicating errors on the Travis environment itself in a short while:
- # https://app.travis-ci.com/github/ruby/ruby/jobs/544382885
- # https://app.travis-ci.com/github/ruby/ruby/jobs/544361370
- # It's not a fault of Ruby's arm32 support but just Travis arm32 seems unsable.
- - name: arm32-linux
- # - name: arm64-linux
- # We see "Some worker was crashed." in about 40% of recent ppc64le-linux jobs
- # e.g. https://app.travis-ci.com/github/ruby/ruby/jobs/530959548
- - name: ppc64le-linux
- # Tentatively disable, because often hungs up **after** all tests
- # have finished successfully and saving caches.
- - name: s390x-linux
- fast_finish: true
-
-before_script:
- - . tool/ci_functions.sh
- - |-
- if [ -n "${TEST_ALL_SKIPPED_TESTS}" ]; then
- TEST_ALL_OPTS="${TEST_ALL_OPTS} $(ci_to_excluded_test_opts "${TEST_ALL_SKIPPED_TESTS}")"
- if [ -z "${TEST_ALL_SEPARATED_TESTS}" ]; then
- TEST_ALL_SEPARATED_TESTS="${TEST_ALL_SKIPPED_TESTS}"
- fi
- fi
- - |-
- if [ -n "${TEST_ALL_SEPARATED_TESTS}" ]; then
- TEST_ALL_OPTS_SEPARATED="$(ci_to_included_test_opts "${TEST_ALL_SEPARATED_TESTS}")"
- fi
- - echo TEST_ALL_OPTS="${TEST_ALL_OPTS}" TEST_ALL_OPTS_SEPARATED="${TEST_ALL_OPTS_SEPARATED}"
- - rm -fr .ext autom4te.cache
- - |-
- [ -d ~/.downloaded-cache ] ||
- mkdir ~/.downloaded-cache
- - ln -s ~/.downloaded-cache
- - "> config.status"
- - "> .rbconfig.time"
- - sed -f tool/prereq.status template/Makefile.in common.mk > Makefile
- - make -s $JOBS up
- - make -s $JOBS srcs
- - rm -f config.status Makefile rbconfig.rb .rbconfig.time
- - |-
- if [ -d ~/config_2nd ]; then
- cp -pr ~/config_2nd build
- else
- mkdir build
- fi
- - mkdir config_1st config_2nd
- - 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 [ -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 7363c106a2..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]: 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 9645728efe..0423d57ac9 100644
--- a/LEGAL
+++ b/LEGAL
@@ -979,7 +979,6 @@ mentioned below.
{MIT License}[rdoc-label:label-MIT+License]
[lib/rubygems/resolver/molinillo]
-[lib/bundler/vendor/molinillo]
molinillo is under the following license.
@@ -988,6 +987,15 @@ mentioned below.
{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.
diff --git a/NEWS.md b/NEWS.md
index 9fe18974fb..f6c3c6fc97 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -20,98 +20,557 @@ Note that each entry is kept to a minimum, see links for details.
end
```
+* A proc that accepts a single positional argument and keywords will
+ no longer autosplat. [[Bug #18633]]
+
+ ```ruby
+ proc{|a, **k| a}.call([1, 2])
+ # Ruby 3.1 and before
+ # => 1
+ # Ruby 3.2 and after
+ # => [1, 2]
+ ```
+
* Constant assignment evaluation order for constants set on explicit
objects has been made consistent with single attribute assignment
- evaluation order. With this code:
+ evaluation order. With this code:
```ruby
foo::BAR = baz
```
- `foo` is now called before `baz`. Similarly, for multiple assignment
- to constants, left-to-right evaluation order is used. With this
- code:
+ `foo` is now called before `baz`. Similarly, for multiple assignments
+ to constants, left-to-right evaluation order is used. With this
+ code:
```ruby
- foo1::BAR1, foo2::BAR2 = baz1, baz2
+ foo1::BAR1, foo2::BAR2 = baz1, baz2
```
- The following evaluation order is now used:
+ The following evaluation order is now used:
- 1. `foo1`
- 2. `foo2`
- 3. `baz1`
- 4. `baz2`
+ 1. `foo1`
+ 2. `foo2`
+ 3. `baz1`
+ 4. `baz2`
- [[Bug #15928]]
+ [[Bug #15928]]
-* Find pattern is no longer experimental.
+* "Find pattern" is no longer experimental.
[[Feature #18585]]
-## Command line options
+* 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
+ 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)
+ ```
## 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]]
+
+ 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.
+
+ ```ruby
+ def log(message)
+ puts "#{Fiber[:request_id]}: #{message}"
+ end
+
+ def handle_requests
+ while request = read_request
+ Fiber.schedule do
+ Fiber[:request_id] = SecureRandom.uuid
+
+ request.messages.each do |message|
+ Fiber.schedule do
+ log("Handling #{message}") # Log includes inherited request_id.
+ end
+ end
+ end
+ end
+ end
+ ```
+
+ 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.
+
+* Fiber::Scheduler
+
+ * Introduce `Fiber::Scheduler#io_select` for non-blocking IO.select.
+ [[Feature #19060]]
+
+* IO
+
+ * Introduce IO#timeout= and IO#timeout which can cause
+ IO::TimeoutError to be raised if a blocking operation exceeds the
+ specified timeout. [[Feature #18630]]
+
+ ```ruby
+ STDIN.timeout = 1
+ STDIN.read # => Blocking operation timed out! (IO::TimeoutError)
+ ```
+
+ * Introduce `IO.new(..., path:)` and promote `File#path` to `IO#path`.
+ [[Feature #19036]]
+
+* Class
+
+ * 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]]
+
+ ```ruby
+ class Foo; end
+
+ 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
+ ```
+
+* Data
+
+ * 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#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.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]]
* Proc
+
* Proc#dup returns an instance of subclass. [[Bug #17545]]
* Proc#parameters now accepts lambda keyword. [[Feature #15357]]
+* 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 builtin class without the need for `require "set"`. [[Feature #16989]]
- It is currently autoloaded via the `Set` constant or a call to `Enumerable#to_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 14.0.0 and Emoji Version 14.0. [[Feature #18037]]
+ * 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
+
* A Struct class can also be initialized with keyword arguments
- without `keyword_init: true` on `Struct.new` [[Feature #16806]]
+ without `keyword_init: true` on Struct.new [[Feature #16806]]
+
+ ```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.each_caller_location is added. [[Feature #16663]]
+
+* Thread::Queue
+
+ * Thread::Queue#pop(timeout: sec) is added. [[Feature #18774]]
+
+* Thread::SizedQueue
+
+ * Thread::SizedQueue#pop(timeout: sec) is added. [[Feature #18774]]
+ * Thread::SizedQueue#push(timeout: sec) is added. [[Feature #18944]]
+
+* Time
+
+ * Time#deconstruct_keys is added, allowing to use Time instances
+ in pattern-matching expressions [[Feature #19071]]
+
+ * Time.new now can parse a string like generated by Time#inspect
+ and return a Time instance based on the given argument.
+ [[Feature #18033]]
+
+* SyntaxError
+ * SyntaxError#path has been added. [[Feature #19138]]
+
+* TracePoint
+
+ * 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
-* The following default gem are updated.
- * RubyGems 3.4.0.dev
- * bigdecimal 3.1.2
- * bundler 2.4.0.dev
- * cgi 0.3.2
- * etc 1.4.0
- * io-console 0.5.11
- * io-wait 0.2.2.pre1
- * ipaddr 1.2.4
- * logger 1.5.1
- * ostruct 0.5.3
- * reline 0.3.1
- * securerandom 0.2.0
+* 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.
- * net-imap 0.2.3
- * rbs 2.2.2
- * typeprof 0.21.2
-* The following default gems are now bundled gems.
+
+ * 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
-Note: 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
@@ -133,56 +592,229 @@ The following deprecated methods are removed.
[[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
+
+* 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
+* 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
-### Removed C APIs
+### Updated C APIs
-The following deprecated APIs are removed.
+The following APIs are updated.
-* `rb_cData` variable.
-* "taintedness" and "trustedness" functions. [[Feature #16131]]
+* PRNG update
-## Implementation improvements
+ `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.
-## JIT
+### Added C APIs
-### MJIT
+* `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.
-### YJIT: New experimental in-process JIT compiler
+### Removed C APIs
-## Static analysis
+The following deprecated APIs are removed.
-### RBS
+* `rb_cData` variable.
+* "taintedness" and "trustedness" functions. [[Feature #16131]]
-### TypeProf
+## Implementation improvements
-## Debugger
+* 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]]
-## error_highlight
+## JIT
-## IRB Autocomplete and Document Display
+### 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.
-## Miscellaneous changes
+### MJIT
-[Feature #12005]: https://bugs.ruby-lang.org/issues/12005
-[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 #16131]: https://bugs.ruby-lang.org/issues/16131
-[Feature #16806]: https://bugs.ruby-lang.org/issues/16806
-[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
-[Feature #17881]: https://bugs.ruby-lang.org/issues/17881
-[Feature #18037]: https://bugs.ruby-lang.org/issues/18037
-[Feature #18351]: https://bugs.ruby-lang.org/issues/18351
-[Feature #18585]: https://bugs.ruby-lang.org/issues/18585
-[Feature #18598]: https://bugs.ruby-lang.org/issues/18598
+* 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 bb69c09055..93c0131690 100644
--- a/README.ja.md
+++ b/README.ja.md
@@ -4,7 +4,6 @@
[![Actions Status: Windows](https://github.com/ruby/ruby/workflows/Windows/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"Windows")
[![AppVeyor status](https://ci.appveyor.com/api/projects/status/0sy8rrxut4o0k960/branch/master?svg=true)](https://ci.appveyor.com/project/ruby/ruby/branch/master)
[![Travis Status](https://app.travis-ci.com/ruby/ruby.svg?branch=master)](https://app.travis-ci.com/ruby/ruby)
-[![Cirrus Status](https://api.cirrus-ci.com/github/ruby/ruby.svg)](https://cirrus-ci.com/github/ruby/ruby/master)
# Rubyã¨ã¯
diff --git a/README.md b/README.md
index 9b5a553ffb..c445448c71 100644
--- a/README.md
+++ b/README.md
@@ -4,9 +4,8 @@
[![Actions Status: Windows](https://github.com/ruby/ruby/workflows/Windows/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"Windows")
[![AppVeyor status](https://ci.appveyor.com/api/projects/status/0sy8rrxut4o0k960/branch/master?svg=true)](https://ci.appveyor.com/project/ruby/ruby/branch/master)
[![Travis Status](https://app.travis-ci.com/ruby/ruby.svg?branch=master)](https://app.travis-ci.com/ruby/ruby)
-[![Cirrus Status](https://api.cirrus-ci.com/github/ruby/ruby.svg)](https://cirrus-ci.com/github/ruby/ruby/master)
-# What's Ruby
+# 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/maintainers.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](rdoc-ref: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](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](rdoc-ref:CONTRIBUTING)
+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 f660be9129..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;
}
@@ -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) {
@@ -1437,8 +1594,21 @@ ranges_include(DebugInfoReader *reader, ranges_t *ptr, uint64_t addr)
const char *p;
uint64_t base = ptr->low_pc_set ? ptr->low_pc : reader->current_low_pc;
bool base_valid = true;
- if (reader->obj->debug_rnglists.ptr) {
- p = reader->obj->debug_rnglists.ptr + ptr->ranges;
+ 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 from = 0, to = 0;
@@ -1548,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;
}
@@ -1580,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;
@@ -1643,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 = {};
@@ -1669,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;
@@ -1677,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;
@@ -1694,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));
@@ -1715,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)
@@ -1843,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++) {
@@ -2100,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) {
@@ -2257,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);
@@ -2296,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;
@@ -2326,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;
}
}
@@ -2337,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 f47c1509ad..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,27 +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); \
@@ -184,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__)
@@ -193,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
@@ -261,7 +331,7 @@ void
rb_mem_clear(VALUE *mem, long size)
{
while (size--) {
- *mem++ = Qnil;
+ *mem++ = Qnil;
}
}
@@ -269,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);
});
}
@@ -277,7 +347,7 @@ static inline void
memfill(register VALUE *mem, register long size, register VALUE val)
{
while (size--) {
- *mem++ = val;
+ *mem++ = val;
}
}
@@ -285,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);
});
}
@@ -391,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));
@@ -440,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)
{
@@ -447,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);
@@ -499,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);
@@ -513,14 +601,16 @@ ary_double_capa(VALUE ary, long min)
static void
rb_ary_decrement_share(VALUE shared_root)
{
- long num = ARY_SHARED_ROOT_REFCNT(shared_root);
- ARY_SET_SHARED_ROOT_REFCNT(shared_root, num - 1);
+ 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);
}
@@ -542,9 +632,11 @@ rb_ary_reset(VALUE ary)
static VALUE
rb_ary_increment_share(VALUE shared_root)
{
- long num = ARY_SHARED_ROOT_REFCNT(shared_root);
- assert(num >= 0);
- ARY_SET_SHARED_ROOT_REFCNT(shared_root, num + 1);
+ 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;
}
@@ -573,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);
@@ -620,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);
@@ -665,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
@@ -690,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);
@@ -710,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
@@ -722,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);
}
@@ -751,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
@@ -765,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);
@@ -780,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;
@@ -794,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);
@@ -805,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);
}
@@ -838,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);
@@ -854,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;
}
@@ -897,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;
}
}
@@ -963,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;
@@ -1025,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
@@ -1039,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]
@@ -1046,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']
*
@@ -1059,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"]
*
@@ -1080,45 +1246,45 @@ rb_ary_initialize(int argc, VALUE *argv, VALUE 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;
+ 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;
}
@@ -1149,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);
}
@@ -1180,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);
@@ -1215,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]);
@@ -1278,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);
}
@@ -1294,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
@@ -1309,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);
@@ -1333,10 +1509,12 @@ 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]]
@@ -1360,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);
@@ -1380,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"]
@@ -1387,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]
*
@@ -1405,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);
@@ -1441,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]
@@ -1449,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]
*
@@ -1470,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);
@@ -1490,8 +1674,8 @@ rb_ary_behead(VALUE ary, long n)
rb_ary_modify_check(ary);
- if (RB_UNLIKELY(!ARY_SHARED_P(ary))) {
- if (RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) {
+ 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 */
@@ -1542,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;
}
}
@@ -1604,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]
*
@@ -1619,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);
@@ -1642,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);
}
@@ -1663,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);
@@ -1697,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"
@@ -1711,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]
@@ -1730,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]
@@ -1737,18 +1927,21 @@ 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
@@ -1757,11 +1950,13 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
* When a single Enumerator::ArithmeticSequence argument +aseq+ is given,
* returns an \Array of elements corresponding to the indexes produced by
* the sequence.
+ *
* a = ['--', 'data1', '--', 'data2', '--', 'data3']
* a[(1..).step(2)] # => ["data1", "data2", "data3"]
*
* Unlike slicing with range, if the start or the end of the arithmetic sequence
* is larger than array size, throws RangeError.
+ *
* a = ['--', 'data1', '--', 'data2', '--', 'data3']
* a[(1..11).step(2)]
* # RangeError (((1..11).step(2)) out of range)
@@ -1770,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]
@@ -1782,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]);
}
@@ -1793,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);
}
@@ -1805,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)) {
@@ -1828,6 +2024,7 @@ rb_ary_aref1(VALUE ary, VALUE arg)
* a = [:foo, 'bar', 2]
* a.at(0) # => :foo
* a.at(2) # => 2
+ *
*/
VALUE
@@ -1844,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]
@@ -1852,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) # []
*
@@ -1869,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);
}
}
@@ -1885,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) # []
*
@@ -1911,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);
}
}
@@ -1930,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"
@@ -1941,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"
*
@@ -1951,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
@@ -1963,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);
}
@@ -1992,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
*
@@ -2000,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>
@@ -2023,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;
}
@@ -2053,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
*
@@ -2060,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
*
@@ -2082,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;
}
@@ -2126,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);
@@ -2183,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));
- }
+ }
}
}
@@ -2194,10 +2408,10 @@ 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);
}
@@ -2211,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;
@@ -2268,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"]
@@ -2285,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"]
@@ -2297,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"]
@@ -2315,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"]
@@ -2351,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
@@ -2364,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]);
}
@@ -2390,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)
@@ -2407,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
@@ -2422,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;
@@ -2454,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
@@ -2491,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;
}
@@ -2505,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
@@ -2542,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;
}
@@ -2556,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
@@ -2593,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;
}
@@ -2664,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;
}
@@ -2680,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;
}
@@ -2723,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);
}
@@ -2741,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);
- }
+ }
}
}
@@ -2754,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);
@@ -2790,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)
@@ -2831,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;
@@ -2846,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]"
*
@@ -2870,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
@@ -2881,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;
}
@@ -2904,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
@@ -2924,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;
}
@@ -2957,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;
}
}
@@ -2974,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;
}
@@ -2984,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
@@ -2998,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
@@ -3013,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;
@@ -3069,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
@@ -3118,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
@@ -3161,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;
@@ -3174,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;
}
@@ -3220,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);
@@ -3248,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!
@@ -3255,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 }
@@ -3269,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
@@ -3281,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 {
@@ -3345,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
@@ -3352,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 }
@@ -3366,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 }
@@ -3400,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;
}
@@ -3423,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 (!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 = 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);
@@ -3482,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"]
@@ -3490,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
@@ -3512,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]
@@ -3546,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!>
@@ -3565,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;
}
@@ -3577,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;
}
@@ -3601,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));
}
@@ -3632,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
@@ -3666,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;
@@ -3681,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>
*
@@ -3701,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;
}
@@ -3721,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;
}
@@ -3740,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;
}
@@ -3762,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!>
*
@@ -3794,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
@@ -3815,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);
+ }
}
}
@@ -3833,6 +4147,7 @@ ary_resize_smaller(VALUE ary, long len)
* 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"
@@ -3845,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
@@ -3862,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);
@@ -3892,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);
@@ -3917,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);
@@ -3938,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]
@@ -3945,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]
@@ -3998,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"]
@@ -4012,12 +4334,14 @@ 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:
+ *
* 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]
@@ -4029,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.
@@ -4038,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
@@ -4060,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));
@@ -4088,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;
}
@@ -4105,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;
}
@@ -4133,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
@@ -4158,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
@@ -4185,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)
@@ -4222,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;
}
@@ -4239,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]
@@ -4251,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]
@@ -4259,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
@@ -4286,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;
@@ -4342,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
@@ -4355,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;
}
@@ -4379,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
@@ -4392,11 +4740,31 @@ rb_ary_replace(VALUE copy, VALUE orig)
rb_ary_reset(copy);
- if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) {
+ /* 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));
- 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);
FL_UNSET_EMBED(copy);
@@ -4413,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
@@ -4422,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);
@@ -4452,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]
@@ -4461,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']
@@ -4484,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"]
@@ -4507,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']
@@ -4522,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']
@@ -4529,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']
@@ -4562,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"]
@@ -4586,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']
@@ -4601,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
@@ -4614,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;
}
@@ -4677,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]
*
@@ -4717,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]
*/
@@ -4727,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);
@@ -4755,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
@@ -4772,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);
@@ -4794,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;
}
@@ -4813,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]
*
@@ -4828,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;
}
@@ -4842,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]
*
@@ -4857,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;
}
@@ -4880,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;
}
@@ -4906,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
@@ -4922,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;
@@ -4939,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;
}
@@ -4951,6 +5356,7 @@ 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
@@ -4978,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
@@ -4992,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);
@@ -5005,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
*/
@@ -5016,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;
}
@@ -5031,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;
}
@@ -5047,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;
}
@@ -5067,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
@@ -5091,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);
@@ -5104,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;
}
@@ -5133,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;
}
@@ -5152,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);
}
}
@@ -5165,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]
@@ -5172,7 +5591,7 @@ ary_recycle_hash(VALUE hash)
* Related: Array#difference.
*/
-static VALUE
+VALUE
rb_ary_diff(VALUE ary1, VALUE ary2)
{
VALUE ary3;
@@ -5184,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;
@@ -5208,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]
@@ -5260,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.
@@ -5282,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);
@@ -5312,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.
@@ -5374,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]
@@ -5388,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);
@@ -5408,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]
@@ -5452,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
@@ -5599,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+.
*
@@ -5607,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]
*
@@ -5618,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;
@@ -5637,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 {
@@ -5661,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;
}
@@ -5762,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+.
*
@@ -5770,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]
*
@@ -5781,16 +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', '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;
@@ -5800,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 {
@@ -5824,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;
}
@@ -5840,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)
@@ -5876,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]
*
@@ -5886,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']
*
@@ -5901,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);
@@ -5931,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
@@ -5952,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);
@@ -5986,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);
@@ -6003,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]
*/
@@ -6024,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
@@ -6045,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);
@@ -6097,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);
@@ -6170,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 ]
@@ -6179,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
@@ -6187,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
@@ -6202,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);
@@ -6221,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 ]
@@ -6231,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]
@@ -6239,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
@@ -6270,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;
}
@@ -6302,120 +6757,120 @@ ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE
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);
@@ -6434,7 +6889,7 @@ 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 (NIL_P(n)) return DBL2NUM(HUGE_VAL);
@@ -6454,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 }
@@ -6472,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)
@@ -6497,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.
@@ -6535,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;
+ }
}
}
@@ -6573,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;
}
@@ -6591,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;
}
@@ -6630,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]
@@ -6651,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]
@@ -6675,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
@@ -6692,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;
}
@@ -6726,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);
}
}
@@ -6760,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
@@ -6799,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;
}
@@ -6841,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);
}
}
@@ -6864,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);
}
@@ -6886,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]
@@ -6909,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 # => [[]]
@@ -6926,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)
@@ -6937,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;
}
@@ -6967,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);
}
}
@@ -6989,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);
}
@@ -7008,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]
@@ -7028,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 # => [[]]
@@ -7045,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
@@ -7056,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;
}
@@ -7088,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]
@@ -7108,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]
@@ -7121,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 */
@@ -7156,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)) {
+ 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);
+ rb_yield(subarray);
if (!FL_TEST(t0, RARRAY_SHARED_ROOT_FLAG)) {
- rb_raise(rb_eRuntimeError, "product reentered");
- }
- else {
+ 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]++;
- }
+ }
+ }
+ 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;
@@ -7228,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
@@ -7240,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);
}
@@ -7256,13 +7773,16 @@ 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:
+ *
* 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
@@ -7272,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));
}
@@ -7286,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
@@ -7298,7 +7820,7 @@ 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));
@@ -7317,11 +7839,14 @@ 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:
+ *
* 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
@@ -7331,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));
}
@@ -7346,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
@@ -7377,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) {
@@ -7387,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;
}
@@ -7404,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
@@ -7461,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
@@ -7518,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
@@ -7525,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
@@ -7589,11 +8126,13 @@ rb_ary_one_p(int argc, VALUE *argv, VALUE ary)
* 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
@@ -7611,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) {
@@ -7626,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
@@ -7683,7 +8229,7 @@ rb_ary_sum(int argc, VALUE *argv, VALUE ary)
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);
@@ -7770,77 +8316,123 @@ 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.
*
- * == Creating Arrays
- *
- * You can create an \Array object explicitly with:
- *
- * - An {array literal}[rdoc-ref:syntax/literals.rdoc@Array+Literals].
- *
- * You can convert certain objects to Arrays with:
- *
- * - \Method #Array.
- *
- * An \Array can contain different types of objects. For
- * example, the array below contains an Integer, a String and a Float:
- *
- * ary = [1, "two", 3.0] #=> [1, "two", 3.0]
+ * 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].
*
- * An array can also be created by calling Array.new with zero, one
- * (the initial size of the \Array) or two arguments (the initial size and a
- * default object).
*
- * ary = Array.new #=> []
- * Array.new(3) #=> [nil, nil, nil]
- * Array.new(3, true) #=> [true, true, true]
- *
- * 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.
- *
- * 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(4) {Hash.new} #=> [{}, {}, {}, {}]
- * Array.new(4) {|i| i.to_s } #=> ["0", "1", "2", "3"]
- *
- * This is also a quick way to build up multi-dimensional arrays:
- *
- * empty_table = Array.new(3) {Array.new(3)}
- * #=> [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
+ * == Creating Arrays
*
- * 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.
+ * You can create an \Array object explicitly with:
*
- * Array({:a => "a", :b => "b"}) #=> [[:a, "a"], [:b, "b"]]
+ * - 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]:
+ *
+ * %i[foo bar baz] # => [:foo, :bar, :baz]
+ * %i[1 % *] # => [:"1", :%, :*]
+ *
+ * - \Method Kernel#Array:
+ *
+ * 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"]]
+ *
+ * - \Method Array.new:
+ *
+ * Array.new # => []
+ * Array.new(3) # => [nil, nil, nil]
+ * Array.new(4) {Hash.new} # => [{}, {}, {}, {}]
+ * Array.new(3, true) # => [true, true, true]
+ *
+ * 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+.
+ *
+ * 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:
+ *
+ * Array.new(4) {|i| i.to_s } # => ["0", "1", "2", "3"]
+ *
+ * Here is a way to create a multi-dimensional array:
+ *
+ * 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
*
@@ -8056,163 +8648,165 @@ rb_ary_deconstruct(VALUE ary)
*
* === 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
-
- * #<=>:: Returns -1, 0, or 1 as +self+ is less than, equal to, or greater than a given
- * object.
- * #==:: Returns whether each element in +self+ is <tt>==</tt> to the corresponding element
- * in a given object.
- * #eql?:: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding
- * element in a given object.
+ *
+ * - #<=>: Returns -1, 0, or 1 * as +self+ is less than, equal to, or
+ * greater than a given object.
+ * - #==: Returns whether each element in +self+ is <tt>==</tt> to the corresponding element
+ * in a given object.
+ * - #eql?: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding
+ * element in a given object.
* === Methods for Fetching
*
* These methods do not modify +self+.
*
- * #[]:: Returns one or more elements.
- * #fetch:: Returns the element at a given offset.
- * #first:: Returns one or more leading elements.
- * #last:: Returns one or more trailing elements.
- * #max:: Returns one or more maximum-valued elements,
- * as determined by <tt><=></tt> or a given block.
- * #min:: Returns one or more minimum-valued elements,
- * as determined by <tt><=></tt> or a given block.
- * #minmax:: Returns the minimum-valued and maximum-valued elements,
- * as determined by <tt><=></tt> or a given block.
- * #assoc:: Returns the first element that is an array
- * whose first element <tt>==</tt> a given object.
- * #rassoc:: Returns the first element that is an array
- * whose second element <tt>==</tt> a given object.
- * #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
*
- * #&:: 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.
- * #|:: 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 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
@@ -8222,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/ast.c b/ast.c
index 0515689a29..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 keep_script_lines);
-static VALUE rb_ast_parse_file(VALUE path, VALUE keep_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 keep_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, keep_script_lines);
+ return rb_ast_parse_str(str, keep_script_lines, error_tolerant, keep_tokens);
}
static VALUE
-rb_ast_parse_str(VALUE str, VALUE keep_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(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 keep_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, keep_script_lines);
+ return rb_ast_parse_file(path, keep_script_lines, error_tolerant, keep_tokens);
}
static VALUE
-rb_ast_parse_file(VALUE path, VALUE keep_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;
@@ -120,6 +122,8 @@ rb_ast_parse_file(VALUE path, VALUE keep_script_lines)
rb_funcall(f, rb_intern("set_encoding"), 2, rb_enc_from_encoding(enc), rb_str_new_cstr("-"));
VALUE vparser = ast_parse_new();
if (RTEST(keep_script_lines)) rb_parser_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 keep_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(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,7 +199,24 @@ script_lines(VALUE path)
}
static VALUE
-ast_s_of(rb_execution_context_t *ec, VALUE module, VALUE body, VALUE keep_script_lines)
+node_id_for_backtrace_location(rb_execution_context_t *ec, VALUE module, VALUE location)
+{
+ 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;
@@ -215,14 +238,14 @@ ast_s_of(rb_execution_context_t *ec, VALUE module, VALUE body, VALUE keep_script
iseq = rb_method_iseq(body);
}
if (iseq) {
- node_id = iseq->body->location.node_id;
+ node_id = ISEQ_BODY(iseq)->location.node_id;
}
}
if (!iseq) {
return Qnil;
}
- lines = iseq->body->variable.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;
@@ -232,13 +255,13 @@ ast_s_of(rb_execution_context_t *ec, VALUE module, VALUE body, VALUE keep_script
}
if (!NIL_P(lines) || !NIL_P(lines = script_lines(path))) {
- node = rb_ast_parse_array(lines, keep_script_lines);
+ 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);
+ node = rb_ast_parse_str(rb_e_script, keep_script_lines, error_tolerant, keep_tokens);
}
else {
- node = rb_ast_parse_file(path, keep_script_lines);
+ node = rb_ast_parse_file(path, keep_script_lines, error_tolerant, keep_tokens);
}
return node_find(node, node_id);
@@ -645,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;
@@ -699,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 f866bd23e5..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, keep_script_lines: false
- Primitive.ast_s_parse string, keep_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, keep_script_lines: false
- Primitive.ast_s_parse_file pathname, keep_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, keep_script_lines: false
- Primitive.ast_s_of body, keep_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/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_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/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
index e375dcf85d..9e1f99d64e 100644
--- a/benchmark/buffer_get.yml
+++ b/benchmark/buffer_get.yml
@@ -1,9 +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:
- - name: buffer.get
- prelude: buffer = IO::Buffer.new(32, IO::Buffer::MAPPED)
- script: buffer.get(:U32, 0)
- loop_count: 20000000
- - name: string.unpack
- prelude: string = "\0" * 32
- script: string.unpack("C")
- loop_count: 20000000
+ 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/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 1d4693e8be..3a58a620de 100644
--- a/benchmark/lib/benchmark_driver/runner/mjit.rb
+++ b/benchmark/lib/benchmark_driver/runner/mjit.rb
@@ -16,7 +16,7 @@ class BenchmarkDriver::Runner::Mjit < BenchmarkDriver::Runner::Ips
job.prelude = "#{job.prelude}\n#{<<~EOS}"
if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
__bmdv_ruby_i = 0
- while __bmdv_ruby_i < 10000 # jit_min_calls
+ while __bmdv_ruby_i < 10000 # MJIT call threshold
#{job.script}
__bmdv_ruby_i += 1
end
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 eac3dfba84..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::MJIT.pause if defined?(RubyVM::MJIT) && RubyVM::MJIT.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::MJIT.pause if defined?(RubyVM::MJIT) && RubyVM::MJIT.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::MJIT.pause if defined?(RubyVM::MJIT) && RubyVM::MJIT.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/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_parse.yml b/benchmark/time_parse.yml
index a6d6948b9c..6060b58bc6 100644
--- a/benchmark/time_parse.yml
+++ b/benchmark/time_parse.yml
@@ -6,3 +6,5 @@ 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_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_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 4ab117b557..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
@@ -99,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) : \
@@ -145,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
@@ -413,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);
}
@@ -431,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);
}
}
@@ -443,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;
}
@@ -971,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;
}
@@ -981,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;
@@ -1344,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++) {
@@ -1365,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;
@@ -1373,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;
}
@@ -1403,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;
@@ -1431,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;
}
@@ -1573,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)
@@ -1591,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 */
@@ -1639,6 +1645,12 @@ 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 *const zds, const size_t zn,
@@ -1656,8 +1668,14 @@ bary_mul_balance_with_mulfunc(BDIGIT *const zds, const size_t zn,
BDIGITS_ZERO(zds, xn);
if (wn < xn) {
- const size_t r = (yn % xn) ? (yn % xn) : xn;
- if ((2 * xn + yn + r) > zn) {
+ /* 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);
}
@@ -1692,7 +1710,7 @@ bary_mul_balance_with_mulfunc(BDIGIT *const zds, const size_t zn,
zds + n, tn,
wds, xn);
}
- n += r;
+ n += r;
}
BDIGITS_ZERO(zds+xn+yn, zn - (xn+yn));
@@ -2084,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);
@@ -2291,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)
{
@@ -2429,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);
@@ -2556,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);
@@ -2580,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;
}
@@ -2668,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);
}
}
@@ -2776,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)
{
@@ -2860,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;
@@ -2935,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);
@@ -2944,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;
@@ -2956,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
@@ -2965,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);
+ }
+ }
}
}
@@ -3077,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;
@@ -3101,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;
}
@@ -3154,7 +3172,7 @@ static VALUE
bignorm(VALUE x)
{
if (RB_BIGNUM_TYPE_P(x)) {
- x = bigfixize(x);
+ x = bigfixize(x);
}
return x;
}
@@ -3176,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
@@ -3196,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;
}
@@ -3362,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;
}
@@ -3682,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 {
@@ -3694,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);
@@ -3748,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;
@@ -3957,7 +3975,7 @@ str2big_karatsuba(
return z;
}
-#ifdef USE_GMP
+#if USE_GMP
static VALUE
str2big_gmp(
int sign,
@@ -4024,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;
}
@@ -4049,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;
@@ -4066,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);
@@ -4149,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);
@@ -4251,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
@@ -4300,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,
@@ -4339,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);
@@ -4381,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);
@@ -4402,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)
{
@@ -4424,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);
@@ -4458,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
@@ -4478,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;
}
@@ -4515,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);
@@ -4533,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;
}
@@ -4569,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);
@@ -4703,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];
@@ -4754,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;
@@ -4771,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;
@@ -4801,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;
}
@@ -4839,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;
@@ -4943,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'");
@@ -4984,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;
@@ -4993,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);
}
@@ -5012,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)
{
@@ -5059,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);
@@ -5068,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'");
@@ -5083,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);
}
@@ -5119,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
@@ -5172,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
@@ -5228,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;
@@ -5264,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;
@@ -5293,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;
@@ -5317,11 +5337,11 @@ rb_big2dbl(VALUE x)
double d = big2dbl(x);
if (isinf(d)) {
- rb_warning("Integer 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;
}
@@ -5418,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);
}
@@ -5456,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 RBOOL(n > 0);
- case big_op_ge: return RBOOL(n >= 0);
- case big_op_lt: return RBOOL(n < 0);
- case big_op_le: return RBOOL(n <= 0);
+ case big_op_gt: return RBOOL(n > 0);
+ case big_op_ge: return RBOOL(n >= 0);
+ case big_op_lt: return RBOOL(n < 0);
+ case big_op_le: return RBOOL(n <= 0);
}
return Qundef;
}
@@ -5523,7 +5543,7 @@ VALUE
rb_big_eq(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
- return RBOOL(bignorm(x) == y);
+ return RBOOL(bignorm(x) == y);
}
else if (RB_BIGNUM_TYPE_P(y)) {
}
@@ -5531,7 +5551,7 @@ 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;
@@ -5638,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);
@@ -5653,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;
@@ -5671,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++) {
@@ -5687,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++) {
@@ -5701,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);
@@ -5744,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;
@@ -5763,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;
@@ -5798,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);
@@ -5823,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, '+');
}
}
@@ -5852,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, '-');
}
}
@@ -5930,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));
@@ -5965,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);
@@ -6044,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;
}
}
@@ -6059,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);
@@ -6102,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);
@@ -6118,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);
@@ -6134,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);
@@ -6148,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;
}
@@ -6174,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);
@@ -6210,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));
@@ -6247,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));
@@ -6269,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));
}
@@ -6313,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
@@ -6343,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);
@@ -6366,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) {
@@ -6393,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);
@@ -6485,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) {
@@ -6512,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);
@@ -6579,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) {
@@ -6603,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);
@@ -6622,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);
}
}
@@ -6652,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;
@@ -6661,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);
}
}
@@ -6684,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;
@@ -6760,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;
}
@@ -6835,7 +6855,7 @@ 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,35 +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);
- }
+ 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)
{
@@ -6966,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;
@@ -7142,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,7 +7192,7 @@ Init_Bignum(void)
{
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 3d42390254..f9b3e919b8 100755
--- a/bootstraptest/runner.rb
+++ b/bootstraptest/runner.rb
@@ -61,7 +61,7 @@ if !Dir.respond_to?(:mktmpdir)
end
# Configuration
-BT = Struct.new(:ruby,
+bt = Struct.new(:ruby,
:verbose,
:color,
:tty,
@@ -73,9 +73,78 @@ BT = Struct.new(:ruby,
:failed,
:reset,
:columns,
+ :window_width,
:width,
+ :indent,
:platform,
- ).new
+ )
+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
@@ -87,7 +156,7 @@ def main
BT.color = nil
BT.tty = nil
BT.quiet = false
- BT.wn = 1
+ # BT.wn = 1
dir = nil
quiet = false
tests = nil
@@ -122,12 +191,7 @@ def main
BT.quiet = true
true
when /\A-j(\d+)?/
- wn = $1.to_i
- if wn <= 0
- require 'etc'
- wn = [Etc.nprocessors / 2, 1].max
- end
- BT.wn = wn
+ BT.wn = $1.to_i
true
when /\A(-v|--v(erbose))\z/
BT.verbose = true
@@ -154,8 +218,7 @@ 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?
@@ -164,6 +227,7 @@ End
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
@@ -241,7 +305,7 @@ def concurrent_exec_test
end
end
- $stderr.print ' ' unless BT.quiet
+ BT.indent = 1
aq.close
i = 1
term_wn = 0
@@ -253,7 +317,7 @@ def concurrent_exec_test
when BT.tty
$stderr.print "#{BT.progress_bs}#{BT.progress[(i+=1) % BT.progress.size]}"
else
- $stderr.print '.'
+ BT.putc '.'
end
else
term_wn += 1
@@ -275,7 +339,7 @@ def exec_test(pathes)
# execute tests
if BT.wn > 1
- concurrent_exec_test if BT.wn > 1
+ concurrent_exec_test
else
prev_basename = nil
Assertion.all.each do |basename, assertions|
@@ -428,7 +492,7 @@ class Assertion < Struct.new(:src, :path, :lineno, :proc)
elsif BT.verbose
$stderr.printf(". %.3f\n", t)
else
- $stderr.print '.'
+ BT.putc '.'
end
else
$stderr.print "#{BT.failed}F"
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_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_io.rb b/bootstraptest/test_io.rb
index 73deca8383..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,6 +31,7 @@ assert_finish 10, %q{
end
}, '[ruby-dev:32566]'
+/freebsd/ =~ RUBY_PLATFORM or
assert_finish 5, %q{
r, w = IO.pipe
Thread.new {
@@ -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_ractor.rb b/bootstraptest/test_ractor.rb
index b29db7ab0e..67e66b03ee 100644
--- a/bootstraptest/test_ractor.rb
+++ b/bootstraptest/test_ractor.rb
@@ -283,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{
@@ -501,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{
@@ -1472,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
@@ -1481,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}")
}
}
@@ -1579,4 +1580,49 @@ assert_equal "ok", %q{
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_yjit.rb b/bootstraptest/test_yjit.rb
index d124d180d1..5c655b8f25 100644
--- a/bootstraptest/test_yjit.rb
+++ b/bootstraptest/test_yjit.rb
@@ -1,32 +1,51 @@
-assert_equal '2022', %q{
- def contrivance(hash, key)
- # Expect this to compile to an `opt_aref`.
- hash[key]
+# 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)
- # The [] call above tracks that the `hash` local has a VALUE that
- # is a heap pointer and the guard for the Kernel#itself call below
- # doesn't check that it's a heap pointer VALUE.
- #
- # As you can see from the crash, the call to rb_hash_aref() can set the
- # `hash` local, making eliding the heap object guard unsound.
- hash.itself
+ 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
+}
- # This is similar to ->(recv, mid) { send(recv, mid).local_variable_set(...) }.
- # By composing we avoid creating new Ruby frames and so sending :binding
- # captures the environment of the frame that does the missing key lookup.
- # We use it to capture the environment inside of `contrivance`.
- cap_then_set =
- Kernel.instance_method(:send).method(:bind_call).to_proc >>
- ->(binding) { binding.local_variable_set(:hash, 2022) }
- special_missing = Hash.new(&cap_then_set)
+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
- # Make YJIT speculate that it's a hash and generate code
- # that calls rb_hash_aref().
- contrivance({}, :warmup)
- contrivance({}, :warmup)
+ # +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
- contrivance(special_missing, :binding)
+ local_setting_cmp(Object.new)
+ local_setting_cmp(Object.new)
}
assert_equal '18374962167983112447', %q{
@@ -45,7 +64,7 @@ assert_equal '18374962167983112447', %q{
}
assert_normal_exit %q{
- # regression test for a leak caught by an asert on --yjit-call-threshold=2
+ # regression test for a leak caught by an assert on --yjit-call-threshold=2
Foo = 1
eval("def foo = [#{(['Foo,']*256).join}]")
@@ -56,6 +75,29 @@ assert_normal_exit %q{
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")
@@ -209,6 +251,8 @@ assert_equal 'string', %q{
# Check that exceptions work when getting global variable
assert_equal 'rescued', %q{
+ Warning[:deprecated] = true
+
module Warning
def warn(message)
raise
@@ -817,7 +861,7 @@ assert_equal "good", %q{
foo
begin
- GC.verify_compaction_references(double_heap: true, toward: :empty)
+ GC.verify_compaction_references(expand_heap: true, toward: :empty)
rescue NotImplementedError
# in case compaction isn't supported
end
@@ -1129,6 +1173,38 @@ assert_equal '42', %q{
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
@@ -1235,6 +1311,19 @@ assert_equal '[1, 2, 42]', %q{
[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)
@@ -1368,6 +1457,46 @@ assert_equal 'foo123', %q{
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
@@ -1384,6 +1513,149 @@ assert_equal 'foo', %q{
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{
@@ -1965,7 +2237,7 @@ assert_equal '[[:c_return, :String, :string_alias, "events_to_str"]]', %q{
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{
@@ -2047,7 +2319,7 @@ assert_equal '[[:c_call, :itself]]', %q{
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{
@@ -2062,6 +2334,26 @@ assert_equal '[[:c_return, :itself, main]]', %q{
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
@@ -2088,7 +2380,6 @@ assert_equal '[:itself]', %q{
itself
end
-
tracing_ractor = Ractor.new do
# 1: start tracing
events = []
@@ -2717,11 +3008,20 @@ assert_equal 'new', %q{
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
@@ -2837,3 +3137,394 @@ assert_equal '', %q{
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_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 96339afdb5..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,28 +33,65 @@ 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);
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 9988b080d9..cf0b7b821f 100644
--- a/class.c
+++ b/class.c
@@ -64,7 +64,7 @@ push_subclass_entry_to_list(VALUE super, VALUE klass)
void
rb_class_subclass_add(VALUE super, VALUE klass)
{
- if (super && super != Qundef) {
+ if (super && !UNDEF_P(super)) {
rb_subclass_entry_t *entry = push_subclass_entry_to_list(super, klass);
RCLASS_SUBCLASS_ENTRY(klass) = entry;
}
@@ -106,7 +106,7 @@ rb_class_remove_from_super_subclasses(VALUE klass)
next->prev = prev;
}
- xfree(entry);
+ xfree(entry);
}
RCLASS_SUBCLASS_ENTRY(klass) = NULL;
@@ -123,11 +123,11 @@ rb_class_remove_from_module_subclasses(VALUE klass)
if (prev) {
prev->next = next;
}
- if (next) {
+ if (next) {
next->prev = prev;
- }
+ }
- xfree(entry);
+ xfree(entry);
}
RCLASS_MODULE_SUBCLASS_ENTRY(klass) = NULL;
@@ -148,11 +148,11 @@ rb_class_foreach_subclass(VALUE klass, void (*f)(VALUE, VALUE), VALUE arg)
/* 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;
+ 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);
+ f(curklass, arg);
}
}
@@ -197,7 +197,7 @@ class_alloc(VALUE flags, VALUE klass)
{
size_t alloc_size = sizeof(struct RClass);
-#if USE_RVARGC
+#if RCLASS_EXT_EMBEDDED
alloc_size += sizeof(rb_classext_t);
#endif
@@ -206,17 +206,13 @@ class_alloc(VALUE flags, VALUE klass)
if (RGENGC_WB_PROTECTED_CLASS) flags |= FL_WB_PROTECTED;
RVARGC_NEWOBJ_OF(obj, struct RClass, klass, flags, alloc_size);
-#if USE_RVARGC
+#if RCLASS_EXT_EMBEDDED
memset(RCLASS_EXT(obj), 0, sizeof(rb_classext_t));
-# if SIZEOF_SERIAL_T != SIZEOF_VALUE
- RCLASS(obj)->class_serial_ptr = ZALLOC(rb_serial_t);
-# endif
#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;
@@ -226,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;
@@ -282,7 +277,7 @@ rb_class_update_superclasses(VALUE klass)
VALUE super = RCLASS_SUPER(klass);
if (!RB_TYPE_P(klass, T_CLASS)) return;
- if (super == Qundef) return;
+ if (UNDEF_P(super)) return;
// If the superclass array is already built
if (RCLASS_SUPERCLASSES(klass))
@@ -316,13 +311,13 @@ 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");
}
}
@@ -331,7 +326,13 @@ 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
@@ -344,12 +345,12 @@ 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));
}
}
@@ -393,45 +394,74 @@ 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);
}
}
@@ -493,11 +523,11 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
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) {
@@ -507,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;
@@ -526,7 +556,6 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
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);
@@ -567,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;
@@ -593,49 +624,47 @@ 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(METACLASS_OF(clone), clone);
}
- FL_SET(clone, FL_SINGLETON);
+ FL_SET(clone, FL_SINGLETON);
- return clone;
+ return clone;
}
}
@@ -643,7 +672,7 @@ 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);
}
}
@@ -664,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));
}
/*!
@@ -706,13 +735,13 @@ 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);
@@ -853,10 +882,10 @@ 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);
}
}
@@ -898,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);
@@ -929,42 +958,47 @@ rb_define_class_under(VALUE outer, const char *name, VALUE super)
}
VALUE
-rb_define_class_id_under(VALUE outer, ID id, VALUE super)
+rb_define_class_id_under_no_pin(VALUE outer, ID id, VALUE super)
{
VALUE klass;
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_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);
@@ -1008,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);
@@ -1036,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);
@@ -1063,16 +1097,13 @@ rb_include_class_new(VALUE module, VALUE super)
RCLASS_SET_ORIGIN(klass, klass);
if (BUILTIN_TYPE(module) == T_ICLASS) {
- module = METACLASS_OF(module);
+ 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);
@@ -1091,7 +1122,7 @@ ensure_includable(VALUE klass, VALUE module)
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");
}
}
@@ -1104,7 +1135,7 @@ 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);
@@ -1114,8 +1145,8 @@ rb_include_module(VALUE klass, VALUE module)
iclass = iclass->next;
}
- int do_include = 1;
while (iclass) {
+ int do_include = 1;
VALUE check_class = iclass->klass;
/* During lazy sweeping, iclass->klass could be a dead object that
* has not yet been swept. */
@@ -1169,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;
@@ -1183,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;
@@ -1234,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);
}
@@ -1248,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;
}
- if (add_subclass) {
- VALUE m = module;
- if (BUILTIN_TYPE(m) == T_ICLASS) m = METACLASS_OF(m);
- rb_module_add_to_subclasses_list(m, iclass);
- }
+ VALUE m = module;
+ if (BUILTIN_TYPE(m) == T_ICLASS) m = METACLASS_OF(m);
+ rb_module_add_to_subclasses_list(m, iclass);
- if (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;
}
@@ -1292,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;
}
}
@@ -1329,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;
@@ -1356,7 +1391,7 @@ 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);
@@ -1373,17 +1408,18 @@ rb_prepend_module(VALUE klass, VALUE module)
/* During lazy sweeping, iclass->klass could be a dead object that
* has not yet been swept. */
if (!rb_objspace_garbage_object_p(iclass->klass)) {
- if (klass_had_no_origin && klass_origin_m_tbl == RCLASS_M_TBL(iclass->klass)) {
+ 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(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);
+ 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(iclass->klass, iclass->klass, module, FALSE);
+ include_modules_at(subclass, subclass, module, FALSE);
}
iclass = iclass->next;
@@ -1422,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 = METACLASS_OF(p);
- 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;
}
@@ -1457,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 (METACLASS_OF(p) == mod2) return Qtrue;
- }
+ if (METACLASS_OF(p) == mod2) return Qtrue;
+ }
}
return Qfalse;
}
@@ -1486,19 +1522,19 @@ rb_mod_ancestors(VALUE mod)
{
VALUE p, ary = rb_ary_new();
VALUE refined_class = Qnil;
- if (FL_TEST(mod, RMODULE_IS_REFINEMENT)) {
+ 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, METACLASS_OF(p));
- }
+ 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;
}
@@ -1572,6 +1608,27 @@ class_descendants(VALUE klass, bool immediate_only)
* 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
@@ -1580,6 +1637,33 @@ 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)
{
@@ -1592,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;
}
@@ -1604,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;
}
@@ -1627,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;
@@ -1640,20 +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);
- RUBY_ASSERT(type != METHOD_VISI_UNDEF);
- }
- 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;
}
@@ -1694,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);
@@ -1735,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
@@ -1798,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
@@ -1831,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);
}
@@ -1931,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);
@@ -2010,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);
}
}
@@ -2058,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)) {
@@ -2077,9 +2191,7 @@ singleton_class_of(VALUE obj)
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));
@@ -2092,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);
+ }
}
}
@@ -2113,7 +2225,7 @@ 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 = METACLASS_OF(obj);
if (!FL_TEST(klass, FL_SINGLETON)) return Qnil;
@@ -2188,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);
@@ -2213,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));
@@ -2237,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];
@@ -2264,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++) {
@@ -2324,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);
}
}
@@ -2383,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) {
@@ -2423,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) {
diff --git a/common.mk b/common.mk
index ae62f38468..126053c9c8 100644
--- a/common.mk
+++ b/common.mk
@@ -18,8 +18,10 @@ mflags = $(MFLAGS)
gnumake_recursive =
enable_shared = $(ENABLE_SHARED:no=)
-UNICODE_VERSION = 14.0.0
-UNICODE_EMOJI_VERSION = 14.0
+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
@@ -82,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) \
@@ -113,7 +115,7 @@ COMMONOBJS = array.$(OBJEXT) \
math.$(OBJEXT) \
memory_view.$(OBJEXT) \
mjit.$(OBJEXT) \
- mjit_compile.$(OBJEXT) \
+ mjit_c.$(OBJEXT) \
node.$(OBJEXT) \
numeric.$(OBJEXT) \
object.$(OBJEXT) \
@@ -134,6 +136,7 @@ COMMONOBJS = array.$(OBJEXT) \
regsyntax.$(OBJEXT) \
ruby.$(OBJEXT) \
scheduler.$(OBJEXT) \
+ shape.$(OBJEXT) \
signal.$(OBJEXT) \
sprintf.$(OBJEXT) \
st.$(OBJEXT) \
@@ -153,7 +156,7 @@ COMMONOBJS = array.$(OBJEXT) \
vm_dump.$(OBJEXT) \
vm_sync.$(OBJEXT) \
vm_trace.$(OBJEXT) \
- yjit.$(OBJEXT) \
+ $(YJIT_OBJ) \
$(COROUTINE_OBJ) \
$(DTRACE_OBJ) \
$(BUILTIN_ENCOBJS) \
@@ -195,6 +198,7 @@ INSTRUBY_ARGS = $(SCRIPT_ARGS) \
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/
@@ -216,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
@@ -229,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.
@@ -270,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)
@@ -610,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)
@@ -687,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
@@ -741,7 +766,7 @@ 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)" && \
@@ -755,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)
@@ -812,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
@@ -839,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?}' \
@@ -857,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
@@ -867,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)
@@ -885,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)
@@ -909,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
@@ -923,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"' \
@@ -1041,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 \
@@ -1054,13 +1087,17 @@ BUILTIN_RB_SRCS = \
$(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 \
@@ -1070,7 +1107,7 @@ 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
@@ -1126,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
@@ -1182,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)
+$(srcdir)/revision.h$(no_baseruby:no=~disabled~): $(REVISION_H)
-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)" > $@
+$(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 > $@
-$(REVISION_H): revision.tmp
- $(Q)$(IFCHANGE) "--timestamp=$@" "$(srcdir)/revision.h" revision.tmp
-
-$(srcdir)/ext/ripper/ripper.c: $(srcdir)/ext/ripper/tools/preproc.rb $(srcdir)/parse.y id.h $(srcdir)/ext/ripper/depend
+$(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) $(CHDIR) $(@D) && \
- sed -e 's/{\$$([^(){}]*)[^{}]*}//g' -e /AUTOGENERATED/q depend | \
+ $(CAT_DEPEND) depend | \
$(exec) $(MAKE) -f - $(mflags) \
- Q=$(Q) ECHO=$(ECHO) RM="$(RM1)" BISON=$(YACC) top_srcdir=../.. srcdir=. 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
@@ -1217,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)
@@ -1225,25 +1256,25 @@ $(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
@@ -1252,7 +1283,7 @@ runruby: $(PROGRAM) PHONY
runirb: $(PROGRAM) PHONY
RUBY_ON_BUG='gdb -x $(srcdir)/.gdbinit -p' $(RUNRUBY) $(RUNOPT0) -r irb -e 'IRB.start("make runirb")' $(RUNOPT)
-parse: fake miniruby$(EXEEXT) PHONY
+parse: yes-fake miniruby$(EXEEXT) PHONY
$(BTESTRUBY) --dump=parsetree_with_comment,insns $(TESTRUN_SCRIPT)
bisect: PHONY
@@ -1309,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)
@@ -1322,10 +1353,15 @@ up::
yes::
no::
+after-update:: common-srcs
after-update:: $(REVISION_H)
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
@@ -1340,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 \
@@ -1355,24 +1392,32 @@ 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
@@ -1380,7 +1425,7 @@ yes-test-bundled-gems-precheck: main
no-test-bundled-gems-precheck:
test-bundled-gems-fetch: yes-test-bundled-gems-fetch
-yes-test-bundled-gems-fetch: $(PREP)
+yes-test-bundled-gems-fetch:
$(ACTIONS_GROUP)
$(Q) $(BASERUBY) -C $(srcdir)/gems ../tool/fetch-bundled_gems.rb src bundled_gems
$(ACTIONS_ENDGROUP)
@@ -1392,7 +1437,7 @@ 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" "test-unit-rr"
+ --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
@@ -1405,11 +1450,34 @@ 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
@@ -1426,14 +1494,18 @@ 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 \
@@ -1445,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)
@@ -1486,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): \
@@ -1548,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 \
@@ -1580,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)
@@ -1652,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
@@ -1744,6 +1832,7 @@ addr2line.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
addr2line.$(OBJEXT): {$(VPATH)}missing.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
@@ -1759,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
@@ -1775,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
@@ -1937,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
@@ -1948,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
@@ -1955,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
@@ -1972,10 +2066,11 @@ ast.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
ast.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
ast.$(OBJEXT): {$(VPATH)}builtin.h
ast.$(OBJEXT): {$(VPATH)}config.h
-ast.$(OBJEXT): {$(VPATH)}darray.h
+ast.$(OBJEXT): {$(VPATH)}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
@@ -2135,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
@@ -2318,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
@@ -2328,11 +2425,13 @@ builtin.$(OBJEXT): $(CCAN_DIR)/list/list.h
builtin.$(OBJEXT): $(CCAN_DIR)/str/str.h
builtin.$(OBJEXT): $(hdrdir)/ruby/ruby.h
builtin.$(OBJEXT): $(top_srcdir)/internal/array.h
+builtin.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
builtin.$(OBJEXT): $(top_srcdir)/internal/compilers.h
builtin.$(OBJEXT): $(top_srcdir)/internal/gc.h
builtin.$(OBJEXT): $(top_srcdir)/internal/imemo.h
builtin.$(OBJEXT): $(top_srcdir)/internal/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
@@ -2350,9 +2449,10 @@ builtin.$(OBJEXT): {$(VPATH)}builtin.c
builtin.$(OBJEXT): {$(VPATH)}builtin.h
builtin.$(OBJEXT): {$(VPATH)}builtin_binary.inc
builtin.$(OBJEXT): {$(VPATH)}config.h
-builtin.$(OBJEXT): {$(VPATH)}darray.h
+builtin.$(OBJEXT): {$(VPATH)}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
@@ -2501,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
@@ -2513,6 +2614,7 @@ class.$(OBJEXT): $(CCAN_DIR)/list/list.h
class.$(OBJEXT): $(CCAN_DIR)/str/str.h
class.$(OBJEXT): $(hdrdir)/ruby/ruby.h
class.$(OBJEXT): $(top_srcdir)/internal/array.h
+class.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
class.$(OBJEXT): $(top_srcdir)/internal/class.h
class.$(OBJEXT): $(top_srcdir)/internal/compilers.h
class.$(OBJEXT): $(top_srcdir)/internal/eval.h
@@ -2540,7 +2642,6 @@ class.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
class.$(OBJEXT): {$(VPATH)}class.c
class.$(OBJEXT): {$(VPATH)}config.h
class.$(OBJEXT): {$(VPATH)}constant.h
-class.$(OBJEXT): {$(VPATH)}darray.h
class.$(OBJEXT): {$(VPATH)}debug_counter.h
class.$(OBJEXT): {$(VPATH)}defines.h
class.$(OBJEXT): {$(VPATH)}encoding.h
@@ -2704,6 +2805,7 @@ 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
@@ -2711,6 +2813,7 @@ class.$(OBJEXT): {$(VPATH)}thread_native.h
class.$(OBJEXT): {$(VPATH)}vm_core.h
class.$(OBJEXT): {$(VPATH)}vm_opts.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
@@ -2895,6 +2998,7 @@ compile.$(OBJEXT): $(CCAN_DIR)/list/list.h
compile.$(OBJEXT): $(CCAN_DIR)/str/str.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
@@ -2934,7 +3038,6 @@ compile.$(OBJEXT): {$(VPATH)}builtin.h
compile.$(OBJEXT): {$(VPATH)}compile.c
compile.$(OBJEXT): {$(VPATH)}config.h
compile.$(OBJEXT): {$(VPATH)}constant.h
-compile.$(OBJEXT): {$(VPATH)}darray.h
compile.$(OBJEXT): {$(VPATH)}debug_counter.h
compile.$(OBJEXT): {$(VPATH)}defines.h
compile.$(OBJEXT): {$(VPATH)}encindex.h
@@ -3108,6 +3211,7 @@ 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
@@ -3117,8 +3221,13 @@ 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): $(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
@@ -3126,15 +3235,18 @@ complex.$(OBJEXT): $(top_srcdir)/internal/compilers.h
complex.$(OBJEXT): $(top_srcdir)/internal/complex.h
complex.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
complex.$(OBJEXT): $(top_srcdir)/internal/gc.h
+complex.$(OBJEXT): $(top_srcdir)/internal/imemo.h
complex.$(OBJEXT): $(top_srcdir)/internal/math.h
complex.$(OBJEXT): $(top_srcdir)/internal/numeric.h
complex.$(OBJEXT): $(top_srcdir)/internal/object.h
complex.$(OBJEXT): $(top_srcdir)/internal/rational.h
complex.$(OBJEXT): $(top_srcdir)/internal/serial.h
complex.$(OBJEXT): $(top_srcdir)/internal/static_assert.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
@@ -3146,6 +3258,7 @@ 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)}id.h
complex.$(OBJEXT): {$(VPATH)}id_table.h
@@ -3291,10 +3404,18 @@ complex.$(OBJEXT): {$(VPATH)}internal/value_type.h
complex.$(OBJEXT): {$(VPATH)}internal/variable.h
complex.$(OBJEXT): {$(VPATH)}internal/warning_push.h
complex.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+complex.$(OBJEXT): {$(VPATH)}method.h
complex.$(OBJEXT): {$(VPATH)}missing.h
+complex.$(OBJEXT): {$(VPATH)}node.h
complex.$(OBJEXT): {$(VPATH)}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
@@ -3302,13 +3423,18 @@ cont.$(OBJEXT): $(CCAN_DIR)/str/str.h
cont.$(OBJEXT): $(hdrdir)/ruby.h
cont.$(OBJEXT): $(hdrdir)/ruby/ruby.h
cont.$(OBJEXT): $(top_srcdir)/internal/array.h
+cont.$(OBJEXT): $(top_srcdir)/internal/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)
@@ -3324,10 +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)}darray.h
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
@@ -3405,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
@@ -3475,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
@@ -3490,6 +3630,7 @@ 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
@@ -3497,12 +3638,15 @@ debug.$(OBJEXT): $(CCAN_DIR)/list/list.h
debug.$(OBJEXT): $(CCAN_DIR)/str/str.h
debug.$(OBJEXT): $(hdrdir)/ruby/ruby.h
debug.$(OBJEXT): $(top_srcdir)/internal/array.h
+debug.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+debug.$(OBJEXT): $(top_srcdir)/internal/class.h
debug.$(OBJEXT): $(top_srcdir)/internal/compilers.h
debug.$(OBJEXT): $(top_srcdir)/internal/gc.h
debug.$(OBJEXT): $(top_srcdir)/internal/imemo.h
debug.$(OBJEXT): $(top_srcdir)/internal/serial.h
debug.$(OBJEXT): $(top_srcdir)/internal/signal.h
debug.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+debug.$(OBJEXT): $(top_srcdir)/internal/variable.h
debug.$(OBJEXT): $(top_srcdir)/internal/vm.h
debug.$(OBJEXT): $(top_srcdir)/internal/warnings.h
debug.$(OBJEXT): {$(VPATH)}assert.h
@@ -3517,7 +3661,7 @@ debug.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
debug.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
debug.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
debug.$(OBJEXT): {$(VPATH)}config.h
-debug.$(OBJEXT): {$(VPATH)}darray.h
+debug.$(OBJEXT): {$(VPATH)}constant.h
debug.$(OBJEXT): {$(VPATH)}debug.c
debug.$(OBJEXT): {$(VPATH)}debug_counter.h
debug.$(OBJEXT): {$(VPATH)}defines.h
@@ -3688,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
@@ -3872,6 +4017,7 @@ 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
@@ -3886,6 +4032,7 @@ 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
@@ -4048,6 +4195,7 @@ 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
@@ -5365,6 +5513,7 @@ 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
@@ -5372,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
@@ -5385,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
@@ -5547,6 +5698,7 @@ 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
@@ -5554,6 +5706,7 @@ encoding.$(OBJEXT): {$(VPATH)}vm_debug.h
encoding.$(OBJEXT): {$(VPATH)}vm_sync.h
enum.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enum.$(OBJEXT): $(top_srcdir)/internal/array.h
+enum.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
enum.$(OBJEXT): $(top_srcdir)/internal/bignum.h
enum.$(OBJEXT): $(top_srcdir)/internal/bits.h
enum.$(OBJEXT): $(top_srcdir)/internal/class.h
@@ -5571,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
@@ -5584,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
@@ -5744,14 +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): $(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
@@ -5769,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
@@ -5783,6 +5946,7 @@ 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
@@ -5934,18 +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/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
@@ -5978,7 +6151,6 @@ error.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
error.$(OBJEXT): {$(VPATH)}builtin.h
error.$(OBJEXT): {$(VPATH)}config.h
error.$(OBJEXT): {$(VPATH)}constant.h
-error.$(OBJEXT): {$(VPATH)}darray.h
error.$(OBJEXT): {$(VPATH)}defines.h
error.$(OBJEXT): {$(VPATH)}encoding.h
error.$(OBJEXT): {$(VPATH)}error.c
@@ -6144,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
@@ -6158,8 +6331,10 @@ eval.$(OBJEXT): $(CCAN_DIR)/str/str.h
eval.$(OBJEXT): $(hdrdir)/ruby.h
eval.$(OBJEXT): $(hdrdir)/ruby/ruby.h
eval.$(OBJEXT): $(top_srcdir)/internal/array.h
+eval.$(OBJEXT): $(top_srcdir)/internal/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
@@ -6188,7 +6363,6 @@ eval.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
eval.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
eval.$(OBJEXT): {$(VPATH)}config.h
eval.$(OBJEXT): {$(VPATH)}constant.h
-eval.$(OBJEXT): {$(VPATH)}darray.h
eval.$(OBJEXT): {$(VPATH)}debug_counter.h
eval.$(OBJEXT): {$(VPATH)}defines.h
eval.$(OBJEXT): {$(VPATH)}encoding.h
@@ -6366,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
@@ -6374,7 +6549,6 @@ eval.$(OBJEXT): {$(VPATH)}vm.h
eval.$(OBJEXT): {$(VPATH)}vm_core.h
eval.$(OBJEXT): {$(VPATH)}vm_debug.h
eval.$(OBJEXT): {$(VPATH)}vm_opts.h
-eval.$(OBJEXT): {$(VPATH)}yjit.h
explicit_bzero.$(OBJEXT): {$(VPATH)}config.h
explicit_bzero.$(OBJEXT): {$(VPATH)}explicit_bzero.c
explicit_bzero.$(OBJEXT): {$(VPATH)}internal/attr/format.h
@@ -6407,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
@@ -6420,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
@@ -6582,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
@@ -6593,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
@@ -6634,7 +6812,6 @@ gc.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
gc.$(OBJEXT): {$(VPATH)}builtin.h
gc.$(OBJEXT): {$(VPATH)}config.h
gc.$(OBJEXT): {$(VPATH)}constant.h
-gc.$(OBJEXT): {$(VPATH)}darray.h
gc.$(OBJEXT): {$(VPATH)}debug.h
gc.$(OBJEXT): {$(VPATH)}debug_counter.h
gc.$(OBJEXT): {$(VPATH)}defines.h
@@ -6642,7 +6819,6 @@ gc.$(OBJEXT): {$(VPATH)}encoding.h
gc.$(OBJEXT): {$(VPATH)}eval_intern.h
gc.$(OBJEXT): {$(VPATH)}gc.c
gc.$(OBJEXT): {$(VPATH)}gc.h
-gc.$(OBJEXT): {$(VPATH)}gc.rb
gc.$(OBJEXT): {$(VPATH)}gc.rbinc
gc.$(OBJEXT): {$(VPATH)}id.h
gc.$(OBJEXT): {$(VPATH)}id_table.h
@@ -6799,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
@@ -6815,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
@@ -6828,7 +7006,6 @@ gc.$(OBJEXT): {$(VPATH)}vm_core.h
gc.$(OBJEXT): {$(VPATH)}vm_debug.h
gc.$(OBJEXT): {$(VPATH)}vm_opts.h
gc.$(OBJEXT): {$(VPATH)}vm_sync.h
-gc.$(OBJEXT): {$(VPATH)}yjit.h
goruby.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
goruby.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
goruby.$(OBJEXT): $(CCAN_DIR)/list/list.h
@@ -6836,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
@@ -6856,12 +7035,12 @@ goruby.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
goruby.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
goruby.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
goruby.$(OBJEXT): {$(VPATH)}config.h
-goruby.$(OBJEXT): {$(VPATH)}darray.h
+goruby.$(OBJEXT): {$(VPATH)}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
@@ -6901,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
@@ -7011,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
@@ -7018,8 +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): $(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
@@ -7028,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
@@ -7048,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
@@ -7205,20 +7396,28 @@ 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
@@ -7390,6 +7589,7 @@ io.$(OBJEXT): $(CCAN_DIR)/list/list.h
io.$(OBJEXT): $(CCAN_DIR)/str/str.h
io.$(OBJEXT): $(hdrdir)/ruby/ruby.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
@@ -7426,7 +7626,6 @@ io.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
io.$(OBJEXT): {$(VPATH)}builtin.h
io.$(OBJEXT): {$(VPATH)}config.h
io.$(OBJEXT): {$(VPATH)}constant.h
-io.$(OBJEXT): {$(VPATH)}darray.h
io.$(OBJEXT): {$(VPATH)}defines.h
io.$(OBJEXT): {$(VPATH)}dln.h
io.$(OBJEXT): {$(VPATH)}encindex.h
@@ -7597,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
@@ -7606,11 +7806,18 @@ 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
@@ -7791,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
@@ -7824,7 +8032,6 @@ iseq.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
iseq.$(OBJEXT): {$(VPATH)}builtin.h
iseq.$(OBJEXT): {$(VPATH)}config.h
iseq.$(OBJEXT): {$(VPATH)}constant.h
-iseq.$(OBJEXT): {$(VPATH)}darray.h
iseq.$(OBJEXT): {$(VPATH)}debug_counter.h
iseq.$(OBJEXT): {$(VPATH)}defines.h
iseq.$(OBJEXT): {$(VPATH)}encoding.h
@@ -7998,6 +8205,7 @@ 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
@@ -8013,6 +8221,7 @@ load.$(OBJEXT): $(CCAN_DIR)/list/list.h
load.$(OBJEXT): $(CCAN_DIR)/str/str.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
@@ -8210,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
@@ -8708,15 +8918,24 @@ main.$(OBJEXT): {$(VPATH)}missing.h
main.$(OBJEXT): {$(VPATH)}st.h
main.$(OBJEXT): {$(VPATH)}subst.h
main.$(OBJEXT): {$(VPATH)}vm_debug.h
+marshal.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+marshal.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+marshal.$(OBJEXT): $(CCAN_DIR)/list/list.h
+marshal.$(OBJEXT): $(CCAN_DIR)/str/str.h
marshal.$(OBJEXT): $(hdrdir)/ruby/ruby.h
marshal.$(OBJEXT): $(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
@@ -8724,9 +8943,11 @@ 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
@@ -8738,9 +8959,11 @@ 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
@@ -8781,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
@@ -8896,12 +9120,21 @@ 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
+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
@@ -8912,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
@@ -8925,6 +9159,7 @@ 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
@@ -9071,15 +9306,20 @@ 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/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
memory_view.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+memory_view.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
memory_view.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
memory_view.$(OBJEXT): {$(VPATH)}backward/2/limits.h
memory_view.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
@@ -9235,6 +9475,7 @@ 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)}shape.h
memory_view.$(OBJEXT): {$(VPATH)}st.h
memory_view.$(OBJEXT): {$(VPATH)}subst.h
memory_view.$(OBJEXT): {$(VPATH)}util.h
@@ -9245,12 +9486,15 @@ miniinit.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
miniinit.$(OBJEXT): $(CCAN_DIR)/list/list.h
miniinit.$(OBJEXT): $(CCAN_DIR)/str/str.h
miniinit.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+miniinit.$(OBJEXT): $(srcdir)/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
@@ -9268,13 +9512,14 @@ miniinit.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
miniinit.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
miniinit.$(OBJEXT): {$(VPATH)}builtin.h
miniinit.$(OBJEXT): {$(VPATH)}config.h
-miniinit.$(OBJEXT): {$(VPATH)}darray.h
+miniinit.$(OBJEXT): {$(VPATH)}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
@@ -9314,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
@@ -9435,6 +9681,8 @@ 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
@@ -9445,10 +9693,13 @@ 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
@@ -9463,6 +9714,7 @@ 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
@@ -9472,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
@@ -9490,7 +9744,6 @@ mjit.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
mjit.$(OBJEXT): {$(VPATH)}builtin.h
mjit.$(OBJEXT): {$(VPATH)}config.h
mjit.$(OBJEXT): {$(VPATH)}constant.h
-mjit.$(OBJEXT): {$(VPATH)}darray.h
mjit.$(OBJEXT): {$(VPATH)}debug.h
mjit.$(OBJEXT): {$(VPATH)}debug_counter.h
mjit.$(OBJEXT): {$(VPATH)}defines.h
@@ -9658,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
@@ -9677,214 +9934,220 @@ mjit.$(OBJEXT): {$(VPATH)}vm_debug.h
mjit.$(OBJEXT): {$(VPATH)}vm_opts.h
mjit.$(OBJEXT): {$(VPATH)}vm_sync.h
mjit.$(OBJEXT): {$(VPATH)}yjit.h
-mjit_compile.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-mjit_compile.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-mjit_compile.$(OBJEXT): $(CCAN_DIR)/list/list.h
-mjit_compile.$(OBJEXT): $(CCAN_DIR)/str/str.h
-mjit_compile.$(OBJEXT): $(hdrdir)/ruby.h
-mjit_compile.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-mjit_compile.$(OBJEXT): $(top_srcdir)/internal/array.h
-mjit_compile.$(OBJEXT): $(top_srcdir)/internal/class.h
-mjit_compile.$(OBJEXT): $(top_srcdir)/internal/compile.h
-mjit_compile.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-mjit_compile.$(OBJEXT): $(top_srcdir)/internal/gc.h
-mjit_compile.$(OBJEXT): $(top_srcdir)/internal/hash.h
-mjit_compile.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-mjit_compile.$(OBJEXT): $(top_srcdir)/internal/object.h
-mjit_compile.$(OBJEXT): $(top_srcdir)/internal/serial.h
-mjit_compile.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-mjit_compile.$(OBJEXT): $(top_srcdir)/internal/variable.h
-mjit_compile.$(OBJEXT): $(top_srcdir)/internal/vm.h
-mjit_compile.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-mjit_compile.$(OBJEXT): {$(VPATH)}assert.h
-mjit_compile.$(OBJEXT): {$(VPATH)}atomic.h
-mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
-mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/bool.h
-mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
-mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
-mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/limits.h
-mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
-mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
-mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
-mjit_compile.$(OBJEXT): {$(VPATH)}builtin.h
-mjit_compile.$(OBJEXT): {$(VPATH)}config.h
-mjit_compile.$(OBJEXT): {$(VPATH)}constant.h
-mjit_compile.$(OBJEXT): {$(VPATH)}darray.h
-mjit_compile.$(OBJEXT): {$(VPATH)}debug_counter.h
-mjit_compile.$(OBJEXT): {$(VPATH)}defines.h
-mjit_compile.$(OBJEXT): {$(VPATH)}id.h
-mjit_compile.$(OBJEXT): {$(VPATH)}id_table.h
-mjit_compile.$(OBJEXT): {$(VPATH)}insns.def
-mjit_compile.$(OBJEXT): {$(VPATH)}insns.inc
-mjit_compile.$(OBJEXT): {$(VPATH)}insns_info.inc
-mjit_compile.$(OBJEXT): {$(VPATH)}intern.h
-mjit_compile.$(OBJEXT): {$(VPATH)}internal.h
-mjit_compile.$(OBJEXT): {$(VPATH)}internal/abi.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_compile.$(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/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
@@ -9907,7 +10170,6 @@ node.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
node.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
node.$(OBJEXT): {$(VPATH)}config.h
node.$(OBJEXT): {$(VPATH)}constant.h
-node.$(OBJEXT): {$(VPATH)}darray.h
node.$(OBJEXT): {$(VPATH)}defines.h
node.$(OBJEXT): {$(VPATH)}id.h
node.$(OBJEXT): {$(VPATH)}id_table.h
@@ -10059,6 +10321,7 @@ 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
@@ -10256,16 +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): $(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
@@ -10274,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
@@ -10286,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
@@ -10453,22 +10723,32 @@ 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.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
+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
@@ -10646,6 +10926,7 @@ 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
@@ -10657,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
@@ -10858,6 +11140,7 @@ 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
@@ -10868,11 +11151,13 @@ proc.$(OBJEXT): $(CCAN_DIR)/list/list.h
proc.$(OBJEXT): $(CCAN_DIR)/str/str.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
@@ -10880,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
@@ -10894,7 +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)}darray.h
+proc.$(OBJEXT): {$(VPATH)}constant.h
proc.$(OBJEXT): {$(VPATH)}defines.h
proc.$(OBJEXT): {$(VPATH)}encoding.h
proc.$(OBJEXT): {$(VPATH)}eval_intern.h
@@ -11061,6 +11347,7 @@ 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
@@ -11075,6 +11362,7 @@ process.$(OBJEXT): $(CCAN_DIR)/str/str.h
process.$(OBJEXT): $(hdrdir)/ruby.h
process.$(OBJEXT): $(hdrdir)/ruby/ruby.h
process.$(OBJEXT): $(top_srcdir)/internal/array.h
+process.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
process.$(OBJEXT): $(top_srcdir)/internal/bignum.h
process.$(OBJEXT): $(top_srcdir)/internal/bits.h
process.$(OBJEXT): $(top_srcdir)/internal/class.h
@@ -11093,6 +11381,7 @@ 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
@@ -11109,7 +11398,6 @@ process.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
process.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
process.$(OBJEXT): {$(VPATH)}config.h
process.$(OBJEXT): {$(VPATH)}constant.h
-process.$(OBJEXT): {$(VPATH)}darray.h
process.$(OBJEXT): {$(VPATH)}debug_counter.h
process.$(OBJEXT): {$(VPATH)}defines.h
process.$(OBJEXT): {$(VPATH)}dln.h
@@ -11280,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
@@ -11288,13 +11577,14 @@ process.$(OBJEXT): {$(VPATH)}thread_native.h
process.$(OBJEXT): {$(VPATH)}util.h
process.$(OBJEXT): {$(VPATH)}vm_core.h
process.$(OBJEXT): {$(VPATH)}vm_opts.h
-process.$(OBJEXT): {$(VPATH)}yjit.h
ractor.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
ractor.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
ractor.$(OBJEXT): $(CCAN_DIR)/list/list.h
ractor.$(OBJEXT): $(CCAN_DIR)/str/str.h
+ractor.$(OBJEXT): $(hdrdir)/ruby.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
@@ -11311,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
@@ -11326,7 +11617,7 @@ ractor.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
ractor.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
ractor.$(OBJEXT): {$(VPATH)}builtin.h
ractor.$(OBJEXT): {$(VPATH)}config.h
-ractor.$(OBJEXT): {$(VPATH)}darray.h
+ractor.$(OBJEXT): {$(VPATH)}constant.h
ractor.$(OBJEXT): {$(VPATH)}debug_counter.h
ractor.$(OBJEXT): {$(VPATH)}defines.h
ractor.$(OBJEXT): {$(VPATH)}encoding.h
@@ -11486,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
@@ -11514,6 +11806,7 @@ random.$(OBJEXT): $(top_srcdir)/internal/bignum.h
random.$(OBJEXT): $(top_srcdir)/internal/bits.h
random.$(OBJEXT): $(top_srcdir)/internal/compilers.h
random.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+random.$(OBJEXT): $(top_srcdir)/internal/gc.h
random.$(OBJEXT): $(top_srcdir)/internal/numeric.h
random.$(OBJEXT): $(top_srcdir)/internal/random.h
random.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
@@ -11685,12 +11978,14 @@ 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/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
@@ -11877,6 +12172,7 @@ 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/ruby.h
@@ -11893,6 +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/variable.h
rational.$(OBJEXT): $(top_srcdir)/internal/vm.h
rational.$(OBJEXT): $(top_srcdir)/internal/warnings.h
rational.$(OBJEXT): {$(VPATH)}assert.h
@@ -11906,6 +12203,7 @@ 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)}id.h
rational.$(OBJEXT): {$(VPATH)}id_table.h
@@ -12054,18 +12352,26 @@ rational.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
rational.$(OBJEXT): {$(VPATH)}missing.h
rational.$(OBJEXT): {$(VPATH)}rational.c
rational.$(OBJEXT): {$(VPATH)}ruby_assert.h
+rational.$(OBJEXT): {$(VPATH)}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/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
@@ -12083,6 +12389,7 @@ 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
@@ -12244,6 +12551,7 @@ 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
@@ -12894,10 +13202,14 @@ regexec.$(OBJEXT): {$(VPATH)}st.h
regexec.$(OBJEXT): {$(VPATH)}subst.h
regparse.$(OBJEXT): $(hdrdir)/ruby.h
regparse.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+regparse.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+regparse.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+regparse.$(OBJEXT): $(top_srcdir)/internal/warnings.h
regparse.$(OBJEXT): {$(VPATH)}assert.h
regparse.$(OBJEXT): {$(VPATH)}backward/2/assume.h
regparse.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
regparse.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+regparse.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
regparse.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
regparse.$(OBJEXT): {$(VPATH)}backward/2/limits.h
regparse.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
@@ -13235,9 +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
@@ -13269,7 +13583,6 @@ ruby.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
ruby.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
ruby.$(OBJEXT): {$(VPATH)}config.h
ruby.$(OBJEXT): {$(VPATH)}constant.h
-ruby.$(OBJEXT): {$(VPATH)}darray.h
ruby.$(OBJEXT): {$(VPATH)}debug_counter.h
ruby.$(OBJEXT): {$(VPATH)}defines.h
ruby.$(OBJEXT): {$(VPATH)}dln.h
@@ -13429,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
@@ -13438,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
@@ -13453,12 +13768,14 @@ scheduler.$(OBJEXT): $(CCAN_DIR)/list/list.h
scheduler.$(OBJEXT): $(CCAN_DIR)/str/str.h
scheduler.$(OBJEXT): $(hdrdir)/ruby/ruby.h
scheduler.$(OBJEXT): $(top_srcdir)/internal/array.h
+scheduler.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
scheduler.$(OBJEXT): $(top_srcdir)/internal/compilers.h
scheduler.$(OBJEXT): $(top_srcdir)/internal/gc.h
scheduler.$(OBJEXT): $(top_srcdir)/internal/imemo.h
scheduler.$(OBJEXT): $(top_srcdir)/internal/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
@@ -13473,11 +13790,12 @@ scheduler.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
scheduler.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
scheduler.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
scheduler.$(OBJEXT): {$(VPATH)}config.h
-scheduler.$(OBJEXT): {$(VPATH)}darray.h
+scheduler.$(OBJEXT): {$(VPATH)}constant.h
scheduler.$(OBJEXT): {$(VPATH)}defines.h
scheduler.$(OBJEXT): {$(VPATH)}encoding.h
scheduler.$(OBJEXT): {$(VPATH)}fiber/scheduler.h
scheduler.$(OBJEXT): {$(VPATH)}id.h
+scheduler.$(OBJEXT): {$(VPATH)}id_table.h
scheduler.$(OBJEXT): {$(VPATH)}intern.h
scheduler.$(OBJEXT): {$(VPATH)}internal.h
scheduler.$(OBJEXT): {$(VPATH)}internal/abi.h
@@ -13639,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
@@ -13804,12 +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/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
@@ -13820,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
@@ -13834,7 +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)}darray.h
+signal.$(OBJEXT): {$(VPATH)}constant.h
signal.$(OBJEXT): {$(VPATH)}debug_counter.h
signal.$(OBJEXT): {$(VPATH)}defines.h
signal.$(OBJEXT): {$(VPATH)}encoding.h
@@ -13880,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
@@ -14001,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
@@ -14025,6 +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/variable.h
sprintf.$(OBJEXT): $(top_srcdir)/internal/vm.h
sprintf.$(OBJEXT): $(top_srcdir)/internal/warnings.h
sprintf.$(OBJEXT): {$(VPATH)}assert.h
@@ -14038,6 +14568,7 @@ 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
@@ -14199,6 +14730,7 @@ 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
@@ -14366,11 +14898,13 @@ st.$(OBJEXT): {$(VPATH)}internal/variable.h
st.$(OBJEXT): {$(VPATH)}internal/warning_push.h
st.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
st.$(OBJEXT): {$(VPATH)}missing.h
+st.$(OBJEXT): {$(VPATH)}ruby_assert.h
st.$(OBJEXT): {$(VPATH)}st.c
st.$(OBJEXT): {$(VPATH)}st.h
st.$(OBJEXT): {$(VPATH)}subst.h
strftime.$(OBJEXT): $(hdrdir)/ruby/ruby.h
strftime.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+strftime.$(OBJEXT): $(top_srcdir)/internal/encoding.h
strftime.$(OBJEXT): $(top_srcdir)/internal/serial.h
strftime.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
strftime.$(OBJEXT): $(top_srcdir)/internal/string.h
@@ -14549,6 +15083,7 @@ strftime.$(OBJEXT): {$(VPATH)}timev.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
@@ -14567,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
@@ -14581,6 +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)}constant.h
string.$(OBJEXT): {$(VPATH)}debug_counter.h
string.$(OBJEXT): {$(VPATH)}defines.h
string.$(OBJEXT): {$(VPATH)}encindex.h
@@ -14627,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
@@ -14748,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
@@ -14791,6 +15330,7 @@ struct.$(OBJEXT): $(CCAN_DIR)/list/list.h
struct.$(OBJEXT): $(CCAN_DIR)/str/str.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
@@ -14804,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
@@ -14819,7 +15360,7 @@ struct.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
struct.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
struct.$(OBJEXT): {$(VPATH)}builtin.h
struct.$(OBJEXT): {$(VPATH)}config.h
-struct.$(OBJEXT): {$(VPATH)}darray.h
+struct.$(OBJEXT): {$(VPATH)}constant.h
struct.$(OBJEXT): {$(VPATH)}defines.h
struct.$(OBJEXT): {$(VPATH)}encoding.h
struct.$(OBJEXT): {$(VPATH)}id.h
@@ -14982,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
@@ -15001,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
@@ -15013,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
@@ -15061,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
@@ -15179,10 +15725,13 @@ 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
@@ -15192,6 +15741,7 @@ thread.$(OBJEXT): $(CCAN_DIR)/str/str.h
thread.$(OBJEXT): $(hdrdir)/ruby.h
thread.$(OBJEXT): $(hdrdir)/ruby/ruby.h
thread.$(OBJEXT): $(top_srcdir)/internal/array.h
+thread.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
thread.$(OBJEXT): $(top_srcdir)/internal/bits.h
thread.$(OBJEXT): $(top_srcdir)/internal/class.h
thread.$(OBJEXT): $(top_srcdir)/internal/compilers.h
@@ -15209,6 +15759,7 @@ 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)}assert.h
@@ -15222,8 +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)}darray.h
+thread.$(OBJEXT): {$(VPATH)}constant.h
thread.$(OBJEXT): {$(VPATH)}debug.h
thread.$(OBJEXT): {$(VPATH)}debug_counter.h
thread.$(OBJEXT): {$(VPATH)}defines.h
@@ -15397,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
@@ -15405,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
-thread.$(OBJEXT): {$(VPATH)}yjit.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
@@ -15600,6 +16155,7 @@ 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
@@ -15616,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
@@ -15628,6 +16185,7 @@ 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
@@ -15786,11 +16344,13 @@ 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): $(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
@@ -15960,6 +16520,7 @@ transient_heap.$(OBJEXT): {$(VPATH)}internal/warning_push.h
transient_heap.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
transient_heap.$(OBJEXT): {$(VPATH)}missing.h
transient_heap.$(OBJEXT): {$(VPATH)}ruby_assert.h
+transient_heap.$(OBJEXT): {$(VPATH)}shape.h
transient_heap.$(OBJEXT): {$(VPATH)}st.h
transient_heap.$(OBJEXT): {$(VPATH)}subst.h
transient_heap.$(OBJEXT): {$(VPATH)}transient_heap.c
@@ -16139,6 +16700,7 @@ variable.$(OBJEXT): $(CCAN_DIR)/list/list.h
variable.$(OBJEXT): $(CCAN_DIR)/str/str.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
@@ -16169,7 +16731,6 @@ variable.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
variable.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
variable.$(OBJEXT): {$(VPATH)}config.h
variable.$(OBJEXT): {$(VPATH)}constant.h
-variable.$(OBJEXT): {$(VPATH)}darray.h
variable.$(OBJEXT): {$(VPATH)}debug_counter.h
variable.$(OBJEXT): {$(VPATH)}defines.h
variable.$(OBJEXT): {$(VPATH)}encoding.h
@@ -16335,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
@@ -16355,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
@@ -16376,10 +16940,11 @@ version.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
version.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
version.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
version.$(OBJEXT): {$(VPATH)}config.h
-version.$(OBJEXT): {$(VPATH)}darray.h
+version.$(OBJEXT): {$(VPATH)}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
@@ -16526,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
@@ -16543,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
@@ -16587,7 +17155,6 @@ vm.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
vm.$(OBJEXT): {$(VPATH)}builtin.h
vm.$(OBJEXT): {$(VPATH)}config.h
vm.$(OBJEXT): {$(VPATH)}constant.h
-vm.$(OBJEXT): {$(VPATH)}darray.h
vm.$(OBJEXT): {$(VPATH)}debug_counter.h
vm.$(OBJEXT): {$(VPATH)}defines.h
vm.$(OBJEXT): {$(VPATH)}defs/opt_operand.def
@@ -16764,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
@@ -16793,6 +17361,7 @@ vm_backtrace.$(OBJEXT): $(CCAN_DIR)/list/list.h
vm_backtrace.$(OBJEXT): $(CCAN_DIR)/str/str.h
vm_backtrace.$(OBJEXT): $(hdrdir)/ruby/ruby.h
vm_backtrace.$(OBJEXT): $(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
@@ -16800,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
@@ -16814,12 +17384,13 @@ vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
vm_backtrace.$(OBJEXT): {$(VPATH)}config.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}darray.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}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
@@ -16979,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
@@ -16992,6 +17564,7 @@ vm_dump.$(OBJEXT): $(CCAN_DIR)/list/list.h
vm_dump.$(OBJEXT): $(CCAN_DIR)/str/str.h
vm_dump.$(OBJEXT): $(hdrdir)/ruby/ruby.h
vm_dump.$(OBJEXT): $(top_srcdir)/internal/array.h
+vm_dump.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
vm_dump.$(OBJEXT): $(top_srcdir)/internal/compilers.h
vm_dump.$(OBJEXT): $(top_srcdir)/internal/gc.h
vm_dump.$(OBJEXT): $(top_srcdir)/internal/imemo.h
@@ -17014,7 +17587,6 @@ vm_dump.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
vm_dump.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
vm_dump.$(OBJEXT): {$(VPATH)}config.h
vm_dump.$(OBJEXT): {$(VPATH)}constant.h
-vm_dump.$(OBJEXT): {$(VPATH)}darray.h
vm_dump.$(OBJEXT): {$(VPATH)}defines.h
vm_dump.$(OBJEXT): {$(VPATH)}gc.h
vm_dump.$(OBJEXT): {$(VPATH)}id.h
@@ -17170,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
@@ -17184,11 +17757,13 @@ vm_sync.$(OBJEXT): $(CCAN_DIR)/list/list.h
vm_sync.$(OBJEXT): $(CCAN_DIR)/str/str.h
vm_sync.$(OBJEXT): $(hdrdir)/ruby/ruby.h
vm_sync.$(OBJEXT): $(top_srcdir)/internal/array.h
+vm_sync.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
vm_sync.$(OBJEXT): $(top_srcdir)/internal/compilers.h
vm_sync.$(OBJEXT): $(top_srcdir)/internal/gc.h
vm_sync.$(OBJEXT): $(top_srcdir)/internal/imemo.h
vm_sync.$(OBJEXT): $(top_srcdir)/internal/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)}assert.h
@@ -17203,7 +17778,7 @@ vm_sync.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
vm_sync.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
vm_sync.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
vm_sync.$(OBJEXT): {$(VPATH)}config.h
-vm_sync.$(OBJEXT): {$(VPATH)}darray.h
+vm_sync.$(OBJEXT): {$(VPATH)}constant.h
vm_sync.$(OBJEXT): {$(VPATH)}debug_counter.h
vm_sync.$(OBJEXT): {$(VPATH)}defines.h
vm_sync.$(OBJEXT): {$(VPATH)}gc.h
@@ -17358,6 +17933,7 @@ 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
@@ -17374,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
@@ -17381,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
@@ -17396,13 +17974,14 @@ vm_trace.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
vm_trace.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
vm_trace.$(OBJEXT): {$(VPATH)}builtin.h
vm_trace.$(OBJEXT): {$(VPATH)}config.h
-vm_trace.$(OBJEXT): {$(VPATH)}darray.h
+vm_trace.$(OBJEXT): {$(VPATH)}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
@@ -17564,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
@@ -17579,19 +18159,19 @@ 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/object.h
-yjit.$(OBJEXT): $(top_srcdir)/internal/re.h
yjit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
yjit.$(OBJEXT): $(top_srcdir)/internal/serial.h
yjit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
yjit.$(OBJEXT): $(top_srcdir)/internal/string.h
-yjit.$(OBJEXT): $(top_srcdir)/internal/struct.h
yjit.$(OBJEXT): $(top_srcdir)/internal/variable.h
yjit.$(OBJEXT): $(top_srcdir)/internal/vm.h
yjit.$(OBJEXT): $(top_srcdir)/internal/warnings.h
@@ -17609,7 +18189,7 @@ yjit.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
yjit.$(OBJEXT): {$(VPATH)}builtin.h
yjit.$(OBJEXT): {$(VPATH)}config.h
yjit.$(OBJEXT): {$(VPATH)}constant.h
-yjit.$(OBJEXT): {$(VPATH)}darray.h
+yjit.$(OBJEXT): {$(VPATH)}debug.h
yjit.$(OBJEXT): {$(VPATH)}debug_counter.h
yjit.$(OBJEXT): {$(VPATH)}defines.h
yjit.$(OBJEXT): {$(VPATH)}encoding.h
@@ -17781,6 +18361,7 @@ 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
@@ -17788,19 +18369,10 @@ 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.rb
yjit.$(OBJEXT): {$(VPATH)}yjit.rbinc
-yjit.$(OBJEXT): {$(VPATH)}yjit_asm.c
-yjit.$(OBJEXT): {$(VPATH)}yjit_asm.h
-yjit.$(OBJEXT): {$(VPATH)}yjit_codegen.c
-yjit.$(OBJEXT): {$(VPATH)}yjit_codegen.h
-yjit.$(OBJEXT): {$(VPATH)}yjit_core.c
-yjit.$(OBJEXT): {$(VPATH)}yjit_core.h
-yjit.$(OBJEXT): {$(VPATH)}yjit_iface.c
-yjit.$(OBJEXT): {$(VPATH)}yjit_iface.h
-yjit.$(OBJEXT): {$(VPATH)}yjit_utils.c
# AUTOGENERATED DEPENDENCIES END
diff --git a/compar.c b/compar.c
index c82d44c103..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);
}
}
@@ -167,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));
}
/*
@@ -231,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)) {
@@ -288,16 +286,18 @@ cmp_clamp(int argc, VALUE *argv, VALUE x)
*
* \Module \Comparable provides these methods, all of which use method <tt><=></tt>:
*
- * - #<:: Returns whether +self+ is less than the given object.
- * - #<=:: Returns whether +self+ is less than or equal to the given object.
- * - #==:: 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:
+ * - #<: 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 cd3f0e2a9d..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)
@@ -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)
@@ -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,108 +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_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->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:
- {
+ /* 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));
+ 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;
- }
- }
+ 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));
@@ -864,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
@@ -883,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;
@@ -978,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 */
@@ -1062,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;
}
}
@@ -1076,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;
}
}
@@ -1089,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;
}
}
@@ -1101,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;
}
}
@@ -1121,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;
}
@@ -1137,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;
}
}
@@ -1149,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;
}
}
@@ -1167,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);
}
@@ -1184,11 +1182,11 @@ 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", (void *)&anchor->anchor,
- (void *)anchor->anchor.next, (void *)anchor->last);
+ (void *)anchor->anchor.next, (void *)anchor->last);
while (list) {
- 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("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");
@@ -1245,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);
@@ -1262,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;
}
@@ -1271,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);
}
@@ -1298,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;
@@ -1323,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 = iseq->body->variable.script_lines;
+ 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");
@@ -1345,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;
}
@@ -1360,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)
@@ -1402,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;
}
}
@@ -1421,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
@@ -1443,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");
@@ -1487,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;
@@ -1499,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");
@@ -1527,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;
}
@@ -1536,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;
}
@@ -1548,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;
}
@@ -1559,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),
@@ -1576,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) {
@@ -1590,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;
}
@@ -1599,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;
}
}
@@ -1619,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;
}
}
@@ -1644,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, RBOOL(write));
+ rb_id_table_insert(ISEQ_BODY(iseq)->outer_variables, id, RBOOL(write));
}
- iseq = iseq->body->parent_iseq;
+ iseq = ISEQ_BODY(iseq)->parent_iseq;
}
}
@@ -1667,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;
}
@@ -1679,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);
}
@@ -1691,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);
}
@@ -1704,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;
@@ -1754,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:
+ ++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;
- }
+ dv = complex_mark;
+ }
- keyword->num = ++di;
- rb_ary_push(default_values, dv);
- }
+ keyword->num = ++di;
+ rb_ary_push(default_values, dv);
+ }
- node = node->nd_next;
+ 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;
}
@@ -1826,120 +1852,120 @@ 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;
@@ -1951,13 +1977,13 @@ iseq_set_local_table(rb_iseq_t *iseq, const rb_ast_id_table_t *tbl)
unsigned int size = tbl ? tbl->size : 0;
if (size > 0) {
- ID *ids = (ID *)ALLOC_N(ID, size);
- MEMCPY(ids, tbl->ids, 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;
}
@@ -2061,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;
}
@@ -2093,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 (IS_LABEL(list)) {
- 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;
}
@@ -2229,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;
}
/**
@@ -2245,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;
@@ -2262,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)) {
@@ -2284,144 +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_ICVARC: /* inline cvar cache */
- 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, 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, body->is_size);
- }
- generated_iseq[code_index + 1 + j] = (VALUE)ic;
- FL_SET(iseqv, ISEQ_MARKABLE_ISEQ);
-
- if (insn == BIN(opt_getinlinecache) && type == TS_IC) {
- // Store the instruction index for opt_getinlinecache on the IC for
- // YJIT to invalidate code when opt_setinlinecache runs.
- ic->get_insn_idx = (unsigned int)code_index;
+ ic_index, ISEQ_IS_SIZE(body));
}
- break;
- }
+ generated_iseq[code_index + 1 + j] = (VALUE)ic;
+
+ break;
+ }
case TS_CALLDATA:
{
const struct rb_callinfo *source_ci = (const struct rb_callinfo *)operands[j];
@@ -2432,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;
@@ -2543,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;
}
@@ -2598,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;
}
@@ -2617,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;
}
@@ -2648,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;
}
@@ -2662,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;
}
@@ -2695,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;
}
@@ -2713,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;
}
@@ -2769,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;
}
}
@@ -2825,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;
}
@@ -2867,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);
@@ -2913,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;
+ }
}
/*
@@ -3039,19 +3157,19 @@ 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);
}
/*
@@ -3071,17 +3189,17 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
}
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!!!
*
@@ -3104,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) {
@@ -3217,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);
- }
+ 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;
- /*
+ LINK_ELEMENT *next = iobj->link.next;
+ /*
* anytostring
- * concatstrings 1
- * =>
+ * concatstrings 1
+ * =>
* anytostring
- */
- if (IS_INSN(next) && IS_INSN_ID(next, concatstrings) &&
- OPERAND_AT(next, 0) == INT2FIX(1)) {
- ELEM_REMOVE(next);
- }
+ */
+ 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)) {
@@ -3450,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;
}
@@ -3475,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)) {
@@ -3502,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
@@ -3555,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;
}
}
@@ -3575,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;
@@ -3585,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;
@@ -3607,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) {
@@ -3634,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;
@@ -3644,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);
@@ -3683,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;
@@ -3741,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;
@@ -3772,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;
@@ -3801,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;
@@ -3890,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;
}
}
@@ -3917,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_p(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;
@@ -3993,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));
@@ -4010,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 */
@@ -4026,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;
}
@@ -4105,25 +4349,25 @@ keyword_node_p(const NODE *const node)
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_p(root_node->nd_head, NODE_LIST)) {
- const NODE *node = root_node->nd_head;
+ 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_p(node, NODE_LIST));
+ 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 {
+ /* can be keywords */
+ }
+ else {
if (flag) {
*flag |= VM_CALL_KW_SPLAT;
if (seen_nodes > 1 || node->nd_next->nd_next) {
@@ -4134,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;
}
@@ -4200,11 +4444,11 @@ static_literal_node_p(const NODE *node, const rb_iseq_t *iseq)
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;
}
}
@@ -4213,11 +4457,11 @@ static_literal_value(const NODE *node, rb_iseq_t *iseq)
{
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;
@@ -4230,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;
}
}
@@ -4240,9 +4484,9 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop
const NODE *line_node = node;
if (nd_type_p(node, NODE_ZLIST)) {
- if (!popped) {
- ADD_INSN1(ret, line_node, newarray, INT2FIX(0));
- }
+ if (!popped) {
+ ADD_INSN1(ret, line_node, newarray, INT2FIX(0));
+ }
return 0;
}
@@ -4317,7 +4561,7 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop
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)
@@ -4368,7 +4612,7 @@ static int
compile_array_1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node)
{
if (static_literal_node_p(node, iseq)) {
- VALUE ary = rb_ary_tmp_new(1);
+ VALUE ary = rb_ary_hidden_new(1);
rb_ary_push(ary, static_literal_value(node, iseq));
OBJ_FREEZE(ary);
@@ -4376,7 +4620,12 @@ compile_array_1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node)
}
else {
CHECK(COMPILE_(ret, "array element", node, FALSE));
- ADD_INSN1(ret, node, newarray, INT2FIX(1));
+ if (keyword_node_p(node)) {
+ ADD_INSN1(ret, node, newarraykwsplat, INT2FIX(1));
+ }
+ else {
+ ADD_INSN1(ret, node, newarray, INT2FIX(1));
+ }
}
return 1;
@@ -4396,9 +4645,9 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int meth
node = node->nd_head;
if (!node || nd_type_p(node, NODE_ZLIST)) {
- if (!popped) {
- ADD_INSN1(ret, line_node, newhash, INT2FIX(0));
- }
+ if (!popped) {
+ ADD_INSN1(ret, line_node, newhash, INT2FIX(0));
+ }
return 0;
}
@@ -4465,7 +4714,7 @@ 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) {
@@ -4583,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_FLOAT_TYPE_P(v) &&
- 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_p(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;
}
@@ -4785,7 +5034,8 @@ struct masgn_state {
};
static int
-add_masgn_lhs_node(struct masgn_state *state, int lhs_pos, const NODE *line_node, int argc, INSN *before_insn) {
+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");
}
@@ -4821,17 +5071,22 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const
{
switch (nd_type(node)) {
case NODE_ATTRASGN: {
- 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 */
- ASSUME(iobj);
- 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;
@@ -4850,23 +5105,27 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const
return COMPILE_NG;
}
- 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);
@@ -4884,7 +5143,7 @@ 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) {
@@ -4910,10 +5169,10 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const
}
/* 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);
}
}
@@ -4925,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;
@@ -4933,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);
@@ -4946,48 +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_p(rhsn, NODE_LIST)) {
- return 0;
+ 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_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);
@@ -5102,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;
}
@@ -5136,20 +5418,20 @@ static int
compile_cpath(LINK_ANCHOR *const ret, rb_iseq_t *iseq, const NODE *cpath)
{
if (nd_type_p(cpath, NODE_COLON3)) {
- /* toplevel class ::Foo */
- ADD_INSN1(ret, cpath, putobject, rb_cObject);
- return VM_DEFINECLASS_FLAG_SCOPED;
+ /* 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;
}
}
@@ -5165,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);
@@ -5182,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:
@@ -5215,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));
@@ -5268,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]) {
@@ -5289,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:
@@ -5313,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
@@ -5359,8 +5641,8 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
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);
@@ -5384,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]);
}
}
@@ -5413,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;
}
@@ -5443,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 */
@@ -5473,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;
@@ -5508,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);
@@ -5616,7 +5898,7 @@ 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_p(argn, NODE_BLOCK_PASS)) {
@@ -5652,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);
@@ -5678,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);
}
@@ -5737,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;
@@ -5760,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));
@@ -5787,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;
@@ -5869,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);
@@ -5962,56 +6244,56 @@ compile_case2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
endlabel = NEW_LABEL(nd_line(node));
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(
+ 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);
@@ -6607,9 +6889,9 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
ADD_INSNL(ret, line_node, jump, unmatched);
break;
case NODE_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);
@@ -7129,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);
@@ -7146,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;
@@ -7209,23 +7491,46 @@ compile_iter(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
ADD_LABEL(ret, retry_label);
if (nd_type_p(node, NODE_FOR)) {
- CHECK(COMPILE(ret, "iter caller (for)", node->nd_iter));
+ CHECK(COMPILE(ret, "iter caller (for)", 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;
@@ -7272,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;
}
@@ -7317,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;
}
@@ -7331,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;
}
@@ -7404,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;
}
@@ -7472,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;
}
@@ -7496,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;
@@ -7512,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 */
@@ -7538,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;
}
@@ -7591,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);
@@ -7622,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;
@@ -7639,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;
}
@@ -7699,7 +8004,7 @@ compile_evstr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
if (!popped && !all_string_result_p(node)) {
const NODE *line_node = node;
- const unsigned int flag = VM_CALL_FCALL;
+ 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.
@@ -7713,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));
@@ -7856,13 +8161,13 @@ 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);
@@ -7873,12 +8178,12 @@ delegate_call_p(const rb_iseq_t *iseq, unsigned int argc, const LINK_ANCHOR *arg
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;
@@ -7956,14 +8261,14 @@ compile_builtin_mandatory_only_method(rb_iseq_t *iseq, const NODE *node, const N
{
// arguments
struct rb_args_info args = {
- .pre_args_num = iseq->body->param.lead_num,
+ .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->param.size - iseq->body->param.lead_num;
- const int table_size = iseq->body->local_table_size - skip_local_size;
+ 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));
@@ -7972,12 +8277,12 @@ compile_builtin_mandatory_only_method(rb_iseq_t *iseq, const NODE *node, const N
int i;
// lead parameters
- for (i=0; i<iseq->body->param.lead_num; i++) {
- tbl->ids[i] = iseq->body->local_table[i];
+ 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->local_table[i + skip_local_size];
+ tbl->ids[i] = ISEQ_BODY(iseq)->local_table[i + skip_local_size];
}
NODE scope_node;
@@ -7986,15 +8291,15 @@ compile_builtin_mandatory_only_method(rb_iseq_t *iseq, const NODE *node, const N
rb_ast_body_t ast = {
.root = &scope_node,
.compile_option = 0,
- .script_lines = iseq->body->variable.script_lines,
+ .script_lines = ISEQ_BODY(iseq)->variable.script_lines,
};
int prev_inline_index = GET_VM()->builtin_inline_index;
- iseq->body->mandatory_only_iseq =
+ 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),
- INT2FIX(nd_line(line_node)), NULL, 0,
+ nd_line(line_node), NULL, 0,
ISEQ_TYPE_METHOD, ISEQ_COMPILE_DATA(iseq)->option);
GET_VM()->builtin_inline_index = prev_inline_index;
@@ -8034,7 +8339,7 @@ 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) {
@@ -8287,106 +8592,106 @@ compile_op_asgn1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
*/
if (!popped) {
- ADD_INSN(ret, node, putnil);
+ 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;
+ argc = INT2FIX(0);
+ break;
case NODE_BLOCK_PASS:
- boff = 1;
- /* fall through */
+ boff = 1;
+ /* fall through */
default:
- argc = setup_args(iseq, ret, node->nd_args->nd_head, &flag, NULL);
- CHECK(!NIL_P(argc));
+ 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);
+ /* 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);
+ 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;
}
@@ -8426,6 +8731,17 @@ compile_op_asgn2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
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
@@ -8446,56 +8762,56 @@ compile_op_asgn2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
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);
+ lskip = NEW_LABEL(line);
+ ADD_INSN(ret, node, dup);
+ ADD_INSNL(ret, node, branchnil, lskip);
}
ADD_INSN(ret, node, dup);
ADD_SEND_WITH_FLAG(ret, node, vid, INT2FIX(0), INT2FIX(asgnflag));
if (atype == idOROP || atype == idANDOP) {
- ADD_INSN(ret, node, dup);
- if (atype == idOROP) {
- ADD_INSNL(ret, node, branchif, lcfin);
- }
- else { /* idANDOP */
- ADD_INSNL(ret, node, branchunless, lcfin);
- }
- ADD_INSN(ret, node, pop);
- CHECK(COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value));
- ADD_INSN(ret, node, swap);
- ADD_INSN1(ret, node, topn, INT2FIX(1));
- ADD_SEND_WITH_FLAG(ret, node, aid, INT2FIX(1), INT2FIX(asgnflag));
- ADD_INSNL(ret, node, jump, lfin);
-
- ADD_LABEL(ret, lcfin);
- ADD_INSN(ret, node, swap);
-
- ADD_LABEL(ret, lfin);
- ADD_INSN(ret, node, pop);
- if (lskip) {
- ADD_LABEL(ret, lskip);
- }
- if (popped) {
- /* we can apply more optimize */
- ADD_INSN(ret, node, pop);
- }
+ 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);
- }
+ 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;
}
@@ -8510,63 +8826,63 @@ compile_op_cdecl(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
switch (nd_type(node->nd_head)) {
case NODE_COLON3:
- ADD_INSN1(ret, node, putobject, rb_cObject);
- break;
+ 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;
+ 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;
+ 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 */
+ 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] */
+ 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));
+ 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;
}
@@ -8579,46 +8895,47 @@ compile_op_log(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
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);
+ 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);
+ lassign = NEW_LABEL(line);
}
CHECK(COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_head", node->nd_head));
- ADD_INSN(ret, node, dup);
+
+ if (!popped) {
+ ADD_INSN(ret, node, dup);
+ }
if (type == NODE_OP_ASGN_AND) {
- ADD_INSNL(ret, node, branchunless, lfin);
+ ADD_INSNL(ret, node, branchunless, lfin);
}
else {
- ADD_INSNL(ret, node, branchif, lfin);
+ ADD_INSNL(ret, node, branchif, lfin);
+ }
+
+ if (!popped) {
+ ADD_INSN(ret, node, pop);
}
- ADD_INSN(ret, node, pop);
ADD_LABEL(ret, lassign);
- CHECK(COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_value", node->nd_value));
+ CHECK(COMPILE_(ret, "NODE_OP_ASGN_AND/OR#nd_value", node->nd_value, popped));
ADD_LABEL(ret, lfin);
-
- if (popped) {
- /* we can apply more optimize */
- ADD_INSN(ret, node, pop);
- }
return COMPILE_OK;
}
static int
compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped, const enum node_type type)
{
- struct rb_iseq_constant_body *const body = iseq->body;
+ struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
DECL_ANCHOR(args);
int argc;
unsigned int flag = 0;
@@ -8628,115 +8945,115 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
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);
+ VALUE vargc = setup_args(iseq, args, node->nd_args, &flag, &keywords);
+ CHECK(!NIL_P(vargc));
+ argc = FIX2INT(vargc);
}
else {
- /* NODE_ZSUPER */
- int i;
- const rb_iseq_t *liseq = body->local_iseq;
- const struct rb_iseq_constant_body *const local_body = liseq->body;
- const struct rb_iseq_param_keyword *const local_kwd = local_body->param.keyword;
- int lvar_level = get_lvar_level(iseq);
-
- argc = local_body->param.lead_num;
-
- /* normal arguments */
- for (i = 0; i < local_body->param.lead_num; i++) {
- int idx = local_body->local_table_size - i;
- ADD_GETLOCAL(args, node, idx, lvar_level);
- }
-
- if (local_body->param.flags.has_opt) {
- /* optional arguments */
- int j;
- for (j = 0; j < local_body->param.opt_num; j++) {
- int idx = local_body->local_table_size - (i + j);
- ADD_GETLOCAL(args, node, idx, lvar_level);
- }
- i += j;
- argc = i;
- }
- if (local_body->param.flags.has_rest) {
- /* rest argument */
- int idx = local_body->local_table_size - local_body->param.rest_start;
- ADD_GETLOCAL(args, node, idx, lvar_level);
- ADD_INSN1(args, node, splatarray, Qfalse);
-
- argc = local_body->param.rest_start + 1;
- flag |= VM_CALL_ARGS_SPLAT;
- }
- if (local_body->param.flags.has_post) {
- /* post arguments */
- int post_len = local_body->param.post_num;
- int post_start = local_body->param.post_start;
-
- if (local_body->param.flags.has_rest) {
- int j;
- for (j=0; 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);
+ /* 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));
+ }
+ 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;
- }
+ }
+ 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++;
- }
+ }
+ 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;
@@ -8744,11 +9061,11 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
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);
+ new_callinfo(iseq, 0, argc, flag, keywords, parent_block != NULL),
+ parent_block);
if (popped) {
- ADD_INSN(ret, node, pop);
+ ADD_INSN(ret, node, pop);
}
return COMPILE_OK;
}
@@ -8763,34 +9080,34 @@ compile_yield(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
INIT_ANCHOR(args);
- switch (iseq->body->local_iseq->body->type) {
+ 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;
+ 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));
+ argc = setup_args(iseq, args, node->nd_head, &flag, &keywords);
+ CHECK(!NIL_P(argc));
}
else {
- argc = INT2FIX(0);
+ 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);
+ ADD_INSN(ret, node, pop);
}
int level = 0;
const rb_iseq_t *tmp_iseq = iseq;
- for (; tmp_iseq != iseq->body->local_iseq; level++ ) {
- tmp_iseq = tmp_iseq->body->parent_iseq;
+ 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);
@@ -8807,18 +9124,18 @@ compile_match(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
INIT_ANCHOR(val);
switch ((int)type) {
case NODE_MATCH:
- ADD_INSN1(recv, node, putobject, node->nd_lit);
- ADD_INSN2(val, node, getspecial, INT2FIX(0),
- INT2FIX(0));
- break;
+ 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;
+ 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;
+ CHECK(COMPILE(recv, "receiver", node->nd_value));
+ CHECK(COMPILE(val, "value", node->nd_recv));
+ break;
}
ADD_SEQ(ret, recv);
@@ -8826,11 +9143,11 @@ compile_match(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
ADD_SEND(ret, node, idEqTilde, INT2FIX(1));
if (node->nd_args) {
- compile_named_capture_assign(iseq, ret, node->nd_args);
+ compile_named_capture_assign(iseq, ret, node->nd_args);
}
if (popped) {
- ADD_INSN(ret, node, pop);
+ ADD_INSN(ret, node, pop);
}
return COMPILE_OK;
}
@@ -8838,46 +9155,41 @@ compile_match(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
static int
compile_colon2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
{
- const int line = nd_line(node);
if (rb_is_const_id(node->nd_mid)) {
- /* constant */
- LABEL *lend = NEW_LABEL(line);
- int ic_index = iseq->body->is_size++;
-
- DECL_ANCHOR(pref);
- DECL_ANCHOR(body);
-
- INIT_ANCHOR(pref);
- INIT_ANCHOR(body);
- CHECK(compile_const_prefix(iseq, node, pref, body));
- if (LIST_INSN_SIZE_ZERO(pref)) {
- if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
- ADD_INSN2(ret, node, opt_getinlinecache, lend, INT2FIX(ic_index));
- }
- else {
- ADD_INSN(ret, node, putnil);
- }
-
- ADD_SEQ(ret, body);
-
- if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
- ADD_INSN1(ret, node, opt_setinlinecache, INT2FIX(ic_index));
- ADD_LABEL(ret, lend);
- }
- }
- else {
- ADD_SEQ(ret, pref);
- ADD_SEQ(ret, body);
- }
+ /* 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));
+ /* 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);
+ ADD_INSN(ret, node, pop);
}
return COMPILE_OK;
}
@@ -8885,29 +9197,23 @@ compile_colon2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
static int
compile_colon3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
{
- const int line = nd_line(node);
- LABEL *lend = NEW_LABEL(line);
- int ic_index = iseq->body->is_size++;
-
debugi("colon3#nd_mid", node->nd_mid);
/* add cache insn */
if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
- ADD_INSN2(ret, node, opt_getinlinecache, lend, INT2FIX(ic_index));
- ADD_INSN(ret, node, pop);
+ 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);
}
-
- ADD_INSN1(ret, node, putobject, rb_cObject);
- ADD_INSN1(ret, node, putobject, Qtrue);
- ADD_INSN1(ret, node, getconstant, ID2SYM(node->nd_mid));
-
- if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
- ADD_INSN1(ret, node, opt_setinlinecache, INT2FIX(ic_index));
- ADD_LABEL(ret, lend);
+ 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);
+ ADD_INSN(ret, node, pop);
}
return COMPILE_OK;
}
@@ -8920,20 +9226,20 @@ compile_dots(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
const NODE *e = node->nd_end;
if (optimizable_range_item_p(b) && optimizable_range_item_p(e)) {
- if (!popped) {
+ 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);
- }
+ 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);
- }
+ CHECK(COMPILE_(ret, "min", b, popped));
+ CHECK(COMPILE_(ret, "max", e, popped));
+ if (!popped) {
+ ADD_INSN1(ret, node, newrange, flag);
+ }
}
return COMPILE_OK;
}
@@ -8942,26 +9248,26 @@ static int
compile_errinfo(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
{
if (!popped) {
- if (iseq->body->type == ISEQ_TYPE_RESCUE) {
- ADD_GETLOCAL(ret, node, LVAR_ERRINFO, 0);
- }
- else {
- const rb_iseq_t *ip = iseq;
- int level = 0;
- while (ip) {
- if (ip->body->type == ISEQ_TYPE_RESCUE) {
- break;
- }
- ip = ip->body->parent_iseq;
- level++;
- }
- if (ip) {
- ADD_GETLOCAL(ret, node, LVAR_ERRINFO, level);
- }
- else {
- ADD_INSN(ret, node, putnil);
- }
- }
+ 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;
}
@@ -8969,34 +9275,34 @@ compile_errinfo(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
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;
+ 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;
+ /* 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;
+ 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);
+ /* 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;
}
@@ -9015,25 +9321,26 @@ compile_attrasgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
/* optimization shortcut
* obj["literal"] = value -> opt_aset_with(obj, "literal", value)
*/
- if (mid == idASET && !private_recv_p(node) && node->nd_args &&
- nd_type_p(node->nd_args, NODE_LIST) && node->nd_args->nd_alen == 2 &&
- nd_type_p(node->nd_args->nd_head, NODE_STR) &&
- ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
- !ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal &&
- ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction)
+ 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;
+ 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);
@@ -9049,38 +9356,38 @@ compile_attrasgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
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);
+ /* 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));
- }
+ 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_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);
@@ -9117,20 +9424,20 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
{
const int line = (int)nd_line(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);
@@ -9140,134 +9447,137 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
switch (type) {
case NODE_BLOCK:
CHECK(compile_block(iseq, ret, node, popped));
- break;
+ 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, 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;
+ 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, node, dup);
- }
- ADD_SETLOCAL(ret, 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: {
- 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;
+ 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, node, dup);
- }
- ADD_INSN1(ret, 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, node, dup);
- }
- ADD_INSN2(ret, 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:{
if (node->nd_vid) {
@@ -9277,12 +9587,12 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
ADD_INSN(ret, node, dup);
}
- ADD_INSN1(ret, node, putspecialobject,
- INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE));
+ 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);
+ }
+ else {
+ compile_cpath(ret, iseq, node->nd_else);
CHECK(COMPILE(ret, "lvalue", node->nd_value));
ADD_INSN(ret, node, swap);
@@ -9292,32 +9602,32 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
}
ADD_INSN1(ret, node, setconstant, ID2SYM(node->nd_else->nd_mid));
- }
- break;
+ }
+ break;
}
case NODE_CVASGN:{
- CHECK(COMPILE(ret, "cvasgn val", node->nd_value));
- if (!popped) {
- ADD_INSN(ret, node, dup);
- }
+ 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;
+ get_cvar_ic_value(iseq,node->nd_vid));
+ break;
}
case NODE_OP_ASGN1:
- CHECK(compile_op_asgn1(iseq, ret, node, popped));
- break;
+ CHECK(compile_op_asgn1(iseq, ret, node, popped));
+ break;
case NODE_OP_ASGN2:
- CHECK(compile_op_asgn2(iseq, ret, node, popped));
- break;
+ CHECK(compile_op_asgn2(iseq, ret, node, popped));
+ break;
case NODE_OP_CDECL:
- CHECK(compile_op_cdecl(iseq, ret, node, popped));
- break;
+ CHECK(compile_op_cdecl(iseq, ret, node, popped));
+ break;
case NODE_OP_ASGN_AND:
case NODE_OP_ASGN_OR:
- CHECK(compile_op_log(iseq, ret, node, popped, type));
- break;
+ 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, node, popped) == TRUE) {
@@ -9332,271 +9642,272 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
break;
case NODE_SUPER:
case NODE_ZSUPER:
- CHECK(compile_super(iseq, ret, node, popped, type));
- break;
+ 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, 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, 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;
+ CHECK(compile_return(iseq, ret, node, popped));
+ break;
case NODE_YIELD:
- CHECK(compile_yield(iseq, ret, node, popped));
- break;
+ CHECK(compile_yield(iseq, ret, node, popped));
+ break;
case NODE_LVAR:{
- if (!popped) {
- compile_lvar(iseq, ret, 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, 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, node, getglobal, ID2SYM(node->nd_entry));
- if (popped) {
- ADD_INSN(ret, 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, 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++;
+ debugi("nd_vid", node->nd_vid);
- ADD_INSN2(ret, node, opt_getinlinecache, lend, INT2FIX(ic_index));
- ADD_INSN1(ret, node, putobject, Qtrue);
- ADD_INSN1(ret, node, getconstant, ID2SYM(node->nd_vid));
- ADD_INSN1(ret, node, opt_setinlinecache, INT2FIX(ic_index));
- ADD_LABEL(ret, lend);
- }
- else {
- ADD_INSN(ret, node, putnil);
+ 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;
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ break;
}
case NODE_CVAR:{
- if (!popped) {
- ADD_INSN2(ret, 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, node, putnil);
- break;
- }
- ADD_INSN2(ret, 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, 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:
- CHECK(compile_match(iseq, ret, node, popped, type));
- break;
+ CHECK(compile_match(iseq, ret, node, popped, type));
+ break;
case NODE_LIT:{
- debugp_param("lit", node->nd_lit);
- if (!popped) {
- ADD_INSN1(ret, 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, 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, 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, node, pop);
- }
- break;
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ break;
}
case NODE_XSTR:{
- ADD_CALL_RECEIVER(ret, node);
+ ADD_CALL_RECEIVER(ret, node);
VALUE str = rb_fstring(node->nd_lit);
- ADD_INSN1(ret, node, putobject, str);
+ ADD_INSN1(ret, node, putobject, str);
RB_OBJ_WRITTEN(iseq, Qundef, str);
- ADD_CALL(ret, node, idBackquote, INT2FIX(1));
+ ADD_CALL(ret, node, idBackquote, INT2FIX(1));
- if (popped) {
- ADD_INSN(ret, node, pop);
- }
- break;
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ break;
}
case NODE_DXSTR:{
- 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;
+ 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, 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, 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, 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, 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;
+ 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, "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;
+ 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, node, splatarray, Qtrue);
+ CHECK(COMPILE(ret, "splat", node->nd_head));
+ ADD_INSN1(ret, node, splatarray, Qtrue);
- if (popped) {
- ADD_INSN(ret, 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));
+ 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, node, putobject, ID2SYM(mid));
- }
+ }
- break;
+ break;
}
case NODE_DEFS:{
ID mid = node->nd_mid;
@@ -9612,206 +9923,206 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
if (!popped) {
ADD_INSN1(ret, node, putobject, ID2SYM(mid));
}
- break;
+ break;
}
case NODE_ALIAS:{
- ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
- ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
- CHECK(COMPILE(ret, "alias arg1", node->nd_1st));
- CHECK(COMPILE(ret, "alias arg2", node->nd_2nd));
- ADD_SEND(ret, node, id_core_set_method_alias, INT2FIX(3));
-
- if (popped) {
- ADD_INSN(ret, 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, 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;
+ 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, 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;
+ 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, 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, 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, node, putnil); /* dummy */
- ADD_INSN3(ret, 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, 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, node, putnil);
- CONST_ID(singletonclass, "singletonclass");
- ADD_INSN3(ret, 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, node, pop);
- }
- break;
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ break;
}
case NODE_COLON2:
- CHECK(compile_colon2(iseq, ret, node, popped));
- break;
+ CHECK(compile_colon2(iseq, ret, node, popped));
+ break;
case NODE_COLON3:
- CHECK(compile_colon3(iseq, ret, node, popped));
- break;
+ CHECK(compile_colon3(iseq, ret, node, popped));
+ break;
case NODE_DOT2:
- CHECK(compile_dots(iseq, ret, node, popped, FALSE));
- break;
+ CHECK(compile_dots(iseq, ret, node, popped, FALSE));
+ break;
case NODE_DOT3:
- CHECK(compile_dots(iseq, ret, node, popped, TRUE));
- break;
+ 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, node, putobject, Qtrue);
- ADD_INSNL(ret, node, jump, lend);
- ADD_LABEL(ret, lfalse);
- ADD_INSN1(ret, 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, node, putself);
- }
- break;
+ if (!popped) {
+ ADD_INSN(ret, node, putself);
+ }
+ break;
}
case NODE_NIL:{
- if (!popped) {
- ADD_INSN(ret, node, putnil);
- }
- break;
+ if (!popped) {
+ ADD_INSN(ret, node, putnil);
+ }
+ break;
}
case NODE_TRUE:{
- if (!popped) {
- ADD_INSN1(ret, node, putobject, Qtrue);
- }
- break;
+ if (!popped) {
+ ADD_INSN1(ret, node, putobject, Qtrue);
+ }
+ break;
}
case NODE_FALSE:{
- if (!popped) {
- ADD_INSN1(ret, node, putobject, Qfalse);
- }
- break;
+ if (!popped) {
+ ADD_INSN1(ret, node, putobject, Qfalse);
+ }
+ break;
}
case NODE_ERRINFO:
- CHECK(compile_errinfo(iseq, ret, node, popped));
- break;
+ 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, 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, node, pop);
- }
- break;
+ if (popped) {
+ ADD_INSN(ret, node, pop);
+ }
+ break;
}
case NODE_KW_ARG:
- CHECK(compile_kw_arg(iseq, ret, node, popped));
- break;
+ CHECK(compile_kw_arg(iseq, ret, node, popped));
+ break;
case NODE_DSYM:{
- compile_dstr(iseq, ret, node);
- if (!popped) {
- ADD_INSN(ret, node, intern);
- }
- else {
- ADD_INSN(ret, 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;
+ 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, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
- ADD_CALL_WITH_BLOCK(ret, 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, 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();
@@ -9839,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);
}
@@ -9860,86 +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_ICVARC: /* inline cvar 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;
}
@@ -9961,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);
@@ -10012,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);
}
@@ -10025,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;
@@ -10042,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;
@@ -10062,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 (NIL_P(RARRAY_AREF(v, 1))) {
- eiseq = NULL;
- }
- else {
+ eiseq = NULL;
+ }
+ else {
eiseq = rb_iseqw_to_iseq(rb_iseq_load(RARRAY_AREF(v, 1), (VALUE)iseq, Qnil));
}
@@ -10089,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;
}
@@ -10113,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;
@@ -10126,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);
@@ -10148,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);
@@ -10181,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);
@@ -10209,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
@@ -10263,95 +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(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->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)->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);
@@ -10367,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;
}
@@ -10388,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;
@@ -10421,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;
@@ -10446,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)
{
@@ -10472,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;
}
@@ -10502,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;
@@ -10517,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
}
@@ -10553,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);
@@ -10608,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 */
@@ -10619,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;
}
@@ -10644,14 +10971,14 @@ 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;
}
@@ -10670,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 3
+#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
@@ -10701,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;
@@ -11081,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);
@@ -11111,17 +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:
+ {
+ 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:
- case TS_ISE:
{
- 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:
@@ -11158,14 +11484,25 @@ 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 unsigned int insn_index = code_index;
const char *types = insn_op_types(insn);
int op_index;
@@ -11182,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;
}
@@ -11201,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:
@@ -11212,25 +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:
- case TS_ICVARC:
{
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);
- if (insn == BIN(opt_getinlinecache) && operand_type == TS_IC) {
- // Store the instruction index for opt_getinlinecache on the IC for
- // YJIT to invalidate code when opt_setinlinecache runs.
- is_entries[op].ic_cache.get_insn_idx = insn_index;
+ 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:
{
@@ -11258,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;
@@ -11269,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);
@@ -11296,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;
@@ -11348,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);
@@ -11414,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;
@@ -11447,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);
@@ -11486,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);
@@ -11504,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;
@@ -11553,7 +11927,7 @@ dump_outer_variable(ID id, VALUE val, void *dump)
static ibf_offset_t
ibf_dump_outer_variables(struct ibf_dump *dump, const rb_iseq_t *iseq)
{
- struct rb_id_table * ovs = iseq->body->outer_variables;
+ struct rb_id_table * ovs = ISEQ_BODY(iseq)->outer_variables;
ibf_offset_t offset = ibf_dump_pos(dump);
@@ -11642,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);
@@ -11664,16 +12038,16 @@ 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 mandatory_only_iseq_index = ibf_dump_iseq(dump, iseq->body->mandatory_only_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);
@@ -11741,7 +12115,10 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq)
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);
@@ -11784,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;
@@ -11830,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);
@@ -11849,12 +12226,51 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
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;
@@ -11877,7 +12293,6 @@ 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;
@@ -11895,7 +12310,11 @@ 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);
@@ -11920,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));
@@ -11954,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
@@ -11977,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;
@@ -12066,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;
}
@@ -12127,11 +12522,11 @@ 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:
@@ -12249,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++) {
@@ -12257,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;
}
@@ -12361,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;
@@ -12645,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;
@@ -12705,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
@@ -12729,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))) {
@@ -12788,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);
@@ -12814,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
@@ -12854,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;
+ }
}
}
@@ -12878,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 92f4e812d6..a227cb0a58 100644
--- a/complex.c
+++ b/complex.c
@@ -97,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);
}
@@ -152,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);
}
@@ -262,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);
}
@@ -270,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);
}
@@ -280,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);
}
@@ -316,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)) {
@@ -329,7 +329,7 @@ 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))
@@ -349,7 +349,7 @@ f_finite_p(VALUE x)
return TRUE;
}
else if (RB_FLOAT_TYPE_P(x)) {
- return isfinite(RFLOAT_VALUE(x));
+ return isfinite(RFLOAT_VALUE(x));
}
return RTEST(rb_funcallv(x, id_finite_p, 0, 0));
}
@@ -361,7 +361,7 @@ f_infinite_p(VALUE x)
return FALSE;
}
else if (RB_FLOAT_TYPE_P(x)) {
- return isinf(RFLOAT_VALUE(x));
+ return isinf(RFLOAT_VALUE(x));
}
return RTEST(rb_funcallv(x, id_infinite_p, 0, 0));
}
@@ -421,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
@@ -439,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));
}
}
@@ -480,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);
}
@@ -550,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);
@@ -580,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)));
}
}
@@ -595,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
@@ -665,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);
@@ -694,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);
}
/*
@@ -760,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));
}
/*
@@ -779,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, '+');
}
@@ -813,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);
}
@@ -847,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),
@@ -873,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);
@@ -922,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);
@@ -986,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);
@@ -1051,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_BIGNUM_TYPE_P(other))
- 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);
}
@@ -1084,15 +1092,15 @@ 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 RBOOL(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 RBOOL(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 RBOOL(f_eqeq_p(other, self));
}
@@ -1101,7 +1109,7 @@ static bool
nucomp_real_p(VALUE self)
{
get_dat1(self);
- return(f_zero_p(dat->imag) ? true : false);
+ return f_zero_p(dat->imag);
}
/*
@@ -1121,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;
}
@@ -1139,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;
}
@@ -1164,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);
}
@@ -1192,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));
}
/*
@@ -1313,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: */
@@ -1346,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 RBOOL((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;
@@ -1360,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);
}
@@ -1387,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;
@@ -1470,7 +1489,7 @@ rb_complex_infinite_p(VALUE self)
get_dat1(self);
if (!f_infinite_p(dat->real) && !f_infinite_p(dat->imag)) {
- return Qnil;
+ return Qnil;
}
return ONE;
}
@@ -1513,7 +1532,7 @@ 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;
@@ -1575,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);
}
@@ -1598,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);
}
@@ -1623,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);
}
@@ -1703,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;
}
@@ -1723,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;
}
@@ -1760,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;
}
@@ -1831,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;
@@ -1857,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" */
}
}
@@ -1930,7 +1949,7 @@ inline static void
skip_ws(const char **s)
{
while (isspace((unsigned char)**s))
- (*s)++;
+ (*s)++;
}
static int
@@ -1971,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;
@@ -2013,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
@@ -2026,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);
@@ -2050,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;
}
@@ -2118,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);
}
}
@@ -2136,31 +2164,6 @@ nucomp_s_convert(int argc, VALUE *argv, VALUE klass)
/*
* 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
*
* Returns square of self.
@@ -2232,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
@@ -2255,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);
}
@@ -2408,9 +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);
@@ -2418,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);
@@ -2429,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 b63e395091..220392d120 100644
--- a/configure.ac
+++ b/configure.ac
@@ -32,8 +32,10 @@ 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
@@ -62,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)
@@ -86,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\" = ''"], [
@@ -98,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=
@@ -118,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
@@ -196,15 +214,23 @@ AS_CASE(["/${rb_CC} "],
[*clang*], [
# Ditto for LLVM. Note however that llvm-as is a LLVM-IR to LLVM bitcode
# assembler that does not target your machine native binary.
- : ${LD:="${CC}"} # ... try -fuse-ld=lld ?
- RUBY_CHECK_PROG_FOR_CC([AR], [s/clang/llvm-ar/])
-# RUBY_CHECK_PROG_FOR_CC([AS], [s/clang/llvm-as/])
+
+ # 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-nm/])
- RUBY_CHECK_PROG_FOR_CC([OBJCOPY], [s/clang/llvm-objcopy/])
- RUBY_CHECK_PROG_FOR_CC([OBJDUMP], [s/clang/llvm-objdump/])
- RUBY_CHECK_PROG_FOR_CC([RANLIB], [s/clang/llvm-ranlib/])
- RUBY_CHECK_PROG_FOR_CC([STRIP], [s/clang/llvm-strip/])
+ 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)
@@ -345,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
@@ -364,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
@@ -478,6 +510,7 @@ AS_CASE(["$target_os"],
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>
@@ -485,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"], [
@@ -505,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([[
@@ -592,22 +625,39 @@ RUBY_WERROR_FLAG([
cd .. && rm -fr tmp.$$.try_link
])
-: ${RPATHFLAG=''}
-rpathflag=''
-AS_IF([test x"${RPATHFLAG}" = x], [
- AS_CASE(["$target_os"],
+: "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], [
@@ -620,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
@@ -633,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=
@@ -644,6 +695,7 @@ 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=div-by-zero \
-Werror=duplicated-cond \
@@ -748,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>])
])
@@ -756,7 +809,7 @@ AS_IF([test "$GCC" = yes], [
# -fstack-protector
AS_CASE(["$target_os"],
- [mingw*|emscripten*|wasi*], [
+ [emscripten*|wasi*], [
stack_protector=no
])
AS_IF([test -z "${stack_protector+set}"], [
@@ -768,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},
@@ -822,33 +888,6 @@ AS_IF([test "$GCC" = yes], [
# need lgamma_r()
])
- # 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
- ])
- ])
-
# suppress annoying -Wstrict-overflow warnings
RUBY_TRY_CFLAGS(-fno-strict-overflow, [RUBY_APPEND_OPTION(XCFLAGS, -fno-strict-overflow)])
@@ -857,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)
@@ -914,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\""
@@ -949,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])
@@ -1006,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
@@ -1169,22 +1197,18 @@ main()
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], [], [],
@@ -1267,21 +1291,17 @@ 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(socket, shutdown) # SunOS/Solaris
-AS_IF([test -n "${PKG_CONFIG}" && ${PKG_CONFIG} --exists capstone], [
- CAPSTONE_CFLAGS=`${PKG_CONFIG} --cflags capstone`
- CAPSTONE_LIB_L=`${PKG_CONFIG} --libs-only-L capstone`
- LDFLAGS="$LDFLAGS $CAPSTONE_LIB_L"
- CFLAGS="$CFLAGS $CAPSTONE_CFLAGS"
-])
-
-AC_CHECK_LIB(capstone, cs_open) # Capstone disassembler for debugging YJIT
-
dnl Checks for header files.
AC_HEADER_DIRENT
dnl AC_HEADER_STDC has been checked in AC_USE_SYSTEM_EXTENSIONS
AC_HEADER_STDBOOL
AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS([afunix.h], [], [],
+[#ifdef _WIN32
+# include <winsock2.h>
+#endif
+])
AC_CHECK_HEADERS(atomic.h)
AC_CHECK_HEADERS(copyfile.h)
AC_CHECK_HEADERS(direct.h)
@@ -1328,16 +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],
@@ -1349,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])
@@ -1380,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],
@@ -1900,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)
@@ -1909,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
@@ -1943,17 +1964,11 @@ 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])])
-])
-
# dup and dup2 are always available except for WASI
AS_CASE(["$target_os"],
[wasi*], [],
[
- m4_map_args_w([dup dup2], [RUBY_REQUIRE_FUNC(], [)])
+ RUBY_REQUIRE_FUNCS(dup dup2)
]
)
@@ -1996,6 +2011,7 @@ AC_CHECK_FUNCS(_longjmp) # used for AC_ARG_WITH(setjmp-type)
test x$ac_cv_func__longjmp = xno && ac_cv_func__setjmp=no
AC_CHECK_FUNCS(arc4random_buf)
AC_CHECK_FUNCS(atan2l atan2f)
+AC_CHECK_DECLS(atomic_signal_fence, [], [], [#include <stdatomic.h>])
AC_CHECK_FUNCS(chmod)
AC_CHECK_FUNCS(chown)
AC_CHECK_FUNCS(chroot)
@@ -2285,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)
@@ -2383,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>
@@ -2462,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
])
@@ -2586,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 ],
@@ -2673,25 +2698,7 @@ 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>
@@ -2780,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>
@@ -2907,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])
@@ -2989,13 +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"],
+: "rpath" && {
+ AS_CASE(["$target_os"],
[solaris*], [ AS_IF([test "$GCC" = yes], [
: ${LDSHARED='$(CC) -shared'}
AS_IF([test "$rb_cv_prog_gnu_ld" = yes], [
@@ -3035,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'}
@@ -3054,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], [
@@ -3087,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}"],
@@ -3126,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)
@@ -3135,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])
@@ -3166,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])
@@ -3295,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])
@@ -3361,7 +3360,6 @@ for var in bindir includedir libdir rubylibprefix; do
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"]']`
@@ -3371,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)'
@@ -3384,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
])
@@ -3396,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=""
@@ -3635,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)]
)
])
@@ -3750,12 +3750,12 @@ 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],
- # Enable mjit by default except for WASI
- [AS_IF([test x"$target_os" != "xwasi"],
- [MJIT_SUPPORT=yes],
- [MJIT_SUPPORT=no ])])
+ 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)],
@@ -3763,6 +3763,116 @@ AS_IF([test x"$MJIT_SUPPORT" = "xyes"],
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
@@ -3799,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])
@@ -3873,8 +3996,6 @@ AS_CASE(["$target_os"],
MINIOBJS="$MINIDLNOBJ"
-RUBY_THREAD
-
AC_ARG_ENABLE(debug-env,
AS_HELP_STRING([--enable-debug-env], [enable RUBY_DEBUG environment variable]),
[AC_SUBST(ENABLE_DEBUG_ENV, yes)])
@@ -4015,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/:.*//'`
@@ -4075,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"'
@@ -4246,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])
@@ -4306,6 +4436,14 @@ 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"])
])
@@ -4322,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'
])
@@ -4350,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]),
@@ -4401,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"
@@ -4414,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 667e6846b3..5375d1945b 100644
--- a/cont.c
+++ b/cont.c
@@ -29,11 +29,15 @@ extern int madvise(caddr_t, size_t, int);
#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"
@@ -66,6 +70,8 @@ static VALUE rb_cFiberPool;
#define FIBER_POOL_ALLOCATION_FREE
#endif
+#define jit_cont_enabled (mjit_enabled || rb_yjit_enabled_p())
+
enum context_type {
CONTINUATION_CONTEXT = 0,
FIBER_CONTEXT = 1
@@ -194,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;
@@ -211,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;
@@ -258,7 +272,7 @@ 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
@@ -274,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)
{
@@ -285,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)
@@ -634,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;
@@ -659,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.
@@ -698,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
@@ -714,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);
}
@@ -751,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
@@ -791,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)
{
@@ -958,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)
{
@@ -978,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);
@@ -1085,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;
}
@@ -1120,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);
}
@@ -1144,13 +1219,110 @@ 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
-cont_init_mjit_cont(rb_context_t *cont)
+jit_cont_free(struct rb_jit_cont *cont)
{
- VM_ASSERT(cont->mjit_cont == NULL);
- if (mjit_enabled) {
- cont->mjit_cont = mjit_cont_new(&(cont->saved_ec));
+ 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_jit_cont(rb_context_t *cont)
+{
+ VM_ASSERT(cont->jit_cont == NULL);
+ if (jit_cont_enabled) {
+ cont->jit_cont = jit_cont_new(&(cont->saved_ec));
+ }
+}
+
+struct rb_execution_context_struct *
+rb_fiberptr_get_ec(struct rb_fiber_struct *fiber)
+{
+ return &fiber->cont.saved_ec;
}
static void
@@ -1162,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 *
@@ -1191,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
@@ -1218,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)
{
@@ -1272,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;
@@ -1293,7 +1466,6 @@ cont_capture(volatile int *volatile stat)
return contval;
}
}
-COMPILER_WARNING_POP
static inline void
cont_restore_thread(rb_context_t *cont)
@@ -1379,9 +1551,17 @@ fiber_setcontext(rb_fiber_t *new_fiber, rb_fiber_t *old_fiber)
// 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");
}
@@ -1401,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;
@@ -1441,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]);
@@ -1652,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);
}
}
@@ -1777,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
@@ -1828,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
+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
-fiber_initialize(VALUE self, VALUE proc, struct fiber_pool * fiber_pool, unsigned int blocking)
+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;
@@ -1865,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)
@@ -1921,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
@@ -1934,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!");
@@ -1977,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
@@ -1996,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).
*
*/
@@ -2030,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.
@@ -2097,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)
{
@@ -2130,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
@@ -2167,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();
@@ -2353,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);
+ }
}
/*
@@ -2439,9 +2888,7 @@ fiber_resume_kw(rb_fiber_t *fiber, 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, false);
-
- return result;
+ return fiber_switch(fiber, argc, argv, kw_splat, fiber, false);
}
VALUE
@@ -2893,329 +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, #io_read, and #io_write
- * * #process_wait
- * * #kernel_sleep
- * * #timeout_after
- * * #address_resolve
- * * #block and #unblock
- * * (the list is expanded as Ruby developers make more methods having non-blocking calls)
- *
- * When not specified otherwise, the hook implementations are mandatory: if they are not
- * implemented, the methods trying to call hook will fail. To provide backward compatibility,
- * in the future hooks will be optional (if they are not implemented, due to the scheduler
- * being created for the older Ruby version, the code which needs this hook will not fail,
- * and will just behave in a blocking fashion).
- *
- * It is also strongly recommended that the scheduler implements the #fiber method, which is
- * delegated to by Fiber.schedule.
- *
- * Sample _toy_ implementation of the scheduler can be found in Ruby's code, in
- * <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#io_read
- * call-seq: io_read(io, buffer, length) -> read length or -errno
- *
- * Invoked by IO#read to read +length+ bytes from +io+ into a specified
- * +buffer+ (see IO::Buffer).
- *
- * The +length+ argument is the "minimum length to be read".
- * If the IO buffer size is 8KiB, but the +length+ is +1024+ (1KiB), up to
- * 8KiB might be read, but at least 1KiB will be.
- * Generally, the only case where less data than +length+ will be read is if
- * there is an error reading the data.
- *
- * Specifying a +length+ of 0 is valid and means try reading at least once
- * and return any available data.
- *
- * Suggested implementation should try to read from +io+ in a non-blocking
- * manner and call #io_wait if the +io+ is not ready (which will yield control
- * to other fibers).
- *
- * See IO::Buffer for an interface available to return data.
- *
- * Expected to return number of bytes read, or, in case of an error, <tt>-errno</tt>
- * (negated number corresponding to system's error code).
- *
- * The method should be considered _experimental_.
- */
-static VALUE
-rb_fiber_scheduler_interface_io_read(VALUE self)
-{
-}
-
-/*
- * Document-method: SchedulerInterface#io_write
- * call-seq: io_write(io, buffer, length) -> written length or -errno
- *
- * Invoked by IO#write to write +length+ bytes to +io+ from
- * from a specified +buffer+ (see IO::Buffer).
- *
- * The +length+ argument is the "(minimum) length to be written".
- * If the IO buffer size is 8KiB, but the +length+ specified is 1024 (1KiB),
- * at most 8KiB will be written, but at least 1KiB will be.
- * Generally, the only case where less data than +length+ will be written is if
- * there is an error writing the data.
- *
- * Specifying a +length+ of 0 is valid and means try writing at least once,
- * as much data as possible.
- *
- * Suggested implementation should try to write to +io+ in a non-blocking
- * manner and call #io_wait if the +io+ is not ready (which will yield control
- * to other fibers).
- *
- * See IO::Buffer for an interface available to get data from buffer efficiently.
- *
- * Expected to return number of bytes written, or, in case of an error, <tt>-errno</tt>
- * (negated number corresponding to system's error code).
- *
- * The method should be considered _experimental_.
- */
-static VALUE
-rb_fiber_scheduler_interface_io_write(VALUE self)
-{
-}
-
-/*
- * Document-method: SchedulerInterface#kernel_sleep
- * call-seq: kernel_sleep(duration = nil)
- *
- * Invoked by Kernel#sleep and Mutex#sleep and is expected to provide
- * an implementation of sleeping in a non-blocking way. Implementation might
- * register the current fiber in some list of "which fiber wait until what
- * moment", call Fiber.yield to pass control, and then in #close resume
- * the fibers whose wait period has elapsed.
- *
- */
-static VALUE
-rb_fiber_scheduler_interface_kernel_sleep(VALUE self)
-{
-}
-
-/*
- * Document-method: SchedulerInterface#address_resolve
- * call-seq: address_resolve(hostname) -> array_of_strings or nil
- *
- * Invoked by any method that performs a non-reverse DNS lookup. The most
- * notable method is Addrinfo.getaddrinfo, but there are many other.
- *
- * The method is expected to return an array of strings corresponding to ip
- * addresses the +hostname+ is resolved to, or +nil+ if it can not be resolved.
- *
- * Fairly exhaustive list of all possible call-sites:
- *
- * - Addrinfo.getaddrinfo
- * - Addrinfo.tcp
- * - Addrinfo.udp
- * - Addrinfo.ip
- * - Addrinfo.new
- * - Addrinfo.marshal_load
- * - SOCKSSocket.new
- * - TCPServer.new
- * - TCPSocket.new
- * - IPSocket.getaddress
- * - TCPSocket.gethostbyname
- * - UDPSocket#connect
- * - UDPSocket#bind
- * - UDPSocket#send
- * - Socket.getaddrinfo
- * - Socket.gethostbyname
- * - Socket.pack_sockaddr_in
- * - Socket.sockaddr_in
- * - Socket.unpack_sockaddr_in
- */
-static VALUE
-rb_fiber_scheduler_interface_address_resolve(VALUE self)
-{
-}
-
-/*
- * Document-method: SchedulerInterface#timeout_after
- * call-seq: timeout_after(duration, exception_class, *exception_arguments, &block) -> result of block
- *
- * Invoked by Timeout.timeout to execute the given +block+ within the given
- * +duration+. It can also be invoked directly by the scheduler or user code.
- *
- * Attempt to limit the execution time of a given +block+ to the given
- * +duration+ if possible. When a non-blocking operation causes the +block+'s
- * execution time to exceed the specified +duration+, that non-blocking
- * operation should be interrupted by raising the specified +exception_class+
- * constructed with the given +exception_arguments+.
- *
- * General execution timeouts are often considered risky. This implementation
- * will only interrupt non-blocking operations. This is by design because it's
- * expected that non-blocking operations can fail for a variety of
- * unpredictable reasons, so applications should already be robust in handling
- * these conditions and by implication timeouts.
- *
- * However, as a result of this design, if the +block+ does not invoke any
- * non-blocking operations, it will be impossible to interrupt it. If you
- * desire to provide predictable points for timeouts, consider adding
- * +sleep(0)+.
- *
- * If the block is executed successfully, its result will be returned.
- *
- * The exception will typically be raised using Fiber#raise.
- */
-static VALUE
-rb_fiber_scheduler_interface_timeout_after(VALUE self)
-{
-}
-
-/*
- * Document-method: SchedulerInterface#block
- * call-seq: block(blocker, timeout = nil)
- *
- * Invoked by methods like Thread.join, and by Mutex, to signify that current
- * Fiber is blocked until further notice (e.g. #unblock) or until +timeout+ has
- * elapsed.
- *
- * +blocker+ is what we are waiting on, informational only (for debugging and
- * logging). There are no guarantee about its value.
- *
- * Expected to return boolean, specifying whether the blocking operation was
- * successful or not.
- */
-static VALUE
-rb_fiber_scheduler_interface_block(VALUE self)
-{
-}
-
-/*
- * Document-method: SchedulerInterface#unblock
- * call-seq: unblock(blocker, fiber)
- *
- * Invoked to wake up Fiber previously blocked with #block (for example, Mutex#lock
- * calls #block and Mutex#unlock calls #unblock). The scheduler should use
- * the +fiber+ parameter to understand which fiber is unblocked.
- *
- * +blocker+ is what was awaited for, but it is informational only (for debugging
- * and logging), and it is not guaranteed to be the same value as the +blocker+ for
- * #block.
- *
- */
-static VALUE
-rb_fiber_scheduler_interface_unblock(VALUE self)
-{
-}
-
-/*
- * Document-method: SchedulerInterface#fiber
- * call-seq: fiber(&block)
- *
- * Implementation of the Fiber.schedule. The method is <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)
{
@@ -3237,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) {
@@ -3248,8 +3373,14 @@ 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_m_raise, -1);
rb_define_method(rb_cFiber, "backtrace", rb_fiber_backtrace, -1);
@@ -3266,21 +3397,6 @@ 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, "io_read", rb_fiber_scheduler_interface_io_read, 0);
- rb_define_method(rb_cFiberScheduler, "io_write", rb_fiber_scheduler_interface_io_write, 0);
- rb_define_method(rb_cFiberScheduler, "kernel_sleep", rb_fiber_scheduler_interface_kernel_sleep, 0);
- rb_define_method(rb_cFiberScheduler, "address_resolve", rb_fiber_scheduler_interface_address_resolve, 0);
- rb_define_method(rb_cFiberScheduler, "timeout_after", rb_fiber_scheduler_interface_timeout_after, 0);
- rb_define_method(rb_cFiberScheduler, "block", rb_fiber_scheduler_interface_block, 0);
- rb_define_method(rb_cFiberScheduler, "unblock", rb_fiber_scheduler_interface_unblock, 0);
- rb_define_method(rb_cFiberScheduler, "fiber", rb_fiber_scheduler_interface_fiber, 0);
-#endif
-
#ifdef RB_EXPERIMENTAL_FIBER_POOL
rb_cFiberPool = rb_define_class_under(rb_cFiber, "Pool", rb_cObject);
rb_define_alloc_func(rb_cFiberPool, fiber_pool_alloc);
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.h b/coroutine/asyncify/Context.h
index 7dba829a1d..71791a4004 100644
--- a/coroutine/asyncify/Context.h
+++ b/coroutine/asyncify/Context.h
@@ -13,6 +13,7 @@
#include <stddef.h>
#include <stdio.h>
+#include <stdint.h>
#include "wasm/asyncify.h"
#include "wasm/machine.h"
#include "wasm/fiber.h"
@@ -47,10 +48,13 @@ static inline void coroutine_initialize_main(struct coroutine_context * context)
static inline void coroutine_initialize(struct coroutine_context *context, coroutine_start start, void *stack, size_t size)
{
- if (ASYNCIFY_CORO_DEBUG) fprintf(stderr, "[%s] entry (context = %p, stack = %p ... %p)\n", __func__, context, stack, (char *)stack + size);
+ // Linear stack pointer must be always aligned down to 16 bytes.
+ // https://github.com/WebAssembly/tool-conventions/blob/c74267a5897c1bdc9aa60adeaf41816387d3cd12/BasicCABI.md#the-linear-stack
+ uintptr_t sp = ((uintptr_t)stack + size) & ~0xF;
+ if (ASYNCIFY_CORO_DEBUG) fprintf(stderr, "[%s] entry (context = %p, stack = %p ... %p)\n", __func__, context, stack, (char *)sp);
rb_wasm_init_context(&context->fc, coroutine_trampoline, start, context);
// record the initial stack pointer position to restore it after resumption
- context->current_sp = (char *)stack + size;
+ context->current_sp = (char *)sp;
context->stack_base = stack;
context->size = size;
}
diff --git a/coroutine/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 b13c3d9c8a..f342d2fcf7 100644
--- a/cygwin/GNUmakefile.in
+++ b/cygwin/GNUmakefile.in
@@ -2,15 +2,17 @@ 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)
@@ -38,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
@@ -47,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 $@
@@ -78,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
@@ -89,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
index bb8199a98c..c9a53f1e01 100644
--- a/darray.h
+++ b/darray.h
@@ -41,20 +41,9 @@
//
// void rb_darray_append(rb_darray(T) *ptr_to_ary, T element);
//
-// TODO: replace this with rb_darray_append_with_gc when YJIT moves to Rust.
-//
#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]), realloc); \
- rb_darray_set(*(ptr_to_ary), \
- (*(ptr_to_ary))->meta.size, \
- (element)); \
- (*(ptr_to_ary))->meta.size++; \
-} while (0)
-
-#define rb_darray_append_with_gc(ptr_to_ary, element) do { \
- rb_darray_ensure_space((ptr_to_ary), sizeof(**(ptr_to_ary)), \
- sizeof((*(ptr_to_ary))->data[0]), ruby_xrealloc); \
+ sizeof((*(ptr_to_ary))->data[0])); \
rb_darray_set(*(ptr_to_ary), \
(*(ptr_to_ary))->meta.size, \
(element)); \
@@ -87,22 +76,14 @@
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.
-// Return 1 on success and 0 on failure.
//
// Note that NULL is a valid empty dynamic array.
//
// void rb_darray_make(rb_darray(T) *ptr_to_ary, size_t size);
//
-// TODO: replace this with rb_darray_make_with_gc with YJIT moves to Rust.
-//
#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]), calloc)
-
-
-#define rb_darray_make_with_gc(ptr_to_ary, size) \
- rb_darray_make_impl((ptr_to_ary), size, sizeof(**(ptr_to_ary)), \
- sizeof((*(ptr_to_ary))->data[0]), ruby_xcalloc)
+ sizeof((*(ptr_to_ary))->data[0]))
#define rb_darray_data_ptr(ary) ((ary)->data)
@@ -136,34 +117,18 @@ rb_darray_capa(const void *ary)
// Free the dynamic array.
//
-// TODO: replace this with rb_darray_free_with_gc when YJIT moves to Rust.
-//
static inline void
rb_darray_free(void *ary)
{
- free(ary);
-}
-
-static inline void
-rb_darray_free_with_gc(void *ary)
-{
rb_darray_meta_t *meta = ary;
ruby_sized_xfree(ary, meta->capa);
}
-// Internal function. Calculate buffer size on malloc heap.
-static inline size_t
-rb_darray_buffer_size(size_t capacity, size_t header_size, size_t element_size)
-{
- if (capacity == 0) return 0;
- return header_size + capacity * element_size;
-}
-
// 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, void *(*realloc_impl)(void *, size_t))
+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;
@@ -173,18 +138,9 @@ rb_darray_ensure_space(void *ptr_to_ary, size_t header_size, size_t element_size
// Double the capacity
size_t new_capa = current_capa == 0 ? 1 : current_capa * 2;
- // Calculate new buffer size
- size_t current_buffer_size = rb_darray_buffer_size(current_capa, header_size, element_size);
- size_t new_buffer_size = rb_darray_buffer_size(new_capa, header_size, element_size);
- if (new_buffer_size <= current_buffer_size) {
- rb_bug("rb_darray_ensure_space: overflow");
- }
-
- // TODO: replace with rb_xrealloc_mul_add(meta, new_capa, element_size, header_size);
- rb_darray_meta_t *doubled_ary = realloc_impl(meta, new_buffer_size);
- if (!doubled_ary) {
- rb_bug("rb_darray_ensure_space: failed");
- }
+ 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
@@ -200,7 +156,7 @@ rb_darray_ensure_space(void *ptr_to_ary, size_t header_size, size_t element_size
}
static inline void
-rb_darray_make_impl(void *ptr_to_ary, size_t array_size, size_t header_size, size_t element_size, void *(*calloc_impl)(size_t, size_t))
+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) {
@@ -208,12 +164,9 @@ rb_darray_make_impl(void *ptr_to_ary, size_t array_size, size_t header_size, siz
return;
}
- // TODO: replace with rb_xcalloc_mul_add(array_size, element_size, header_size)
- size_t buffer_size = rb_darray_buffer_size(array_size, header_size, element_size);
- rb_darray_meta_t *meta = calloc_impl(buffer_size, 1);
- if (!meta) {
- rb_bug("rb_darray_make_impl: failed");
- }
+ 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;
diff --git a/debug.c b/debug.c
index 95a994e63c..3dd0f71906 100644
--- a/debug.c
+++ b/debug.c
@@ -53,7 +53,9 @@ const union {
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
@@ -62,23 +64,23 @@ const union {
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,
@@ -86,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;
@@ -100,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;
}
@@ -122,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;
}
@@ -141,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;
}
@@ -151,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;
}
@@ -182,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 && \
@@ -195,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);
@@ -221,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
@@ -232,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;
@@ -244,7 +246,7 @@ 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);
}
}
@@ -268,14 +270,31 @@ ruby_set_debug_option(const char *str)
#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;
@@ -287,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");
@@ -315,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;
@@ -377,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, ...)
{
@@ -410,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;
}
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 3f0dec948f..6e0b8dee60 100644
--- a/debug_counter.h
+++ b/debug_counter.h
@@ -130,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)
@@ -140,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
*
@@ -244,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)
@@ -347,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 c32fee0a6c..54fef6685f 100644
--- a/defs/gmake.mk
+++ b/defs/gmake.mk
@@ -11,11 +11,15 @@ 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))
@@ -36,15 +40,13 @@ TEST_TARGETS := $(patsubst test-short,btest-ruby test-knownbug test-basic,$(TEST
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) \
@@ -72,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)),)
@@ -81,7 +84,8 @@ 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 \
)
@@ -89,6 +93,7 @@ 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))
@@ -134,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)
@@ -160,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
@@ -180,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
@@ -194,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
@@ -221,31 +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 prune
- 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-%
@@ -254,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
@@ -278,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 \
@@ -289,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) $@
@@ -332,30 +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
-ifeq ($(wildcard $(srcdir)/revision.h),)
-REVISION_IN_HEADER := none
-REVISION_LATEST := update
+ifeq ($(HAVE_GIT),yes)
+REVISION_LATEST := $(shell $(CHDIR) $(srcdir) && $(GIT) log -1 --format=%H 2>/dev/null)
else
-REVISION_IN_HEADER := $(shell sed -n 's/^\#define RUBY_FULL_REVISION "\(.*\)"/\1/p' $(srcdir)/revision.h 2>/dev/null)
-REVISION_LATEST := $(shell $(CHDIR) $(srcdir) && git log -1 --format=%H 2>/dev/null)
+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#+
@@ -398,19 +447,19 @@ 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.
diff --git a/defs/id.def b/defs/id.def
index 097e34e405..ebf00506ea 100644
--- a/defs/id.def
+++ b/defs/id.def
@@ -58,6 +58,7 @@ firstline, predefined = __LINE__+1, %[\
quo
name
nil
+ path
_ UScore
@@ -75,6 +76,7 @@ firstline, predefined = __LINE__+1, %[\
"/*NULL*/" NULL
empty?
eql?
+ default
respond_to? Respond_to
respond_to_missing? Respond_to_missing
<IFUNC>
@@ -194,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,
@@ -212,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 8c6d6fea56..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
@@ -160,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;
@@ -175,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;
}
@@ -254,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;
@@ -338,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);
}
}
@@ -424,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;
@@ -520,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
@@ -551,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);
@@ -630,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);
}
@@ -677,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
@@ -709,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))
@@ -731,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;
@@ -766,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 */
}
}
@@ -821,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;
}
@@ -978,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;
@@ -997,7 +997,7 @@ chdir_yield(VALUE v)
args->done = TRUE;
chdir_blocking++;
if (NIL_P(chdir_thread))
- chdir_thread = rb_thread_current();
+ chdir_thread = rb_thread_current();
return rb_yield(args->new_path);
}
@@ -1006,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;
}
@@ -1063,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);
@@ -1131,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);
@@ -1174,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);
}
@@ -1195,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);
}
@@ -1238,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);
}
@@ -1280,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);
}
@@ -1386,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 : ".";
@@ -1403,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;
}
@@ -1418,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;
}
@@ -1443,9 +1443,9 @@ 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 RBOOL(rb_gc_for_fd(e));
+ return RBOOL(rb_gc_for_fd(e));
}
static void *
@@ -1457,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;
@@ -1497,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 */
@@ -1550,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;
@@ -1596,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;
@@ -1636,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;
}
@@ -1670,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);
@@ -1736,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);
}
}
@@ -1752,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';
@@ -1769,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;
@@ -1779,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;
}
@@ -1793,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;
@@ -1807,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) {
@@ -1821,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;
@@ -1856,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;
}
@@ -2003,7 +2003,7 @@ rb_glob_error(const char *path, VALUE a, const void *enc, int error)
#ifdef ENOTCAPABLE
case ENOTCAPABLE:
#endif
- errfunc = glob_func_warning;
+ errfunc = glob_func_warning;
}
args.path = path;
args.enc = enc;
@@ -2027,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;
@@ -2068,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;
}
@@ -2108,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);
@@ -2148,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;
@@ -2216,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;
@@ -2288,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)) {
@@ -2428,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;
@@ -2618,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;
}
@@ -2647,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;
@@ -2677,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;
@@ -2689,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);
@@ -2708,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
@@ -2737,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);
}
@@ -2756,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;
@@ -2766,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);
@@ -2858,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;
@@ -2868,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
@@ -2895,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();
@@ -2918,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);
@@ -2932,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);
@@ -2948,7 +2948,7 @@ dir_glob_option_base(VALUE base)
static int
dir_glob_option_sort(VALUE sort)
{
- return (rb_bool_expected(sort, "sort") ? 0 : FNM_GLOB_NOSORT);
+ return (rb_bool_expected(sort, "sort", TRUE) ? 0 : FNM_GLOB_NOSORT);
}
static VALUE
@@ -2957,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);
}
@@ -2969,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;
}
@@ -3174,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);
}
@@ -3200,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);
@@ -3244,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));
@@ -3279,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;
@@ -3324,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 RBOOL(attrbuf[1] == 0);
- 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;
}
diff --git a/dir.rb b/dir.rb
index 243dd837ed..2e426b0881 100644
--- a/dir.rb
+++ b/dir.rb
@@ -25,61 +25,61 @@
#
# === 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
diff --git a/dln.c b/dln.c
index 6fa68289dd..0edd709bbe 100644
--- a/dln.c
+++ b/dln.c
@@ -41,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();
@@ -58,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
@@ -110,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 */
@@ -126,7 +130,7 @@ 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);\
@@ -170,14 +174,14 @@ 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;
}
@@ -200,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);
}
@@ -229,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;
}
@@ -252,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)
@@ -273,7 +277,7 @@ dln_incompatible_func(void *handle, const char *funcname, void *const fp, const
if (!ex) return false;
if (ex == fp) return false;
if (dladdr(ex, &dli)) {
- *libname = dli.dli_fname;
+ *libname = dli.dli_fname;
}
return true;
}
@@ -287,15 +291,28 @@ dln_incompatible_library_p(void *handle, const char **libname)
{
#define check_func(func) \
if (dln_incompatible_func(handle, EXTERNAL_PREFIX #func, (void *)&func, libname)) \
- return true
+ return true
check_func(ruby_xmalloc);
return false;
}
COMPILER_WARNING_POP
#endif
-#if defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \
- (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_11)
+#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
@@ -308,8 +325,6 @@ dln_disable_dlclose(void)
if (rev < MAC_OS_X_VERSION_10_11) return true;
return false;
}
-#else
-# define dln_disable_dlclose() false
#endif
#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
@@ -326,7 +341,7 @@ dln_open(const char *file)
/* Convert the file path to wide char */
WCHAR *winfile = rb_w32_mbstr_to_wstr(CP_UTF8, file, -1, NULL);
if (!winfile) {
- dln_memerror();
+ dln_memerror();
}
/* Load file */
@@ -334,15 +349,15 @@ dln_open(const char *file)
free(winfile);
if (!handle) {
- error = dln_strerror();
- goto failed;
+ error = dln_strerror();
+ goto failed;
}
# if defined(RUBY_EXPORT)
if (!rb_w32_check_imported(handle, rb_libruby_handle())) {
- FreeLibrary(handle);
- error = incompatible;
- goto failed;
+ FreeLibrary(handle);
+ error = incompatible;
+ goto failed;
}
# endif
@@ -367,24 +382,24 @@ dln_open(const char *file)
# if defined(RUBY_EXPORT)
{
- 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;
- }
- }
+ 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
#endif
@@ -445,7 +460,7 @@ dln_load(const char *file)
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("ABI version of binary is incompatible with this Ruby. Try rebuilding this binary.");
+ dln_loaderror("incompatible ABI version of binary - %s", file);
}
#endif
@@ -460,17 +475,17 @@ dln_load(const char *file)
#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;
+ 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();
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 84c1be6e5e..f589dda07c 100644
--- a/doc/.document
+++ b/doc/.document
@@ -1,6 +1,9 @@
*.md
*.rb
*.rdoc
+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 ff3c376f4d..59d195e780 100644
--- a/doc/ChangeLog-0.60_to_1.1
+++ b/doc/ChangeLog-0.60_to_1.1
@@ -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 58e3b6f67d..0f80eed2d5 100644
--- a/doc/ChangeLog-1.9.3
+++ b/doc/ChangeLog-1.9.3
@@ -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>
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/NEWS/NEWS-3.0.0.md b/doc/NEWS/NEWS-3.0.0.md
index 00c26fe585..bdbd47327b 100644
--- a/doc/NEWS/NEWS-3.0.0.md
+++ b/doc/NEWS/NEWS-3.0.0.md
@@ -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/case_mapping.rdoc b/doc/case_mapping.rdoc
index 29d7bc6c33..3c42154973 100644
--- a/doc/case_mapping.rdoc
+++ b/doc/case_mapping.rdoc
@@ -28,13 +28,13 @@ In Symbol:
By default, all of these methods use full Unicode case mapping,
which is suitable for most languages.
-See {Unicode Latin Case Chart}[https://www.unicode.org/charts/case].
+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 of the Unicode standard}[https://www.unicode.org/versions/Unicode13.0.0/ch03.pdf]
+{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.
diff --git a/doc/command_injection.rdoc b/doc/command_injection.rdoc
index 8f1303bcf7..af09be23f0 100644
--- a/doc/command_injection.rdoc
+++ b/doc/command_injection.rdoc
@@ -8,7 +8,7 @@ They should not be called with unknown or unsanitized commands.
These methods include:
- Kernel.system
-- {`command` (backtick method)}[rdoc-ref:Kernel#`]
+- {\`command` (backtick method)}[rdoc-ref:Kernel#`]
(also called by the expression <tt>%x[command]</tt>).
- IO.popen(command).
- IO.read(command).
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 00875d1428..0000000000
--- a/doc/contributing.rdoc
+++ /dev/null
@@ -1,402 +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)
-
-== 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
- ./autogen.sh
- mkdir build && cd build # its good practice to build outside of source dir
- mkdir ~/.rubies # we will install to .rubies/ruby-master in our home dir
- ../configure --prefix="${HOME}/.rubies/ruby-master"
- 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 f6f7eb3710..0000000000
--- a/doc/documentation_guide.rdoc
+++ /dev/null
@@ -1,327 +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}[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 <tt>doc/*.rdoc</tt>:
-
-- For class +Foo+ (defined in file <tt>foo.c</tt>),
- create file <tt>doc/foo.rdoc</tt>, declare <tt>class Foo; end</tt>,
- and place the class documentation above that declaration:
-
- # :markup: ruby
- # Documentation for class Foo goes here.
- class Foo; end
-
-- Similarly, for module +Bar+ (defined in file <tt>bar.c</tt>,
- create file <tt>doc/bar.rdoc</tt>, declare <tt>module Bar; end</tt>,
- and place the module documentation above that declaration:
-
- # :markup: 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 documentaion.
-
- 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 <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}[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.
-
-=== 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}[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].
-
-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}[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,
-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/encoding.rdoc b/doc/encodings.rdoc
index acb0e3aa47..1f3c54d740 100644
--- a/doc/encoding.rdoc
+++ b/doc/encodings.rdoc
@@ -1,4 +1,4 @@
-== \Encoding
+== Encodings
=== The Basics
@@ -467,12 +467,13 @@ These keyword-value pairs specify encoding options:
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/line-feed string
+ - <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\n" # => "\n \r\n"
- s.encode('ASCII', cr_newline: true) # => "\r \r\r"
- s.encode('ASCII', crlf_newline: true) # => "\r\n \r\r\n"
- s.encode('ASCII', universal_newline: true) # => "\n \n"
+ 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 3b68ec6cbc..93f5753cd1 100644
--- a/doc/extension.ja.rdoc
+++ b/doc/extension.ja.rdoc
@@ -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 30800c2435..ad9ae641d2 100644
--- a/doc/extension.rdoc
+++ b/doc/extension.rdoc
@@ -956,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
@@ -984,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.
@@ -1048,9 +1055,9 @@ 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> are allowed to be <tt>#include</tt>-d
-by C extensions. Files under <tt>$repo_root/include/ruby/internal</tt>
-should not be <tt>#include</tt>-d directly.
+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.
@@ -1925,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
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/hacking.md b/doc/hacking.md
deleted file mode 100644
index e441a40554..0000000000
--- a/doc/hacking.md
+++ /dev/null
@@ -1,104 +0,0 @@
-# Ruby Hacking Guide
-
-This document gives some helpful instructions which should make your
-experience as a Ruby core developer easier.
-
-## Setup
-
-### Make
-
-It's common to want to compile things as quickly as possible. Ensuring
-`make` has the right `--jobs` flag will ensure all processors are
-utilized when building software projects To do this effectively, you
-can set `MAKEFLAGS` in your shell configuration/profile:
-
-``` shell
-# On macOS with Fish shell:
-export MAKEFLAGS="--jobs "(sysctl -n hw.ncpu)
-
-# On macOS with Bash/ZSH shell:
-export MAKEFLAGS="--jobs $(sysctl -n hw.ncpu)"
-
-# On Linux with Fish shell:
-export MAKEFLAGS="--jobs "(nproc)
-
-# On Linux with Bash/ZSH shell:
-export MAKEFLAGS="--jobs $(nproc)"
-```
-
-## Configure Ruby
-
-It's generally advisable to use a build directory.
-
-``` shell
-./autogen.sh
-mkdir build
-cd build
-../configure --prefix $HOME/.rubies/ruby-head
-make install
-```
-
-### Without Documentation
-
-If you are frequently building Ruby, this will reduce the time it
-takes to `make install`.
-
-``` shell
-../configure --disable-install-doc
-```
-
-## Running Ruby
-
-### Run Local Test Script
-
-You can create a file in the Ruby source root called `test.rb`. You
-can build `miniruby` and execute this script:
-
-``` shell
-make run
-```
-
-If you want more of the standard library, you can use `runruby`
-instead of `run`.
-
-## Running Tests
-
-You can run the following tests at once:
-
-``` shell
-make check
-```
-
-### Run Bootstrap Tests
-
-There are a set of tests in `bootstraptest/` which cover most basic
-features of the core Ruby language.
-
-``` shell
-make test
-```
-
-### Run Extensive Tests
-
-There are extensive tests in `test/` which cover a wide range of
-features of the Ruby core language.
-
-``` shell
-make test-all
-```
-
-You can run specific tests by specifying their path:
-
-``` shell
-make test-all TESTS=../test/fiber/test_io.rb
-```
-
-### Run Ruby Spec Suite Tests
-
-The [Ruby Spec Suite](https://github.com/ruby/spec/) is a test suite
-that aims to provide an executable description for the behavior of the
-language.
-
-``` shell
-make test-spec
-```
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/maintainers.rdoc b/doc/maintainers.rdoc
index b56a3d887f..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
@@ -412,3 +420,5 @@ Yukihiro Matsumoto (matz)
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 6b056a4f0b..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
-
-```
-$ ./autogen.sh
-$ ./configure --prefix=$PWD/local
-$ make
-$ make install
-$ ./local/bin/ruby -e 'puts "Hello"'
-Hello
-```
-
-## Out-of-place build
-
-```
-$ ./autogen.sh
-$ mkdir ../ruby-build
-$ cd ../ruby-build
-$ ../ruby-src/configure --prefix=$PWD/local
-$ make
-$ make install
-$ ./local/bin/ruby -e 'puts "Hello"'
-Hello
-```
-
-## How to run the whole test suite
-
-```
-$ make check
-```
-
-It runs (about) three test suites:
-
-* `make test` (a test suite for the interpreter core)
-* `make test-all` (for all builtin classes and libraries)
-* `make test-spec` (a conformance test suite for Ruby implementations)
-* `make test-bundler` (a test suite for the bundler examples)
-
-## How to run the test suite with log
-
-```
-$ make test OPTS=-v
-
-$ make test-all TESTS=-v
-
-$ make test-spec MSPECOPT=-Vfs
-```
-
-## How to run a part of the test suite
-
-### Runs a directory
-```
-$ make test-all TESTS=test/rubygems
-$ make test-all TESTS=rubygems
-```
-
-### Runs a file
-```
-$ make test-all TESTS=test/ruby/test_foo.rb
-$ make test-all TESTS=ruby/foo
-```
-
-### Runs a test whose name includes test_bar
-```
-$ make test-all TESTS="test/ruby/test_foo.rb -n /test_bar/"
-```
-
-### Runs a file or directory with GNU make
-```
-$ make test/ruby/test_foo.rb
-$ make test/ruby/test_foo.rb TESTOPTS="-n /test_bar/"
-```
-
-### Runs a ruby-spec directory
-```
-$ make test-spec MSPECOPT=spec/ruby/core/foo
-```
-
-### Runs a ruby-spec file
-```
-$ make test-spec MSPECOPT=spec/ruby/core/foo/bar_spec.rb
-```
-
-### Runs a ruby-spec file or directory with GNU make
-```
-$ make spec/ruby/core/foo/bar_spec.rb
-```
-
-### Runs a bundler spec file
-```
-$ make test-bundler BUNDLER_SPECS=commands/exec_spec.rb:58
-```
-
-## How to measure coverage of C and Ruby code
-
-You need to be able to use gcc (gcov) and lcov visualizer.
-
-```
-$ ./autogen.sh
-$ ./configure --enable-gcov
-$ make
-$ make update-coverage
-$ rm -f test-coverage.dat
-$ make test-all COVERAGE=true
-$ make lcov
-$ open lcov-out/index.html
-```
-
-If you need only C code coverage, you can remove `COVERAGE=true` from the above process.
-You can also use `gcov` command directly to get per-file coverage.
-
-If you need only Ruby code coverage, you can remove `--enable-gcov`.
-Note that `test-coverage.dat` accumulates all runs of `make test-all`.
-Make sure that you remove the file if you want to measure one test run.
-
-You can see the coverage result of CI: https://rubyci.org/coverage
-
-## How to benchmark
-
-see https://github.com/ruby/ruby/tree/master/benchmark#make-benchmark
diff --git a/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/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/creates_option.rdoc b/doc/optparse/creates_option.rdoc
index ad52c6671b..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}[./option_params.rdoc].
+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#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 b2e4e1a33c..ace2c4283f 100644
--- a/doc/optparse/option_params.rdoc
+++ b/doc/optparse/option_params.rdoc
@@ -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 19c86b93d8..b95089826d 100644
--- a/doc/optparse/tutorial.rdoc
+++ b/doc/optparse/tutorial.rdoc
@@ -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].
+ 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/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 6aa11b0c5a..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>
@@ -540,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:
@@ -610,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>
@@ -669,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;
@@ -759,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/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_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/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
index 3eee2b82e0..d955e61c87 100644
--- a/doc/string/new.rdoc
+++ b/doc/string/new.rdoc
@@ -1,36 +1,50 @@
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 ça?')
- s # => "Que veut dire ça?"
- s.encoding # => #<Encoding:UTF-8>
-
-Literal strings like <tt>""</tt> or here-documents always use
-Encoding@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
-
-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) # => ""
+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:
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
index d93b76d9b4..2b5e14ddb6 100644
--- a/doc/string/split.rdoc
+++ b/doc/string/split.rdoc
@@ -82,3 +82,5 @@ 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/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 32fe5110ce..b641433249 100644
--- a/doc/syntax/literals.rdoc
+++ b/doc/syntax/literals.rdoc
@@ -90,15 +90,36 @@ point numbers as well.
=== \Rational Literals
-You can write a Rational number as follows (suffixed +r+):
+You can write a Rational literal using a special suffix, <tt>'r'</tt>.
- 12r #=> (12/1)
- 12.3r #=> (123/10)
-
-A \Rational number is exact, whereas a \Float number may be inexact.
+Examples:
- 0.1r + 0.2r #=> (3/10)
- 0.1 + 0.2 #=> 0.30000000000000004
+ 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.
+
+Syntax:
+
+ <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'
+
+Note this, which is parsed as \Float numerator <tt>1.2</tt>
+divided by \Rational denominator <tt>3r</tt>,
+resulting in a \Float:
+
+ 1.2/3r # => 0.39999999999999997
=== \Complex Literals
@@ -256,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:
@@ -381,15 +408,15 @@ on the methods you need to implement.
== \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
@@ -420,10 +447,10 @@ This proc will add one to its argument.
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>.
+* <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.
@@ -482,13 +509,23 @@ You can write a symbol with <tt>%s</tt>:
=== <tt>%r</tt>: Regexp Literals
-You can write a regular expression with <tt>%r</tt>:
+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/
+
+A few "symmetrical" character pairs may be used as delimiters:
- r = %r[foo\sbar] # => /foo\sbar/
- 'foo bar'.match(r) # => #<MatchData "foo bar">
- r = %r[foo\sbar]i # => /foo\sbar/i
- 'FOO BAR'.match(r) # => #<MatchData "FOO BAR">
+ %r[foo] # => /foo/
+ %r{foo} # => /foo/
+ %r(foo) # => /foo/
+ %r<foo> # => /foo/
+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.
=== <tt>%x</tt>: Backtick Literals
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/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
index 29787fe907..4f15dff94a 100644
--- a/doc/transcode.rdoc
+++ b/doc/transcode.rdoc
@@ -44,7 +44,7 @@ class String
# t.encoding # => #<Encoding:UTF-8>
#
# Optional keyword arguments +enc_opts+ specify encoding options;
- # see {Encoding Options}[rdoc-ref:encoding.rdoc@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(...)
diff --git a/doc/yjit/yjit.md b/doc/yjit/yjit.md
index 3c731247a3..67b2ffa5f0 100644
--- a/doc/yjit/yjit.md
+++ b/doc/yjit/yjit.md
@@ -8,99 +8,135 @@
YJIT - Yet Another Ruby JIT
===========================
-**DISCLAIMER: Please note that this project is experimental. It is very much a work in progress, it may cause your software to crash, and current performance results will vary widely, especially on larger applications.**
-
YJIT is a lightweight, minimalistic Ruby JIT built inside CRuby.
-It lazily compiles code using a Basic Block Versioning (BBV) architecture. The target use case is that of servers running
-Ruby on Rails, an area where MJIT has not yet managed to deliver speedups.
-To simplify development, we currently support only macOS and Linux on x86-64, but an ARM64 backend
-is part of future plans.
+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 this repository in your publications, please use this bibtex snippet:
-
-```
-@misc{yjit_ruby_jit,
- author = {Chevalier-Boisvert, Maxime and Wu, Alan and Patterson, Aaron},
- title = {YJIT - Yet Another Ruby JIT},
- year = {2021},
- publisher = {GitHub},
- journal = {GitHub repository},
- howpublished = {\url{https://github.com/Shopify/yjit}},
+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 is a work in progress and as such may not yet be mature enough for mission-critical software. Below is a list of known limitations, all of which we plan to eventually address:
-
-- No garbage collection for generated code.
-- Currently supports only macOS and Linux.
-- Currently supports only x86-64 CPUs.
-
-Because there is no GC for generated code yet, your software could run out of executable memory if it is large enough. You can change how much executable memory is allocated using [YJIT's command-line options](#command-line-options).
+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
-Current YJIT versions are installed by default with CRuby. Make sure to specify the "--yjit" command line option to enable it at runtime.
+### Requirements
-Experimental YJIT patches that have not yet been merged with CRuby can be found in ruby-build:
+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).
-```
-ruby-build yjit-dev ~/.rubies/ruby-yjit-dev
-```
+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.
-They can also be found in the Shopify/yjit repository, which is cloned and build like CRuby.
+[rust-install]: https://www.rust-lang.org/tools/install
+[editor-tools]: https://www.rust-lang.org/tools
-Start by cloning the `Shopify/yjit` repository:
+### Building YJIT
-```
-git clone https://github.com/Shopify/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. For development, we recommend enabling debug symbols so that assertions are enabled as this makes debugging easier. Enabling debug mode will also make it possible for you to disassemble code generated by YJIT. However, this causes a performance hit. For maximum performance, compile with GCC, without the `-DRUBY_DEBUG` or `-DYJIT_STATS` build options. More detailed build instructions are provided in the [Ruby README](https://github.com/ruby/ruby#how-to-compile-and-install).
-To support disassembly of the generated code, `libcapstone` is also required (`brew install capstone` on MacOS, `sudo apt-get install -y libcapstone-dev` on Ubuntu/Debian and `sudo dnf -y install capstone-devel` on Fedora).
+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).
-```
-# Configure with debugging/stats options for development, build and install
+```sh
+# Configure in release mode for maximum performance, build and install
./autogen.sh
-./configure cppflags="-DRUBY_DEBUG -DYJIT_STATS" --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc --disable--install-rdoc
-make -j16 install
+./configure --enable-yjit --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc
+make -j && make install
```
-On macOS, you may need to specify where to find openssl, libyaml and gdbm:
+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
```
-# Configure with debugging/stats options for development, build and install
-./configure cppflags="-DRUBY_DEBUG -DYJIT_STATS" --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc --disable--install-rdoc --with-opt-dir=$(brew --prefix openssl):$(brew --prefix readline):$(brew --prefix libyaml):$(brew --prefix gdbm)
-make -j16 install
+
+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
```
-Typically configure will choose default C compiler. To specify the C compiler, use
+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 -j16 test-all
+make -j test-all
```
## Usage
@@ -110,71 +146,111 @@ make -j16 test-all
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:
-- `--disable-yjit`: turn off YJIT (enabled by default)
-- `--yjit-stats`: produce statistics after the execution of a program (must compile with `cppflags=-DRUBY_DEBUG` to use this)
-- `--yjit-exec-mem-size=N`: size of the executable memory block to allocate, in MiB (default 256 MiB)
-- `--yjit-call-threshold=N`: number of calls after which YJIT begins to compile a function (default 2)
-- `--yjit-max-versions=N`: maximum number of versions to generate per basic block (default 4)
-- `--yjit-greedy-versioning`: greedy versioning mode (disabled by default, may increase code size)
+- `--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
+## 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.
-This section contains tips on writing Ruby code that will run as fast as possible on YJIT. Some of this advice is based on current limitations of YJIT, while other advice is broadly applicable. It probably won't be practical to apply these tips everywhere in your codebase, but you can profile your code using a tool such as [stackprof](https://github.com/tmm1/stackprof) and refactor the specific methods that make up the largest fractions of the execution time.
+## Code Optimization Tips
-- Use exceptions for error recovery only, not as part of normal control-flow
+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
-- Use while loops if you can, instead of `integer.times`
- Minimize layers of indirection
- Avoid classes that wrap objects if you can
- Avoid methods that just call another method, trivial one liner methods
-- CRuby method calls are costly. Favor larger methods over smaller methods.
- Try to write code so that the same variables always have the same type
+- 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 compile YJIT in debug mode and use the `--yjit-stats` command-line option to see which bytecodes cause YJIT to exit, and refactor your code to avoid using these instructions in the hottest methods of your code.
-
-### Memory Statistics
-
-YJIT, including in production configuration, keeps track of the size of generated code. If you check YJIT.runtime_stats you can see them:
-
-```
-$ RUBYOPT="--yjit" irb
-irb(main):001:0> RubyVM::YJIT.runtime_stats
-=> {:inline_code_size=>331945, :outlined_code_size=>272980}
-```
-
-These are the size in bytes of generated inlined code and generated outlined code. If the combined sizes for generated code are very close to the total YJIT exec-mem-size (see above), YJIT will stop generating code once the limit is reached. Try to make sure you have enough exec-mem-size for the program you're running. By default YJIT will allocate 268,435,456 bytes (256 MiB) of space for generated inlined and outlined code.
+You can also use the `--yjit-stats` command-line option to see which bytecodes cause YJIT to exit, and refactor your code to avoid using these instructions in the hottest methods of your code.
### Other Statistics
-If you compile Ruby with RUBY_DEBUG and/or YJIT_STATS defined and run with "--yjit --yjit-stats", YJIT will track and return performance statistics in RubyVM::YJIT.runtime_stats.
+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> YJIT.runtime_stats
+irb(main):001:0> RubyVM::YJIT.runtime_stats
=>
{:inline_code_size=>340745,
:outlined_code_size=>297664,
@@ -188,16 +264,24 @@ irb(main):001:0> YJIT.runtime_stats
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
-:vm_insns_count - number of instructions executed by the Ruby interpreter
-:compiled_iseq_count - number of bytecode sequences compiled
+* :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.
@@ -215,20 +299,36 @@ you can contribute things we will want to merge into YJIT.
### Source Code Organization
The YJIT source code is divided between:
-- `yjit_asm.c`: x86 in-memory assembler we use to generate machine code
-- `yjit_codegen.c`: logic for translating Ruby bytecode to machine code
-- `yjit_core.c`: basic block versioning logic, core structure of YJIT
-- `yjit_iface.c`: code YJIT uses to interface with the rest of CRuby
+- `yjit.c`: code YJIT uses to interface with the rest of CRuby
- `yjit.h`: C definitions YJIT exposes to the rest of the CRuby
- `yjit.rb`: `YJIT` Ruby module that is exposed to Ruby
-- `misc/test_yjit_asm.sh`: script to compile and run the in-memory assembler tests
-- `misc/yjit_asm_tests.c`: tests for the in-memory assembler
+- `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:
@@ -239,37 +339,79 @@ There are 3 test suites:
The tests can be run in parallel like this:
-```
-make -j16 test-all RUN_OPTS="--yjit-call-threshold=1"
+```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/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 60c5a3ebb2..973ad93010 100644
--- a/enc/depend
+++ b/enc/depend
@@ -7018,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
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/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/unicode/14.0.0/casefold.h b/enc/unicode/15.0.0/casefold.h
index d387cff628..51120d867d 100644
--- a/enc/unicode/14.0.0/casefold.h
+++ b/enc/unicode/15.0.0/casefold.h
@@ -1,15 +1,15 @@
/* 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 == 14 && \
+ 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 "14.0.0"
-#define ONIG_UNICODE_VERSION_MAJOR 14
+#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
diff --git a/enc/unicode/14.0.0/name2ctype.h b/enc/unicode/15.0.0/name2ctype.h
index 99a3eeca19..a2c996423d 100644
--- a/enc/unicode/14.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[] = {
- 722,
+ 732,
0x0041, 0x005a,
0x0061, 0x007a,
0x00aa, 0x00aa,
@@ -178,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,
@@ -202,7 +201,7 @@ static const OnigCodePoint CR_Alpha[] = {
0x0cd5, 0x0cd6,
0x0cdd, 0x0cde,
0x0ce0, 0x0ce3,
- 0x0cf1, 0x0cf2,
+ 0x0cf1, 0x0cf3,
0x0d00, 0x0d0c,
0x0d0e, 0x0d10,
0x0d12, 0x0d3a,
@@ -240,7 +239,7 @@ static const OnigCodePoint CR_Alpha[] = {
0x0f00, 0x0f00,
0x0f40, 0x0f47,
0x0f49, 0x0f6c,
- 0x0f71, 0x0f81,
+ 0x0f71, 0x0f83,
0x0f88, 0x0f97,
0x0f99, 0x0fbc,
0x1000, 0x1036,
@@ -542,7 +541,7 @@ static const OnigCodePoint CR_Alpha[] = {
0x10fe0, 0x10ff6,
0x11000, 0x11045,
0x11071, 0x11075,
- 0x11082, 0x110b8,
+ 0x11080, 0x110b8,
0x110c2, 0x110c2,
0x110d0, 0x110e8,
0x11100, 0x11132,
@@ -557,7 +556,7 @@ static const OnigCodePoint CR_Alpha[] = {
0x11200, 0x11211,
0x11213, 0x11234,
0x11237, 0x11237,
- 0x1123e, 0x1123e,
+ 0x1123e, 0x11241,
0x11280, 0x11286,
0x11288, 0x11288,
0x1128a, 0x1128d,
@@ -637,12 +636,16 @@ 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,
0x12f90, 0x12ff0,
- 0x13000, 0x1342e,
+ 0x13000, 0x1342f,
+ 0x13441, 0x13446,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
@@ -666,7 +669,9 @@ static const OnigCodePoint CR_Alpha[] = {
0x1aff5, 0x1affb,
0x1affd, 0x1affe,
0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -705,16 +710,20 @@ static const OnigCodePoint CR_Alpha[] = {
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,
@@ -760,12 +769,13 @@ static const OnigCodePoint CR_Alpha[] = {
0x1f150, 0x1f169,
0x1f170, 0x1f189,
0x20000, 0x2a6df,
- 0x2a700, 0x2b738,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
}; /* CR_Alpha */
/* 'Blank': [[:Blank:]] */
@@ -790,7 +800,7 @@ static const OnigCodePoint CR_Cntrl[] = {
/* 'Digit': [[:Digit:]] */
static const OnigCodePoint CR_Digit[] = {
- 62,
+ 64,
0x0030, 0x0039,
0x0660, 0x0669,
0x06f0, 0x06f9,
@@ -845,19 +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[] = {
- 703,
+ 712,
0x0021, 0x007e,
0x00a1, 0x0377,
0x037a, 0x037f,
@@ -980,7 +992,7 @@ static const OnigCodePoint CR_Graph[] = {
0x0cdd, 0x0cde,
0x0ce0, 0x0ce3,
0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
+ 0x0cf1, 0x0cf3,
0x0d00, 0x0d0c,
0x0d0e, 0x0d10,
0x0d12, 0x0d44,
@@ -1010,7 +1022,7 @@ static const OnigCodePoint CR_Graph[] = {
0x0ea7, 0x0ebd,
0x0ec0, 0x0ec4,
0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
+ 0x0ec8, 0x0ece,
0x0ed0, 0x0ed9,
0x0edc, 0x0edf,
0x0f00, 0x0f47,
@@ -1285,7 +1297,7 @@ static const OnigCodePoint CR_Graph[] = {
0x10e80, 0x10ea9,
0x10eab, 0x10ead,
0x10eb0, 0x10eb1,
- 0x10f00, 0x10f27,
+ 0x10efd, 0x10f27,
0x10f30, 0x10f59,
0x10f70, 0x10f89,
0x10fb0, 0x10fcb,
@@ -1302,7 +1314,7 @@ static const OnigCodePoint CR_Graph[] = {
0x11180, 0x111df,
0x111e1, 0x111f4,
0x11200, 0x11211,
- 0x11213, 0x1123e,
+ 0x11213, 0x11241,
0x11280, 0x11286,
0x11288, 0x11288,
0x1128a, 0x1128d,
@@ -1355,6 +1367,7 @@ static const OnigCodePoint CR_Graph[] = {
0x11a00, 0x11a47,
0x11a50, 0x11aa2,
0x11ab0, 0x11af8,
+ 0x11b00, 0x11b09,
0x11c00, 0x11c08,
0x11c0a, 0x11c36,
0x11c38, 0x11c45,
@@ -1376,6 +1389,9 @@ static const OnigCodePoint CR_Graph[] = {
0x11d93, 0x11d98,
0x11da0, 0x11da9,
0x11ee0, 0x11ef8,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f59,
0x11fb0, 0x11fb0,
0x11fc0, 0x11ff1,
0x11fff, 0x12399,
@@ -1383,8 +1399,7 @@ static const OnigCodePoint CR_Graph[] = {
0x12470, 0x12474,
0x12480, 0x12543,
0x12f90, 0x12ff2,
- 0x13000, 0x1342e,
- 0x13430, 0x13438,
+ 0x13000, 0x13455,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
@@ -1411,7 +1426,9 @@ static const OnigCodePoint CR_Graph[] = {
0x1aff5, 0x1affb,
0x1affd, 0x1affe,
0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -1426,6 +1443,7 @@ static const OnigCodePoint CR_Graph[] = {
0x1d100, 0x1d126,
0x1d129, 0x1d1ea,
0x1d200, 0x1d245,
+ 0x1d2c0, 0x1d2d3,
0x1d2e0, 0x1d2f3,
0x1d300, 0x1d356,
0x1d360, 0x1d378,
@@ -1453,11 +1471,14 @@ static const OnigCodePoint CR_Graph[] = {
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,
@@ -1465,6 +1486,7 @@ static const OnigCodePoint CR_Graph[] = {
0x1e290, 0x1e2ae,
0x1e2c0, 0x1e2f9,
0x1e2ff, 0x1e2ff,
+ 0x1e4d0, 0x1e4f9,
0x1e7e0, 0x1e7e6,
0x1e7e8, 0x1e7eb,
0x1e7ed, 0x1e7ee,
@@ -1523,10 +1545,10 @@ static const OnigCodePoint CR_Graph[] = {
0x1f250, 0x1f251,
0x1f260, 0x1f265,
0x1f300, 0x1f6d7,
- 0x1f6dd, 0x1f6ec,
+ 0x1f6dc, 0x1f6ec,
0x1f6f0, 0x1f6fc,
- 0x1f700, 0x1f773,
- 0x1f780, 0x1f7d8,
+ 0x1f700, 0x1f776,
+ 0x1f77b, 0x1f7d9,
0x1f7e0, 0x1f7eb,
0x1f7f0, 0x1f7f0,
0x1f800, 0x1f80b,
@@ -1537,25 +1559,24 @@ static const OnigCodePoint CR_Graph[] = {
0x1f8b0, 0x1f8b1,
0x1f900, 0x1fa53,
0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa74,
- 0x1fa78, 0x1fa7c,
- 0x1fa80, 0x1fa86,
- 0x1fa90, 0x1faac,
- 0x1fab0, 0x1faba,
- 0x1fac0, 0x1fac5,
- 0x1fad0, 0x1fad9,
- 0x1fae0, 0x1fae7,
- 0x1faf0, 0x1faf6,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa88,
+ 0x1fa90, 0x1fabd,
+ 0x1fabf, 0x1fac5,
+ 0x1face, 0x1fadb,
+ 0x1fae0, 0x1fae8,
+ 0x1faf0, 0x1faf8,
0x1fb00, 0x1fb92,
0x1fb94, 0x1fbca,
0x1fbf0, 0x1fbf9,
0x20000, 0x2a6df,
- 0x2a700, 0x2b738,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
0xe0001, 0xe0001,
0xe0020, 0xe007f,
0xe0100, 0xe01ef,
@@ -1565,7 +1586,7 @@ static const OnigCodePoint CR_Graph[] = {
/* 'Lower': [[:Lower:]] */
static const OnigCodePoint CR_Lower[] = {
- 664,
+ 671,
0x0061, 0x007a,
0x00aa, 0x00aa,
0x00b5, 0x00b5,
@@ -1842,7 +1863,7 @@ static const OnigCodePoint CR_Lower[] = {
0x052f, 0x052f,
0x0560, 0x0588,
0x10d0, 0x10fa,
- 0x10fd, 0x10ff,
+ 0x10fc, 0x10ff,
0x13f8, 0x13fd,
0x1c80, 0x1c88,
0x1d00, 0x1dbf,
@@ -2182,10 +2203,11 @@ static const OnigCodePoint CR_Lower[] = {
0xa7d5, 0xa7d5,
0xa7d7, 0xa7d7,
0xa7d9, 0xa7d9,
+ 0xa7f2, 0xa7f4,
0xa7f6, 0xa7f6,
0xa7f8, 0xa7fa,
0xab30, 0xab5a,
- 0xab5c, 0xab68,
+ 0xab5c, 0xab69,
0xab70, 0xabbf,
0xfb00, 0xfb06,
0xfb13, 0xfb17,
@@ -2196,6 +2218,10 @@ static const OnigCodePoint CR_Lower[] = {
0x105a3, 0x105b1,
0x105b3, 0x105b9,
0x105bb, 0x105bc,
+ 0x10780, 0x10780,
+ 0x10783, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
0x10cc0, 0x10cf2,
0x118c0, 0x118df,
0x16e60, 0x16e7f,
@@ -2229,12 +2255,14 @@ static const OnigCodePoint CR_Lower[] = {
0x1d7cb, 0x1d7cb,
0x1df00, 0x1df09,
0x1df0b, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e030, 0x1e06d,
0x1e922, 0x1e943,
}; /* CR_Lower */
/* 'Print': [[:Print:]] */
static const OnigCodePoint CR_Print[] = {
- 700,
+ 709,
0x0020, 0x007e,
0x00a0, 0x0377,
0x037a, 0x037f,
@@ -2357,7 +2385,7 @@ static const OnigCodePoint CR_Print[] = {
0x0cdd, 0x0cde,
0x0ce0, 0x0ce3,
0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
+ 0x0cf1, 0x0cf3,
0x0d00, 0x0d0c,
0x0d0e, 0x0d10,
0x0d12, 0x0d44,
@@ -2387,7 +2415,7 @@ static const OnigCodePoint CR_Print[] = {
0x0ea7, 0x0ebd,
0x0ec0, 0x0ec4,
0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
+ 0x0ec8, 0x0ece,
0x0ed0, 0x0ed9,
0x0edc, 0x0edf,
0x0f00, 0x0f47,
@@ -2659,7 +2687,7 @@ static const OnigCodePoint CR_Print[] = {
0x10e80, 0x10ea9,
0x10eab, 0x10ead,
0x10eb0, 0x10eb1,
- 0x10f00, 0x10f27,
+ 0x10efd, 0x10f27,
0x10f30, 0x10f59,
0x10f70, 0x10f89,
0x10fb0, 0x10fcb,
@@ -2676,7 +2704,7 @@ static const OnigCodePoint CR_Print[] = {
0x11180, 0x111df,
0x111e1, 0x111f4,
0x11200, 0x11211,
- 0x11213, 0x1123e,
+ 0x11213, 0x11241,
0x11280, 0x11286,
0x11288, 0x11288,
0x1128a, 0x1128d,
@@ -2729,6 +2757,7 @@ static const OnigCodePoint CR_Print[] = {
0x11a00, 0x11a47,
0x11a50, 0x11aa2,
0x11ab0, 0x11af8,
+ 0x11b00, 0x11b09,
0x11c00, 0x11c08,
0x11c0a, 0x11c36,
0x11c38, 0x11c45,
@@ -2750,6 +2779,9 @@ static const OnigCodePoint CR_Print[] = {
0x11d93, 0x11d98,
0x11da0, 0x11da9,
0x11ee0, 0x11ef8,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f59,
0x11fb0, 0x11fb0,
0x11fc0, 0x11ff1,
0x11fff, 0x12399,
@@ -2757,8 +2789,7 @@ static const OnigCodePoint CR_Print[] = {
0x12470, 0x12474,
0x12480, 0x12543,
0x12f90, 0x12ff2,
- 0x13000, 0x1342e,
- 0x13430, 0x13438,
+ 0x13000, 0x13455,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
@@ -2785,7 +2816,9 @@ static const OnigCodePoint CR_Print[] = {
0x1aff5, 0x1affb,
0x1affd, 0x1affe,
0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -2800,6 +2833,7 @@ static const OnigCodePoint CR_Print[] = {
0x1d100, 0x1d126,
0x1d129, 0x1d1ea,
0x1d200, 0x1d245,
+ 0x1d2c0, 0x1d2d3,
0x1d2e0, 0x1d2f3,
0x1d300, 0x1d356,
0x1d360, 0x1d378,
@@ -2827,11 +2861,14 @@ static const OnigCodePoint CR_Print[] = {
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,
@@ -2839,6 +2876,7 @@ static const OnigCodePoint CR_Print[] = {
0x1e290, 0x1e2ae,
0x1e2c0, 0x1e2f9,
0x1e2ff, 0x1e2ff,
+ 0x1e4d0, 0x1e4f9,
0x1e7e0, 0x1e7e6,
0x1e7e8, 0x1e7eb,
0x1e7ed, 0x1e7ee,
@@ -2897,10 +2935,10 @@ static const OnigCodePoint CR_Print[] = {
0x1f250, 0x1f251,
0x1f260, 0x1f265,
0x1f300, 0x1f6d7,
- 0x1f6dd, 0x1f6ec,
+ 0x1f6dc, 0x1f6ec,
0x1f6f0, 0x1f6fc,
- 0x1f700, 0x1f773,
- 0x1f780, 0x1f7d8,
+ 0x1f700, 0x1f776,
+ 0x1f77b, 0x1f7d9,
0x1f7e0, 0x1f7eb,
0x1f7f0, 0x1f7f0,
0x1f800, 0x1f80b,
@@ -2911,25 +2949,24 @@ static const OnigCodePoint CR_Print[] = {
0x1f8b0, 0x1f8b1,
0x1f900, 0x1fa53,
0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa74,
- 0x1fa78, 0x1fa7c,
- 0x1fa80, 0x1fa86,
- 0x1fa90, 0x1faac,
- 0x1fab0, 0x1faba,
- 0x1fac0, 0x1fac5,
- 0x1fad0, 0x1fad9,
- 0x1fae0, 0x1fae7,
- 0x1faf0, 0x1faf6,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa88,
+ 0x1fa90, 0x1fabd,
+ 0x1fabf, 0x1fac5,
+ 0x1face, 0x1fadb,
+ 0x1fae0, 0x1fae8,
+ 0x1faf0, 0x1faf8,
0x1fb00, 0x1fb92,
0x1fb94, 0x1fbca,
0x1fbf0, 0x1fbf9,
0x20000, 0x2a6df,
- 0x2a700, 0x2b738,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
0xe0001, 0xe0001,
0xe0020, 0xe007f,
0xe0100, 0xe01ef,
@@ -2939,7 +2976,7 @@ static const OnigCodePoint CR_Print[] = {
/* 'XPosixPunct': [[:Punct:]] */
static const OnigCodePoint CR_XPosixPunct[] = {
- 184,
+ 186,
0x0021, 0x002f,
0x003a, 0x0040,
0x005b, 0x0060,
@@ -3109,9 +3146,11 @@ 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,
@@ -3807,7 +3846,7 @@ static const OnigCodePoint CR_XDigit[] = {
/* 'Word': [[:Word:]] */
static const OnigCodePoint CR_Word[] = {
- 758,
+ 770,
0x0030, 0x0039,
0x0041, 0x005a,
0x005f, 0x005f,
@@ -3965,7 +4004,7 @@ static const OnigCodePoint CR_Word[] = {
0x0cdd, 0x0cde,
0x0ce0, 0x0ce3,
0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
+ 0x0cf1, 0x0cf3,
0x0d00, 0x0d0c,
0x0d0e, 0x0d10,
0x0d12, 0x0d44,
@@ -3998,7 +4037,7 @@ static const OnigCodePoint CR_Word[] = {
0x0ea7, 0x0ebd,
0x0ec0, 0x0ec4,
0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
+ 0x0ec8, 0x0ece,
0x0ed0, 0x0ed9,
0x0edc, 0x0edf,
0x0f00, 0x0f00,
@@ -4311,7 +4350,7 @@ static const OnigCodePoint CR_Word[] = {
0x10e80, 0x10ea9,
0x10eab, 0x10eac,
0x10eb0, 0x10eb1,
- 0x10f00, 0x10f1c,
+ 0x10efd, 0x10f1c,
0x10f27, 0x10f27,
0x10f30, 0x10f50,
0x10f70, 0x10f85,
@@ -4334,7 +4373,7 @@ static const OnigCodePoint CR_Word[] = {
0x111dc, 0x111dc,
0x11200, 0x11211,
0x11213, 0x11237,
- 0x1123e, 0x1123e,
+ 0x1123e, 0x11241,
0x11280, 0x11286,
0x11288, 0x11288,
0x1128a, 0x1128d,
@@ -4415,12 +4454,17 @@ 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,
0x12f90, 0x12ff0,
- 0x13000, 0x1342e,
+ 0x13000, 0x1342f,
+ 0x13440, 0x13455,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
@@ -4448,7 +4492,9 @@ static const OnigCodePoint CR_Word[] = {
0x1aff5, 0x1affb,
0x1affd, 0x1affe,
0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -4502,17 +4548,21 @@ static const OnigCodePoint CR_Word[] = {
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,
@@ -4559,18 +4609,19 @@ static const OnigCodePoint CR_Word[] = {
0x1f170, 0x1f189,
0x1fbf0, 0x1fbf9,
0x20000, 0x2a6df,
- 0x2a700, 0x2b738,
+ 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[] = {
- 760,
+ 772,
0x0030, 0x0039,
0x0041, 0x005a,
0x0061, 0x007a,
@@ -4709,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,
@@ -4735,7 +4785,7 @@ static const OnigCodePoint CR_Alnum[] = {
0x0cdd, 0x0cde,
0x0ce0, 0x0ce3,
0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
+ 0x0cf1, 0x0cf3,
0x0d00, 0x0d0c,
0x0d0e, 0x0d10,
0x0d12, 0x0d3a,
@@ -4778,7 +4828,7 @@ static const OnigCodePoint CR_Alnum[] = {
0x0f20, 0x0f29,
0x0f40, 0x0f47,
0x0f49, 0x0f6c,
- 0x0f71, 0x0f81,
+ 0x0f71, 0x0f83,
0x0f88, 0x0f97,
0x0f99, 0x0fbc,
0x1000, 0x1036,
@@ -5088,7 +5138,7 @@ static const OnigCodePoint CR_Alnum[] = {
0x11000, 0x11045,
0x11066, 0x1106f,
0x11071, 0x11075,
- 0x11082, 0x110b8,
+ 0x11080, 0x110b8,
0x110c2, 0x110c2,
0x110d0, 0x110e8,
0x110f0, 0x110f9,
@@ -5104,7 +5154,7 @@ static const OnigCodePoint CR_Alnum[] = {
0x11200, 0x11211,
0x11213, 0x11234,
0x11237, 0x11237,
- 0x1123e, 0x1123e,
+ 0x1123e, 0x11241,
0x11280, 0x11286,
0x11288, 0x11288,
0x1128a, 0x1128d,
@@ -5194,12 +5244,17 @@ 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,
0x12f90, 0x12ff0,
- 0x13000, 0x1342e,
+ 0x13000, 0x1342f,
+ 0x13441, 0x13446,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
@@ -5226,7 +5281,9 @@ static const OnigCodePoint CR_Alnum[] = {
0x1aff5, 0x1affb,
0x1affd, 0x1affe,
0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -5266,11 +5323,14 @@ static const OnigCodePoint CR_Alnum[] = {
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,
@@ -5278,6 +5338,8 @@ static const OnigCodePoint CR_Alnum[] = {
0x1e290, 0x1e2ad,
0x1e2c0, 0x1e2eb,
0x1e2f0, 0x1e2f9,
+ 0x1e4d0, 0x1e4eb,
+ 0x1e4f0, 0x1e4f9,
0x1e7e0, 0x1e7e6,
0x1e7e8, 0x1e7eb,
0x1e7ed, 0x1e7ee,
@@ -5325,12 +5387,13 @@ static const OnigCodePoint CR_Alnum[] = {
0x1f170, 0x1f189,
0x1fbf0, 0x1fbf9,
0x20000, 0x2a6df,
- 0x2a700, 0x2b738,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
}; /* CR_Alnum */
/* 'ASCII': [[:ASCII:]] */
@@ -5341,7 +5404,7 @@ static const OnigCodePoint CR_ASCII[] = {
/* 'Punct' */
static const OnigCodePoint CR_Punct[] = {
- 189,
+ 191,
0x0021, 0x0023,
0x0025, 0x002a,
0x002c, 0x002f,
@@ -5516,9 +5579,11 @@ 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,
@@ -5542,7 +5607,7 @@ static const OnigCodePoint CR_Any[] = {
/* 'Assigned': - */
static const OnigCodePoint CR_Assigned[] = {
- 698,
+ 707,
0x0000, 0x0377,
0x037a, 0x037f,
0x0384, 0x038a,
@@ -5664,7 +5729,7 @@ static const OnigCodePoint CR_Assigned[] = {
0x0cdd, 0x0cde,
0x0ce0, 0x0ce3,
0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
+ 0x0cf1, 0x0cf3,
0x0d00, 0x0d0c,
0x0d0e, 0x0d10,
0x0d12, 0x0d44,
@@ -5694,7 +5759,7 @@ static const OnigCodePoint CR_Assigned[] = {
0x0ea7, 0x0ebd,
0x0ec0, 0x0ec4,
0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
+ 0x0ec8, 0x0ece,
0x0ed0, 0x0ed9,
0x0edc, 0x0edf,
0x0f00, 0x0f47,
@@ -5965,7 +6030,7 @@ static const OnigCodePoint CR_Assigned[] = {
0x10e80, 0x10ea9,
0x10eab, 0x10ead,
0x10eb0, 0x10eb1,
- 0x10f00, 0x10f27,
+ 0x10efd, 0x10f27,
0x10f30, 0x10f59,
0x10f70, 0x10f89,
0x10fb0, 0x10fcb,
@@ -5982,7 +6047,7 @@ static const OnigCodePoint CR_Assigned[] = {
0x11180, 0x111df,
0x111e1, 0x111f4,
0x11200, 0x11211,
- 0x11213, 0x1123e,
+ 0x11213, 0x11241,
0x11280, 0x11286,
0x11288, 0x11288,
0x1128a, 0x1128d,
@@ -6035,6 +6100,7 @@ static const OnigCodePoint CR_Assigned[] = {
0x11a00, 0x11a47,
0x11a50, 0x11aa2,
0x11ab0, 0x11af8,
+ 0x11b00, 0x11b09,
0x11c00, 0x11c08,
0x11c0a, 0x11c36,
0x11c38, 0x11c45,
@@ -6056,6 +6122,9 @@ static const OnigCodePoint CR_Assigned[] = {
0x11d93, 0x11d98,
0x11da0, 0x11da9,
0x11ee0, 0x11ef8,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f59,
0x11fb0, 0x11fb0,
0x11fc0, 0x11ff1,
0x11fff, 0x12399,
@@ -6063,8 +6132,7 @@ static const OnigCodePoint CR_Assigned[] = {
0x12470, 0x12474,
0x12480, 0x12543,
0x12f90, 0x12ff2,
- 0x13000, 0x1342e,
- 0x13430, 0x13438,
+ 0x13000, 0x13455,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
@@ -6091,7 +6159,9 @@ static const OnigCodePoint CR_Assigned[] = {
0x1aff5, 0x1affb,
0x1affd, 0x1affe,
0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -6106,6 +6176,7 @@ static const OnigCodePoint CR_Assigned[] = {
0x1d100, 0x1d126,
0x1d129, 0x1d1ea,
0x1d200, 0x1d245,
+ 0x1d2c0, 0x1d2d3,
0x1d2e0, 0x1d2f3,
0x1d300, 0x1d356,
0x1d360, 0x1d378,
@@ -6133,11 +6204,14 @@ static const OnigCodePoint CR_Assigned[] = {
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,
@@ -6145,6 +6219,7 @@ static const OnigCodePoint CR_Assigned[] = {
0x1e290, 0x1e2ae,
0x1e2c0, 0x1e2f9,
0x1e2ff, 0x1e2ff,
+ 0x1e4d0, 0x1e4f9,
0x1e7e0, 0x1e7e6,
0x1e7e8, 0x1e7eb,
0x1e7ed, 0x1e7ee,
@@ -6203,10 +6278,10 @@ static const OnigCodePoint CR_Assigned[] = {
0x1f250, 0x1f251,
0x1f260, 0x1f265,
0x1f300, 0x1f6d7,
- 0x1f6dd, 0x1f6ec,
+ 0x1f6dc, 0x1f6ec,
0x1f6f0, 0x1f6fc,
- 0x1f700, 0x1f773,
- 0x1f780, 0x1f7d8,
+ 0x1f700, 0x1f776,
+ 0x1f77b, 0x1f7d9,
0x1f7e0, 0x1f7eb,
0x1f7f0, 0x1f7f0,
0x1f800, 0x1f80b,
@@ -6217,25 +6292,24 @@ static const OnigCodePoint CR_Assigned[] = {
0x1f8b0, 0x1f8b1,
0x1f900, 0x1fa53,
0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa74,
- 0x1fa78, 0x1fa7c,
- 0x1fa80, 0x1fa86,
- 0x1fa90, 0x1faac,
- 0x1fab0, 0x1faba,
- 0x1fac0, 0x1fac5,
- 0x1fad0, 0x1fad9,
- 0x1fae0, 0x1fae7,
- 0x1faf0, 0x1faf6,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa88,
+ 0x1fa90, 0x1fabd,
+ 0x1fabf, 0x1fac5,
+ 0x1face, 0x1fadb,
+ 0x1fae0, 0x1fae8,
+ 0x1faf0, 0x1faf8,
0x1fb00, 0x1fb92,
0x1fb94, 0x1fbca,
0x1fbf0, 0x1fbf9,
0x20000, 0x2a6df,
- 0x2a700, 0x2b738,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
0xe0001, 0xe0001,
0xe0020, 0xe007f,
0xe0100, 0xe01ef,
@@ -6245,7 +6319,7 @@ static const OnigCodePoint CR_Assigned[] = {
/* 'C': Major Category */
static const OnigCodePoint CR_C[] = {
- 701,
+ 712,
0x0000, 0x001f,
0x007f, 0x009f,
0x00ad, 0x00ad,
@@ -6372,7 +6446,7 @@ static const OnigCodePoint CR_C[] = {
0x0cdf, 0x0cdf,
0x0ce4, 0x0ce5,
0x0cf0, 0x0cf0,
- 0x0cf3, 0x0cff,
+ 0x0cf4, 0x0cff,
0x0d0d, 0x0d0d,
0x0d11, 0x0d11,
0x0d45, 0x0d45,
@@ -6402,7 +6476,7 @@ static const OnigCodePoint CR_C[] = {
0x0ebe, 0x0ebf,
0x0ec5, 0x0ec5,
0x0ec7, 0x0ec7,
- 0x0ece, 0x0ecf,
+ 0x0ecf, 0x0ecf,
0x0eda, 0x0edb,
0x0ee0, 0x0eff,
0x0f48, 0x0f48,
@@ -6674,7 +6748,7 @@ static const OnigCodePoint CR_C[] = {
0x10e7f, 0x10e7f,
0x10eaa, 0x10eaa,
0x10eae, 0x10eaf,
- 0x10eb2, 0x10eff,
+ 0x10eb2, 0x10efc,
0x10f28, 0x10f2f,
0x10f5a, 0x10f6f,
0x10f8a, 0x10faf,
@@ -6692,7 +6766,7 @@ static const OnigCodePoint CR_C[] = {
0x111e0, 0x111e0,
0x111f5, 0x111ff,
0x11212, 0x11212,
- 0x1123f, 0x1127f,
+ 0x11242, 0x1127f,
0x11287, 0x11287,
0x11289, 0x11289,
0x1128e, 0x1128e,
@@ -6744,7 +6818,8 @@ static const OnigCodePoint CR_C[] = {
0x119e5, 0x119ff,
0x11a48, 0x11a4f,
0x11aa3, 0x11aaf,
- 0x11af9, 0x11bff,
+ 0x11af9, 0x11aff,
+ 0x11b0a, 0x11bff,
0x11c09, 0x11c09,
0x11c37, 0x11c37,
0x11c46, 0x11c4f,
@@ -6765,7 +6840,10 @@ 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,
@@ -6773,7 +6851,8 @@ static const OnigCodePoint CR_C[] = {
0x12475, 0x1247f,
0x12544, 0x12f8f,
0x12ff3, 0x12fff,
- 0x1342f, 0x143ff,
+ 0x13430, 0x1343f,
+ 0x13456, 0x143ff,
0x14647, 0x167ff,
0x16a39, 0x16a3f,
0x16a5f, 0x16a5f,
@@ -6799,8 +6878,10 @@ static const OnigCodePoint CR_C[] = {
0x1aff4, 0x1aff4,
0x1affc, 0x1affc,
0x1afff, 0x1afff,
- 0x1b123, 0x1b14f,
- 0x1b153, 0x1b163,
+ 0x1b123, 0x1b131,
+ 0x1b133, 0x1b14f,
+ 0x1b153, 0x1b154,
+ 0x1b156, 0x1b163,
0x1b168, 0x1b16f,
0x1b2fc, 0x1bbff,
0x1bc6b, 0x1bc6f,
@@ -6815,7 +6896,8 @@ static const OnigCodePoint CR_C[] = {
0x1d127, 0x1d128,
0x1d173, 0x1d17a,
0x1d1eb, 0x1d1ff,
- 0x1d246, 0x1d2df,
+ 0x1d246, 0x1d2bf,
+ 0x1d2d4, 0x1d2df,
0x1d2f4, 0x1d2ff,
0x1d357, 0x1d35f,
0x1d379, 0x1d3ff,
@@ -6842,19 +6924,23 @@ static const OnigCodePoint CR_C[] = {
0x1da8c, 0x1da9a,
0x1daa0, 0x1daa0,
0x1dab0, 0x1deff,
- 0x1df1f, 0x1dfff,
+ 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, 0x1e28f,
0x1e2af, 0x1e2bf,
0x1e2fa, 0x1e2fe,
- 0x1e300, 0x1e7df,
+ 0x1e300, 0x1e4cf,
+ 0x1e4fa, 0x1e7df,
0x1e7e7, 0x1e7e7,
0x1e7ec, 0x1e7ec,
0x1e7ef, 0x1e7ef,
@@ -6912,11 +6998,11 @@ static const OnigCodePoint CR_C[] = {
0x1f249, 0x1f24f,
0x1f252, 0x1f25f,
0x1f266, 0x1f2ff,
- 0x1f6d8, 0x1f6dc,
+ 0x1f6d8, 0x1f6db,
0x1f6ed, 0x1f6ef,
0x1f6fd, 0x1f6ff,
- 0x1f774, 0x1f77f,
- 0x1f7d9, 0x1f7df,
+ 0x1f777, 0x1f77a,
+ 0x1f7da, 0x1f7df,
0x1f7ec, 0x1f7ef,
0x1f7f1, 0x1f7ff,
0x1f80c, 0x1f80f,
@@ -6927,25 +7013,24 @@ static const OnigCodePoint CR_C[] = {
0x1f8b2, 0x1f8ff,
0x1fa54, 0x1fa5f,
0x1fa6e, 0x1fa6f,
- 0x1fa75, 0x1fa77,
0x1fa7d, 0x1fa7f,
- 0x1fa87, 0x1fa8f,
- 0x1faad, 0x1faaf,
- 0x1fabb, 0x1fabf,
- 0x1fac6, 0x1facf,
- 0x1fada, 0x1fadf,
- 0x1fae8, 0x1faef,
- 0x1faf7, 0x1faff,
+ 0x1fa89, 0x1fa8f,
+ 0x1fabe, 0x1fabe,
+ 0x1fac6, 0x1facd,
+ 0x1fadc, 0x1fadf,
+ 0x1fae9, 0x1faef,
+ 0x1faf9, 0x1faff,
0x1fb93, 0x1fb93,
0x1fbcb, 0x1fbef,
0x1fbfa, 0x1ffff,
0x2a6e0, 0x2a6ff,
- 0x2b739, 0x2b73f,
+ 0x2b73a, 0x2b73f,
0x2b81e, 0x2b81f,
0x2cea2, 0x2ceaf,
0x2ebe1, 0x2f7ff,
0x2fa1e, 0x2ffff,
- 0x3134b, 0xe00ff,
+ 0x3134b, 0x3134f,
+ 0x323b0, 0xe00ff,
0xe01f0, 0x10ffff,
}; /* CR_C */
@@ -6971,7 +7056,7 @@ static const OnigCodePoint CR_Cf[] = {
0xfff9, 0xfffb,
0x110bd, 0x110bd,
0x110cd, 0x110cd,
- 0x13430, 0x13438,
+ 0x13430, 0x1343f,
0x1bca0, 0x1bca3,
0x1d173, 0x1d17a,
0xe0001, 0xe0001,
@@ -6980,7 +7065,7 @@ static const OnigCodePoint CR_Cf[] = {
/* 'Cn': General Category */
static const OnigCodePoint CR_Cn[] = {
- 698,
+ 707,
0x0378, 0x0379,
0x0380, 0x0383,
0x038b, 0x038b,
@@ -7102,7 +7187,7 @@ static const OnigCodePoint CR_Cn[] = {
0x0cdf, 0x0cdf,
0x0ce4, 0x0ce5,
0x0cf0, 0x0cf0,
- 0x0cf3, 0x0cff,
+ 0x0cf4, 0x0cff,
0x0d0d, 0x0d0d,
0x0d11, 0x0d11,
0x0d45, 0x0d45,
@@ -7132,7 +7217,7 @@ static const OnigCodePoint CR_Cn[] = {
0x0ebe, 0x0ebf,
0x0ec5, 0x0ec5,
0x0ec7, 0x0ec7,
- 0x0ece, 0x0ecf,
+ 0x0ecf, 0x0ecf,
0x0eda, 0x0edb,
0x0ee0, 0x0eff,
0x0f48, 0x0f48,
@@ -7402,7 +7487,7 @@ static const OnigCodePoint CR_Cn[] = {
0x10e7f, 0x10e7f,
0x10eaa, 0x10eaa,
0x10eae, 0x10eaf,
- 0x10eb2, 0x10eff,
+ 0x10eb2, 0x10efc,
0x10f28, 0x10f2f,
0x10f5a, 0x10f6f,
0x10f8a, 0x10faf,
@@ -7420,7 +7505,7 @@ static const OnigCodePoint CR_Cn[] = {
0x111e0, 0x111e0,
0x111f5, 0x111ff,
0x11212, 0x11212,
- 0x1123f, 0x1127f,
+ 0x11242, 0x1127f,
0x11287, 0x11287,
0x11289, 0x11289,
0x1128e, 0x1128e,
@@ -7472,7 +7557,8 @@ static const OnigCodePoint CR_Cn[] = {
0x119e5, 0x119ff,
0x11a48, 0x11a4f,
0x11aa3, 0x11aaf,
- 0x11af9, 0x11bff,
+ 0x11af9, 0x11aff,
+ 0x11b0a, 0x11bff,
0x11c09, 0x11c09,
0x11c37, 0x11c37,
0x11c46, 0x11c4f,
@@ -7493,7 +7579,10 @@ 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,
@@ -7501,8 +7590,7 @@ static const OnigCodePoint CR_Cn[] = {
0x12475, 0x1247f,
0x12544, 0x12f8f,
0x12ff3, 0x12fff,
- 0x1342f, 0x1342f,
- 0x13439, 0x143ff,
+ 0x13456, 0x143ff,
0x14647, 0x167ff,
0x16a39, 0x16a3f,
0x16a5f, 0x16a5f,
@@ -7528,8 +7616,10 @@ static const OnigCodePoint CR_Cn[] = {
0x1aff4, 0x1aff4,
0x1affc, 0x1affc,
0x1afff, 0x1afff,
- 0x1b123, 0x1b14f,
- 0x1b153, 0x1b163,
+ 0x1b123, 0x1b131,
+ 0x1b133, 0x1b14f,
+ 0x1b153, 0x1b154,
+ 0x1b156, 0x1b163,
0x1b168, 0x1b16f,
0x1b2fc, 0x1bbff,
0x1bc6b, 0x1bc6f,
@@ -7543,7 +7633,8 @@ static const OnigCodePoint CR_Cn[] = {
0x1d0f6, 0x1d0ff,
0x1d127, 0x1d128,
0x1d1eb, 0x1d1ff,
- 0x1d246, 0x1d2df,
+ 0x1d246, 0x1d2bf,
+ 0x1d2d4, 0x1d2df,
0x1d2f4, 0x1d2ff,
0x1d357, 0x1d35f,
0x1d379, 0x1d3ff,
@@ -7570,19 +7661,23 @@ static const OnigCodePoint CR_Cn[] = {
0x1da8c, 0x1da9a,
0x1daa0, 0x1daa0,
0x1dab0, 0x1deff,
- 0x1df1f, 0x1dfff,
+ 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, 0x1e28f,
0x1e2af, 0x1e2bf,
0x1e2fa, 0x1e2fe,
- 0x1e300, 0x1e7df,
+ 0x1e300, 0x1e4cf,
+ 0x1e4fa, 0x1e7df,
0x1e7e7, 0x1e7e7,
0x1e7ec, 0x1e7ec,
0x1e7ef, 0x1e7ef,
@@ -7640,11 +7735,11 @@ static const OnigCodePoint CR_Cn[] = {
0x1f249, 0x1f24f,
0x1f252, 0x1f25f,
0x1f266, 0x1f2ff,
- 0x1f6d8, 0x1f6dc,
+ 0x1f6d8, 0x1f6db,
0x1f6ed, 0x1f6ef,
0x1f6fd, 0x1f6ff,
- 0x1f774, 0x1f77f,
- 0x1f7d9, 0x1f7df,
+ 0x1f777, 0x1f77a,
+ 0x1f7da, 0x1f7df,
0x1f7ec, 0x1f7ef,
0x1f7f1, 0x1f7ff,
0x1f80c, 0x1f80f,
@@ -7655,25 +7750,24 @@ static const OnigCodePoint CR_Cn[] = {
0x1f8b2, 0x1f8ff,
0x1fa54, 0x1fa5f,
0x1fa6e, 0x1fa6f,
- 0x1fa75, 0x1fa77,
0x1fa7d, 0x1fa7f,
- 0x1fa87, 0x1fa8f,
- 0x1faad, 0x1faaf,
- 0x1fabb, 0x1fabf,
- 0x1fac6, 0x1facf,
- 0x1fada, 0x1fadf,
- 0x1fae8, 0x1faef,
- 0x1faf7, 0x1faff,
+ 0x1fa89, 0x1fa8f,
+ 0x1fabe, 0x1fabe,
+ 0x1fac6, 0x1facd,
+ 0x1fadc, 0x1fadf,
+ 0x1fae9, 0x1faef,
+ 0x1faf9, 0x1faff,
0x1fb93, 0x1fb93,
0x1fbcb, 0x1fbef,
0x1fbfa, 0x1ffff,
0x2a6e0, 0x2a6ff,
- 0x2b739, 0x2b73f,
+ 0x2b73a, 0x2b73f,
0x2b81e, 0x2b81f,
0x2cea2, 0x2ceaf,
0x2ebe1, 0x2f7ff,
0x2fa1e, 0x2ffff,
- 0x3134b, 0xe0000,
+ 0x3134b, 0x3134f,
+ 0x323b0, 0xe0000,
0xe0002, 0xe001f,
0xe0080, 0xe00ff,
0xe01f0, 0xeffff,
@@ -7697,7 +7791,7 @@ static const OnigCodePoint CR_Cs[] = {
/* 'L': Major Category */
static const OnigCodePoint CR_L[] = {
- 648,
+ 659,
0x0041, 0x005a,
0x0061, 0x007a,
0x00aa, 0x00aa,
@@ -8167,6 +8261,7 @@ static const OnigCodePoint CR_L[] = {
0x111dc, 0x111dc,
0x11200, 0x11211,
0x11213, 0x1122b,
+ 0x1123f, 0x11240,
0x11280, 0x11286,
0x11288, 0x11288,
0x1128a, 0x1128d,
@@ -8229,11 +8324,15 @@ static const OnigCodePoint CR_L[] = {
0x11d6a, 0x11d89,
0x11d98, 0x11d98,
0x11ee0, 0x11ef2,
+ 0x11f02, 0x11f02,
+ 0x11f04, 0x11f10,
+ 0x11f12, 0x11f33,
0x11fb0, 0x11fb0,
0x12000, 0x12399,
0x12480, 0x12543,
0x12f90, 0x12ff0,
- 0x13000, 0x1342e,
+ 0x13000, 0x1342f,
+ 0x13441, 0x13446,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
@@ -8256,7 +8355,9 @@ static const OnigCodePoint CR_L[] = {
0x1aff5, 0x1affb,
0x1affd, 0x1affe,
0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -8294,11 +8395,14 @@ static const OnigCodePoint CR_L[] = {
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,
@@ -8340,17 +8444,18 @@ static const OnigCodePoint CR_L[] = {
0x1eea5, 0x1eea9,
0x1eeab, 0x1eebb,
0x20000, 0x2a6df,
- 0x2a700, 0x2b738,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
}; /* CR_L */
/* 'LC': General Category */
static const OnigCodePoint CR_LC[] = {
- 142,
+ 143,
0x0041, 0x005a,
0x0061, 0x007a,
0x00b5, 0x00b5,
@@ -8492,12 +8597,13 @@ static const OnigCodePoint CR_LC[] = {
0x1d7c4, 0x1d7cb,
0x1df00, 0x1df09,
0x1df0b, 0x1df1e,
+ 0x1df25, 0x1df2a,
0x1e900, 0x1e943,
}; /* CR_LC */
/* 'Ll': General Category */
static const OnigCodePoint CR_Ll[] = {
- 657,
+ 658,
0x0061, 0x007a,
0x00b5, 0x00b5,
0x00df, 0x00f6,
@@ -9154,12 +9260,13 @@ static const OnigCodePoint CR_Ll[] = {
0x1d7cb, 0x1d7cb,
0x1df00, 0x1df09,
0x1df0b, 0x1df1e,
+ 0x1df25, 0x1df2a,
0x1e922, 0x1e943,
}; /* CR_Ll */
/* 'Lm': General Category */
static const OnigCodePoint CR_Lm[] = {
- 69,
+ 71,
0x02b0, 0x02c1,
0x02c6, 0x02d1,
0x02e0, 0x02e4,
@@ -9227,13 +9334,15 @@ static const OnigCodePoint CR_Lm[] = {
0x1aff0, 0x1aff3,
0x1aff5, 0x1affb,
0x1affd, 0x1affe,
+ 0x1e030, 0x1e06d,
0x1e137, 0x1e13d,
+ 0x1e4eb, 0x1e4eb,
0x1e94b, 0x1e94b,
}; /* CR_Lm */
/* 'Lo': General Category */
static const OnigCodePoint CR_Lo[] = {
- 501,
+ 510,
0x00aa, 0x00aa,
0x00ba, 0x00ba,
0x01bb, 0x01bb,
@@ -9598,6 +9707,7 @@ static const OnigCodePoint CR_Lo[] = {
0x111dc, 0x111dc,
0x11200, 0x11211,
0x11213, 0x1122b,
+ 0x1123f, 0x11240,
0x11280, 0x11286,
0x11288, 0x11288,
0x1128a, 0x1128d,
@@ -9659,11 +9769,15 @@ static const OnigCodePoint CR_Lo[] = {
0x11d6a, 0x11d89,
0x11d98, 0x11d98,
0x11ee0, 0x11ef2,
+ 0x11f02, 0x11f02,
+ 0x11f04, 0x11f10,
+ 0x11f12, 0x11f33,
0x11fb0, 0x11fb0,
0x12000, 0x12399,
0x12480, 0x12543,
0x12f90, 0x12ff0,
- 0x13000, 0x1342e,
+ 0x13000, 0x1342f,
+ 0x13441, 0x13446,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
@@ -9678,7 +9792,9 @@ static const OnigCodePoint CR_Lo[] = {
0x18800, 0x18cd5,
0x18d00, 0x18d08,
0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -9690,6 +9806,7 @@ static const OnigCodePoint CR_Lo[] = {
0x1e14e, 0x1e14e,
0x1e290, 0x1e2ad,
0x1e2c0, 0x1e2eb,
+ 0x1e4d0, 0x1e4ea,
0x1e7e0, 0x1e7e6,
0x1e7e8, 0x1e7eb,
0x1e7ed, 0x1e7ee,
@@ -9729,12 +9846,13 @@ static const OnigCodePoint CR_Lo[] = {
0x1eea5, 0x1eea9,
0x1eeab, 0x1eebb,
0x20000, 0x2a6df,
- 0x2a700, 0x2b738,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
}; /* CR_Lo */
/* 'Lt': General Category */
@@ -10405,7 +10523,7 @@ static const OnigCodePoint CR_Lu[] = {
/* 'M': Major Category */
static const OnigCodePoint CR_M[] = {
- 299,
+ 310,
0x0300, 0x036f,
0x0483, 0x0489,
0x0591, 0x05bd,
@@ -10486,6 +10604,7 @@ static const OnigCodePoint CR_M[] = {
0x0cca, 0x0ccd,
0x0cd5, 0x0cd6,
0x0ce2, 0x0ce3,
+ 0x0cf3, 0x0cf3,
0x0d00, 0x0d03,
0x0d3b, 0x0d3c,
0x0d3e, 0x0d44,
@@ -10504,7 +10623,7 @@ static const OnigCodePoint CR_M[] = {
0x0e47, 0x0e4e,
0x0eb1, 0x0eb1,
0x0eb4, 0x0ebc,
- 0x0ec8, 0x0ecd,
+ 0x0ec8, 0x0ece,
0x0f18, 0x0f19,
0x0f35, 0x0f35,
0x0f37, 0x0f37,
@@ -10606,6 +10725,7 @@ static const OnigCodePoint CR_M[] = {
0x10ae5, 0x10ae6,
0x10d24, 0x10d27,
0x10eab, 0x10eac,
+ 0x10efd, 0x10eff,
0x10f46, 0x10f50,
0x10f82, 0x10f85,
0x11000, 0x11002,
@@ -10625,6 +10745,7 @@ static const OnigCodePoint CR_M[] = {
0x111ce, 0x111cf,
0x1122c, 0x11237,
0x1123e, 0x1123e,
+ 0x11241, 0x11241,
0x112df, 0x112ea,
0x11300, 0x11303,
0x1133b, 0x1133c,
@@ -10672,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,
@@ -10699,9 +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,
@@ -10709,7 +10838,7 @@ static const OnigCodePoint CR_M[] = {
/* 'Mc': General Category */
static const OnigCodePoint CR_Mc[] = {
- 177,
+ 182,
0x0903, 0x0903,
0x093b, 0x093b,
0x093e, 0x0940,
@@ -10745,6 +10874,7 @@ static const OnigCodePoint CR_Mc[] = {
0x0cc7, 0x0cc8,
0x0cca, 0x0ccb,
0x0cd5, 0x0cd6,
+ 0x0cf3, 0x0cf3,
0x0d02, 0x0d03,
0x0d3e, 0x0d40,
0x0d46, 0x0d48,
@@ -10883,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,
@@ -10901,7 +11035,7 @@ static const OnigCodePoint CR_Me[] = {
/* 'Mn': General Category */
static const OnigCodePoint CR_Mn[] = {
- 336,
+ 346,
0x0300, 0x036f,
0x0483, 0x0487,
0x0591, 0x05bd,
@@ -10994,7 +11128,7 @@ static const OnigCodePoint CR_Mn[] = {
0x0e47, 0x0e4e,
0x0eb1, 0x0eb1,
0x0eb4, 0x0ebc,
- 0x0ec8, 0x0ecd,
+ 0x0ec8, 0x0ece,
0x0f18, 0x0f19,
0x0f35, 0x0f35,
0x0f37, 0x0f37,
@@ -11125,6 +11259,7 @@ static const OnigCodePoint CR_Mn[] = {
0x10ae5, 0x10ae6,
0x10d24, 0x10d27,
0x10eab, 0x10eac,
+ 0x10efd, 0x10eff,
0x10f46, 0x10f50,
0x10f82, 0x10f85,
0x11001, 0x11001,
@@ -11147,6 +11282,7 @@ static const OnigCodePoint CR_Mn[] = {
0x11234, 0x11234,
0x11236, 0x11237,
0x1123e, 0x1123e,
+ 0x11241, 0x11241,
0x112df, 0x112df,
0x112e3, 0x112ea,
0x11300, 0x11301,
@@ -11208,6 +11344,12 @@ 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,
@@ -11232,9 +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,
@@ -11242,7 +11386,7 @@ static const OnigCodePoint CR_Mn[] = {
/* 'N': Major Category */
static const OnigCodePoint CR_N[] = {
- 134,
+ 137,
0x0030, 0x0039,
0x00b2, 0x00b3,
0x00b9, 0x00b9,
@@ -11356,6 +11500,7 @@ static const OnigCodePoint CR_N[] = {
0x11c50, 0x11c6c,
0x11d50, 0x11d59,
0x11da0, 0x11da9,
+ 0x11f50, 0x11f59,
0x11fc0, 0x11fd4,
0x12400, 0x1246e,
0x16a60, 0x16a69,
@@ -11363,11 +11508,13 @@ static const OnigCodePoint CR_N[] = {
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,
@@ -11401,7 +11548,7 @@ static const OnigCodePoint CR_Nl[] = {
/* 'No': General Category */
static const OnigCodePoint CR_No[] = {
- 71,
+ 72,
0x00b2, 0x00b3,
0x00b9, 0x00b9,
0x00bc, 0x00be,
@@ -11464,6 +11611,7 @@ static const OnigCodePoint CR_No[] = {
0x11fc0, 0x11fd4,
0x16b5b, 0x16b61,
0x16e80, 0x16e96,
+ 0x1d2c0, 0x1d2d3,
0x1d2e0, 0x1d2f3,
0x1d360, 0x1d378,
0x1e8c7, 0x1e8cf,
@@ -11627,7 +11775,7 @@ static const OnigCodePoint CR_Pi[] = {
/* 'Po': General Category */
static const OnigCodePoint CR_Po[] = {
- 185,
+ 187,
0x0021, 0x0023,
0x0025, 0x0027,
0x002a, 0x002a,
@@ -11798,9 +11946,11 @@ 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,
@@ -11901,7 +12051,7 @@ static const OnigCodePoint CR_Ps[] = {
/* 'S': Major Category */
static const OnigCodePoint CR_S[] = {
- 234,
+ 232,
0x0024, 0x0024,
0x002b, 0x002b,
0x003c, 0x003e,
@@ -12111,10 +12261,10 @@ static const OnigCodePoint CR_S[] = {
0x1f250, 0x1f251,
0x1f260, 0x1f265,
0x1f300, 0x1f6d7,
- 0x1f6dd, 0x1f6ec,
+ 0x1f6dc, 0x1f6ec,
0x1f6f0, 0x1f6fc,
- 0x1f700, 0x1f773,
- 0x1f780, 0x1f7d8,
+ 0x1f700, 0x1f776,
+ 0x1f77b, 0x1f7d9,
0x1f7e0, 0x1f7eb,
0x1f7f0, 0x1f7f0,
0x1f800, 0x1f80b,
@@ -12125,15 +12275,13 @@ static const OnigCodePoint CR_S[] = {
0x1f8b0, 0x1f8b1,
0x1f900, 0x1fa53,
0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa74,
- 0x1fa78, 0x1fa7c,
- 0x1fa80, 0x1fa86,
- 0x1fa90, 0x1faac,
- 0x1fab0, 0x1faba,
- 0x1fac0, 0x1fac5,
- 0x1fad0, 0x1fad9,
- 0x1fae0, 0x1fae7,
- 0x1faf0, 0x1faf6,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa88,
+ 0x1fa90, 0x1fabd,
+ 0x1fabf, 0x1fac5,
+ 0x1face, 0x1fadb,
+ 0x1fae0, 0x1fae8,
+ 0x1faf0, 0x1faf8,
0x1fb00, 0x1fb92,
0x1fb94, 0x1fbca,
}; /* CR_S */
@@ -12271,7 +12419,7 @@ static const OnigCodePoint CR_Sm[] = {
/* 'So': General Category */
static const OnigCodePoint CR_So[] = {
- 186,
+ 184,
0x00a6, 0x00a6,
0x00a9, 0x00a9,
0x00ae, 0x00ae,
@@ -12433,10 +12581,10 @@ static const OnigCodePoint CR_So[] = {
0x1f260, 0x1f265,
0x1f300, 0x1f3fa,
0x1f400, 0x1f6d7,
- 0x1f6dd, 0x1f6ec,
+ 0x1f6dc, 0x1f6ec,
0x1f6f0, 0x1f6fc,
- 0x1f700, 0x1f773,
- 0x1f780, 0x1f7d8,
+ 0x1f700, 0x1f776,
+ 0x1f77b, 0x1f7d9,
0x1f7e0, 0x1f7eb,
0x1f7f0, 0x1f7f0,
0x1f800, 0x1f80b,
@@ -12447,15 +12595,13 @@ static const OnigCodePoint CR_So[] = {
0x1f8b0, 0x1f8b1,
0x1f900, 0x1fa53,
0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa74,
- 0x1fa78, 0x1fa7c,
- 0x1fa80, 0x1fa86,
- 0x1fa90, 0x1faac,
- 0x1fab0, 0x1faba,
- 0x1fac0, 0x1fac5,
- 0x1fad0, 0x1fad9,
- 0x1fae0, 0x1fae7,
- 0x1faf0, 0x1faf6,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa88,
+ 0x1fa90, 0x1fabd,
+ 0x1fabf, 0x1fac5,
+ 0x1face, 0x1fadb,
+ 0x1fae0, 0x1fae8,
+ 0x1faf0, 0x1faf8,
0x1fb00, 0x1fb92,
0x1fb94, 0x1fbca,
}; /* CR_So */
@@ -12651,7 +12797,7 @@ static const OnigCodePoint CR_Math[] = {
/* 'Cased': Derived Property */
static const OnigCodePoint CR_Cased[] = {
- 151,
+ 157,
0x0041, 0x005a,
0x0061, 0x007a,
0x00aa, 0x00aa,
@@ -12683,7 +12829,7 @@ static const OnigCodePoint CR_Cased[] = {
0x10c7, 0x10c7,
0x10cd, 0x10cd,
0x10d0, 0x10fa,
- 0x10fd, 0x10ff,
+ 0x10fc, 0x10ff,
0x13a0, 0x13f5,
0x13f8, 0x13fd,
0x1c80, 0x1c88,
@@ -12743,10 +12889,10 @@ static const OnigCodePoint CR_Cased[] = {
0xa7d0, 0xa7d1,
0xa7d3, 0xa7d3,
0xa7d5, 0xa7d9,
- 0xa7f5, 0xa7f6,
+ 0xa7f2, 0xa7f6,
0xa7f8, 0xa7fa,
0xab30, 0xab5a,
- 0xab5c, 0xab68,
+ 0xab5c, 0xab69,
0xab70, 0xabbf,
0xfb00, 0xfb06,
0xfb13, 0xfb17,
@@ -12763,6 +12909,10 @@ static const OnigCodePoint CR_Cased[] = {
0x105a3, 0x105b1,
0x105b3, 0x105b9,
0x105bb, 0x105bc,
+ 0x10780, 0x10780,
+ 0x10783, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
0x10c80, 0x10cb2,
0x10cc0, 0x10cf2,
0x118a0, 0x118df,
@@ -12799,6 +12949,8 @@ static const OnigCodePoint CR_Cased[] = {
0x1d7c4, 0x1d7cb,
0x1df00, 0x1df09,
0x1df0b, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e030, 0x1e06d,
0x1e900, 0x1e943,
0x1f130, 0x1f149,
0x1f150, 0x1f169,
@@ -12807,7 +12959,7 @@ static const OnigCodePoint CR_Cased[] = {
/* 'Case_Ignorable': Derived Property */
static const OnigCodePoint CR_Case_Ignorable[] = {
- 427,
+ 437,
0x0027, 0x0027,
0x002e, 0x002e,
0x003a, 0x003a,
@@ -12921,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,
@@ -13110,6 +13262,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = {
0x10ae5, 0x10ae6,
0x10d24, 0x10d27,
0x10eab, 0x10eac,
+ 0x10efd, 0x10eff,
0x10f46, 0x10f50,
0x10f82, 0x10f85,
0x11001, 0x11001,
@@ -13134,6 +13287,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = {
0x11234, 0x11234,
0x11236, 0x11237,
0x1123e, 0x1123e,
+ 0x11241, 0x11241,
0x112df, 0x112df,
0x112e3, 0x112ea,
0x11300, 0x11301,
@@ -13195,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,
@@ -13226,9 +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,
@@ -15879,7 +16041,7 @@ static const OnigCodePoint CR_Changes_When_Casemapped[] = {
/* 'ID_Start': Derived Property */
static const OnigCodePoint CR_ID_Start[] = {
- 648,
+ 659,
0x0041, 0x005a,
0x0061, 0x007a,
0x00aa, 0x00aa,
@@ -16348,6 +16510,7 @@ static const OnigCodePoint CR_ID_Start[] = {
0x111dc, 0x111dc,
0x11200, 0x11211,
0x11213, 0x1122b,
+ 0x1123f, 0x11240,
0x11280, 0x11286,
0x11288, 0x11288,
0x1128a, 0x1128d,
@@ -16410,12 +16573,16 @@ 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,
0x12f90, 0x12ff0,
- 0x13000, 0x1342e,
+ 0x13000, 0x1342f,
+ 0x13441, 0x13446,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
@@ -16438,7 +16605,9 @@ static const OnigCodePoint CR_ID_Start[] = {
0x1aff5, 0x1affb,
0x1affd, 0x1affe,
0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -16476,11 +16645,14 @@ static const OnigCodePoint CR_ID_Start[] = {
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,
@@ -16522,17 +16694,18 @@ static const OnigCodePoint CR_ID_Start[] = {
0x1eea5, 0x1eea9,
0x1eeab, 0x1eebb,
0x20000, 0x2a6df,
- 0x2a700, 0x2b738,
+ 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[] = {
- 756,
+ 768,
0x0030, 0x0039,
0x0041, 0x005a,
0x005f, 0x005f,
@@ -16691,7 +16864,7 @@ static const OnigCodePoint CR_ID_Continue[] = {
0x0cdd, 0x0cde,
0x0ce0, 0x0ce3,
0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
+ 0x0cf1, 0x0cf3,
0x0d00, 0x0d0c,
0x0d0e, 0x0d10,
0x0d12, 0x0d44,
@@ -16724,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,
@@ -17037,7 +17210,7 @@ static const OnigCodePoint CR_ID_Continue[] = {
0x10e80, 0x10ea9,
0x10eab, 0x10eac,
0x10eb0, 0x10eb1,
- 0x10f00, 0x10f1c,
+ 0x10efd, 0x10f1c,
0x10f27, 0x10f27,
0x10f30, 0x10f50,
0x10f70, 0x10f85,
@@ -17060,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,
@@ -17141,12 +17314,17 @@ 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,
0x12f90, 0x12ff0,
- 0x13000, 0x1342e,
+ 0x13000, 0x1342f,
+ 0x13440, 0x13455,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
@@ -17174,7 +17352,9 @@ static const OnigCodePoint CR_ID_Continue[] = {
0x1aff5, 0x1affb,
0x1affd, 0x1affe,
0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -17228,17 +17408,21 @@ static const OnigCodePoint CR_ID_Continue[] = {
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,
@@ -17282,18 +17466,19 @@ static const OnigCodePoint CR_ID_Continue[] = {
0x1eeab, 0x1eebb,
0x1fbf0, 0x1fbf9,
0x20000, 0x2a6df,
- 0x2a700, 0x2b738,
+ 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[] = {
- 655,
+ 666,
0x0041, 0x005a,
0x0061, 0x007a,
0x00aa, 0x00aa,
@@ -17769,6 +17954,7 @@ static const OnigCodePoint CR_XID_Start[] = {
0x111dc, 0x111dc,
0x11200, 0x11211,
0x11213, 0x1122b,
+ 0x1123f, 0x11240,
0x11280, 0x11286,
0x11288, 0x11288,
0x1128a, 0x1128d,
@@ -17831,12 +18017,16 @@ 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,
0x12f90, 0x12ff0,
- 0x13000, 0x1342e,
+ 0x13000, 0x1342f,
+ 0x13441, 0x13446,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
@@ -17859,7 +18049,9 @@ static const OnigCodePoint CR_XID_Start[] = {
0x1aff5, 0x1affb,
0x1affd, 0x1affe,
0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -17897,11 +18089,14 @@ static const OnigCodePoint CR_XID_Start[] = {
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,
@@ -17943,17 +18138,18 @@ static const OnigCodePoint CR_XID_Start[] = {
0x1eea5, 0x1eea9,
0x1eeab, 0x1eebb,
0x20000, 0x2a6df,
- 0x2a700, 0x2b738,
+ 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[] = {
- 763,
+ 775,
0x0030, 0x0039,
0x0041, 0x005a,
0x005f, 0x005f,
@@ -18112,7 +18308,7 @@ static const OnigCodePoint CR_XID_Continue[] = {
0x0cdd, 0x0cde,
0x0ce0, 0x0ce3,
0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
+ 0x0cf1, 0x0cf3,
0x0d00, 0x0d0c,
0x0d0e, 0x0d10,
0x0d12, 0x0d44,
@@ -18145,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,
@@ -18465,7 +18661,7 @@ static const OnigCodePoint CR_XID_Continue[] = {
0x10e80, 0x10ea9,
0x10eab, 0x10eac,
0x10eb0, 0x10eb1,
- 0x10f00, 0x10f1c,
+ 0x10efd, 0x10f1c,
0x10f27, 0x10f27,
0x10f30, 0x10f50,
0x10f70, 0x10f85,
@@ -18488,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,
@@ -18569,12 +18765,17 @@ 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,
0x12f90, 0x12ff0,
- 0x13000, 0x1342e,
+ 0x13000, 0x1342f,
+ 0x13440, 0x13455,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
@@ -18602,7 +18803,9 @@ static const OnigCodePoint CR_XID_Continue[] = {
0x1aff5, 0x1affb,
0x1affd, 0x1affe,
0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -18656,17 +18859,21 @@ static const OnigCodePoint CR_XID_Continue[] = {
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,
@@ -18710,12 +18917,13 @@ static const OnigCodePoint CR_XID_Continue[] = {
0x1eeab, 0x1eebb,
0x1fbf0, 0x1fbf9,
0x20000, 0x2a6df,
- 0x2a700, 0x2b738,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
0xe0100, 0xe01ef,
}; /* CR_XID_Continue */
@@ -18743,7 +18951,7 @@ static const OnigCodePoint CR_Default_Ignorable_Code_Point[] = {
/* 'Grapheme_Extend': Derived Property */
static const OnigCodePoint CR_Grapheme_Extend[] = {
- 353,
+ 363,
0x0300, 0x036f,
0x0483, 0x0489,
0x0591, 0x05bd,
@@ -18846,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,
@@ -18975,6 +19183,7 @@ static const OnigCodePoint CR_Grapheme_Extend[] = {
0x10ae5, 0x10ae6,
0x10d24, 0x10d27,
0x10eab, 0x10eac,
+ 0x10efd, 0x10eff,
0x10f46, 0x10f50,
0x10f82, 0x10f85,
0x11001, 0x11001,
@@ -18997,6 +19206,7 @@ static const OnigCodePoint CR_Grapheme_Extend[] = {
0x11234, 0x11234,
0x11236, 0x11237,
0x1123e, 0x1123e,
+ 0x11241, 0x11241,
0x112df, 0x112df,
0x112e3, 0x112ea,
0x11300, 0x11301,
@@ -19064,6 +19274,12 @@ 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,
@@ -19090,9 +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,
@@ -19101,7 +19319,7 @@ static const OnigCodePoint CR_Grapheme_Extend[] = {
/* 'Grapheme_Base': Derived Property */
static const OnigCodePoint CR_Grapheme_Base[] = {
- 861,
+ 875,
0x0020, 0x007e,
0x00a0, 0x00ac,
0x00ae, 0x02ff,
@@ -19251,7 +19469,7 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x0cdd, 0x0cde,
0x0ce0, 0x0ce1,
0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
+ 0x0cf1, 0x0cf3,
0x0d02, 0x0d0c,
0x0d0e, 0x0d10,
0x0d12, 0x0d3a,
@@ -19670,6 +19888,7 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x11232, 0x11233,
0x11235, 0x11235,
0x11238, 0x1123d,
+ 0x1123f, 0x11240,
0x11280, 0x11286,
0x11288, 0x11288,
0x1128a, 0x1128d,
@@ -19756,6 +19975,7 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x11a97, 0x11a97,
0x11a9a, 0x11aa2,
0x11ab0, 0x11af8,
+ 0x11b00, 0x11b09,
0x11c00, 0x11c08,
0x11c0a, 0x11c2f,
0x11c3e, 0x11c3e,
@@ -19779,6 +19999,11 @@ 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,
@@ -19786,7 +20011,8 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x12470, 0x12474,
0x12480, 0x12543,
0x12f90, 0x12ff2,
- 0x13000, 0x1342e,
+ 0x13000, 0x1342f,
+ 0x13441, 0x13446,
0x14400, 0x14646,
0x16800, 0x16a38,
0x16a40, 0x16a5e,
@@ -19814,7 +20040,9 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x1aff5, 0x1affb,
0x1affd, 0x1affe,
0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
0x1b170, 0x1b2fb,
0x1bc00, 0x1bc6a,
@@ -19834,6 +20062,7 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x1d1ae, 0x1d1ea,
0x1d200, 0x1d241,
0x1d245, 0x1d245,
+ 0x1d2c0, 0x1d2d3,
0x1d2e0, 0x1d2f3,
0x1d300, 0x1d356,
0x1d360, 0x1d378,
@@ -19863,6 +20092,8 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x1da76, 0x1da83,
0x1da85, 0x1da8b,
0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e030, 0x1e06d,
0x1e100, 0x1e12c,
0x1e137, 0x1e13d,
0x1e140, 0x1e149,
@@ -19871,6 +20102,8 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x1e2c0, 0x1e2eb,
0x1e2f0, 0x1e2f9,
0x1e2ff, 0x1e2ff,
+ 0x1e4d0, 0x1e4eb,
+ 0x1e4f0, 0x1e4f9,
0x1e7e0, 0x1e7e6,
0x1e7e8, 0x1e7eb,
0x1e7ed, 0x1e7ee,
@@ -19930,10 +20163,10 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x1f250, 0x1f251,
0x1f260, 0x1f265,
0x1f300, 0x1f6d7,
- 0x1f6dd, 0x1f6ec,
+ 0x1f6dc, 0x1f6ec,
0x1f6f0, 0x1f6fc,
- 0x1f700, 0x1f773,
- 0x1f780, 0x1f7d8,
+ 0x1f700, 0x1f776,
+ 0x1f77b, 0x1f7d9,
0x1f7e0, 0x1f7eb,
0x1f7f0, 0x1f7f0,
0x1f800, 0x1f80b,
@@ -19944,30 +20177,29 @@ static const OnigCodePoint CR_Grapheme_Base[] = {
0x1f8b0, 0x1f8b1,
0x1f900, 0x1fa53,
0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa74,
- 0x1fa78, 0x1fa7c,
- 0x1fa80, 0x1fa86,
- 0x1fa90, 0x1faac,
- 0x1fab0, 0x1faba,
- 0x1fac0, 0x1fac5,
- 0x1fad0, 0x1fad9,
- 0x1fae0, 0x1fae7,
- 0x1faf0, 0x1faf6,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa88,
+ 0x1fa90, 0x1fabd,
+ 0x1fabf, 0x1fac5,
+ 0x1face, 0x1fadb,
+ 0x1fae0, 0x1fae8,
+ 0x1faf0, 0x1faf8,
0x1fb00, 0x1fb92,
0x1fb94, 0x1fbca,
0x1fbf0, 0x1fbf9,
0x20000, 0x2a6df,
- 0x2a700, 0x2b738,
+ 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[] = {
- 55,
+ 56,
0x094d, 0x094d,
0x09cd, 0x09cd,
0x0a4d, 0x0a4d,
@@ -20023,11 +20255,12 @@ static const OnigCodePoint CR_Grapheme_Link[] = {
0x11c3f, 0x11c3f,
0x11d44, 0x11d45,
0x11d97, 0x11d97,
+ 0x11f41, 0x11f42,
}; /* CR_Grapheme_Link */
/* 'Common': Script */
static const OnigCodePoint CR_Common[] = {
- 174,
+ 173,
0x0000, 0x0040,
0x005b, 0x0060,
0x007b, 0x00a9,
@@ -20134,6 +20367,7 @@ static const OnigCodePoint CR_Common[] = {
0x1d183, 0x1d184,
0x1d18c, 0x1d1a9,
0x1d1ae, 0x1d1ea,
+ 0x1d2c0, 0x1d2d3,
0x1d2e0, 0x1d2f3,
0x1d300, 0x1d356,
0x1d360, 0x1d378,
@@ -20174,10 +20408,10 @@ static const OnigCodePoint CR_Common[] = {
0x1f250, 0x1f251,
0x1f260, 0x1f265,
0x1f300, 0x1f6d7,
- 0x1f6dd, 0x1f6ec,
+ 0x1f6dc, 0x1f6ec,
0x1f6f0, 0x1f6fc,
- 0x1f700, 0x1f773,
- 0x1f780, 0x1f7d8,
+ 0x1f700, 0x1f776,
+ 0x1f77b, 0x1f7d9,
0x1f7e0, 0x1f7eb,
0x1f7f0, 0x1f7f0,
0x1f800, 0x1f80b,
@@ -20188,15 +20422,13 @@ static const OnigCodePoint CR_Common[] = {
0x1f8b0, 0x1f8b1,
0x1f900, 0x1fa53,
0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa74,
- 0x1fa78, 0x1fa7c,
- 0x1fa80, 0x1fa86,
- 0x1fa90, 0x1faac,
- 0x1fab0, 0x1faba,
- 0x1fac0, 0x1fac5,
- 0x1fad0, 0x1fad9,
- 0x1fae0, 0x1fae7,
- 0x1faf0, 0x1faf6,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa88,
+ 0x1fa90, 0x1fabd,
+ 0x1fabf, 0x1fac5,
+ 0x1face, 0x1fadb,
+ 0x1fae0, 0x1fae8,
+ 0x1faf0, 0x1faf8,
0x1fb00, 0x1fb92,
0x1fb94, 0x1fbca,
0x1fbf0, 0x1fbf9,
@@ -20206,7 +20438,7 @@ static const OnigCodePoint CR_Common[] = {
/* 'Latin': Script */
static const OnigCodePoint CR_Latin[] = {
- 38,
+ 39,
0x0041, 0x005a,
0x0061, 0x007a,
0x00aa, 0x00aa,
@@ -20245,6 +20477,7 @@ static const OnigCodePoint CR_Latin[] = {
0x10787, 0x107b0,
0x107b2, 0x107ba,
0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
}; /* CR_Latin */
/* 'Greek': Script */
@@ -20290,7 +20523,7 @@ static const OnigCodePoint CR_Greek[] = {
/* 'Cyrillic': Script */
static const OnigCodePoint CR_Cyrillic[] = {
- 8,
+ 10,
0x0400, 0x0484,
0x0487, 0x052f,
0x1c80, 0x1c88,
@@ -20299,6 +20532,8 @@ static const OnigCodePoint CR_Cyrillic[] = {
0x2de0, 0x2dff,
0xa640, 0xa69f,
0xfe2e, 0xfe2f,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
}; /* CR_Cyrillic */
/* 'Armenian': Script */
@@ -20326,7 +20561,7 @@ static const OnigCodePoint CR_Hebrew[] = {
/* 'Arabic': Script */
static const OnigCodePoint CR_Arabic[] = {
- 57,
+ 58,
0x0600, 0x0604,
0x0606, 0x060b,
0x060d, 0x061a,
@@ -20350,6 +20585,7 @@ static const OnigCodePoint CR_Arabic[] = {
0xfe70, 0xfe74,
0xfe76, 0xfefc,
0x10e60, 0x10e7e,
+ 0x10efd, 0x10eff,
0x1ee00, 0x1ee03,
0x1ee05, 0x1ee1f,
0x1ee21, 0x1ee22,
@@ -20403,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 */
@@ -20544,7 +20781,7 @@ static const OnigCodePoint CR_Kannada[] = {
0x0cdd, 0x0cde,
0x0ce0, 0x0ce3,
0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
+ 0x0cf1, 0x0cf3,
}; /* CR_Kannada */
/* 'Malayalam': Script */
@@ -20595,7 +20832,7 @@ static const OnigCodePoint CR_Lao[] = {
0x0ea7, 0x0ebd,
0x0ec0, 0x0ec4,
0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
+ 0x0ec8, 0x0ece,
0x0ed0, 0x0ed9,
0x0edc, 0x0edf,
}; /* CR_Lao */
@@ -20746,17 +20983,18 @@ static const OnigCodePoint CR_Mongolian[] = {
/* 'Hiragana': Script */
static const OnigCodePoint CR_Hiragana[] = {
- 5,
+ 6,
0x3041, 0x3096,
0x309d, 0x309f,
0x1b001, 0x1b11f,
+ 0x1b132, 0x1b132,
0x1b150, 0x1b152,
0x1f200, 0x1f200,
}; /* CR_Hiragana */
/* 'Katakana': Script */
static const OnigCodePoint CR_Katakana[] = {
- 13,
+ 14,
0x30a1, 0x30fa,
0x30fd, 0x30ff,
0x31f0, 0x31ff,
@@ -20769,6 +21007,7 @@ static const OnigCodePoint CR_Katakana[] = {
0x1affd, 0x1affe,
0x1b000, 0x1b000,
0x1b120, 0x1b122,
+ 0x1b155, 0x1b155,
0x1b164, 0x1b167,
}; /* CR_Katakana */
@@ -20782,7 +21021,7 @@ static const OnigCodePoint CR_Bopomofo[] = {
/* 'Han': Script */
static const OnigCodePoint CR_Han[] = {
- 20,
+ 21,
0x2e80, 0x2e99,
0x2e9b, 0x2ef3,
0x2f00, 0x2fd5,
@@ -20797,12 +21036,13 @@ static const OnigCodePoint CR_Han[] = {
0x16fe2, 0x16fe3,
0x16ff0, 0x16ff1,
0x20000, 0x2a6df,
- 0x2a700, 0x2b738,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
}; /* CR_Han */
/* 'Yi': Script */
@@ -21165,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 */
@@ -21382,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 */
@@ -21772,6 +22011,20 @@ static const OnigCodePoint CR_Vithkuqi[] = {
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
@@ -21853,7 +22106,7 @@ static const OnigCodePoint CR_Quotation_Mark[] = {
/* 'Terminal_Punctuation': Binary Property */
static const OnigCodePoint CR_Terminal_Punctuation[] = {
- 107,
+ 108,
0x0021, 0x0021,
0x002c, 0x002c,
0x002e, 0x002e,
@@ -21953,6 +22206,7 @@ static const OnigCodePoint CR_Terminal_Punctuation[] = {
0x11c41, 0x11c43,
0x11c71, 0x11c71,
0x11ef7, 0x11ef8,
+ 0x11f43, 0x11f44,
0x12470, 0x12474,
0x16a6e, 0x16a6f,
0x16af5, 0x16af5,
@@ -22118,7 +22372,7 @@ static const OnigCodePoint CR_Hex_Digit[] = {
/* 'Other_Alphabetic': Binary Property */
static const OnigCodePoint CR_Other_Alphabetic[] = {
- 233,
+ 240,
0x0345, 0x0345,
0x05b0, 0x05bd,
0x05bf, 0x05bf,
@@ -22178,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,
@@ -22190,6 +22444,7 @@ static const OnigCodePoint CR_Other_Alphabetic[] = {
0x0cca, 0x0ccc,
0x0cd5, 0x0cd6,
0x0ce2, 0x0ce3,
+ 0x0cf3, 0x0cf3,
0x0d00, 0x0d03,
0x0d3e, 0x0d44,
0x0d46, 0x0d48,
@@ -22208,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,
@@ -22281,7 +22536,7 @@ static const OnigCodePoint CR_Other_Alphabetic[] = {
0x11000, 0x11002,
0x11038, 0x11045,
0x11073, 0x11074,
- 0x11082, 0x11082,
+ 0x11080, 0x11082,
0x110b0, 0x110b8,
0x110c2, 0x110c2,
0x11100, 0x11102,
@@ -22293,6 +22548,7 @@ static const OnigCodePoint CR_Other_Alphabetic[] = {
0x1122c, 0x11234,
0x11237, 0x11237,
0x1123e, 0x1123e,
+ 0x11241, 0x11241,
0x112df, 0x112e8,
0x11300, 0x11303,
0x1133e, 0x11344,
@@ -22338,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,
@@ -22348,6 +22608,7 @@ static const OnigCodePoint CR_Other_Alphabetic[] = {
0x1e01b, 0x1e021,
0x1e023, 0x1e024,
0x1e026, 0x1e02a,
+ 0x1e08f, 0x1e08f,
0x1e947, 0x1e947,
0x1f130, 0x1f149,
0x1f150, 0x1f169,
@@ -22356,7 +22617,7 @@ static const OnigCodePoint CR_Other_Alphabetic[] = {
/* 'Ideographic': Binary Property */
static const OnigCodePoint CR_Ideographic[] = {
- 19,
+ 20,
0x3006, 0x3007,
0x3021, 0x3029,
0x3038, 0x303a,
@@ -22370,17 +22631,18 @@ static const OnigCodePoint CR_Ideographic[] = {
0x18d00, 0x18d08,
0x1b170, 0x1b2fb,
0x20000, 0x2a6df,
- 0x2a700, 0x2b738,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x2f800, 0x2fa1d,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
}; /* CR_Ideographic */
/* 'Diacritic': Binary Property */
static const OnigCodePoint CR_Diacritic[] = {
- 192,
+ 195,
0x005e, 0x005e,
0x0060, 0x0060,
0x00a8, 0x00a8,
@@ -22520,6 +22782,7 @@ static const OnigCodePoint CR_Diacritic[] = {
0x107b2, 0x107ba,
0x10ae5, 0x10ae6,
0x10d22, 0x10d27,
+ 0x10efd, 0x10eff,
0x10f46, 0x10f50,
0x10f82, 0x10f85,
0x11046, 0x11046,
@@ -22553,6 +22816,7 @@ static const OnigCodePoint CR_Diacritic[] = {
0x11d42, 0x11d42,
0x11d44, 0x11d45,
0x11d97, 0x11d97,
+ 0x13447, 0x13455,
0x16af0, 0x16af4,
0x16b30, 0x16b36,
0x16f8f, 0x16f9f,
@@ -22567,6 +22831,7 @@ static const OnigCodePoint CR_Diacritic[] = {
0x1d17b, 0x1d182,
0x1d185, 0x1d18b,
0x1d1aa, 0x1d1ad,
+ 0x1e030, 0x1e06d,
0x1e130, 0x1e136,
0x1e2ae, 0x1e2ae,
0x1e2ec, 0x1e2ef,
@@ -22615,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,
@@ -22623,6 +22888,7 @@ static const OnigCodePoint CR_Other_Lowercase[] = {
0x02e0, 0x02e4,
0x0345, 0x0345,
0x037a, 0x037a,
+ 0x10fc, 0x10fc,
0x1d2c, 0x1d6a,
0x1d78, 0x1d78,
0x1d9b, 0x1dbf,
@@ -22634,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 */
@@ -22724,7 +22997,7 @@ static const OnigCodePoint CR_Radical[] = {
/* 'Unified_Ideograph': Binary Property */
static const OnigCodePoint CR_Unified_Ideograph[] = {
- 15,
+ 16,
0x3400, 0x4dbf,
0x4e00, 0x9fff,
0xfa0e, 0xfa0f,
@@ -22735,11 +23008,12 @@ static const OnigCodePoint CR_Unified_Ideograph[] = {
0xfa23, 0xfa24,
0xfa27, 0xfa29,
0x20000, 0x2a6df,
- 0x2a700, 0x2b738,
+ 0x2a700, 0x2b739,
0x2b740, 0x2b81d,
0x2b820, 0x2cea1,
0x2ceb0, 0x2ebe0,
0x30000, 0x3134a,
+ 0x31350, 0x323af,
}; /* CR_Unified_Ideograph */
/* 'Other_Default_Ignorable_Code_Point': Binary Property */
@@ -22773,7 +23047,7 @@ static const OnigCodePoint CR_Deprecated[] = {
/* 'Soft_Dotted': Binary Property */
static const OnigCodePoint CR_Soft_Dotted[] = {
- 32,
+ 34,
0x0069, 0x006a,
0x012f, 0x012f,
0x0249, 0x0249,
@@ -22806,6 +23080,8 @@ static const OnigCodePoint CR_Soft_Dotted[] = {
0x1d65e, 0x1d65f,
0x1d692, 0x1d693,
0x1df1a, 0x1df1a,
+ 0x1e04c, 0x1e04d,
+ 0x1e068, 0x1e068,
}; /* CR_Soft_Dotted */
/* 'Logical_Order_Exception': Binary Property */
@@ -22840,7 +23116,7 @@ static const OnigCodePoint CR_Other_ID_Continue[] = {
/* 'Sentence_Terminal': Binary Property */
static const OnigCodePoint CR_Sentence_Terminal[] = {
- 79,
+ 80,
0x0021, 0x0021,
0x002e, 0x002e,
0x003f, 0x003f,
@@ -22913,6 +23189,7 @@ static const OnigCodePoint CR_Sentence_Terminal[] = {
0x11a9b, 0x11a9c,
0x11c41, 0x11c42,
0x11ef7, 0x11ef8,
+ 0x11f43, 0x11f44,
0x16a6e, 0x16a6f,
0x16af5, 0x16af5,
0x16b37, 0x16b38,
@@ -22994,7 +23271,7 @@ static const OnigCodePoint CR_Regional_Indicator[] = {
/* 'Emoji': Emoji */
static const OnigCodePoint CR_Emoji[] = {
- 153,
+ 151,
0x0023, 0x0023,
0x002a, 0x002a,
0x0030, 0x0039,
@@ -23129,7 +23406,7 @@ static const OnigCodePoint CR_Emoji[] = {
0x1f680, 0x1f6c5,
0x1f6cb, 0x1f6d2,
0x1f6d5, 0x1f6d7,
- 0x1f6dd, 0x1f6e5,
+ 0x1f6dc, 0x1f6e5,
0x1f6e9, 0x1f6e9,
0x1f6eb, 0x1f6ec,
0x1f6f0, 0x1f6f0,
@@ -23139,20 +23416,18 @@ static const OnigCodePoint CR_Emoji[] = {
0x1f90c, 0x1f93a,
0x1f93c, 0x1f945,
0x1f947, 0x1f9ff,
- 0x1fa70, 0x1fa74,
- 0x1fa78, 0x1fa7c,
- 0x1fa80, 0x1fa86,
- 0x1fa90, 0x1faac,
- 0x1fab0, 0x1faba,
- 0x1fac0, 0x1fac5,
- 0x1fad0, 0x1fad9,
- 0x1fae0, 0x1fae7,
- 0x1faf0, 0x1faf6,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa88,
+ 0x1fa90, 0x1fabd,
+ 0x1fabf, 0x1fac5,
+ 0x1face, 0x1fadb,
+ 0x1fae0, 0x1fae8,
+ 0x1faf0, 0x1faf8,
}; /* CR_Emoji */
/* 'Emoji_Presentation': Emoji */
static const OnigCodePoint CR_Emoji_Presentation[] = {
- 83,
+ 81,
0x231a, 0x231b,
0x23e9, 0x23ec,
0x23f0, 0x23f0,
@@ -23219,7 +23494,7 @@ static const OnigCodePoint CR_Emoji_Presentation[] = {
0x1f6cc, 0x1f6cc,
0x1f6d0, 0x1f6d2,
0x1f6d5, 0x1f6d7,
- 0x1f6dd, 0x1f6df,
+ 0x1f6dc, 0x1f6df,
0x1f6eb, 0x1f6ec,
0x1f6f4, 0x1f6fc,
0x1f7e0, 0x1f7eb,
@@ -23227,15 +23502,13 @@ static const OnigCodePoint CR_Emoji_Presentation[] = {
0x1f90c, 0x1f93a,
0x1f93c, 0x1f945,
0x1f947, 0x1f9ff,
- 0x1fa70, 0x1fa74,
- 0x1fa78, 0x1fa7c,
- 0x1fa80, 0x1fa86,
- 0x1fa90, 0x1faac,
- 0x1fab0, 0x1faba,
- 0x1fac0, 0x1fac5,
- 0x1fad0, 0x1fad9,
- 0x1fae0, 0x1fae7,
- 0x1faf0, 0x1faf6,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa88,
+ 0x1fa90, 0x1fabd,
+ 0x1fabf, 0x1fac5,
+ 0x1face, 0x1fadb,
+ 0x1fae0, 0x1fae8,
+ 0x1faf0, 0x1faf8,
}; /* CR_Emoji_Presentation */
/* 'Emoji_Modifier': Emoji */
@@ -23286,7 +23559,7 @@ static const OnigCodePoint CR_Emoji_Modifier_Base[] = {
0x1f9cd, 0x1f9cf,
0x1f9d1, 0x1f9dd,
0x1fac3, 0x1fac5,
- 0x1faf0, 0x1faf6,
+ 0x1faf0, 0x1faf8,
}; /* CR_Emoji_Modifier_Base */
/* 'Emoji_Component': Emoji */
@@ -23389,7 +23662,7 @@ static const OnigCodePoint CR_Extended_Pictographic[] = {
/* 'Unknown': Script */
static const OnigCodePoint CR_Unknown[] = {
- 696,
+ 705,
0x0378, 0x0379,
0x0380, 0x0383,
0x038b, 0x038b,
@@ -23511,7 +23784,7 @@ static const OnigCodePoint CR_Unknown[] = {
0x0cdf, 0x0cdf,
0x0ce4, 0x0ce5,
0x0cf0, 0x0cf0,
- 0x0cf3, 0x0cff,
+ 0x0cf4, 0x0cff,
0x0d0d, 0x0d0d,
0x0d11, 0x0d11,
0x0d45, 0x0d45,
@@ -23541,7 +23814,7 @@ static const OnigCodePoint CR_Unknown[] = {
0x0ebe, 0x0ebf,
0x0ec5, 0x0ec5,
0x0ec7, 0x0ec7,
- 0x0ece, 0x0ecf,
+ 0x0ecf, 0x0ecf,
0x0eda, 0x0edb,
0x0ee0, 0x0eff,
0x0f48, 0x0f48,
@@ -23811,7 +24084,7 @@ static const OnigCodePoint CR_Unknown[] = {
0x10e7f, 0x10e7f,
0x10eaa, 0x10eaa,
0x10eae, 0x10eaf,
- 0x10eb2, 0x10eff,
+ 0x10eb2, 0x10efc,
0x10f28, 0x10f2f,
0x10f5a, 0x10f6f,
0x10f8a, 0x10faf,
@@ -23829,7 +24102,7 @@ static const OnigCodePoint CR_Unknown[] = {
0x111e0, 0x111e0,
0x111f5, 0x111ff,
0x11212, 0x11212,
- 0x1123f, 0x1127f,
+ 0x11242, 0x1127f,
0x11287, 0x11287,
0x11289, 0x11289,
0x1128e, 0x1128e,
@@ -23881,7 +24154,8 @@ static const OnigCodePoint CR_Unknown[] = {
0x119e5, 0x119ff,
0x11a48, 0x11a4f,
0x11aa3, 0x11aaf,
- 0x11af9, 0x11bff,
+ 0x11af9, 0x11aff,
+ 0x11b0a, 0x11bff,
0x11c09, 0x11c09,
0x11c37, 0x11c37,
0x11c46, 0x11c4f,
@@ -23902,7 +24176,10 @@ 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,
@@ -23910,8 +24187,7 @@ static const OnigCodePoint CR_Unknown[] = {
0x12475, 0x1247f,
0x12544, 0x12f8f,
0x12ff3, 0x12fff,
- 0x1342f, 0x1342f,
- 0x13439, 0x143ff,
+ 0x13456, 0x143ff,
0x14647, 0x167ff,
0x16a39, 0x16a3f,
0x16a5f, 0x16a5f,
@@ -23937,8 +24213,10 @@ static const OnigCodePoint CR_Unknown[] = {
0x1aff4, 0x1aff4,
0x1affc, 0x1affc,
0x1afff, 0x1afff,
- 0x1b123, 0x1b14f,
- 0x1b153, 0x1b163,
+ 0x1b123, 0x1b131,
+ 0x1b133, 0x1b14f,
+ 0x1b153, 0x1b154,
+ 0x1b156, 0x1b163,
0x1b168, 0x1b16f,
0x1b2fc, 0x1bbff,
0x1bc6b, 0x1bc6f,
@@ -23952,7 +24230,8 @@ static const OnigCodePoint CR_Unknown[] = {
0x1d0f6, 0x1d0ff,
0x1d127, 0x1d128,
0x1d1eb, 0x1d1ff,
- 0x1d246, 0x1d2df,
+ 0x1d246, 0x1d2bf,
+ 0x1d2d4, 0x1d2df,
0x1d2f4, 0x1d2ff,
0x1d357, 0x1d35f,
0x1d379, 0x1d3ff,
@@ -23979,19 +24258,23 @@ static const OnigCodePoint CR_Unknown[] = {
0x1da8c, 0x1da9a,
0x1daa0, 0x1daa0,
0x1dab0, 0x1deff,
- 0x1df1f, 0x1dfff,
+ 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, 0x1e28f,
0x1e2af, 0x1e2bf,
0x1e2fa, 0x1e2fe,
- 0x1e300, 0x1e7df,
+ 0x1e300, 0x1e4cf,
+ 0x1e4fa, 0x1e7df,
0x1e7e7, 0x1e7e7,
0x1e7ec, 0x1e7ec,
0x1e7ef, 0x1e7ef,
@@ -24049,11 +24332,11 @@ static const OnigCodePoint CR_Unknown[] = {
0x1f249, 0x1f24f,
0x1f252, 0x1f25f,
0x1f266, 0x1f2ff,
- 0x1f6d8, 0x1f6dc,
+ 0x1f6d8, 0x1f6db,
0x1f6ed, 0x1f6ef,
0x1f6fd, 0x1f6ff,
- 0x1f774, 0x1f77f,
- 0x1f7d9, 0x1f7df,
+ 0x1f777, 0x1f77a,
+ 0x1f7da, 0x1f7df,
0x1f7ec, 0x1f7ef,
0x1f7f1, 0x1f7ff,
0x1f80c, 0x1f80f,
@@ -24064,25 +24347,24 @@ static const OnigCodePoint CR_Unknown[] = {
0x1f8b2, 0x1f8ff,
0x1fa54, 0x1fa5f,
0x1fa6e, 0x1fa6f,
- 0x1fa75, 0x1fa77,
0x1fa7d, 0x1fa7f,
- 0x1fa87, 0x1fa8f,
- 0x1faad, 0x1faaf,
- 0x1fabb, 0x1fabf,
- 0x1fac6, 0x1facf,
- 0x1fada, 0x1fadf,
- 0x1fae8, 0x1faef,
- 0x1faf7, 0x1faff,
+ 0x1fa89, 0x1fa8f,
+ 0x1fabe, 0x1fabe,
+ 0x1fac6, 0x1facd,
+ 0x1fadc, 0x1fadf,
+ 0x1fae9, 0x1faef,
+ 0x1faf9, 0x1faff,
0x1fb93, 0x1fb93,
0x1fbcb, 0x1fbef,
0x1fbfa, 0x1ffff,
0x2a6e0, 0x2a6ff,
- 0x2b739, 0x2b73f,
+ 0x2b73a, 0x2b73f,
0x2b81e, 0x2b81f,
0x2cea2, 0x2ceaf,
0x2ebe1, 0x2f7ff,
0x2fa1e, 0x2ffff,
- 0x3134b, 0xe0000,
+ 0x3134b, 0x3134f,
+ 0x323b0, 0xe0000,
0xe0002, 0xe001f,
0xe0080, 0xe00ff,
0xe01f0, 0x10ffff,
@@ -36632,10 +36914,730 @@ static const OnigCodePoint CR_Age_14_0[] = {
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[] = {
- 14,
+ 15,
0x0600, 0x0605,
0x06dd, 0x06dd,
0x070f, 0x070f,
@@ -36650,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 */
@@ -36677,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,
@@ -36687,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[] = {
- 354,
+ 364,
0x0300, 0x036f,
0x0483, 0x0489,
0x0591, 0x05bd,
@@ -36790,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,
@@ -36919,6 +37922,7 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = {
0x10ae5, 0x10ae6,
0x10d24, 0x10d27,
0x10eab, 0x10eac,
+ 0x10efd, 0x10eff,
0x10f46, 0x10f50,
0x10f82, 0x10f85,
0x11001, 0x11001,
@@ -36941,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,
@@ -37008,6 +38013,12 @@ 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,
@@ -37034,9 +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,
@@ -37049,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[] = {
- 161,
+ 165,
0x0903, 0x0903,
0x093b, 0x093b,
0x093e, 0x0940,
@@ -37081,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,
@@ -37183,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,
@@ -37207,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,
@@ -39275,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,
@@ -39458,6 +40481,12 @@ static const OnigCodePoint CR_In_Pau_Cin_Hau[] = {
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,
@@ -39488,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,
@@ -39533,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 */
@@ -39680,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,
@@ -39722,6 +40763,12 @@ static const OnigCodePoint CR_In_Glagolitic_Supplement[] = {
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,
@@ -39740,6 +40787,12 @@ static const OnigCodePoint CR_In_Wancho[] = {
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,
@@ -39914,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,
@@ -39952,7 +41011,6 @@ static const OnigCodePoint CR_In_No_Block[] = {
0x10bb0, 0x10bff,
0x10c50, 0x10c7f,
0x10d40, 0x10e5f,
- 0x10ec0, 0x10eff,
0x11250, 0x1127f,
0x11380, 0x113ff,
0x114e0, 0x1157f,
@@ -39960,12 +41018,12 @@ static const OnigCodePoint CR_In_No_Block[] = {
0x11750, 0x117ff,
0x11850, 0x1189f,
0x11960, 0x1199f,
- 0x11b00, 0x11bff,
+ 0x11b60, 0x11bff,
0x11cc0, 0x11cff,
0x11db0, 0x11edf,
- 0x11f00, 0x11faf,
+ 0x11f60, 0x11faf,
0x12550, 0x12f8f,
- 0x13440, 0x143ff,
+ 0x13460, 0x143ff,
0x14680, 0x167ff,
0x16b90, 0x16e3f,
0x16ea0, 0x16eff,
@@ -39974,12 +41032,13 @@ static const OnigCodePoint CR_In_No_Block[] = {
0x1b300, 0x1bbff,
0x1bcb0, 0x1ceff,
0x1cfd0, 0x1cfff,
- 0x1d250, 0x1d2df,
+ 0x1d250, 0x1d2bf,
0x1d380, 0x1d3ff,
0x1dab0, 0x1deff,
- 0x1e030, 0x1e0ff,
+ 0x1e090, 0x1e0ff,
0x1e150, 0x1e28f,
- 0x1e300, 0x1e7df,
+ 0x1e300, 0x1e4cf,
+ 0x1e500, 0x1e7df,
0x1e8e0, 0x1e8ff,
0x1e960, 0x1ec6f,
0x1ecc0, 0x1ecff,
@@ -39989,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 */
@@ -40233,6 +41292,8 @@ static const OnigCodePoint* const CodeRanges[] = {
CR_Tangsa,
CR_Toto,
CR_Vithkuqi,
+ CR_Kawi,
+ CR_Nag_Mundari,
CR_White_Space,
CR_Bidi_Control,
CR_Join_Control,
@@ -40299,6 +41360,7 @@ static const OnigCodePoint* const CodeRanges[] = {
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,
@@ -40522,6 +41584,7 @@ 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,
@@ -40553,11 +41616,13 @@ static const OnigCodePoint* const CodeRanges[] = {
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,
@@ -40590,6 +41655,7 @@ static const OnigCodePoint* const CodeRanges[] = {
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,
@@ -40597,9 +41663,11 @@ static const OnigCodePoint* const CodeRanges[] = {
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,
@@ -40629,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,
@@ -40642,11 +41711,7 @@ 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
@@ -40657,9 +41722,9 @@ static const struct uniname2ctype_struct *uniname2ctype_p(
/* maximum key range = 15, duplicates = 0 */
#else /* USE_UNICODE_PROPERTIES */
#ifndef USE_UNICODE_AGE_PROPERTIES
-#define TOTAL_KEYWORDS 856
+#define TOTAL_KEYWORDS 866
#else /* USE_UNICODE_AGE_PROPERTIES */
-#define TOTAL_KEYWORDS 880
+#define TOTAL_KEYWORDS 891
#endif /* USE_UNICODE_AGE_PROPERTIES */
#define MIN_WORD_LENGTH 1
#define MAX_WORD_LENGTH 45
@@ -40708,13 +41773,13 @@ uniname2ctype_hash (register const char *str, register size_t len)
6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099,
#else /* USE_UNICODE_AGE_PROPERTIES */
6099, 6099, 6099, 6099, 6099, 6099, 12, 6099, 3, 1,
- 4, 8, 36, 24, 14, 16, 10, 7, 6099, 6099,
+ 4, 8, 32, 26, 14, 17, 10, 7, 6099, 6099,
#endif /* USE_UNICODE_AGE_PROPERTIES */
6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099,
6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099,
6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099,
6099, 6099, 6099, 6099, 6099, 6099, 6099, 1, 1425, 113,
- 437, 37, 1086, 1071, 1051, 4, 1267, 9, 500, 88,
+ 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 */
@@ -40944,6 +42009,7 @@ struct uniname2ctype_pool_t
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")];
@@ -40958,6 +42024,7 @@ struct uniname2ctype_pool_t
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")];
@@ -41078,11 +42145,13 @@ 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")];
@@ -41126,48 +42195,46 @@ struct uniname2ctype_pool_t
#ifdef USE_UNICODE_AGE_PROPERTIES
char uniname2ctype_pool_str1257[sizeof("age=6.0")];
char uniname2ctype_pool_str1258[sizeof("age=6.2")];
- char uniname2ctype_pool_str1259[sizeof("age=7.0")];
+ 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=5.1")];
+ 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.0")];
- char uniname2ctype_pool_str1268[sizeof("age=5.2")];
- char uniname2ctype_pool_str1269[sizeof("age=14.0")];
+ char uniname2ctype_pool_str1267[sizeof("age=5.1")];
+ char uniname2ctype_pool_str1269[sizeof("age=5.0")];
+ char uniname2ctype_pool_str1270[sizeof("age=5.2")];
#endif /* USE_UNICODE_AGE_PROPERTIES */
char uniname2ctype_pool_str1271[sizeof("diacritic")];
+#ifdef USE_UNICODE_AGE_PROPERTIES
+ char uniname2ctype_pool_str1273[sizeof("age=4.1")];
+#endif /* USE_UNICODE_AGE_PROPERTIES */
char uniname2ctype_pool_str1274[sizeof("ahom")];
#ifdef USE_UNICODE_AGE_PROPERTIES
- char uniname2ctype_pool_str1277[sizeof("age=4.1")];
- char uniname2ctype_pool_str1279[sizeof("age=4.0")];
+ char uniname2ctype_pool_str1275[sizeof("age=4.0")];
#endif /* USE_UNICODE_AGE_PROPERTIES */
char uniname2ctype_pool_str1282[sizeof("incjkunifiedideographsextensione")];
- char uniname2ctype_pool_str1284[sizeof("hani")];
char uniname2ctype_pool_str1285[sizeof("khmr")];
- char uniname2ctype_pool_str1287[sizeof("han")];
char uniname2ctype_pool_str1289[sizeof("insinhala")];
char uniname2ctype_pool_str1292[sizeof("inmiscellaneoustechnical")];
char uniname2ctype_pool_str1297[sizeof("saur")];
- char uniname2ctype_pool_str1298[sizeof("hano")];
char uniname2ctype_pool_str1300[sizeof("guru")];
char uniname2ctype_pool_str1301[sizeof("sundanese")];
char uniname2ctype_pool_str1306[sizeof("punct")];
char uniname2ctype_pool_str1314[sizeof("paucinhau")];
char uniname2ctype_pool_str1317[sizeof("gurmukhi")];
- char uniname2ctype_pool_str1323[sizeof("inkhojki")];
- char uniname2ctype_pool_str1327[sizeof("hanunoo")];
char uniname2ctype_pool_str1328[sizeof("chorasmian")];
- char uniname2ctype_pool_str1330[sizeof("hira")];
char uniname2ctype_pool_str1331[sizeof("logicalorderexception")];
char uniname2ctype_pool_str1340[sizeof("khmer")];
char uniname2ctype_pool_str1343[sizeof("limbu")];
char uniname2ctype_pool_str1349[sizeof("chrs")];
char uniname2ctype_pool_str1352[sizeof("oriya")];
char uniname2ctype_pool_str1354[sizeof("inscriptionalpahlavi")];
+ char uniname2ctype_pool_str1356[sizeof("incyrillicextendedd")];
char uniname2ctype_pool_str1358[sizeof("incjkunifiedideographsextensionc")];
char uniname2ctype_pool_str1360[sizeof("cntrl")];
char uniname2ctype_pool_str1365[sizeof("inlatinextendedadditional")];
@@ -41235,7 +42302,6 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str1587[sizeof("indogra")];
char uniname2ctype_pool_str1597[sizeof("arab")];
char uniname2ctype_pool_str1598[sizeof("medefaidrin")];
- char uniname2ctype_pool_str1601[sizeof("hatran")];
char uniname2ctype_pool_str1607[sizeof("inshorthandformatcontrols")];
char uniname2ctype_pool_str1613[sizeof("phli")];
char uniname2ctype_pool_str1617[sizeof("inimperialaramaic")];
@@ -41244,7 +42310,6 @@ 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_str1636[sizeof("hatr")];
char uniname2ctype_pool_str1643[sizeof("cwl")];
char uniname2ctype_pool_str1644[sizeof("vith")];
char uniname2ctype_pool_str1654[sizeof("ingeometricshapes")];
@@ -41302,7 +42367,6 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str1845[sizeof("oidc")];
char uniname2ctype_pool_str1848[sizeof("bopo")];
char uniname2ctype_pool_str1851[sizeof("cuneiform")];
- char uniname2ctype_pool_str1857[sizeof("hex")];
char uniname2ctype_pool_str1866[sizeof("caseignorable")];
char uniname2ctype_pool_str1871[sizeof("inoldpersian")];
char uniname2ctype_pool_str1881[sizeof("cwu")];
@@ -41321,10 +42385,8 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str1935[sizeof("oids")];
char uniname2ctype_pool_str1936[sizeof("inarabicextendeda")];
char uniname2ctype_pool_str1941[sizeof("modifierletter")];
- char uniname2ctype_pool_str1948[sizeof("gujr")];
char uniname2ctype_pool_str1950[sizeof("incjksymbolsandpunctuation")];
char uniname2ctype_pool_str1956[sizeof("olower")];
- char uniname2ctype_pool_str1957[sizeof("gujarati")];
char uniname2ctype_pool_str1958[sizeof("bopomofo")];
char uniname2ctype_pool_str1964[sizeof("inlisu")];
char uniname2ctype_pool_str1967[sizeof("inoldpermic")];
@@ -41338,19 +42400,26 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str1993[sizeof("inbalinese")];
char uniname2ctype_pool_str1994[sizeof("sorasompeng")];
char uniname2ctype_pool_str1996[sizeof("closepunctuation")];
+ char uniname2ctype_pool_str2001[sizeof("hani")];
char uniname2ctype_pool_str2002[sizeof("inmayannumerals")];
+ char uniname2ctype_pool_str2004[sizeof("han")];
char uniname2ctype_pool_str2006[sizeof("inmiscellaneousmathematicalsymbolsb")];
char uniname2ctype_pool_str2010[sizeof("inlepcha")];
char uniname2ctype_pool_str2011[sizeof("patsyn")];
char uniname2ctype_pool_str2012[sizeof("inlisusupplement")];
char uniname2ctype_pool_str2014[sizeof("insyriacsupplement")];
+ char uniname2ctype_pool_str2015[sizeof("hano")];
char uniname2ctype_pool_str2016[sizeof("newa")];
char uniname2ctype_pool_str2023[sizeof("spacingmark")];
char uniname2ctype_pool_str2024[sizeof("inpalmyrene")];
char uniname2ctype_pool_str2026[sizeof("takr")];
char uniname2ctype_pool_str2033[sizeof("xposixpunct")];
+ char uniname2ctype_pool_str2040[sizeof("inkhojki")];
char uniname2ctype_pool_str2042[sizeof("taile")];
char uniname2ctype_pool_str2043[sizeof("assigned")];
+ char uniname2ctype_pool_str2044[sizeof("hanunoo")];
+ char uniname2ctype_pool_str2047[sizeof("hira")];
+ char uniname2ctype_pool_str2048[sizeof("inarabicextendedc")];
char uniname2ctype_pool_str2062[sizeof("newtailue")];
char uniname2ctype_pool_str2070[sizeof("space")];
char uniname2ctype_pool_str2073[sizeof("intelugu")];
@@ -41401,41 +42470,35 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str2278[sizeof("shaw")];
char uniname2ctype_pool_str2279[sizeof("palmyrene")];
char uniname2ctype_pool_str2283[sizeof("soyo")];
+ char uniname2ctype_pool_str2296[sizeof("incjkunifiedideographsextensionh")];
char uniname2ctype_pool_str2305[sizeof("sgnw")];
char uniname2ctype_pool_str2308[sizeof("toto")];
char uniname2ctype_pool_str2312[sizeof("caucasianalbanian")];
char uniname2ctype_pool_str2315[sizeof("inmathematicalalphanumericsymbols")];
char uniname2ctype_pool_str2316[sizeof("incjkunifiedideographsextensiong")];
+ char uniname2ctype_pool_str2318[sizeof("hatran")];
char uniname2ctype_pool_str2321[sizeof("taiviet")];
char uniname2ctype_pool_str2323[sizeof("meroitichieroglyphs")];
char uniname2ctype_pool_str2327[sizeof("ingeorgianextended")];
char uniname2ctype_pool_str2331[sizeof("incjkunifiedideographsextensionf")];
char uniname2ctype_pool_str2333[sizeof("oldpersian")];
- char uniname2ctype_pool_str2341[sizeof("mahj")];
char uniname2ctype_pool_str2343[sizeof("induployan")];
char uniname2ctype_pool_str2344[sizeof("incyrillicextendedb")];
char uniname2ctype_pool_str2345[sizeof("dash")];
- char uniname2ctype_pool_str2350[sizeof("mahajani")];
- char uniname2ctype_pool_str2351[sizeof("hang")];
+ char uniname2ctype_pool_str2353[sizeof("hatr")];
char uniname2ctype_pool_str2361[sizeof("innyiakengpuachuehmong")];
char uniname2ctype_pool_str2364[sizeof("incombiningdiacriticalmarks")];
- char uniname2ctype_pool_str2370[sizeof("ingujarati")];
char uniname2ctype_pool_str2373[sizeof("nl")];
char uniname2ctype_pool_str2374[sizeof("incombiningdiacriticalmarksforsymbols")];
char uniname2ctype_pool_str2375[sizeof("khudawadi")];
- char uniname2ctype_pool_str2389[sizeof("ingunjalagondi")];
char uniname2ctype_pool_str2397[sizeof("incjkradicalssupplement")];
char uniname2ctype_pool_str2398[sizeof("inglagolitic")];
char uniname2ctype_pool_str2405[sizeof("orkh")];
- char uniname2ctype_pool_str2406[sizeof("hiragana")];
char uniname2ctype_pool_str2414[sizeof("syrc")];
- char uniname2ctype_pool_str2418[sizeof("inrejang")];
char uniname2ctype_pool_str2427[sizeof("surrogate")];
- char uniname2ctype_pool_str2428[sizeof("khoj")];
char uniname2ctype_pool_str2433[sizeof("indevanagari")];
char uniname2ctype_pool_str2434[sizeof("avestan")];
char uniname2ctype_pool_str2437[sizeof("oldpermic")];
- char uniname2ctype_pool_str2438[sizeof("hmng")];
char uniname2ctype_pool_str2440[sizeof("ethi")];
char uniname2ctype_pool_str2451[sizeof("ogam")];
char uniname2ctype_pool_str2454[sizeof("rohg")];
@@ -41443,7 +42506,7 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str2464[sizeof("java")];
char uniname2ctype_pool_str2470[sizeof("inphagspa")];
char uniname2ctype_pool_str2475[sizeof("lepcha")];
- char uniname2ctype_pool_str2476[sizeof("inenclosedcjklettersandmonths")];
+ char uniname2ctype_pool_str2476[sizeof("indevanagariextendeda")];
char uniname2ctype_pool_str2478[sizeof("intifinagh")];
char uniname2ctype_pool_str2479[sizeof("intagalog")];
char uniname2ctype_pool_str2481[sizeof("incombiningdiacriticalmarkssupplement")];
@@ -41453,6 +42516,7 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str2513[sizeof("insymbolsandpictographsextendeda")];
char uniname2ctype_pool_str2530[sizeof("syriac")];
char uniname2ctype_pool_str2534[sizeof("inbengali")];
+ char uniname2ctype_pool_str2535[sizeof("nagm")];
char uniname2ctype_pool_str2545[sizeof("extendedpictographic")];
char uniname2ctype_pool_str2548[sizeof("buhd")];
char uniname2ctype_pool_str2549[sizeof("javanese")];
@@ -41461,6 +42525,7 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str2567[sizeof("inlatin1supplement")];
char uniname2ctype_pool_str2570[sizeof("ingothic")];
char uniname2ctype_pool_str2572[sizeof("invariationselectors")];
+ char uniname2ctype_pool_str2574[sizeof("hex")];
char uniname2ctype_pool_str2575[sizeof("inverticalforms")];
char uniname2ctype_pool_str2576[sizeof("ebase")];
char uniname2ctype_pool_str2582[sizeof("incurrencysymbols")];
@@ -41474,15 +42539,15 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str2652[sizeof("invedicextensions")];
char uniname2ctype_pool_str2656[sizeof("inlimbu")];
char uniname2ctype_pool_str2657[sizeof("olditalic")];
- char uniname2ctype_pool_str2660[sizeof("rjng")];
+ char uniname2ctype_pool_str2665[sizeof("gujr")];
char uniname2ctype_pool_str2666[sizeof("mathsymbol")];
char uniname2ctype_pool_str2670[sizeof("incjkunifiedideographsextensionb")];
+ char uniname2ctype_pool_str2674[sizeof("gujarati")];
char uniname2ctype_pool_str2688[sizeof("phagspa")];
char uniname2ctype_pool_str2689[sizeof("invariationselectorssupplement")];
char uniname2ctype_pool_str2694[sizeof("currencysymbol")];
char uniname2ctype_pool_str2705[sizeof("inlinearbsyllabary")];
char uniname2ctype_pool_str2726[sizeof("wancho")];
- char uniname2ctype_pool_str2738[sizeof("hmnp")];
char uniname2ctype_pool_str2750[sizeof("inpaucinhau")];
char uniname2ctype_pool_str2761[sizeof("other")];
char uniname2ctype_pool_str2762[sizeof("otheridcontinue")];
@@ -41492,7 +42557,6 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str2772[sizeof("warangciti")];
char uniname2ctype_pool_str2775[sizeof("othernumber")];
char uniname2ctype_pool_str2786[sizeof("digit")];
- char uniname2ctype_pool_str2787[sizeof("hebr")];
char uniname2ctype_pool_str2793[sizeof("nonspacingmark")];
char uniname2ctype_pool_str2801[sizeof("titlecaseletter")];
char uniname2ctype_pool_str2808[sizeof("inmeroiticcursive")];
@@ -41512,7 +42576,6 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str2871[sizeof("noncharactercodepoint")];
char uniname2ctype_pool_str2879[sizeof("oldhungarian")];
char uniname2ctype_pool_str2886[sizeof("insymbolsforlegacycomputing")];
- char uniname2ctype_pool_str2901[sizeof("hangul")];
char uniname2ctype_pool_str2902[sizeof("insmallformvariants")];
char uniname2ctype_pool_str2904[sizeof("inhangulsyllables")];
char uniname2ctype_pool_str2905[sizeof("emojipresentation")];
@@ -41524,15 +42587,12 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str2964[sizeof("inpsalterpahlavi")];
char uniname2ctype_pool_str2966[sizeof("whitespace")];
char uniname2ctype_pool_str2967[sizeof("finalpunctuation")];
- char uniname2ctype_pool_str2969[sizeof("hung")];
char uniname2ctype_pool_str2970[sizeof("orya")];
- char uniname2ctype_pool_str2972[sizeof("hexdigit")];
char uniname2ctype_pool_str2980[sizeof("phlp")];
char uniname2ctype_pool_str2984[sizeof("inbamumsupplement")];
char uniname2ctype_pool_str2986[sizeof("buhid")];
char uniname2ctype_pool_str2987[sizeof("paragraphseparator")];
char uniname2ctype_pool_str2988[sizeof("inalphabeticpresentationforms")];
- char uniname2ctype_pool_str2993[sizeof("hluw")];
char uniname2ctype_pool_str2997[sizeof("inlatinextendedg")];
char uniname2ctype_pool_str3001[sizeof("elba")];
char uniname2ctype_pool_str3002[sizeof("changeswhentitlecased")];
@@ -41549,30 +42609,39 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str3048[sizeof("tagbanwa")];
char uniname2ctype_pool_str3052[sizeof("tamil")];
char uniname2ctype_pool_str3053[sizeof("khitansmallscript")];
+ char uniname2ctype_pool_str3058[sizeof("mahj")];
+ char uniname2ctype_pool_str3067[sizeof("mahajani")];
+ char uniname2ctype_pool_str3068[sizeof("hang")];
char uniname2ctype_pool_str3071[sizeof("tirh")];
char uniname2ctype_pool_str3072[sizeof("sylotinagri")];
char uniname2ctype_pool_str3082[sizeof("talu")];
+ char uniname2ctype_pool_str3084[sizeof("nagmundari")];
char uniname2ctype_pool_str3086[sizeof("deva")];
+ char uniname2ctype_pool_str3087[sizeof("ingujarati")];
char uniname2ctype_pool_str3091[sizeof("deprecated")];
char uniname2ctype_pool_str3099[sizeof("inarabicpresentationformsb")];
char uniname2ctype_pool_str3104[sizeof("devanagari")];
+ char uniname2ctype_pool_str3106[sizeof("ingunjalagondi")];
char uniname2ctype_pool_str3107[sizeof("graphemeclusterbreak=t")];
char uniname2ctype_pool_str3109[sizeof("graphemeclusterbreak=lvt")];
char uniname2ctype_pool_str3110[sizeof("taitham")];
char uniname2ctype_pool_str3111[sizeof("nbat")];
char uniname2ctype_pool_str3118[sizeof("telu")];
+ char uniname2ctype_pool_str3123[sizeof("hiragana")];
char uniname2ctype_pool_str3125[sizeof("nabataean")];
- char uniname2ctype_pool_str3140[sizeof("inmahjongtiles")];
+ char uniname2ctype_pool_str3135[sizeof("inrejang")];
char uniname2ctype_pool_str3142[sizeof("intangutsupplement")];
+ char uniname2ctype_pool_str3145[sizeof("khoj")];
+ char uniname2ctype_pool_str3155[sizeof("hmng")];
char uniname2ctype_pool_str3157[sizeof("cyprominoan")];
char uniname2ctype_pool_str3158[sizeof("inhebrew")];
char uniname2ctype_pool_str3176[sizeof("inmathematicaloperators")];
char uniname2ctype_pool_str3180[sizeof("inarabicsupplement")];
+ char uniname2ctype_pool_str3193[sizeof("inenclosedcjklettersandmonths")];
char uniname2ctype_pool_str3209[sizeof("changeswhenlowercased")];
char uniname2ctype_pool_str3212[sizeof("tangut")];
char uniname2ctype_pool_str3215[sizeof("elbasan")];
char uniname2ctype_pool_str3218[sizeof("osmanya")];
- char uniname2ctype_pool_str3227[sizeof("inyijinghexagramsymbols")];
char uniname2ctype_pool_str3237[sizeof("insuperscriptsandsubscripts")];
char uniname2ctype_pool_str3239[sizeof("graphemeclusterbreak=extend")];
char uniname2ctype_pool_str3240[sizeof("graphemeclusterbreak=prepend")];
@@ -41583,7 +42652,6 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str3275[sizeof("kayahli")];
char uniname2ctype_pool_str3284[sizeof("inplayingcards")];
char uniname2ctype_pool_str3287[sizeof("elym")];
- char uniname2ctype_pool_str3290[sizeof("injavanese")];
char uniname2ctype_pool_str3297[sizeof("graphemeclusterbreak=l")];
char uniname2ctype_pool_str3303[sizeof("graphemeclusterbreak=control")];
char uniname2ctype_pool_str3313[sizeof("ogrext")];
@@ -41599,6 +42667,7 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str3371[sizeof("cypriot")];
char uniname2ctype_pool_str3372[sizeof("any")];
char uniname2ctype_pool_str3373[sizeof("otheruppercase")];
+ char uniname2ctype_pool_str3377[sizeof("rjng")];
char uniname2ctype_pool_str3391[sizeof("wspace")];
char uniname2ctype_pool_str3396[sizeof("inindicsiyaqnumbers")];
char uniname2ctype_pool_str3405[sizeof("inprivateusearea")];
@@ -41606,11 +42675,12 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str3428[sizeof("oupper")];
char uniname2ctype_pool_str3433[sizeof("signwriting")];
char uniname2ctype_pool_str3436[sizeof("nushu")];
- char uniname2ctype_pool_str3452[sizeof("hanifirohingya")];
+ char uniname2ctype_pool_str3455[sizeof("hmnp")];
char uniname2ctype_pool_str3458[sizeof("upper")];
char uniname2ctype_pool_str3460[sizeof("insupplementalarrowsc")];
char uniname2ctype_pool_str3483[sizeof("omath")];
char uniname2ctype_pool_str3502[sizeof("modifiersymbol")];
+ char uniname2ctype_pool_str3504[sizeof("hebr")];
char uniname2ctype_pool_str3505[sizeof("inhalfwidthandfullwidthforms")];
char uniname2ctype_pool_str3511[sizeof("insupplementalmathematicaloperators")];
char uniname2ctype_pool_str3532[sizeof("inpahawhhmong")];
@@ -41619,60 +42689,68 @@ struct uniname2ctype_pool_t
char uniname2ctype_pool_str3580[sizeof("dupl")];
char uniname2ctype_pool_str3590[sizeof("ogham")];
char uniname2ctype_pool_str3613[sizeof("dashpunctuation")];
+ char uniname2ctype_pool_str3618[sizeof("hangul")];
char uniname2ctype_pool_str3648[sizeof("inhanguljamoextendedb")];
char uniname2ctype_pool_str3659[sizeof("bassavah")];
char uniname2ctype_pool_str3664[sizeof("aghb")];
+ char uniname2ctype_pool_str3686[sizeof("hung")];
+ char uniname2ctype_pool_str3689[sizeof("hexdigit")];
char uniname2ctype_pool_str3698[sizeof("incypriotsyllabary")];
char uniname2ctype_pool_str3699[sizeof("indivesakuru")];
char uniname2ctype_pool_str3701[sizeof("tibt")];
char uniname2ctype_pool_str3705[sizeof("inlatinextendedb")];
+ char uniname2ctype_pool_str3710[sizeof("hluw")];
char uniname2ctype_pool_str3713[sizeof("tibetan")];
char uniname2ctype_pool_str3721[sizeof("inyisyllables")];
char uniname2ctype_pool_str3744[sizeof("oldnortharabian")];
char uniname2ctype_pool_str3754[sizeof("defaultignorablecodepoint")];
char uniname2ctype_pool_str3766[sizeof("inhighprivateusesurrogates")];
- char uniname2ctype_pool_str3770[sizeof("rejang")];
char uniname2ctype_pool_str3799[sizeof("soyombo")];
char uniname2ctype_pool_str3807[sizeof("otherdefaultignorablecodepoint")];
char uniname2ctype_pool_str3842[sizeof("pahawhhmong")];
char uniname2ctype_pool_str3845[sizeof("unifiedideograph")];
char uniname2ctype_pool_str3850[sizeof("othermath")];
char uniname2ctype_pool_str3854[sizeof("changeswhencasefolded")];
+ char uniname2ctype_pool_str3857[sizeof("inmahjongtiles")];
char uniname2ctype_pool_str3868[sizeof("dep")];
char uniname2ctype_pool_str3881[sizeof("divesakuru")];
char uniname2ctype_pool_str3884[sizeof("graphemeclusterbreak=lf")];
char uniname2ctype_pool_str3891[sizeof("uppercaseletter")];
char uniname2ctype_pool_str3924[sizeof("insupplementalpunctuation")];
char uniname2ctype_pool_str3942[sizeof("ethiopic")];
+ char uniname2ctype_pool_str3944[sizeof("inyijinghexagramsymbols")];
char uniname2ctype_pool_str3949[sizeof("ecomp")];
char uniname2ctype_pool_str3976[sizeof("inglagoliticsupplement")];
- char uniname2ctype_pool_str3978[sizeof("hebrew")];
char uniname2ctype_pool_str3998[sizeof("inbopomofoextended")];
- char uniname2ctype_pool_str4066[sizeof("graphemeclusterbreak=zwj")];
+ char uniname2ctype_pool_str4007[sizeof("injavanese")];
char uniname2ctype_pool_str4106[sizeof("otherpunctuation")];
char uniname2ctype_pool_str4116[sizeof("tifinagh")];
char uniname2ctype_pool_str4127[sizeof("tfng")];
+ char uniname2ctype_pool_str4169[sizeof("hanifirohingya")];
char uniname2ctype_pool_str4231[sizeof("tavt")];
char uniname2ctype_pool_str4308[sizeof("inboxdrawing")];
char uniname2ctype_pool_str4309[sizeof("oldsoutharabian")];
- char uniname2ctype_pool_str4321[sizeof("hyphen")];
char uniname2ctype_pool_str4348[sizeof("inegyptianhieroglyphs")];
char uniname2ctype_pool_str4361[sizeof("inegyptianhieroglyphformatcontrols")];
char uniname2ctype_pool_str4459[sizeof("tagb")];
+ char uniname2ctype_pool_str4487[sizeof("rejang")];
char uniname2ctype_pool_str4604[sizeof("tglg")];
char uniname2ctype_pool_str4626[sizeof("tagalog")];
char uniname2ctype_pool_str4627[sizeof("othergraphemeextend")];
char uniname2ctype_pool_str4674[sizeof("insupplementaryprivateuseareaa")];
char uniname2ctype_pool_str4683[sizeof("inhighsurrogates")];
+ char uniname2ctype_pool_str4695[sizeof("hebrew")];
char uniname2ctype_pool_str4734[sizeof("duployan")];
char uniname2ctype_pool_str4755[sizeof("graphemeclusterbreak=v")];
char uniname2ctype_pool_str4756[sizeof("graphemeclusterbreak=lv")];
char uniname2ctype_pool_str4772[sizeof("insupplementalarrowsb")];
+ char uniname2ctype_pool_str4783[sizeof("graphemeclusterbreak=zwj")];
char uniname2ctype_pool_str4810[sizeof("telugu")];
char uniname2ctype_pool_str4898[sizeof("zyyy")];
char uniname2ctype_pool_str4982[sizeof("olduyghur")];
char uniname2ctype_pool_str4986[sizeof("inhangulcompatibilityjamo")];
char uniname2ctype_pool_str5018[sizeof("openpunctuation")];
+ char uniname2ctype_pool_str5038[sizeof("hyphen")];
char uniname2ctype_pool_str5134[sizeof("insupplementalsymbolsandpictographs")];
char uniname2ctype_pool_str5141[sizeof("egyp")];
char uniname2ctype_pool_str5300[sizeof("nyiakengpuachuehmong")];
@@ -41849,6 +42927,7 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"innewa",
"sk",
"control",
+ "inkawi",
"inancientsymbols",
"palm",
"inlycian",
@@ -41863,6 +42942,7 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"inwarangciti",
"sora",
"inopticalcharacterrecognition",
+ "kawi",
"inoldsogdian",
"inmalayalam",
"bamum",
@@ -41995,11 +43075,13 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"inogham",
"cher",
"chakma",
+ "inkaktoviknumerals",
"emoji",
"insiddham",
"cherokee",
"khar",
"inmongolian",
+ "innagmundari",
"incherokeesupplement",
"manichaean",
"inolchiki",
@@ -42043,48 +43125,46 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
#ifdef USE_UNICODE_AGE_PROPERTIES
"age=6.0",
"age=6.2",
+ "age=15.0",
"age=7.0",
"age=6.3",
#endif /* USE_UNICODE_AGE_PROPERTIES */
"cwt",
#ifdef USE_UNICODE_AGE_PROPERTIES
- "age=5.1",
+ "age=14.0",
#endif /* USE_UNICODE_AGE_PROPERTIES */
"unassigned",
#ifdef USE_UNICODE_AGE_PROPERTIES
+ "age=5.1",
"age=5.0",
"age=5.2",
- "age=14.0",
#endif /* USE_UNICODE_AGE_PROPERTIES */
"diacritic",
- "ahom",
#ifdef USE_UNICODE_AGE_PROPERTIES
"age=4.1",
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ "ahom",
+#ifdef USE_UNICODE_AGE_PROPERTIES
"age=4.0",
#endif /* USE_UNICODE_AGE_PROPERTIES */
"incjkunifiedideographsextensione",
- "hani",
"khmr",
- "han",
"insinhala",
"inmiscellaneoustechnical",
"saur",
- "hano",
"guru",
"sundanese",
"punct",
"paucinhau",
"gurmukhi",
- "inkhojki",
- "hanunoo",
"chorasmian",
- "hira",
"logicalorderexception",
"khmer",
"limbu",
"chrs",
"oriya",
"inscriptionalpahlavi",
+ "incyrillicextendedd",
"incjkunifiedideographsextensionc",
#endif /* USE_UNICODE_PROPERTIES */
"cntrl",
@@ -42156,7 +43236,6 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"indogra",
"arab",
"medefaidrin",
- "hatran",
"inshorthandformatcontrols",
"phli",
"inimperialaramaic",
@@ -42165,7 +43244,6 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"inanatolianhieroglyphs",
"punctuation",
"graphemeextend",
- "hatr",
"cwl",
"vith",
"ingeometricshapes",
@@ -42223,7 +43301,6 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"oidc",
"bopo",
"cuneiform",
- "hex",
"caseignorable",
"inoldpersian",
"cwu",
@@ -42242,10 +43319,8 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"oids",
"inarabicextendeda",
"modifierletter",
- "gujr",
"incjksymbolsandpunctuation",
"olower",
- "gujarati",
"bopomofo",
"inlisu",
"inoldpermic",
@@ -42259,12 +43334,15 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"inbalinese",
"sorasompeng",
"closepunctuation",
+ "hani",
"inmayannumerals",
+ "han",
"inmiscellaneousmathematicalsymbolsb",
"inlepcha",
"patsyn",
"inlisusupplement",
"insyriacsupplement",
+ "hano",
"newa",
"spacingmark",
"inpalmyrene",
@@ -42274,8 +43352,12 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
#ifndef USE_UNICODE_PROPERTIES
"lower",
#else /* USE_UNICODE_PROPERTIES */
+ "inkhojki",
"taile",
"assigned",
+ "hanunoo",
+ "hira",
+ "inarabicextendedc",
"newtailue",
"space",
"intelugu",
@@ -42328,41 +43410,35 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"shaw",
"palmyrene",
"soyo",
+ "incjkunifiedideographsextensionh",
"sgnw",
"toto",
"caucasianalbanian",
"inmathematicalalphanumericsymbols",
"incjkunifiedideographsextensiong",
+ "hatran",
"taiviet",
"meroitichieroglyphs",
"ingeorgianextended",
"incjkunifiedideographsextensionf",
"oldpersian",
- "mahj",
"induployan",
"incyrillicextendedb",
"dash",
- "mahajani",
- "hang",
+ "hatr",
"innyiakengpuachuehmong",
"incombiningdiacriticalmarks",
- "ingujarati",
"nl",
"incombiningdiacriticalmarksforsymbols",
"khudawadi",
- "ingunjalagondi",
"incjkradicalssupplement",
"inglagolitic",
"orkh",
- "hiragana",
"syrc",
- "inrejang",
"surrogate",
- "khoj",
"indevanagari",
"avestan",
"oldpermic",
- "hmng",
"ethi",
"ogam",
"rohg",
@@ -42370,7 +43446,7 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"java",
"inphagspa",
"lepcha",
- "inenclosedcjklettersandmonths",
+ "indevanagariextendeda",
"intifinagh",
"intagalog",
"incombiningdiacriticalmarkssupplement",
@@ -42380,6 +43456,7 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"insymbolsandpictographsextendeda",
"syriac",
"inbengali",
+ "nagm",
"extendedpictographic",
"buhd",
"javanese",
@@ -42388,6 +43465,7 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"inlatin1supplement",
"ingothic",
"invariationselectors",
+ "hex",
"inverticalforms",
"ebase",
"incurrencysymbols",
@@ -42401,15 +43479,15 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"invedicextensions",
"inlimbu",
"olditalic",
- "rjng",
+ "gujr",
"mathsymbol",
"incjkunifiedideographsextensionb",
+ "gujarati",
"phagspa",
"invariationselectorssupplement",
"currencysymbol",
"inlinearbsyllabary",
"wancho",
- "hmnp",
"inpaucinhau",
"other",
"otheridcontinue",
@@ -42423,7 +43501,6 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
#ifndef USE_UNICODE_PROPERTIES
"blank"
#else /* USE_UNICODE_PROPERTIES */
- "hebr",
"nonspacingmark",
"titlecaseletter",
"inmeroiticcursive",
@@ -42443,7 +43520,6 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"noncharactercodepoint",
"oldhungarian",
"insymbolsforlegacycomputing",
- "hangul",
"insmallformvariants",
"inhangulsyllables",
"emojipresentation",
@@ -42455,15 +43531,12 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"inpsalterpahlavi",
"whitespace",
"finalpunctuation",
- "hung",
"orya",
- "hexdigit",
"phlp",
"inbamumsupplement",
"buhid",
"paragraphseparator",
"inalphabeticpresentationforms",
- "hluw",
"inlatinextendedg",
"elba",
"changeswhentitlecased",
@@ -42480,30 +43553,39 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"tagbanwa",
"tamil",
"khitansmallscript",
+ "mahj",
+ "mahajani",
+ "hang",
"tirh",
"sylotinagri",
"talu",
+ "nagmundari",
"deva",
+ "ingujarati",
"deprecated",
"inarabicpresentationformsb",
"devanagari",
+ "ingunjalagondi",
"graphemeclusterbreak=t",
"graphemeclusterbreak=lvt",
"taitham",
"nbat",
"telu",
+ "hiragana",
"nabataean",
- "inmahjongtiles",
+ "inrejang",
"intangutsupplement",
+ "khoj",
+ "hmng",
"cyprominoan",
"inhebrew",
"inmathematicaloperators",
"inarabicsupplement",
+ "inenclosedcjklettersandmonths",
"changeswhenlowercased",
"tangut",
"elbasan",
"osmanya",
- "inyijinghexagramsymbols",
"insuperscriptsandsubscripts",
"graphemeclusterbreak=extend",
"graphemeclusterbreak=prepend",
@@ -42514,7 +43596,6 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"kayahli",
"inplayingcards",
"elym",
- "injavanese",
"graphemeclusterbreak=l",
"graphemeclusterbreak=control",
"ogrext",
@@ -42530,6 +43611,7 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"cypriot",
"any",
"otheruppercase",
+ "rjng",
"wspace",
"inindicsiyaqnumbers",
"inprivateusearea",
@@ -42537,11 +43619,12 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"oupper",
"signwriting",
"nushu",
- "hanifirohingya",
+ "hmnp",
"upper",
"insupplementalarrowsc",
"omath",
"modifiersymbol",
+ "hebr",
"inhalfwidthandfullwidthforms",
"insupplementalmathematicaloperators",
"inpahawhhmong",
@@ -42550,60 +43633,68 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
"dupl",
"ogham",
"dashpunctuation",
+ "hangul",
"inhanguljamoextendedb",
"bassavah",
"aghb",
+ "hung",
+ "hexdigit",
"incypriotsyllabary",
"indivesakuru",
"tibt",
"inlatinextendedb",
+ "hluw",
"tibetan",
"inyisyllables",
"oldnortharabian",
"defaultignorablecodepoint",
"inhighprivateusesurrogates",
- "rejang",
"soyombo",
"otherdefaultignorablecodepoint",
"pahawhhmong",
"unifiedideograph",
"othermath",
"changeswhencasefolded",
+ "inmahjongtiles",
"dep",
"divesakuru",
"graphemeclusterbreak=lf",
"uppercaseletter",
"insupplementalpunctuation",
"ethiopic",
+ "inyijinghexagramsymbols",
"ecomp",
"inglagoliticsupplement",
- "hebrew",
"inbopomofoextended",
- "graphemeclusterbreak=zwj",
+ "injavanese",
"otherpunctuation",
"tifinagh",
"tfng",
+ "hanifirohingya",
"tavt",
"inboxdrawing",
"oldsoutharabian",
- "hyphen",
"inegyptianhieroglyphs",
"inegyptianhieroglyphformatcontrols",
"tagb",
+ "rejang",
"tglg",
"tagalog",
"othergraphemeextend",
"insupplementaryprivateuseareaa",
"inhighsurrogates",
+ "hebrew",
"duployan",
"graphemeclusterbreak=v",
"graphemeclusterbreak=lv",
"insupplementalarrowsb",
+ "graphemeclusterbreak=zwj",
"telugu",
"zyyy",
"olduyghur",
"inhangulcompatibilityjamo",
"openpunctuation",
+ "hyphen",
"insupplementalsymbolsandpictographs",
"egyp",
"nyiakengpuachuehmong",
@@ -42639,13 +43730,13 @@ uniname2ctype_p (register const char *str, register size_t len)
{uniname2ctype_offset(str48), 95},
{uniname2ctype_offset(str49), 95},
{-1}, {-1},
- {uniname2ctype_offset(str52), 343},
+ {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), 330},
+ {uniname2ctype_offset(str66), 333},
{uniname2ctype_offset(str67), 52},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str71), 181},
@@ -42663,9 +43754,9 @@ uniname2ctype_p (register const char *str, register size_t len)
{uniname2ctype_offset(str94), 33},
{-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str100), 149},
- {uniname2ctype_offset(str101), 510},
+ {uniname2ctype_offset(str101), 513},
{uniname2ctype_offset(str102), 108},
- {uniname2ctype_offset(str103), 261},
+ {uniname2ctype_offset(str103), 263},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str107), 31},
{uniname2ctype_offset(str108), 77},
@@ -42684,27 +43775,27 @@ uniname2ctype_p (register const char *str, register size_t len)
{uniname2ctype_offset(str130), 42},
{uniname2ctype_offset(str131), 172},
{-1}, {-1},
- {uniname2ctype_offset(str134), 494},
+ {uniname2ctype_offset(str134), 497},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str139), 170},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str145), 513},
- {uniname2ctype_offset(str146), 569},
+ {uniname2ctype_offset(str145), 516},
+ {uniname2ctype_offset(str146), 575},
{-1},
- {uniname2ctype_offset(str148), 574},
- {uniname2ctype_offset(str149), 531},
+ {uniname2ctype_offset(str148), 580},
+ {uniname2ctype_offset(str149), 535},
{-1},
{uniname2ctype_offset(str151), 18},
{uniname2ctype_offset(str152), 169},
{uniname2ctype_offset(str153), 160},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str158), 276},
+ {uniname2ctype_offset(str158), 278},
{-1}, {-1},
- {uniname2ctype_offset(str161), 324},
+ {uniname2ctype_offset(str161), 327},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str177), 349},
- {uniname2ctype_offset(str178), 558},
+ {uniname2ctype_offset(str177), 352},
+ {uniname2ctype_offset(str178), 563},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str183), 75},
{-1}, {-1},
@@ -42713,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), 357},
- {uniname2ctype_offset(str204), 485},
+ {uniname2ctype_offset(str203), 360},
+ {uniname2ctype_offset(str204), 488},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str210), 575},
+ {uniname2ctype_offset(str210), 581},
{-1},
- {uniname2ctype_offset(str212), 362},
+ {uniname2ctype_offset(str212), 365},
{uniname2ctype_offset(str213), 115},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str218), 545},
+ {uniname2ctype_offset(str218), 549},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str226), 171},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str230), 526},
+ {uniname2ctype_offset(str230), 530},
{uniname2ctype_offset(str231), 31},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str236), 25},
@@ -42737,64 +43828,64 @@ 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), 562},
+ {uniname2ctype_offset(str260), 568},
{-1}, {-1},
{uniname2ctype_offset(str263), 161},
{-1},
{uniname2ctype_offset(str265), 19},
{-1},
{uniname2ctype_offset(str267), 79},
- {uniname2ctype_offset(str268), 354},
+ {uniname2ctype_offset(str268), 357},
{-1},
- {uniname2ctype_offset(str270), 268},
+ {uniname2ctype_offset(str270), 270},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str274), 561},
- {uniname2ctype_offset(str275), 514},
+ {uniname2ctype_offset(str274), 567},
+ {uniname2ctype_offset(str275), 517},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str281), 318},
+ {uniname2ctype_offset(str281), 321},
{uniname2ctype_offset(str282), 40},
{uniname2ctype_offset(str283), 79},
{-1},
- {uniname2ctype_offset(str285), 533},
+ {uniname2ctype_offset(str285), 537},
{-1},
{uniname2ctype_offset(str287), 144},
{uniname2ctype_offset(str288), 144},
- {uniname2ctype_offset(str289), 555},
+ {uniname2ctype_offset(str289), 560},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str293), 218},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str297), 212},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str301), 392},
+ {uniname2ctype_offset(str301), 395},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str311), 322},
+ {uniname2ctype_offset(str311), 325},
{-1},
- {uniname2ctype_offset(str313), 453},
+ {uniname2ctype_offset(str313), 456},
{-1},
- {uniname2ctype_offset(str315), 241},
+ {uniname2ctype_offset(str315), 243},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str320), 269},
+ {uniname2ctype_offset(str320), 271},
{-1},
{uniname2ctype_offset(str322), 129},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str328), 331},
+ {uniname2ctype_offset(str328), 334},
{-1}, {-1},
{uniname2ctype_offset(str331), 76},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str335), 556},
+ {uniname2ctype_offset(str335), 561},
{-1}, {-1},
- {uniname2ctype_offset(str338), 329},
+ {uniname2ctype_offset(str338), 332},
{-1},
{uniname2ctype_offset(str340), 76},
{-1},
- {uniname2ctype_offset(str342), 346},
+ {uniname2ctype_offset(str342), 349},
{-1}, {-1},
{uniname2ctype_offset(str345), 53},
- {uniname2ctype_offset(str346), 268},
+ {uniname2ctype_offset(str346), 270},
{-1},
- {uniname2ctype_offset(str348), 423},
+ {uniname2ctype_offset(str348), 426},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str352), 529},
+ {uniname2ctype_offset(str352), 533},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str362), 163},
{-1}, {-1}, {-1},
@@ -42802,14 +43893,14 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str373), 160},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str381), 550},
+ {uniname2ctype_offset(str381), 554},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str386), 368},
+ {uniname2ctype_offset(str386), 371},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str399), 327},
+ {uniname2ctype_offset(str399), 330},
{-1},
- {uniname2ctype_offset(str401), 544},
+ {uniname2ctype_offset(str401), 548},
{-1}, {-1},
{uniname2ctype_offset(str404), 81},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
@@ -42832,176 +43923,179 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1},
{uniname2ctype_offset(str470), 22},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str475), 521},
+ {uniname2ctype_offset(str475), 524},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str480), 454},
+ {uniname2ctype_offset(str480), 457},
{uniname2ctype_offset(str481), 188},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str486), 473},
+ {uniname2ctype_offset(str486), 476},
{-1},
- {uniname2ctype_offset(str488), 582},
+ {uniname2ctype_offset(str488), 588},
{-1}, {-1},
- {uniname2ctype_offset(str491), 467},
+ {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), 247},
+ {uniname2ctype_offset(str505), 249},
{uniname2ctype_offset(str506), 24},
{-1}, {-1},
{uniname2ctype_offset(str509), 24},
{-1},
- {uniname2ctype_offset(str511), 460},
+ {uniname2ctype_offset(str511), 463},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str520), 420},
+ {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), 549},
+ {uniname2ctype_offset(str541), 553},
{-1},
{uniname2ctype_offset(str543), 91},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str556), 542},
+ {uniname2ctype_offset(str556), 546},
{-1},
- {uniname2ctype_offset(str558), 347},
+ {uniname2ctype_offset(str558), 350},
{uniname2ctype_offset(str559), 70},
- {uniname2ctype_offset(str560), 512},
+ {uniname2ctype_offset(str560), 515},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str565), 615},
+ {uniname2ctype_offset(str565), 624},
{uniname2ctype_offset(str566), 37},
{-1},
{uniname2ctype_offset(str568), 113},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str572), 499},
+ {uniname2ctype_offset(str572), 502},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str577), 602},
+ {uniname2ctype_offset(str577), 611},
{-1},
{uniname2ctype_offset(str579), 106},
{-1}, {-1},
- {uniname2ctype_offset(str582), 403},
- {uniname2ctype_offset(str583), 477},
+ {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), 613},
+ {uniname2ctype_offset(str596), 622},
{uniname2ctype_offset(str597), 146},
{-1}, {-1},
- {uniname2ctype_offset(str600), 487},
+ {uniname2ctype_offset(str600), 490},
{-1},
{uniname2ctype_offset(str602), 70},
{-1},
- {uniname2ctype_offset(str604), 573},
- {uniname2ctype_offset(str605), 620},
+ {uniname2ctype_offset(str604), 579},
+ {uniname2ctype_offset(str605), 629},
{-1}, {-1},
- {uniname2ctype_offset(str608), 628},
+ {uniname2ctype_offset(str608), 637},
{uniname2ctype_offset(str609), 229},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str614), 603},
+ {uniname2ctype_offset(str614), 612},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str624), 195},
- {uniname2ctype_offset(str625), 444},
+ {uniname2ctype_offset(str625), 447},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str630), 29},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str636), 539},
+ {uniname2ctype_offset(str636), 543},
{-1}, {-1},
{uniname2ctype_offset(str639), 49},
{-1}, {-1},
{uniname2ctype_offset(str642), 19},
- {-1}, {-1},
- {uniname2ctype_offset(str645), 482},
+ {uniname2ctype_offset(str643), 564},
+ {-1},
+ {uniname2ctype_offset(str645), 485},
{-1},
{uniname2ctype_offset(str647), 192},
{-1}, {-1},
- {uniname2ctype_offset(str650), 484},
+ {uniname2ctype_offset(str650), 487},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str657), 51},
{-1}, {-1},
- {uniname2ctype_offset(str660), 266},
+ {uniname2ctype_offset(str660), 268},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1},
- {uniname2ctype_offset(str672), 332},
+ {uniname2ctype_offset(str672), 335},
{-1}, {-1},
{uniname2ctype_offset(str675), 68},
{-1}, {-1},
{uniname2ctype_offset(str678), 171},
- {uniname2ctype_offset(str679), 599},
+ {uniname2ctype_offset(str679), 607},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str683), 265},
+ {uniname2ctype_offset(str683), 267},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str692), 69},
{-1}, {-1},
- {uniname2ctype_offset(str695), 547},
+ {uniname2ctype_offset(str695), 551},
{uniname2ctype_offset(str696), 175},
- {uniname2ctype_offset(str697), 396},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str703), 523},
+ {uniname2ctype_offset(str697), 399},
+ {-1}, {-1},
+ {uniname2ctype_offset(str700), 236},
+ {-1}, {-1},
+ {uniname2ctype_offset(str703), 527},
{-1},
- {uniname2ctype_offset(str705), 344},
+ {uniname2ctype_offset(str705), 347},
{-1},
{uniname2ctype_offset(str707), 158},
- {uniname2ctype_offset(str708), 581},
+ {uniname2ctype_offset(str708), 587},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str713), 373},
+ {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), 370},
+ {uniname2ctype_offset(str738), 373},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str742), 6},
{-1}, {-1},
- {uniname2ctype_offset(str745), 267},
+ {uniname2ctype_offset(str745), 269},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str753), 238},
+ {uniname2ctype_offset(str753), 240},
{-1},
- {uniname2ctype_offset(str755), 511},
+ {uniname2ctype_offset(str755), 514},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str760), 428},
+ {uniname2ctype_offset(str760), 431},
{uniname2ctype_offset(str761), 167},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str766), 156},
- {uniname2ctype_offset(str767), 600},
+ {uniname2ctype_offset(str767), 608},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str771), 167},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str776), 266},
+ {uniname2ctype_offset(str776), 268},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str783), 156},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str787), 254},
+ {uniname2ctype_offset(str787), 256},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str791), 193},
{-1}, {-1},
- {uniname2ctype_offset(str794), 583},
+ {uniname2ctype_offset(str794), 589},
{-1}, {-1},
{uniname2ctype_offset(str797), 50},
{-1},
- {uniname2ctype_offset(str799), 608},
+ {uniname2ctype_offset(str799), 617},
{-1}, {-1},
{uniname2ctype_offset(str802), 13},
- {uniname2ctype_offset(str803), 587},
+ {uniname2ctype_offset(str803), 593},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str809), 443},
+ {uniname2ctype_offset(str809), 446},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str814), 490},
+ {uniname2ctype_offset(str814), 493},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str818), 395},
+ {uniname2ctype_offset(str818), 398},
{-1}, {-1},
- {uniname2ctype_offset(str821), 479},
- {uniname2ctype_offset(str822), 589},
+ {uniname2ctype_offset(str821), 482},
+ {uniname2ctype_offset(str822), 595},
{uniname2ctype_offset(str823), 47},
{uniname2ctype_offset(str824), 112},
- {uniname2ctype_offset(str825), 441},
+ {uniname2ctype_offset(str825), 444},
{-1}, {-1},
- {uniname2ctype_offset(str828), 590},
+ {uniname2ctype_offset(str828), 596},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str838), 157},
{-1}, {-1}, {-1},
@@ -43014,32 +44108,32 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str855), 67},
{-1},
- {uniname2ctype_offset(str857), 316},
+ {uniname2ctype_offset(str857), 319},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str875), 366},
+ {uniname2ctype_offset(str875), 369},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1},
- {uniname2ctype_offset(str886), 401},
+ {uniname2ctype_offset(str886), 404},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str895), 409},
+ {uniname2ctype_offset(str895), 412},
{-1}, {-1},
- {uniname2ctype_offset(str898), 497},
+ {uniname2ctype_offset(str898), 500},
{-1},
- {uniname2ctype_offset(str900), 612},
+ {uniname2ctype_offset(str900), 621},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str906), 518},
- {uniname2ctype_offset(str907), 446},
+ {uniname2ctype_offset(str906), 521},
+ {uniname2ctype_offset(str907), 449},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str920), 416},
+ {uniname2ctype_offset(str920), 419},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str924), 68},
- {uniname2ctype_offset(str925), 592},
- {uniname2ctype_offset(str926), 341},
+ {uniname2ctype_offset(str925), 599},
+ {uniname2ctype_offset(str926), 344},
{-1},
- {uniname2ctype_offset(str928), 536},
- {uniname2ctype_offset(str929), 458},
+ {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},
@@ -43048,13 +44142,13 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str961), 2},
{-1},
- {uniname2ctype_offset(str963), 255},
+ {uniname2ctype_offset(str963), 257},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1},
- {uniname2ctype_offset(str974), 507},
+ {uniname2ctype_offset(str974), 510},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1},
- {uniname2ctype_offset(str986), 367},
+ {uniname2ctype_offset(str986), 370},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str994), 85},
{uniname2ctype_offset(str995), 104},
@@ -43062,21 +44156,21 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1010), 26},
{-1}, {-1},
- {uniname2ctype_offset(str1013), 492},
+ {uniname2ctype_offset(str1013), 495},
{-1},
- {uniname2ctype_offset(str1015), 481},
+ {uniname2ctype_offset(str1015), 484},
{-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1021), 67},
{-1}, {-1},
{uniname2ctype_offset(str1024), 53},
- {uniname2ctype_offset(str1025), 456},
+ {uniname2ctype_offset(str1025), 459},
{-1}, {-1},
{uniname2ctype_offset(str1028), 136},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1032), 377},
+ {uniname2ctype_offset(str1032), 380},
{-1}, {-1},
- {uniname2ctype_offset(str1035), 319},
- {uniname2ctype_offset(str1036), 563},
+ {uniname2ctype_offset(str1035), 322},
+ {uniname2ctype_offset(str1036), 569},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str1049), 173},
@@ -43086,26 +44180,26 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1072), 197},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1081), 411},
+ {uniname2ctype_offset(str1081), 414},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1085), 257},
+ {uniname2ctype_offset(str1085), 259},
{-1},
- {uniname2ctype_offset(str1087), 593},
+ {uniname2ctype_offset(str1087), 600},
{-1},
{uniname2ctype_offset(str1089), 115},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1095), 248},
+ {uniname2ctype_offset(str1095), 250},
{uniname2ctype_offset(str1096), 71},
- {uniname2ctype_offset(str1097), 537},
+ {uniname2ctype_offset(str1097), 541},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1102), 520},
+ {uniname2ctype_offset(str1102), 523},
{-1},
{uniname2ctype_offset(str1104), 228},
{uniname2ctype_offset(str1105), 217},
{-1},
- {uniname2ctype_offset(str1107), 538},
+ {uniname2ctype_offset(str1107), 542},
{-1},
- {uniname2ctype_offset(str1109), 237},
+ {uniname2ctype_offset(str1109), 239},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1114), 69},
{uniname2ctype_offset(str1115), 11},
@@ -43114,7 +44208,7 @@ uniname2ctype_p (register const char *str, register size_t len)
{uniname2ctype_offset(str1120), 60},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1134), 422},
+ {uniname2ctype_offset(str1134), 425},
{-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1140), 93},
{-1},
@@ -43122,153 +44216,155 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1}, {-1},
{uniname2ctype_offset(str1145), 137},
{uniname2ctype_offset(str1146), 131},
- {uniname2ctype_offset(str1147), 264},
+ {uniname2ctype_offset(str1147), 266},
{-1},
{uniname2ctype_offset(str1149), 158},
{uniname2ctype_offset(str1150), 98},
- {uniname2ctype_offset(str1151), 495},
+ {uniname2ctype_offset(str1151), 498},
{uniname2ctype_offset(str1152), 217},
{uniname2ctype_offset(str1153), 138},
{-1}, {-1},
- {uniname2ctype_offset(str1156), 525},
+ {uniname2ctype_offset(str1156), 529},
{uniname2ctype_offset(str1157), 203},
{uniname2ctype_offset(str1158), 166},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1164), 238},
+ {uniname2ctype_offset(str1164), 240},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str1168), 104},
{-1},
- {uniname2ctype_offset(str1170), 386},
- {uniname2ctype_offset(str1171), 532},
+ {uniname2ctype_offset(str1170), 389},
+ {uniname2ctype_offset(str1171), 536},
{-1}, {-1},
- {uniname2ctype_offset(str1174), 323},
+ {uniname2ctype_offset(str1174), 326},
{uniname2ctype_offset(str1175), 26},
{uniname2ctype_offset(str1176), 208},
{uniname2ctype_offset(str1177), 74},
- {uniname2ctype_offset(str1178), 350},
+ {uniname2ctype_offset(str1178), 353},
{-1},
{uniname2ctype_offset(str1180), 183},
{uniname2ctype_offset(str1181), 151},
- {uniname2ctype_offset(str1182), 356},
+ {uniname2ctype_offset(str1182), 359},
{uniname2ctype_offset(str1183), 101},
{-1},
{uniname2ctype_offset(str1185), 170},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1190), 270},
- {uniname2ctype_offset(str1191), 541},
+ {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), 363},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1207), 459},
+ {uniname2ctype_offset(str1203), 366},
+ {uniname2ctype_offset(str1204), 609},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1207), 462},
{-1},
{uniname2ctype_offset(str1209), 186},
{-1}, {-1},
- {uniname2ctype_offset(str1212), 376},
+ {uniname2ctype_offset(str1212), 379},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1},
- {uniname2ctype_offset(str1223), 578},
+ {uniname2ctype_offset(str1223), 584},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1227), 241},
+ {uniname2ctype_offset(str1227), 243},
{-1},
{uniname2ctype_offset(str1229), 235},
- {uniname2ctype_offset(str1230), 265},
+ {uniname2ctype_offset(str1230), 267},
{uniname2ctype_offset(str1231), 206},
- {uniname2ctype_offset(str1232), 352},
+ {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), 296},
- {uniname2ctype_offset(str1235), 298},
- {uniname2ctype_offset(str1236), 295},
- {uniname2ctype_offset(str1237), 297},
+ {uniname2ctype_offset(str1234), 298},
+ {uniname2ctype_offset(str1235), 300},
+ {uniname2ctype_offset(str1236), 297},
+ {uniname2ctype_offset(str1237), 299},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1241), 299},
- {uniname2ctype_offset(str1242), 277},
+ {uniname2ctype_offset(str1241), 301},
+ {uniname2ctype_offset(str1242), 279},
#endif /* USE_UNICODE_AGE_PROPERTIES */
{uniname2ctype_offset(str1243), 25},
- {uniname2ctype_offset(str1244), 338},
+ {uniname2ctype_offset(str1244), 341},
#ifndef USE_UNICODE_AGE_PROPERTIES
{-1},
#else /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1245), 279},
+ {uniname2ctype_offset(str1245), 281},
#endif /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1246), 432},
+ {uniname2ctype_offset(str1246), 435},
#ifndef USE_UNICODE_AGE_PROPERTIES
{-1},
#else /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1247), 278},
+ {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), 281},
- {uniname2ctype_offset(str1250), 294},
- {uniname2ctype_offset(str1251), 280},
- {uniname2ctype_offset(str1252), 282},
- {uniname2ctype_offset(str1253), 293},
+ {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), 560},
+ {uniname2ctype_offset(str1254), 566},
#ifndef USE_UNICODE_AGE_PROPERTIES
{-1},
#else /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1255), 289},
+ {uniname2ctype_offset(str1255), 291},
#endif /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1256), 276},
+ {uniname2ctype_offset(str1256), 278},
#ifndef USE_UNICODE_AGE_PROPERTIES
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1263), 64},
#else /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1257), 288},
- {uniname2ctype_offset(str1258), 290},
- {uniname2ctype_offset(str1259), 292},
+ {uniname2ctype_offset(str1257), 290},
+ {uniname2ctype_offset(str1258), 292},
+ {uniname2ctype_offset(str1259), 303},
+ {uniname2ctype_offset(str1260), 294},
+ {-1},
+ {uniname2ctype_offset(str1262), 293},
#endif /* USE_UNICODE_AGE_PROPERTIES */
- {-1}, {-1},
-#ifdef USE_UNICODE_AGE_PROPERTIES
- {uniname2ctype_offset(str1262), 291},
{uniname2ctype_offset(str1263), 64},
+#ifndef USE_UNICODE_AGE_PROPERTIES
+ {-1}, {-1},
+#else /* USE_UNICODE_AGE_PROPERTIES */
{-1},
- {uniname2ctype_offset(str1265), 286},
+ {uniname2ctype_offset(str1265), 302},
#endif /* USE_UNICODE_AGE_PROPERTIES */
{uniname2ctype_offset(str1266), 21},
#ifndef USE_UNICODE_AGE_PROPERTIES
{-1}, {-1}, {-1}, {-1},
#else /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1267), 285},
- {uniname2ctype_offset(str1268), 287},
- {uniname2ctype_offset(str1269), 300},
+ {uniname2ctype_offset(str1267), 288},
{-1},
+ {uniname2ctype_offset(str1269), 287},
+ {uniname2ctype_offset(str1270), 289},
#endif /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1271), 248},
+ {uniname2ctype_offset(str1271), 250},
+#ifndef USE_UNICODE_AGE_PROPERTIES
{-1}, {-1},
+#else /* USE_UNICODE_AGE_PROPERTIES */
+ {-1},
+ {uniname2ctype_offset(str1273), 286},
+#endif /* USE_UNICODE_AGE_PROPERTIES */
{uniname2ctype_offset(str1274), 200},
#ifndef USE_UNICODE_AGE_PROPERTIES
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
#else /* USE_UNICODE_AGE_PROPERTIES */
- {-1}, {-1},
- {uniname2ctype_offset(str1277), 284},
- {-1},
- {uniname2ctype_offset(str1279), 283},
- {-1}, {-1},
+ {uniname2ctype_offset(str1275), 285},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
#endif /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1282), 626},
- {-1},
- {uniname2ctype_offset(str1284), 110},
+ {uniname2ctype_offset(str1282), 635},
+ {-1}, {-1},
{uniname2ctype_offset(str1285), 105},
- {-1},
- {uniname2ctype_offset(str1287), 110},
- {-1},
- {uniname2ctype_offset(str1289), 345},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1289), 348},
{-1}, {-1},
- {uniname2ctype_offset(str1292), 394},
+ {uniname2ctype_offset(str1292), 397},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1297), 145},
- {uniname2ctype_offset(str1298), 117},
- {-1},
+ {-1}, {-1},
{uniname2ctype_offset(str1300), 86},
{uniname2ctype_offset(str1301), 141},
{-1}, {-1}, {-1}, {-1},
@@ -43277,14 +44373,11 @@ uniname2ctype_p (register const char *str, register size_t len)
{uniname2ctype_offset(str1314), 193},
{-1}, {-1},
{uniname2ctype_offset(str1317), 86},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1323), 535},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1327), 117},
- {uniname2ctype_offset(str1328), 227},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1},
- {uniname2ctype_offset(str1330), 107},
- {uniname2ctype_offset(str1331), 261},
+ {uniname2ctype_offset(str1328), 227},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1331), 263},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1340), 105},
{-1}, {-1},
@@ -43295,18 +44388,20 @@ uniname2ctype_p (register const char *str, register size_t len)
{uniname2ctype_offset(str1352), 88},
{-1},
{uniname2ctype_offset(str1354), 164},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1358), 624},
+ {-1},
+ {uniname2ctype_offset(str1356), 605},
+ {-1},
+ {uniname2ctype_offset(str1358), 633},
{-1},
{uniname2ctype_offset(str1360), 3},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1365), 384},
+ {uniname2ctype_offset(str1365), 387},
{-1},
- {uniname2ctype_offset(str1367), 530},
+ {uniname2ctype_offset(str1367), 534},
{-1},
- {uniname2ctype_offset(str1369), 256},
+ {uniname2ctype_offset(str1369), 258},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1373), 272},
+ {uniname2ctype_offset(str1373), 274},
{-1},
{uniname2ctype_offset(str1375), 135},
{-1}, {-1}, {-1}, {-1},
@@ -43319,29 +44414,29 @@ uniname2ctype_p (register const char *str, register size_t len)
{uniname2ctype_offset(str1392), 138},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1400), 201},
- {uniname2ctype_offset(str1401), 397},
+ {uniname2ctype_offset(str1401), 400},
{-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1407), 224},
{-1},
{uniname2ctype_offset(str1409), 38},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1415), 570},
+ {uniname2ctype_offset(str1415), 576},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str1419), 140},
{uniname2ctype_offset(str1420), 140},
{-1},
- {uniname2ctype_offset(str1422), 321},
+ {uniname2ctype_offset(str1422), 324},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str1426), 39},
{-1},
{uniname2ctype_offset(str1428), 181},
{uniname2ctype_offset(str1429), 36},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1438), 434},
+ {uniname2ctype_offset(str1438), 437},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1442), 540},
+ {uniname2ctype_offset(str1442), 544},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1448), 505},
+ {uniname2ctype_offset(str1448), 508},
{uniname2ctype_offset(str1449), 122},
{-1},
{uniname2ctype_offset(str1451), 203},
@@ -43352,109 +44447,106 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1}, {-1},
{uniname2ctype_offset(str1460), 215},
{-1},
- {uniname2ctype_offset(str1462), 554},
+ {uniname2ctype_offset(str1462), 559},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1470), 504},
- {uniname2ctype_offset(str1471), 506},
+ {uniname2ctype_offset(str1470), 507},
+ {uniname2ctype_offset(str1471), 509},
{-1}, {-1},
{uniname2ctype_offset(str1474), 134},
- {uniname2ctype_offset(str1475), 426},
- {uniname2ctype_offset(str1476), 508},
+ {uniname2ctype_offset(str1475), 429},
+ {uniname2ctype_offset(str1476), 511},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1480), 245},
+ {uniname2ctype_offset(str1480), 247},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1489), 33},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1495), 260},
+ {uniname2ctype_offset(str1495), 262},
{-1},
- {uniname2ctype_offset(str1497), 496},
+ {uniname2ctype_offset(str1497), 499},
{-1},
- {uniname2ctype_offset(str1499), 611},
+ {uniname2ctype_offset(str1499), 620},
{-1},
{uniname2ctype_offset(str1501), 196},
{-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1507), 122},
{uniname2ctype_offset(str1508), 231},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1517), 610},
+ {uniname2ctype_offset(str1517), 619},
{-1}, {-1},
- {uniname2ctype_offset(str1520), 237},
+ {uniname2ctype_offset(str1520), 239},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1524), 483},
+ {uniname2ctype_offset(str1524), 486},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1529), 120},
{-1},
- {uniname2ctype_offset(str1531), 419},
+ {uniname2ctype_offset(str1531), 422},
{-1},
{uniname2ctype_offset(str1533), 142},
{-1}, {-1},
{uniname2ctype_offset(str1536), 127},
- {uniname2ctype_offset(str1537), 269},
+ {uniname2ctype_offset(str1537), 271},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1542), 465},
+ {uniname2ctype_offset(str1542), 468},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1547), 168},
{-1},
- {uniname2ctype_offset(str1549), 519},
+ {uniname2ctype_offset(str1549), 522},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1557), 85},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1563), 273},
+ {uniname2ctype_offset(str1563), 275},
{-1},
- {uniname2ctype_offset(str1565), 326},
+ {uniname2ctype_offset(str1565), 329},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1570), 210},
{-1},
{uniname2ctype_offset(str1572), 115},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1577), 564},
+ {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), 546},
+ {uniname2ctype_offset(str1587), 550},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1597), 81},
{uniname2ctype_offset(str1598), 219},
- {-1}, {-1},
- {uniname2ctype_offset(str1601), 202},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1607), 586},
+ {-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), 502},
- {uniname2ctype_offset(str1618), 272},
+ {uniname2ctype_offset(str1617), 505},
+ {uniname2ctype_offset(str1618), 274},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1622), 385},
- {uniname2ctype_offset(str1623), 567},
+ {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},
- {uniname2ctype_offset(str1636), 202},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1643), 62},
{uniname2ctype_offset(str1644), 235},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1654), 400},
- {uniname2ctype_offset(str1655), 274},
+ {uniname2ctype_offset(str1654), 403},
+ {uniname2ctype_offset(str1655), 276},
{-1},
{uniname2ctype_offset(str1657), 114},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1662), 129},
{-1},
- {uniname2ctype_offset(str1664), 448},
+ {uniname2ctype_offset(str1664), 451},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1671), 340},
+ {uniname2ctype_offset(str1671), 343},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1675), 469},
+ {uniname2ctype_offset(str1675), 472},
{-1},
- {uniname2ctype_offset(str1677), 314},
+ {uniname2ctype_offset(str1677), 317},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1682), 625},
+ {uniname2ctype_offset(str1682), 634},
{-1},
{uniname2ctype_offset(str1684), 199},
{-1},
@@ -43463,186 +44555,192 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1}, {-1}, {-1},
{uniname2ctype_offset(str1691), 124},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1699), 379},
+ {uniname2ctype_offset(str1699), 382},
{-1},
- {uniname2ctype_offset(str1701), 522},
+ {uniname2ctype_offset(str1701), 525},
{-1}, {-1},
{uniname2ctype_offset(str1704), 207},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1714), 207},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1722), 359},
+ {uniname2ctype_offset(str1722), 362},
{-1},
- {uniname2ctype_offset(str1724), 576},
+ {uniname2ctype_offset(str1724), 582},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str1728), 221},
- {uniname2ctype_offset(str1729), 442},
+ {uniname2ctype_offset(str1729), 445},
{uniname2ctype_offset(str1730), 222},
- {uniname2ctype_offset(str1731), 534},
- {uniname2ctype_offset(str1732), 247},
+ {uniname2ctype_offset(str1731), 538},
+ {uniname2ctype_offset(str1732), 249},
{uniname2ctype_offset(str1733), 123},
{uniname2ctype_offset(str1734), 114},
- {uniname2ctype_offset(str1735), 258},
+ {uniname2ctype_offset(str1735), 260},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1740), 129},
{-1},
{uniname2ctype_offset(str1742), 161},
{-1}, {-1},
- {uniname2ctype_offset(str1745), 524},
- {uniname2ctype_offset(str1746), 402},
+ {uniname2ctype_offset(str1745), 528},
+ {uniname2ctype_offset(str1746), 405},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str1750), 20},
{-1},
- {uniname2ctype_offset(str1752), 516},
+ {uniname2ctype_offset(str1752), 519},
{uniname2ctype_offset(str1753), 148},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1757), 515},
+ {uniname2ctype_offset(str1757), 518},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1766), 73},
{-1},
{uniname2ctype_offset(str1768), 148},
- {uniname2ctype_offset(str1769), 374},
+ {uniname2ctype_offset(str1769), 377},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1776), 126},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1781), 552},
+ {uniname2ctype_offset(str1781), 556},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1788), 97},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1793), 97},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1806), 348},
+ {uniname2ctype_offset(str1806), 351},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1810), 630},
- {uniname2ctype_offset(str1811), 245},
+ {uniname2ctype_offset(str1810), 640},
+ {uniname2ctype_offset(str1811), 247},
{-1},
- {uniname2ctype_offset(str1813), 264},
+ {uniname2ctype_offset(str1813), 266},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1821), 224},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1828), 399},
+ {uniname2ctype_offset(str1828), 402},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1838), 614},
+ {uniname2ctype_offset(str1838), 623},
{-1}, {-1},
- {uniname2ctype_offset(str1841), 457},
- {uniname2ctype_offset(str1842), 391},
+ {uniname2ctype_offset(str1841), 460},
+ {uniname2ctype_offset(str1842), 394},
{uniname2ctype_offset(str1843), 65},
{-1},
- {uniname2ctype_offset(str1845), 263},
+ {uniname2ctype_offset(str1845), 265},
{-1}, {-1},
{uniname2ctype_offset(str1848), 109},
{-1}, {-1},
{uniname2ctype_offset(str1851), 137},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1857), 244},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1866), 61},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1871), 491},
+ {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), 527},
- {uniname2ctype_offset(str1889), 551},
+ {uniname2ctype_offset(str1888), 531},
+ {uniname2ctype_offset(str1889), 555},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1896), 617},
+ {uniname2ctype_offset(str1896), 626},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1902), 431},
+ {uniname2ctype_offset(str1902), 434},
{-1},
- {uniname2ctype_offset(str1904), 452},
- {uniname2ctype_offset(str1905), 584},
+ {uniname2ctype_offset(str1904), 455},
+ {uniname2ctype_offset(str1905), 590},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1912), 580},
+ {uniname2ctype_offset(str1912), 586},
{uniname2ctype_offset(str1913), 143},
{-1}, {-1},
- {uniname2ctype_offset(str1916), 588},
+ {uniname2ctype_offset(str1916), 594},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1924), 143},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1929), 429},
+ {uniname2ctype_offset(str1929), 432},
{-1}, {-1},
- {uniname2ctype_offset(str1932), 412},
+ {uniname2ctype_offset(str1932), 415},
{-1}, {-1},
- {uniname2ctype_offset(str1935), 262},
- {uniname2ctype_offset(str1936), 335},
+ {uniname2ctype_offset(str1935), 264},
+ {uniname2ctype_offset(str1936), 338},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1941), 27},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1948), 87},
- {-1},
- {uniname2ctype_offset(str1950), 421},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1950), 424},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1956), 250},
- {uniname2ctype_offset(str1957), 87},
+ {uniname2ctype_offset(str1956), 252},
+ {-1},
{uniname2ctype_offset(str1958), 109},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1964), 437},
+ {uniname2ctype_offset(str1964), 440},
{-1}, {-1},
- {uniname2ctype_offset(str1967), 489},
- {uniname2ctype_offset(str1968), 634},
- {uniname2ctype_offset(str1969), 249},
+ {uniname2ctype_offset(str1967), 492},
+ {uniname2ctype_offset(str1968), 644},
+ {uniname2ctype_offset(str1969), 251},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1974), 355},
+ {uniname2ctype_offset(str1974), 358},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str1981), 176},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str1985), 405},
+ {uniname2ctype_offset(str1985), 408},
{-1}, {-1},
- {uniname2ctype_offset(str1988), 438},
+ {uniname2ctype_offset(str1988), 441},
{-1}, {-1},
{uniname2ctype_offset(str1991), 1},
{-1},
- {uniname2ctype_offset(str1993), 372},
+ {uniname2ctype_offset(str1993), 375},
{uniname2ctype_offset(str1994), 175},
{-1},
{uniname2ctype_offset(str1996), 42},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2002), 591},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2006), 407},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2010), 375},
- {uniname2ctype_offset(str2011), 267},
- {uniname2ctype_offset(str2012), 559},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2001), 110},
+ {uniname2ctype_offset(str2002), 598},
{-1},
- {uniname2ctype_offset(str2014), 333},
+ {uniname2ctype_offset(str2004), 110},
+ {-1},
+ {uniname2ctype_offset(str2006), 410},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2010), 378},
+ {uniname2ctype_offset(str2011), 269},
+ {uniname2ctype_offset(str2012), 565},
{-1},
+ {uniname2ctype_offset(str2014), 336},
+ {uniname2ctype_offset(str2015), 117},
{uniname2ctype_offset(str2016), 209},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2023), 32},
- {uniname2ctype_offset(str2024), 503},
+ {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}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2040), 539},
+ {-1},
{uniname2ctype_offset(str2042), 121},
{uniname2ctype_offset(str2043), 17},
+ {uniname2ctype_offset(str2044), 117},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2047), 107},
+ {uniname2ctype_offset(str2048), 526},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2062), 130},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2070), 9},
{-1}, {-1},
- {uniname2ctype_offset(str2073), 342},
+ {uniname2ctype_offset(str2073), 345},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str2077), 150},
- {uniname2ctype_offset(str2078), 254},
+ {uniname2ctype_offset(str2078), 256},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1},
- {uniname2ctype_offset(str2090), 275},
+ {uniname2ctype_offset(str2090), 277},
{-1},
{uniname2ctype_offset(str2092), 150},
{-1}, {-1},
- {uniname2ctype_offset(str2095), 353},
+ {uniname2ctype_offset(str2095), 356},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2103), 162},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2110), 123},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str2114), 436},
- {uniname2ctype_offset(str2115), 381},
+ {uniname2ctype_offset(str2114), 439},
+ {uniname2ctype_offset(str2115), 384},
{-1},
{uniname2ctype_offset(str2117), 174},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
@@ -43653,15 +44751,15 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1},
{uniname2ctype_offset(str2137), 12},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str2141), 242},
+ {uniname2ctype_offset(str2141), 244},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str2145), 52},
- {uniname2ctype_offset(str2146), 413},
+ {uniname2ctype_offset(str2146), 416},
{-1}, {-1},
{uniname2ctype_offset(str2149), 221},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2163), 249},
+ {uniname2ctype_offset(str2163), 251},
{-1},
{uniname2ctype_offset(str2165), 174},
{uniname2ctype_offset(str2166), 5},
@@ -43674,107 +44772,100 @@ uniname2ctype_p (register const char *str, register size_t len)
{uniname2ctype_offset(str2182), 216},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str2195), 351},
- {uniname2ctype_offset(str2196), 493},
+ {uniname2ctype_offset(str2195), 354},
+ {uniname2ctype_offset(str2196), 496},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1},
{uniname2ctype_offset(str2207), 196},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str2211), 20},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2216), 364},
+ {uniname2ctype_offset(str2216), 367},
{uniname2ctype_offset(str2217), 128},
- {uniname2ctype_offset(str2218), 543},
+ {uniname2ctype_offset(str2218), 547},
{uniname2ctype_offset(str2219), 78},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2224), 450},
+ {uniname2ctype_offset(str2224), 453},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str2228), 43},
{uniname2ctype_offset(str2229), 35},
{-1}, {-1},
- {uniname2ctype_offset(str2232), 382},
+ {uniname2ctype_offset(str2232), 385},
{uniname2ctype_offset(str2233), 216},
{uniname2ctype_offset(str2234), 92},
- {uniname2ctype_offset(str2235), 486},
+ {uniname2ctype_offset(str2235), 489},
{-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2241), 92},
{-1}, {-1},
- {uniname2ctype_offset(str2244), 440},
+ {uniname2ctype_offset(str2244), 443},
{-1}, {-1},
{uniname2ctype_offset(str2247), 36},
- {uniname2ctype_offset(str2248), 595},
+ {uniname2ctype_offset(str2248), 602},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2276), 415},
+ {uniname2ctype_offset(str2276), 418},
{-1},
{uniname2ctype_offset(str2278), 124},
{uniname2ctype_offset(str2279), 192},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str2283), 214},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-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), 594},
- {uniname2ctype_offset(str2316), 629},
- {-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},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str2327), 378},
+ {uniname2ctype_offset(str2327), 381},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str2331), 627},
+ {uniname2ctype_offset(str2331), 636},
{-1},
{uniname2ctype_offset(str2333), 134},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2341), 185},
- {-1},
- {uniname2ctype_offset(str2343), 585},
- {uniname2ctype_offset(str2344), 439},
- {uniname2ctype_offset(str2345), 239},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2350), 185},
- {uniname2ctype_offset(str2351), 99},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2361), 598},
- {-1}, {-1},
- {uniname2ctype_offset(str2364), 320},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2370), 339},
+ {uniname2ctype_offset(str2343), 591},
+ {uniname2ctype_offset(str2344), 442},
+ {uniname2ctype_offset(str2345), 241},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2353), 202},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2361), 606},
{-1}, {-1},
+ {uniname2ctype_offset(str2364), 323},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2373), 37},
- {uniname2ctype_offset(str2374), 389},
+ {uniname2ctype_offset(str2374), 392},
{uniname2ctype_offset(str2375), 197},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2389), 557},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2397), 418},
- {uniname2ctype_offset(str2398), 410},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2397), 421},
+ {uniname2ctype_offset(str2398), 413},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2405), 165},
- {uniname2ctype_offset(str2406), 107},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2414), 82},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str2418), 449},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2427), 23},
- {uniname2ctype_offset(str2428), 183},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2433), 336},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2433), 339},
{uniname2ctype_offset(str2434), 154},
{-1}, {-1},
{uniname2ctype_offset(str2437), 194},
- {uniname2ctype_offset(str2438), 182},
- {-1},
+ {-1}, {-1},
{uniname2ctype_offset(str2440), 100},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1},
@@ -43782,36 +44873,36 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1}, {-1},
{uniname2ctype_offset(str2454), 220},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2460), 255},
+ {uniname2ctype_offset(str2460), 257},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str2464), 159},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2470), 445},
+ {uniname2ctype_offset(str2470), 448},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2475), 142},
- {uniname2ctype_offset(str2476), 430},
+ {uniname2ctype_offset(str2476), 558},
{-1},
- {uniname2ctype_offset(str2478), 414},
- {uniname2ctype_offset(str2479), 358},
+ {uniname2ctype_offset(str2478), 417},
+ {uniname2ctype_offset(str2479), 361},
{-1},
- {uniname2ctype_offset(str2481), 383},
+ {uniname2ctype_offset(str2481), 386},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2500), 121},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2506), 528},
+ {uniname2ctype_offset(str2506), 532},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2511), 242},
+ {uniname2ctype_offset(str2511), 244},
{-1},
- {uniname2ctype_offset(str2513), 621},
+ {uniname2ctype_offset(str2513), 630},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2530), 82},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str2534), 337},
+ {uniname2ctype_offset(str2534), 340},
+ {uniname2ctype_offset(str2535), 237},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str2545), 275},
+ {uniname2ctype_offset(str2545), 277},
{-1}, {-1},
{uniname2ctype_offset(str2548), 118},
{uniname2ctype_offset(str2549), 159},
@@ -43819,74 +44910,74 @@ uniname2ctype_p (register const char *str, register size_t len)
{uniname2ctype_offset(str2551), 89},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str2564), 369},
+ {uniname2ctype_offset(str2564), 372},
{-1}, {-1},
- {uniname2ctype_offset(str2567), 315},
+ {uniname2ctype_offset(str2567), 318},
{-1}, {-1},
- {uniname2ctype_offset(str2570), 488},
+ {uniname2ctype_offset(str2570), 491},
{-1},
- {uniname2ctype_offset(str2572), 470},
- {-1}, {-1},
- {uniname2ctype_offset(str2575), 471},
- {uniname2ctype_offset(str2576), 273},
+ {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), 388},
+ {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), 371},
+ {uniname2ctype_offset(str2606), 374},
{-1},
- {uniname2ctype_offset(str2608), 455},
+ {uniname2ctype_offset(str2608), 458},
{uniname2ctype_offset(str2609), 55},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2625), 260},
+ {uniname2ctype_offset(str2625), 262},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2648), 252},
+ {uniname2ctype_offset(str2648), 254},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str2652), 380},
+ {uniname2ctype_offset(str2652), 383},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str2656), 365},
+ {uniname2ctype_offset(str2656), 368},
{uniname2ctype_offset(str2657), 112},
- {-1}, {-1},
- {uniname2ctype_offset(str2660), 147},
- {-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), 623},
+ {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},
- {uniname2ctype_offset(str2689), 631},
+ {uniname2ctype_offset(str2689), 641},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2694), 48},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1},
- {uniname2ctype_offset(str2705), 478},
+ {uniname2ctype_offset(str2705), 481},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1},
{uniname2ctype_offset(str2726), 226},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str2738), 225},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str2750), 553},
+ {-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), 263},
+ {uniname2ctype_offset(str2762), 265},
{-1}, {-1},
{uniname2ctype_offset(str2765), 133},
{uniname2ctype_offset(str2766), 54},
{-1}, {-1},
- {uniname2ctype_offset(str2769), 480},
+ {uniname2ctype_offset(str2769), 483},
{-1}, {-1},
{uniname2ctype_offset(str2772), 199},
{-1}, {-1},
@@ -43894,94 +44985,87 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1},
{uniname2ctype_offset(str2786), 4},
- {uniname2ctype_offset(str2787), 80},
- {-1}, {-1}, {-1}, {-1}, {-1},
+ {-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), 509},
+ {uniname2ctype_offset(str2808), 512},
{-1},
{uniname2ctype_offset(str2810), 226},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2816), 307},
+ {uniname2ctype_offset(str2816), 310},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2821), 390},
+ {uniname2ctype_offset(str2821), 393},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2830), 605},
+ {uniname2ctype_offset(str2830), 614},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str2834), 361},
+ {uniname2ctype_offset(str2834), 364},
{-1},
{uniname2ctype_offset(str2836), 78},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1},
- {uniname2ctype_offset(str2847), 246},
+ {uniname2ctype_offset(str2847), 248},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2852), 302},
+ {uniname2ctype_offset(str2852), 305},
{-1}, {-1},
{uniname2ctype_offset(str2855), 190},
{uniname2ctype_offset(str2856), 66},
{-1}, {-1},
- {uniname2ctype_offset(str2859), 424},
+ {uniname2ctype_offset(str2859), 427},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2867), 306},
- {uniname2ctype_offset(str2868), 246},
+ {uniname2ctype_offset(str2867), 309},
+ {uniname2ctype_offset(str2868), 248},
{-1}, {-1},
- {uniname2ctype_offset(str2871), 252},
+ {uniname2ctype_offset(str2871), 254},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2879), 204},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2886), 622},
+ {uniname2ctype_offset(str2886), 631},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2901), 99},
- {uniname2ctype_offset(str2902), 474},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2902), 477},
{-1},
- {uniname2ctype_offset(str2904), 461},
- {uniname2ctype_offset(str2905), 271},
+ {uniname2ctype_offset(str2904), 464},
+ {uniname2ctype_offset(str2905), 273},
{-1},
- {uniname2ctype_offset(str2907), 271},
+ {uniname2ctype_offset(str2907), 273},
{-1},
- {uniname2ctype_offset(str2909), 571},
+ {uniname2ctype_offset(str2909), 577},
{-1},
- {uniname2ctype_offset(str2911), 447},
+ {uniname2ctype_offset(str2911), 450},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1},
- {uniname2ctype_offset(str2941), 360},
+ {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), 517},
+ {uniname2ctype_offset(str2964), 520},
{-1},
- {uniname2ctype_offset(str2966), 236},
+ {uniname2ctype_offset(str2966), 238},
{uniname2ctype_offset(str2967), 43},
- {-1},
- {uniname2ctype_offset(str2969), 204},
+ {-1}, {-1},
{uniname2ctype_offset(str2970), 88},
- {-1},
- {uniname2ctype_offset(str2972), 244},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str2980), 195},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str2984), 568},
+ {uniname2ctype_offset(str2984), 574},
{-1},
{uniname2ctype_offset(str2986), 118},
{uniname2ctype_offset(str2987), 54},
- {uniname2ctype_offset(str2988), 468},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2993), 201},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2997), 596},
+ {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), 472},
- {uniname2ctype_offset(str3006), 577},
+ {uniname2ctype_offset(str3005), 475},
+ {uniname2ctype_offset(str3006), 583},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str3015), 83},
{-1}, {-1},
@@ -43989,60 +45073,73 @@ uniname2ctype_p (register const char *str, register size_t len)
{uniname2ctype_offset(str3019), 165},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str3026), 83},
- {uniname2ctype_offset(str3027), 500},
+ {uniname2ctype_offset(str3027), 503},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str3035), 232},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str3042), 211},
{-1}, {-1},
- {uniname2ctype_offset(str3045), 606},
+ {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}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3058), 185},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3067), 185},
+ {uniname2ctype_offset(str3068), 99},
+ {-1}, {-1},
{uniname2ctype_offset(str3071), 198},
{uniname2ctype_offset(str3072), 133},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str3082), 130},
- {-1}, {-1}, {-1},
+ {-1},
+ {uniname2ctype_offset(str3084), 237},
+ {-1},
{uniname2ctype_offset(str3086), 84},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3091), 259},
+ {uniname2ctype_offset(str3087), 342},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3091), 261},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3099), 475},
+ {uniname2ctype_offset(str3099), 478},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str3104), 84},
- {-1}, {-1},
- {uniname2ctype_offset(str3107), 310},
{-1},
- {uniname2ctype_offset(str3109), 312},
+ {uniname2ctype_offset(str3106), 562},
+ {uniname2ctype_offset(str3107), 313},
+ {-1},
+ {uniname2ctype_offset(str3109), 315},
{uniname2ctype_offset(str3110), 152},
{uniname2ctype_offset(str3111), 191},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str3118), 90},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3123), 107},
+ {-1},
{uniname2ctype_offset(str3125), 191},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3140), 607},
- {-1},
- {uniname2ctype_offset(str3142), 579},
+ {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},
- {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3155), 182},
+ {-1},
{uniname2ctype_offset(str3157), 231},
- {uniname2ctype_offset(str3158), 325},
+ {uniname2ctype_offset(str3158), 328},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3176), 393},
+ {uniname2ctype_offset(str3176), 396},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str3180), 328},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3180), 331},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3193), 433},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str3209), 62},
{-1}, {-1},
{uniname2ctype_offset(str3212), 211},
@@ -44050,97 +45147,97 @@ uniname2ctype_p (register const char *str, register size_t len)
{uniname2ctype_offset(str3215), 180},
{-1}, {-1},
{uniname2ctype_offset(str3218), 125},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3227), 433},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3237), 387},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3237), 390},
{-1},
- {uniname2ctype_offset(str3239), 305},
- {uniname2ctype_offset(str3240), 301},
+ {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), 250},
+ {uniname2ctype_offset(str3254), 252},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1},
- {uniname2ctype_offset(str3265), 601},
+ {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), 609},
+ {uniname2ctype_offset(str3284), 618},
{-1}, {-1},
{uniname2ctype_offset(str3287), 223},
- {-1}, {-1},
- {uniname2ctype_offset(str3290), 451},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3297), 308},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3297), 311},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3303), 304},
+ {uniname2ctype_offset(str3303), 307},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3313), 253},
+ {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), 616},
+ {uniname2ctype_offset(str3329), 625},
{-1},
{uniname2ctype_offset(str3331), 222},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3338), 262},
+ {uniname2ctype_offset(str3338), 264},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3348), 404},
+ {uniname2ctype_offset(str3348), 407},
{-1},
- {uniname2ctype_offset(str3350), 498},
+ {uniname2ctype_offset(str3350), 501},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str3355), 47},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3360), 334},
+ {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), 251},
+ {uniname2ctype_offset(str3373), 253},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3377), 147},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3391), 236},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3396), 604},
+ {uniname2ctype_offset(str3391), 238},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3396), 613},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3405), 466},
+ {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), 251},
+ {uniname2ctype_offset(str3428), 253},
{-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str3433), 205},
{-1}, {-1},
{uniname2ctype_offset(str3436), 213},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3452), 220},
- {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3455), 225},
+ {-1}, {-1},
{uniname2ctype_offset(str3458), 10},
{-1},
- {uniname2ctype_offset(str3460), 618},
+ {uniname2ctype_offset(str3460), 627},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3483), 243},
+ {uniname2ctype_offset(str3483), 245},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str3502), 49},
- {-1}, {-1},
- {uniname2ctype_offset(str3505), 476},
+ {-1},
+ {uniname2ctype_offset(str3504), 80},
+ {uniname2ctype_offset(str3505), 479},
{-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3511), 408},
+ {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), 572},
+ {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},
@@ -44156,11 +45253,13 @@ uniname2ctype_p (register const char *str, register size_t len)
{-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), 462},
+ {-1}, {-1},
+ {uniname2ctype_offset(str3648), 465},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1},
{uniname2ctype_offset(str3659), 178},
@@ -44168,18 +45267,23 @@ uniname2ctype_p (register const char *str, register size_t len)
{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), 501},
- {uniname2ctype_offset(str3699), 548},
+ {-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), 317},
- {-1}, {-1}, {-1}, {-1}, {-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), 435},
+ {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},
@@ -44188,57 +45292,59 @@ uniname2ctype_p (register const char *str, register size_t len)
{uniname2ctype_offset(str3754), 71},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1},
- {uniname2ctype_offset(str3766), 464},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3770), 147},
+ {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}, {-1},
{uniname2ctype_offset(str3799), 214},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3807), 258},
+ {uniname2ctype_offset(str3807), 260},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str3842), 182},
{-1}, {-1},
- {uniname2ctype_offset(str3845), 257},
+ {uniname2ctype_offset(str3845), 259},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3850), 243},
+ {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}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3868), 259},
+ {-1},
+ {uniname2ctype_offset(str3868), 261},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str3881), 228},
{-1}, {-1},
- {uniname2ctype_offset(str3884), 303},
+ {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), 417},
+ {uniname2ctype_offset(str3924), 420},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str3942), 100},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3949), 274},
+ {-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), 597},
- {-1},
- {uniname2ctype_offset(str3978), 80},
+ {uniname2ctype_offset(str3976), 604},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str3998), 427},
+ {-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},
@@ -44246,13 +45352,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},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4066), 313},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-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},
@@ -44263,14 +45366,15 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4169), 220},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-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},
@@ -44281,18 +45385,17 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4308), 398},
+ {uniname2ctype_offset(str4308), 401},
{uniname2ctype_offset(str4309), 162},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str4321), 240},
{-1}, {-1}, {-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), 565},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str4348), 571},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str4361), 566},
+ {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},
@@ -44308,6 +45411,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(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},
@@ -44320,42 +45424,45 @@ 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}, {-1}, {-1}, {-1},
{uniname2ctype_offset(str4604), 116},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1},
{uniname2ctype_offset(str4626), 116},
- {uniname2ctype_offset(str4627), 253},
+ {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), 632},
+ {uniname2ctype_offset(str4674), 642},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4683), 463},
+ {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}, {-1}, {-1}, {-1},
+ {-1}, {-1},
{uniname2ctype_offset(str4734), 179},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1},
- {uniname2ctype_offset(str4755), 309},
- {uniname2ctype_offset(str4756), 311},
+ {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), 406},
- {-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}, {-1},
{uniname2ctype_offset(str4810), 90},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
@@ -44380,7 +45487,7 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1}, {-1},
{uniname2ctype_offset(str4982), 232},
{-1}, {-1}, {-1},
- {uniname2ctype_offset(str4986), 425},
+ {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},
@@ -44388,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},
@@ -44398,8 +45507,8 @@ uniname2ctype_p (register const char *str, register size_t len)
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str5134), 619},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str5134), 628},
#endif /* USE_UNICODE_PROPERTIES */
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
#ifndef USE_UNICODE_PROPERTIES
@@ -44529,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), 633}
+ {uniname2ctype_offset(str6098), 643}
#endif /* USE_UNICODE_PROPERTIES */
};
@@ -44560,22 +45669,22 @@ uniname2ctype(const UChar *name, unsigned int len)
return -1;
}
#if defined ONIG_UNICODE_VERSION_STRING && !( \
- ONIG_UNICODE_VERSION_MAJOR == 14 && \
+ 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 "14.0.0"
-#define ONIG_UNICODE_VERSION_MAJOR 14
+#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 == 14 && \
+ 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 "14.0"
-#define ONIG_UNICODE_EMOJI_VERSION_MAJOR 14
+#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 2737108379..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);
}
}
@@ -524,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;
}
@@ -538,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);
@@ -569,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);
}
@@ -581,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");
@@ -705,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
@@ -713,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;
}
@@ -724,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;
}
@@ -756,29 +718,23 @@ rb_encdb_alias(const char *alias, const char *orig)
return r;
}
-void
-rb_encdb_set_unicode(int index)
-{
- rb_raw_encoding *enc = (rb_raw_encoding *)rb_enc_from_index(index);
- ASSUME(enc);
- enc->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);
@@ -813,9 +769,9 @@ 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_debug = Qfalse;
@@ -848,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 {
@@ -880,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;
}
@@ -931,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;
}
}
@@ -957,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
@@ -969,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;
@@ -982,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;
}
@@ -1019,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));
@@ -1044,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;
@@ -1078,9 +1032,9 @@ static rb_encoding*
rb_encoding_check(rb_encoding* enc, VALUE str1, VALUE str2)
{
if (!enc)
- rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s",
- rb_enc_name(rb_enc_get(str1)),
- rb_enc_name(rb_enc_get(str2)));
+ rb_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;
}
@@ -1109,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;
}
@@ -1165,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);
}
}
@@ -1182,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);
@@ -1207,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);
}
@@ -1274,7 +1228,7 @@ 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);
@@ -1285,7 +1239,7 @@ 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;
}
@@ -1317,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)" : "");
}
/*
@@ -1350,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;
}
@@ -1371,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];
}
@@ -1400,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;
}
@@ -1438,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);
@@ -1520,7 +1464,7 @@ rb_ascii8bit_encoding(void)
int
rb_ascii8bit_encindex(void)
{
- return ENCINDEX_ASCII;
+ return ENCINDEX_ASCII_8BIT;
}
rb_encoding *
@@ -1556,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;
}
@@ -1578,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;
}
@@ -1607,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 {
@@ -1807,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);
+ }
}
}
@@ -1875,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;
}
@@ -1896,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);
@@ -1929,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:
+ * 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::US_ASCII.name # => "US-ASCII"
+ * Encoding::US_ASCII.names # => ["US-ASCII", "ASCII", "ANSI_X3.4-1968", "646"]
*
- * Encoding::ISO_8859_1.names
- * #=> ["ISO-8859-1", "ISO8859-1"]
+ * A Ruby method that accepts an encoding as an argument will accept:
*
- * 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).
+ * - An \Encoding object.
+ * - The name of an encoding.
+ * - An alias for an encoding name.
*
- * "some string".encoding
- * #=> #<Encoding:UTF-8>
- *
- * string = "some string".encode(Encoding::ISO_8859_1)
- * #=> "some string"
- * string.encoding
- * #=> #<Encoding:ISO-8859-1>
+ * These are equivalent:
*
- * "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.
- *
- * 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>
- *
- * == Script encoding
- *
- * All Ruby script code has an associated Encoding which any String literal
- * created in the source code will be associated to.
- *
- * 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:
- *
- * # encoding: UTF-8
- *
- * "some string".encoding
- * #=> #<Encoding:UTF-8>
- *
- * 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>
+ * 'foo'.encode(Encoding::US_ASCII) # Encoding object.
+ * 'foo'.encode('US-ASCII') # Encoding name.
+ * 'foo'.encode('ASCII') # Encoding alias.
*
- * <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.
+ * For a full discussion of encodings and their uses,
+ * see {the Encodings document}[rdoc-ref:encodings.rdoc].
*
- * == 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.
*
*/
@@ -2169,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);
@@ -2197,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 519d8873f6..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;
}
@@ -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);
@@ -1010,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 &&
@@ -1043,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;
}
@@ -1055,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;
@@ -1116,11 +1124,11 @@ 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;
}
@@ -1280,12 +1288,12 @@ 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;
}
}
@@ -1346,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;
}
@@ -1365,19 +1373,18 @@ 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);
}
/*
@@ -1473,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;
@@ -1490,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,
@@ -1499,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);
@@ -1548,8 +1555,8 @@ 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;
}
@@ -1609,8 +1616,8 @@ 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;
}
@@ -1669,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;
}
@@ -1705,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
}
@@ -1737,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);
@@ -1757,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
@@ -1815,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;
@@ -1828,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;
@@ -1855,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,
@@ -1886,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, {
@@ -1954,15 +1960,15 @@ 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;
}
@@ -2019,7 +2025,6 @@ enum_none(int argc, VALUE *argv, VALUE obj)
struct min_t {
VALUE min;
- struct cmp_opt_data cmp_opt;
};
static VALUE
@@ -2029,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;
}
@@ -2048,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;
}
@@ -2122,7 +2127,7 @@ 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;
@@ -2130,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
@@ -2155,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;
}
@@ -2174,14 +2176,14 @@ 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;
}
@@ -2247,7 +2249,7 @@ 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;
@@ -2255,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;
}
@@ -2272,7 +2272,6 @@ struct minmax_t {
VALUE min;
VALUE max;
VALUE last;
- struct cmp_opt_data cmp_opt;
};
static void
@@ -2280,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;
+ }
}
}
@@ -2305,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) {
@@ -2332,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;
+ }
}
}
@@ -2357,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;
}
@@ -2414,24 +2413,22 @@ 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);
}
@@ -2439,20 +2436,19 @@ 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;
}
@@ -2514,20 +2510,19 @@ 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;
}
@@ -2598,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;
@@ -2630,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;
@@ -2639,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;
@@ -2697,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);
@@ -2709,8 +2701,8 @@ 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;
}
@@ -2927,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;
@@ -3010,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;
}
@@ -3025,7 +3017,6 @@ 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));
@@ -3035,7 +3026,7 @@ enum_each_cons_size(VALUE obj, VALUE args, VALUE eobj)
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;
}
/*
@@ -3090,8 +3081,10 @@ each_with_object_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo))
* Calls the block once for each element, passing both the element
* and the given object:
*
- * (1..4).each_with_object([]) {|i, a| a.push(i**2) } # => [1, 4, 9, 16]
- * h.each_with_object({}) {|element, h| k, v = *element; h[v] = k }
+ * (1..4).each_with_object([]) {|i, a| a.push(i**2) }
+ * # => [1, 4, 9, 16]
+ *
+ * {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.
@@ -3120,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);
@@ -3167,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);
@@ -3273,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, -) */
@@ -3334,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);
@@ -3388,10 +3381,10 @@ 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;
}
@@ -3423,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();
@@ -3440,10 +3433,10 @@ 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;
}
@@ -3498,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);
@@ -3562,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;
@@ -3589,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)) {
@@ -3616,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);
@@ -3642,8 +3635,8 @@ 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;
}
@@ -3824,7 +3817,7 @@ slicebefore_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator))
/*
* call-seq:
* slice_before(pattern) -> enumerator
- * slice_before {|array| ... } -> enumerator
+ * slice_before {|elt| ... } -> enumerator
*
* With argument +pattern+, returns an enumerator that uses the pattern
* to partition elements into arrays ("slices").
@@ -4069,39 +4062,24 @@ sliceafter_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator))
/*
* call-seq:
- * slice_after(pattern) -> enumerator
- * slice_after {|array| ... } -> enumerator
+ * enum.slice_after(pattern) -> an_enumerator
+ * enum.slice_after { |elt| bool } -> an_enumerator
*
- * With argument +pattern+, returns an enumerator that uses the pattern
- * to partition elements into arrays ("slices").
- * An element ends the current slice if <tt>element === pattern</tt>:
+ * Creates an enumerator for each chunked elements.
+ * The ends of chunks are defined by _pattern_ and the block.
*
- * a = %w[foo bar fop for baz fob fog bam foy]
- * e = a.slice_after(/ba/) # => #<Enumerator: ...>
- * e.each {|array| p array }
- *
- * Output:
+ * If <code>_pattern_ === _elt_</code> returns <code>true</code> or the block
+ * returns <code>true</code> for the element, the element is end of a
+ * chunk.
*
- * ["foo", "bar"]
- * ["fop", "for", "baz"]
- * ["fob", "fog", "bam"]
- * ["foy"]
+ * The <code>===</code> and _block_ is called from the first element to the last
+ * element of _enum_.
*
- * With a block, returns an enumerator that uses the block
- * to partition elements into arrays.
- * An element ends the current slice if its block return is a truthy value:
+ * The result enumerator yields the chunked elements as an array.
+ * So +each+ method can be called as follows:
*
- * e = (1..20).slice_after {|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]
+ * enum.slice_after(pattern).each { |ary| ... }
+ * enum.slice_after { |elt| bool }.each { |ary| ... }
*
* Other methods of the Enumerator class and Enumerable module,
* such as +map+, etc., are also usable.
@@ -4160,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;
@@ -4197,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);
@@ -4215,23 +4193,65 @@ slicewhen_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator))
/*
* call-seq:
- * slice_when {|element, next_element| ... } -> enumerator
+ * enum.slice_when {|elt_before, elt_after| bool } -> an_enumerator
*
- * The returned enumerator uses the block
- * to partition elements into arrays ("slices");
- * it calls the block with each element and its successor;
- * begins a new slice if and only if the block returns a truthy value:
+ * Creates an enumerator for each chunked elements.
+ * The beginnings of chunks are defined by the block.
*
- * a = [0, 1, 2, 4, 5, 6, 8, 9]
- * e = a.slice_when {|i, j| j != i + 1 }
- * e.each {|array| p array }
+ * This method splits each chunk using adjacent elements,
+ * _elt_before_ and _elt_after_,
+ * in the receiver enumerator.
+ * This method split chunks between _elt_before_ and _elt_after_ where
+ * the block returns <code>true</code>.
*
- * Output:
+ * The block is called the length of the receiver enumerator minus one.
+ *
+ * The result enumerator yields the chunked elements as an array.
+ * So +each+ method can be called as follows:
+ *
+ * enum.slice_when { |elt_before, elt_after| bool }.each { |ary| ... }
+ *
+ * Other methods of the Enumerator class and Enumerable module,
+ * such as +to_a+, +map+, etc., are also usable.
+ *
+ * For example, one-by-one increasing subsequence can be chunked as follows:
*
- * [0, 1, 2]
- * [4, 5, 6]
- * [8, 9]
+ * a = [1,2,4,9,10,11,12,15,16,19,20,21]
+ * b = a.slice_when {|i, j| i+1 != j }
+ * p b.to_a #=> [[1, 2], [4], [9, 10, 11, 12], [15, 16], [19, 20, 21]]
+ * c = b.map {|a| a.length < 3 ? a : "#{a.first}-#{a.last}" }
+ * p c #=> [[1, 2], [4], "9-12", [15, 16], "19-21"]
+ * d = c.join(",")
+ * p d #=> "1,2,4,9-12,15,16,19-21"
*
+ * Near elements (threshold: 6) in sorted array can be chunked as follows:
+ *
+ * a = [3, 11, 14, 25, 28, 29, 29, 41, 55, 57]
+ * p a.slice_when {|i, j| 6 < j - i }.to_a
+ * #=> [[3], [11, 14], [25, 28, 29, 29], [41], [55, 57]]
+ *
+ * Increasing (non-decreasing) subsequence can be chunked as follows:
+ *
+ * a = [0, 9, 2, 2, 3, 2, 7, 5, 9, 5]
+ * p a.slice_when {|i, j| i > j }.to_a
+ * #=> [[0, 9], [2, 2, 3], [2, 7], [5, 9], [5]]
+ *
+ * Adjacent evens and odds can be chunked as follows:
+ * (Enumerable#chunk is another way to do it.)
+ *
+ * a = [7, 5, 9, 2, 0, 7, 9, 4, 2, 0]
+ * p a.slice_when {|i, j| i.even? != j.even? }.to_a
+ * #=> [[7, 5, 9], [2, 0], [7, 9], [4, 2, 0]]
+ *
+ * Paragraphs (non-empty lines with trailing empty lines) can be chunked as follows:
+ * (See Enumerable#chunk to ignore empty lines.)
+ *
+ * lines = ["foo\n", "bar\n", "\n", "baz\n", "qux\n"]
+ * p lines.slice_when {|l1, l2| /\A\s*\z/ =~ l1 && /\S/ =~ l2 }.to_a
+ * #=> [["foo\n", "bar\n", "\n"], ["baz\n", "qux\n"]]
+ *
+ * Enumerable#chunk_while does the same, except splitting when the block
+ * returns <code>false</code> instead of <code>true</code>.
*/
static VALUE
enum_slice_when(VALUE enumerable)
@@ -4252,27 +4272,52 @@ enum_slice_when(VALUE enumerable)
/*
* call-seq:
- * chunk_while {|element, next_element| ... } -> enumerator
+ * enum.chunk_while {|elt_before, elt_after| bool } -> an_enumerator
*
- * The returned Enumerator uses the block to partition elements
- * into arrays ("chunks");
- * it calls the block with each element and its successor;
- * begins a new chunk if and only if the block returns a truthy value:
+ * Creates an enumerator for each chunked elements.
+ * The beginnings of chunks are defined by the block.
*
- * Example:
+ * This method splits each chunk using adjacent elements,
+ * _elt_before_ and _elt_after_,
+ * in the receiver enumerator.
+ * This method split chunks between _elt_before_ and _elt_after_ where
+ * the block returns <code>false</code>.
*
- * a = [1, 2, 4, 9, 10, 11, 12, 15, 16, 19, 20, 21]
- * e = a.chunk_while {|i, j| j == i + 1 }
- * e.each {|array| p array }
+ * The block is called the length of the receiver enumerator minus one.
*
- * Output:
+ * The result enumerator yields the chunked elements as an array.
+ * So +each+ method can be called as follows:
*
- * [1, 2]
- * [4]
- * [9, 10, 11, 12]
- * [15, 16]
- * [19, 20, 21]
+ * enum.chunk_while { |elt_before, elt_after| bool }.each { |ary| ... }
*
+ * Other methods of the Enumerator class and Enumerable module,
+ * such as +to_a+, +map+, etc., are also usable.
+ *
+ * For example, one-by-one increasing subsequence can be chunked as follows:
+ *
+ * a = [1,2,4,9,10,11,12,15,16,19,20,21]
+ * b = a.chunk_while {|i, j| i+1 == j }
+ * p b.to_a #=> [[1, 2], [4], [9, 10, 11, 12], [15, 16], [19, 20, 21]]
+ * c = b.map {|a| a.length < 3 ? a : "#{a.first}-#{a.last}" }
+ * p c #=> [[1, 2], [4], "9-12", [15, 16], "19-21"]
+ * d = c.join(",")
+ * p d #=> "1,2,4,9-12,15,16,19-21"
+ *
+ * Increasing (non-decreasing) subsequence can be chunked as follows:
+ *
+ * a = [0, 9, 2, 2, 3, 2, 7, 5, 9, 5]
+ * p a.chunk_while {|i, j| i <= j }.to_a
+ * #=> [[0, 9], [2, 2, 3], [2, 7], [5, 9], [5]]
+ *
+ * Adjacent evens and odds can be chunked as follows:
+ * (Enumerable#chunk is another way to do it.)
+ *
+ * a = [7, 5, 9, 2, 0, 7, 9, 4, 2, 0]
+ * p a.chunk_while {|i, j| i.even? == j.even? }.to_a
+ * #=> [[7, 5, 9], [2, 0], [7, 9], [4, 2, 0]]
+ *
+ * Enumerable#slice_when does the same, except splitting when the block
+ * returns <code>true</code> instead of <code>false</code>.
*/
static VALUE
enum_chunk_while(VALUE enumerable)
@@ -4333,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 {
@@ -4414,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:
@@ -4554,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;
@@ -4603,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);
@@ -4650,6 +4695,7 @@ enum_compact(VALUE obj)
* == What's Here
*
* \Module \Enumerable provides methods that are useful to a collection class for:
+ *
* - {Querying}[rdoc-ref:Enumerable@Methods+for+Querying]
* - {Fetching}[rdoc-ref:Enumerable@Methods+for+Fetching]
* - {Searching}[rdoc-ref:Enumerable@Methods+for+Searching]
@@ -4661,91 +4707,94 @@ enum_compact(VALUE obj)
*
* These methods return information about the \Enumerable other than the elements themselves:
*
- * #include?, #member?:: Returns +true+ if self == object, +false+ otherwise.
- * #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
*
diff --git a/enumerator.c b/enumerator.c
index be469ee38b..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;
@@ -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,
@@ -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 24df7ce064..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"
@@ -82,7 +83,7 @@ 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)
@@ -99,54 +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;
@@ -357,47 +352,42 @@ 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)
@@ -410,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);
@@ -419,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));
}
@@ -439,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);
+ }
}
}
@@ -450,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);
+ }
}
}
@@ -460,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));
}
@@ -480,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
@@ -513,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
@@ -526,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: */
@@ -546,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;
}
@@ -571,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;
}
@@ -621,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;
@@ -640,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;
}
@@ -657,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;
@@ -704,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;
@@ -730,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);
}
@@ -747,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);
}
@@ -759,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) \
@@ -816,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);
@@ -856,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();
}
@@ -882,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);
@@ -948,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;
}
@@ -974,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;
}
@@ -991,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));
}
@@ -1008,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);
@@ -1022,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);
@@ -1040,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;
}
@@ -1050,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;
}
@@ -1231,7 +1222,7 @@ 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;
}
@@ -1246,7 +1237,7 @@ rb_get_detailed_message(VALUE exc, VALUE opt)
else {
e = rb_check_funcall_kw(exc, id_detailed_message, 1, &opt, 1);
}
- 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;
}
@@ -1269,24 +1260,18 @@ check_highlight_keyword(VALUE opt, int auto_tty_detect)
VALUE highlight = Qnil;
if (!NIL_P(opt)) {
- highlight = rb_hash_aref(opt, sym_highlight);
+ highlight = rb_hash_lookup(opt, sym_highlight);
switch (highlight) {
default:
- rb_bool_expected(highlight, "highlight");
+ rb_bool_expected(highlight, "highlight", TRUE);
UNREACHABLE;
- case Qundef: highlight = Qnil; break;
case Qtrue: case Qfalse: case Qnil: break;
}
}
if (NIL_P(highlight)) {
- if (auto_tty_detect) {
- highlight = rb_stderr_tty_p() ? Qtrue : Qfalse;
- }
- else {
- highlight = Qfalse;
- }
+ highlight = RBOOL(auto_tty_detect && rb_stderr_tty_p());
}
return highlight;
@@ -1301,7 +1286,7 @@ check_order_keyword(VALUE opt)
static VALUE kw_order;
if (!kw_order) kw_order = ID2SYM(rb_intern_const("order"));
- order = rb_hash_aref(opt, kw_order);
+ order = rb_hash_lookup(opt, kw_order);
if (order != Qnil) {
ID id = rb_check_id(&order);
@@ -1391,6 +1376,28 @@ exc_message(VALUE exc)
*
* 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
@@ -1428,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;
@@ -1478,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;
@@ -1493,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);
@@ -1525,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;
}
@@ -1537,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;
}
@@ -1612,26 +1626,26 @@ 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;
+ return Qfalse;
return rb_equal(exc_backtrace(exc), backtrace);
}
@@ -1652,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);
@@ -1718,7 +1732,7 @@ exit_success_p(VALUE exc)
int status;
if (NIL_P(status_val))
- return Qtrue;
+ return Qtrue;
status = NUM2INT(status_val);
return RBOOL(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS);
}
@@ -1726,7 +1740,7 @@ exit_success_p(VALUE exc)
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;
}
@@ -1804,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;
}
@@ -1881,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;
}
@@ -1960,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
};
@@ -2019,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;
}
@@ -2051,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 || NIL_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, "");
- }
+ 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;
}
@@ -2125,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];
@@ -2183,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");
}
@@ -2200,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");
}
@@ -2231,17 +2247,17 @@ 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;
@@ -2260,7 +2276,7 @@ no_matching_pattern_key_err_matchee(VALUE self)
VALUE matchee;
matchee = rb_ivar_lookup(self, id_matchee, Qundef);
- if (matchee != Qundef) return matchee;
+ if (!UNDEF_P(matchee)) return matchee;
rb_raise(rb_eArgError, "no matchee is available");
}
@@ -2277,7 +2293,7 @@ no_matching_pattern_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");
}
@@ -2304,7 +2320,7 @@ no_matching_pattern_key_err_initialize(int argc, VALUE *argv, VALUE self)
keywords[1] = id_key;
rb_get_kwargs(options, keywords, 0, numberof(values), values);
for (i = 0; i < numberof(values); ++i) {
- if (values[i] != Qundef) {
+ if (!UNDEF_P(values[i])) {
rb_ivar_set(self, keywords[i], values[i]);
}
}
@@ -2326,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
*
@@ -2371,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;
}
@@ -2405,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;
}
@@ -2426,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;
@@ -2496,13 +2528,13 @@ 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);
return RBOOL(FIXNUM_P(num) ? num == e : rb_equal(num, e));
@@ -2929,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)
{
@@ -2943,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);
}
@@ -2994,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);
@@ -3150,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
@@ -3182,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);
}
@@ -3195,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);
}
@@ -3262,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);
@@ -3323,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;
}
}
@@ -3335,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);
+ }
}
}
@@ -3345,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;
}
}
@@ -3357,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
@@ -3368,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;
}
}
@@ -3381,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
@@ -3392,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;
}
}
@@ -3404,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);
+ }
}
}
@@ -3464,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);
}
diff --git a/eval.c b/eval.c
index 3a1a6b45df..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;
@@ -67,7 +68,7 @@ ruby_setup(void)
enum ruby_tag_type state;
if (GET_VM())
- return 0;
+ return 0;
ruby_init_stack((void *)&state);
@@ -85,9 +86,9 @@ 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();
@@ -99,9 +100,11 @@ 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);
}
}
@@ -115,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;
@@ -136,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();
}
@@ -175,20 +179,21 @@ ruby_finalize(void)
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);
@@ -198,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);
@@ -262,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;
}
@@ -277,9 +286,9 @@ 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;
@@ -301,8 +310,8 @@ 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;
@@ -314,8 +323,8 @@ 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));
@@ -350,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;
}
@@ -391,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);
}
@@ -422,45 +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);
}
}
@@ -474,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;
}
@@ -502,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;
}
@@ -527,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;
}
@@ -546,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)) {
@@ -615,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;
@@ -630,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);
}
}
@@ -655,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);
}
@@ -699,20 +716,20 @@ extract_raise_opts(int argc, VALUE *argv, VALUE *opts)
{
int i;
if (argc > 0) {
- VALUE opt;
- argc = rb_scan_args(argc, argv, "*:", NULL, &opt);
- if (!NIL_P(opt)) {
- if (!RHASH_EMPTY_P(opt)) {
- ID keywords[1];
- CONST_ID(keywords[0], "cause");
- rb_get_kwargs(opt, keywords, 0, -1-raise_max_opt, opts);
- if (!RHASH_EMPTY_P(opt)) argv[argc++] = opt;
- return argc;
- }
- }
+ VALUE 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;
}
@@ -725,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();
@@ -784,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)) {
@@ -842,7 +859,7 @@ 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);
}
@@ -851,10 +868,10 @@ 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;
}
}
@@ -872,7 +889,7 @@ 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);
}
}
@@ -901,48 +918,48 @@ 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;
}
@@ -952,7 +969,7 @@ 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);
}
VALUE
@@ -965,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();
@@ -991,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;
}
@@ -1012,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;
}
}
@@ -1025,10 +1042,10 @@ 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;
}
}
@@ -1085,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;
}
@@ -1106,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);
@@ -1129,20 +1146,20 @@ rb_mod_include(int argc, VALUE *argv, VALUE module)
CONST_ID(id_append_features, "append_features");
CONST_ID(id_included, "included");
- if (FL_TEST(module, RMODULE_IS_REFINEMENT)) {
+ 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);
+ 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;
}
@@ -1163,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);
@@ -1183,7 +1200,7 @@ rb_mod_prepend(int argc, VALUE *argv, VALUE module)
int i;
ID id_prepend_features, id_prepended;
- if (FL_TEST(module, RMODULE_IS_REFINEMENT)) {
+ if (BUILTIN_TYPE(module) == T_MODULE && FL_TEST(module, RMODULE_IS_REFINEMENT)) {
rb_raise(rb_eTypeError, "Refinement#prepend has been removed");
}
@@ -1192,14 +1209,14 @@ rb_mod_prepend(int argc, VALUE *argv, VALUE module)
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
for (i = 0; i < argc; i++) {
- Check_Type(argv[i], T_MODULE);
+ 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;
}
@@ -1208,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));
}
}
@@ -1227,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;
}
}
@@ -1246,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);
@@ -1273,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);
}
@@ -1298,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);
@@ -1348,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);
}
@@ -1396,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_refinement_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;
@@ -1439,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);
}
@@ -1458,14 +1472,14 @@ 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;
@@ -1511,9 +1525,9 @@ 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;
}
@@ -1550,10 +1564,10 @@ 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);
@@ -1562,9 +1576,9 @@ rb_mod_s_used_modules(VALUE _)
static int
used_refinements_i(VALUE _, VALUE mod, VALUE ary)
{
- while (FL_TEST(rb_class_of(mod), RMODULE_IS_REFINEMENT)) {
+ 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);
+ mod = RCLASS_SUPER(mod);
}
return ST_CONTINUE;
}
@@ -1601,10 +1615,10 @@ rb_mod_s_used_refinements(VALUE _)
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);
+ if (!NIL_P(CREF_REFINEMENTS(cref))) {
+ rb_hash_foreach(CREF_REFINEMENTS(cref), used_refinements_i, ary);
+ }
+ cref = CREF_NEXT(cref);
}
return ary;
@@ -1751,18 +1765,28 @@ rb_obj_extend(int argc, VALUE *argv, VALUE obj)
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
for (i = 0; i < argc; i++) {
- Check_Type(argv[i], T_MODULE);
+ 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
@@ -1775,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"));
}
/*
@@ -1795,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;
@@ -1815,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;
}
@@ -1835,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;
}
}
@@ -1864,7 +1884,7 @@ 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;
}
@@ -1874,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;
}
}
@@ -1886,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);
}
@@ -1907,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;
}
}
@@ -1929,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;
}
}
@@ -1951,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;
@@ -2048,7 +2068,7 @@ Init_eval(void)
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");
@@ -2067,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 abbb708bd5..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,23 +62,17 @@ 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);
- }
+ 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);
-}
-
#define CSI_BEGIN "\033["
#define CSI_SGR "m"
@@ -106,24 +100,24 @@ print_errinfo(const VALUE eclass, const VALUE errat, const VALUE emesg, const VA
}
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);
+ 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 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");
}
}
}
@@ -141,73 +135,73 @@ rb_decorate_message(const VALUE eclass, const VALUE emesg, int highlight)
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);
+ 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);
- }
- 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) {
+ if (RSTRING_PTR(epath)[0] == '#')
+ epath = 0;
+ if ((tail = memchr(einfo, '\n', elen)) != 0) {
write_warn2(str, einfo, tail - einfo);
- tail++; /* skip newline */
- }
- else {
+ tail++; /* skip newline */
+ }
+ else {
write_warn_str(str, emesg);
- }
- if (epath) {
- write_warn(str, " (");
- if (highlight) write_warn(str, underline);
+ }
+ 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);
- }
- if (tail && einfo+elen > tail) {
- if (!highlight) {
+ 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;
+ }
+ 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);
+ 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_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;
- }
- }
- }
- }
+ elen -= tail - einfo;
+ einfo = tail;
+ }
+ }
+ }
+ }
}
return str;
@@ -217,13 +211,13 @@ 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;
@@ -244,19 +238,19 @@ 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));
+ }
+ }
}
}
@@ -297,6 +291,17 @@ show_cause(VALUE errinfo, VALUE str, VALUE opt, VALUE highlight, VALUE reverse,
}
void
+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;
@@ -304,68 +309,68 @@ rb_error_write(VALUE errinfo, VALUE emesg, VALUE errat, VALUE str, VALUE opt, VA
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 (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 (RTEST(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);
+ 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));
+ print_backtrace(eclass, errat, str, TRUE, backtrace_limit);
+ print_errinfo(eclass, errat, emesg, str, RTEST(highlight));
}
else {
- print_errinfo(eclass, errat, emesg, str, RTEST(highlight));
- print_backtrace(eclass, errat, str, FALSE, backtrace_limit);
+ 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_detailed_message(errinfo, opt);
+ if (UNDEF_P(emesg)) {
+ emesg = Qnil;
+ emesg = rb_get_detailed_message(errinfo, opt);
}
if (!written) {
written = true;
- rb_error_write(errinfo, emesg, errat, Qnil, opt, highlight, Qfalse);
+ rb_error_write(errinfo, emesg, errat, str, opt, highlight, Qfalse);
}
EC_POP_TAG();
@@ -373,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)
@@ -403,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)
@@ -429,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 0efbcb0441..6cbaa51361 100644
--- a/eval_intern.h
+++ b/eval_intern.h
@@ -329,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-/abi/extconf.rb b/ext/-test-/abi/extconf.rb
index d786b15db9..3b090b7553 100644
--- a/ext/-test-/abi/extconf.rb
+++ b/ext/-test-/abi/extconf.rb
@@ -1,3 +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-/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-/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/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-/file/fs.c b/ext/-test-/file/fs.c
index 1a6c3d06dc..eb17e9768e 100644
--- a/ext/-test-/file/fs.c
+++ b/ext/-test-/file/fs.c
@@ -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-/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-/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-/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-/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-/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/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 602526cf7b..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
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 8729695886..ce977821b8 100644
--- a/ext/-test-/rational/depend
+++ b/ext/-test-/rational/depend
@@ -174,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/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-/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/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/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/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 1eadb8b4fd..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);
}
@@ -65,14 +65,14 @@ bug_str_unterminated_substring(VALUE str, VALUE vbeg, VALUE vlen)
#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;
+ 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;
}
@@ -104,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
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/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/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-/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/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-/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 fc74c0be53..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)
@@ -120,10 +279,7 @@ 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 ****
@@ -138,7 +294,7 @@ static VALUE BigDecimal_negative_zero(void);
static void
BigDecimal_delete(void *pv)
{
- VpFree(pv);
+ rbd_free_struct(pv);
}
static size_t
@@ -161,6 +317,60 @@ static const rb_data_type_t BigDecimal_data_type = {
#endif
};
+static Real *
+rbd_allocate_struct_zero_wrap_klass(VALUE klass, int sign, size_t const digits, bool limit_precision)
+{
+ Real *real = rbd_allocate_struct_zero(sign, digits, limit_precision);
+ if (real != NULL) {
+ VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
+ BigDecimal_wrap_struct(obj, real);
+ }
+ return real;
+}
+
+MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_limited_wrap(int sign, size_t const digits));
+#define NewZeroWrapLimited rbd_allocate_struct_zero_limited_wrap
+static inline Real *
+rbd_allocate_struct_zero_limited_wrap(int sign, size_t const digits)
+{
+ return rbd_allocate_struct_zero_wrap_klass(rb_cBigDecimal, sign, digits, true);
+}
+
+MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_nolimit_wrap(int sign, size_t const digits));
+#define NewZeroWrapNolimit rbd_allocate_struct_zero_nolimit_wrap
+static inline Real *
+rbd_allocate_struct_zero_nolimit_wrap(int sign, size_t const digits)
+{
+ return rbd_allocate_struct_zero_wrap_klass(rb_cBigDecimal, sign, digits, false);
+}
+
+static Real *
+rbd_allocate_struct_one_wrap_klass(VALUE klass, int sign, size_t const digits, bool limit_precision)
+{
+ Real *real = rbd_allocate_struct_one(sign, digits, limit_precision);
+ if (real != NULL) {
+ VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
+ BigDecimal_wrap_struct(obj, real);
+ }
+ return real;
+}
+
+MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_limited_wrap(int sign, size_t const digits));
+#define NewOneWrapLimited rbd_allocate_struct_one_limited_wrap
+static inline Real *
+rbd_allocate_struct_one_limited_wrap(int sign, size_t const digits)
+{
+ return rbd_allocate_struct_one_wrap_klass(rb_cBigDecimal, sign, digits, true);
+}
+
+MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_nolimit_wrap(int sign, size_t const digits));
+#define NewOneWrapNolimit rbd_allocate_struct_one_nolimit_wrap
+static inline Real *
+rbd_allocate_struct_one_nolimit_wrap(int sign, size_t const digits)
+{
+ return rbd_allocate_struct_one_wrap_klass(rb_cBigDecimal, sign, digits, false);
+}
+
static inline int
is_kind_of_BigDecimal(VALUE const v)
{
@@ -214,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;
}
@@ -249,7 +459,7 @@ SomeOneMayDoIt:
return NULL; /* NULL means to coerce */
}
-static Real*
+static inline Real*
GetVpValue(VALUE v, int must)
{
return GetVpValueWithPrec(v, -1, must);
@@ -264,7 +474,7 @@ GetVpValue(VALUE v, int must)
* BigDecimal.double_fig # => 16
*
*/
-static VALUE
+static inline VALUE
BigDecimal_double_fig(VALUE self)
{
return INT2FIX(VpDblFig());
@@ -486,15 +696,15 @@ BigDecimal_precision_scale(VALUE self)
*
* Returns the number of decimal significant digits in +self+.
*
- * BigDecimal("0").scale # => 0
- * BigDecimal("1").scale # => 1
- * BigDecimal("1.1").scale # => 2
- * BigDecimal("3.1415").scale # => 5
- * BigDecimal("-1e20").precision # => 1
- * BigDecimal("1e-20").precision # => 1
- * BigDecimal("Infinity").scale # => 0
- * BigDecimal("-Infinity").scale # => 0
- * BigDecimal("NaN").scale # => 0
+ * 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)
@@ -573,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;
}
@@ -623,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);
@@ -652,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();
}
@@ -667,34 +878,23 @@ 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:
@@ -933,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");
}
@@ -979,26 +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))
-
-static Real *
-VpReallocReal(Real *pv, size_t prec)
-{
- VALUE obj = pv ? pv->obj : 0;
- Real *new_pv = (Real *)VpMemRealloc(pv, offsetof(Real, frac) + prec * sizeof(DECDIG));
- if (obj) {
- new_pv->obj = 0;
- BigDecimal_wrap_struct(obj, new_pv);
- }
- return new_pv;
-}
-
static Real *
VpCopy(Real *pv, Real const* const x)
{
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;
@@ -1119,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) {
@@ -1276,17 +1468,17 @@ 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);
}
@@ -1331,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);
}
@@ -1581,7 +1773,7 @@ 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);
}
@@ -1608,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);
}
@@ -1655,8 +1847,8 @@ BigDecimal_divide(VALUE self, VALUE r, Real **c, Real **res, Real **div)
if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
- GUARD_OBJ((*c), VpCreateRbObject(mx + 2*BASE_FIG, "#0", true));
- GUARD_OBJ((*res), VpCreateRbObject((mx + 1)*2 + 2*BASE_FIG, "#0", true));
+ 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;
@@ -1721,7 +1913,7 @@ BigDecimal_quo(int argc, VALUE *argv, VALUE self)
argc = rb_scan_args(argc, argv, "11", &value, &digits);
if (argc > 1) {
- n = GetPrecisionInt(digits);
+ n = check_int_precision(digits);
}
if (n > 0) {
@@ -1811,12 +2003,12 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
- GUARD_OBJ(c, VpCreateRbObject(mx + 2*BASE_FIG, "0", true));
- GUARD_OBJ(res, VpCreateRbObject(mx*2 + 2*BASE_FIG, "#0", true));
+ GUARD_OBJ(c, NewZeroWrapLimited(1, mx + 2*BASE_FIG));
+ GUARD_OBJ(res, NewZeroWrapNolimit(1, mx*2 + 2*BASE_FIG));
VpDivd(c, res, a, b);
mx = c->Prec * BASE_FIG;
- GUARD_OBJ(d, VpCreateRbObject(mx, "0", true));
+ GUARD_OBJ(d, NewZeroWrapLimited(1, mx));
VpActiveRound(d, c, VP_ROUND_DOWN, 0);
VpMult(res, d, b);
@@ -1824,10 +2016,10 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
if (!VpIsZero(c) && (VpGetSign(a) * VpGetSign(b) < 0)) {
/* result adjustment for negative case */
- res = VpReallocReal(res, d->MaxPrec);
+ res = rbd_reallocate_struct(res, d->MaxPrec);
res->MaxPrec = d->MaxPrec;
VpAddSub(res, d, VpOne(), -1);
- GUARD_OBJ(d, VpCreateRbObject(GetAddSubPrec(c, b) * 2*BASE_FIG, "0", true));
+ GUARD_OBJ(d, NewZeroWrapLimited(1, GetAddSubPrec(c, b) * 2*BASE_FIG));
VpAddSub(d, c, b, 1);
*div = res;
*mod = d;
@@ -1891,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 */
@@ -1986,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);
}
@@ -1997,7 +2189,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
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));
/* TODO: I want to refactor this precision control for a float value later
* by introducing an implicit conversion function instead of
@@ -2008,7 +2200,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
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);
@@ -2091,7 +2283,7 @@ 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);
@@ -2121,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);
@@ -2164,7 +2356,7 @@ 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);
@@ -2196,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);
@@ -2219,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);
}
@@ -2237,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);
}
@@ -2310,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) {
@@ -2356,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) {
@@ -2376,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);
}
@@ -2416,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
@@ -2462,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) {
@@ -2566,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;
@@ -2611,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);
@@ -2660,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;
}
@@ -2770,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));
@@ -2808,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);
}
@@ -2879,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);
@@ -3017,15 +3200,15 @@ 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);
}
@@ -3114,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;
@@ -3122,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;
@@ -3148,7 +3331,7 @@ rb_uint64_convert_to_BigDecimal(uint64_t uval, RB_UNUSED_VAR(size_t digs), int r
}
const size_t exp = len + ntz;
- vp = VpAllocReal(len);
+ vp = rbd_allocate_struct(len);
vp->MaxPrec = len;
vp->Prec = len;
vp->exponent = exp;
@@ -3281,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) {
/*
@@ -3493,12 +3676,15 @@ rb_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
* BigDecimal(value, exception: true) -> bigdecimal
* BigDecimal(value, ndigits, exception: true) -> bigdecimal
*
- * Returns the \BigDecimal converted from +value+
- * with a precision of +ndigits+ decimal digits.
+ * Returns the \BigDecimal converted from +value+
+ * with a precision of +ndigits+ decimal digits.
+ *
+ * When +ndigits+ is less than the number of significant digits
+ * in the value, the result is rounded to that number of digits,
+ * according to the current rounding mode; see BigDecimal.mode.
*
- * When +ndigits+ is less than the number of significant digits
- * in the value, the result is rounded to that number of digits,
- * according to the current rounding mode; see BigDecimal.mode.
+ * When +ndigits+ is 0, the number of digits to correctly represent a float number
+ * is determined automatically.
*
* Returns +value+ converted to a \BigDecimal, depending on the type of +value+:
*
@@ -3606,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:
@@ -3771,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) {
@@ -3800,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;
@@ -3927,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);
@@ -3949,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;
@@ -4414,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 */
}
/*
@@ -4447,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() */
@@ -4478,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.
*/
@@ -4902,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;
@@ -4993,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:
@@ -5017,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
@@ -5032,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 */
@@ -5235,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);
@@ -5804,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;
}
@@ -5812,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;
@@ -5863,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);
@@ -6235,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)
{
@@ -6248,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)
@@ -6381,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;
+ }
+ if (p - 1 > buf && p[-1] == '.') {
+ snprintf(p, plen, "0");
}
- *psz = 0;
- while (psz[-1] == '0') *(--psz) = 0;
- if (psz[-1] == '.') sprintf(psz, "0");
- if (fFmt) VpFormatSt(pszSav, fFmt);
+ if (fFmt) VpFormatSt(buf, fFmt);
+
+ overflow:
+ return;
+#undef ADVANCE
}
/*
@@ -6971,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;
@@ -6997,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
@@ -7031,8 +7256,8 @@ converge:
y->MaxPrec = y_prec;
Exit:
- VpFree(f);
- VpFree(r);
+ rbd_free_struct(f);
+ rbd_free_struct(r);
return 1;
}
@@ -7423,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);
@@ -7454,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 2ed7d09373..d215757188 100644
--- a/ext/bigdecimal/bigdecimal.gemspec
+++ b/ext/bigdecimal/bigdecimal.gemspec
@@ -2,14 +2,14 @@
Gem::Specification.new do |s|
s.name = "bigdecimal"
- s.version = "3.1.2"
+ 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]
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/extconf.rb b/ext/bigdecimal/extconf.rb
index 9b0c55b21c..17e7905dd6 100644
--- a/ext/bigdecimal/extconf.rb
+++ b/ext/bigdecimal/extconf.rb
@@ -67,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/escape.c b/ext/cgi/escape/escape.c
index f88b61478b..c5b76de596 100644
--- a/ext/cgi/escape/escape.c
+++ b/ext/cgi/escape/escape.c
@@ -37,7 +37,7 @@ 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);
+ ruby_malloc_size_overflow(len, HTML_ESCAPE_MAX_LEN);
}
return len * HTML_ESCAPE_MAX_LEN;
}
@@ -81,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;
@@ -94,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);
}
}
@@ -200,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;
@@ -211,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;
@@ -254,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;
}
@@ -317,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);
}
}
@@ -337,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);
}
}
@@ -348,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
@@ -357,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);
}
}
@@ -368,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);
}
@@ -376,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
@@ -387,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);
}
}
@@ -414,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/coverage/coverage.c b/ext/coverage/coverage.c
index 3dc2490d40..4578de54e4 100644
--- a/ext/coverage/coverage.c
+++ b/ext/coverage/coverage.c
@@ -24,11 +24,37 @@ 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.setup => nil
- * Coverage.setup(:all) => nil
- * Coverage.setup(lines: bool, branches: bool, methods: bool) => nil
- * Coverage.setup(oneshot_lines: true) => 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.
*
@@ -44,56 +70,57 @@ rb_coverage_setup(int argc, VALUE *argv, VALUE klass)
int mode;
if (current_state != IDLE) {
- rb_raise(rb_eRuntimeError, "coverage measurement is already setup");
+ 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;
}
@@ -104,7 +131,7 @@ rb_coverage_setup(int argc, VALUE *argv, VALUE klass)
* Start/resume the coverage measurement.
*
* Caveat: Currently, only process-global coverage measurement is supported.
- * You cannot measure per-thread covearge. If your process has multiple thread,
+ * 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.
*/
@@ -112,10 +139,10 @@ VALUE
rb_coverage_resume(VALUE klass)
{
if (current_state == IDLE) {
- rb_raise(rb_eRuntimeError, "coverage measurement is not set up yet");
+ 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_raise(rb_eRuntimeError, "coverage measurement is already running");
}
rb_resume_coverages();
current_state = RUNNING;
@@ -124,10 +151,10 @@ rb_coverage_resume(VALUE klass)
/*
* call-seq:
- * Coverage.start => nil
- * Coverage.start(:all) => nil
- * Coverage.start(lines: bool, branches: bool, methods: bool) => nil
- * Coverage.start(oneshot_lines: true) => nil
+ * 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.
@@ -218,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);
@@ -272,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);
@@ -322,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);
@@ -354,7 +381,7 @@ VALUE
rb_coverage_suspend(VALUE klass)
{
if (current_state != RUNNING) {
- rb_raise(rb_eRuntimeError, "coverage measurement is not running");
+ rb_raise(rb_eRuntimeError, "coverage measurement is not running");
}
rb_suspend_coverages();
current_state = SUSPENDED;
@@ -377,7 +404,7 @@ rb_coverage_result(int argc, VALUE *argv, VALUE klass)
int stop = 1, clear = 1;
if (current_state == IDLE) {
- rb_raise(rb_eRuntimeError, "coverage measurement is not enabled");
+ rb_raise(rb_eRuntimeError, "coverage measurement is not enabled");
}
rb_scan_args(argc, argv, "01", &opt);
@@ -443,7 +470,7 @@ rb_coverage_running(VALUE klass)
* This feature is experimental, so these APIs may be changed in future.
*
* Caveat: Currently, only process-global coverage measurement is supported.
- * You cannot measure per-thread covearge.
+ * You cannot measure per-thread coverage.
*
* = Usage
*
@@ -589,6 +616,9 @@ 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);
diff --git a/ext/coverage/depend b/ext/coverage/depend
index 7c6aa6c2d8..e7fab16484 100644
--- a/ext/coverage/depend
+++ b/ext/coverage/depend
@@ -165,10 +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)/darray.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
@@ -177,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 cf07696976..660353ebc5 100644
--- a/ext/date/date.gemspec
+++ b/ext/date/date.gemspec
@@ -10,14 +10,22 @@ Gem::Specification.new do |s|
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 c7b4459c89..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
*
- * Just returns true. It's nonsense, but is for symmetry.
+ * Implemented for compatibility;
+ * returns +true+ unless +jd+ is invalid (i.e., not a Numeric).
*
- * Date.valid_jd?(2451944) #=> true
+ * Date.valid_jd?(2451944) # => true
*
- * See also ::jd.
+ * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ *
+ * 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:
*
- * 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.
+ * Date.valid_date?(2001, 2, 3) # => true
+ * Date.valid_date?(2001, 2, 29) # => false
+ * Date.valid_date?(2001, 2, -1) # => true
*
- * Date.valid_date?(2001,2,3) #=> true
- * Date.valid_date?(2001,2,29) #=> false
- * Date.valid_date?(2001,2,-1) #=> true
+ * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
*
- * See also ::jd and ::civil.
+ * Date.valid_date? is an alias for Date.valid_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 given ordinal date is valid, and false if not.
+ * Returns +true+ if the arguments define a valid ordinal date,
+ * +false+ otherwise:
*
- * 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 also ::jd and ::ordinal.
+ * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ *
+ * 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 arguments define a valid commercial date,
+ * +false+ otherwise:
*
- * Returns true if the given week date is valid, and false if not.
+ * 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 Date.commercial.
*
- * See also ::jd and ::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
+ *
+ * Returns a new \Date object formed from the arguments:
+ *
+ * Date.jd(2451944).to_s # => "2001-02-03"
+ * Date.jd(2451945).to_s # => "2001-02-04"
+ * Date.jd(0).to_s # => "-4712-01-01"
*
- * Creates a date object denoting the given chronological Julian day
- * number.
+ * The returned date is:
*
- * Date.jd(2451944) #=> #<Date: 2001-02-03 ...>
- * Date.jd(2451945) #=> #<Date: 2001-02-04 ...>
- * Date.jd(0) #=> #<Date: -4712-01-01 ...>
+ * - Gregorian, if the argument is greater than or equal to +start+:
*
- * See also ::new.
+ * 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.
*
- * Creates a date object denoting the given ordinal date.
+ * With no arguments, returns the date for January 1, -4712:
*
- * 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.
+ * Date.ordinal.to_s # => "-4712-01-01"
*
- * Date.ordinal(2001) #=> #<Date: 2001-01-01 ...>
- * Date.ordinal(2001,34) #=> #<Date: 2001-02-03 ...>
- * Date.ordinal(2001,-1) #=> #<Date: 2001-12-31 ...>
+ * With argument +year+, returns the date for January 1 of that year:
*
- * See also ::jd and ::new.
+ * 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:
+ *
+ * Date.ordinal(2001, 14).to_s # => "2001-01-14"
+ *
+ * With negative argument +yday+, counts backward from the end of the year:
+ *
+ * Date.ordinal(2001, -14).to_s # => "2001-12-18"
+ *
+ * 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:
+ *
+ * Date.commercial(2022, 1, 1).to_s # => "2022-01-03"
+ * Date.commercial(2022, 1, -7).to_s # => "2022-01-03"
+ *
+ * When +cweek+ is 1:
+ *
+ * - If January 1 is a Friday, Saturday, or Sunday,
+ * the first week begins in the week after:
*
- * Creates a date object denoting the given week date.
+ * 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"
*
- * 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.
+ * - Otherwise, the first week is the week of January 1,
+ * which may mean some of the days fall on the year before:
*
- * Date.commercial(2001) #=> #<Date: 2001-01-01 ...>
- * Date.commercial(2002) #=> #<Date: 2001-12-31 ...>
- * Date.commercial(2001,5,6) #=> #<Date: 2001-02-03 ...>
+ * 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 also ::jd and ::new.
+ * 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
+ *
+ * Returns a new \Date object constructed from the present date:
+ *
+ * Date.today.to_s # => "2022-07-06"
*
- * Creates a date object denoting the present day.
+ * 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)
@@ -4385,25 +4507,32 @@ date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * Date._parse(string[, comp=true], limit: 128) -> 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}
+ * Date._parse('2001-02-03') # => {:year=>2001, :mon=>2, :mday=>3}
*
- * Raise an ArgumentError when the string length is longer than _limit_.
- * You can stop this check by passing `limit: nil`, but note that
- * it may take a long time to parse.
+ * 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].
+ *
+ * Related: Date.parse(returns a \Date object).
*/
static VALUE
date_s__parse(int argc, VALUE *argv, VALUE klass)
@@ -4413,27 +4542,36 @@ date_s__parse(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * Date.parse(string='-4712-01-01'[, comp=true[, start=Date::ITALY]], limit: 128) -> 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>
*
- * 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:
*
- * Raise an ArgumentError when the string length is longer than _limit_.
- * You can stop this check by passing `limit: nil`, but note that
- * it may take a long time to parse.
+ * Date.parse('01-02-03', true) # => #<Date: 2001-02-03>
+ * Date.parse('01-02-03', false) # => #<Date: 0001-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)
@@ -4472,13 +4610,18 @@ VALUE date__jisx0301(VALUE);
/*
* call-seq:
- * Date._iso8601(string, limit: 128) -> hash
+ * Date._iso8601(string, limit: 128) -> hash
*
- * Returns a hash of parsed elements.
+ * 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]:
*
- * Raise an ArgumentError when the string length is longer than _limit_.
- * You can stop this check by passing `limit: nil`, but note that
- * it may take a long time to parse.
+ * 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(int argc, VALUE *argv, VALUE klass)
@@ -4493,18 +4636,22 @@ date_s__iso8601(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * Date.iso8601(string='-4712-01-01'[, start=Date::ITALY], limit: 128) -> 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]:
*
- * 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 ...>
+ * d = Date.new(2001, 2, 3)
+ * s = d.iso8601 # => "2001-02-03"
+ * Date.iso8601(s) # => #<Date: 2001-02-03>
*
- * Raise an ArgumentError when the string length is longer than _limit_.
- * You can stop this check by passing `limit: nil`, but note that
- * it may take a long time to parse.
+ * 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)
@@ -4533,13 +4680,19 @@ date_s_iso8601(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * Date._rfc3339(string, limit: 128) -> hash
+ * Date._rfc3339(string, limit: 128) -> hash
*
- * Returns a hash of parsed elements.
+ * Returns a hash of values parsed from +string+, which should be a valid
+ * {RFC 3339 format}[rdoc-ref:strftime_formatting.rdoc@RFC+3339+Format]:
*
- * Raise an ArgumentError when the string length is longer than _limit_.
- * You can stop this check by passing `limit: nil`, but note that
- * it may take a long time to parse.
+ * 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(int argc, VALUE *argv, VALUE klass)
@@ -4554,16 +4707,22 @@ date_s__rfc3339(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * Date.rfc3339(string='-4712-01-01T00:00:00+00:00'[, start=Date::ITALY], limit: 128) -> 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]:
*
- * Date.rfc3339('2001-02-03T04:05:06+07:00') #=> #<Date: 2001-02-03 ...>
+ * d = Date.new(2001, 2, 3)
+ * s = d.rfc3339 # => "2001-02-03T00:00:00+00:00"
+ * Date.rfc3339(s) # => #<Date: 2001-02-03>
*
- * Raise an ArgumentError when the string length is longer than _limit_.
- * You can stop this check by passing `limit: nil`, but note that
- * it may take a long time to parse.
+ * See:
+ *
+ * - Argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * - Argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Related: Date._rfc3339 (returns a hash).
*/
static VALUE
date_s_rfc3339(int argc, VALUE *argv, VALUE klass)
@@ -4592,13 +4751,18 @@ date_s_rfc3339(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * Date._xmlschema(string, limit: 128) -> 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:
*
- * Raise an ArgumentError when the string length is longer than _limit_.
- * You can stop this check by passing `limit: nil`, but note that
- * it may take a long time to parse.
+ * 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(int argc, VALUE *argv, VALUE klass)
@@ -4613,16 +4777,21 @@ date_s__xmlschema(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * Date.xmlschema(string='-4712-01-01'[, start=Date::ITALY], limit: 128) -> 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>
*
- * Raise an ArgumentError when the string length is longer than _limit_.
- * You can stop this check by passing `limit: nil`, but note that
- * it may take a long time to parse.
+ * 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)
@@ -4651,14 +4820,21 @@ date_s_xmlschema(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * Date._rfc2822(string, limit: 128) -> hash
- * Date._rfc822(string, limit: 128) -> hash
+ * Date._rfc2822(string, limit: 128) -> hash
*
- * Returns a hash of parsed elements.
+ * 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]:
*
- * Raise an ArgumentError when the string length is longer than _limit_.
- * You can stop this check by passing `limit: nil`, but note that
- * it may take a long time to parse.
+ * 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].
+ *
+ * Date._rfc822 is an alias for Date._rfc2822.
+ *
+ * Related: Date.rfc2822 (returns a \Date object).
*/
static VALUE
date_s__rfc2822(int argc, VALUE *argv, VALUE klass)
@@ -4673,18 +4849,24 @@ date_s__rfc2822(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * Date.rfc2822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128) -> date
- * Date.rfc822(string='Mon, 1 Jan -4712 00:00:00 +0000'[, start=Date::ITALY], limit: 128) -> date
+ * 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]:
*
- * Date.rfc2822('Sat, 3 Feb 2001 00:00:00 +0000')
- * #=> #<Date: 2001-02-03 ...>
+ * d = Date.new(2001, 2, 3)
+ * s = d.rfc2822 # => "Sat, 3 Feb 2001 00:00:00 +0000"
+ * Date.rfc2822(s) # => #<Date: 2001-02-03>
*
- * Raise an ArgumentError when the string length is longer than _limit_.
- * You can stop this check by passing `limit: nil`, but note that
- * it may take a long time to parse.
+ * See:
+ *
+ * - 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)
@@ -4712,13 +4894,17 @@ date_s_rfc2822(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * Date._httpdate(string, limit: 128) -> hash
+ * Date._httpdate(string, limit: 128) -> hash
*
- * Returns a hash of parsed elements.
+ * Returns a hash of values parsed from +string+, which should be a valid
+ * {HTTP date format}[rdoc-ref:strftime_formatting.rdoc@HTTP+Format]:
*
- * Raise an ArgumentError when the string length is longer than _limit_.
- * You can stop this check by passing `limit: nil`, but note that
- * it may take a long time to parse.
+ * 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(int argc, VALUE *argv, VALUE klass)
@@ -4733,17 +4919,22 @@ date_s__httpdate(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * Date.httpdate(string='Mon, 01 Jan -4712 00:00:00 GMT'[, start=Date::ITALY], limit: 128) -> 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]:
*
- * Date.httpdate('Sat, 03 Feb 2001 00:00:00 GMT')
- * #=> #<Date: 2001-02-03 ...>
+ * d = Date.new(2001, 2, 3)
+ s = d.httpdate # => "Sat, 03 Feb 2001 00:00:00 GMT"
+ Date.httpdate(s) # => #<Date: 2001-02-03>
*
- * Raise an ArgumentError when the string length is longer than _limit_.
- * You can stop this check by passing `limit: nil`, but note that
- * it may take a long time to parse.
+ * See:
+ *
+ * - 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)
@@ -4771,13 +4962,18 @@ date_s_httpdate(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * Date._jisx0301(string, limit: 128) -> hash
+ * Date._jisx0301(string, limit: 128) -> hash
*
- * Returns a hash of parsed elements.
+ * 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]:
*
- * Raise an ArgumentError when the string length is longer than _limit_.
- * You can stop this check by passing `limit: nil`, but note that
- * it may take a long time to parse.
+ * d = Date.new(2001, 2, 3)
+ * s = d.jisx0301 # => "H13.02.03"
+ * Date._jisx0301(s) # => {:year=>2001, :mon=>2, :mday=>3}
+ *
+ * See argument {limit}[rdoc-ref:Date@Argument+limit].
+ *
+ * Related: Date.jisx0301 (returns a \Date object).
*/
static VALUE
date_s__jisx0301(int argc, VALUE *argv, VALUE klass)
@@ -4792,20 +4988,25 @@ date_s__jisx0301(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * Date.jisx0301(string='-4712-01-01'[, start=Date::ITALY], limit: 128) -> 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>
*
- * Raise an ArgumentError when the string length is longer than _limit_.
- * You can stop this check by passing `limit: nil`, but note that
- * it may take a long time to parse.
+ * 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)
@@ -4997,6 +5198,7 @@ d_lite_initialize_copy(VALUE copy, VALUE date)
}
#ifndef NDEBUG
+/* :nodoc: */
static VALUE
d_lite_fill(VALUE self)
{
@@ -5086,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)
@@ -5102,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)
@@ -5118,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)
@@ -5133,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)
@@ -5149,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)
@@ -5165,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)
@@ -5182,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)
@@ -5198,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)
@@ -5213,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)
@@ -5227,6 +5444,7 @@ d_lite_cwday(VALUE self)
}
#ifndef NDEBUG
+/* :nodoc: */
static VALUE
d_lite_wnum0(VALUE self)
{
@@ -5234,6 +5452,7 @@ d_lite_wnum0(VALUE self)
return INT2FIX(m_wnum0(dat));
}
+/* :nodoc: */
static VALUE
d_lite_wnum1(VALUE self)
{
@@ -5244,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)
@@ -5259,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)
@@ -5272,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)
@@ -5285,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)
@@ -5298,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)
@@ -5311,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)
@@ -5324,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)
@@ -5337,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)
@@ -5349,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)
{
@@ -5370,11 +5591,12 @@ d_lite_nth_kday_p(VALUE self, VALUE n, VALUE k)
/*
* call-seq:
- * d.hour -> fixnum
+ * hour -> integer
*
- * Returns the hour (0-23).
+ * Returns the hour in range (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)
@@ -5385,12 +5607,13 @@ d_lite_hour(VALUE self)
/*
* call-seq:
- * d.min -> fixnum
- * d.minute -> fixnum
+ * min -> integer
+ *
+ * Returns the minute in range (0..59):
*
- * Returns the minute (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)
@@ -5401,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)
@@ -5417,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.
+ * Returns the fractional part of the second in range
+ * (Rational(0, 1)...Rational(1, 1)):
*
- * 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)
@@ -5463,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 date of calendar reform,
+ * +false+ otherwise:
*
- * Returns true if the date is before the day of calendar reform.
+ * (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)
@@ -5479,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 day of calendar reform.
+ * Returns +true+ if the date is on or after
+ * the date of calendar reform, +false+ otherwise:
+ *
+ * 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)
@@ -5495,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)
@@ -5519,12 +5750,25 @@ d_lite_leap_p(VALUE self)
/*
* call-seq:
- * d.start -> float
+ * start -> float
+ *
+ * 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
*
- * Returns the Julian day number denoting the day of calendar reform.
+ * 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)
@@ -5589,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
*
- * Duplicates self and resets its day of calendar reform.
+ * 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
+ *
+ * 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)
@@ -5613,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)
@@ -5625,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)
@@ -5637,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)
@@ -5649,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)
@@ -6132,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)
@@ -6149,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)
@@ -6166,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)
@@ -6179,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)
@@ -6243,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)
@@ -6271,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)
@@ -6290,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)
@@ -6309,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)
@@ -6332,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)
@@ -6357,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+.
+ *
+ * - 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.
+ *
+ * Example:
*
- * Iterates evaluation of the given block, which takes a date object.
- * The limit should be a date object.
+ * limit = Date.new(2001, 12, 31)
+ * Date.new(2001).step(limit){|date| p date.to_s if date.mday == 31 }
*
- * Date.new(2001).step(Date.new(2001,-1,-1)).select{|d| d.sunday?}.size
- * #=> 52
+ * 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)
@@ -6407,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)
@@ -6429,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)
@@ -6520,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.
+ *
+ * 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 <=> 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
*
- * 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.
+ * - Any other object:
*
- * 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
+ * d <=> Object.new # => nil
*
- * See also Comparable.
*/
static VALUE
d_lite_cmp(VALUE self, VALUE other)
@@ -6592,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)
@@ -6668,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)
@@ -6682,6 +6991,7 @@ d_lite_to_s(VALUE self)
}
#ifndef NDEBUG
+/* :nodoc: */
static VALUE
mk_inspect_raw(union DateData *x, VALUE klass)
{
@@ -6731,6 +7041,7 @@ mk_inspect_raw(union DateData *x, VALUE klass)
}
}
+/* :nodoc: */
static VALUE
d_lite_inspect_raw(VALUE self)
{
@@ -6752,14 +7063,13 @@ mk_inspect(union DateData *x, VALUE klass, VALUE to_s)
/*
* call-seq:
- * d.inspect -> string
+ * inspect -> string
*
- * Returns the value as a string for inspection.
+ * Returns a string representation of +self+:
+ *
+ * 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)
@@ -6941,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)
@@ -7142,13 +7288,17 @@ strftimev(const char *fmt, VALUE self,
/*
* call-seq:
- * d.asctime -> string
- * d.ctime -> string
+ * asctime -> string
*
- * Returns a string in asctime(3) format (but without "\n\0" at the
- * end). This method is equivalent to strftime('%c').
+ * 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>):
*
- * See also asctime(3) or ctime(3).
+ * Date.new(2001, 2, 3).asctime # => "Sat Feb 3 00:00:00 2001"
+ *
+ * See {asctime}[https://linux.die.net/man/3/asctime].
+ *
+ * Date#ctime is an alias for Date#asctime.
*/
static VALUE
d_lite_asctime(VALUE self)
@@ -7158,10 +7308,15 @@ d_lite_asctime(VALUE self)
/*
* call-seq:
- * d.iso8601 -> string
- * d.xmlschema -> string
+ * iso8601 -> string
+ *
+ * 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>);
*
- * This method is equivalent to strftime('%F').
+ * Date.new(2001, 2, 3).iso8601 # => "2001-02-03"
+ *
+ * Date#xmlschema is an alias for Date#iso8601.
*/
static VALUE
d_lite_iso8601(VALUE self)
@@ -7171,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)
@@ -7183,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)
@@ -7196,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)
@@ -7250,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)
@@ -7269,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)
{
@@ -7557,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)
@@ -7757,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)
{
@@ -7826,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)
{
@@ -8171,9 +8422,9 @@ datetime_s_strptime(int argc, VALUE *argv, VALUE klass)
* 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
@@ -8187,8 +8438,8 @@ datetime_s_strptime(int argc, VALUE *argv, VALUE klass)
* #=> #<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 `limit: nil`, but note that
- * it may take a long time to parse.
+ * 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)
@@ -8234,8 +8485,8 @@ datetime_s_parse(int argc, VALUE *argv, VALUE klass)
* #=> #<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 `limit: nil`, but note that
- * it may take a long time to parse.
+ * 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)
@@ -8274,8 +8525,8 @@ datetime_s_iso8601(int argc, VALUE *argv, VALUE klass)
* #=> #<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 `limit: nil`, but note that
- * it may take a long time to parse.
+ * 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)
@@ -8314,8 +8565,8 @@ datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass)
* #=> #<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 `limit: nil`, but note that
- * it may take a long time to parse.
+ * 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)
@@ -8355,8 +8606,8 @@ datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass)
* #=> #<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 `limit: nil`, but note that
- * it may take a long time to parse.
+ * 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)
@@ -8395,8 +8646,8 @@ datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass)
* #=> #<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 `limit: nil`, but note that
- * it may take a long time to parse.
+ * 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)
@@ -8440,8 +8691,8 @@ datetime_s_httpdate(int argc, VALUE *argv, VALUE klass)
* #=> #<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 `limit: nil`, but note that
- * it may take a long time to parse.
+ * 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)
@@ -8487,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)
@@ -8749,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)
@@ -8827,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);
@@ -8840,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)
@@ -8864,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)
@@ -8878,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)
@@ -8923,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,
@@ -8996,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)
{
@@ -9016,6 +9157,7 @@ test_civil(int from, int to, double sg)
return 1;
}
+/* :nodoc: */
static VALUE
date_s_test_civil(VALUE klass)
{
@@ -9036,6 +9178,7 @@ date_s_test_civil(VALUE klass)
return Qtrue;
}
+/* :nodoc: */
static int
test_ordinal(int from, int to, double sg)
{
@@ -9056,6 +9199,7 @@ test_ordinal(int from, int to, double sg)
return 1;
}
+/* :nodoc: */
static VALUE
date_s_test_ordinal(VALUE klass)
{
@@ -9076,6 +9220,7 @@ date_s_test_ordinal(VALUE klass)
return Qtrue;
}
+/* :nodoc: */
static int
test_commercial(int from, int to, double sg)
{
@@ -9096,6 +9241,7 @@ test_commercial(int from, int to, double sg)
return 1;
}
+/* :nodoc: */
static VALUE
date_s_test_commercial(VALUE klass)
{
@@ -9116,6 +9262,7 @@ date_s_test_commercial(VALUE klass)
return Qtrue;
}
+/* :nodoc: */
static int
test_weeknum(int from, int to, int f, double sg)
{
@@ -9136,6 +9283,7 @@ test_weeknum(int from, int to, int f, double sg)
return 1;
}
+/* :nodoc: */
static VALUE
date_s_test_weeknum(VALUE klass)
{
@@ -9160,6 +9308,7 @@ date_s_test_weeknum(VALUE klass)
return Qtrue;
}
+/* :nodoc: */
static int
test_nth_kday(int from, int to, double sg)
{
@@ -9180,6 +9329,7 @@ test_nth_kday(int from, int to, double sg)
return 1;
}
+/* :nodoc: */
static VALUE
date_s_test_nth_kday(VALUE klass)
{
@@ -9200,6 +9350,7 @@ date_s_test_nth_kday(VALUE klass)
return Qtrue;
}
+/* :nodoc: */
static int
test_unit_v2v(VALUE i,
VALUE (* conv1)(VALUE),
@@ -9211,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))
@@ -9242,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))
@@ -9253,6 +9406,7 @@ test_unit_v2v_iter(VALUE (* conv1)(VALUE),
return 1;
}
+/* :nodoc: */
static VALUE
date_s_test_unit_conv(VALUE klass)
{
@@ -9267,6 +9421,7 @@ date_s_test_unit_conv(VALUE klass)
return Qtrue;
}
+/* :nodoc: */
static VALUE
date_s_test_all(VALUE klass)
{
@@ -9333,6 +9488,7 @@ mk_ary_of_str(long len, const char *a[])
return o;
}
+/* :nodoc: */
static VALUE
d_lite_zero(VALUE x)
{
@@ -9350,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
@@ -9370,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.
- *
- * == Terms and Definitions
- *
- * Some terms and definitions are based on ISO 8601 and JIS X 0301.
+ * \Class \Date provides methods for storing and manipulating
+ * calendar dates.
*
- * === Calendar Date
+ * Consider using
+ * {class Time}[rdoc-ref:Time]
+ * instead of class \Date if:
*
- * The calendar date is a particular day of a calendar year,
- * identified by its ordinal number within a calendar month within
- * that year.
+ * - 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].
*
- * In those classes, this is so-called "civil".
+ * A \Date object, once created, is immutable, and cannot be modified.
*
- * === Ordinal Date
+ * == Creating a \Date
*
- * The ordinal date is a particular day of a calendar year identified
- * by its ordinal number within the year.
+ * You can create a date for the current date, using Date.today:
*
- * In those classes, this is so-called "ordinal".
+ * Date.today # => #<Date: 1999-12-31>
*
- * === Week Date
+ * You can create a specific date from various combinations of arguments:
*
- * The week date is a date identified by calendar week and day numbers.
+ * - Date.new takes integer year, month, and day-of-month:
*
- * 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.new(1999, 12, 31) # => #<Date: 1999-12-31>
*
- * In those classes, this is so-called "commercial".
+ * - Date.ordinal takes integer year and day-of-year:
*
- * === Julian Day Number
+ * Date.ordinal(1999, 365) # => #<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.jd takes integer Julian day:
*
- * 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.jd(2451544) # => #<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.commercial takes integer commercial data (year, week, day-of-week):
*
- * In those classes, those are so-called "ajd" and "jd".
+ * Date.commercial(1999, 52, 5) # => #<Date: 1999-12-31>
*
- * === Modified Julian Day Number
+ * - Date.parse takes a string, which it parses heuristically:
*
- * The modified Julian day number is in elapsed days since midnight
- * (Coordinated Universal Time) on November 17, 1858 CE (in the
- * Gregorian calendar).
+ * 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>
*
- * 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.
+ * - Date.strptime takes a date string and a format string,
+ * then parses the date string according to the format string:
*
- * In this document, when the term "modified Julian day number" simply
- * appears, it just refers to "chronological modified Julian day
- * number", not the original.
+ * 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 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'
+ * See also the specialized methods in
+ * {"Specialized Format Strings" in Formats for Dates and Times}[rdoc-ref:strftime_formatting.rdoc@Specialized+Format+Strings]
*
- * 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 ...>
+ * == Argument +limit+
*
- * All date objects are immutable; hence cannot modify themselves.
+ * Certain singleton methods in \Date that parse string arguments
+ * also take optional keyword argument +limit+,
+ * which can limit the length of the string argument.
*
- * The concept of a date object can be represented as a tuple
- * of the day count, the offset and the day of calendar reform.
+ * When +limit+ is:
*
- * 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);
@@ -9742,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
@@ -9952,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 95274d5baa..c6f26ecb91 100644
--- a/ext/date/date_parse.c
+++ b/ext/date/date_parse.c
@@ -413,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);
@@ -439,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)
@@ -457,6 +466,7 @@ date_zone_to_diff(VALUE str)
goto ok;
}
}
+
{
char *p;
int sign = 0;
@@ -473,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) {
@@ -506,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;
}
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/lib/date.rb b/ext/date/lib/date.rb
index 5770187a8e..a9fe3ce4b0 100644
--- a/ext/date/lib/date.rb
+++ b/ext/date/lib/date.rb
@@ -4,8 +4,12 @@
require 'date_core'
class Date
- VERSION = '3.2.2' # :nodoc:
+ VERSION = "3.3.3" # :nodoc:
+ # call-seq:
+ # infinite? -> false
+ #
+ # Returns +false+
def infinite?
false
end
diff --git a/ext/date/zonetab.h b/ext/date/zonetab.h
index d82b011dc1..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,
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/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.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/lib/digest/version.rb b/ext/digest/lib/digest/version.rb
index 79e6aeee99..42fd7acf6e 100644
--- a/ext/digest/lib/digest/version.rb
+++ b/ext/digest/lib/digest/version.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
module Digest
- VERSION = "3.1.0"
+ VERSION = "3.1.1"
end
diff --git a/ext/digest/md5/depend b/ext/digest/md5/depend
index 0353e7a40d..ea1ceec7fd 100644
--- a/ext/digest/md5/depend
+++ b/ext/digest/md5/depend
@@ -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/sha1/depend b/ext/digest/sha1/depend
index a4e454d214..48aaef158b 100644
--- a/ext/digest/sha1/depend
+++ b/ext/digest/sha1/depend
@@ -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 2fb598aa48..47a859068c 100644
--- a/ext/digest/sha2/depend
+++ b/ext/digest/sha2/depend
@@ -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/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/etc.c b/ext/etc/etc.c
index 9a691d6e34..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.4.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
@@ -1067,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+.
@@ -1096,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);
@@ -1159,14 +1169,17 @@ Init_etc(void)
NULL);
#if 0
/*
- * Passwd is a Struct that contains the following members:
+ * Passwd is a placeholder Struct for user database on Unix systems.
+ *
+ * === 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,25 +1189,24 @@ 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).
*/
sPasswd = rb_define_class_under(mEtc, "Passwd", rb_cStruct);
#endif
@@ -1210,9 +1222,9 @@ Init_etc(void)
#if 0
/*
- * 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.
@@ -1221,7 +1233,7 @@ Init_etc(void)
* 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::
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/fcntl.gemspec b/ext/fcntl/fcntl.gemspec
index 048e101aa5..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.1"
+ 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/extconf.rb b/ext/fiddle/extconf.rb
index 93b4f9d4fa..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
@@ -167,7 +151,7 @@ if libffi_version
libffi_version = libffi_version.gsub(/-rc\d+/, '')
libffi_version = (libffi_version.split('.').map(&:to_i) + [0,0])[0,3]
$defs.push(%{-DRUBY_LIBFFI_MODVERSION=#{ '%d%03d%03d' % libffi_version }})
- puts "libffi_version: #{libffi_version.join('.')}"
+ warn "libffi_version: #{libffi_version.join('.')}"
end
case
@@ -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 a9c0ec4026..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",
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/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 4ec24178c4..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
@@ -112,18 +112,34 @@ rb_f_send(int argc, VALUE *argv, VALUE recv)
}
#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
@@ -138,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);
@@ -165,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:
@@ -1633,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 06ccdde70d..36747ef583 100644
--- a/ext/io/console/depend
+++ b/ext/io/console/depend
@@ -185,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 aa57f8ac52..d26a757b01 100644
--- a/ext/io/console/io-console.gemspec
+++ b/ext/io/console/io-console.gemspec
@@ -1,5 +1,5 @@
# -*- ruby -*-
-_VERSION = "0.5.11"
+_VERSION = "0.6.0"
Gem::Specification.new do |s|
s.name = "io-console"
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/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/extconf.rb b/ext/io/wait/extconf.rb
index eecdcce99f..c6230b7783 100644
--- a/ext/io/wait/extconf.rb
+++ b/ext/io/wait/extconf.rb
@@ -5,7 +5,7 @@ if RUBY_VERSION < "2.6"
File.write("Makefile", dummy_makefile($srcdir).join(""))
else
target = "io/wait"
- have_func("rb_io_wait")
+ have_func("rb_io_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|
diff --git a/ext/io/wait/io-wait.gemspec b/ext/io/wait/io-wait.gemspec
index ad1624585b..ebc1f6f5c7 100644
--- a/ext/io/wait/io-wait.gemspec
+++ b/ext/io/wait/io-wait.gemspec
@@ -1,10 +1,10 @@
-_VERSION = "0.2.2.pre1"
+_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.}
@@ -16,11 +16,23 @@ Gem::Specification.new do |spec|
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) 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)})
+ 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 568c7b54a8..d74afb580b 100644
--- a/ext/io/wait/wait.c
+++ b/ext/io/wait/wait.c
@@ -41,22 +41,17 @@
#endif
#ifndef HAVE_RB_IO_WAIT
-static VALUE io_ready_p _((VALUE io));
-static VALUE io_wait_readable _((int argc, VALUE *argv, VALUE io));
-static VALUE io_wait_writable _((int argc, VALUE *argv, VALUE io));
-void Init_wait _((void));
-
static struct timeval *
get_timeout(int argc, VALUE *argv, struct timeval *timerec)
{
VALUE timeout = Qnil;
rb_check_arity(argc, 0, 1);
if (!argc || NIL_P(timeout = argv[0])) {
- return NULL;
+ return NULL;
}
else {
- *timerec = rb_time_interval(timeout);
- return timerec;
+ *timerec = rb_time_interval(timeout);
+ return timerec;
}
}
@@ -65,7 +60,7 @@ 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_sys_fail(0);
rb_io_check_closed(fptr);
return (i & events);
}
@@ -100,21 +95,24 @@ io_nread(VALUE io)
#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
@@ -142,15 +140,15 @@ io_ready_p(VALUE io)
if (rb_io_read_pending(fptr)) return Qtrue;
#ifndef HAVE_RB_IO_WAIT
- if (wait_for_single_fd(fptr, RB_WAITFD_IN, &tv))
- return Qtrue;
+ return wait_for_single_fd(fptr, RB_WAITFD_IN, &tv) ? Qtrue : Qfalse;
#else
- if (RTEST(io_wait_event(io, RUBY_IO_READABLE, RB_INT2NUM(0))))
- return Qtrue;
+ return io_wait_event(io, RUBY_IO_READABLE, RB_INT2NUM(0), 1);
#endif
- return Qfalse;
}
+/* Ruby 3.2+ can define these methods. This macro indicates that case. */
+#ifndef RUBY_IO_WAIT_METHODS
+
/*
* call-seq:
* io.wait_readable -> truthy or falsy
@@ -182,14 +180,14 @@ io_wait_readable(int argc, VALUE *argv, VALUE io)
#ifndef HAVE_RB_IO_WAIT
if (wait_for_single_fd(fptr, RB_WAITFD_IN, tv)) {
- return io;
+ 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
}
@@ -218,14 +216,14 @@ io_wait_writable(int argc, VALUE *argv, VALUE io)
#ifndef HAVE_RB_IO_WAIT
tv = get_timeout(argc, argv, &timerec);
if (wait_for_single_fd(fptr, RB_WAITFD_OUT, tv)) {
- return io;
+ 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
}
@@ -236,7 +234,8 @@ io_wait_writable(int argc, VALUE *argv, VALUE io)
* io.wait_priority(timeout) -> truthy or falsy
*
* Waits until IO is priority and returns a truthy value or a falsy
- * value when times out.
+ * value when times out. Priority data is sent and received using
+ * the Socket::MSG_OOB flag and is typically limited to streams.
*
* You must require 'io/wait' to use this method.
*/
@@ -253,7 +252,7 @@ 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
@@ -261,40 +260,52 @@ 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) -> truthy or falsy
- * io.wait(timeout = nil, mode = :read) -> truthy or falsy.
+ * 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.
@@ -322,61 +333,77 @@ io_wait(int argc, VALUE *argv, VALUE io)
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]);
- }
+ 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;
+ return Qtrue;
if (wait_for_single_fd(fptr, event, tv))
- return io;
+ 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
*/
@@ -391,6 +418,7 @@ 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);
@@ -398,4 +426,5 @@ Init_wait(void)
#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 6a6a3d8e35..ec1cf33c3f 100644
--- a/ext/json/VERSION
+++ b/ext/json/VERSION
@@ -1 +1 @@
-2.6.1
+2.6.3
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 35e8dd3252..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.6.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/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/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 533f9b782f..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.
@@ -365,7 +365,7 @@ rb_nkf_guess(VALUE obj, VALUE src)
* 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 2d77c71ff8..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.1"
+ 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 377b803d2a..52797664e0 100644
--- a/ext/objspace/depend
+++ b/ext/objspace/depend
@@ -158,12 +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/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
@@ -336,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
@@ -348,9 +356,17 @@ 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)
@@ -533,10 +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)/darray.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
@@ -545,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 66d6baa491..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
@@ -236,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;
}
@@ -258,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;
@@ -287,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) {
@@ -374,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");
@@ -387,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");
}
@@ -397,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);
@@ -408,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;
}
@@ -435,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;
}
}
@@ -455,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;
}
}
@@ -486,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;
}
}
@@ -518,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;
}
}
@@ -550,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 bd80e540cf..ca08604c95 100644
--- a/ext/objspace/objspace.c
+++ b/ext/objspace/objspace.c
@@ -62,9 +62,9 @@ total_i(VALUE v, void *ptr)
struct total_data *data = (struct total_data *)ptr;
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);
- }
+ if (data->klass == 0 || rb_obj_is_kind_of(v, data->klass)) {
+ data->total += rb_obj_memsize_of(v);
+ }
}
}
@@ -140,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);
@@ -190,33 +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_ZOMBIE);
#undef CASE_TYPE
default: rb_bug("type2sym: unknown type (%d)", i);
}
@@ -255,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;
@@ -379,127 +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_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;
}
@@ -629,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);
@@ -815,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);
}
}
@@ -870,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;
}
}
@@ -896,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)) {
@@ -923,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);
diff --git a/ext/objspace/objspace_dump.c b/ext/objspace/objspace_dump.c
index b570acbd95..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"
@@ -41,6 +46,7 @@ struct dump_config {
unsigned int full_heap: 1;
unsigned int partial_dump;
size_t since;
+ size_t shapes_since;
unsigned long buffer_len;
char buffer[BUFFER_CAPACITY];
};
@@ -76,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);
@@ -142,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);
@@ -163,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)];
@@ -235,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;
}
@@ -313,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)
{
@@ -323,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)
{
@@ -345,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;
@@ -361,6 +405,10 @@ 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);
@@ -389,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))
@@ -403,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:
@@ -417,7 +484,7 @@ 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 (FL_TEST(obj, RARRAY_EMBED_FLAG))
dump_append(dc, ", \"embedded\":true");
@@ -431,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\":");
@@ -443,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\":\"");
@@ -474,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:
@@ -486,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;
@@ -545,8 +619,8 @@ heap_i(void *vstart, void *vend, size_t stride, void *data)
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);
@@ -578,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;
@@ -587,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;
}
@@ -599,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
@@ -611,12 +689,14 @@ 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)
{
@@ -625,18 +705,87 @@ objspace_dump(VALUE os, VALUE obj, VALUE output)
dc.cur_page_slot_size = rb_gc_obj_slot_size(obj);
}
- dump_output(&dc, output, Qnil, Qnil);
+ 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 */
@@ -644,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)
{
@@ -659,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 479ec3b4a2..1e0df7dd87 100644
--- a/ext/openssl/History.md
+++ b/ext/openssl/History.md
@@ -1,3 +1,77 @@
+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
=============
@@ -100,6 +174,27 @@ Notable changes
[[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
=============
@@ -194,6 +289,16 @@ 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
=============
diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb
index 467f7e7a86..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,64 +138,59 @@ 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(NULL, NULL)", "openssl/ts.h")
-have_func("TS_VERIFY_CTX_set_store")
-have_func("TS_VERIFY_CTX_add_flags")
-have_func("TS_RESP_CTX_set_time_cb")
-have_func("EVP_PBE_scrypt")
-have_func("SSL_CTX_set_post_handshake_auth")
+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
-openssl_3 =
-have_func("SSL_set0_tmp_dh_pkey")
-have_func("ERR_get_error_all")
-have_func("TS_VERIFY_CTX_set_certs(NULL, NULL)", "openssl/ts.h")
-have_func("SSL_CTX_load_verify_file")
-have_func("BN_check_prime")
-have_func("EVP_MD_CTX_get0_md")
-have_func("EVP_MD_CTX_get_pkey_ctx")
-have_func("EVP_PKEY_eq")
-have_func("EVP_PKEY_dup")
+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"
-if openssl_3
- if $warnflags.sub!(/-W\K(?=deprecated-declarations)/, 'no-')
- $warnflags << " -Wno-incompatible-pointer-types-discards-qualifiers"
- end
-end
-
create_header
create_makefile("openssl")
Logging::message "Done.\n"
diff --git a/ext/openssl/lib/openssl/pkey.rb b/ext/openssl/lib/openssl/pkey.rb
index c3e0629091..0414658a10 100644
--- a/ext/openssl/lib/openssl/pkey.rb
+++ b/ext/openssl/lib/openssl/pkey.rb
@@ -167,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
@@ -355,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>.
@@ -378,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
@@ -399,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>.
@@ -420,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 a9103ecd27..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"
@@ -540,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 5e60604353..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 = "3.0.0"
+ VERSION = "3.1.0"
end
diff --git a/ext/openssl/openssl.gemspec b/ext/openssl/openssl.gemspec
index c6cd818336..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 = "3.0.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.}
diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h
index 4b5126893b..facb80aa73 100644
--- a/ext/openssl/ossl.h
+++ b/ext/openssl/ossl.h
@@ -43,13 +43,19 @@
#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))
+ (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))
+ (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)
diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c
index a61d3eefb1..71c452c88a 100644
--- a/ext/openssl/ossl_asn1.c
+++ b/ext/openssl/ossl_asn1.c
@@ -509,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);
@@ -522,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 */
@@ -546,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");
@@ -1522,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 56fa0ec302..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:
@@ -1234,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);
diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c
index d9c7891433..cb8fbc3ca2 100644
--- a/ext/openssl/ossl_cipher.c
+++ b/ext/openssl/ossl_cipher.c
@@ -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_hmac.c b/ext/openssl/ossl_hmac.c
index bfe3a74b12..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);
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 1e87484afc..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))
@@ -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_pkey.c b/ext/openssl/ossl_pkey.c
index 2a4835a28d..476256679b 100644
--- a/ext/openssl/ossl_pkey.c
+++ b/ext/openssl/ossl_pkey.c
@@ -99,17 +99,56 @@ ossl_pkey_read_generic(BIO *bio, VALUE pass)
/* 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 */
- OSSL_BIO_reset(bio);
if (OSSL_DECODER_CTX_set_input_type(dctx, "PEM") != 1)
goto out;
- while (OSSL_DECODER_from_bio(dctx, bio) != 1) {
- if (BIO_eof(bio))
+ /*
+ * 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;
}
@@ -200,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]);
@@ -670,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)) {
@@ -911,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);
@@ -1016,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));
diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h
index 38fb9fad10..10669b824c 100644
--- a/ext/openssl/ossl_pkey.h
+++ b/ext/openssl/ossl_pkey.h
@@ -92,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); \
diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c
index 696455dcfd..83c41378fe 100644
--- a/ext/openssl/ossl_pkey_dh.c
+++ b/ext/openssl/ossl_pkey_dh.c
@@ -178,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);
@@ -197,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
@@ -223,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;
@@ -252,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;
@@ -280,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;
diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c
index 25404aa7f5..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);
}
@@ -179,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);
@@ -198,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);
@@ -225,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))
@@ -244,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))
@@ -265,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;
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
index dee215447d..92842f95ac 100644
--- a/ext/openssl/ossl_pkey_ec.c
+++ b/ext/openssl/ossl_pkey_ec.c
@@ -227,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);
@@ -272,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);
@@ -323,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);
@@ -375,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);
@@ -391,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);
@@ -411,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
@@ -429,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
@@ -479,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;
@@ -664,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");
+ }
}
/*
@@ -1228,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;
}
/*
@@ -1249,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;
@@ -1270,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;
@@ -1293,7 +1313,7 @@ static VALUE ossl_ec_point_make_affine(VALUE self)
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;
@@ -1312,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;
}
@@ -1330,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;
}
diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c
index 4d66010f49..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);
}
@@ -174,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);
/*
@@ -193,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);
@@ -203,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);
@@ -453,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;
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index 9a0682a7cd..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;
@@ -291,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 */
@@ -441,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)
{
@@ -655,7 +706,7 @@ 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)
@@ -852,7 +903,7 @@ 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);
@@ -911,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;
}
@@ -959,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);
@@ -993,14 +1042,67 @@ 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:
@@ -1439,7 +1541,6 @@ ossl_sslctx_flush_sessions(int argc, VALUE *argv, VALUE self)
/*
* SSLSocket class
*/
-#ifndef OPENSSL_NO_SOCK
static inline int
ssl_started(SSL *ssl)
{
@@ -1602,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
@@ -1616,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;
@@ -2342,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
@@ -2392,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.
@@ -2419,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");
@@ -2441,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.
@@ -2613,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.
@@ -2635,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
@@ -2697,12 +2835,38 @@ 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
@@ -2779,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");
@@ -2814,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));
@@ -2974,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_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_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/pathname/lib/pathname.rb b/ext/pathname/lib/pathname.rb
index 3799d589d5..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,9 +578,9 @@ class Pathname # * Find *
end
-class Pathname # * FileUtils *
- autoload(:FileUtils, 'fileutils')
+autoload(:FileUtils, 'fileutils')
+class Pathname # * FileUtils *
# Creates a full path, including any intermediate directories that don't yet
# exist.
#
@@ -588,11 +592,12 @@ class Pathname # * FileUtils *
# 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".
- FileUtils.rm_r(@path)
+ require 'fileutils'
+ FileUtils.rm_rf(@path, noop: noop, verbose: verbose, secure: secure)
nil
end
end
diff --git a/ext/pathname/pathname.c b/ext/pathname/pathname.c
index 00ca85205b..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);
}
@@ -1465,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
@@ -1563,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);
@@ -1646,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 c9c0b84e69..92bc02b0db 100644
--- a/ext/pathname/pathname.gemspec
+++ b/ext/pathname/pathname.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "pathname"
- spec.version = "0.2.0"
+ spec.version = "0.2.1"
spec.authors = ["Tanaka Akira"]
spec.email = ["akr@fsij.org"]
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 b3952c8145..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
@@ -203,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
@@ -381,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
@@ -559,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
@@ -737,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
@@ -915,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 42d79efb83..4a2ab58514 100644
--- a/ext/psych/lib/psych.rb
+++ b/ext/psych/lib/psych.rb
@@ -307,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
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/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 58deea3baa..3cb4bf3c7e 100644
--- a/ext/psych/lib/psych/scalar_scanner.rb
+++ b/ext/psych/lib/psych/scalar_scanner.rb
@@ -63,7 +63,7 @@ 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
@@ -95,7 +95,7 @@ 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_regex)
parse_int string
@@ -107,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/versions.rb b/ext/psych/lib/psych/versions.rb
index 3cfd59e751..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.3'
+ 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/to_ruby.rb b/ext/psych/lib/psych/visitors/to_ruby.rb
index 935bc74f21..8614251ca9 100644
--- a/ext/psych/lib/psych/visitors/to_ruby.rb
+++ b/ext/psych/lib/psych/visitors/to_ruby.rb
@@ -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 316a3a9496..31858798e4 100644
--- a/ext/psych/lib/psych/visitors/yaml_tree.rb
+++ b/ext/psych/lib/psych/visitors/yaml_tree.rb
@@ -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?
@@ -482,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 65dd7156cb..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",
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 c43d3dcf9a..f251caae3f 100644
--- a/ext/pty/depend
+++ b/ext/pty/depend
@@ -181,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 cb663ab2de..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,42 +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(_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);
@@ -435,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);
}
}
@@ -519,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;
}
@@ -531,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;
@@ -539,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.
@@ -550,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.
*
@@ -597,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;
}
@@ -618,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);
@@ -657,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/readline/readline-ext.gemspec b/ext/readline/readline-ext.gemspec
index 177ee2152e..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.4"
+ 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 5ae037dd41..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) {
diff --git a/ext/ripper/depend b/ext/ripper/depend
index 80a6d62346..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
@@ -234,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
@@ -255,6 +253,7 @@ 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/lib/ripper/lexer.rb b/ext/ripper/lib/ripper/lexer.rb
index 19c59e2ccc..a0f1cbeaa8 100644
--- a/ext/ripper/lib/ripper/lexer.rb
+++ b/ext/ripper/lib/ripper/lexer.rb
@@ -228,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)
@@ -242,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 aa62cab0ec..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;
@@ -906,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));
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;
@@ -1136,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;
@@ -1160,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;
@@ -1215,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.
*
@@ -1242,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
}
@@ -1256,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);
@@ -1284,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);
@@ -1311,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
@@ -1422,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;
@@ -1443,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;
@@ -1505,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
@@ -1556,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
@@ -1579,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
@@ -1605,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)
@@ -1616,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);
@@ -1636,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);
@@ -1679,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);
@@ -1689,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 44fb7a4eb7..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);
@@ -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 ffe2fce844..28c5540cd6 100644
--- a/ext/socket/depend
+++ b/ext/socket/depend
@@ -197,6 +197,7 @@ 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
@@ -388,6 +389,7 @@ 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
@@ -579,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
@@ -771,6 +774,7 @@ 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
@@ -962,6 +966,7 @@ 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
@@ -1153,6 +1158,7 @@ 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
@@ -1344,6 +1350,7 @@ 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
@@ -1535,6 +1542,7 @@ 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
@@ -1726,6 +1734,7 @@ 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
@@ -1917,6 +1926,7 @@ 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
@@ -2108,6 +2118,7 @@ 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
@@ -2299,6 +2310,7 @@ 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
@@ -2490,6 +2502,7 @@ 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
@@ -2681,6 +2694,7 @@ 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
@@ -2872,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 b70a862414..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
@@ -551,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
@@ -655,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?
@@ -670,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 1da259bd6f..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;
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 577958a358..5e6c0668f6 100644
--- a/ext/socket/mkconstants.rb
+++ b/ext/socket/mkconstants.rb
@@ -626,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
@@ -661,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
@@ -670,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 8772572d2e..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
@@ -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));
- }
+ }