From a1949df5474429641446c89ca9664c12a32868d2 Mon Sep 17 00:00:00 2001 From: S-H-GAMELINKS Date: Wed, 10 Jan 2024 12:13:19 +0900 Subject: [PATCH 001/640] Remove unnecessary semicolon and add break --- compile.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compile.c b/compile.c index ae78d9edc348dd..3822646c0e7666 100644 --- a/compile.c +++ b/compile.c @@ -1946,7 +1946,8 @@ iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, dv = rb_node_sym_string_val(val_node); break; case NODE_LINE: - dv = rb_node_line_lineno_val(val_node);; + dv = rb_node_line_lineno_val(val_node); + break; case NODE_INTEGER: dv = rb_node_integer_literal_val(val_node); break; From 8b65d15ff079ebcf7fa9f68a1163f76e87c47764 Mon Sep 17 00:00:00 2001 From: Hiroya Fujinami Date: Wed, 10 Jan 2024 13:40:20 +0900 Subject: [PATCH 002/640] Fix test case for `test_match_cache_with_peek_optimization` (#9466) --- test/ruby/test_regexp.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb index e04794263724bc..0d6ab4682d0631 100644 --- a/test/ruby/test_regexp.rb +++ b/test/ruby/test_regexp.rb @@ -1950,7 +1950,7 @@ def test_match_cache_with_peek_optimization timeout = #{ EnvUtil.apply_timeout_scale(10).inspect } begin; Regexp.timeout = timeout - assert_nil(/a*z/ =~ "a" * 1000000 + "x") + assert_nil(/a+z/ =~ "a" * 1000000 + "xz") end; end From 3ecfea60757e45aa3977f9a1151b590d02c0da5b Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 10 Jan 2024 13:41:54 +0900 Subject: [PATCH 003/640] Need newline after changes list --- tool/gen-github-release.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tool/gen-github-release.rb b/tool/gen-github-release.rb index 8276c438c7c615..fe0b459cb374a6 100755 --- a/tool/gen-github-release.rb +++ b/tool/gen-github-release.rb @@ -51,7 +51,7 @@ note << notes.join("\n") -note << "\n" +note << "\n\n" note << "Note: This list is automatically generated by tool/gen-github-release.rb. Because of this, some commits may be missing.\n\n" note << "## Full Changelog\n\n" note << "https://github.com/ruby/ruby/compare/#{ARGV[0]}...#{ARGV[1]}\n\n" From 48fd311721a3d6c56584bebafb48fa6c8e69eb5f Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 10 Jan 2024 13:49:00 +0900 Subject: [PATCH 004/640] Constify --- ruby_parser.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ruby_parser.c b/ruby_parser.c index 1721df841bc928..739bd3a86575d6 100644 --- a/ruby_parser.c +++ b/ruby_parser.c @@ -40,7 +40,7 @@ compile_negative_numeric(VALUE val) } static VALUE -compile_numeric_literal(char* val, int base) +compile_numeric_literal(const char *val, int base) { return rb_cstr_to_inum(val, base, FALSE); } @@ -48,7 +48,7 @@ compile_numeric_literal(char* val, int base) VALUE rb_node_integer_literal_val(const NODE *n) { - rb_node_integer_t *node = RNODE_INTEGER(n); + const rb_node_integer_t *node = RNODE_INTEGER(n); VALUE val = compile_numeric_literal(node->val, node->base); if (node->minus) { val = compile_negative_numeric(val); @@ -59,7 +59,7 @@ rb_node_integer_literal_val(const NODE *n) VALUE rb_node_float_literal_val(const NODE *n) { - rb_node_float_t *node = RNODE_FLOAT(n); + const rb_node_float_t *node = RNODE_FLOAT(n); double d = strtod(node->val, 0); if (node->minus) { d = -d; @@ -69,7 +69,7 @@ rb_node_float_literal_val(const NODE *n) } static VALUE -compile_rational_literal(char* node_val, int base, int seen_point) +compile_rational_literal(const char *node_val, int base, int seen_point) { VALUE lit; char* val = strdup(node_val); @@ -94,7 +94,7 @@ VALUE rb_node_rational_literal_val(const NODE *n) { VALUE lit; - rb_node_rational_t *node = RNODE_RATIONAL(n); + const rb_node_rational_t *node = RNODE_RATIONAL(n); lit = compile_rational_literal(node->val, node->base, node->seen_point); @@ -109,7 +109,7 @@ VALUE rb_node_imaginary_literal_val(const NODE *n) { VALUE lit; - rb_node_imaginary_t *node = RNODE_IMAGINARY(n); + const rb_node_imaginary_t *node = RNODE_IMAGINARY(n); enum rb_numeric_type type = node->type; From e59a7304779c6a51a89ff39695743a470f086c4e Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 8 Jan 2024 21:53:33 +0900 Subject: [PATCH 005/640] `st_index_t` is not `VALUE` --- parse.y | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/parse.y b/parse.y index 8a1bda1b0ca8cf..a3a4346f5b4b43 100644 --- a/parse.y +++ b/parse.y @@ -213,7 +213,8 @@ node_cdhash_hash(VALUE a) switch (type) { case NODE_INTEGER: val = rb_node_integer_literal_val(node); - return (FIXNUM_P(val) ? val : FIX2LONG(rb_big_hash(val))); + if (!FIXNUM_P(val)) val = rb_big_hash(val); + return FIX2LONG(val); case NODE_FLOAT: val = rb_node_float_literal_val(node); return rb_dbl_long_hash(RFLOAT_VALUE(val)); @@ -227,7 +228,7 @@ node_cdhash_hash(VALUE a) return rb_node_sym_string_val(node); case NODE_LINE: /* Same with NODE_INTEGER FIXNUM case */ - return INT2FIX(node->nd_loc.beg_pos.lineno); + return (st_index_t)node->nd_loc.beg_pos.lineno; case NODE_FILE: /* Same with String in rb_iseq_cdhash_hash */ return rb_str_hash(rb_node_file_path_val(node)); From d16f992e1bfacb638b8a9b8b5a7ef8149ee1d50d Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 9 Jan 2024 16:33:30 +0900 Subject: [PATCH 006/640] Extract mutex_m as bundled gems --- doc/maintainers.md | 8 +-- doc/standard_library.rdoc | 2 +- lib/mutex_m.gemspec | 28 --------- lib/mutex_m.rb | 116 -------------------------------------- test/test_mutex_m.rb | 79 -------------------------- 5 files changed, 4 insertions(+), 229 deletions(-) delete mode 100644 lib/mutex_m.gemspec delete mode 100644 lib/mutex_m.rb delete mode 100644 test/test_mutex_m.rb diff --git a/doc/maintainers.md b/doc/maintainers.md index 631371e178399f..e8790342096f21 100644 --- a/doc/maintainers.md +++ b/doc/maintainers.md @@ -181,11 +181,6 @@ have commit right, others don't. * https://github.com/ruby/logger * https://rubygems.org/gems/logger -#### lib/mutex_m.rb -* Keiju ISHITSUKA (keiju) -* https://github.com/ruby/mutex_m -* https://rubygems.org/gems/mutex_m - #### lib/net/http.rb, lib/net/https.rb * NARUSE, Yui (naruse) * https://github.com/ruby/net-http @@ -487,6 +482,9 @@ have commit right, others don't. ### racc * https://github.com/ruby/racc +#### mutex_m +* https://github.com/ruby/mutex_m + ## Platform Maintainers ### mswin64 (Microsoft Windows) diff --git a/doc/standard_library.rdoc b/doc/standard_library.rdoc index 2282d7226bb93a..d0a7ba42077036 100644 --- a/doc/standard_library.rdoc +++ b/doc/standard_library.rdoc @@ -53,7 +53,6 @@ IPAddr:: Provides methods to manipulate IPv4 and IPv6 IP addresses IRB:: Interactive Ruby command-line tool for REPL (Read Eval Print Loop) OptionParser:: Ruby-oriented class for command-line option analysis Logger:: Provides a simple logging utility for outputting messages -Mutex_m:: Mixin to extend objects to be handled like a Mutex Net::HTTP:: HTTP client api for Ruby Observable:: Provides a mechanism for publish/subscribe pattern in Ruby Open3:: Provides access to stdin, stdout and stderr when running other programs @@ -130,3 +129,4 @@ RBS:: RBS is a language to describe the structure of Ruby programs TypeProf:: A type analysis tool for Ruby code based on abstract interpretation DEBUGGER__:: Debugging functionality for Ruby Racc:: A LALR(1) parser generator written in Ruby. +Mutex_m:: Mixin to extend objects to be handled like a Mutex diff --git a/lib/mutex_m.gemspec b/lib/mutex_m.gemspec deleted file mode 100644 index ebbda2606c9fb5..00000000000000 --- a/lib/mutex_m.gemspec +++ /dev/null @@ -1,28 +0,0 @@ -begin - require_relative "lib/mutex_m" -rescue LoadError - # for Ruby core repository - require_relative "mutex_m" -end - -Gem::Specification.new do |spec| - spec.name = "mutex_m" - spec.version = Mutex_m::VERSION - spec.authors = ["Keiju ISHITSUKA"] - spec.email = ["keiju@ruby-lang.org"] - - spec.summary = %q{Mixin to extend objects to be handled like a Mutex.} - spec.description = %q{Mixin to extend objects to be handled like a Mutex.} - spec.homepage = "https://github.com/ruby/mutex_m" - spec.licenses = ["Ruby", "BSD-2-Clause"] - - spec.files = ["Gemfile", "LICENSE.txt", "README.md", "Rakefile", "lib/mutex_m.rb", "mutex_m.gemspec"] - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } - spec.require_paths = ["lib"] - spec.required_ruby_version = '>= 2.5' - - spec.add_development_dependency "bundler" - spec.add_development_dependency "rake" - spec.add_development_dependency "test-unit" -end diff --git a/lib/mutex_m.rb b/lib/mutex_m.rb deleted file mode 100644 index 7e55181881ab8a..00000000000000 --- a/lib/mutex_m.rb +++ /dev/null @@ -1,116 +0,0 @@ -# frozen_string_literal: false -# -# mutex_m.rb - -# $Release Version: 3.0$ -# $Revision: 1.7 $ -# Original from mutex.rb -# by Keiju ISHITSUKA(keiju@ishitsuka.com) -# modified by matz -# patched by akira yamada -# -# -- - -# = mutex_m.rb -# -# When 'mutex_m' is required, any object that extends or includes Mutex_m will -# be treated like a Mutex. -# -# Start by requiring the standard library Mutex_m: -# -# require "mutex_m.rb" -# -# From here you can extend an object with Mutex instance methods: -# -# obj = Object.new -# obj.extend Mutex_m -# -# Or mixin Mutex_m into your module to your class inherit Mutex instance -# methods --- remember to call super() in your class initialize method. -# -# class Foo -# include Mutex_m -# def initialize -# # ... -# super() -# end -# # ... -# end -# obj = Foo.new -# # this obj can be handled like Mutex -# -module Mutex_m - - VERSION = "0.2.0" - Ractor.make_shareable(VERSION) if defined?(Ractor) - - def Mutex_m.define_aliases(cl) # :nodoc: - cl.alias_method(:locked?, :mu_locked?) - cl.alias_method(:lock, :mu_lock) - cl.alias_method(:unlock, :mu_unlock) - cl.alias_method(:try_lock, :mu_try_lock) - cl.alias_method(:synchronize, :mu_synchronize) - end - - def Mutex_m.append_features(cl) # :nodoc: - super - define_aliases(cl) unless cl.instance_of?(Module) - end - - def Mutex_m.extend_object(obj) # :nodoc: - super - obj.mu_extended - end - - def mu_extended # :nodoc: - unless (defined? locked? and - defined? lock and - defined? unlock and - defined? try_lock and - defined? synchronize) - Mutex_m.define_aliases(singleton_class) - end - mu_initialize - end - - # See Thread::Mutex#synchronize - def mu_synchronize(&block) - @_mutex.synchronize(&block) - end - - # See Thread::Mutex#locked? - def mu_locked? - @_mutex.locked? - end - - # See Thread::Mutex#try_lock - def mu_try_lock - @_mutex.try_lock - end - - # See Thread::Mutex#lock - def mu_lock - @_mutex.lock - end - - # See Thread::Mutex#unlock - def mu_unlock - @_mutex.unlock - end - - # See Thread::Mutex#sleep - def sleep(timeout = nil) - @_mutex.sleep(timeout) - end - - private - - def mu_initialize # :nodoc: - @_mutex = Thread::Mutex.new - end - - def initialize(*args) # :nodoc: - mu_initialize - super - end - ruby2_keywords(:initialize) if respond_to?(:ruby2_keywords, true) -end diff --git a/test/test_mutex_m.rb b/test/test_mutex_m.rb deleted file mode 100644 index f938e7172993af..00000000000000 --- a/test/test_mutex_m.rb +++ /dev/null @@ -1,79 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' -require 'mutex_m' - -class TestMutexM < Test::Unit::TestCase - def test_cv_wait - o = Object.new - o.instance_variable_set(:@foo, nil) - o.extend(Mutex_m) - c = Thread::ConditionVariable.new - t = Thread.start { - o.synchronize do - until foo = o.instance_variable_get(:@foo) - c.wait(o) - end - foo - end - } - sleep(0.0001) - o.synchronize do - o.instance_variable_set(:@foo, "abc") - end - c.signal - assert_equal "abc", t.value - end - - class KeywordInitializeParent - def initialize(x:) - end - end - - class KeywordInitializeChild < KeywordInitializeParent - include Mutex_m - def initialize - super(x: 1) - end - end - - def test_initialize_with_keyword_arg - assert KeywordInitializeChild.new - end - - class NoArgInitializeParent - def initialize - end - end - - class NoArgInitializeChild < NoArgInitializeParent - include Mutex_m - def initialize - super() - end - end - - def test_initialize_no_args - assert NoArgInitializeChild.new - end - - def test_alias_extended_object - object = Object.new - object.extend(Mutex_m) - - assert object.respond_to?(:locked?) - assert object.respond_to?(:lock) - assert object.respond_to?(:unlock) - assert object.respond_to?(:try_lock) - assert object.respond_to?(:synchronize) - end - - def test_alias_included_class - object = NoArgInitializeChild.new - - assert object.respond_to?(:locked?) - assert object.respond_to?(:lock) - assert object.respond_to?(:unlock) - assert object.respond_to?(:try_lock) - assert object.respond_to?(:synchronize) - end -end From 1500946ce4ed7d89ed33059e3629e526b1dc207a Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 10 Jan 2024 16:15:21 +0900 Subject: [PATCH 007/640] Added mutex_m to bundled gems --- gems/bundled_gems | 1 + 1 file changed, 1 insertion(+) diff --git a/gems/bundled_gems b/gems/bundled_gems index 470cf8ffe97bf4..caa0469c54e138 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -21,3 +21,4 @@ rbs 3.4.1 https://github.com/ruby/rbs typeprof 0.21.9 https://github.com/ruby/typeprof debug 1.9.1 https://github.com/ruby/debug racc 1.7.3 https://github.com/ruby/racc +mutex_m 0.2.0 https://github.com/ruby/mutex_m From c4051d5f4324536a932e99cbe43f5b7dbe34254a Mon Sep 17 00:00:00 2001 From: git Date: Wed, 10 Jan 2024 08:28:55 +0000 Subject: [PATCH 008/640] Update bundled gems list at 1500946ce4ed7d89ed33059e3629e5 [ci skip] --- NEWS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS.md b/NEWS.md index bd7886a107d6db..4caa78d8216fa4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -37,6 +37,10 @@ The following bundled gems are updated. * typeprof 0.21.9 * debug 1.9.1 +The following bundled gem is promoted from default gems. + +* mutex_m 0.2.0 + See GitHub releases like [GitHub Releases of Logger](https://github.com/ruby/logger/releases) or changelog for details of the default gems or bundled gems. ## Supported platforms From 31371b2e24b03ccb0a03b622faf8c65e6cf6a31a Mon Sep 17 00:00:00 2001 From: KJ Tsanaktsidis Date: Thu, 28 Dec 2023 16:08:54 +1100 Subject: [PATCH 009/640] Fix CRLF -> LF conversion on read for rb_io_fdopen & rb_file_open When opening a file with `File.open`, and then setting the encoding with `IO#set_encoding`, it still correctly performs CRLF -> LF conversion on Windows when reading files with a CRLF line ending in them (in text mode). However, the file is opened instead with either the `rb_io_fdopen` or `rb_file_open` APIs from C, the CRLF conversion is _NOT_ set up correctly; it works if the encoding is not specified, but if `IO#set_encoding` is called, the conversion stops happening. This seems to be because the encflags never get ECONV_DEFAULT_NEWLINE_DECORATOR set in these codepaths. Concretely, this means that the conversion doesn't happen in the following circumstances: * When loading ruby files with require (that calls rb_io_fdopen) * When parsing ruuby files with RubyVM::AbstractSyntaxTree (that calls rb_file_open). This then causes the ErrorHighlight tests to fail on windows if git has checked them out with CRLF line endings - the error messages it's testing wind up with literal \r\n sequences in them because the iseq text from the parser contains un-newline-converted strings. This commit fixes the problem by copy-pasting the relevant snippet which sets this up in `rb_io_extract_modeenc` (for the File.open path) into the relevant codepaths for `rb_io_fdopen` and `rb_file_open`. [Bug #20101] --- ext/-test-/file/depend | 171 +++++++++++++++++++++++ ext/-test-/file/newline_conv.c | 73 ++++++++++ io.c | 33 ++++- test/ruby/test_file.rb | 246 +++++++++++++++++++++++++++++++++ 4 files changed, 518 insertions(+), 5 deletions(-) create mode 100644 ext/-test-/file/newline_conv.c diff --git a/ext/-test-/file/depend b/ext/-test-/file/depend index 662136f1ba069b..2c8a04e4331e1d 100644 --- a/ext/-test-/file/depend +++ b/ext/-test-/file/depend @@ -329,6 +329,177 @@ init.o: $(hdrdir)/ruby/ruby.h init.o: $(hdrdir)/ruby/st.h init.o: $(hdrdir)/ruby/subst.h init.o: init.c +newline_conv.o: $(RUBY_EXTCONF_H) +newline_conv.o: $(arch_hdrdir)/ruby/config.h +newline_conv.o: $(hdrdir)/ruby/assert.h +newline_conv.o: $(hdrdir)/ruby/backward.h +newline_conv.o: $(hdrdir)/ruby/backward/2/assume.h +newline_conv.o: $(hdrdir)/ruby/backward/2/attributes.h +newline_conv.o: $(hdrdir)/ruby/backward/2/bool.h +newline_conv.o: $(hdrdir)/ruby/backward/2/inttypes.h +newline_conv.o: $(hdrdir)/ruby/backward/2/limits.h +newline_conv.o: $(hdrdir)/ruby/backward/2/long_long.h +newline_conv.o: $(hdrdir)/ruby/backward/2/stdalign.h +newline_conv.o: $(hdrdir)/ruby/backward/2/stdarg.h +newline_conv.o: $(hdrdir)/ruby/defines.h +newline_conv.o: $(hdrdir)/ruby/encoding.h +newline_conv.o: $(hdrdir)/ruby/intern.h +newline_conv.o: $(hdrdir)/ruby/internal/abi.h +newline_conv.o: $(hdrdir)/ruby/internal/anyargs.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/char.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/double.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/int.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/long.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/short.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +newline_conv.o: $(hdrdir)/ruby/internal/assume.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/artificial.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/cold.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/const.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/constexpr.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/deprecated.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/error.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/forceinline.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/format.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/noalias.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/noexcept.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/noinline.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/nonnull.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/noreturn.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/pure.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/restrict.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/warning.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/weakref.h +newline_conv.o: $(hdrdir)/ruby/internal/cast.h +newline_conv.o: $(hdrdir)/ruby/internal/compiler_is.h +newline_conv.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +newline_conv.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +newline_conv.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +newline_conv.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +newline_conv.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +newline_conv.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +newline_conv.o: $(hdrdir)/ruby/internal/compiler_since.h +newline_conv.o: $(hdrdir)/ruby/internal/config.h +newline_conv.o: $(hdrdir)/ruby/internal/constant_p.h +newline_conv.o: $(hdrdir)/ruby/internal/core.h +newline_conv.o: $(hdrdir)/ruby/internal/core/rarray.h +newline_conv.o: $(hdrdir)/ruby/internal/core/rbasic.h +newline_conv.o: $(hdrdir)/ruby/internal/core/rbignum.h +newline_conv.o: $(hdrdir)/ruby/internal/core/rclass.h +newline_conv.o: $(hdrdir)/ruby/internal/core/rdata.h +newline_conv.o: $(hdrdir)/ruby/internal/core/rfile.h +newline_conv.o: $(hdrdir)/ruby/internal/core/rhash.h +newline_conv.o: $(hdrdir)/ruby/internal/core/robject.h +newline_conv.o: $(hdrdir)/ruby/internal/core/rregexp.h +newline_conv.o: $(hdrdir)/ruby/internal/core/rstring.h +newline_conv.o: $(hdrdir)/ruby/internal/core/rstruct.h +newline_conv.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +newline_conv.o: $(hdrdir)/ruby/internal/ctype.h +newline_conv.o: $(hdrdir)/ruby/internal/dllexport.h +newline_conv.o: $(hdrdir)/ruby/internal/dosish.h +newline_conv.o: $(hdrdir)/ruby/internal/encoding/coderange.h +newline_conv.o: $(hdrdir)/ruby/internal/encoding/ctype.h +newline_conv.o: $(hdrdir)/ruby/internal/encoding/encoding.h +newline_conv.o: $(hdrdir)/ruby/internal/encoding/pathname.h +newline_conv.o: $(hdrdir)/ruby/internal/encoding/re.h +newline_conv.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +newline_conv.o: $(hdrdir)/ruby/internal/encoding/string.h +newline_conv.o: $(hdrdir)/ruby/internal/encoding/symbol.h +newline_conv.o: $(hdrdir)/ruby/internal/encoding/transcode.h +newline_conv.o: $(hdrdir)/ruby/internal/error.h +newline_conv.o: $(hdrdir)/ruby/internal/eval.h +newline_conv.o: $(hdrdir)/ruby/internal/event.h +newline_conv.o: $(hdrdir)/ruby/internal/fl_type.h +newline_conv.o: $(hdrdir)/ruby/internal/gc.h +newline_conv.o: $(hdrdir)/ruby/internal/glob.h +newline_conv.o: $(hdrdir)/ruby/internal/globals.h +newline_conv.o: $(hdrdir)/ruby/internal/has/attribute.h +newline_conv.o: $(hdrdir)/ruby/internal/has/builtin.h +newline_conv.o: $(hdrdir)/ruby/internal/has/c_attribute.h +newline_conv.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +newline_conv.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +newline_conv.o: $(hdrdir)/ruby/internal/has/extension.h +newline_conv.o: $(hdrdir)/ruby/internal/has/feature.h +newline_conv.o: $(hdrdir)/ruby/internal/has/warning.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/array.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/bignum.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/class.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/compar.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/complex.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/cont.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/dir.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/enum.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/enumerator.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/error.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/eval.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/file.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/hash.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/io.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/load.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/marshal.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/numeric.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/object.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/parse.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/proc.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/process.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/random.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/range.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/rational.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/re.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/ruby.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/select.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/signal.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/sprintf.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/string.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/struct.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/thread.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/time.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/variable.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/vm.h +newline_conv.o: $(hdrdir)/ruby/internal/interpreter.h +newline_conv.o: $(hdrdir)/ruby/internal/iterator.h +newline_conv.o: $(hdrdir)/ruby/internal/memory.h +newline_conv.o: $(hdrdir)/ruby/internal/method.h +newline_conv.o: $(hdrdir)/ruby/internal/module.h +newline_conv.o: $(hdrdir)/ruby/internal/newobj.h +newline_conv.o: $(hdrdir)/ruby/internal/scan_args.h +newline_conv.o: $(hdrdir)/ruby/internal/special_consts.h +newline_conv.o: $(hdrdir)/ruby/internal/static_assert.h +newline_conv.o: $(hdrdir)/ruby/internal/stdalign.h +newline_conv.o: $(hdrdir)/ruby/internal/stdbool.h +newline_conv.o: $(hdrdir)/ruby/internal/symbol.h +newline_conv.o: $(hdrdir)/ruby/internal/value.h +newline_conv.o: $(hdrdir)/ruby/internal/value_type.h +newline_conv.o: $(hdrdir)/ruby/internal/variable.h +newline_conv.o: $(hdrdir)/ruby/internal/warning_push.h +newline_conv.o: $(hdrdir)/ruby/internal/xmalloc.h +newline_conv.o: $(hdrdir)/ruby/io.h +newline_conv.o: $(hdrdir)/ruby/missing.h +newline_conv.o: $(hdrdir)/ruby/onigmo.h +newline_conv.o: $(hdrdir)/ruby/oniguruma.h +newline_conv.o: $(hdrdir)/ruby/ruby.h +newline_conv.o: $(hdrdir)/ruby/st.h +newline_conv.o: $(hdrdir)/ruby/subst.h +newline_conv.o: newline_conv.c stat.o: $(RUBY_EXTCONF_H) stat.o: $(arch_hdrdir)/ruby/config.h stat.o: $(hdrdir)/ruby/assert.h diff --git a/ext/-test-/file/newline_conv.c b/ext/-test-/file/newline_conv.c new file mode 100644 index 00000000000000..2ac5aef801ef7f --- /dev/null +++ b/ext/-test-/file/newline_conv.c @@ -0,0 +1,73 @@ +#include "ruby/ruby.h" +#include "ruby/io.h" +#include + +static VALUE +open_with_rb_file_open(VALUE self, VALUE filename, VALUE read_or_write, VALUE binary_or_text) +{ + char fmode[3] = { 0 }; + if (rb_sym2id(read_or_write) == rb_intern("read")) { + fmode[0] = 'r'; + } + else if (rb_sym2id(read_or_write) == rb_intern("write")) { + fmode[0] = 'w'; + } + else { + rb_raise(rb_eArgError, "read_or_write param must be :read or :write"); + } + + if (rb_sym2id(binary_or_text) == rb_intern("binary")) { + fmode[1] = 'b'; + } + else if (rb_sym2id(binary_or_text) == rb_intern("text")) { + + } + else { + rb_raise(rb_eArgError, "binary_or_text param must be :binary or :text"); + } + + return rb_file_open(StringValueCStr(filename), fmode); +} + +static VALUE +open_with_rb_io_fdopen(VALUE self, VALUE filename, VALUE read_or_write, VALUE binary_or_text) +{ + int omode = 0; + if (rb_sym2id(read_or_write) == rb_intern("read")) { + omode |= O_RDONLY; + } + else if (rb_sym2id(read_or_write) == rb_intern("write")) { + omode |= O_WRONLY; + } + else { + rb_raise(rb_eArgError, "read_or_write param must be :read or :write"); + } + + if (rb_sym2id(binary_or_text) == rb_intern("binary")) { +#ifdef O_BINARY + omode |= O_BINARY; +#endif + } + else if (rb_sym2id(binary_or_text) == rb_intern("text")) { + + } + else { + rb_raise(rb_eArgError, "binary_or_text param must be :binary or :text"); + } + + int fd = rb_cloexec_open(StringValueCStr(filename), omode, 0); + if (fd < 0) { + rb_raise(rb_eIOError, "failed to open the file"); + } + + rb_update_max_fd(fd); + return rb_io_fdopen(fd, omode, StringValueCStr(filename)); +} + +void +Init_newline_conv(VALUE module) +{ + VALUE newline_conv = rb_define_module_under(module, "NewlineConv"); + rb_define_module_function(newline_conv, "rb_file_open", open_with_rb_file_open, 3); + rb_define_module_function(newline_conv, "rb_io_fdopen", open_with_rb_io_fdopen, 3); +} diff --git a/io.c b/io.c index f6cd2c1a56aa31..90bf24507187e5 100644 --- a/io.c +++ b/io.c @@ -7166,8 +7166,6 @@ rb_file_open_internal(VALUE io, VALUE filename, const char *modestr) if (p) { parse_mode_enc(p+1, rb_usascii_encoding(), &convconfig.enc, &convconfig.enc2, &fmode); - convconfig.ecflags = 0; - convconfig.ecopts = Qnil; } else { rb_encoding *e; @@ -7175,10 +7173,19 @@ rb_file_open_internal(VALUE io, VALUE filename, const char *modestr) e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL; rb_io_ext_int_to_encs(e, NULL, &convconfig.enc, &convconfig.enc2, fmode); - convconfig.ecflags = 0; - convconfig.ecopts = Qnil; } + convconfig.ecflags = (fmode & FMODE_READABLE) ? + MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR, + 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR) : 0; +#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE + convconfig.ecflags |= (fmode & FMODE_WRITABLE) ? + MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE, + 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0; +#endif + SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(convconfig.enc2, convconfig.ecflags); + convconfig.ecopts = Qnil; + return rb_file_open_generic(io, filename, rb_io_fmode_oflags(fmode), fmode, @@ -9241,11 +9248,27 @@ static VALUE prep_io(int fd, int fmode, VALUE klass, const char *path) { VALUE path_value = Qnil; + rb_encoding *e; + struct rb_io_encoding convconfig; + if (path) { path_value = rb_obj_freeze(rb_str_new_cstr(path)); } - VALUE self = rb_io_open_descriptor(klass, fd, fmode, path_value, Qnil, NULL); + e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL; + rb_io_ext_int_to_encs(e, NULL, &convconfig.enc, &convconfig.enc2, fmode); + convconfig.ecflags = (fmode & FMODE_READABLE) ? + MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR, + 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR) : 0; +#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE + convconfig.ecflags |= (fmode & FMODE_WRITABLE) ? + MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE, + 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0; +#endif + SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(convconfig.enc2, convconfig.ecflags); + convconfig.ecopts = Qnil; + + VALUE self = rb_io_open_descriptor(klass, fd, fmode, path_value, Qnil, &convconfig); rb_io_t*io = RFILE(self)->fptr; if (!io_check_tty(io)) { diff --git a/test/ruby/test_file.rb b/test/ruby/test_file.rb index 409d21fc4e3a09..aa10566bfa73a1 100644 --- a/test/ruby/test_file.rb +++ b/test/ruby/test_file.rb @@ -554,4 +554,250 @@ def test_absolute_path? assert_file.absolute_path?("/foo/bar\\baz") end end + + class NewlineConvTests < Test::Unit::TestCase + TEST_STRING_WITH_CRLF = "line1\r\nline2\r\n".freeze + TEST_STRING_WITH_LF = "line1\nline2\n".freeze + + def setup + @tmpdir = Dir.mktmpdir(self.class.name) + @read_path_with_crlf = File.join(@tmpdir, "read_path_with_crlf") + File.binwrite(@read_path_with_crlf, TEST_STRING_WITH_CRLF) + @read_path_with_lf = File.join(@tmpdir, "read_path_with_lf") + File.binwrite(@read_path_with_lf, TEST_STRING_WITH_LF) + @write_path = File.join(@tmpdir, "write_path") + File.binwrite(@write_path, '') + end + + def teardown + FileUtils.rm_rf @tmpdir + end + + def windows? + /cygwin|mswin|mingw/ =~ RUBY_PLATFORM + end + + def open_file_with(method, filename, mode) + read_or_write = mode.include?('w') ? :write : :read + binary_or_text = mode.include?('b') ? :binary : :text + + f = case method + when :ruby_file_open + File.open(filename, mode) + when :c_rb_file_open + Bug::File::NewlineConv.rb_file_open(filename, read_or_write, binary_or_text) + when :c_rb_io_fdopen + Bug::File::NewlineConv.rb_io_fdopen(filename, read_or_write, binary_or_text) + else + raise "Don't know how to open with #{method}" + end + + begin + yield f + ensure + f.close + end + end + + def assert_file_contents_has_lf(f) + assert_equal TEST_STRING_WITH_LF, f.read + end + + def assert_file_contents_has_crlf(f) + assert_equal TEST_STRING_WITH_CRLF, f.read + end + + def assert_file_contents_has_lf_on_windows(f) + if windows? + assert_file_contents_has_lf(f) + else + assert_file_contents_has_crlf(f) + end + end + + def assert_file_contents_has_crlf_on_windows(f) + if windows? + assert_file_contents_has_crlf(f) + else + assert_file_contents_has_lf(f) + end + end + + def test_ruby_file_open_text_mode_read_crlf + open_file_with(:ruby_file_open, @read_path_with_crlf, 'r') { |f| assert_file_contents_has_lf_on_windows(f) } + end + + def test_ruby_file_open_bin_mode_read_crlf + open_file_with(:ruby_file_open, @read_path_with_crlf, 'rb') { |f| assert_file_contents_has_crlf(f) } + end + + def test_ruby_file_open_text_mode_read_lf + open_file_with(:ruby_file_open, @read_path_with_lf, 'r') { |f| assert_file_contents_has_lf(f) } + end + + def test_ruby_file_open_bin_mode_read_lf + open_file_with(:ruby_file_open, @read_path_with_lf, 'rb') { |f| assert_file_contents_has_lf(f) } + end + + def test_ruby_file_open_text_mode_read_crlf_with_utf8_encoding + open_file_with(:ruby_file_open, @read_path_with_crlf, 'r') do |f| + f.set_encoding Encoding::UTF_8, '-' + assert_file_contents_has_lf_on_windows(f) + end + end + + def test_ruby_file_open_bin_mode_read_crlf_with_utf8_encoding + open_file_with(:ruby_file_open, @read_path_with_crlf, 'rb') do |f| + f.set_encoding Encoding::UTF_8, '-' + assert_file_contents_has_crlf(f) + end + end + + def test_ruby_file_open_text_mode_read_lf_with_utf8_encoding + open_file_with(:ruby_file_open, @read_path_with_lf, 'r') do |f| + f.set_encoding Encoding::UTF_8, '-' + assert_file_contents_has_lf(f) + end + end + + def test_ruby_file_open_bin_mode_read_lf_with_utf8_encoding + open_file_with(:ruby_file_open, @read_path_with_lf, 'rb') do |f| + f.set_encoding Encoding::UTF_8, '-' + assert_file_contents_has_lf(f) + end + end + + def test_ruby_file_open_text_mode_write_lf + open_file_with(:ruby_file_open, @write_path, 'w') { |f| f.write TEST_STRING_WITH_LF } + File.open(@write_path, 'rb') { |f| assert_file_contents_has_crlf_on_windows(f) } + end + + def test_ruby_file_open_bin_mode_write_lf + open_file_with(:ruby_file_open, @write_path, 'wb') { |f| f.write TEST_STRING_WITH_LF } + File.open(@write_path, 'rb') { |f| assert_file_contents_has_lf(f) } + end + + def test_ruby_file_open_bin_mode_write_crlf + open_file_with(:ruby_file_open, @write_path, 'wb') { |f| f.write TEST_STRING_WITH_CRLF } + File.open(@write_path, 'rb') { |f| assert_file_contents_has_crlf(f) } + end + + def test_c_rb_file_open_text_mode_read_crlf + open_file_with(:c_rb_file_open, @read_path_with_crlf, 'r') { |f| assert_file_contents_has_lf_on_windows(f) } + end + + def test_c_rb_file_open_bin_mode_read_crlf + open_file_with(:c_rb_file_open, @read_path_with_crlf, 'rb') { |f| assert_file_contents_has_crlf(f) } + end + + def test_c_rb_file_open_text_mode_read_lf + open_file_with(:c_rb_file_open, @read_path_with_lf, 'r') { |f| assert_file_contents_has_lf(f) } + end + + def test_c_rb_file_open_bin_mode_read_lf + open_file_with(:c_rb_file_open, @read_path_with_lf, 'rb') { |f| assert_file_contents_has_lf(f) } + end + + def test_c_rb_file_open_text_mode_write_lf + open_file_with(:c_rb_file_open, @write_path, 'w') { |f| f.write TEST_STRING_WITH_LF } + File.open(@write_path, 'rb') { |f| assert_file_contents_has_crlf_on_windows(f) } + end + + def test_c_rb_file_open_bin_mode_write_lf + open_file_with(:c_rb_file_open, @write_path, 'wb') { |f| f.write TEST_STRING_WITH_LF } + File.open(@write_path, 'rb') { |f| assert_file_contents_has_lf(f) } + end + + def test_c_rb_file_open_bin_mode_write_crlf + open_file_with(:c_rb_file_open, @write_path, 'wb') { |f| f.write TEST_STRING_WITH_CRLF } + File.open(@write_path, 'rb') { |f| assert_file_contents_has_crlf(f) } + end + + def test_c_rb_file_open_text_mode_read_crlf_with_utf8_encoding + open_file_with(:c_rb_file_open, @read_path_with_crlf, 'r') do |f| + f.set_encoding Encoding::UTF_8, '-' + assert_file_contents_has_lf_on_windows(f) + end + end + + def test_c_rb_file_open_bin_mode_read_crlf_with_utf8_encoding + open_file_with(:c_rb_file_open, @read_path_with_crlf, 'rb') do |f| + f.set_encoding Encoding::UTF_8, '-' + assert_file_contents_has_crlf(f) + end + end + + def test_c_rb_file_open_text_mode_read_lf_with_utf8_encoding + open_file_with(:c_rb_file_open, @read_path_with_lf, 'r') do |f| + f.set_encoding Encoding::UTF_8, '-' + assert_file_contents_has_lf(f) + end + end + + def test_c_rb_file_open_bin_mode_read_lf_with_utf8_encoding + open_file_with(:c_rb_file_open, @read_path_with_lf, 'rb') do |f| + f.set_encoding Encoding::UTF_8, '-' + assert_file_contents_has_lf(f) + end + end + + def test_c_rb_io_fdopen_text_mode_read_crlf + open_file_with(:c_rb_io_fdopen, @read_path_with_crlf, 'r') { |f| assert_file_contents_has_lf_on_windows(f) } + end + + def test_c_rb_io_fdopen_bin_mode_read_crlf + open_file_with(:c_rb_io_fdopen, @read_path_with_crlf, 'rb') { |f| assert_file_contents_has_crlf(f) } + end + + def test_c_rb_io_fdopen_text_mode_read_lf + open_file_with(:c_rb_io_fdopen, @read_path_with_lf, 'r') { |f| assert_file_contents_has_lf(f) } + end + + def test_c_rb_io_fdopen_bin_mode_read_lf + open_file_with(:c_rb_io_fdopen, @read_path_with_lf, 'rb') { |f| assert_file_contents_has_lf(f) } + end + + def test_c_rb_io_fdopen_text_mode_write_lf + open_file_with(:c_rb_io_fdopen, @write_path, 'w') { |f| f.write TEST_STRING_WITH_LF } + File.open(@write_path, 'rb') { |f| assert_file_contents_has_crlf_on_windows(f) } + end + + def test_c_rb_io_fdopen_bin_mode_write_lf + open_file_with(:c_rb_io_fdopen, @write_path, 'wb') { |f| f.write TEST_STRING_WITH_LF } + File.open(@write_path, 'rb') { |f| assert_file_contents_has_lf(f) } + end + + def test_c_rb_io_fdopen_bin_mode_write_crlf + open_file_with(:c_rb_io_fdopen, @write_path, 'wb') { |f| f.write TEST_STRING_WITH_CRLF } + File.open(@write_path, 'rb') { |f| assert_file_contents_has_crlf(f) } + end + + def test_c_rb_io_fdopen_text_mode_read_crlf_with_utf8_encoding + open_file_with(:c_rb_io_fdopen, @read_path_with_crlf, 'r') do |f| + f.set_encoding Encoding::UTF_8, '-' + assert_file_contents_has_lf_on_windows(f) + end + end + + def test_c_rb_io_fdopen_bin_mode_read_crlf_with_utf8_encoding + open_file_with(:c_rb_io_fdopen, @read_path_with_crlf, 'rb') do |f| + f.set_encoding Encoding::UTF_8, '-' + assert_file_contents_has_crlf(f) + end + end + + def test_c_rb_io_fdopen_text_mode_read_lf_with_utf8_encoding + open_file_with(:c_rb_io_fdopen, @read_path_with_lf, 'r') do |f| + f.set_encoding Encoding::UTF_8, '-' + assert_file_contents_has_lf(f) + end + end + + def test_c_rb_io_fdopen_bin_mode_read_lf_with_utf8_encoding + open_file_with(:c_rb_io_fdopen, @read_path_with_lf, 'rb') do |f| + f.set_encoding Encoding::UTF_8, '-' + assert_file_contents_has_lf(f) + end + end + end end From 8940922d1889f885d4f26b4c815beb136a9a2095 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Sun, 7 Jan 2024 14:26:10 -0500 Subject: [PATCH 010/640] [DOC] Improve doc for GC.latest_compact_info --- gc.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/gc.c b/gc.c index 372274959e6d33..1150f1794dd1ef 100644 --- a/gc.c +++ b/gc.c @@ -11002,11 +11002,19 @@ gc_update_references(rb_objspace_t *objspace) * * Returns information about object moved in the most recent \GC compaction. * - * The returned hash has two keys :considered and :moved. The hash for - * :considered lists the number of objects that were considered for movement - * by the compactor, and the :moved hash lists the number of objects that - * were actually moved. Some objects can't be moved (maybe they were pinned) - * so these numbers can be used to calculate compaction efficiency. + * The returned +hash+ has the following keys: + * + * - +:considered+: a hash containing the type of the object as the key and + * the number of objects of that type that were considered for movement. + * - +:moved+: a hash containing the type of the object as the key and the + * number of objects of that type that were actually moved. + * - +:moved_up+: a hash containing the type of the object as the key and the + * number of objects of that type that were increased in size. + * - +:moved_down+: a hash containing the type of the object as the key and + * the number of objects of that type that were decreased in size. + * + * Some objects can't be moved (due to pinning) so these numbers can be used to + * calculate compaction efficiency. */ static VALUE gc_compact_stats(VALUE self) From 881c5a1846c220662a4ad49208a28fe0287b3c58 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 9 Jan 2024 10:12:03 -0800 Subject: [PATCH 011/640] [ruby/prism] Add a "repeated flag" to parameter nodes It's possible to repeat parameters in method definitions like so: ```ruby def foo(_a, _a) end ``` The compiler needs to know to adjust the local table size to account for these duplicate names. We'll use the repeated parameter flag to account for the extra stack space required https://github.com/ruby/prism/commit/b443cb1f60 Co-Authored-By: Kevin Newton Co-Authored-By: Jemma Issroff --- lib/prism/debug.rb | 12 +- prism/config.yml | 29 ++ prism/prism.c | 87 +++- test/prism/errors_test.rb | 64 +-- test/prism/fixtures/methods.txt | 3 - test/prism/fixtures/repeat_parameters.txt | 38 ++ test/prism/snapshots/arrays.txt | 9 + test/prism/snapshots/blocks.txt | 12 + test/prism/snapshots/break.txt | 1 + test/prism/snapshots/if.txt | 3 + test/prism/snapshots/keyword_method_names.txt | 1 + test/prism/snapshots/lambda.txt | 5 + test/prism/snapshots/method_calls.txt | 6 + test/prism/snapshots/methods.txt | 346 +++++++------ .../snapshots/non_alphanumeric_methods.txt | 2 + test/prism/snapshots/procs.txt | 28 + test/prism/snapshots/repeat_parameters.txt | 482 ++++++++++++++++++ test/prism/snapshots/rescue.txt | 1 + .../seattlerb/TestRubyParserShared.txt | 4 + .../snapshots/seattlerb/args_kw_block.txt | 2 + .../snapshots/seattlerb/block_arg__bare.txt | 1 + .../snapshots/seattlerb/block_arg_kwsplat.txt | 1 + .../seattlerb/block_arg_opt_arg_block.txt | 4 + .../seattlerb/block_arg_opt_splat.txt | 3 + .../block_arg_opt_splat_arg_block_omfg.txt | 5 + .../seattlerb/block_arg_optional.txt | 1 + .../snapshots/seattlerb/block_arg_scope.txt | 2 + .../snapshots/seattlerb/block_arg_scope2.txt | 3 + .../seattlerb/block_arg_splat_arg.txt | 3 + .../snapshots/seattlerb/block_args_kwargs.txt | 1 + .../snapshots/seattlerb/block_args_opt1.txt | 2 + .../snapshots/seattlerb/block_args_opt2.txt | 2 + .../snapshots/seattlerb/block_args_opt2_2.txt | 3 + .../snapshots/seattlerb/block_args_opt3.txt | 4 + .../prism/snapshots/seattlerb/block_break.txt | 1 + .../block_call_defn_call_block_call.txt | 1 + .../block_call_dot_op2_brace_block.txt | 1 + .../block_call_dot_op2_cmd_args_do_block.txt | 1 + .../seattlerb/block_decomp_anon_splat_arg.txt | 1 + .../seattlerb/block_decomp_arg_splat.txt | 1 + .../seattlerb/block_decomp_arg_splat_arg.txt | 3 + .../seattlerb/block_decomp_splat.txt | 1 + test/prism/snapshots/seattlerb/block_kw.txt | 1 + .../seattlerb/block_kw__required.txt | 1 + .../snapshots/seattlerb/block_kwarg_lvar.txt | 1 + .../seattlerb/block_kwarg_lvar_multiple.txt | 2 + test/prism/snapshots/seattlerb/block_next.txt | 1 + .../snapshots/seattlerb/block_opt_arg.txt | 2 + .../snapshots/seattlerb/block_opt_splat.txt | 2 + .../block_opt_splat_arg_block_omfg.txt | 4 + .../snapshots/seattlerb/block_optarg.txt | 1 + .../snapshots/seattlerb/block_paren_splat.txt | 2 + .../snapshots/seattlerb/block_reg_optarg.txt | 2 + .../snapshots/seattlerb/block_return.txt | 1 + .../prism/snapshots/seattlerb/block_scope.txt | 1 + .../snapshots/seattlerb/block_splat_reg.txt | 2 + test/prism/snapshots/seattlerb/bug236.txt | 2 + .../snapshots/seattlerb/bug_args__19.txt | 2 + .../snapshots/seattlerb/bug_args_masgn.txt | 3 + .../snapshots/seattlerb/bug_args_masgn2.txt | 4 + .../bug_args_masgn_outer_parens__19.txt | 3 + .../snapshots/seattlerb/bug_masgn_right.txt | 3 + test/prism/snapshots/seattlerb/case_in.txt | 1 + .../seattlerb/defn_arg_asplat_arg.txt | 3 + .../seattlerb/defn_arg_forward_args.txt | 1 + .../seattlerb/defn_args_forward_args.txt | 3 + .../snapshots/seattlerb/defn_kwarg_env.txt | 1 + .../snapshots/seattlerb/defn_kwarg_kwarg.txt | 3 + .../seattlerb/defn_kwarg_kwsplat.txt | 2 + .../seattlerb/defn_kwarg_kwsplat_anon.txt | 2 + .../snapshots/seattlerb/defn_kwarg_lvar.txt | 1 + .../seattlerb/defn_kwarg_no_parens.txt | 1 + .../snapshots/seattlerb/defn_kwarg_val.txt | 2 + .../snapshots/seattlerb/defn_oneliner.txt | 1 + .../snapshots/seattlerb/defn_oneliner_eq2.txt | 1 + .../seattlerb/defn_oneliner_rescue.txt | 3 + .../snapshots/seattlerb/defn_opt_last_arg.txt | 1 + .../snapshots/seattlerb/defn_opt_reg.txt | 2 + .../seattlerb/defn_opt_splat_arg.txt | 3 + .../prism/snapshots/seattlerb/defn_powarg.txt | 1 + .../snapshots/seattlerb/defn_reg_opt_reg.txt | 3 + .../snapshots/seattlerb/defn_splat_arg.txt | 2 + test/prism/snapshots/seattlerb/defs_kwarg.txt | 1 + .../snapshots/seattlerb/defs_oneliner.txt | 1 + .../snapshots/seattlerb/defs_oneliner_eq2.txt | 1 + .../seattlerb/defs_oneliner_rescue.txt | 3 + .../prism/snapshots/seattlerb/difficult3_.txt | 3 + .../snapshots/seattlerb/difficult3_2.txt | 2 + .../snapshots/seattlerb/difficult3_3.txt | 3 + .../snapshots/seattlerb/difficult3__10.txt | 3 + .../snapshots/seattlerb/difficult3__11.txt | 1 + .../snapshots/seattlerb/difficult3__12.txt | 2 + .../snapshots/seattlerb/difficult3__6.txt | 4 + .../snapshots/seattlerb/difficult3__7.txt | 2 + .../snapshots/seattlerb/difficult3__8.txt | 3 + .../snapshots/seattlerb/difficult3__9.txt | 2 + .../prism/snapshots/seattlerb/difficult6_.txt | 2 + test/prism/snapshots/seattlerb/do_bug.txt | 1 + test/prism/snapshots/seattlerb/f_kw.txt | 1 + .../snapshots/seattlerb/f_kw__required.txt | 1 + .../prism/snapshots/seattlerb/iter_args_1.txt | 2 + .../snapshots/seattlerb/iter_args_10_1.txt | 3 + .../snapshots/seattlerb/iter_args_10_2.txt | 4 + .../snapshots/seattlerb/iter_args_11_1.txt | 4 + .../snapshots/seattlerb/iter_args_11_2.txt | 5 + .../snapshots/seattlerb/iter_args_2__19.txt | 2 + .../prism/snapshots/seattlerb/iter_args_3.txt | 4 + .../prism/snapshots/seattlerb/iter_args_4.txt | 3 + .../prism/snapshots/seattlerb/iter_args_5.txt | 2 + .../prism/snapshots/seattlerb/iter_args_6.txt | 3 + .../snapshots/seattlerb/iter_args_7_1.txt | 2 + .../snapshots/seattlerb/iter_args_7_2.txt | 3 + .../snapshots/seattlerb/iter_args_8_1.txt | 3 + .../snapshots/seattlerb/iter_args_8_2.txt | 4 + .../snapshots/seattlerb/iter_args_9_1.txt | 2 + .../snapshots/seattlerb/iter_args_9_2.txt | 3 + test/prism/snapshots/seattlerb/iter_kwarg.txt | 1 + .../seattlerb/iter_kwarg_kwsplat.txt | 2 + .../seattlerb/parse_line_call_no_args.txt | 2 + .../seattlerb/parse_line_defn_complex.txt | 1 + .../parse_line_defn_no_parens_args.txt | 1 + .../parse_line_iter_call_no_parens.txt | 2 + .../seattlerb/parse_line_iter_call_parens.txt | 2 + .../snapshots/seattlerb/pipe_semicolon.txt | 1 + .../seattlerb/required_kwarg_no_value.txt | 2 + .../seattlerb/stabby_arg_no_paren.txt | 1 + .../stabby_arg_opt_splat_arg_block_omfg.txt | 5 + .../snapshots/seattlerb/stabby_block_kw.txt | 1 + .../seattlerb/stabby_block_kw__required.txt | 1 + .../snapshots/seattlerb/stabby_proc_scope.txt | 2 + .../unparser/corpus/literal/block.txt | 23 + .../snapshots/unparser/corpus/literal/def.txt | 31 ++ .../unparser/corpus/literal/defs.txt | 1 + .../unparser/corpus/literal/dstr.txt | 1 + .../snapshots/unparser/corpus/literal/if.txt | 1 + .../unparser/corpus/literal/lambda.txt | 8 + .../unparser/corpus/literal/since/31.txt | 3 + .../unparser/corpus/literal/since/32.txt | 4 + .../unparser/corpus/literal/while.txt | 3 + .../unparser/corpus/semantic/block.txt | 2 + test/prism/snapshots/while.txt | 1 + .../whitequark/anonymous_blockarg.txt | 1 + test/prism/snapshots/whitequark/arg.txt | 3 + .../whitequark/arg_duplicate_ignored.txt | 4 + test/prism/snapshots/whitequark/arg_scope.txt | 1 + test/prism/snapshots/whitequark/args.txt | 70 +++ test/prism/snapshots/whitequark/blockarg.txt | 1 + test/prism/snapshots/whitequark/blockargs.txt | 74 +++ test/prism/snapshots/whitequark/bug_435.txt | 1 + .../whitequark/bug_lambda_leakage.txt | 1 + .../whitequark/endless_comparison_method.txt | 6 + .../snapshots/whitequark/endless_method.txt | 2 + .../endless_method_command_syntax.txt | 4 + .../whitequark/forward_arg_with_open_args.txt | 7 + .../forwarded_argument_with_kwrestarg.txt | 2 + .../forwarded_argument_with_restarg.txt | 2 + .../whitequark/forwarded_kwrestarg.txt | 1 + ...warded_kwrestarg_with_additional_kwarg.txt | 1 + .../whitequark/forwarded_restarg.txt | 1 + test/prism/snapshots/whitequark/kwarg.txt | 1 + test/prism/snapshots/whitequark/kwoptarg.txt | 1 + ...targ_with_kwrestarg_and_forwarded_args.txt | 2 + .../snapshots/whitequark/kwrestarg_named.txt | 1 + .../whitequark/kwrestarg_unnamed.txt | 1 + .../method_definition_in_while_cond.txt | 2 + test/prism/snapshots/whitequark/optarg.txt | 3 + .../snapshots/whitequark/parser_bug_272.txt | 1 + .../snapshots/whitequark/parser_bug_507.txt | 1 + .../snapshots/whitequark/parser_bug_645.txt | 1 + test/prism/snapshots/whitequark/procarg0.txt | 3 + .../snapshots/whitequark/restarg_named.txt | 1 + .../snapshots/whitequark/restarg_unnamed.txt | 1 + .../snapshots/whitequark/ruby_bug_10653.txt | 1 + .../snapshots/whitequark/ruby_bug_12073.txt | 1 + .../snapshots/whitequark/ruby_bug_15789.txt | 2 + .../snapshots/whitequark/ruby_bug_9669.txt | 1 + .../snapshots/whitequark/send_lambda.txt | 1 + .../snapshots/whitequark/send_lambda_args.txt | 2 + .../whitequark/send_lambda_args_noparen.txt | 2 + .../whitequark/send_lambda_args_shadow.txt | 3 + .../whitequark/trailing_forward_arg.txt | 2 + 181 files changed, 1442 insertions(+), 218 deletions(-) create mode 100644 test/prism/fixtures/repeat_parameters.txt create mode 100644 test/prism/snapshots/repeat_parameters.txt diff --git a/lib/prism/debug.rb b/lib/prism/debug.rb index e275fe1dffafb7..24a27d07ef4fb0 100644 --- a/lib/prism/debug.rb +++ b/lib/prism/debug.rb @@ -138,12 +138,14 @@ def self.prism_locals(source) *params.keywords.grep(OptionalKeywordParameterNode).map(&:name), ] + sorted << AnonymousLocal if params.keywords.any? + if params.keyword_rest.is_a?(ForwardingParameterNode) sorted.push(:*, :&, :"...") + elsif params.keyword_rest.is_a?(KeywordRestParameterNode) + sorted << params.keyword_rest.name if params.keyword_rest.name end - sorted << AnonymousLocal if params.keywords.any? - # Recurse down the parameter tree to find any destructured # parameters and add them after the other parameters. param_stack = params.requireds.concat(params.posts).grep(MultiTargetNode).reverse @@ -151,15 +153,17 @@ def self.prism_locals(source) case param when MultiTargetNode param_stack.concat(param.rights.reverse) - param_stack << param.rest + param_stack << param.rest if param.rest&.expression && !sorted.include?(param.rest.expression.name) param_stack.concat(param.lefts.reverse) when RequiredParameterNode sorted << param.name when SplatNode - sorted << param.expression.name if param.expression + sorted << param.expression.name end end + sorted << params.block.name if params.block&.name + names = sorted.concat(names - sorted) end diff --git a/prism/config.yml b/prism/config.yml index 6af11159f72cdd..748729ec6b1eb3 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -378,6 +378,11 @@ flags: - name: BEGIN_MODIFIER comment: "a loop after a begin statement, so the body is executed first before the condition" comment: Flags for while and until loop nodes. + - name: ParameterFlags + values: + - name: REPEATED_PARAMETER + comment: "a parameter name that has been repeated in the method signature" + comment: Flags for parameter nodes. - name: RangeFlags values: - name: EXCLUDE_END @@ -648,6 +653,9 @@ nodes: ^^^^^^^^^^ - name: BlockLocalVariableNode fields: + - name: flags + type: flags + kind: ParameterFlags - name: name type: constant comment: | @@ -676,6 +684,9 @@ nodes: ^^^^^^^^^^^^^^ - name: BlockParameterNode fields: + - name: flags + type: flags + kind: ParameterFlags - name: name type: constant? - name: name_loc @@ -1923,6 +1934,9 @@ nodes: ^^^^ - name: KeywordRestParameterNode fields: + - name: flags + type: flags + kind: ParameterFlags - name: name type: constant? - name: name_loc @@ -2221,6 +2235,9 @@ nodes: ^^ - name: OptionalKeywordParameterNode fields: + - name: flags + type: flags + kind: ParameterFlags - name: name type: constant - name: name_loc @@ -2235,6 +2252,9 @@ nodes: end - name: OptionalParameterNode fields: + - name: flags + type: flags + kind: ParameterFlags - name: name type: constant - name: name_loc @@ -2451,6 +2471,9 @@ nodes: ^^^^^^ - name: RequiredKeywordParameterNode fields: + - name: flags + type: flags + kind: ParameterFlags - name: name type: constant - name: name_loc @@ -2463,6 +2486,9 @@ nodes: end - name: RequiredParameterNode fields: + - name: flags + type: flags + kind: ParameterFlags - name: name type: constant comment: | @@ -2514,6 +2540,9 @@ nodes: `ex` is in the `exception` field. - name: RestParameterNode fields: + - name: flags + type: flags + kind: ParameterFlags - name: name type: constant? - name: name_loc diff --git a/prism/prism.c b/prism/prism.c index 7ff50630ce2eab..73a35c4d46d9e3 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -887,6 +887,27 @@ pm_node_flag_unset(pm_node_t *node, pm_node_flags_t flag) { node->flags &= (pm_node_flags_t) ~flag; } +/** + * Set the repeated parameter flag on the given node. + */ +static inline void +pm_node_flag_set_repeated_parameter(pm_node_t *node) { + switch (PM_NODE_TYPE(node)) { + case PM_BLOCK_LOCAL_VARIABLE_NODE: + case PM_BLOCK_PARAMETER_NODE: + case PM_KEYWORD_REST_PARAMETER_NODE: + case PM_OPTIONAL_KEYWORD_PARAMETER_NODE: + case PM_OPTIONAL_PARAMETER_NODE: + case PM_REQUIRED_KEYWORD_PARAMETER_NODE: + case PM_REQUIRED_PARAMETER_NODE: + case PM_REST_PARAMETER_NODE: + pm_node_flag_set(node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER); + break; + default: + fprintf(stderr, "unhandled type %d\n", PM_NODE_TYPE(node)); + abort(); + }; +} /******************************************************************************/ /* Node creation functions */ @@ -5996,22 +6017,24 @@ pm_parser_local_add_owned(pm_parser_t *parser, const uint8_t *start, size_t leng * Add a parameter name to the current scope and check whether the name of the * parameter is unique or not. */ -static void +static bool pm_parser_parameter_name_check(pm_parser_t *parser, const pm_token_t *name) { // We want to check whether the parameter name is a numbered parameter or // not. pm_refute_numbered_parameter(parser, name->start, name->end); - // We want to ignore any parameter name that starts with an underscore. - if ((name->start < name->end) && (*name->start == '_')) return; - // Otherwise we'll fetch the constant id for the parameter name and check // whether it's already in the current scope. pm_constant_id_t constant_id = pm_parser_constant_id_token(parser, name); if (pm_constant_id_list_includes(&parser->current_scope->locals, constant_id)) { - pm_parser_err_token(parser, name, PM_ERR_PARAMETER_NAME_REPEAT); + // Add an error if the parameter doesn't start with _ and has been seen before + if ((name->start < name->end) && (*name->start != '_')) { + pm_parser_err_token(parser, name, PM_ERR_PARAMETER_NAME_REPEAT); + } + return true; } + return false; } /** @@ -11466,7 +11489,9 @@ parse_required_destructured_parameter(pm_parser_t *parser) { if (accept1(parser, PM_TOKEN_IDENTIFIER)) { pm_token_t name = parser->previous; value = (pm_node_t *) pm_required_parameter_node_create(parser, &name); - pm_parser_parameter_name_check(parser, &name); + if (pm_parser_parameter_name_check(parser, &name)) { + pm_node_flag_set_repeated_parameter(value); + } pm_parser_local_add_token(parser, &name); } @@ -11476,7 +11501,9 @@ parse_required_destructured_parameter(pm_parser_t *parser) { pm_token_t name = parser->previous; param = (pm_node_t *) pm_required_parameter_node_create(parser, &name); - pm_parser_parameter_name_check(parser, &name); + if (pm_parser_parameter_name_check(parser, &name)) { + pm_node_flag_set_repeated_parameter(param); + } pm_parser_local_add_token(parser, &name); } @@ -11593,9 +11620,10 @@ parse_parameters( pm_token_t operator = parser->previous; pm_token_t name; + bool repeated = false; if (accept1(parser, PM_TOKEN_IDENTIFIER)) { name = parser->previous; - pm_parser_parameter_name_check(parser, &name); + repeated = pm_parser_parameter_name_check(parser, &name); pm_parser_local_add_token(parser, &name); } else { name = not_provided(parser); @@ -11606,6 +11634,9 @@ parse_parameters( } pm_block_parameter_node_t *param = pm_block_parameter_node_create(parser, &name, &operator); + if (repeated) { + pm_node_flag_set_repeated_parameter((pm_node_t *)param); + } if (params->block == NULL) { pm_parameters_node_block_set(params, param); } else { @@ -11678,7 +11709,7 @@ parse_parameters( } pm_token_t name = parser->previous; - pm_parser_parameter_name_check(parser, &name); + bool repeated = pm_parser_parameter_name_check(parser, &name); pm_parser_local_add_token(parser, &name); if (accept1(parser, PM_TOKEN_EQUAL)) { @@ -11689,6 +11720,9 @@ parse_parameters( pm_node_t *value = parse_value_expression(parser, binding_power, false, PM_ERR_PARAMETER_NO_DEFAULT); pm_optional_parameter_node_t *param = pm_optional_parameter_node_create(parser, &name, &operator, value); + if (repeated) { + pm_node_flag_set_repeated_parameter((pm_node_t *)param); + } pm_parameters_node_optionals_append(params, param); parser->current_param_name = old_param_name; @@ -11703,9 +11737,15 @@ parse_parameters( } } else if (order > PM_PARAMETERS_ORDER_AFTER_OPTIONAL) { pm_required_parameter_node_t *param = pm_required_parameter_node_create(parser, &name); + if (repeated) { + pm_node_flag_set_repeated_parameter((pm_node_t *)param); + } pm_parameters_node_requireds_append(params, (pm_node_t *) param); } else { pm_required_parameter_node_t *param = pm_required_parameter_node_create(parser, &name); + if (repeated) { + pm_node_flag_set_repeated_parameter((pm_node_t *)param); + } pm_parameters_node_posts_append(params, (pm_node_t *) param); } @@ -11720,7 +11760,7 @@ parse_parameters( pm_token_t local = name; local.end -= 1; - pm_parser_parameter_name_check(parser, &local); + bool repeated = pm_parser_parameter_name_check(parser, &local); pm_parser_local_add_token(parser, &local); switch (parser->current.type) { @@ -11728,6 +11768,9 @@ parse_parameters( case PM_TOKEN_PARENTHESIS_RIGHT: case PM_TOKEN_PIPE: { pm_node_t *param = (pm_node_t *) pm_required_keyword_parameter_node_create(parser, &name); + if (repeated) { + pm_node_flag_set_repeated_parameter(param); + } pm_parameters_node_keywords_append(params, param); break; } @@ -11739,6 +11782,9 @@ parse_parameters( } pm_node_t *param = (pm_node_t *) pm_required_keyword_parameter_node_create(parser, &name); + if (repeated) { + pm_node_flag_set_repeated_parameter(param); + } pm_parameters_node_keywords_append(params, param); break; } @@ -11758,6 +11804,9 @@ parse_parameters( param = (pm_node_t *) pm_required_keyword_parameter_node_create(parser, &name); } + if (repeated) { + pm_node_flag_set_repeated_parameter(param); + } pm_parameters_node_keywords_append(params, param); // If parsing the value of the parameter resulted in error recovery, @@ -11780,10 +11829,10 @@ parse_parameters( pm_token_t operator = parser->previous; pm_token_t name; - + bool repeated = false; if (accept1(parser, PM_TOKEN_IDENTIFIER)) { name = parser->previous; - pm_parser_parameter_name_check(parser, &name); + repeated = pm_parser_parameter_name_check(parser, &name); pm_parser_local_add_token(parser, &name); } else { name = not_provided(parser); @@ -11794,6 +11843,9 @@ parse_parameters( } pm_node_t *param = (pm_node_t *) pm_rest_parameter_node_create(parser, &operator, &name); + if (repeated) { + pm_node_flag_set_repeated_parameter(param); + } if (params->rest == NULL) { pm_parameters_node_rest_set(params, param); } else { @@ -11816,9 +11868,10 @@ parse_parameters( } else { pm_token_t name; + bool repeated = false; if (accept1(parser, PM_TOKEN_IDENTIFIER)) { name = parser->previous; - pm_parser_parameter_name_check(parser, &name); + repeated = pm_parser_parameter_name_check(parser, &name); pm_parser_local_add_token(parser, &name); } else { name = not_provided(parser); @@ -11829,6 +11882,9 @@ parse_parameters( } param = (pm_node_t *) pm_keyword_rest_parameter_node_create(parser, &operator, &name); + if (repeated) { + pm_node_flag_set_repeated_parameter(param); + } } if (params->keyword_rest == NULL) { @@ -12064,10 +12120,13 @@ parse_block_parameters( if ((opening->type != PM_TOKEN_NOT_PROVIDED) && accept1(parser, PM_TOKEN_SEMICOLON)) { do { expect1(parser, PM_TOKEN_IDENTIFIER, PM_ERR_BLOCK_PARAM_LOCAL_VARIABLE); - pm_parser_parameter_name_check(parser, &parser->previous); + bool repeated = pm_parser_parameter_name_check(parser, &parser->previous); pm_parser_local_add_token(parser, &parser->previous); pm_block_local_variable_node_t *local = pm_block_local_variable_node_create(parser, &parser->previous); + if (repeated) { + pm_node_flag_set_repeated_parameter((pm_node_t *)local); + } pm_block_parameters_node_append_local(block_parameters, local); } while (accept1(parser, PM_TOKEN_COMMA)); } diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index 2c981fbd427976..d1af9a5dae8385 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -566,10 +566,10 @@ def test_bad_arguments Location(), nil, ParametersNode([ - RequiredParameterNode(:A), - RequiredParameterNode(:@a), - RequiredParameterNode(:$A), - RequiredParameterNode(:@@a), + RequiredParameterNode(0, :A), + RequiredParameterNode(0, :@a), + RequiredParameterNode(0, :$A), + RequiredParameterNode(0, :@@a), ], [], nil, [], [], nil, nil), nil, [:A, :@a, :$A, :@@a], @@ -635,7 +635,7 @@ def test_do_not_allow_trailing_commas_in_method_parameters Location(), nil, ParametersNode( - [RequiredParameterNode(:a), RequiredParameterNode(:b), RequiredParameterNode(:c)], + [RequiredParameterNode(0, :a), RequiredParameterNode(0, :b), RequiredParameterNode(0, :c)], [], nil, [], @@ -667,7 +667,7 @@ def test_do_not_allow_trailing_commas_in_lambda_parameters Location(), Location(), BlockParametersNode( - ParametersNode([RequiredParameterNode(:a), RequiredParameterNode(:b)], [], nil, [], [], nil, nil), + ParametersNode([RequiredParameterNode(0, :a), RequiredParameterNode(0, :b)], [], nil, [], [], nil, nil), [], Location(), Location() @@ -724,10 +724,10 @@ def test_method_parameters_after_block [], [], nil, - [RequiredParameterNode(:a)], + [RequiredParameterNode(0, :a)], [], nil, - BlockParameterNode(:block, Location(), Location()) + BlockParameterNode(0, :block, Location(), Location()) ), nil, [:block, :a], @@ -749,7 +749,7 @@ def test_method_with_arguments_after_anonymous_block :foo, Location(), nil, - ParametersNode([], [], nil, [RequiredParameterNode(:a)], [], nil, BlockParameterNode(nil, nil, Location())), + ParametersNode([], [], nil, [RequiredParameterNode(0, :a)], [], nil, BlockParameterNode(0, nil, nil, Location())), nil, [:&, :a], 2, @@ -775,7 +775,7 @@ def test_method_parameters_after_arguments_forwarding [], [], nil, - [RequiredParameterNode(:a)], + [RequiredParameterNode(0, :a)], [], ForwardingParameterNode(), nil @@ -804,8 +804,8 @@ def test_keywords_parameters_before_required_parameters [], [], nil, - [RequiredParameterNode(:a)], - [RequiredKeywordParameterNode(:b, Location())], + [RequiredParameterNode(0, :a)], + [RequiredKeywordParameterNode(0, :b, Location())], nil, nil ), @@ -834,8 +834,8 @@ def test_rest_keywords_parameters_before_required_parameters [], nil, [], - [RequiredKeywordParameterNode(:b, Location())], - KeywordRestParameterNode(:rest, Location(), Location()), + [RequiredKeywordParameterNode(0, :b, Location())], + KeywordRestParameterNode(0, :rest, Location(), Location()), nil ), nil, @@ -885,9 +885,9 @@ def test_multiple_error_in_parameters_order [], [], nil, - [RequiredParameterNode(:a)], - [RequiredKeywordParameterNode(:b, Location())], - KeywordRestParameterNode(:args, Location(), Location()), + [RequiredParameterNode(0, :a)], + [RequiredKeywordParameterNode(0, :b, Location())], + KeywordRestParameterNode(0, :args, Location(), Location()), nil ), nil, @@ -916,9 +916,9 @@ def test_switching_to_optional_arguments_twice [], [], nil, - [RequiredParameterNode(:a)], - [RequiredKeywordParameterNode(:b, Location())], - KeywordRestParameterNode(:args, Location(), Location()), + [RequiredParameterNode(0, :a)], + [RequiredKeywordParameterNode(0, :b, Location())], + KeywordRestParameterNode(0, :args, Location(), Location()), nil ), nil, @@ -947,9 +947,9 @@ def test_switching_to_named_arguments_twice [], [], nil, - [RequiredParameterNode(:a)], - [RequiredKeywordParameterNode(:b, Location())], - KeywordRestParameterNode(:args, Location(), Location()), + [RequiredParameterNode(0, :a)], + [RequiredKeywordParameterNode(0, :b, Location())], + KeywordRestParameterNode(0, :args, Location(), Location()), nil ), nil, @@ -975,13 +975,13 @@ def test_returning_to_optional_parameters_multiple_times Location(), nil, ParametersNode( - [RequiredParameterNode(:a)], + [RequiredParameterNode(0, :a)], [ - OptionalParameterNode(:b, Location(), Location(), IntegerNode(IntegerBaseFlags::DECIMAL)), - OptionalParameterNode(:d, Location(), Location(), IntegerNode(IntegerBaseFlags::DECIMAL)) + OptionalParameterNode(0, :b, Location(), Location(), IntegerNode(IntegerBaseFlags::DECIMAL)), + OptionalParameterNode(0, :d, Location(), Location(), IntegerNode(IntegerBaseFlags::DECIMAL)) ], nil, - [RequiredParameterNode(:c), RequiredParameterNode(:e)], + [RequiredParameterNode(0, :c), RequiredParameterNode(0, :e)], [], nil, nil @@ -1152,7 +1152,7 @@ def test_duplicated_parameter_names :foo, Location(), nil, - ParametersNode([RequiredParameterNode(:a), RequiredParameterNode(:b), RequiredParameterNode(:a)], [], nil, [], [], nil, nil), + ParametersNode([RequiredParameterNode(0, :a), RequiredParameterNode(0, :b), RequiredParameterNode(ParameterFlags::REPEATED_PARAMETER, :a)], [], nil, [], [], nil, nil), nil, [:a, :b], 2, @@ -1173,7 +1173,7 @@ def test_duplicated_parameter_names :foo, Location(), nil, - ParametersNode([RequiredParameterNode(:a), RequiredParameterNode(:b)], [], RestParameterNode(:a, Location(), Location()), [], [], nil, nil), + ParametersNode([RequiredParameterNode(0, :a), RequiredParameterNode(0, :b)], [], RestParameterNode(ParameterFlags::REPEATED_PARAMETER, :a, Location(), Location()), [], [], nil, nil), nil, [:a, :b], 2, @@ -1193,7 +1193,7 @@ def test_duplicated_parameter_names :foo, Location(), nil, - ParametersNode([RequiredParameterNode(:a), RequiredParameterNode(:b)], [], nil, [], [], KeywordRestParameterNode(:a, Location(), Location()), nil), + ParametersNode([RequiredParameterNode(0, :a), RequiredParameterNode(0, :b)], [], nil, [], [], KeywordRestParameterNode(ParameterFlags::REPEATED_PARAMETER, :a, Location(), Location()), nil), nil, [:a, :b], 2, @@ -1213,7 +1213,7 @@ def test_duplicated_parameter_names :foo, Location(), nil, - ParametersNode([RequiredParameterNode(:a), RequiredParameterNode(:b)], [], nil, [], [], nil, BlockParameterNode(:a, Location(), Location())), + ParametersNode([RequiredParameterNode(0, :a), RequiredParameterNode(0, :b)], [], nil, [], [], nil, BlockParameterNode(ParameterFlags::REPEATED_PARAMETER, :a, Location(), Location())), nil, [:a, :b], 2, @@ -1233,7 +1233,7 @@ def test_duplicated_parameter_names :foo, Location(), nil, - ParametersNode([], [OptionalParameterNode(:a, Location(), Location(), IntegerNode(IntegerBaseFlags::DECIMAL))], RestParameterNode(:c, Location(), Location()), [RequiredParameterNode(:b)], [], nil, nil), + ParametersNode([], [OptionalParameterNode(0, :a, Location(), Location(), IntegerNode(IntegerBaseFlags::DECIMAL))], RestParameterNode(0, :c, Location(), Location()), [RequiredParameterNode(0, :b)], [], nil, nil), nil, [:a, :b, :c], 3, diff --git a/test/prism/fixtures/methods.txt b/test/prism/fixtures/methods.txt index 703527f2de653d..0d2286056fe30d 100644 --- a/test/prism/fixtures/methods.txt +++ b/test/prism/fixtures/methods.txt @@ -161,9 +161,6 @@ def method(a) item >> a {} end -def foo(_a, _a, b, c) -end - foo = 1 def foo.bar; end diff --git a/test/prism/fixtures/repeat_parameters.txt b/test/prism/fixtures/repeat_parameters.txt new file mode 100644 index 00000000000000..9c69e9718ad22f --- /dev/null +++ b/test/prism/fixtures/repeat_parameters.txt @@ -0,0 +1,38 @@ +def foo(a, _) +end + +def foo(a, _, _) +end + +def foo(a, _, _, _b) +end + +def foo(a, _, _, _b, _b) +end + +def foo(a, (b, *_c, d), (e, *_c, f)) +end + +def foo(_a, _a, b, c) +end + +def foo((a, *_b, c), (d, *_b, e)) +end + +def foo(_a = 1, _a = 2) +end + +def foo(_a:, _a:) +end + +def foo(_a: 1, _a: 2) +end + +def foo(_a, **_a) +end + +def foo(_a, &_a) +end + +def foo(_a, *_a) +end diff --git a/test/prism/snapshots/arrays.txt b/test/prism/snapshots/arrays.txt index 7f58faaed5caba..c1b29134619bbc 100644 --- a/test/prism/snapshots/arrays.txt +++ b/test/prism/snapshots/arrays.txt @@ -1031,6 +1031,7 @@ │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (88,8)-(88,9)) + │ │ ├── flags: ∅ │ │ ├── name: ∅ │ │ ├── name_loc: ∅ │ │ └── operator_loc: (88,8)-(88,9) = "&" @@ -1809,6 +1810,7 @@ │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (128,6)-(128,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: ∅ │ │ │ ├── name_loc: ∅ │ │ │ └── operator_loc: (128,6)-(128,7) = "*" @@ -1863,6 +1865,7 @@ │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (130,6)-(130,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: ∅ │ │ │ ├── name_loc: ∅ │ │ │ └── operator_loc: (130,6)-(130,7) = "*" @@ -1919,6 +1922,7 @@ │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (132,6)-(132,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: ∅ │ │ │ ├── name_loc: ∅ │ │ │ └── operator_loc: (132,6)-(132,7) = "*" @@ -1975,6 +1979,7 @@ │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (134,6)-(134,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: ∅ │ │ │ ├── name_loc: ∅ │ │ │ └── operator_loc: (134,6)-(134,7) = "*" @@ -2033,6 +2038,7 @@ │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (136,6)-(136,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: ∅ │ │ │ ├── name_loc: ∅ │ │ │ └── operator_loc: (136,6)-(136,7) = "*" @@ -2090,6 +2096,7 @@ │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (138,6)-(138,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: ∅ │ │ │ ├── name_loc: ∅ │ │ │ └── operator_loc: (138,6)-(138,7) = "*" @@ -2148,6 +2155,7 @@ │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (140,6)-(140,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: ∅ │ │ │ ├── name_loc: ∅ │ │ │ └── operator_loc: (140,6)-(140,7) = "*" @@ -2211,6 +2219,7 @@ │ ├── optionals: (length: 0) │ ├── rest: │ │ @ RestParameterNode (location: (142,6)-(142,7)) + │ │ ├── flags: ∅ │ │ ├── name: ∅ │ │ ├── name_loc: ∅ │ │ └── operator_loc: (142,6)-(142,7) = "*" diff --git a/test/prism/snapshots/blocks.txt b/test/prism/snapshots/blocks.txt index 9d560d4016e925..577a11ab16b0d6 100644 --- a/test/prism/snapshots/blocks.txt +++ b/test/prism/snapshots/blocks.txt @@ -141,8 +141,10 @@ │ │ │ @ ParametersNode (location: (7,15)-(7,22)) │ │ │ ├── requireds: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (7,15)-(7,16)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :x │ │ │ │ └── @ RequiredParameterNode (location: (7,18)-(7,22)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :memo │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -324,6 +326,7 @@ │ │ │ ├── requireds: (length: 0) │ │ │ ├── optionals: (length: 1) │ │ │ │ └── @ OptionalParameterNode (location: (17,8)-(17,16)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :a │ │ │ │ ├── name_loc: (17,8)-(17,9) = "a" │ │ │ │ ├── operator_loc: (17,10)-(17,11) = "=" @@ -521,9 +524,11 @@ │ │ │ @ ParametersNode (location: (33,7)-(33,19)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (33,7)-(33,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :x │ │ │ ├── optionals: (length: 1) │ │ │ │ └── @ OptionalParameterNode (location: (33,10)-(33,15)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :y │ │ │ │ ├── name_loc: (33,10)-(33,11) = "y" │ │ │ │ ├── operator_loc: (33,12)-(33,13) = "=" @@ -534,6 +539,7 @@ │ │ │ ├── posts: (length: 0) │ │ │ ├── keywords: (length: 1) │ │ │ │ └── @ RequiredKeywordParameterNode (location: (33,17)-(33,19)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :z │ │ │ │ └── name_loc: (33,17)-(33,19) = "z:" │ │ │ ├── keyword_rest: ∅ @@ -568,6 +574,7 @@ │ │ │ @ ParametersNode (location: (35,7)-(35,8)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (35,7)-(35,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :x │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -608,6 +615,7 @@ │ │ │ @ ParametersNode (location: (38,9)-(38,10)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (38,9)-(38,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -640,6 +648,7 @@ │ │ │ @ ParametersNode (location: (41,8)-(41,9)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (41,8)-(41,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -721,12 +730,14 @@ │ │ │ │ ├── posts: (length: 0) │ │ │ │ ├── keywords: (length: 2) │ │ │ │ │ ├── @ OptionalKeywordParameterNode (location: (49,2)-(49,6)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ ├── name: :a │ │ │ │ │ │ ├── name_loc: (49,2)-(49,4) = "a:" │ │ │ │ │ │ └── value: │ │ │ │ │ │ @ IntegerNode (location: (49,5)-(49,6)) │ │ │ │ │ │ └── flags: decimal │ │ │ │ │ └── @ OptionalKeywordParameterNode (location: (50,2)-(50,6)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── name: :b │ │ │ │ │ ├── name_loc: (50,2)-(50,4) = "b:" │ │ │ │ │ └── value: @@ -761,6 +772,7 @@ │ │ @ ParametersNode (location: (54,8)-(54,12)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (54,8)-(54,11)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :bar │ │ ├── optionals: (length: 0) │ │ ├── rest: diff --git a/test/prism/snapshots/break.txt b/test/prism/snapshots/break.txt index 30b15e47540bfa..c30231c02d4e7c 100644 --- a/test/prism/snapshots/break.txt +++ b/test/prism/snapshots/break.txt @@ -189,6 +189,7 @@ │ │ │ @ ParametersNode (location: (25,7)-(25,8)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (25,7)-(25,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/if.txt b/test/prism/snapshots/if.txt index f2166052a51f60..ae3df9719b7040 100644 --- a/test/prism/snapshots/if.txt +++ b/test/prism/snapshots/if.txt @@ -356,6 +356,7 @@ │ │ │ @ ParametersNode (location: (34,13)-(34,14)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (34,13)-(34,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :_ │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -398,6 +399,7 @@ │ │ │ │ @ ParametersNode (location: (37,13)-(37,14)) │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ └── @ RequiredParameterNode (location: (37,13)-(37,14)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :_ │ │ │ │ ├── optionals: (length: 0) │ │ │ │ ├── rest: ∅ @@ -436,6 +438,7 @@ │ │ │ │ │ @ ParametersNode (location: (40,13)-(40,14)) │ │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ │ └── @ RequiredParameterNode (location: (40,13)-(40,14)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── name: :_ │ │ │ │ │ ├── optionals: (length: 0) │ │ │ │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/keyword_method_names.txt b/test/prism/snapshots/keyword_method_names.txt index afaff8d60435ee..3fdf69971d0c6f 100644 --- a/test/prism/snapshots/keyword_method_names.txt +++ b/test/prism/snapshots/keyword_method_names.txt @@ -86,6 +86,7 @@ │ │ @ ParametersNode (location: (12,6)-(12,14)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (12,6)-(12,7)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/lambda.txt b/test/prism/snapshots/lambda.txt index eb7c12dc5b8b5a..05e803c62bcb9c 100644 --- a/test/prism/snapshots/lambda.txt +++ b/test/prism/snapshots/lambda.txt @@ -15,6 +15,7 @@ │ │ │ @ ParametersNode (location: (2,2)-(2,5)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (2,2)-(2,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :foo │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -42,6 +43,7 @@ │ │ │ ├── posts: (length: 0) │ │ │ ├── keywords: (length: 1) │ │ │ │ └── @ OptionalKeywordParameterNode (location: (5,3)-(5,13)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :x │ │ │ │ ├── name_loc: (5,3)-(5,5) = "x:" │ │ │ │ └── value: @@ -93,6 +95,7 @@ │ │ │ ├── posts: (length: 0) │ │ │ ├── keywords: (length: 1) │ │ │ │ └── @ OptionalKeywordParameterNode (location: (7,3)-(7,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :a │ │ │ │ ├── name_loc: (7,3)-(7,5) = "a:" │ │ │ │ └── value: @@ -140,6 +143,7 @@ │ │ │ ├── requireds: (length: 0) │ │ │ ├── optionals: (length: 1) │ │ │ │ └── @ OptionalParameterNode (location: (9,3)-(9,12)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :foo │ │ │ │ ├── name_loc: (9,3)-(9,6) = "foo" │ │ │ │ ├── operator_loc: (9,7)-(9,8) = "=" @@ -179,6 +183,7 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) │ │ │ └── @ OptionalKeywordParameterNode (location: (11,3)-(11,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :foo │ │ │ ├── name_loc: (11,3)-(11,7) = "foo:" │ │ │ └── value: diff --git a/test/prism/snapshots/method_calls.txt b/test/prism/snapshots/method_calls.txt index fdebd48d5a9a87..0828a65a348977 100644 --- a/test/prism/snapshots/method_calls.txt +++ b/test/prism/snapshots/method_calls.txt @@ -938,8 +938,10 @@ │ │ │ @ ParametersNode (location: (64,20)-(64,24)) │ │ │ ├── requireds: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (64,20)-(64,21)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :a │ │ │ │ └── @ RequiredParameterNode (location: (64,23)-(64,24)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -1932,6 +1934,7 @@ │ │ │ │ │ @ ParametersNode (location: (121,12)-(121,13)) │ │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ │ └── @ RequiredParameterNode (location: (121,12)-(121,13)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── name: :a │ │ │ │ │ ├── optionals: (length: 0) │ │ │ │ │ ├── rest: ∅ @@ -2008,6 +2011,7 @@ │ │ │ │ │ @ ParametersNode (location: (128,12)-(128,13)) │ │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ │ └── @ RequiredParameterNode (location: (128,12)-(128,13)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── name: :a │ │ │ │ │ ├── optionals: (length: 0) │ │ │ │ │ ├── rest: ∅ @@ -2131,6 +2135,7 @@ │ │ │ │ @ ParametersNode (location: (139,10)-(139,11)) │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ └── @ RequiredParameterNode (location: (139,10)-(139,11)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :a │ │ │ │ ├── optionals: (length: 0) │ │ │ │ ├── rest: ∅ @@ -2309,6 +2314,7 @@ │ ├── optionals: (length: 0) │ ├── rest: │ │ @ RestParameterNode (location: (149,6)-(149,7)) + │ │ ├── flags: ∅ │ │ ├── name: ∅ │ │ ├── name_loc: ∅ │ │ └── operator_loc: (149,6)-(149,7) = "*" diff --git a/test/prism/snapshots/methods.txt b/test/prism/snapshots/methods.txt index 225f27e1781382..9e0e0548e8137d 100644 --- a/test/prism/snapshots/methods.txt +++ b/test/prism/snapshots/methods.txt @@ -1,8 +1,8 @@ -@ ProgramNode (location: (1,0)-(186,37)) +@ ProgramNode (location: (1,0)-(183,37)) ├── locals: [:a, :c, :foo] └── statements: - @ StatementsNode (location: (1,0)-(186,37)) - └── body: (length: 70) + @ StatementsNode (location: (1,0)-(183,37)) + └── body: (length: 69) ├── @ DefNode (location: (1,0)-(2,3)) │ ├── name: :foo │ ├── name_loc: (1,4)-(1,7) = "foo" @@ -13,8 +13,10 @@ │ │ │ └── @ MultiTargetNode (location: (1,8)-(1,18)) │ │ │ ├── lefts: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (1,9)-(1,12)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :bar │ │ │ │ └── @ RequiredParameterNode (location: (1,14)-(1,17)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :baz │ │ │ ├── rest: ∅ │ │ │ ├── rights: (length: 0) @@ -45,8 +47,10 @@ │ │ │ └── @ MultiTargetNode (location: (4,8)-(4,18)) │ │ │ ├── lefts: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (4,9)-(4,12)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :bar │ │ │ │ └── @ RequiredParameterNode (location: (4,14)-(4,17)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :baz │ │ │ ├── rest: ∅ │ │ │ ├── rights: (length: 0) @@ -54,6 +58,7 @@ │ │ │ └── rparen_loc: (4,17)-(4,18) = ")" │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (4,20)-(4,32)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :optional │ │ │ ├── name_loc: (4,20)-(4,28) = "optional" │ │ │ ├── operator_loc: (4,29)-(4,30) = "=" @@ -65,8 +70,10 @@ │ │ │ └── @ MultiTargetNode (location: (4,34)-(4,44)) │ │ │ ├── lefts: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (4,35)-(4,38)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :bin │ │ │ │ └── @ RequiredParameterNode (location: (4,40)-(4,43)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :bag │ │ │ ├── rest: ∅ │ │ │ ├── rights: (length: 0) @@ -271,6 +278,7 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) │ │ │ └── @ RequiredKeywordParameterNode (location: (31,6)-(31,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ └── name_loc: (31,6)-(31,8) = "b:" │ │ ├── keyword_rest: ∅ @@ -302,6 +310,7 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) │ │ │ └── @ RequiredKeywordParameterNode (location: (35,6)-(35,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ └── name_loc: (35,6)-(35,8) = "b:" │ │ ├── keyword_rest: ∅ @@ -328,6 +337,7 @@ │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: │ │ │ @ KeywordRestParameterNode (location: (38,6)-(38,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (38,8)-(38,9) = "b" │ │ │ └── operator_loc: (38,6)-(38,8) = "**" @@ -354,6 +364,7 @@ │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: │ │ │ @ KeywordRestParameterNode (location: (41,6)-(41,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: ∅ │ │ │ ├── name_loc: ∅ │ │ │ └── operator_loc: (41,6)-(41,8) = "**" @@ -397,10 +408,13 @@ │ │ @ ParametersNode (location: (47,6)-(47,13)) │ │ ├── requireds: (length: 3) │ │ │ ├── @ RequiredParameterNode (location: (47,6)-(47,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── @ RequiredParameterNode (location: (47,9)-(47,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :c │ │ │ └── @ RequiredParameterNode (location: (47,12)-(47,13)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :d │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -444,9 +458,11 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 2) │ │ │ ├── @ RequiredKeywordParameterNode (location: (53,6)-(53,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :b │ │ │ │ └── name_loc: (53,6)-(53,8) = "b:" │ │ │ └── @ OptionalKeywordParameterNode (location: (53,10)-(53,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ ├── name_loc: (53,10)-(53,12) = "c:" │ │ │ └── value: @@ -475,9 +491,11 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 2) │ │ │ ├── @ RequiredKeywordParameterNode (location: (56,6)-(56,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :b │ │ │ │ └── name_loc: (56,6)-(56,8) = "b:" │ │ │ └── @ OptionalKeywordParameterNode (location: (56,10)-(56,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ ├── name_loc: (56,10)-(56,12) = "c:" │ │ │ └── value: @@ -506,12 +524,14 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 2) │ │ │ ├── @ OptionalKeywordParameterNode (location: (59,6)-(60,3)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :b │ │ │ │ ├── name_loc: (59,6)-(59,8) = "b:" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (60,2)-(60,3)) │ │ │ │ └── flags: decimal │ │ │ └── @ RequiredKeywordParameterNode (location: (60,5)-(60,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ └── name_loc: (60,5)-(60,7) = "c:" │ │ ├── keyword_rest: ∅ @@ -540,6 +560,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 2) │ │ │ ├── @ OptionalParameterNode (location: (65,6)-(65,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :b │ │ │ │ ├── name_loc: (65,6)-(65,7) = "b" │ │ │ │ ├── operator_loc: (65,8)-(65,9) = "=" @@ -547,6 +568,7 @@ │ │ │ │ @ IntegerNode (location: (65,10)-(65,11)) │ │ │ │ └── flags: decimal │ │ │ └── @ OptionalParameterNode (location: (65,13)-(65,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ ├── name_loc: (65,13)-(65,14) = "c" │ │ │ ├── operator_loc: (65,15)-(65,16) = "=" @@ -589,9 +611,11 @@ │ │ @ ParametersNode (location: (71,6)-(71,14)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (71,6)-(71,7)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :b │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (71,9)-(71,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ ├── name_loc: (71,9)-(71,10) = "c" │ │ │ ├── operator_loc: (71,11)-(71,12) = "=" @@ -620,6 +644,7 @@ │ │ @ ParametersNode (location: (74,6)-(74,7)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (74,6)-(74,7)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :b │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -682,6 +707,7 @@ │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (79,6)-(79,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (79,7)-(79,8) = "b" │ │ │ └── operator_loc: (79,6)-(79,7) = "*" @@ -708,6 +734,7 @@ │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (82,6)-(82,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: ∅ │ │ │ ├── name_loc: ∅ │ │ │ └── operator_loc: (82,6)-(82,7) = "*" @@ -880,6 +907,7 @@ │ │ @ ParametersNode (location: (106,8)-(106,11)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (106,8)-(106,11)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :bar │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -928,6 +956,7 @@ │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (110,6)-(110,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: ∅ │ │ │ ├── name_loc: ∅ │ │ │ └── operator_loc: (110,6)-(110,7) = "*" @@ -1092,6 +1121,7 @@ │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (119,6)-(119,8)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (119,7)-(119,8) = "b" │ │ └── operator_loc: (119,6)-(119,7) = "&" @@ -1118,6 +1148,7 @@ │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (122,6)-(122,7)) + │ │ ├── flags: ∅ │ │ ├── name: ∅ │ │ ├── name_loc: ∅ │ │ └── operator_loc: (122,6)-(122,7) = "&" @@ -1360,6 +1391,7 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) │ │ │ └── @ OptionalKeywordParameterNode (location: (142,8)-(142,19)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ ├── name_loc: (142,8)-(142,10) = "a:" │ │ │ └── value: @@ -1401,6 +1433,7 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) │ │ │ └── @ OptionalKeywordParameterNode (location: (145,8)-(145,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ ├── name_loc: (145,8)-(145,10) = "a:" │ │ │ └── value: @@ -1440,6 +1473,7 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) │ │ │ └── @ OptionalKeywordParameterNode (location: (148,8)-(148,17)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ ├── name_loc: (148,8)-(148,10) = "a:" │ │ │ └── value: @@ -1476,6 +1510,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (151,8)-(151,20)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ ├── name_loc: (151,8)-(151,9) = "a" │ │ │ ├── operator_loc: (151,10)-(151,11) = "=" @@ -1518,6 +1553,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (154,8)-(154,19)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ ├── name_loc: (154,8)-(154,9) = "a" │ │ │ ├── operator_loc: (154,10)-(154,11) = "=" @@ -1558,6 +1594,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (157,8)-(157,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ ├── name_loc: (157,8)-(157,9) = "a" │ │ │ ├── operator_loc: (157,10)-(157,11) = "=" @@ -1597,6 +1634,7 @@ │ │ @ ParametersNode (location: (160,11)-(160,12)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (160,11)-(160,12)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -1655,128 +1693,100 @@ │ ├── rparen_loc: (160,12)-(160,13) = ")" │ ├── equal_loc: ∅ │ └── end_keyword_loc: (162,0)-(162,3) = "end" - ├── @ DefNode (location: (164,0)-(165,3)) - │ ├── name: :foo - │ ├── name_loc: (164,4)-(164,7) = "foo" - │ ├── receiver: ∅ - │ ├── parameters: - │ │ @ ParametersNode (location: (164,8)-(164,20)) - │ │ ├── requireds: (length: 4) - │ │ │ ├── @ RequiredParameterNode (location: (164,8)-(164,10)) - │ │ │ │ └── name: :_a - │ │ │ ├── @ RequiredParameterNode (location: (164,12)-(164,14)) - │ │ │ │ └── name: :_a - │ │ │ ├── @ RequiredParameterNode (location: (164,16)-(164,17)) - │ │ │ │ └── name: :b - │ │ │ └── @ RequiredParameterNode (location: (164,19)-(164,20)) - │ │ │ └── name: :c - │ │ ├── optionals: (length: 0) - │ │ ├── rest: ∅ - │ │ ├── posts: (length: 0) - │ │ ├── keywords: (length: 0) - │ │ ├── keyword_rest: ∅ - │ │ └── block: ∅ - │ ├── body: ∅ - │ ├── locals: [:_a, :b, :c] - │ ├── locals_body_index: 3 - │ ├── def_keyword_loc: (164,0)-(164,3) = "def" - │ ├── operator_loc: ∅ - │ ├── lparen_loc: (164,7)-(164,8) = "(" - │ ├── rparen_loc: (164,20)-(164,21) = ")" - │ ├── equal_loc: ∅ - │ └── end_keyword_loc: (165,0)-(165,3) = "end" - ├── @ LocalVariableWriteNode (location: (167,0)-(167,7)) + ├── @ LocalVariableWriteNode (location: (164,0)-(164,7)) │ ├── name: :foo │ ├── depth: 0 - │ ├── name_loc: (167,0)-(167,3) = "foo" + │ ├── name_loc: (164,0)-(164,3) = "foo" │ ├── value: - │ │ @ IntegerNode (location: (167,6)-(167,7)) + │ │ @ IntegerNode (location: (164,6)-(164,7)) │ │ └── flags: decimal - │ └── operator_loc: (167,4)-(167,5) = "=" - ├── @ DefNode (location: (168,0)-(168,16)) + │ └── operator_loc: (164,4)-(164,5) = "=" + ├── @ DefNode (location: (165,0)-(165,16)) │ ├── name: :bar - │ ├── name_loc: (168,8)-(168,11) = "bar" + │ ├── name_loc: (165,8)-(165,11) = "bar" │ ├── receiver: - │ │ @ LocalVariableReadNode (location: (168,4)-(168,7)) + │ │ @ LocalVariableReadNode (location: (165,4)-(165,7)) │ │ ├── name: :foo │ │ └── depth: 0 │ ├── parameters: ∅ │ ├── body: ∅ │ ├── locals: [] │ ├── locals_body_index: 0 - │ ├── def_keyword_loc: (168,0)-(168,3) = "def" - │ ├── operator_loc: (168,7)-(168,8) = "." + │ ├── def_keyword_loc: (165,0)-(165,3) = "def" + │ ├── operator_loc: (165,7)-(165,8) = "." │ ├── lparen_loc: ∅ │ ├── rparen_loc: ∅ │ ├── equal_loc: ∅ - │ └── end_keyword_loc: (168,13)-(168,16) = "end" - ├── @ DefNode (location: (170,0)-(170,18)) + │ └── end_keyword_loc: (165,13)-(165,16) = "end" + ├── @ DefNode (location: (167,0)-(167,18)) │ ├── name: :f - │ ├── name_loc: (170,4)-(170,5) = "f" + │ ├── name_loc: (167,4)-(167,5) = "f" │ ├── receiver: ∅ │ ├── parameters: - │ │ @ ParametersNode (location: (170,6)-(170,7)) + │ │ @ ParametersNode (location: (167,6)-(167,7)) │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: - │ │ │ @ RestParameterNode (location: (170,6)-(170,7)) + │ │ │ @ RestParameterNode (location: (167,6)-(167,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: ∅ │ │ │ ├── name_loc: ∅ - │ │ │ └── operator_loc: (170,6)-(170,7) = "*" + │ │ │ └── operator_loc: (167,6)-(167,7) = "*" │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ │ │ └── block: ∅ │ ├── body: - │ │ @ StatementsNode (location: (170,10)-(170,13)) + │ │ @ StatementsNode (location: (167,10)-(167,13)) │ │ └── body: (length: 1) - │ │ └── @ ArrayNode (location: (170,10)-(170,13)) + │ │ └── @ ArrayNode (location: (167,10)-(167,13)) │ │ ├── flags: contains_splat │ │ ├── elements: (length: 1) - │ │ │ └── @ SplatNode (location: (170,11)-(170,12)) - │ │ │ ├── operator_loc: (170,11)-(170,12) = "*" + │ │ │ └── @ SplatNode (location: (167,11)-(167,12)) + │ │ │ ├── operator_loc: (167,11)-(167,12) = "*" │ │ │ └── expression: ∅ - │ │ ├── opening_loc: (170,10)-(170,11) = "[" - │ │ └── closing_loc: (170,12)-(170,13) = "]" + │ │ ├── opening_loc: (167,10)-(167,11) = "[" + │ │ └── closing_loc: (167,12)-(167,13) = "]" │ ├── locals: [:*] │ ├── locals_body_index: 1 - │ ├── def_keyword_loc: (170,0)-(170,3) = "def" + │ ├── def_keyword_loc: (167,0)-(167,3) = "def" │ ├── operator_loc: ∅ - │ ├── lparen_loc: (170,5)-(170,6) = "(" - │ ├── rparen_loc: (170,7)-(170,8) = ")" + │ ├── lparen_loc: (167,5)-(167,6) = "(" + │ ├── rparen_loc: (167,7)-(167,8) = ")" │ ├── equal_loc: ∅ - │ └── end_keyword_loc: (170,15)-(170,18) = "end" - ├── @ DefNode (location: (172,0)-(172,15)) + │ └── end_keyword_loc: (167,15)-(167,18) = "end" + ├── @ DefNode (location: (169,0)-(169,15)) │ ├── name: :f - │ ├── name_loc: (172,4)-(172,5) = "f" + │ ├── name_loc: (169,4)-(169,5) = "f" │ ├── receiver: ∅ │ ├── parameters: - │ │ @ ParametersNode (location: (172,6)-(172,10)) + │ │ @ ParametersNode (location: (169,6)-(169,10)) │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) - │ │ │ └── @ OptionalKeywordParameterNode (location: (172,6)-(172,10)) + │ │ │ └── @ OptionalKeywordParameterNode (location: (169,6)-(169,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :x - │ │ │ ├── name_loc: (172,6)-(172,8) = "x:" + │ │ │ ├── name_loc: (169,6)-(169,8) = "x:" │ │ │ └── value: - │ │ │ @ CallNode (location: (172,8)-(172,10)) + │ │ │ @ CallNode (location: (169,8)-(169,10)) │ │ │ ├── flags: ∅ │ │ │ ├── receiver: - │ │ │ │ @ CallNode (location: (172,9)-(172,10)) + │ │ │ │ @ CallNode (location: (169,9)-(169,10)) │ │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :a - │ │ │ │ ├── message_loc: (172,9)-(172,10) = "a" + │ │ │ │ ├── message_loc: (169,9)-(169,10) = "a" │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── arguments: ∅ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :-@ - │ │ │ ├── message_loc: (172,8)-(172,9) = "-" + │ │ │ ├── message_loc: (169,8)-(169,9) = "-" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ @@ -1786,43 +1796,44 @@ │ ├── body: ∅ │ ├── locals: [:x] │ ├── locals_body_index: 1 - │ ├── def_keyword_loc: (172,0)-(172,3) = "def" + │ ├── def_keyword_loc: (169,0)-(169,3) = "def" │ ├── operator_loc: ∅ │ ├── lparen_loc: ∅ │ ├── rparen_loc: ∅ │ ├── equal_loc: ∅ - │ └── end_keyword_loc: (172,12)-(172,15) = "end" - ├── @ DefNode (location: (174,0)-(174,15)) + │ └── end_keyword_loc: (169,12)-(169,15) = "end" + ├── @ DefNode (location: (171,0)-(171,15)) │ ├── name: :f - │ ├── name_loc: (174,4)-(174,5) = "f" + │ ├── name_loc: (171,4)-(171,5) = "f" │ ├── receiver: ∅ │ ├── parameters: - │ │ @ ParametersNode (location: (174,6)-(174,10)) + │ │ @ ParametersNode (location: (171,6)-(171,10)) │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) - │ │ │ └── @ OptionalKeywordParameterNode (location: (174,6)-(174,10)) + │ │ │ └── @ OptionalKeywordParameterNode (location: (171,6)-(171,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :x - │ │ │ ├── name_loc: (174,6)-(174,8) = "x:" + │ │ │ ├── name_loc: (171,6)-(171,8) = "x:" │ │ │ └── value: - │ │ │ @ CallNode (location: (174,8)-(174,10)) + │ │ │ @ CallNode (location: (171,8)-(171,10)) │ │ │ ├── flags: ∅ │ │ │ ├── receiver: - │ │ │ │ @ CallNode (location: (174,9)-(174,10)) + │ │ │ │ @ CallNode (location: (171,9)-(171,10)) │ │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :a - │ │ │ │ ├── message_loc: (174,9)-(174,10) = "a" + │ │ │ │ ├── message_loc: (171,9)-(171,10) = "a" │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── arguments: ∅ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :+@ - │ │ │ ├── message_loc: (174,8)-(174,9) = "+" + │ │ │ ├── message_loc: (171,8)-(171,9) = "+" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ @@ -1832,43 +1843,44 @@ │ ├── body: ∅ │ ├── locals: [:x] │ ├── locals_body_index: 1 - │ ├── def_keyword_loc: (174,0)-(174,3) = "def" + │ ├── def_keyword_loc: (171,0)-(171,3) = "def" │ ├── operator_loc: ∅ │ ├── lparen_loc: ∅ │ ├── rparen_loc: ∅ │ ├── equal_loc: ∅ - │ └── end_keyword_loc: (174,12)-(174,15) = "end" - ├── @ DefNode (location: (176,0)-(176,15)) + │ └── end_keyword_loc: (171,12)-(171,15) = "end" + ├── @ DefNode (location: (173,0)-(173,15)) │ ├── name: :f - │ ├── name_loc: (176,4)-(176,5) = "f" + │ ├── name_loc: (173,4)-(173,5) = "f" │ ├── receiver: ∅ │ ├── parameters: - │ │ @ ParametersNode (location: (176,6)-(176,10)) + │ │ @ ParametersNode (location: (173,6)-(173,10)) │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) - │ │ │ └── @ OptionalKeywordParameterNode (location: (176,6)-(176,10)) + │ │ │ └── @ OptionalKeywordParameterNode (location: (173,6)-(173,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :x - │ │ │ ├── name_loc: (176,6)-(176,8) = "x:" + │ │ │ ├── name_loc: (173,6)-(173,8) = "x:" │ │ │ └── value: - │ │ │ @ CallNode (location: (176,8)-(176,10)) + │ │ │ @ CallNode (location: (173,8)-(173,10)) │ │ │ ├── flags: ∅ │ │ │ ├── receiver: - │ │ │ │ @ CallNode (location: (176,9)-(176,10)) + │ │ │ │ @ CallNode (location: (173,9)-(173,10)) │ │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :a - │ │ │ │ ├── message_loc: (176,9)-(176,10) = "a" + │ │ │ │ ├── message_loc: (173,9)-(173,10) = "a" │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── arguments: ∅ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :! - │ │ │ ├── message_loc: (176,8)-(176,9) = "!" + │ │ │ ├── message_loc: (173,8)-(173,9) = "!" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ @@ -1878,107 +1890,110 @@ │ ├── body: ∅ │ ├── locals: [:x] │ ├── locals_body_index: 1 - │ ├── def_keyword_loc: (176,0)-(176,3) = "def" + │ ├── def_keyword_loc: (173,0)-(173,3) = "def" │ ├── operator_loc: ∅ │ ├── lparen_loc: ∅ │ ├── rparen_loc: ∅ │ ├── equal_loc: ∅ - │ └── end_keyword_loc: (176,12)-(176,15) = "end" - ├── @ DefNode (location: (178,0)-(178,20)) + │ └── end_keyword_loc: (173,12)-(173,15) = "end" + ├── @ DefNode (location: (175,0)-(175,20)) │ ├── name: :foo - │ ├── name_loc: (178,4)-(178,7) = "foo" + │ ├── name_loc: (175,4)-(175,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: - │ │ @ ParametersNode (location: (178,8)-(178,15)) + │ │ @ ParametersNode (location: (175,8)-(175,15)) │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) - │ │ │ └── @ OptionalKeywordParameterNode (location: (178,8)-(178,15)) + │ │ │ └── @ OptionalKeywordParameterNode (location: (175,8)-(175,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :x - │ │ │ ├── name_loc: (178,8)-(178,10) = "x:" + │ │ │ ├── name_loc: (175,8)-(175,10) = "x:" │ │ │ └── value: - │ │ │ @ StringNode (location: (178,10)-(178,15)) + │ │ │ @ StringNode (location: (175,10)-(175,15)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (178,10)-(178,12) = "%(" - │ │ │ ├── content_loc: (178,12)-(178,14) = "xx" - │ │ │ ├── closing_loc: (178,14)-(178,15) = ")" + │ │ │ ├── opening_loc: (175,10)-(175,12) = "%(" + │ │ │ ├── content_loc: (175,12)-(175,14) = "xx" + │ │ │ ├── closing_loc: (175,14)-(175,15) = ")" │ │ │ └── unescaped: "xx" │ │ ├── keyword_rest: ∅ │ │ └── block: ∅ │ ├── body: ∅ │ ├── locals: [:x] │ ├── locals_body_index: 1 - │ ├── def_keyword_loc: (178,0)-(178,3) = "def" + │ ├── def_keyword_loc: (175,0)-(175,3) = "def" │ ├── operator_loc: ∅ │ ├── lparen_loc: ∅ │ ├── rparen_loc: ∅ │ ├── equal_loc: ∅ - │ └── end_keyword_loc: (178,17)-(178,20) = "end" - ├── @ DefNode (location: (180,0)-(182,3)) + │ └── end_keyword_loc: (175,17)-(175,20) = "end" + ├── @ DefNode (location: (177,0)-(179,3)) │ ├── name: :foo - │ ├── name_loc: (180,4)-(180,7) = "foo" + │ ├── name_loc: (177,4)-(177,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: - │ │ @ ParametersNode (location: (180,8)-(180,11)) + │ │ @ ParametersNode (location: (177,8)-(177,11)) │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: - │ │ │ @ ForwardingParameterNode (location: (180,8)-(180,11)) + │ │ │ @ ForwardingParameterNode (location: (177,8)-(177,11)) │ │ └── block: ∅ │ ├── body: - │ │ @ StatementsNode (location: (181,2)-(181,7)) + │ │ @ StatementsNode (location: (178,2)-(178,7)) │ │ └── body: (length: 1) - │ │ └── @ CallNode (location: (181,2)-(181,7)) + │ │ └── @ CallNode (location: (178,2)-(178,7)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :bar - │ │ ├── message_loc: (181,2)-(181,5) = "bar" - │ │ ├── opening_loc: (181,5)-(181,6) = "(" + │ │ ├── message_loc: (178,2)-(178,5) = "bar" + │ │ ├── opening_loc: (178,5)-(178,6) = "(" │ │ ├── arguments: ∅ - │ │ ├── closing_loc: (181,7)-(181,8) = ")" + │ │ ├── closing_loc: (178,7)-(178,8) = ")" │ │ └── block: - │ │ @ BlockArgumentNode (location: (181,6)-(181,7)) + │ │ @ BlockArgumentNode (location: (178,6)-(178,7)) │ │ ├── expression: ∅ - │ │ └── operator_loc: (181,6)-(181,7) = "&" + │ │ └── operator_loc: (178,6)-(178,7) = "&" │ ├── locals: [:"..."] │ ├── locals_body_index: 1 - │ ├── def_keyword_loc: (180,0)-(180,3) = "def" + │ ├── def_keyword_loc: (177,0)-(177,3) = "def" │ ├── operator_loc: ∅ - │ ├── lparen_loc: (180,7)-(180,8) = "(" - │ ├── rparen_loc: (180,11)-(180,12) = ")" + │ ├── lparen_loc: (177,7)-(177,8) = "(" + │ ├── rparen_loc: (177,11)-(177,12) = ")" │ ├── equal_loc: ∅ - │ └── end_keyword_loc: (182,0)-(182,3) = "end" - ├── @ DefNode (location: (184,0)-(184,42)) + │ └── end_keyword_loc: (179,0)-(179,3) = "end" + ├── @ DefNode (location: (181,0)-(181,42)) │ ├── name: :foo - │ ├── name_loc: (184,4)-(184,7) = "foo" + │ ├── name_loc: (181,4)-(181,7) = "foo" │ ├── receiver: ∅ │ ├── parameters: - │ │ @ ParametersNode (location: (184,8)-(184,37)) + │ │ @ ParametersNode (location: (181,8)-(181,37)) │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) - │ │ │ └── @ OptionalParameterNode (location: (184,8)-(184,37)) + │ │ │ └── @ OptionalParameterNode (location: (181,8)-(181,37)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar - │ │ │ ├── name_loc: (184,8)-(184,11) = "bar" - │ │ │ ├── operator_loc: (184,12)-(184,13) = "=" + │ │ │ ├── name_loc: (181,8)-(181,11) = "bar" + │ │ │ ├── operator_loc: (181,12)-(181,13) = "=" │ │ │ └── value: - │ │ │ @ ParenthesesNode (location: (184,14)-(184,37)) + │ │ │ @ ParenthesesNode (location: (181,14)-(181,37)) │ │ │ ├── body: - │ │ │ │ @ StatementsNode (location: (184,15)-(184,36)) + │ │ │ │ @ StatementsNode (location: (181,15)-(181,36)) │ │ │ │ └── body: (length: 2) - │ │ │ │ ├── @ DefNode (location: (184,15)-(184,33)) + │ │ │ │ ├── @ DefNode (location: (181,15)-(181,33)) │ │ │ │ │ ├── name: :baz - │ │ │ │ │ ├── name_loc: (184,19)-(184,22) = "baz" + │ │ │ │ │ ├── name_loc: (181,19)-(181,22) = "baz" │ │ │ │ │ ├── receiver: ∅ │ │ │ │ │ ├── parameters: - │ │ │ │ │ │ @ ParametersNode (location: (184,23)-(184,26)) + │ │ │ │ │ │ @ ParametersNode (location: (181,23)-(181,26)) │ │ │ │ │ │ ├── requireds: (length: 1) - │ │ │ │ │ │ │ └── @ RequiredParameterNode (location: (184,23)-(184,26)) + │ │ │ │ │ │ │ └── @ RequiredParameterNode (location: (181,23)-(181,26)) + │ │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ │ └── name: :bar │ │ │ │ │ │ ├── optionals: (length: 0) │ │ │ │ │ │ ├── rest: ∅ @@ -1987,70 +2002,71 @@ │ │ │ │ │ │ ├── keyword_rest: ∅ │ │ │ │ │ │ └── block: ∅ │ │ │ │ │ ├── body: - │ │ │ │ │ │ @ StatementsNode (location: (184,30)-(184,33)) + │ │ │ │ │ │ @ StatementsNode (location: (181,30)-(181,33)) │ │ │ │ │ │ └── body: (length: 1) - │ │ │ │ │ │ └── @ LocalVariableReadNode (location: (184,30)-(184,33)) + │ │ │ │ │ │ └── @ LocalVariableReadNode (location: (181,30)-(181,33)) │ │ │ │ │ │ ├── name: :bar │ │ │ │ │ │ └── depth: 0 │ │ │ │ │ ├── locals: [:bar] │ │ │ │ │ ├── locals_body_index: 1 - │ │ │ │ │ ├── def_keyword_loc: (184,15)-(184,18) = "def" + │ │ │ │ │ ├── def_keyword_loc: (181,15)-(181,18) = "def" │ │ │ │ │ ├── operator_loc: ∅ - │ │ │ │ │ ├── lparen_loc: (184,22)-(184,23) = "(" - │ │ │ │ │ ├── rparen_loc: (184,26)-(184,27) = ")" - │ │ │ │ │ ├── equal_loc: (184,28)-(184,29) = "=" + │ │ │ │ │ ├── lparen_loc: (181,22)-(181,23) = "(" + │ │ │ │ │ ├── rparen_loc: (181,26)-(181,27) = ")" + │ │ │ │ │ ├── equal_loc: (181,28)-(181,29) = "=" │ │ │ │ │ └── end_keyword_loc: ∅ - │ │ │ │ └── @ IntegerNode (location: (184,35)-(184,36)) + │ │ │ │ └── @ IntegerNode (location: (181,35)-(181,36)) │ │ │ │ └── flags: decimal - │ │ │ ├── opening_loc: (184,14)-(184,15) = "(" - │ │ │ └── closing_loc: (184,36)-(184,37) = ")" + │ │ │ ├── opening_loc: (181,14)-(181,15) = "(" + │ │ │ └── closing_loc: (181,36)-(181,37) = ")" │ │ ├── rest: ∅ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ │ │ └── block: ∅ │ ├── body: - │ │ @ StatementsNode (location: (184,41)-(184,42)) + │ │ @ StatementsNode (location: (181,41)-(181,42)) │ │ └── body: (length: 1) - │ │ └── @ IntegerNode (location: (184,41)-(184,42)) + │ │ └── @ IntegerNode (location: (181,41)-(181,42)) │ │ └── flags: decimal │ ├── locals: [:bar] │ ├── locals_body_index: 1 - │ ├── def_keyword_loc: (184,0)-(184,3) = "def" + │ ├── def_keyword_loc: (181,0)-(181,3) = "def" │ ├── operator_loc: ∅ - │ ├── lparen_loc: (184,7)-(184,8) = "(" - │ ├── rparen_loc: (184,37)-(184,38) = ")" - │ ├── equal_loc: (184,39)-(184,40) = "=" + │ ├── lparen_loc: (181,7)-(181,8) = "(" + │ ├── rparen_loc: (181,37)-(181,38) = ")" + │ ├── equal_loc: (181,39)-(181,40) = "=" │ └── end_keyword_loc: ∅ - └── @ DefNode (location: (186,0)-(186,37)) + └── @ DefNode (location: (183,0)-(183,37)) ├── name: :foo - ├── name_loc: (186,21)-(186,24) = "foo" + ├── name_loc: (183,21)-(183,24) = "foo" ├── receiver: - │ @ ParenthesesNode (location: (186,4)-(186,20)) + │ @ ParenthesesNode (location: (183,4)-(183,20)) │ ├── body: - │ │ @ ClassNode (location: (186,5)-(186,19)) + │ │ @ ClassNode (location: (183,5)-(183,19)) │ │ ├── locals: [] - │ │ ├── class_keyword_loc: (186,5)-(186,10) = "class" + │ │ ├── class_keyword_loc: (183,5)-(183,10) = "class" │ │ ├── constant_path: - │ │ │ @ ConstantReadNode (location: (186,11)-(186,14)) + │ │ │ @ ConstantReadNode (location: (183,11)-(183,14)) │ │ │ └── name: :Foo │ │ ├── inheritance_operator_loc: ∅ │ │ ├── superclass: ∅ │ │ ├── body: ∅ - │ │ ├── end_keyword_loc: (186,16)-(186,19) = "end" + │ │ ├── end_keyword_loc: (183,16)-(183,19) = "end" │ │ └── name: :Foo - │ ├── opening_loc: (186,4)-(186,5) = "(" - │ └── closing_loc: (186,19)-(186,20) = ")" + │ ├── opening_loc: (183,4)-(183,5) = "(" + │ └── closing_loc: (183,19)-(183,20) = ")" ├── parameters: - │ @ ParametersNode (location: (186,25)-(186,32)) + │ @ ParametersNode (location: (183,25)-(183,32)) │ ├── requireds: (length: 0) │ ├── optionals: (length: 1) - │ │ └── @ OptionalParameterNode (location: (186,25)-(186,32)) + │ │ └── @ OptionalParameterNode (location: (183,25)-(183,32)) + │ │ ├── flags: ∅ │ │ ├── name: :bar - │ │ ├── name_loc: (186,25)-(186,28) = "bar" - │ │ ├── operator_loc: (186,29)-(186,30) = "=" + │ │ ├── name_loc: (183,25)-(183,28) = "bar" + │ │ ├── operator_loc: (183,29)-(183,30) = "=" │ │ └── value: - │ │ @ IntegerNode (location: (186,31)-(186,32)) + │ │ @ IntegerNode (location: (183,31)-(183,32)) │ │ └── flags: decimal │ ├── rest: ∅ │ ├── posts: (length: 0) @@ -2058,15 +2074,15 @@ │ ├── keyword_rest: ∅ │ └── block: ∅ ├── body: - │ @ StatementsNode (location: (186,36)-(186,37)) + │ @ StatementsNode (location: (183,36)-(183,37)) │ └── body: (length: 1) - │ └── @ IntegerNode (location: (186,36)-(186,37)) + │ └── @ IntegerNode (location: (183,36)-(183,37)) │ └── flags: decimal ├── locals: [:bar] ├── locals_body_index: 1 - ├── def_keyword_loc: (186,0)-(186,3) = "def" - ├── operator_loc: (186,20)-(186,21) = "." - ├── lparen_loc: (186,24)-(186,25) = "(" - ├── rparen_loc: (186,32)-(186,33) = ")" - ├── equal_loc: (186,34)-(186,35) = "=" + ├── def_keyword_loc: (183,0)-(183,3) = "def" + ├── operator_loc: (183,20)-(183,21) = "." + ├── lparen_loc: (183,24)-(183,25) = "(" + ├── rparen_loc: (183,32)-(183,33) = ")" + ├── equal_loc: (183,34)-(183,35) = "=" └── end_keyword_loc: ∅ diff --git a/test/prism/snapshots/non_alphanumeric_methods.txt b/test/prism/snapshots/non_alphanumeric_methods.txt index cbd024e4ecef75..21bec6eff306a6 100644 --- a/test/prism/snapshots/non_alphanumeric_methods.txt +++ b/test/prism/snapshots/non_alphanumeric_methods.txt @@ -135,6 +135,7 @@ │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: │ │ │ @ KeywordRestParameterNode (location: (27,6)-(27,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (27,8)-(27,9) = "b" │ │ │ └── operator_loc: (27,6)-(27,8) = "**" @@ -170,6 +171,7 @@ │ │ @ ParametersNode (location: (33,6)-(33,7)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (33,6)-(33,7)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :b │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/procs.txt b/test/prism/snapshots/procs.txt index 1060fb54f40348..31ae6ece5bdda6 100644 --- a/test/prism/snapshots/procs.txt +++ b/test/prism/snapshots/procs.txt @@ -15,6 +15,7 @@ │ │ │ @ ParametersNode (location: (1,4)-(1,5)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,4)-(1,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -24,10 +25,13 @@ │ │ │ └── block: ∅ │ │ ├── locals: (length: 3) │ │ │ ├── @ BlockLocalVariableNode (location: (1,7)-(1,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── @ BlockLocalVariableNode (location: (1,10)-(1,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :c │ │ │ └── @ BlockLocalVariableNode (location: (1,13)-(1,14)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :d │ │ ├── opening_loc: (1,3)-(1,4) = "(" │ │ └── closing_loc: (1,14)-(1,15) = ")" @@ -138,9 +142,11 @@ │ │ │ @ ParametersNode (location: (17,3)-(17,23)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (17,3)-(17,4)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 1) │ │ │ │ └── @ OptionalParameterNode (location: (17,6)-(17,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :b │ │ │ │ ├── name_loc: (17,6)-(17,7) = "b" │ │ │ │ ├── operator_loc: (17,8)-(17,9) = "=" @@ -151,14 +157,17 @@ │ │ │ ├── posts: (length: 0) │ │ │ ├── keywords: (length: 2) │ │ │ │ ├── @ RequiredKeywordParameterNode (location: (17,13)-(17,15)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── name: :c │ │ │ │ │ └── name_loc: (17,13)-(17,15) = "c:" │ │ │ │ └── @ RequiredKeywordParameterNode (location: (17,17)-(17,19)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :d │ │ │ │ └── name_loc: (17,17)-(17,19) = "d:" │ │ │ ├── keyword_rest: ∅ │ │ │ └── block: │ │ │ @ BlockParameterNode (location: (17,21)-(17,23)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :e │ │ │ ├── name_loc: (17,22)-(17,23) = "e" │ │ │ └── operator_loc: (17,21)-(17,22) = "&" @@ -183,9 +192,11 @@ │ │ │ @ ParametersNode (location: (19,4)-(19,33)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (19,4)-(19,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 1) │ │ │ │ └── @ OptionalParameterNode (location: (19,7)-(19,12)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :b │ │ │ │ ├── name_loc: (19,7)-(19,8) = "b" │ │ │ │ ├── operator_loc: (19,9)-(19,10) = "=" @@ -194,24 +205,29 @@ │ │ │ │ └── flags: decimal │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (19,14)-(19,16)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :c │ │ │ │ ├── name_loc: (19,15)-(19,16) = "c" │ │ │ │ └── operator_loc: (19,14)-(19,15) = "*" │ │ │ ├── posts: (length: 0) │ │ │ ├── keywords: (length: 2) │ │ │ │ ├── @ RequiredKeywordParameterNode (location: (19,18)-(19,20)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── name: :d │ │ │ │ │ └── name_loc: (19,18)-(19,20) = "d:" │ │ │ │ └── @ RequiredKeywordParameterNode (location: (19,22)-(19,24)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :e │ │ │ │ └── name_loc: (19,22)-(19,24) = "e:" │ │ │ ├── keyword_rest: │ │ │ │ @ KeywordRestParameterNode (location: (19,26)-(19,29)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :f │ │ │ │ ├── name_loc: (19,28)-(19,29) = "f" │ │ │ │ └── operator_loc: (19,26)-(19,28) = "**" │ │ │ └── block: │ │ │ @ BlockParameterNode (location: (19,31)-(19,33)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :g │ │ │ ├── name_loc: (19,32)-(19,33) = "g" │ │ │ └── operator_loc: (19,31)-(19,32) = "&" @@ -236,9 +252,11 @@ │ │ │ @ ParametersNode (location: (21,4)-(21,33)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (21,4)-(21,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 1) │ │ │ │ └── @ OptionalParameterNode (location: (21,7)-(21,12)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :b │ │ │ │ ├── name_loc: (21,7)-(21,8) = "b" │ │ │ │ ├── operator_loc: (21,9)-(21,10) = "=" @@ -247,24 +265,29 @@ │ │ │ │ └── flags: decimal │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (21,14)-(21,16)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :c │ │ │ │ ├── name_loc: (21,15)-(21,16) = "c" │ │ │ │ └── operator_loc: (21,14)-(21,15) = "*" │ │ │ ├── posts: (length: 0) │ │ │ ├── keywords: (length: 2) │ │ │ │ ├── @ RequiredKeywordParameterNode (location: (21,18)-(21,20)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── name: :d │ │ │ │ │ └── name_loc: (21,18)-(21,20) = "d:" │ │ │ │ └── @ RequiredKeywordParameterNode (location: (21,22)-(21,24)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :e │ │ │ │ └── name_loc: (21,22)-(21,24) = "e:" │ │ │ ├── keyword_rest: │ │ │ │ @ KeywordRestParameterNode (location: (21,26)-(21,29)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :f │ │ │ │ ├── name_loc: (21,28)-(21,29) = "f" │ │ │ │ └── operator_loc: (21,26)-(21,28) = "**" │ │ │ └── block: │ │ │ @ BlockParameterNode (location: (21,31)-(21,33)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :g │ │ │ ├── name_loc: (21,32)-(21,33) = "g" │ │ │ └── operator_loc: (21,31)-(21,32) = "&" @@ -289,6 +312,7 @@ │ │ │ @ ParametersNode (location: (25,4)-(25,5)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (25,4)-(25,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -314,6 +338,7 @@ │ │ │ @ ParametersNode (location: (25,12)-(25,13)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (25,12)-(25,13)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -360,8 +385,10 @@ │ │ │ └── @ MultiTargetNode (location: (27,4)-(27,10)) │ │ │ ├── lefts: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (27,5)-(27,6)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :a │ │ │ │ └── @ RequiredParameterNode (location: (27,8)-(27,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── rest: ∅ │ │ │ ├── rights: (length: 0) @@ -370,6 +397,7 @@ │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (27,12)-(27,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ ├── name_loc: (27,13)-(27,14) = "c" │ │ │ └── operator_loc: (27,12)-(27,13) = "*" diff --git a/test/prism/snapshots/repeat_parameters.txt b/test/prism/snapshots/repeat_parameters.txt new file mode 100644 index 00000000000000..f680a2f1b9e9de --- /dev/null +++ b/test/prism/snapshots/repeat_parameters.txt @@ -0,0 +1,482 @@ +@ ProgramNode (location: (1,0)-(38,3)) +├── locals: [] +└── statements: + @ StatementsNode (location: (1,0)-(38,3)) + └── body: (length: 13) + ├── @ DefNode (location: (1,0)-(2,3)) + │ ├── name: :foo + │ ├── name_loc: (1,4)-(1,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (1,8)-(1,12)) + │ │ ├── requireds: (length: 2) + │ │ │ ├── @ RequiredParameterNode (location: (1,8)-(1,9)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :a + │ │ │ └── @ RequiredParameterNode (location: (1,11)-(1,12)) + │ │ │ ├── flags: ∅ + │ │ │ └── name: :_ + │ │ ├── optionals: (length: 0) + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: ∅ + │ │ └── block: ∅ + │ ├── body: ∅ + │ ├── locals: [:a, :_] + │ ├── locals_body_index: 2 + │ ├── def_keyword_loc: (1,0)-(1,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (1,7)-(1,8) = "(" + │ ├── rparen_loc: (1,12)-(1,13) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (2,0)-(2,3) = "end" + ├── @ DefNode (location: (4,0)-(5,3)) + │ ├── name: :foo + │ ├── name_loc: (4,4)-(4,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (4,8)-(4,15)) + │ │ ├── requireds: (length: 3) + │ │ │ ├── @ RequiredParameterNode (location: (4,8)-(4,9)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :a + │ │ │ ├── @ RequiredParameterNode (location: (4,11)-(4,12)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :_ + │ │ │ └── @ RequiredParameterNode (location: (4,14)-(4,15)) + │ │ │ ├── flags: repeated_parameter + │ │ │ └── name: :_ + │ │ ├── optionals: (length: 0) + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: ∅ + │ │ └── block: ∅ + │ ├── body: ∅ + │ ├── locals: [:a, :_] + │ ├── locals_body_index: 2 + │ ├── def_keyword_loc: (4,0)-(4,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (4,7)-(4,8) = "(" + │ ├── rparen_loc: (4,15)-(4,16) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (5,0)-(5,3) = "end" + ├── @ DefNode (location: (7,0)-(8,3)) + │ ├── name: :foo + │ ├── name_loc: (7,4)-(7,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (7,8)-(7,19)) + │ │ ├── requireds: (length: 4) + │ │ │ ├── @ RequiredParameterNode (location: (7,8)-(7,9)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :a + │ │ │ ├── @ RequiredParameterNode (location: (7,11)-(7,12)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :_ + │ │ │ ├── @ RequiredParameterNode (location: (7,14)-(7,15)) + │ │ │ │ ├── flags: repeated_parameter + │ │ │ │ └── name: :_ + │ │ │ └── @ RequiredParameterNode (location: (7,17)-(7,19)) + │ │ │ ├── flags: ∅ + │ │ │ └── name: :_b + │ │ ├── optionals: (length: 0) + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: ∅ + │ │ └── block: ∅ + │ ├── body: ∅ + │ ├── locals: [:a, :_, :_b] + │ ├── locals_body_index: 3 + │ ├── def_keyword_loc: (7,0)-(7,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (7,7)-(7,8) = "(" + │ ├── rparen_loc: (7,19)-(7,20) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (8,0)-(8,3) = "end" + ├── @ DefNode (location: (10,0)-(11,3)) + │ ├── name: :foo + │ ├── name_loc: (10,4)-(10,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (10,8)-(10,23)) + │ │ ├── requireds: (length: 5) + │ │ │ ├── @ RequiredParameterNode (location: (10,8)-(10,9)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :a + │ │ │ ├── @ RequiredParameterNode (location: (10,11)-(10,12)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :_ + │ │ │ ├── @ RequiredParameterNode (location: (10,14)-(10,15)) + │ │ │ │ ├── flags: repeated_parameter + │ │ │ │ └── name: :_ + │ │ │ ├── @ RequiredParameterNode (location: (10,17)-(10,19)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :_b + │ │ │ └── @ RequiredParameterNode (location: (10,21)-(10,23)) + │ │ │ ├── flags: repeated_parameter + │ │ │ └── name: :_b + │ │ ├── optionals: (length: 0) + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: ∅ + │ │ └── block: ∅ + │ ├── body: ∅ + │ ├── locals: [:a, :_, :_b] + │ ├── locals_body_index: 3 + │ ├── def_keyword_loc: (10,0)-(10,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (10,7)-(10,8) = "(" + │ ├── rparen_loc: (10,23)-(10,24) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (11,0)-(11,3) = "end" + ├── @ DefNode (location: (13,0)-(14,3)) + │ ├── name: :foo + │ ├── name_loc: (13,4)-(13,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (13,8)-(13,35)) + │ │ ├── requireds: (length: 3) + │ │ │ ├── @ RequiredParameterNode (location: (13,8)-(13,9)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :a + │ │ │ ├── @ MultiTargetNode (location: (13,11)-(13,22)) + │ │ │ │ ├── lefts: (length: 1) + │ │ │ │ │ └── @ RequiredParameterNode (location: (13,12)-(13,13)) + │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ └── name: :b + │ │ │ │ ├── rest: + │ │ │ │ │ @ SplatNode (location: (13,15)-(13,18)) + │ │ │ │ │ ├── operator_loc: (13,15)-(13,16) = "*" + │ │ │ │ │ └── expression: + │ │ │ │ │ @ RequiredParameterNode (location: (13,16)-(13,18)) + │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ └── name: :_c + │ │ │ │ ├── rights: (length: 1) + │ │ │ │ │ └── @ RequiredParameterNode (location: (13,20)-(13,21)) + │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ └── name: :d + │ │ │ │ ├── lparen_loc: (13,11)-(13,12) = "(" + │ │ │ │ └── rparen_loc: (13,21)-(13,22) = ")" + │ │ │ └── @ MultiTargetNode (location: (13,24)-(13,35)) + │ │ │ ├── lefts: (length: 1) + │ │ │ │ └── @ RequiredParameterNode (location: (13,25)-(13,26)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :e + │ │ │ ├── rest: + │ │ │ │ @ SplatNode (location: (13,28)-(13,31)) + │ │ │ │ ├── operator_loc: (13,28)-(13,29) = "*" + │ │ │ │ └── expression: + │ │ │ │ @ RequiredParameterNode (location: (13,29)-(13,31)) + │ │ │ │ ├── flags: repeated_parameter + │ │ │ │ └── name: :_c + │ │ │ ├── rights: (length: 1) + │ │ │ │ └── @ RequiredParameterNode (location: (13,33)-(13,34)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :f + │ │ │ ├── lparen_loc: (13,24)-(13,25) = "(" + │ │ │ └── rparen_loc: (13,34)-(13,35) = ")" + │ │ ├── optionals: (length: 0) + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: ∅ + │ │ └── block: ∅ + │ ├── body: ∅ + │ ├── locals: [:a, :b, :_c, :d, :e, :f] + │ ├── locals_body_index: 6 + │ ├── def_keyword_loc: (13,0)-(13,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (13,7)-(13,8) = "(" + │ ├── rparen_loc: (13,35)-(13,36) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (14,0)-(14,3) = "end" + ├── @ DefNode (location: (16,0)-(17,3)) + │ ├── name: :foo + │ ├── name_loc: (16,4)-(16,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (16,8)-(16,20)) + │ │ ├── requireds: (length: 4) + │ │ │ ├── @ RequiredParameterNode (location: (16,8)-(16,10)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :_a + │ │ │ ├── @ RequiredParameterNode (location: (16,12)-(16,14)) + │ │ │ │ ├── flags: repeated_parameter + │ │ │ │ └── name: :_a + │ │ │ ├── @ RequiredParameterNode (location: (16,16)-(16,17)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :b + │ │ │ └── @ RequiredParameterNode (location: (16,19)-(16,20)) + │ │ │ ├── flags: ∅ + │ │ │ └── name: :c + │ │ ├── optionals: (length: 0) + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: ∅ + │ │ └── block: ∅ + │ ├── body: ∅ + │ ├── locals: [:_a, :b, :c] + │ ├── locals_body_index: 3 + │ ├── def_keyword_loc: (16,0)-(16,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (16,7)-(16,8) = "(" + │ ├── rparen_loc: (16,20)-(16,21) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (17,0)-(17,3) = "end" + ├── @ DefNode (location: (19,0)-(20,3)) + │ ├── name: :foo + │ ├── name_loc: (19,4)-(19,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (19,8)-(19,32)) + │ │ ├── requireds: (length: 2) + │ │ │ ├── @ MultiTargetNode (location: (19,8)-(19,19)) + │ │ │ │ ├── lefts: (length: 1) + │ │ │ │ │ └── @ RequiredParameterNode (location: (19,9)-(19,10)) + │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ └── name: :a + │ │ │ │ ├── rest: + │ │ │ │ │ @ SplatNode (location: (19,12)-(19,15)) + │ │ │ │ │ ├── operator_loc: (19,12)-(19,13) = "*" + │ │ │ │ │ └── expression: + │ │ │ │ │ @ RequiredParameterNode (location: (19,13)-(19,15)) + │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ └── name: :_b + │ │ │ │ ├── rights: (length: 1) + │ │ │ │ │ └── @ RequiredParameterNode (location: (19,17)-(19,18)) + │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ └── name: :c + │ │ │ │ ├── lparen_loc: (19,8)-(19,9) = "(" + │ │ │ │ └── rparen_loc: (19,18)-(19,19) = ")" + │ │ │ └── @ MultiTargetNode (location: (19,21)-(19,32)) + │ │ │ ├── lefts: (length: 1) + │ │ │ │ └── @ RequiredParameterNode (location: (19,22)-(19,23)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :d + │ │ │ ├── rest: + │ │ │ │ @ SplatNode (location: (19,25)-(19,28)) + │ │ │ │ ├── operator_loc: (19,25)-(19,26) = "*" + │ │ │ │ └── expression: + │ │ │ │ @ RequiredParameterNode (location: (19,26)-(19,28)) + │ │ │ │ ├── flags: repeated_parameter + │ │ │ │ └── name: :_b + │ │ │ ├── rights: (length: 1) + │ │ │ │ └── @ RequiredParameterNode (location: (19,30)-(19,31)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── name: :e + │ │ │ ├── lparen_loc: (19,21)-(19,22) = "(" + │ │ │ └── rparen_loc: (19,31)-(19,32) = ")" + │ │ ├── optionals: (length: 0) + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: ∅ + │ │ └── block: ∅ + │ ├── body: ∅ + │ ├── locals: [:a, :_b, :c, :d, :e] + │ ├── locals_body_index: 5 + │ ├── def_keyword_loc: (19,0)-(19,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (19,7)-(19,8) = "(" + │ ├── rparen_loc: (19,32)-(19,33) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (20,0)-(20,3) = "end" + ├── @ DefNode (location: (22,0)-(23,3)) + │ ├── name: :foo + │ ├── name_loc: (22,4)-(22,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (22,8)-(22,22)) + │ │ ├── requireds: (length: 0) + │ │ ├── optionals: (length: 2) + │ │ │ ├── @ OptionalParameterNode (location: (22,8)-(22,14)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── name: :_a + │ │ │ │ ├── name_loc: (22,8)-(22,10) = "_a" + │ │ │ │ ├── operator_loc: (22,11)-(22,12) = "=" + │ │ │ │ └── value: + │ │ │ │ @ IntegerNode (location: (22,13)-(22,14)) + │ │ │ │ └── flags: decimal + │ │ │ └── @ OptionalParameterNode (location: (22,16)-(22,22)) + │ │ │ ├── flags: repeated_parameter + │ │ │ ├── name: :_a + │ │ │ ├── name_loc: (22,16)-(22,18) = "_a" + │ │ │ ├── operator_loc: (22,19)-(22,20) = "=" + │ │ │ └── value: + │ │ │ @ IntegerNode (location: (22,21)-(22,22)) + │ │ │ └── flags: decimal + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: ∅ + │ │ └── block: ∅ + │ ├── body: ∅ + │ ├── locals: [:_a] + │ ├── locals_body_index: 1 + │ ├── def_keyword_loc: (22,0)-(22,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (22,7)-(22,8) = "(" + │ ├── rparen_loc: (22,22)-(22,23) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (23,0)-(23,3) = "end" + ├── @ DefNode (location: (25,0)-(26,3)) + │ ├── name: :foo + │ ├── name_loc: (25,4)-(25,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (25,8)-(25,16)) + │ │ ├── requireds: (length: 0) + │ │ ├── optionals: (length: 0) + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 2) + │ │ │ ├── @ RequiredKeywordParameterNode (location: (25,8)-(25,11)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── name: :_a + │ │ │ │ └── name_loc: (25,8)-(25,11) = "_a:" + │ │ │ └── @ RequiredKeywordParameterNode (location: (25,13)-(25,16)) + │ │ │ ├── flags: repeated_parameter + │ │ │ ├── name: :_a + │ │ │ └── name_loc: (25,13)-(25,16) = "_a:" + │ │ ├── keyword_rest: ∅ + │ │ └── block: ∅ + │ ├── body: ∅ + │ ├── locals: [:_a] + │ ├── locals_body_index: 1 + │ ├── def_keyword_loc: (25,0)-(25,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (25,7)-(25,8) = "(" + │ ├── rparen_loc: (25,16)-(25,17) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (26,0)-(26,3) = "end" + ├── @ DefNode (location: (28,0)-(29,3)) + │ ├── name: :foo + │ ├── name_loc: (28,4)-(28,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (28,8)-(28,20)) + │ │ ├── requireds: (length: 0) + │ │ ├── optionals: (length: 0) + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 2) + │ │ │ ├── @ OptionalKeywordParameterNode (location: (28,8)-(28,13)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── name: :_a + │ │ │ │ ├── name_loc: (28,8)-(28,11) = "_a:" + │ │ │ │ └── value: + │ │ │ │ @ IntegerNode (location: (28,12)-(28,13)) + │ │ │ │ └── flags: decimal + │ │ │ └── @ OptionalKeywordParameterNode (location: (28,15)-(28,20)) + │ │ │ ├── flags: repeated_parameter + │ │ │ ├── name: :_a + │ │ │ ├── name_loc: (28,15)-(28,18) = "_a:" + │ │ │ └── value: + │ │ │ @ IntegerNode (location: (28,19)-(28,20)) + │ │ │ └── flags: decimal + │ │ ├── keyword_rest: ∅ + │ │ └── block: ∅ + │ ├── body: ∅ + │ ├── locals: [:_a] + │ ├── locals_body_index: 1 + │ ├── def_keyword_loc: (28,0)-(28,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (28,7)-(28,8) = "(" + │ ├── rparen_loc: (28,20)-(28,21) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (29,0)-(29,3) = "end" + ├── @ DefNode (location: (31,0)-(32,3)) + │ ├── name: :foo + │ ├── name_loc: (31,4)-(31,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (31,8)-(31,16)) + │ │ ├── requireds: (length: 1) + │ │ │ └── @ RequiredParameterNode (location: (31,8)-(31,10)) + │ │ │ ├── flags: ∅ + │ │ │ └── name: :_a + │ │ ├── optionals: (length: 0) + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: + │ │ │ @ KeywordRestParameterNode (location: (31,12)-(31,16)) + │ │ │ ├── flags: repeated_parameter + │ │ │ ├── name: :_a + │ │ │ ├── name_loc: (31,14)-(31,16) = "_a" + │ │ │ └── operator_loc: (31,12)-(31,14) = "**" + │ │ └── block: ∅ + │ ├── body: ∅ + │ ├── locals: [:_a] + │ ├── locals_body_index: 1 + │ ├── def_keyword_loc: (31,0)-(31,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (31,7)-(31,8) = "(" + │ ├── rparen_loc: (31,16)-(31,17) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (32,0)-(32,3) = "end" + ├── @ DefNode (location: (34,0)-(35,3)) + │ ├── name: :foo + │ ├── name_loc: (34,4)-(34,7) = "foo" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (34,8)-(34,15)) + │ │ ├── requireds: (length: 1) + │ │ │ └── @ RequiredParameterNode (location: (34,8)-(34,10)) + │ │ │ ├── flags: ∅ + │ │ │ └── name: :_a + │ │ ├── optionals: (length: 0) + │ │ ├── rest: ∅ + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: ∅ + │ │ └── block: + │ │ @ BlockParameterNode (location: (34,12)-(34,15)) + │ │ ├── flags: repeated_parameter + │ │ ├── name: :_a + │ │ ├── name_loc: (34,13)-(34,15) = "_a" + │ │ └── operator_loc: (34,12)-(34,13) = "&" + │ ├── body: ∅ + │ ├── locals: [:_a] + │ ├── locals_body_index: 1 + │ ├── def_keyword_loc: (34,0)-(34,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (34,7)-(34,8) = "(" + │ ├── rparen_loc: (34,15)-(34,16) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (35,0)-(35,3) = "end" + └── @ DefNode (location: (37,0)-(38,3)) + ├── name: :foo + ├── name_loc: (37,4)-(37,7) = "foo" + ├── receiver: ∅ + ├── parameters: + │ @ ParametersNode (location: (37,8)-(37,15)) + │ ├── requireds: (length: 1) + │ │ └── @ RequiredParameterNode (location: (37,8)-(37,10)) + │ │ ├── flags: ∅ + │ │ └── name: :_a + │ ├── optionals: (length: 0) + │ ├── rest: + │ │ @ RestParameterNode (location: (37,12)-(37,15)) + │ │ ├── flags: repeated_parameter + │ │ ├── name: :_a + │ │ ├── name_loc: (37,13)-(37,15) = "_a" + │ │ └── operator_loc: (37,12)-(37,13) = "*" + │ ├── posts: (length: 0) + │ ├── keywords: (length: 0) + │ ├── keyword_rest: ∅ + │ └── block: ∅ + ├── body: ∅ + ├── locals: [:_a] + ├── locals_body_index: 1 + ├── def_keyword_loc: (37,0)-(37,3) = "def" + ├── operator_loc: ∅ + ├── lparen_loc: (37,7)-(37,8) = "(" + ├── rparen_loc: (37,15)-(37,16) = ")" + ├── equal_loc: ∅ + └── end_keyword_loc: (38,0)-(38,3) = "end" diff --git a/test/prism/snapshots/rescue.txt b/test/prism/snapshots/rescue.txt index 55ae2f223245f7..f7675ce927d70d 100644 --- a/test/prism/snapshots/rescue.txt +++ b/test/prism/snapshots/rescue.txt @@ -170,6 +170,7 @@ │ │ │ @ ParametersNode (location: (18,8)-(18,9)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (18,8)-(18,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :x │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/TestRubyParserShared.txt b/test/prism/snapshots/seattlerb/TestRubyParserShared.txt index 10e71f786d233d..64030f3aeb023f 100644 --- a/test/prism/snapshots/seattlerb/TestRubyParserShared.txt +++ b/test/prism/snapshots/seattlerb/TestRubyParserShared.txt @@ -134,8 +134,10 @@ │ │ │ @ ParametersNode (location: (52,13)-(53,9)) │ │ │ ├── requireds: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (52,13)-(52,14)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :a │ │ │ │ └── @ RequiredParameterNode (location: (53,8)-(53,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -227,8 +229,10 @@ │ │ │ @ ParametersNode (location: (67,8)-(68,9)) │ │ │ ├── requireds: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (67,8)-(67,9)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :a │ │ │ │ └── @ RequiredParameterNode (location: (68,8)-(68,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/args_kw_block.txt b/test/prism/snapshots/seattlerb/args_kw_block.txt index 538a2691d6dbc7..85a7e856d7bc33 100644 --- a/test/prism/snapshots/seattlerb/args_kw_block.txt +++ b/test/prism/snapshots/seattlerb/args_kw_block.txt @@ -15,6 +15,7 @@ │ ├── posts: (length: 0) │ ├── keywords: (length: 1) │ │ └── @ OptionalKeywordParameterNode (location: (1,6)-(1,10)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ ├── name_loc: (1,6)-(1,8) = "a:" │ │ └── value: @@ -23,6 +24,7 @@ │ ├── keyword_rest: ∅ │ └── block: │ @ BlockParameterNode (location: (1,12)-(1,14)) + │ ├── flags: ∅ │ ├── name: :b │ ├── name_loc: (1,13)-(1,14) = "b" │ └── operator_loc: (1,12)-(1,13) = "&" diff --git a/test/prism/snapshots/seattlerb/block_arg__bare.txt b/test/prism/snapshots/seattlerb/block_arg__bare.txt index 81d5727812b36d..f3b6d3c11cef1a 100644 --- a/test/prism/snapshots/seattlerb/block_arg__bare.txt +++ b/test/prism/snapshots/seattlerb/block_arg__bare.txt @@ -17,6 +17,7 @@ │ ├── keyword_rest: ∅ │ └── block: │ @ BlockParameterNode (location: (1,6)-(1,7)) + │ ├── flags: ∅ │ ├── name: ∅ │ ├── name_loc: ∅ │ └── operator_loc: (1,6)-(1,7) = "&" diff --git a/test/prism/snapshots/seattlerb/block_arg_kwsplat.txt b/test/prism/snapshots/seattlerb/block_arg_kwsplat.txt index bb6b9740a617dd..7429ae06385b47 100644 --- a/test/prism/snapshots/seattlerb/block_arg_kwsplat.txt +++ b/test/prism/snapshots/seattlerb/block_arg_kwsplat.txt @@ -27,6 +27,7 @@ │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: │ │ │ @ KeywordRestParameterNode (location: (1,5)-(1,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (1,7)-(1,8) = "b" │ │ │ └── operator_loc: (1,5)-(1,7) = "**" diff --git a/test/prism/snapshots/seattlerb/block_arg_opt_arg_block.txt b/test/prism/snapshots/seattlerb/block_arg_opt_arg_block.txt index a5b4a6ea9c23fb..a3588b281e76ab 100644 --- a/test/prism/snapshots/seattlerb/block_arg_opt_arg_block.txt +++ b/test/prism/snapshots/seattlerb/block_arg_opt_arg_block.txt @@ -22,9 +22,11 @@ │ │ @ ParametersNode (location: (1,5)-(1,18)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :b │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,8)-(1,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ ├── name_loc: (1,8)-(1,9) = "c" │ │ │ ├── operator_loc: (1,9)-(1,10) = "=" @@ -34,11 +36,13 @@ │ │ ├── rest: ∅ │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,13)-(1,14)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :d │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (1,16)-(1,18)) + │ │ ├── flags: ∅ │ │ ├── name: :e │ │ ├── name_loc: (1,17)-(1,18) = "e" │ │ └── operator_loc: (1,16)-(1,17) = "&" diff --git a/test/prism/snapshots/seattlerb/block_arg_opt_splat.txt b/test/prism/snapshots/seattlerb/block_arg_opt_splat.txt index b1b51ce765fc6c..41d5f0d5e035fd 100644 --- a/test/prism/snapshots/seattlerb/block_arg_opt_splat.txt +++ b/test/prism/snapshots/seattlerb/block_arg_opt_splat.txt @@ -22,9 +22,11 @@ │ │ @ ParametersNode (location: (1,5)-(1,17)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :b │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,8)-(1,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ ├── name_loc: (1,8)-(1,9) = "c" │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" @@ -33,6 +35,7 @@ │ │ │ └── flags: decimal │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,15)-(1,17)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :d │ │ │ ├── name_loc: (1,16)-(1,17) = "d" │ │ │ └── operator_loc: (1,15)-(1,16) = "*" diff --git a/test/prism/snapshots/seattlerb/block_arg_opt_splat_arg_block_omfg.txt b/test/prism/snapshots/seattlerb/block_arg_opt_splat_arg_block_omfg.txt index d16f9f1a7e2e4d..baa5f22523a504 100644 --- a/test/prism/snapshots/seattlerb/block_arg_opt_splat_arg_block_omfg.txt +++ b/test/prism/snapshots/seattlerb/block_arg_opt_splat_arg_block_omfg.txt @@ -22,9 +22,11 @@ │ │ @ ParametersNode (location: (1,5)-(1,22)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :b │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,8)-(1,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ ├── name_loc: (1,8)-(1,9) = "c" │ │ │ ├── operator_loc: (1,9)-(1,10) = "=" @@ -33,16 +35,19 @@ │ │ │ └── flags: decimal │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,13)-(1,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :d │ │ │ ├── name_loc: (1,14)-(1,15) = "d" │ │ │ └── operator_loc: (1,13)-(1,14) = "*" │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,17)-(1,18)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :e │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (1,20)-(1,22)) + │ │ ├── flags: ∅ │ │ ├── name: :f │ │ ├── name_loc: (1,21)-(1,22) = "f" │ │ └── operator_loc: (1,20)-(1,21) = "&" diff --git a/test/prism/snapshots/seattlerb/block_arg_optional.txt b/test/prism/snapshots/seattlerb/block_arg_optional.txt index fd0a988dd7416e..a5dde7ea589940 100644 --- a/test/prism/snapshots/seattlerb/block_arg_optional.txt +++ b/test/prism/snapshots/seattlerb/block_arg_optional.txt @@ -23,6 +23,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,5)-(1,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (1,5)-(1,6) = "b" │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" diff --git a/test/prism/snapshots/seattlerb/block_arg_scope.txt b/test/prism/snapshots/seattlerb/block_arg_scope.txt index 67a57a4ab8488a..e17de7cf31f7bc 100644 --- a/test/prism/snapshots/seattlerb/block_arg_scope.txt +++ b/test/prism/snapshots/seattlerb/block_arg_scope.txt @@ -22,6 +22,7 @@ │ │ @ ParametersNode (location: (1,5)-(1,6)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :b │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -31,6 +32,7 @@ │ │ └── block: ∅ │ ├── locals: (length: 1) │ │ └── @ BlockLocalVariableNode (location: (1,8)-(1,9)) + │ │ ├── flags: ∅ │ │ └── name: :c │ ├── opening_loc: (1,4)-(1,5) = "|" │ └── closing_loc: (1,9)-(1,10) = "|" diff --git a/test/prism/snapshots/seattlerb/block_arg_scope2.txt b/test/prism/snapshots/seattlerb/block_arg_scope2.txt index e9cc9ee3d7d203..b71b8fffb16ccb 100644 --- a/test/prism/snapshots/seattlerb/block_arg_scope2.txt +++ b/test/prism/snapshots/seattlerb/block_arg_scope2.txt @@ -22,6 +22,7 @@ │ │ @ ParametersNode (location: (1,4)-(1,5)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,4)-(1,5)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :b │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -31,8 +32,10 @@ │ │ └── block: ∅ │ ├── locals: (length: 2) │ │ ├── @ BlockLocalVariableNode (location: (1,7)-(1,8)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :c │ │ └── @ BlockLocalVariableNode (location: (1,10)-(1,11)) + │ │ ├── flags: ∅ │ │ └── name: :d │ ├── opening_loc: (1,3)-(1,4) = "|" │ └── closing_loc: (1,11)-(1,12) = "|" diff --git a/test/prism/snapshots/seattlerb/block_arg_splat_arg.txt b/test/prism/snapshots/seattlerb/block_arg_splat_arg.txt index 3670be88e97057..f28af4561a0270 100644 --- a/test/prism/snapshots/seattlerb/block_arg_splat_arg.txt +++ b/test/prism/snapshots/seattlerb/block_arg_splat_arg.txt @@ -22,15 +22,18 @@ │ │ @ ParametersNode (location: (1,5)-(1,13)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :b │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,8)-(1,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ ├── name_loc: (1,9)-(1,10) = "c" │ │ │ └── operator_loc: (1,8)-(1,9) = "*" │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,12)-(1,13)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :d │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ diff --git a/test/prism/snapshots/seattlerb/block_args_kwargs.txt b/test/prism/snapshots/seattlerb/block_args_kwargs.txt index 91233a8f4c3508..16f0e553140e1a 100644 --- a/test/prism/snapshots/seattlerb/block_args_kwargs.txt +++ b/test/prism/snapshots/seattlerb/block_args_kwargs.txt @@ -27,6 +27,7 @@ │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: │ │ │ @ KeywordRestParameterNode (location: (1,5)-(1,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :kwargs │ │ │ ├── name_loc: (1,7)-(1,13) = "kwargs" │ │ │ └── operator_loc: (1,5)-(1,7) = "**" diff --git a/test/prism/snapshots/seattlerb/block_args_opt1.txt b/test/prism/snapshots/seattlerb/block_args_opt1.txt index 524971b7832d01..e7e3fa3ea017d1 100644 --- a/test/prism/snapshots/seattlerb/block_args_opt1.txt +++ b/test/prism/snapshots/seattlerb/block_args_opt1.txt @@ -22,9 +22,11 @@ │ │ @ ParametersNode (location: (1,5)-(1,14)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,8)-(1,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (1,8)-(1,9) = "b" │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" diff --git a/test/prism/snapshots/seattlerb/block_args_opt2.txt b/test/prism/snapshots/seattlerb/block_args_opt2.txt index c31456c2c74f27..3b1db514a0240c 100644 --- a/test/prism/snapshots/seattlerb/block_args_opt2.txt +++ b/test/prism/snapshots/seattlerb/block_args_opt2.txt @@ -23,6 +23,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 2) │ │ │ ├── @ OptionalParameterNode (location: (1,6)-(1,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :b │ │ │ │ ├── name_loc: (1,6)-(1,7) = "b" │ │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" @@ -30,6 +31,7 @@ │ │ │ │ @ IntegerNode (location: (1,8)-(1,9)) │ │ │ │ └── flags: decimal │ │ │ └── @ OptionalParameterNode (location: (1,11)-(1,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ ├── name_loc: (1,11)-(1,12) = "c" │ │ │ ├── operator_loc: (1,12)-(1,13) = "=" diff --git a/test/prism/snapshots/seattlerb/block_args_opt2_2.txt b/test/prism/snapshots/seattlerb/block_args_opt2_2.txt index 530d14404e5234..05c9e3cf8d4091 100644 --- a/test/prism/snapshots/seattlerb/block_args_opt2_2.txt +++ b/test/prism/snapshots/seattlerb/block_args_opt2_2.txt @@ -22,9 +22,11 @@ │ │ @ ParametersNode (location: (1,5)-(1,22)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 2) │ │ │ ├── @ OptionalParameterNode (location: (1,8)-(1,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :b │ │ │ │ ├── name_loc: (1,8)-(1,9) = "b" │ │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" @@ -32,6 +34,7 @@ │ │ │ │ @ IntegerNode (location: (1,12)-(1,14)) │ │ │ │ └── flags: decimal │ │ │ └── @ OptionalParameterNode (location: (1,16)-(1,22)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ ├── name_loc: (1,16)-(1,17) = "c" │ │ │ ├── operator_loc: (1,18)-(1,19) = "=" diff --git a/test/prism/snapshots/seattlerb/block_args_opt3.txt b/test/prism/snapshots/seattlerb/block_args_opt3.txt index d21aa4e53568a7..b0f3dfef77cb11 100644 --- a/test/prism/snapshots/seattlerb/block_args_opt3.txt +++ b/test/prism/snapshots/seattlerb/block_args_opt3.txt @@ -22,9 +22,11 @@ │ │ @ ParametersNode (location: (1,5)-(1,26)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 2) │ │ │ ├── @ OptionalParameterNode (location: (1,8)-(1,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :b │ │ │ │ ├── name_loc: (1,8)-(1,9) = "b" │ │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" @@ -32,6 +34,7 @@ │ │ │ │ @ IntegerNode (location: (1,12)-(1,14)) │ │ │ │ └── flags: decimal │ │ │ └── @ OptionalParameterNode (location: (1,16)-(1,22)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ ├── name_loc: (1,16)-(1,17) = "c" │ │ │ ├── operator_loc: (1,18)-(1,19) = "=" @@ -44,6 +47,7 @@ │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (1,24)-(1,26)) + │ │ ├── flags: ∅ │ │ ├── name: :d │ │ ├── name_loc: (1,25)-(1,26) = "d" │ │ └── operator_loc: (1,24)-(1,25) = "&" diff --git a/test/prism/snapshots/seattlerb/block_break.txt b/test/prism/snapshots/seattlerb/block_break.txt index beaf322ca7ae6b..063d6b501451cf 100644 --- a/test/prism/snapshots/seattlerb/block_break.txt +++ b/test/prism/snapshots/seattlerb/block_break.txt @@ -40,6 +40,7 @@ │ │ │ @ ParametersNode (location: (1,18)-(1,21)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,18)-(1,21)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :bar │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/block_call_defn_call_block_call.txt b/test/prism/snapshots/seattlerb/block_call_defn_call_block_call.txt index 0bcbe473cdb0ce..6e3cb97b72503b 100644 --- a/test/prism/snapshots/seattlerb/block_call_defn_call_block_call.txt +++ b/test/prism/snapshots/seattlerb/block_call_defn_call_block_call.txt @@ -22,6 +22,7 @@ │ │ │ @ ParametersNode (location: (1,8)-(1,9)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,8)-(1,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :c │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/block_call_dot_op2_brace_block.txt b/test/prism/snapshots/seattlerb/block_call_dot_op2_brace_block.txt index 47360ddd0390b4..79c39dbec97fa5 100644 --- a/test/prism/snapshots/seattlerb/block_call_dot_op2_brace_block.txt +++ b/test/prism/snapshots/seattlerb/block_call_dot_op2_brace_block.txt @@ -74,6 +74,7 @@ │ │ @ ParametersNode (location: (1,23)-(1,24)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,23)-(1,24)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :f │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/block_call_dot_op2_cmd_args_do_block.txt b/test/prism/snapshots/seattlerb/block_call_dot_op2_cmd_args_do_block.txt index 4c72b78ff8762c..2f1f72525ab01a 100644 --- a/test/prism/snapshots/seattlerb/block_call_dot_op2_cmd_args_do_block.txt +++ b/test/prism/snapshots/seattlerb/block_call_dot_op2_cmd_args_do_block.txt @@ -87,6 +87,7 @@ │ │ @ ParametersNode (location: (1,25)-(1,26)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,25)-(1,26)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :g │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/block_decomp_anon_splat_arg.txt b/test/prism/snapshots/seattlerb/block_decomp_anon_splat_arg.txt index 8b02d32e05045d..be0081deea1ef2 100644 --- a/test/prism/snapshots/seattlerb/block_decomp_anon_splat_arg.txt +++ b/test/prism/snapshots/seattlerb/block_decomp_anon_splat_arg.txt @@ -29,6 +29,7 @@ │ │ │ │ └── expression: ∅ │ │ │ ├── rights: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,9)-(1,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── lparen_loc: (1,5)-(1,6) = "(" │ │ │ └── rparen_loc: (1,10)-(1,11) = ")" diff --git a/test/prism/snapshots/seattlerb/block_decomp_arg_splat.txt b/test/prism/snapshots/seattlerb/block_decomp_arg_splat.txt index 7c9783f695e32b..b7a45492b4d5bc 100644 --- a/test/prism/snapshots/seattlerb/block_decomp_arg_splat.txt +++ b/test/prism/snapshots/seattlerb/block_decomp_arg_splat.txt @@ -24,6 +24,7 @@ │ │ │ └── @ MultiTargetNode (location: (1,5)-(1,11)) │ │ │ ├── lefts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,6)-(1,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (1,9)-(1,10)) diff --git a/test/prism/snapshots/seattlerb/block_decomp_arg_splat_arg.txt b/test/prism/snapshots/seattlerb/block_decomp_arg_splat_arg.txt index d5a8d7cbacc802..6b72016b6fd08b 100644 --- a/test/prism/snapshots/seattlerb/block_decomp_arg_splat_arg.txt +++ b/test/prism/snapshots/seattlerb/block_decomp_arg_splat_arg.txt @@ -24,15 +24,18 @@ │ │ │ └── @ MultiTargetNode (location: (1,5)-(1,15)) │ │ │ ├── lefts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,6)-(1,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (1,9)-(1,11)) │ │ │ │ ├── operator_loc: (1,9)-(1,10) = "*" │ │ │ │ └── expression: │ │ │ │ @ RequiredParameterNode (location: (1,10)-(1,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── rights: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,13)-(1,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :c │ │ │ ├── lparen_loc: (1,5)-(1,6) = "(" │ │ │ └── rparen_loc: (1,14)-(1,15) = ")" diff --git a/test/prism/snapshots/seattlerb/block_decomp_splat.txt b/test/prism/snapshots/seattlerb/block_decomp_splat.txt index cc41dd84acb649..91cd1fa2dd264e 100644 --- a/test/prism/snapshots/seattlerb/block_decomp_splat.txt +++ b/test/prism/snapshots/seattlerb/block_decomp_splat.txt @@ -28,6 +28,7 @@ │ │ │ │ ├── operator_loc: (1,6)-(1,7) = "*" │ │ │ │ └── expression: │ │ │ │ @ RequiredParameterNode (location: (1,7)-(1,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── rights: (length: 0) │ │ │ ├── lparen_loc: (1,5)-(1,6) = "(" diff --git a/test/prism/snapshots/seattlerb/block_kw.txt b/test/prism/snapshots/seattlerb/block_kw.txt index 344793c40dc4ae..3a73f0ec7d6e0a 100644 --- a/test/prism/snapshots/seattlerb/block_kw.txt +++ b/test/prism/snapshots/seattlerb/block_kw.txt @@ -26,6 +26,7 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) │ │ │ └── @ OptionalKeywordParameterNode (location: (1,8)-(1,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :k │ │ │ ├── name_loc: (1,8)-(1,10) = "k:" │ │ │ └── value: diff --git a/test/prism/snapshots/seattlerb/block_kw__required.txt b/test/prism/snapshots/seattlerb/block_kw__required.txt index 0a4c5e72e93252..d314cc5c70defc 100644 --- a/test/prism/snapshots/seattlerb/block_kw__required.txt +++ b/test/prism/snapshots/seattlerb/block_kw__required.txt @@ -26,6 +26,7 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) │ │ │ └── @ RequiredKeywordParameterNode (location: (1,9)-(1,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :k │ │ │ └── name_loc: (1,9)-(1,11) = "k:" │ │ ├── keyword_rest: ∅ diff --git a/test/prism/snapshots/seattlerb/block_kwarg_lvar.txt b/test/prism/snapshots/seattlerb/block_kwarg_lvar.txt index f41cb228aea024..05c6c9c323b4c5 100644 --- a/test/prism/snapshots/seattlerb/block_kwarg_lvar.txt +++ b/test/prism/snapshots/seattlerb/block_kwarg_lvar.txt @@ -26,6 +26,7 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) │ │ │ └── @ OptionalKeywordParameterNode (location: (1,6)-(1,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :kw │ │ │ ├── name_loc: (1,6)-(1,9) = "kw:" │ │ │ └── value: diff --git a/test/prism/snapshots/seattlerb/block_kwarg_lvar_multiple.txt b/test/prism/snapshots/seattlerb/block_kwarg_lvar_multiple.txt index c353854a048de6..a05ca0c380032e 100644 --- a/test/prism/snapshots/seattlerb/block_kwarg_lvar_multiple.txt +++ b/test/prism/snapshots/seattlerb/block_kwarg_lvar_multiple.txt @@ -26,6 +26,7 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 2) │ │ │ ├── @ OptionalKeywordParameterNode (location: (1,6)-(1,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :kw │ │ │ │ ├── name_loc: (1,6)-(1,9) = "kw:" │ │ │ │ └── value: @@ -36,6 +37,7 @@ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "val" │ │ │ └── @ OptionalKeywordParameterNode (location: (1,16)-(1,26)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :kw2 │ │ │ ├── name_loc: (1,16)-(1,20) = "kw2:" │ │ │ └── value: diff --git a/test/prism/snapshots/seattlerb/block_next.txt b/test/prism/snapshots/seattlerb/block_next.txt index d43e301412b42e..5c3cc4c2a6cd92 100644 --- a/test/prism/snapshots/seattlerb/block_next.txt +++ b/test/prism/snapshots/seattlerb/block_next.txt @@ -40,6 +40,7 @@ │ │ │ @ ParametersNode (location: (1,17)-(1,20)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,17)-(1,20)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :bar │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/block_opt_arg.txt b/test/prism/snapshots/seattlerb/block_opt_arg.txt index 9a0539458c25de..38f678ab822678 100644 --- a/test/prism/snapshots/seattlerb/block_opt_arg.txt +++ b/test/prism/snapshots/seattlerb/block_opt_arg.txt @@ -23,6 +23,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,5)-(1,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (1,5)-(1,6) = "b" │ │ │ ├── operator_loc: (1,6)-(1,7) = "=" @@ -32,6 +33,7 @@ │ │ ├── rest: ∅ │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,10)-(1,11)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :c │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ diff --git a/test/prism/snapshots/seattlerb/block_opt_splat.txt b/test/prism/snapshots/seattlerb/block_opt_splat.txt index 9cc74fda4c77e4..f0182c9cc1031b 100644 --- a/test/prism/snapshots/seattlerb/block_opt_splat.txt +++ b/test/prism/snapshots/seattlerb/block_opt_splat.txt @@ -23,6 +23,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,5)-(1,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (1,5)-(1,6) = "b" │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" @@ -31,6 +32,7 @@ │ │ │ └── flags: decimal │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,12)-(1,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ ├── name_loc: (1,13)-(1,14) = "c" │ │ │ └── operator_loc: (1,12)-(1,13) = "*" diff --git a/test/prism/snapshots/seattlerb/block_opt_splat_arg_block_omfg.txt b/test/prism/snapshots/seattlerb/block_opt_splat_arg_block_omfg.txt index ca0b2414eab04c..48d8d3e4f20ebe 100644 --- a/test/prism/snapshots/seattlerb/block_opt_splat_arg_block_omfg.txt +++ b/test/prism/snapshots/seattlerb/block_opt_splat_arg_block_omfg.txt @@ -23,6 +23,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,5)-(1,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (1,5)-(1,6) = "b" │ │ │ ├── operator_loc: (1,6)-(1,7) = "=" @@ -31,16 +32,19 @@ │ │ │ └── flags: decimal │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,10)-(1,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ ├── name_loc: (1,11)-(1,12) = "c" │ │ │ └── operator_loc: (1,10)-(1,11) = "*" │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,14)-(1,15)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :d │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (1,17)-(1,19)) + │ │ ├── flags: ∅ │ │ ├── name: :e │ │ ├── name_loc: (1,18)-(1,19) = "e" │ │ └── operator_loc: (1,17)-(1,18) = "&" diff --git a/test/prism/snapshots/seattlerb/block_optarg.txt b/test/prism/snapshots/seattlerb/block_optarg.txt index 5e63cc3636d552..3328ee30e3ed78 100644 --- a/test/prism/snapshots/seattlerb/block_optarg.txt +++ b/test/prism/snapshots/seattlerb/block_optarg.txt @@ -23,6 +23,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,5)-(1,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (1,5)-(1,6) = "b" │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" diff --git a/test/prism/snapshots/seattlerb/block_paren_splat.txt b/test/prism/snapshots/seattlerb/block_paren_splat.txt index e17dc52702cc4b..5426cad0a36369 100644 --- a/test/prism/snapshots/seattlerb/block_paren_splat.txt +++ b/test/prism/snapshots/seattlerb/block_paren_splat.txt @@ -24,12 +24,14 @@ │ │ │ └── @ MultiTargetNode (location: (1,5)-(1,12)) │ │ │ ├── lefts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,6)-(1,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (1,9)-(1,11)) │ │ │ │ ├── operator_loc: (1,9)-(1,10) = "*" │ │ │ │ └── expression: │ │ │ │ @ RequiredParameterNode (location: (1,10)-(1,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :c │ │ │ ├── rights: (length: 0) │ │ │ ├── lparen_loc: (1,5)-(1,6) = "(" diff --git a/test/prism/snapshots/seattlerb/block_reg_optarg.txt b/test/prism/snapshots/seattlerb/block_reg_optarg.txt index 8a43bec7d0f598..47d19852002ed8 100644 --- a/test/prism/snapshots/seattlerb/block_reg_optarg.txt +++ b/test/prism/snapshots/seattlerb/block_reg_optarg.txt @@ -22,9 +22,11 @@ │ │ @ ParametersNode (location: (1,5)-(1,14)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :b │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,8)-(1,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ ├── name_loc: (1,8)-(1,9) = "c" │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" diff --git a/test/prism/snapshots/seattlerb/block_return.txt b/test/prism/snapshots/seattlerb/block_return.txt index 32f24f3312b504..7d9e29036acd7b 100644 --- a/test/prism/snapshots/seattlerb/block_return.txt +++ b/test/prism/snapshots/seattlerb/block_return.txt @@ -41,6 +41,7 @@ │ │ @ ParametersNode (location: (1,19)-(1,22)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,19)-(1,22)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :bar │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/block_scope.txt b/test/prism/snapshots/seattlerb/block_scope.txt index f84212af5d4650..6537393872a9d9 100644 --- a/test/prism/snapshots/seattlerb/block_scope.txt +++ b/test/prism/snapshots/seattlerb/block_scope.txt @@ -21,6 +21,7 @@ │ ├── parameters: ∅ │ ├── locals: (length: 1) │ │ └── @ BlockLocalVariableNode (location: (1,6)-(1,7)) + │ │ ├── flags: ∅ │ │ └── name: :b │ ├── opening_loc: (1,4)-(1,5) = "|" │ └── closing_loc: (1,7)-(1,8) = "|" diff --git a/test/prism/snapshots/seattlerb/block_splat_reg.txt b/test/prism/snapshots/seattlerb/block_splat_reg.txt index 7ea8f5d05ccbd6..47d3b694633399 100644 --- a/test/prism/snapshots/seattlerb/block_splat_reg.txt +++ b/test/prism/snapshots/seattlerb/block_splat_reg.txt @@ -24,11 +24,13 @@ │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,5)-(1,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (1,6)-(1,7) = "b" │ │ │ └── operator_loc: (1,5)-(1,6) = "*" │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,9)-(1,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :c │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ diff --git a/test/prism/snapshots/seattlerb/bug236.txt b/test/prism/snapshots/seattlerb/bug236.txt index b5815e152e1ba7..07ec809bd1e82a 100644 --- a/test/prism/snapshots/seattlerb/bug236.txt +++ b/test/prism/snapshots/seattlerb/bug236.txt @@ -22,6 +22,7 @@ │ │ │ @ ParametersNode (location: (1,3)-(1,5)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,3)-(1,4)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: @@ -55,6 +56,7 @@ │ │ @ ParametersNode (location: (3,3)-(3,4)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (3,3)-(3,4)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/bug_args__19.txt b/test/prism/snapshots/seattlerb/bug_args__19.txt index 92b1628c469be1..ec17de9a2e217b 100644 --- a/test/prism/snapshots/seattlerb/bug_args__19.txt +++ b/test/prism/snapshots/seattlerb/bug_args__19.txt @@ -24,8 +24,10 @@ │ │ │ └── @ MultiTargetNode (location: (1,5)-(1,11)) │ │ │ ├── lefts: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (1,6)-(1,7)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :a │ │ │ │ └── @ RequiredParameterNode (location: (1,9)-(1,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── rest: ∅ │ │ │ ├── rights: (length: 0) diff --git a/test/prism/snapshots/seattlerb/bug_args_masgn.txt b/test/prism/snapshots/seattlerb/bug_args_masgn.txt index b71736c49d5cde..1ea7d0555ecfc4 100644 --- a/test/prism/snapshots/seattlerb/bug_args_masgn.txt +++ b/test/prism/snapshots/seattlerb/bug_args_masgn.txt @@ -24,14 +24,17 @@ │ │ │ ├── @ MultiTargetNode (location: (1,5)-(1,11)) │ │ │ │ ├── lefts: (length: 2) │ │ │ │ │ ├── @ RequiredParameterNode (location: (1,6)-(1,7)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── name: :a │ │ │ │ │ └── @ RequiredParameterNode (location: (1,9)-(1,10)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :b │ │ │ │ ├── rest: ∅ │ │ │ │ ├── rights: (length: 0) │ │ │ │ ├── lparen_loc: (1,5)-(1,6) = "(" │ │ │ │ └── rparen_loc: (1,10)-(1,11) = ")" │ │ │ └── @ RequiredParameterNode (location: (1,13)-(1,14)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :c │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/bug_args_masgn2.txt b/test/prism/snapshots/seattlerb/bug_args_masgn2.txt index 1b19f520e4171c..947c9cdfd31b28 100644 --- a/test/prism/snapshots/seattlerb/bug_args_masgn2.txt +++ b/test/prism/snapshots/seattlerb/bug_args_masgn2.txt @@ -26,20 +26,24 @@ │ │ │ │ │ ├── @ MultiTargetNode (location: (1,6)-(1,12)) │ │ │ │ │ │ ├── lefts: (length: 2) │ │ │ │ │ │ │ ├── @ RequiredParameterNode (location: (1,7)-(1,8)) + │ │ │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ │ │ └── name: :a │ │ │ │ │ │ │ └── @ RequiredParameterNode (location: (1,10)-(1,11)) + │ │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ │ └── name: :b │ │ │ │ │ │ ├── rest: ∅ │ │ │ │ │ │ ├── rights: (length: 0) │ │ │ │ │ │ ├── lparen_loc: (1,6)-(1,7) = "(" │ │ │ │ │ │ └── rparen_loc: (1,11)-(1,12) = ")" │ │ │ │ │ └── @ RequiredParameterNode (location: (1,14)-(1,15)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :c │ │ │ │ ├── rest: ∅ │ │ │ │ ├── rights: (length: 0) │ │ │ │ ├── lparen_loc: (1,5)-(1,6) = "(" │ │ │ │ └── rparen_loc: (1,15)-(1,16) = ")" │ │ │ └── @ RequiredParameterNode (location: (1,18)-(1,19)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :d │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/bug_args_masgn_outer_parens__19.txt b/test/prism/snapshots/seattlerb/bug_args_masgn_outer_parens__19.txt index d5a2c6264fc258..615e6445b7731b 100644 --- a/test/prism/snapshots/seattlerb/bug_args_masgn_outer_parens__19.txt +++ b/test/prism/snapshots/seattlerb/bug_args_masgn_outer_parens__19.txt @@ -26,14 +26,17 @@ │ │ │ │ ├── @ MultiTargetNode (location: (1,6)-(1,12)) │ │ │ │ │ ├── lefts: (length: 2) │ │ │ │ │ │ ├── @ RequiredParameterNode (location: (1,7)-(1,8)) + │ │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ │ └── name: :k │ │ │ │ │ │ └── @ RequiredParameterNode (location: (1,10)-(1,11)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── name: :v │ │ │ │ │ ├── rest: ∅ │ │ │ │ │ ├── rights: (length: 0) │ │ │ │ │ ├── lparen_loc: (1,6)-(1,7) = "(" │ │ │ │ │ └── rparen_loc: (1,11)-(1,12) = ")" │ │ │ │ └── @ RequiredParameterNode (location: (1,14)-(1,15)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :i │ │ │ ├── rest: ∅ │ │ │ ├── rights: (length: 0) diff --git a/test/prism/snapshots/seattlerb/bug_masgn_right.txt b/test/prism/snapshots/seattlerb/bug_masgn_right.txt index d68ac5ecfcec92..d84a59d97f8b02 100644 --- a/test/prism/snapshots/seattlerb/bug_masgn_right.txt +++ b/test/prism/snapshots/seattlerb/bug_masgn_right.txt @@ -22,12 +22,15 @@ │ │ @ ParametersNode (location: (1,5)-(1,14)) │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ └── @ MultiTargetNode (location: (1,8)-(1,14)) │ │ │ ├── lefts: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (1,9)-(1,10)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :b │ │ │ │ └── @ RequiredParameterNode (location: (1,12)-(1,13)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :c │ │ │ ├── rest: ∅ │ │ │ ├── rights: (length: 0) diff --git a/test/prism/snapshots/seattlerb/case_in.txt b/test/prism/snapshots/seattlerb/case_in.txt index 26a3642dc7517e..94ff42b8b27635 100644 --- a/test/prism/snapshots/seattlerb/case_in.txt +++ b/test/prism/snapshots/seattlerb/case_in.txt @@ -557,6 +557,7 @@ │ │ │ │ │ │ │ @ ParametersNode (location: (70,7)-(70,8)) │ │ │ │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ │ │ │ └── @ RequiredParameterNode (location: (70,7)-(70,8)) + │ │ │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ │ │ └── name: :b │ │ │ │ │ │ │ ├── optionals: (length: 0) │ │ │ │ │ │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_arg_asplat_arg.txt b/test/prism/snapshots/seattlerb/defn_arg_asplat_arg.txt index 6adedb23957c08..ecc7ad04a4cd7a 100644 --- a/test/prism/snapshots/seattlerb/defn_arg_asplat_arg.txt +++ b/test/prism/snapshots/seattlerb/defn_arg_asplat_arg.txt @@ -11,15 +11,18 @@ │ @ ParametersNode (location: (1,9)-(1,24)) │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,9)-(1,15)) + │ │ ├── flags: ∅ │ │ └── name: :interp │ ├── optionals: (length: 0) │ ├── rest: │ │ @ RestParameterNode (location: (1,17)-(1,18)) + │ │ ├── flags: ∅ │ │ ├── name: ∅ │ │ ├── name_loc: ∅ │ │ └── operator_loc: (1,17)-(1,18) = "*" │ ├── posts: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,20)-(1,24)) + │ │ ├── flags: ∅ │ │ └── name: :args │ ├── keywords: (length: 0) │ ├── keyword_rest: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_arg_forward_args.txt b/test/prism/snapshots/seattlerb/defn_arg_forward_args.txt index 4124819bb08b7c..46c0e91adeca27 100644 --- a/test/prism/snapshots/seattlerb/defn_arg_forward_args.txt +++ b/test/prism/snapshots/seattlerb/defn_arg_forward_args.txt @@ -11,6 +11,7 @@ │ @ ParametersNode (location: (1,6)-(1,12)) │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,6)-(1,7)) + │ │ ├── flags: ∅ │ │ └── name: :x │ ├── optionals: (length: 0) │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_args_forward_args.txt b/test/prism/snapshots/seattlerb/defn_args_forward_args.txt index 5f718c15469426..76d0fbe71c6c2a 100644 --- a/test/prism/snapshots/seattlerb/defn_args_forward_args.txt +++ b/test/prism/snapshots/seattlerb/defn_args_forward_args.txt @@ -11,10 +11,13 @@ │ @ ParametersNode (location: (1,6)-(1,18)) │ ├── requireds: (length: 3) │ │ ├── @ RequiredParameterNode (location: (1,6)-(1,7)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :x │ │ ├── @ RequiredParameterNode (location: (1,9)-(1,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :y │ │ └── @ RequiredParameterNode (location: (1,12)-(1,13)) + │ │ ├── flags: ∅ │ │ └── name: :z │ ├── optionals: (length: 0) │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_kwarg_env.txt b/test/prism/snapshots/seattlerb/defn_kwarg_env.txt index 933af33cdaffeb..c0abf7f99a6f36 100644 --- a/test/prism/snapshots/seattlerb/defn_kwarg_env.txt +++ b/test/prism/snapshots/seattlerb/defn_kwarg_env.txt @@ -16,6 +16,7 @@ │ ├── keywords: (length: 0) │ ├── keyword_rest: │ │ @ KeywordRestParameterNode (location: (1,9)-(1,18)) + │ │ ├── flags: ∅ │ │ ├── name: :testing │ │ ├── name_loc: (1,11)-(1,18) = "testing" │ │ └── operator_loc: (1,9)-(1,11) = "**" diff --git a/test/prism/snapshots/seattlerb/defn_kwarg_kwarg.txt b/test/prism/snapshots/seattlerb/defn_kwarg_kwarg.txt index 18ead9e6241411..4bad9a69d95f5d 100644 --- a/test/prism/snapshots/seattlerb/defn_kwarg_kwarg.txt +++ b/test/prism/snapshots/seattlerb/defn_kwarg_kwarg.txt @@ -11,18 +11,21 @@ │ @ ParametersNode (location: (1,6)-(1,19)) │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,6)-(1,7)) + │ │ ├── flags: ∅ │ │ └── name: :a │ ├── optionals: (length: 0) │ ├── rest: ∅ │ ├── posts: (length: 0) │ ├── keywords: (length: 2) │ │ ├── @ OptionalKeywordParameterNode (location: (1,9)-(1,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (1,9)-(1,11) = "b:" │ │ │ └── value: │ │ │ @ IntegerNode (location: (1,12)-(1,13)) │ │ │ └── flags: decimal │ │ └── @ OptionalKeywordParameterNode (location: (1,15)-(1,19)) + │ │ ├── flags: ∅ │ │ ├── name: :c │ │ ├── name_loc: (1,15)-(1,17) = "c:" │ │ └── value: diff --git a/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat.txt b/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat.txt index a711c393055f27..8aafbb0e48b19d 100644 --- a/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat.txt +++ b/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat.txt @@ -15,6 +15,7 @@ │ ├── posts: (length: 0) │ ├── keywords: (length: 1) │ │ └── @ OptionalKeywordParameterNode (location: (1,6)-(1,10)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (1,6)-(1,8) = "b:" │ │ └── value: @@ -22,6 +23,7 @@ │ │ └── flags: decimal │ ├── keyword_rest: │ │ @ KeywordRestParameterNode (location: (1,12)-(1,15)) + │ │ ├── flags: ∅ │ │ ├── name: :c │ │ ├── name_loc: (1,14)-(1,15) = "c" │ │ └── operator_loc: (1,12)-(1,14) = "**" diff --git a/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat_anon.txt b/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat_anon.txt index f16cf144ad4e5c..897a36bc6afa31 100644 --- a/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat_anon.txt +++ b/test/prism/snapshots/seattlerb/defn_kwarg_kwsplat_anon.txt @@ -15,6 +15,7 @@ │ ├── posts: (length: 0) │ ├── keywords: (length: 1) │ │ └── @ OptionalKeywordParameterNode (location: (1,6)-(1,10)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (1,6)-(1,8) = "b:" │ │ └── value: @@ -22,6 +23,7 @@ │ │ └── flags: decimal │ ├── keyword_rest: │ │ @ KeywordRestParameterNode (location: (1,12)-(1,14)) + │ │ ├── flags: ∅ │ │ ├── name: ∅ │ │ ├── name_loc: ∅ │ │ └── operator_loc: (1,12)-(1,14) = "**" diff --git a/test/prism/snapshots/seattlerb/defn_kwarg_lvar.txt b/test/prism/snapshots/seattlerb/defn_kwarg_lvar.txt index ad8d189fd1ad1a..93bdb4205438f5 100644 --- a/test/prism/snapshots/seattlerb/defn_kwarg_lvar.txt +++ b/test/prism/snapshots/seattlerb/defn_kwarg_lvar.txt @@ -15,6 +15,7 @@ │ ├── posts: (length: 0) │ ├── keywords: (length: 1) │ │ └── @ OptionalKeywordParameterNode (location: (1,8)-(1,16)) + │ │ ├── flags: ∅ │ │ ├── name: :kw │ │ ├── name_loc: (1,8)-(1,11) = "kw:" │ │ └── value: diff --git a/test/prism/snapshots/seattlerb/defn_kwarg_no_parens.txt b/test/prism/snapshots/seattlerb/defn_kwarg_no_parens.txt index 9899f4360d3a5b..df04231ea46e14 100644 --- a/test/prism/snapshots/seattlerb/defn_kwarg_no_parens.txt +++ b/test/prism/snapshots/seattlerb/defn_kwarg_no_parens.txt @@ -15,6 +15,7 @@ │ ├── posts: (length: 0) │ ├── keywords: (length: 1) │ │ └── @ OptionalKeywordParameterNode (location: (1,6)-(1,10)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ ├── name_loc: (1,6)-(1,8) = "a:" │ │ └── value: diff --git a/test/prism/snapshots/seattlerb/defn_kwarg_val.txt b/test/prism/snapshots/seattlerb/defn_kwarg_val.txt index beca85c9964c11..61c3dd29bddc70 100644 --- a/test/prism/snapshots/seattlerb/defn_kwarg_val.txt +++ b/test/prism/snapshots/seattlerb/defn_kwarg_val.txt @@ -11,12 +11,14 @@ │ @ ParametersNode (location: (1,6)-(1,12)) │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,6)-(1,7)) + │ │ ├── flags: ∅ │ │ └── name: :a │ ├── optionals: (length: 0) │ ├── rest: ∅ │ ├── posts: (length: 0) │ ├── keywords: (length: 1) │ │ └── @ OptionalKeywordParameterNode (location: (1,9)-(1,12)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (1,9)-(1,11) = "b:" │ │ └── value: diff --git a/test/prism/snapshots/seattlerb/defn_oneliner.txt b/test/prism/snapshots/seattlerb/defn_oneliner.txt index 38191d0f5a82f5..d100d10eab2f09 100644 --- a/test/prism/snapshots/seattlerb/defn_oneliner.txt +++ b/test/prism/snapshots/seattlerb/defn_oneliner.txt @@ -11,6 +11,7 @@ │ @ ParametersNode (location: (1,9)-(1,12)) │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,9)-(1,12)) + │ │ ├── flags: ∅ │ │ └── name: :cmd │ ├── optionals: (length: 0) │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_oneliner_eq2.txt b/test/prism/snapshots/seattlerb/defn_oneliner_eq2.txt index 7252adaa93f6c6..31418f1116f4b3 100644 --- a/test/prism/snapshots/seattlerb/defn_oneliner_eq2.txt +++ b/test/prism/snapshots/seattlerb/defn_oneliner_eq2.txt @@ -22,6 +22,7 @@ │ │ @ ParametersNode (location: (2,9)-(2,10)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (2,9)-(2,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :o │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_oneliner_rescue.txt b/test/prism/snapshots/seattlerb/defn_oneliner_rescue.txt index ebabc02c97a3a5..bb23f56c7037da 100644 --- a/test/prism/snapshots/seattlerb/defn_oneliner_rescue.txt +++ b/test/prism/snapshots/seattlerb/defn_oneliner_rescue.txt @@ -11,6 +11,7 @@ │ │ @ ParametersNode (location: (1,9)-(1,12)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,9)-(1,12)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :cmd │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -70,6 +71,7 @@ │ │ @ ParametersNode (location: (8,9)-(8,12)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (8,9)-(8,12)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :cmd │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -117,6 +119,7 @@ │ @ ParametersNode (location: (13,9)-(13,12)) │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (13,9)-(13,12)) + │ │ ├── flags: ∅ │ │ └── name: :cmd │ ├── optionals: (length: 0) │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_opt_last_arg.txt b/test/prism/snapshots/seattlerb/defn_opt_last_arg.txt index fae68d5342ab63..05a4cec8696720 100644 --- a/test/prism/snapshots/seattlerb/defn_opt_last_arg.txt +++ b/test/prism/snapshots/seattlerb/defn_opt_last_arg.txt @@ -12,6 +12,7 @@ │ ├── requireds: (length: 0) │ ├── optionals: (length: 1) │ │ └── @ OptionalParameterNode (location: (1,6)-(1,17)) + │ │ ├── flags: ∅ │ │ ├── name: :arg │ │ ├── name_loc: (1,6)-(1,9) = "arg" │ │ ├── operator_loc: (1,10)-(1,11) = "=" diff --git a/test/prism/snapshots/seattlerb/defn_opt_reg.txt b/test/prism/snapshots/seattlerb/defn_opt_reg.txt index aeff12d658a2fe..34b1faafa6a782 100644 --- a/test/prism/snapshots/seattlerb/defn_opt_reg.txt +++ b/test/prism/snapshots/seattlerb/defn_opt_reg.txt @@ -12,6 +12,7 @@ │ ├── requireds: (length: 0) │ ├── optionals: (length: 1) │ │ └── @ OptionalParameterNode (location: (1,6)-(1,11)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ ├── name_loc: (1,6)-(1,7) = "a" │ │ ├── operator_loc: (1,7)-(1,8) = "=" @@ -20,6 +21,7 @@ │ ├── rest: ∅ │ ├── posts: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,13)-(1,14)) + │ │ ├── flags: ∅ │ │ └── name: :b │ ├── keywords: (length: 0) │ ├── keyword_rest: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_opt_splat_arg.txt b/test/prism/snapshots/seattlerb/defn_opt_splat_arg.txt index 7ec94cf6704815..7cd554222ed555 100644 --- a/test/prism/snapshots/seattlerb/defn_opt_splat_arg.txt +++ b/test/prism/snapshots/seattlerb/defn_opt_splat_arg.txt @@ -12,6 +12,7 @@ │ ├── requireds: (length: 0) │ ├── optionals: (length: 1) │ │ └── @ OptionalParameterNode (location: (1,7)-(1,12)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ ├── name_loc: (1,7)-(1,8) = "a" │ │ ├── operator_loc: (1,9)-(1,10) = "=" @@ -20,11 +21,13 @@ │ │ └── flags: decimal │ ├── rest: │ │ @ RestParameterNode (location: (1,14)-(1,16)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (1,15)-(1,16) = "b" │ │ └── operator_loc: (1,14)-(1,15) = "*" │ ├── posts: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,18)-(1,19)) + │ │ ├── flags: ∅ │ │ └── name: :c │ ├── keywords: (length: 0) │ ├── keyword_rest: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_powarg.txt b/test/prism/snapshots/seattlerb/defn_powarg.txt index 1b0fbe656c4f85..5e756ca3426c66 100644 --- a/test/prism/snapshots/seattlerb/defn_powarg.txt +++ b/test/prism/snapshots/seattlerb/defn_powarg.txt @@ -16,6 +16,7 @@ │ ├── keywords: (length: 0) │ ├── keyword_rest: │ │ @ KeywordRestParameterNode (location: (1,6)-(1,12)) + │ │ ├── flags: ∅ │ │ ├── name: :opts │ │ ├── name_loc: (1,8)-(1,12) = "opts" │ │ └── operator_loc: (1,6)-(1,8) = "**" diff --git a/test/prism/snapshots/seattlerb/defn_reg_opt_reg.txt b/test/prism/snapshots/seattlerb/defn_reg_opt_reg.txt index 6ef9635fb6b7b4..2a5e151bc24836 100644 --- a/test/prism/snapshots/seattlerb/defn_reg_opt_reg.txt +++ b/test/prism/snapshots/seattlerb/defn_reg_opt_reg.txt @@ -11,9 +11,11 @@ │ @ ParametersNode (location: (1,6)-(1,18)) │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,6)-(1,7)) + │ │ ├── flags: ∅ │ │ └── name: :a │ ├── optionals: (length: 1) │ │ └── @ OptionalParameterNode (location: (1,9)-(1,15)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (1,9)-(1,10) = "b" │ │ ├── operator_loc: (1,11)-(1,12) = "=" @@ -27,6 +29,7 @@ │ ├── rest: ∅ │ ├── posts: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,17)-(1,18)) + │ │ ├── flags: ∅ │ │ └── name: :d │ ├── keywords: (length: 0) │ ├── keyword_rest: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_splat_arg.txt b/test/prism/snapshots/seattlerb/defn_splat_arg.txt index 453673f753078c..6533258fe6accc 100644 --- a/test/prism/snapshots/seattlerb/defn_splat_arg.txt +++ b/test/prism/snapshots/seattlerb/defn_splat_arg.txt @@ -13,11 +13,13 @@ │ ├── optionals: (length: 0) │ ├── rest: │ │ @ RestParameterNode (location: (1,6)-(1,7)) + │ │ ├── flags: ∅ │ │ ├── name: ∅ │ │ ├── name_loc: ∅ │ │ └── operator_loc: (1,6)-(1,7) = "*" │ ├── posts: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,9)-(1,10)) + │ │ ├── flags: ∅ │ │ └── name: :a │ ├── keywords: (length: 0) │ ├── keyword_rest: ∅ diff --git a/test/prism/snapshots/seattlerb/defs_kwarg.txt b/test/prism/snapshots/seattlerb/defs_kwarg.txt index 9c42a36282794e..f96c6264a06160 100644 --- a/test/prism/snapshots/seattlerb/defs_kwarg.txt +++ b/test/prism/snapshots/seattlerb/defs_kwarg.txt @@ -16,6 +16,7 @@ │ ├── posts: (length: 0) │ ├── keywords: (length: 1) │ │ └── @ OptionalKeywordParameterNode (location: (1,11)-(1,15)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (1,11)-(1,13) = "b:" │ │ └── value: diff --git a/test/prism/snapshots/seattlerb/defs_oneliner.txt b/test/prism/snapshots/seattlerb/defs_oneliner.txt index e1ae681bb3af2b..dbbb5e172b56a8 100644 --- a/test/prism/snapshots/seattlerb/defs_oneliner.txt +++ b/test/prism/snapshots/seattlerb/defs_oneliner.txt @@ -12,6 +12,7 @@ │ @ ParametersNode (location: (1,14)-(1,17)) │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,14)-(1,17)) + │ │ ├── flags: ∅ │ │ └── name: :cmd │ ├── optionals: (length: 0) │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/defs_oneliner_eq2.txt b/test/prism/snapshots/seattlerb/defs_oneliner_eq2.txt index ffbb6befd87124..868efde81fa60b 100644 --- a/test/prism/snapshots/seattlerb/defs_oneliner_eq2.txt +++ b/test/prism/snapshots/seattlerb/defs_oneliner_eq2.txt @@ -23,6 +23,7 @@ │ │ @ ParametersNode (location: (2,14)-(2,15)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (2,14)-(2,15)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :o │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/defs_oneliner_rescue.txt b/test/prism/snapshots/seattlerb/defs_oneliner_rescue.txt index 69f7b9986de468..80d0332823a8bc 100644 --- a/test/prism/snapshots/seattlerb/defs_oneliner_rescue.txt +++ b/test/prism/snapshots/seattlerb/defs_oneliner_rescue.txt @@ -12,6 +12,7 @@ │ │ @ ParametersNode (location: (1,14)-(1,17)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,14)-(1,17)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :cmd │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -72,6 +73,7 @@ │ │ @ ParametersNode (location: (8,14)-(8,17)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (8,14)-(8,17)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :cmd │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -120,6 +122,7 @@ │ @ ParametersNode (location: (13,14)-(13,17)) │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (13,14)-(13,17)) + │ │ ├── flags: ∅ │ │ └── name: :cmd │ ├── optionals: (length: 0) │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/difficult3_.txt b/test/prism/snapshots/seattlerb/difficult3_.txt index 9b6052f0321ef2..4d5051d5644609 100644 --- a/test/prism/snapshots/seattlerb/difficult3_.txt +++ b/test/prism/snapshots/seattlerb/difficult3_.txt @@ -22,16 +22,19 @@ │ │ @ ParametersNode (location: (1,5)-(1,15)) │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ └── @ MultiTargetNode (location: (1,8)-(1,15)) │ │ │ ├── lefts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,9)-(1,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (1,12)-(1,14)) │ │ │ │ ├── operator_loc: (1,12)-(1,13) = "*" │ │ │ │ └── expression: │ │ │ │ @ RequiredParameterNode (location: (1,13)-(1,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :c │ │ │ ├── rights: (length: 0) │ │ │ ├── lparen_loc: (1,8)-(1,9) = "(" diff --git a/test/prism/snapshots/seattlerb/difficult3_2.txt b/test/prism/snapshots/seattlerb/difficult3_2.txt index 9daf24bba02e2b..842c3e86a1dd81 100644 --- a/test/prism/snapshots/seattlerb/difficult3_2.txt +++ b/test/prism/snapshots/seattlerb/difficult3_2.txt @@ -24,11 +24,13 @@ │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,5)-(1,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ ├── name_loc: (1,6)-(1,7) = "a" │ │ │ └── operator_loc: (1,5)-(1,6) = "*" │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,9)-(1,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :b │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ diff --git a/test/prism/snapshots/seattlerb/difficult3_3.txt b/test/prism/snapshots/seattlerb/difficult3_3.txt index b8a80f545392ea..bfc3a0329bd5ca 100644 --- a/test/prism/snapshots/seattlerb/difficult3_3.txt +++ b/test/prism/snapshots/seattlerb/difficult3_3.txt @@ -24,16 +24,19 @@ │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,5)-(1,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ ├── name_loc: (1,6)-(1,7) = "a" │ │ │ └── operator_loc: (1,5)-(1,6) = "*" │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,9)-(1,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :b │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (1,12)-(1,14)) + │ │ ├── flags: ∅ │ │ ├── name: :c │ │ ├── name_loc: (1,13)-(1,14) = "c" │ │ └── operator_loc: (1,12)-(1,13) = "&" diff --git a/test/prism/snapshots/seattlerb/difficult3__10.txt b/test/prism/snapshots/seattlerb/difficult3__10.txt index 4242d24d0659ed..a7dc59371c77eb 100644 --- a/test/prism/snapshots/seattlerb/difficult3__10.txt +++ b/test/prism/snapshots/seattlerb/difficult3__10.txt @@ -22,6 +22,7 @@ │ │ @ ParametersNode (location: (1,5)-(1,15)) │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ └── @ MultiTargetNode (location: (1,8)-(1,15)) │ │ │ ├── lefts: (length: 0) @@ -30,9 +31,11 @@ │ │ │ │ ├── operator_loc: (1,9)-(1,10) = "*" │ │ │ │ └── expression: │ │ │ │ @ RequiredParameterNode (location: (1,10)-(1,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── rights: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,13)-(1,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :c │ │ │ ├── lparen_loc: (1,8)-(1,9) = "(" │ │ │ └── rparen_loc: (1,14)-(1,15) = ")" diff --git a/test/prism/snapshots/seattlerb/difficult3__11.txt b/test/prism/snapshots/seattlerb/difficult3__11.txt index 6cc067406a5af2..5b393885a347fc 100644 --- a/test/prism/snapshots/seattlerb/difficult3__11.txt +++ b/test/prism/snapshots/seattlerb/difficult3__11.txt @@ -22,6 +22,7 @@ │ │ @ ParametersNode (location: (1,5)-(1,11)) │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ └── @ MultiTargetNode (location: (1,8)-(1,11)) │ │ │ ├── lefts: (length: 0) diff --git a/test/prism/snapshots/seattlerb/difficult3__12.txt b/test/prism/snapshots/seattlerb/difficult3__12.txt index b4854b1be15977..71be50a515d4e5 100644 --- a/test/prism/snapshots/seattlerb/difficult3__12.txt +++ b/test/prism/snapshots/seattlerb/difficult3__12.txt @@ -22,6 +22,7 @@ │ │ @ ParametersNode (location: (1,5)-(1,14)) │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ └── @ MultiTargetNode (location: (1,8)-(1,14)) │ │ │ ├── lefts: (length: 0) @@ -31,6 +32,7 @@ │ │ │ │ └── expression: ∅ │ │ │ ├── rights: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,12)-(1,13)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── lparen_loc: (1,8)-(1,9) = "(" │ │ │ └── rparen_loc: (1,13)-(1,14) = ")" diff --git a/test/prism/snapshots/seattlerb/difficult3__6.txt b/test/prism/snapshots/seattlerb/difficult3__6.txt index c6f7aa442f4993..77d14c992d80b2 100644 --- a/test/prism/snapshots/seattlerb/difficult3__6.txt +++ b/test/prism/snapshots/seattlerb/difficult3__6.txt @@ -22,19 +22,23 @@ │ │ @ ParametersNode (location: (1,5)-(1,18)) │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ └── @ MultiTargetNode (location: (1,8)-(1,18)) │ │ │ ├── lefts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,9)-(1,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (1,12)-(1,14)) │ │ │ │ ├── operator_loc: (1,12)-(1,13) = "*" │ │ │ │ └── expression: │ │ │ │ @ RequiredParameterNode (location: (1,13)-(1,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :c │ │ │ ├── rights: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,16)-(1,17)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :d │ │ │ ├── lparen_loc: (1,8)-(1,9) = "(" │ │ │ └── rparen_loc: (1,17)-(1,18) = ")" diff --git a/test/prism/snapshots/seattlerb/difficult3__7.txt b/test/prism/snapshots/seattlerb/difficult3__7.txt index 6ca5f2f5860762..c21a92d5eca4b8 100644 --- a/test/prism/snapshots/seattlerb/difficult3__7.txt +++ b/test/prism/snapshots/seattlerb/difficult3__7.txt @@ -22,10 +22,12 @@ │ │ @ ParametersNode (location: (1,5)-(1,14)) │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ └── @ MultiTargetNode (location: (1,8)-(1,14)) │ │ │ ├── lefts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,9)-(1,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (1,12)-(1,13)) diff --git a/test/prism/snapshots/seattlerb/difficult3__8.txt b/test/prism/snapshots/seattlerb/difficult3__8.txt index caf9e7248da8bd..0c437bddc1fdda 100644 --- a/test/prism/snapshots/seattlerb/difficult3__8.txt +++ b/test/prism/snapshots/seattlerb/difficult3__8.txt @@ -22,10 +22,12 @@ │ │ @ ParametersNode (location: (1,5)-(1,17)) │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ └── @ MultiTargetNode (location: (1,8)-(1,17)) │ │ │ ├── lefts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,9)-(1,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (1,12)-(1,13)) @@ -33,6 +35,7 @@ │ │ │ │ └── expression: ∅ │ │ │ ├── rights: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,15)-(1,16)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :c │ │ │ ├── lparen_loc: (1,8)-(1,9) = "(" │ │ │ └── rparen_loc: (1,16)-(1,17) = ")" diff --git a/test/prism/snapshots/seattlerb/difficult3__9.txt b/test/prism/snapshots/seattlerb/difficult3__9.txt index 98e1771a771e4c..eec21b775c38da 100644 --- a/test/prism/snapshots/seattlerb/difficult3__9.txt +++ b/test/prism/snapshots/seattlerb/difficult3__9.txt @@ -22,6 +22,7 @@ │ │ @ ParametersNode (location: (1,5)-(1,12)) │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ └── @ MultiTargetNode (location: (1,8)-(1,12)) │ │ │ ├── lefts: (length: 0) @@ -30,6 +31,7 @@ │ │ │ │ ├── operator_loc: (1,9)-(1,10) = "*" │ │ │ │ └── expression: │ │ │ │ @ RequiredParameterNode (location: (1,10)-(1,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── rights: (length: 0) │ │ │ ├── lparen_loc: (1,8)-(1,9) = "(" diff --git a/test/prism/snapshots/seattlerb/difficult6_.txt b/test/prism/snapshots/seattlerb/difficult6_.txt index 12ada8521d5569..70cd8b29fc3a25 100644 --- a/test/prism/snapshots/seattlerb/difficult6_.txt +++ b/test/prism/snapshots/seattlerb/difficult6_.txt @@ -15,9 +15,11 @@ │ │ @ ParametersNode (location: (1,3)-(1,11)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,3)-(1,4)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,6)-(1,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (1,6)-(1,7) = "b" │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" diff --git a/test/prism/snapshots/seattlerb/do_bug.txt b/test/prism/snapshots/seattlerb/do_bug.txt index 143dd53a3bfb18..a520f5ba207bdb 100644 --- a/test/prism/snapshots/seattlerb/do_bug.txt +++ b/test/prism/snapshots/seattlerb/do_bug.txt @@ -47,6 +47,7 @@ │ │ @ ParametersNode (location: (2,8)-(2,9)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (2,8)-(2,9)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :c │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/f_kw.txt b/test/prism/snapshots/seattlerb/f_kw.txt index 3f4d6d69811bbd..f1aaa471f02509 100644 --- a/test/prism/snapshots/seattlerb/f_kw.txt +++ b/test/prism/snapshots/seattlerb/f_kw.txt @@ -15,6 +15,7 @@ │ ├── posts: (length: 0) │ ├── keywords: (length: 1) │ │ └── @ OptionalKeywordParameterNode (location: (1,6)-(1,10)) + │ │ ├── flags: ∅ │ │ ├── name: :k │ │ ├── name_loc: (1,6)-(1,8) = "k:" │ │ └── value: diff --git a/test/prism/snapshots/seattlerb/f_kw__required.txt b/test/prism/snapshots/seattlerb/f_kw__required.txt index 61fe5edbae1b6f..6f64c71ae4fc76 100644 --- a/test/prism/snapshots/seattlerb/f_kw__required.txt +++ b/test/prism/snapshots/seattlerb/f_kw__required.txt @@ -15,6 +15,7 @@ │ ├── posts: (length: 0) │ ├── keywords: (length: 1) │ │ └── @ RequiredKeywordParameterNode (location: (1,6)-(1,8)) + │ │ ├── flags: ∅ │ │ ├── name: :k │ │ └── name_loc: (1,6)-(1,8) = "k:" │ ├── keyword_rest: ∅ diff --git a/test/prism/snapshots/seattlerb/iter_args_1.txt b/test/prism/snapshots/seattlerb/iter_args_1.txt index efc52b5dfc5cd7..46775a253d899e 100644 --- a/test/prism/snapshots/seattlerb/iter_args_1.txt +++ b/test/prism/snapshots/seattlerb/iter_args_1.txt @@ -22,8 +22,10 @@ │ │ @ ParametersNode (location: (1,5)-(1,8)) │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ └── @ RequiredParameterNode (location: (1,7)-(1,8)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :b │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/iter_args_10_1.txt b/test/prism/snapshots/seattlerb/iter_args_10_1.txt index dae3d474ef57eb..1f607cd2d3d782 100644 --- a/test/prism/snapshots/seattlerb/iter_args_10_1.txt +++ b/test/prism/snapshots/seattlerb/iter_args_10_1.txt @@ -22,9 +22,11 @@ │ │ @ ParametersNode (location: (1,5)-(1,18)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,8)-(1,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (1,8)-(1,9) = "b" │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" @@ -33,6 +35,7 @@ │ │ │ └── flags: decimal │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,16)-(1,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ ├── name_loc: (1,17)-(1,18) = "c" │ │ │ └── operator_loc: (1,16)-(1,17) = "*" diff --git a/test/prism/snapshots/seattlerb/iter_args_10_2.txt b/test/prism/snapshots/seattlerb/iter_args_10_2.txt index 062fec6aef0780..d15486a375e90f 100644 --- a/test/prism/snapshots/seattlerb/iter_args_10_2.txt +++ b/test/prism/snapshots/seattlerb/iter_args_10_2.txt @@ -22,9 +22,11 @@ │ │ @ ParametersNode (location: (1,5)-(1,22)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,8)-(1,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (1,8)-(1,9) = "b" │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" @@ -33,6 +35,7 @@ │ │ │ └── flags: decimal │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,16)-(1,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ ├── name_loc: (1,17)-(1,18) = "c" │ │ │ └── operator_loc: (1,16)-(1,17) = "*" @@ -41,6 +44,7 @@ │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (1,20)-(1,22)) + │ │ ├── flags: ∅ │ │ ├── name: :d │ │ ├── name_loc: (1,21)-(1,22) = "d" │ │ └── operator_loc: (1,20)-(1,21) = "&" diff --git a/test/prism/snapshots/seattlerb/iter_args_11_1.txt b/test/prism/snapshots/seattlerb/iter_args_11_1.txt index 16c9539fcb7842..972a0f1c904258 100644 --- a/test/prism/snapshots/seattlerb/iter_args_11_1.txt +++ b/test/prism/snapshots/seattlerb/iter_args_11_1.txt @@ -22,9 +22,11 @@ │ │ @ ParametersNode (location: (1,5)-(1,21)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,8)-(1,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (1,8)-(1,9) = "b" │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" @@ -33,11 +35,13 @@ │ │ │ └── flags: decimal │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,16)-(1,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ ├── name_loc: (1,17)-(1,18) = "c" │ │ │ └── operator_loc: (1,16)-(1,17) = "*" │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,20)-(1,21)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :d │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ diff --git a/test/prism/snapshots/seattlerb/iter_args_11_2.txt b/test/prism/snapshots/seattlerb/iter_args_11_2.txt index ca74c5bca7c4f5..66b82cb5070e3a 100644 --- a/test/prism/snapshots/seattlerb/iter_args_11_2.txt +++ b/test/prism/snapshots/seattlerb/iter_args_11_2.txt @@ -22,9 +22,11 @@ │ │ @ ParametersNode (location: (1,5)-(1,25)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,8)-(1,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (1,8)-(1,9) = "b" │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" @@ -33,16 +35,19 @@ │ │ │ └── flags: decimal │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,16)-(1,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ ├── name_loc: (1,17)-(1,18) = "c" │ │ │ └── operator_loc: (1,16)-(1,17) = "*" │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,20)-(1,21)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :d │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (1,23)-(1,25)) + │ │ ├── flags: ∅ │ │ ├── name: :e │ │ ├── name_loc: (1,24)-(1,25) = "e" │ │ └── operator_loc: (1,23)-(1,24) = "&" diff --git a/test/prism/snapshots/seattlerb/iter_args_2__19.txt b/test/prism/snapshots/seattlerb/iter_args_2__19.txt index 788c0ba50faeeb..3d7d251e3bf7aa 100644 --- a/test/prism/snapshots/seattlerb/iter_args_2__19.txt +++ b/test/prism/snapshots/seattlerb/iter_args_2__19.txt @@ -24,8 +24,10 @@ │ │ │ └── @ MultiTargetNode (location: (1,5)-(1,11)) │ │ │ ├── lefts: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (1,6)-(1,7)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :a │ │ │ │ └── @ RequiredParameterNode (location: (1,9)-(1,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── rest: ∅ │ │ │ ├── rights: (length: 0) diff --git a/test/prism/snapshots/seattlerb/iter_args_3.txt b/test/prism/snapshots/seattlerb/iter_args_3.txt index 6f7ce2b5c19314..6cd964d27b5155 100644 --- a/test/prism/snapshots/seattlerb/iter_args_3.txt +++ b/test/prism/snapshots/seattlerb/iter_args_3.txt @@ -22,18 +22,22 @@ │ │ @ ParametersNode (location: (1,5)-(1,17)) │ │ ├── requireds: (length: 3) │ │ │ ├── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── @ MultiTargetNode (location: (1,8)-(1,14)) │ │ │ │ ├── lefts: (length: 2) │ │ │ │ │ ├── @ RequiredParameterNode (location: (1,9)-(1,10)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── name: :b │ │ │ │ │ └── @ RequiredParameterNode (location: (1,12)-(1,13)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :c │ │ │ │ ├── rest: ∅ │ │ │ │ ├── rights: (length: 0) │ │ │ │ ├── lparen_loc: (1,8)-(1,9) = "(" │ │ │ │ └── rparen_loc: (1,13)-(1,14) = ")" │ │ │ └── @ RequiredParameterNode (location: (1,16)-(1,17)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :d │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/iter_args_4.txt b/test/prism/snapshots/seattlerb/iter_args_4.txt index 516273f02fa3e3..d2622965d67232 100644 --- a/test/prism/snapshots/seattlerb/iter_args_4.txt +++ b/test/prism/snapshots/seattlerb/iter_args_4.txt @@ -22,15 +22,18 @@ │ │ @ ParametersNode (location: (1,5)-(1,13)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,8)-(1,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (1,9)-(1,10) = "b" │ │ │ └── operator_loc: (1,8)-(1,9) = "*" │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,12)-(1,13)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :c │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ diff --git a/test/prism/snapshots/seattlerb/iter_args_5.txt b/test/prism/snapshots/seattlerb/iter_args_5.txt index efd1cfbcb81eea..4f121beccd6be9 100644 --- a/test/prism/snapshots/seattlerb/iter_args_5.txt +++ b/test/prism/snapshots/seattlerb/iter_args_5.txt @@ -22,6 +22,7 @@ │ │ @ ParametersNode (location: (1,5)-(1,10)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -30,6 +31,7 @@ │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (1,8)-(1,10)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (1,9)-(1,10) = "b" │ │ └── operator_loc: (1,8)-(1,9) = "&" diff --git a/test/prism/snapshots/seattlerb/iter_args_6.txt b/test/prism/snapshots/seattlerb/iter_args_6.txt index d0f707012dee87..4e0c8e1150249f 100644 --- a/test/prism/snapshots/seattlerb/iter_args_6.txt +++ b/test/prism/snapshots/seattlerb/iter_args_6.txt @@ -22,9 +22,11 @@ │ │ @ ParametersNode (location: (1,5)-(1,15)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,5)-(1,6)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,8)-(1,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (1,8)-(1,9) = "b" │ │ │ ├── operator_loc: (1,9)-(1,10) = "=" @@ -34,6 +36,7 @@ │ │ ├── rest: ∅ │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,14)-(1,15)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :c │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ diff --git a/test/prism/snapshots/seattlerb/iter_args_7_1.txt b/test/prism/snapshots/seattlerb/iter_args_7_1.txt index 9b71f4aecbc9ad..5e61efdaae19e8 100644 --- a/test/prism/snapshots/seattlerb/iter_args_7_1.txt +++ b/test/prism/snapshots/seattlerb/iter_args_7_1.txt @@ -23,6 +23,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,5)-(1,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ ├── name_loc: (1,5)-(1,6) = "a" │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" @@ -31,6 +32,7 @@ │ │ │ └── flags: decimal │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,13)-(1,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (1,14)-(1,15) = "b" │ │ │ └── operator_loc: (1,13)-(1,14) = "*" diff --git a/test/prism/snapshots/seattlerb/iter_args_7_2.txt b/test/prism/snapshots/seattlerb/iter_args_7_2.txt index bc9e23496ef130..e1fa58d7286071 100644 --- a/test/prism/snapshots/seattlerb/iter_args_7_2.txt +++ b/test/prism/snapshots/seattlerb/iter_args_7_2.txt @@ -23,6 +23,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,5)-(1,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ ├── name_loc: (1,5)-(1,6) = "a" │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" @@ -31,6 +32,7 @@ │ │ │ └── flags: decimal │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,13)-(1,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (1,14)-(1,15) = "b" │ │ │ └── operator_loc: (1,13)-(1,14) = "*" @@ -39,6 +41,7 @@ │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (1,17)-(1,19)) + │ │ ├── flags: ∅ │ │ ├── name: :c │ │ ├── name_loc: (1,18)-(1,19) = "c" │ │ └── operator_loc: (1,17)-(1,18) = "&" diff --git a/test/prism/snapshots/seattlerb/iter_args_8_1.txt b/test/prism/snapshots/seattlerb/iter_args_8_1.txt index 488ee837f4628e..46e1ab5f6bb1ce 100644 --- a/test/prism/snapshots/seattlerb/iter_args_8_1.txt +++ b/test/prism/snapshots/seattlerb/iter_args_8_1.txt @@ -23,6 +23,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,5)-(1,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ ├── name_loc: (1,5)-(1,6) = "a" │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" @@ -31,11 +32,13 @@ │ │ │ └── flags: decimal │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,13)-(1,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (1,14)-(1,15) = "b" │ │ │ └── operator_loc: (1,13)-(1,14) = "*" │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,17)-(1,18)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :c │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ diff --git a/test/prism/snapshots/seattlerb/iter_args_8_2.txt b/test/prism/snapshots/seattlerb/iter_args_8_2.txt index cd4fcc59f600f6..ecce85c3bf9457 100644 --- a/test/prism/snapshots/seattlerb/iter_args_8_2.txt +++ b/test/prism/snapshots/seattlerb/iter_args_8_2.txt @@ -23,6 +23,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,5)-(1,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ ├── name_loc: (1,5)-(1,6) = "a" │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" @@ -31,16 +32,19 @@ │ │ │ └── flags: decimal │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,13)-(1,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (1,14)-(1,15) = "b" │ │ │ └── operator_loc: (1,13)-(1,14) = "*" │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,17)-(1,18)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :c │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (1,20)-(1,22)) + │ │ ├── flags: ∅ │ │ ├── name: :d │ │ ├── name_loc: (1,21)-(1,22) = "d" │ │ └── operator_loc: (1,20)-(1,21) = "&" diff --git a/test/prism/snapshots/seattlerb/iter_args_9_1.txt b/test/prism/snapshots/seattlerb/iter_args_9_1.txt index 40ffcec0294063..cb617efc7ca841 100644 --- a/test/prism/snapshots/seattlerb/iter_args_9_1.txt +++ b/test/prism/snapshots/seattlerb/iter_args_9_1.txt @@ -23,6 +23,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,5)-(1,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ ├── name_loc: (1,5)-(1,6) = "a" │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" @@ -32,6 +33,7 @@ │ │ ├── rest: ∅ │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,13)-(1,14)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :b │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ diff --git a/test/prism/snapshots/seattlerb/iter_args_9_2.txt b/test/prism/snapshots/seattlerb/iter_args_9_2.txt index 18cdc620ce256e..1488be20e24a11 100644 --- a/test/prism/snapshots/seattlerb/iter_args_9_2.txt +++ b/test/prism/snapshots/seattlerb/iter_args_9_2.txt @@ -23,6 +23,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,5)-(1,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ ├── name_loc: (1,5)-(1,6) = "a" │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" @@ -32,11 +33,13 @@ │ │ ├── rest: ∅ │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,13)-(1,14)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :b │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (1,16)-(1,18)) + │ │ ├── flags: ∅ │ │ ├── name: :c │ │ ├── name_loc: (1,17)-(1,18) = "c" │ │ └── operator_loc: (1,16)-(1,17) = "&" diff --git a/test/prism/snapshots/seattlerb/iter_kwarg.txt b/test/prism/snapshots/seattlerb/iter_kwarg.txt index b7655eec2cb99b..fc91eaa70307e4 100644 --- a/test/prism/snapshots/seattlerb/iter_kwarg.txt +++ b/test/prism/snapshots/seattlerb/iter_kwarg.txt @@ -26,6 +26,7 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) │ │ │ └── @ OptionalKeywordParameterNode (location: (1,5)-(1,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (1,5)-(1,7) = "b:" │ │ │ └── value: diff --git a/test/prism/snapshots/seattlerb/iter_kwarg_kwsplat.txt b/test/prism/snapshots/seattlerb/iter_kwarg_kwsplat.txt index 0c4b3920c1c912..5fcda7645e563a 100644 --- a/test/prism/snapshots/seattlerb/iter_kwarg_kwsplat.txt +++ b/test/prism/snapshots/seattlerb/iter_kwarg_kwsplat.txt @@ -26,6 +26,7 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) │ │ │ └── @ OptionalKeywordParameterNode (location: (1,5)-(1,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (1,5)-(1,7) = "b:" │ │ │ └── value: @@ -33,6 +34,7 @@ │ │ │ └── flags: decimal │ │ ├── keyword_rest: │ │ │ @ KeywordRestParameterNode (location: (1,11)-(1,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ ├── name_loc: (1,13)-(1,14) = "c" │ │ │ └── operator_loc: (1,11)-(1,13) = "**" diff --git a/test/prism/snapshots/seattlerb/parse_line_call_no_args.txt b/test/prism/snapshots/seattlerb/parse_line_call_no_args.txt index 475e8d9efd5c4e..1688e88c78348a 100644 --- a/test/prism/snapshots/seattlerb/parse_line_call_no_args.txt +++ b/test/prism/snapshots/seattlerb/parse_line_call_no_args.txt @@ -22,8 +22,10 @@ │ │ @ ParametersNode (location: (1,6)-(1,10)) │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (1,6)-(1,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :x │ │ │ └── @ RequiredParameterNode (location: (1,9)-(1,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :y │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/parse_line_defn_complex.txt b/test/prism/snapshots/seattlerb/parse_line_defn_complex.txt index 4df2cea7cd69a4..cd61a9897e1ab9 100644 --- a/test/prism/snapshots/seattlerb/parse_line_defn_complex.txt +++ b/test/prism/snapshots/seattlerb/parse_line_defn_complex.txt @@ -11,6 +11,7 @@ │ @ ParametersNode (location: (1,6)-(1,7)) │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,6)-(1,7)) + │ │ ├── flags: ∅ │ │ └── name: :y │ ├── optionals: (length: 0) │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/parse_line_defn_no_parens_args.txt b/test/prism/snapshots/seattlerb/parse_line_defn_no_parens_args.txt index 8a0a1c752a634d..aebf2cf933f974 100644 --- a/test/prism/snapshots/seattlerb/parse_line_defn_no_parens_args.txt +++ b/test/prism/snapshots/seattlerb/parse_line_defn_no_parens_args.txt @@ -11,6 +11,7 @@ │ @ ParametersNode (location: (1,6)-(1,7)) │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,6)-(1,7)) + │ │ ├── flags: ∅ │ │ └── name: :a │ ├── optionals: (length: 0) │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/parse_line_iter_call_no_parens.txt b/test/prism/snapshots/seattlerb/parse_line_iter_call_no_parens.txt index 9edb2c6202e8ac..cd721a3feaa493 100644 --- a/test/prism/snapshots/seattlerb/parse_line_iter_call_no_parens.txt +++ b/test/prism/snapshots/seattlerb/parse_line_iter_call_no_parens.txt @@ -35,8 +35,10 @@ │ │ @ ParametersNode (location: (1,8)-(1,12)) │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (1,8)-(1,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :x │ │ │ └── @ RequiredParameterNode (location: (1,11)-(1,12)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :y │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/parse_line_iter_call_parens.txt b/test/prism/snapshots/seattlerb/parse_line_iter_call_parens.txt index d92e8a18dcfa1a..2fba775aac6f97 100644 --- a/test/prism/snapshots/seattlerb/parse_line_iter_call_parens.txt +++ b/test/prism/snapshots/seattlerb/parse_line_iter_call_parens.txt @@ -35,8 +35,10 @@ │ │ @ ParametersNode (location: (1,9)-(1,13)) │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (1,9)-(1,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :x │ │ │ └── @ RequiredParameterNode (location: (1,12)-(1,13)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :y │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/pipe_semicolon.txt b/test/prism/snapshots/seattlerb/pipe_semicolon.txt index 1d83dc50cf83e9..cf26a2951e78e9 100644 --- a/test/prism/snapshots/seattlerb/pipe_semicolon.txt +++ b/test/prism/snapshots/seattlerb/pipe_semicolon.txt @@ -31,6 +31,7 @@ │ ├── parameters: ∅ │ ├── locals: (length: 1) │ │ └── @ BlockLocalVariableNode (location: (1,11)-(1,12)) + │ │ ├── flags: ∅ │ │ └── name: :c │ ├── opening_loc: (1,7)-(1,8) = "|" │ └── closing_loc: (1,13)-(1,14) = "|" diff --git a/test/prism/snapshots/seattlerb/required_kwarg_no_value.txt b/test/prism/snapshots/seattlerb/required_kwarg_no_value.txt index fe2ce0bc7ec07e..922817c191588c 100644 --- a/test/prism/snapshots/seattlerb/required_kwarg_no_value.txt +++ b/test/prism/snapshots/seattlerb/required_kwarg_no_value.txt @@ -15,9 +15,11 @@ │ ├── posts: (length: 0) │ ├── keywords: (length: 2) │ │ ├── @ RequiredKeywordParameterNode (location: (1,6)-(1,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ └── name_loc: (1,6)-(1,8) = "a:" │ │ └── @ RequiredKeywordParameterNode (location: (1,10)-(1,12)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ └── name_loc: (1,10)-(1,12) = "b:" │ ├── keyword_rest: ∅ diff --git a/test/prism/snapshots/seattlerb/stabby_arg_no_paren.txt b/test/prism/snapshots/seattlerb/stabby_arg_no_paren.txt index a2c67e609cf304..dddd22eb2322ca 100644 --- a/test/prism/snapshots/seattlerb/stabby_arg_no_paren.txt +++ b/test/prism/snapshots/seattlerb/stabby_arg_no_paren.txt @@ -15,6 +15,7 @@ │ │ @ ParametersNode (location: (1,2)-(1,3)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,2)-(1,3)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/seattlerb/stabby_arg_opt_splat_arg_block_omfg.txt b/test/prism/snapshots/seattlerb/stabby_arg_opt_splat_arg_block_omfg.txt index 1cd4580bc56725..d0d5885432c386 100644 --- a/test/prism/snapshots/seattlerb/stabby_arg_opt_splat_arg_block_omfg.txt +++ b/test/prism/snapshots/seattlerb/stabby_arg_opt_splat_arg_block_omfg.txt @@ -15,9 +15,11 @@ │ │ @ ParametersNode (location: (1,3)-(1,20)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,3)-(1,4)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :b │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,6)-(1,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :c │ │ │ ├── name_loc: (1,6)-(1,7) = "c" │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" @@ -26,16 +28,19 @@ │ │ │ └── flags: decimal │ │ ├── rest: │ │ │ @ RestParameterNode (location: (1,11)-(1,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :d │ │ │ ├── name_loc: (1,12)-(1,13) = "d" │ │ │ └── operator_loc: (1,11)-(1,12) = "*" │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,15)-(1,16)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :e │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (1,18)-(1,20)) + │ │ ├── flags: ∅ │ │ ├── name: :f │ │ ├── name_loc: (1,19)-(1,20) = "f" │ │ └── operator_loc: (1,18)-(1,19) = "&" diff --git a/test/prism/snapshots/seattlerb/stabby_block_kw.txt b/test/prism/snapshots/seattlerb/stabby_block_kw.txt index b9a2151a76f3b8..342145bb639cc5 100644 --- a/test/prism/snapshots/seattlerb/stabby_block_kw.txt +++ b/test/prism/snapshots/seattlerb/stabby_block_kw.txt @@ -19,6 +19,7 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) │ │ │ └── @ OptionalKeywordParameterNode (location: (1,4)-(1,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :k │ │ │ ├── name_loc: (1,4)-(1,6) = "k:" │ │ │ └── value: diff --git a/test/prism/snapshots/seattlerb/stabby_block_kw__required.txt b/test/prism/snapshots/seattlerb/stabby_block_kw__required.txt index 5d0ac1e5c07fb5..ed34442272f1c6 100644 --- a/test/prism/snapshots/seattlerb/stabby_block_kw__required.txt +++ b/test/prism/snapshots/seattlerb/stabby_block_kw__required.txt @@ -19,6 +19,7 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) │ │ │ └── @ RequiredKeywordParameterNode (location: (1,4)-(1,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :k │ │ │ └── name_loc: (1,4)-(1,6) = "k:" │ │ ├── keyword_rest: ∅ diff --git a/test/prism/snapshots/seattlerb/stabby_proc_scope.txt b/test/prism/snapshots/seattlerb/stabby_proc_scope.txt index 23ab524fad40ba..38d9a455cbb66e 100644 --- a/test/prism/snapshots/seattlerb/stabby_proc_scope.txt +++ b/test/prism/snapshots/seattlerb/stabby_proc_scope.txt @@ -15,6 +15,7 @@ │ │ @ ParametersNode (location: (1,3)-(1,4)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,3)-(1,4)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -24,6 +25,7 @@ │ │ └── block: ∅ │ ├── locals: (length: 1) │ │ └── @ BlockLocalVariableNode (location: (1,6)-(1,7)) + │ │ ├── flags: ∅ │ │ └── name: :b │ ├── opening_loc: (1,2)-(1,3) = "(" │ └── closing_loc: (1,7)-(1,8) = ")" diff --git a/test/prism/snapshots/unparser/corpus/literal/block.txt b/test/prism/snapshots/unparser/corpus/literal/block.txt index 8c8d9ac5086044..17cde39e645c35 100644 --- a/test/prism/snapshots/unparser/corpus/literal/block.txt +++ b/test/prism/snapshots/unparser/corpus/literal/block.txt @@ -39,6 +39,7 @@ │ │ │ @ ParametersNode (location: (3,7)-(3,8)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (3,7)-(3,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -71,6 +72,7 @@ │ │ │ @ ParametersNode (location: (5,7)-(5,9)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (5,7)-(5,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: @@ -104,6 +106,7 @@ │ │ │ @ ParametersNode (location: (7,7)-(7,9)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (7,7)-(7,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: @@ -114,6 +117,7 @@ │ │ │ └── block: ∅ │ │ ├── locals: (length: 1) │ │ │ └── @ BlockLocalVariableNode (location: (7,11)-(7,12)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :x │ │ ├── opening_loc: (7,6)-(7,7) = "|" │ │ └── closing_loc: (7,12)-(7,13) = "|" @@ -139,8 +143,10 @@ │ │ │ @ ParametersNode (location: (9,7)-(9,11)) │ │ │ ├── requireds: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (9,7)-(9,8)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :a │ │ │ │ └── @ RequiredParameterNode (location: (9,10)-(9,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -198,10 +204,12 @@ │ │ │ @ ParametersNode (location: (14,7)-(14,12)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (14,7)-(14,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (14,10)-(14,12)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :b │ │ │ │ ├── name_loc: (14,11)-(14,12) = "b" │ │ │ │ └── operator_loc: (14,10)-(14,11) = "*" @@ -237,10 +245,12 @@ │ │ │ @ ParametersNode (location: (17,7)-(17,11)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (17,7)-(17,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (17,10)-(17,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: ∅ │ │ │ │ ├── name_loc: ∅ │ │ │ │ └── operator_loc: (17,10)-(17,11) = "*" @@ -317,14 +327,17 @@ │ │ │ │ ├── @ MultiTargetNode (location: (23,11)-(23,17)) │ │ │ │ │ ├── lefts: (length: 2) │ │ │ │ │ │ ├── @ RequiredParameterNode (location: (23,12)-(23,13)) + │ │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ │ └── name: :a │ │ │ │ │ │ └── @ RequiredParameterNode (location: (23,15)-(23,16)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── name: :b │ │ │ │ │ ├── rest: ∅ │ │ │ │ │ ├── rights: (length: 0) │ │ │ │ │ ├── lparen_loc: (23,11)-(23,12) = "(" │ │ │ │ │ └── rparen_loc: (23,16)-(23,17) = ")" │ │ │ │ └── @ RequiredParameterNode (location: (23,19)-(23,20)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :c │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -381,6 +394,7 @@ │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (26,11)-(26,13)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :a │ │ │ │ ├── name_loc: (26,12)-(26,13) = "a" │ │ │ │ └── operator_loc: (26,11)-(26,12) = "*" @@ -390,6 +404,7 @@ │ │ │ └── block: ∅ │ │ ├── locals: (length: 1) │ │ │ └── @ BlockLocalVariableNode (location: (26,15)-(26,16)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :b │ │ ├── opening_loc: (26,10)-(26,11) = "|" │ │ └── closing_loc: (26,16)-(26,17) = "|" @@ -425,6 +440,7 @@ │ │ │ @ ParametersNode (location: (28,11)-(28,12)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (28,11)-(28,12)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -434,6 +450,7 @@ │ │ │ └── block: ∅ │ │ ├── locals: (length: 1) │ │ │ └── @ BlockLocalVariableNode (location: (28,14)-(28,15)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :b │ │ ├── opening_loc: (28,10)-(28,11) = "|" │ │ └── closing_loc: (28,15)-(28,16) = "|" @@ -468,8 +485,10 @@ │ │ ├── parameters: ∅ │ │ ├── locals: (length: 2) │ │ │ ├── @ BlockLocalVariableNode (location: (30,13)-(30,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ └── @ BlockLocalVariableNode (location: (30,16)-(30,17)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :b │ │ ├── opening_loc: (30,10)-(30,11) = "|" │ │ └── closing_loc: (30,17)-(30,18) = "|" @@ -507,6 +526,7 @@ │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (32,11)-(32,12)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: ∅ │ │ │ │ ├── name_loc: ∅ │ │ │ │ └── operator_loc: (32,11)-(32,12) = "*" @@ -691,6 +711,7 @@ │ │ │ │ └── @ MultiTargetNode (location: (41,11)-(41,19)) │ │ │ │ ├── lefts: (length: 2) │ │ │ │ │ ├── @ RequiredParameterNode (location: (41,12)-(41,13)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── name: :a │ │ │ │ │ └── @ MultiTargetNode (location: (41,15)-(41,18)) │ │ │ │ │ ├── lefts: (length: 0) @@ -760,8 +781,10 @@ │ │ │ │ └── @ MultiTargetNode (location: (44,11)-(44,17)) │ │ │ │ ├── lefts: (length: 2) │ │ │ │ │ ├── @ RequiredParameterNode (location: (44,12)-(44,13)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── name: :a │ │ │ │ │ └── @ RequiredParameterNode (location: (44,15)-(44,16)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :b │ │ │ │ ├── rest: ∅ │ │ │ │ ├── rights: (length: 0) diff --git a/test/prism/snapshots/unparser/corpus/literal/def.txt b/test/prism/snapshots/unparser/corpus/literal/def.txt index 085f0ef8b35f5c..d1face88105293 100644 --- a/test/prism/snapshots/unparser/corpus/literal/def.txt +++ b/test/prism/snapshots/unparser/corpus/literal/def.txt @@ -197,9 +197,11 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 2) │ │ │ ├── @ RequiredKeywordParameterNode (location: (21,8)-(21,12)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :bar │ │ │ │ └── name_loc: (21,8)-(21,12) = "bar:" │ │ │ └── @ RequiredKeywordParameterNode (location: (21,14)-(21,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :baz │ │ │ └── name_loc: (21,14)-(21,18) = "baz:" │ │ ├── keyword_rest: ∅ @@ -430,6 +432,7 @@ │ │ @ ParametersNode (location: (51,8)-(51,11)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (51,8)-(51,11)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :bar │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -459,8 +462,10 @@ │ │ @ ParametersNode (location: (55,8)-(55,16)) │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (55,8)-(55,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :bar │ │ │ └── @ RequiredParameterNode (location: (55,13)-(55,16)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :baz │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -491,6 +496,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (59,8)-(59,16)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ ├── name_loc: (59,8)-(59,11) = "bar" │ │ │ ├── operator_loc: (59,12)-(59,13) = "=" @@ -527,6 +533,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (63,8)-(63,24)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ ├── name_loc: (63,8)-(63,11) = "bar" │ │ │ ├── operator_loc: (63,12)-(63,13) = "=" @@ -571,6 +578,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (66,8)-(66,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ ├── name_loc: (66,8)-(66,11) = "bar" │ │ │ ├── operator_loc: (66,12)-(66,13) = "=" @@ -603,9 +611,11 @@ │ │ @ ParametersNode (location: (70,8)-(70,23)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (70,8)-(70,11)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :bar │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (70,13)-(70,23)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :baz │ │ │ ├── name_loc: (70,13)-(70,16) = "baz" │ │ │ ├── operator_loc: (70,17)-(70,18) = "=" @@ -642,6 +652,7 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) │ │ │ └── @ OptionalKeywordParameterNode (location: (74,8)-(74,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ ├── name_loc: (74,8)-(74,12) = "bar:" │ │ │ └── value: @@ -670,6 +681,7 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) │ │ │ └── @ OptionalKeywordParameterNode (location: (77,8)-(77,16)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ ├── name_loc: (77,8)-(77,12) = "bar:" │ │ │ └── value: @@ -706,6 +718,7 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) │ │ │ └── @ OptionalKeywordParameterNode (location: (80,8)-(80,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ ├── name_loc: (80,8)-(80,12) = "bar:" │ │ │ └── value: @@ -740,6 +753,7 @@ │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (83,8)-(83,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: ∅ │ │ │ ├── name_loc: ∅ │ │ │ └── operator_loc: (83,8)-(83,9) = "*" @@ -778,6 +792,7 @@ │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (87,8)-(87,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ ├── name_loc: (87,9)-(87,12) = "bar" │ │ │ └── operator_loc: (87,8)-(87,9) = "*" @@ -807,10 +822,12 @@ │ │ @ ParametersNode (location: (91,8)-(91,17)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (91,8)-(91,11)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :bar │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (91,13)-(91,17)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :baz │ │ │ ├── name_loc: (91,14)-(91,17) = "baz" │ │ │ └── operator_loc: (91,13)-(91,14) = "*" @@ -841,6 +858,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (95,8)-(95,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :baz │ │ │ ├── name_loc: (95,8)-(95,11) = "baz" │ │ │ ├── operator_loc: (95,12)-(95,13) = "=" @@ -848,6 +866,7 @@ │ │ │ @ TrueNode (location: (95,14)-(95,18)) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (95,20)-(95,24)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bor │ │ │ ├── name_loc: (95,21)-(95,24) = "bor" │ │ │ └── operator_loc: (95,20)-(95,21) = "*" @@ -885,6 +904,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (99,8)-(99,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :baz │ │ │ ├── name_loc: (99,8)-(99,11) = "baz" │ │ │ ├── operator_loc: (99,12)-(99,13) = "=" @@ -892,6 +912,7 @@ │ │ │ @ TrueNode (location: (99,14)-(99,18)) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (99,20)-(99,24)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bor │ │ │ ├── name_loc: (99,21)-(99,24) = "bor" │ │ │ └── operator_loc: (99,20)-(99,21) = "*" @@ -900,6 +921,7 @@ │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (99,26)-(99,32)) + │ │ ├── flags: ∅ │ │ ├── name: :block │ │ ├── name_loc: (99,27)-(99,32) = "block" │ │ └── operator_loc: (99,26)-(99,27) = "&" @@ -932,9 +954,11 @@ │ │ @ ParametersNode (location: (103,8)-(103,29)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (103,8)-(103,11)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :bar │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (103,13)-(103,23)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :baz │ │ │ ├── name_loc: (103,13)-(103,16) = "baz" │ │ │ ├── operator_loc: (103,17)-(103,18) = "=" @@ -942,6 +966,7 @@ │ │ │ @ TrueNode (location: (103,19)-(103,23)) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (103,25)-(103,29)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bor │ │ │ ├── name_loc: (103,26)-(103,29) = "bor" │ │ │ └── operator_loc: (103,25)-(103,26) = "*" @@ -977,6 +1002,7 @@ │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (107,8)-(107,14)) + │ │ ├── flags: ∅ │ │ ├── name: :block │ │ ├── name_loc: (107,9)-(107,14) = "block" │ │ └── operator_loc: (107,8)-(107,9) = "&" @@ -1009,6 +1035,7 @@ │ │ @ ParametersNode (location: (111,8)-(111,19)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (111,8)-(111,11)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :bar │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -1017,6 +1044,7 @@ │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (111,13)-(111,19)) + │ │ ├── flags: ∅ │ │ ├── name: :block │ │ ├── name_loc: (111,14)-(111,19) = "block" │ │ └── operator_loc: (111,13)-(111,14) = "&" @@ -1082,6 +1110,7 @@ │ │ │ │ └── @ MultiTargetNode (location: (120,7)-(120,10)) │ │ │ │ ├── lefts: (length: 1) │ │ │ │ │ └── @ RequiredParameterNode (location: (120,8)-(120,9)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :a │ │ │ │ ├── rest: ∅ │ │ │ │ ├── rights: (length: 0) @@ -1118,9 +1147,11 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 2) │ │ │ ├── @ RequiredKeywordParameterNode (location: (123,8)-(123,12)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :bar │ │ │ │ └── name_loc: (123,8)-(123,12) = "bar:" │ │ │ └── @ OptionalKeywordParameterNode (location: (123,14)-(123,26)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :baz │ │ │ ├── name_loc: (123,14)-(123,18) = "baz:" │ │ │ └── value: diff --git a/test/prism/snapshots/unparser/corpus/literal/defs.txt b/test/prism/snapshots/unparser/corpus/literal/defs.txt index 196cef2dc57b6f..97bf48af32f6fa 100644 --- a/test/prism/snapshots/unparser/corpus/literal/defs.txt +++ b/test/prism/snapshots/unparser/corpus/literal/defs.txt @@ -135,6 +135,7 @@ │ │ │ │ │ @ ParametersNode (location: (17,12)-(17,15)) │ │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ │ └── @ RequiredParameterNode (location: (17,12)-(17,15)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── name: :bar │ │ │ │ │ ├── optionals: (length: 0) │ │ │ │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/dstr.txt b/test/prism/snapshots/unparser/corpus/literal/dstr.txt index 45c399720ef6d1..a960746a3e42ca 100644 --- a/test/prism/snapshots/unparser/corpus/literal/dstr.txt +++ b/test/prism/snapshots/unparser/corpus/literal/dstr.txt @@ -325,6 +325,7 @@ │ │ @ ParametersNode (location: (34,19)-(34,20)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (34,19)-(34,20)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :x │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/if.txt b/test/prism/snapshots/unparser/corpus/literal/if.txt index 2c019ff502a9d6..08682ab155d8cb 100644 --- a/test/prism/snapshots/unparser/corpus/literal/if.txt +++ b/test/prism/snapshots/unparser/corpus/literal/if.txt @@ -239,6 +239,7 @@ │ │ │ @ ParametersNode (location: (31,10)-(31,14)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (31,10)-(31,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :pair │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/lambda.txt b/test/prism/snapshots/unparser/corpus/literal/lambda.txt index 1a00ea9a59a82d..33629895544672 100644 --- a/test/prism/snapshots/unparser/corpus/literal/lambda.txt +++ b/test/prism/snapshots/unparser/corpus/literal/lambda.txt @@ -39,8 +39,10 @@ │ │ │ @ ParametersNode (location: (3,10)-(3,14)) │ │ │ ├── requireds: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (3,10)-(3,11)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :a │ │ │ │ └── @ RequiredParameterNode (location: (3,13)-(3,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -84,6 +86,7 @@ │ │ │ @ ParametersNode (location: (8,3)-(8,4)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (8,3)-(8,4)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -107,8 +110,10 @@ │ │ │ @ ParametersNode (location: (10,3)-(10,7)) │ │ │ ├── requireds: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (10,3)-(10,4)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :a │ │ │ │ └── @ RequiredParameterNode (location: (10,6)-(10,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -132,8 +137,10 @@ │ │ @ ParametersNode (location: (12,3)-(12,7)) │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (12,3)-(12,4)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ └── @ RequiredParameterNode (location: (12,6)-(12,7)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :b │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -143,6 +150,7 @@ │ │ └── block: ∅ │ ├── locals: (length: 1) │ │ └── @ BlockLocalVariableNode (location: (12,9)-(12,10)) + │ │ ├── flags: ∅ │ │ └── name: :c │ ├── opening_loc: (12,2)-(12,3) = "(" │ └── closing_loc: (12,10)-(12,11) = ")" diff --git a/test/prism/snapshots/unparser/corpus/literal/since/31.txt b/test/prism/snapshots/unparser/corpus/literal/since/31.txt index 7a033021e2b52b..7927a8e44ad64a 100644 --- a/test/prism/snapshots/unparser/corpus/literal/since/31.txt +++ b/test/prism/snapshots/unparser/corpus/literal/since/31.txt @@ -17,6 +17,7 @@ │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (1,8)-(1,9)) + │ │ ├── flags: ∅ │ │ ├── name: ∅ │ │ ├── name_loc: ∅ │ │ └── operator_loc: (1,8)-(1,9) = "&" @@ -52,6 +53,7 @@ │ @ ParametersNode (location: (5,8)-(5,12)) │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (5,8)-(5,9)) + │ │ ├── flags: ∅ │ │ └── name: :a │ ├── optionals: (length: 0) │ ├── rest: ∅ @@ -60,6 +62,7 @@ │ ├── keyword_rest: ∅ │ └── block: │ @ BlockParameterNode (location: (5,11)-(5,12)) + │ ├── flags: ∅ │ ├── name: ∅ │ ├── name_loc: ∅ │ └── operator_loc: (5,11)-(5,12) = "&" diff --git a/test/prism/snapshots/unparser/corpus/literal/since/32.txt b/test/prism/snapshots/unparser/corpus/literal/since/32.txt index 1678985f7e63c9..a202628595c631 100644 --- a/test/prism/snapshots/unparser/corpus/literal/since/32.txt +++ b/test/prism/snapshots/unparser/corpus/literal/since/32.txt @@ -11,6 +11,7 @@ │ │ @ ParametersNode (location: (1,8)-(1,20)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,8)-(1,16)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :argument │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -18,6 +19,7 @@ │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: │ │ │ @ KeywordRestParameterNode (location: (1,18)-(1,20)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: ∅ │ │ │ ├── name_loc: ∅ │ │ │ └── operator_loc: (1,18)-(1,20) = "**" @@ -63,10 +65,12 @@ │ @ ParametersNode (location: (5,8)-(5,19)) │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (5,8)-(5,16)) + │ │ ├── flags: ∅ │ │ └── name: :argument │ ├── optionals: (length: 0) │ ├── rest: │ │ @ RestParameterNode (location: (5,18)-(5,19)) + │ │ ├── flags: ∅ │ │ ├── name: ∅ │ │ ├── name_loc: ∅ │ │ └── operator_loc: (5,18)-(5,19) = "*" diff --git a/test/prism/snapshots/unparser/corpus/literal/while.txt b/test/prism/snapshots/unparser/corpus/literal/while.txt index ae006ea41f90fa..ac015b1cc6a533 100644 --- a/test/prism/snapshots/unparser/corpus/literal/while.txt +++ b/test/prism/snapshots/unparser/corpus/literal/while.txt @@ -31,6 +31,7 @@ │ │ │ │ @ ParametersNode (location: (2,9)-(2,12)) │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ └── @ RequiredParameterNode (location: (2,9)-(2,12)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :bar │ │ │ │ ├── optionals: (length: 0) │ │ │ │ ├── rest: ∅ @@ -290,6 +291,7 @@ │ │ │ │ @ ParametersNode (location: (28,10)-(28,13)) │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ └── @ RequiredParameterNode (location: (28,10)-(28,13)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :baz │ │ │ │ ├── optionals: (length: 0) │ │ │ │ ├── rest: ∅ @@ -369,6 +371,7 @@ │ │ │ │ @ ParametersNode (location: (36,10)-(36,13)) │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ └── @ RequiredParameterNode (location: (36,10)-(36,13)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :foo │ │ │ │ ├── optionals: (length: 0) │ │ │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/unparser/corpus/semantic/block.txt b/test/prism/snapshots/unparser/corpus/semantic/block.txt index c62afa6d37f922..55190730db1a60 100644 --- a/test/prism/snapshots/unparser/corpus/semantic/block.txt +++ b/test/prism/snapshots/unparser/corpus/semantic/block.txt @@ -96,6 +96,7 @@ │ │ │ @ ParametersNode (location: (13,8)-(13,9)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (13,8)-(13,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -137,6 +138,7 @@ │ │ │ @ ParametersNode (location: (16,16)-(16,17)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (16,16)-(16,17)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/while.txt b/test/prism/snapshots/while.txt index bb2d86dcc7e57f..a2919154f2a3a5 100644 --- a/test/prism/snapshots/while.txt +++ b/test/prism/snapshots/while.txt @@ -119,6 +119,7 @@ │ │ │ ├── requireds: (length: 0) │ │ │ ├── optionals: (length: 1) │ │ │ │ └── @ OptionalParameterNode (location: (13,19)-(13,33)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :a │ │ │ │ ├── name_loc: (13,19)-(13,20) = "a" │ │ │ │ ├── operator_loc: (13,21)-(13,22) = "=" diff --git a/test/prism/snapshots/whitequark/anonymous_blockarg.txt b/test/prism/snapshots/whitequark/anonymous_blockarg.txt index 8e0c70a4b30e29..aaeef280a0d106 100644 --- a/test/prism/snapshots/whitequark/anonymous_blockarg.txt +++ b/test/prism/snapshots/whitequark/anonymous_blockarg.txt @@ -17,6 +17,7 @@ │ ├── keyword_rest: ∅ │ └── block: │ @ BlockParameterNode (location: (1,8)-(1,9)) + │ ├── flags: ∅ │ ├── name: ∅ │ ├── name_loc: ∅ │ └── operator_loc: (1,8)-(1,9) = "&" diff --git a/test/prism/snapshots/whitequark/arg.txt b/test/prism/snapshots/whitequark/arg.txt index 8e3cd2ec69eb84..fc9f701631ada5 100644 --- a/test/prism/snapshots/whitequark/arg.txt +++ b/test/prism/snapshots/whitequark/arg.txt @@ -11,6 +11,7 @@ │ │ @ ParametersNode (location: (1,6)-(1,9)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,6)-(1,9)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :foo │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -35,8 +36,10 @@ │ @ ParametersNode (location: (3,6)-(3,14)) │ ├── requireds: (length: 2) │ │ ├── @ RequiredParameterNode (location: (3,6)-(3,9)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :foo │ │ └── @ RequiredParameterNode (location: (3,11)-(3,14)) + │ │ ├── flags: ∅ │ │ └── name: :bar │ ├── optionals: (length: 0) │ ├── rest: ∅ diff --git a/test/prism/snapshots/whitequark/arg_duplicate_ignored.txt b/test/prism/snapshots/whitequark/arg_duplicate_ignored.txt index 11a3bcc986e69c..a0778b8f7a2bc4 100644 --- a/test/prism/snapshots/whitequark/arg_duplicate_ignored.txt +++ b/test/prism/snapshots/whitequark/arg_duplicate_ignored.txt @@ -11,8 +11,10 @@ │ │ @ ParametersNode (location: (1,8)-(1,12)) │ │ ├── requireds: (length: 2) │ │ │ ├── @ RequiredParameterNode (location: (1,8)-(1,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :_ │ │ │ └── @ RequiredParameterNode (location: (1,11)-(1,12)) + │ │ │ ├── flags: repeated_parameter │ │ │ └── name: :_ │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -37,8 +39,10 @@ │ @ ParametersNode (location: (3,8)-(3,14)) │ ├── requireds: (length: 2) │ │ ├── @ RequiredParameterNode (location: (3,8)-(3,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :_a │ │ └── @ RequiredParameterNode (location: (3,12)-(3,14)) + │ │ ├── flags: repeated_parameter │ │ └── name: :_a │ ├── optionals: (length: 0) │ ├── rest: ∅ diff --git a/test/prism/snapshots/whitequark/arg_scope.txt b/test/prism/snapshots/whitequark/arg_scope.txt index adbe43f03d943e..0a4788f4fd4fd9 100644 --- a/test/prism/snapshots/whitequark/arg_scope.txt +++ b/test/prism/snapshots/whitequark/arg_scope.txt @@ -21,6 +21,7 @@ │ ├── parameters: ∅ │ ├── locals: (length: 1) │ │ └── @ BlockLocalVariableNode (location: (1,9)-(1,10)) + │ │ ├── flags: ∅ │ │ └── name: :a │ ├── opening_loc: (1,7)-(1,8) = "|" │ └── closing_loc: (1,10)-(1,11) = "|" diff --git a/test/prism/snapshots/whitequark/args.txt b/test/prism/snapshots/whitequark/args.txt index 3346517743cd29..927ee3c1fecd1e 100644 --- a/test/prism/snapshots/whitequark/args.txt +++ b/test/prism/snapshots/whitequark/args.txt @@ -17,6 +17,7 @@ │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (1,6)-(1,8)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (1,7)-(1,8) = "b" │ │ └── operator_loc: (1,6)-(1,7) = "&" @@ -41,6 +42,7 @@ │ │ │ │ └── @ MultiTargetNode (location: (3,8)-(3,11)) │ │ │ │ ├── lefts: (length: 1) │ │ │ │ │ └── @ RequiredParameterNode (location: (3,9)-(3,10)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :a │ │ │ │ ├── rest: ∅ │ │ │ │ ├── rights: (length: 0) @@ -111,6 +113,7 @@ │ │ │ │ └── expression: ∅ │ │ │ ├── rights: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (7,11)-(7,12)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :p │ │ │ ├── lparen_loc: (7,7)-(7,8) = "(" │ │ │ └── rparen_loc: (7,12)-(7,13) = ")" @@ -143,6 +146,7 @@ │ │ │ │ ├── operator_loc: (9,8)-(9,9) = "*" │ │ │ │ └── expression: │ │ │ │ @ RequiredParameterNode (location: (9,9)-(9,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :r │ │ │ ├── rights: (length: 0) │ │ │ ├── lparen_loc: (9,7)-(9,8) = "(" @@ -176,9 +180,11 @@ │ │ │ │ ├── operator_loc: (11,8)-(11,9) = "*" │ │ │ │ └── expression: │ │ │ │ @ RequiredParameterNode (location: (11,9)-(11,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :r │ │ │ ├── rights: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (11,12)-(11,13)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :p │ │ │ ├── lparen_loc: (11,7)-(11,8) = "(" │ │ │ └── rparen_loc: (11,13)-(11,14) = ")" @@ -207,6 +213,7 @@ │ │ │ └── @ MultiTargetNode (location: (13,7)-(13,13)) │ │ │ ├── lefts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (13,8)-(13,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (13,11)-(13,12)) @@ -240,6 +247,7 @@ │ │ │ └── @ MultiTargetNode (location: (15,7)-(15,16)) │ │ │ ├── lefts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (15,8)-(15,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (15,11)-(15,12)) @@ -247,6 +255,7 @@ │ │ │ │ └── expression: ∅ │ │ │ ├── rights: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (15,14)-(15,15)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :p │ │ │ ├── lparen_loc: (15,7)-(15,8) = "(" │ │ │ └── rparen_loc: (15,15)-(15,16) = ")" @@ -275,12 +284,14 @@ │ │ │ └── @ MultiTargetNode (location: (17,7)-(17,14)) │ │ │ ├── lefts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (17,8)-(17,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (17,11)-(17,13)) │ │ │ │ ├── operator_loc: (17,11)-(17,12) = "*" │ │ │ │ └── expression: │ │ │ │ @ RequiredParameterNode (location: (17,12)-(17,13)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :r │ │ │ ├── rights: (length: 0) │ │ │ ├── lparen_loc: (17,7)-(17,8) = "(" @@ -310,15 +321,18 @@ │ │ │ └── @ MultiTargetNode (location: (19,7)-(19,17)) │ │ │ ├── lefts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (19,8)-(19,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── rest: │ │ │ │ @ SplatNode (location: (19,11)-(19,13)) │ │ │ │ ├── operator_loc: (19,11)-(19,12) = "*" │ │ │ │ └── expression: │ │ │ │ @ RequiredParameterNode (location: (19,12)-(19,13)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :r │ │ │ ├── rights: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (19,15)-(19,16)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :p │ │ │ ├── lparen_loc: (19,7)-(19,8) = "(" │ │ │ └── rparen_loc: (19,16)-(19,17) = ")" @@ -347,8 +361,10 @@ │ │ │ └── @ MultiTargetNode (location: (21,7)-(21,14)) │ │ │ ├── lefts: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (21,8)-(21,9)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :a │ │ │ │ └── @ RequiredParameterNode (location: (21,11)-(21,13)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a1 │ │ │ ├── rest: ∅ │ │ │ ├── rights: (length: 0) @@ -381,6 +397,7 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) │ │ │ └── @ OptionalKeywordParameterNode (location: (23,7)-(23,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :foo │ │ │ ├── name_loc: (23,7)-(23,11) = "foo:" │ │ │ └── value: @@ -389,6 +406,7 @@ │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (23,15)-(23,17)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (23,16)-(23,17) = "b" │ │ └── operator_loc: (23,15)-(23,16) = "&" @@ -413,12 +431,14 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 2) │ │ │ ├── @ OptionalKeywordParameterNode (location: (25,7)-(25,13)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :foo │ │ │ │ ├── name_loc: (25,7)-(25,11) = "foo:" │ │ │ │ └── value: │ │ │ │ @ IntegerNode (location: (25,12)-(25,13)) │ │ │ │ └── flags: decimal │ │ │ └── @ OptionalKeywordParameterNode (location: (25,15)-(25,21)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :bar │ │ │ ├── name_loc: (25,15)-(25,19) = "bar:" │ │ │ └── value: @@ -426,11 +446,13 @@ │ │ │ └── flags: decimal │ │ ├── keyword_rest: │ │ │ @ KeywordRestParameterNode (location: (25,23)-(25,28)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :baz │ │ │ ├── name_loc: (25,25)-(25,28) = "baz" │ │ │ └── operator_loc: (25,23)-(25,25) = "**" │ │ └── block: │ │ @ BlockParameterNode (location: (25,30)-(25,32)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (25,31)-(25,32) = "b" │ │ └── operator_loc: (25,30)-(25,31) = "&" @@ -456,11 +478,13 @@ │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: │ │ │ @ KeywordRestParameterNode (location: (27,6)-(27,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :baz │ │ │ ├── name_loc: (27,8)-(27,11) = "baz" │ │ │ └── operator_loc: (27,6)-(27,8) = "**" │ │ └── block: │ │ @ BlockParameterNode (location: (27,13)-(27,15)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (27,14)-(27,15) = "b" │ │ └── operator_loc: (27,13)-(27,14) = "&" @@ -483,6 +507,7 @@ │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (29,6)-(29,7)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: ∅ │ │ │ ├── name_loc: ∅ │ │ │ └── operator_loc: (29,6)-(29,7) = "*" @@ -490,6 +515,7 @@ │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: │ │ │ @ KeywordRestParameterNode (location: (29,9)-(29,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: ∅ │ │ │ ├── name_loc: ∅ │ │ │ └── operator_loc: (29,9)-(29,11) = "**" @@ -513,6 +539,7 @@ │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (31,6)-(31,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :r │ │ │ ├── name_loc: (31,7)-(31,8) = "r" │ │ │ └── operator_loc: (31,6)-(31,7) = "*" @@ -521,6 +548,7 @@ │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (31,10)-(31,12)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (31,11)-(31,12) = "b" │ │ └── operator_loc: (31,10)-(31,11) = "&" @@ -543,16 +571,19 @@ │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (33,6)-(33,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :r │ │ │ ├── name_loc: (33,7)-(33,8) = "r" │ │ │ └── operator_loc: (33,6)-(33,7) = "*" │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (33,10)-(33,11)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :p │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (33,13)-(33,15)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (33,14)-(33,15) = "b" │ │ └── operator_loc: (33,13)-(33,14) = "&" @@ -587,6 +618,7 @@ │ │ @ ParametersNode (location: (37,6)-(37,11)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (37,6)-(37,7)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -595,6 +627,7 @@ │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (37,9)-(37,11)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (37,10)-(37,11) = "b" │ │ └── operator_loc: (37,9)-(37,10) = "&" @@ -615,10 +648,12 @@ │ │ @ ParametersNode (location: (39,6)-(39,15)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (39,6)-(39,7)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (39,9)-(39,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :r │ │ │ ├── name_loc: (39,10)-(39,11) = "r" │ │ │ └── operator_loc: (39,9)-(39,10) = "*" @@ -627,6 +662,7 @@ │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (39,13)-(39,15)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (39,14)-(39,15) = "b" │ │ └── operator_loc: (39,13)-(39,14) = "&" @@ -647,20 +683,24 @@ │ │ @ ParametersNode (location: (41,6)-(41,18)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (41,6)-(41,7)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 0) │ │ ├── rest: │ │ │ @ RestParameterNode (location: (41,9)-(41,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :r │ │ │ ├── name_loc: (41,10)-(41,11) = "r" │ │ │ └── operator_loc: (41,9)-(41,10) = "*" │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (41,13)-(41,14)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :p │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (41,16)-(41,18)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (41,17)-(41,18) = "b" │ │ └── operator_loc: (41,16)-(41,17) = "&" @@ -681,9 +721,11 @@ │ │ @ ParametersNode (location: (43,6)-(43,16)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (43,6)-(43,7)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (43,9)-(43,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :o │ │ │ ├── name_loc: (43,9)-(43,10) = "o" │ │ │ ├── operator_loc: (43,10)-(43,11) = "=" @@ -696,6 +738,7 @@ │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (43,14)-(43,16)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (43,15)-(43,16) = "b" │ │ └── operator_loc: (43,14)-(43,15) = "&" @@ -716,9 +759,11 @@ │ │ @ ParametersNode (location: (45,6)-(45,20)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (45,6)-(45,7)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (45,9)-(45,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :o │ │ │ ├── name_loc: (45,9)-(45,10) = "o" │ │ │ ├── operator_loc: (45,10)-(45,11) = "=" @@ -727,6 +772,7 @@ │ │ │ └── flags: decimal │ │ ├── rest: │ │ │ @ RestParameterNode (location: (45,14)-(45,16)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :r │ │ │ ├── name_loc: (45,15)-(45,16) = "r" │ │ │ └── operator_loc: (45,14)-(45,15) = "*" @@ -735,6 +781,7 @@ │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (45,18)-(45,20)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (45,19)-(45,20) = "b" │ │ └── operator_loc: (45,18)-(45,19) = "&" @@ -755,9 +802,11 @@ │ │ @ ParametersNode (location: (47,6)-(47,23)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (47,6)-(47,7)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (47,9)-(47,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :o │ │ │ ├── name_loc: (47,9)-(47,10) = "o" │ │ │ ├── operator_loc: (47,10)-(47,11) = "=" @@ -766,16 +815,19 @@ │ │ │ └── flags: decimal │ │ ├── rest: │ │ │ @ RestParameterNode (location: (47,14)-(47,16)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :r │ │ │ ├── name_loc: (47,15)-(47,16) = "r" │ │ │ └── operator_loc: (47,14)-(47,15) = "*" │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (47,18)-(47,19)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :p │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (47,21)-(47,23)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (47,22)-(47,23) = "b" │ │ └── operator_loc: (47,21)-(47,22) = "&" @@ -796,9 +848,11 @@ │ │ @ ParametersNode (location: (49,6)-(49,19)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (49,6)-(49,7)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (49,9)-(49,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :o │ │ │ ├── name_loc: (49,9)-(49,10) = "o" │ │ │ ├── operator_loc: (49,10)-(49,11) = "=" @@ -808,11 +862,13 @@ │ │ ├── rest: ∅ │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (49,14)-(49,15)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :p │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (49,17)-(49,19)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (49,18)-(49,19) = "b" │ │ └── operator_loc: (49,17)-(49,18) = "&" @@ -837,6 +893,7 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) │ │ │ └── @ RequiredKeywordParameterNode (location: (51,6)-(51,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :foo │ │ │ └── name_loc: (51,6)-(51,10) = "foo:" │ │ ├── keyword_rest: ∅ @@ -862,6 +919,7 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) │ │ │ └── @ OptionalKeywordParameterNode (location: (54,6)-(54,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :foo │ │ │ ├── name_loc: (54,6)-(54,10) = "foo:" │ │ │ └── value: @@ -887,6 +945,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (57,6)-(57,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :o │ │ │ ├── name_loc: (57,6)-(57,7) = "o" │ │ │ ├── operator_loc: (57,7)-(57,8) = "=" @@ -899,6 +958,7 @@ │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (57,11)-(57,13)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (57,12)-(57,13) = "b" │ │ └── operator_loc: (57,11)-(57,12) = "&" @@ -920,6 +980,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (59,6)-(59,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :o │ │ │ ├── name_loc: (59,6)-(59,7) = "o" │ │ │ ├── operator_loc: (59,7)-(59,8) = "=" @@ -928,6 +989,7 @@ │ │ │ └── flags: decimal │ │ ├── rest: │ │ │ @ RestParameterNode (location: (59,11)-(59,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :r │ │ │ ├── name_loc: (59,12)-(59,13) = "r" │ │ │ └── operator_loc: (59,11)-(59,12) = "*" @@ -936,6 +998,7 @@ │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (59,15)-(59,17)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (59,16)-(59,17) = "b" │ │ └── operator_loc: (59,15)-(59,16) = "&" @@ -957,6 +1020,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (61,6)-(61,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :o │ │ │ ├── name_loc: (61,6)-(61,7) = "o" │ │ │ ├── operator_loc: (61,7)-(61,8) = "=" @@ -965,16 +1029,19 @@ │ │ │ └── flags: decimal │ │ ├── rest: │ │ │ @ RestParameterNode (location: (61,11)-(61,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :r │ │ │ ├── name_loc: (61,12)-(61,13) = "r" │ │ │ └── operator_loc: (61,11)-(61,12) = "*" │ │ ├── posts: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (61,15)-(61,16)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :p │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ │ │ └── block: │ │ @ BlockParameterNode (location: (61,18)-(61,20)) + │ │ ├── flags: ∅ │ │ ├── name: :b │ │ ├── name_loc: (61,19)-(61,20) = "b" │ │ └── operator_loc: (61,18)-(61,19) = "&" @@ -996,6 +1063,7 @@ │ ├── requireds: (length: 0) │ ├── optionals: (length: 1) │ │ └── @ OptionalParameterNode (location: (63,6)-(63,9)) + │ │ ├── flags: ∅ │ │ ├── name: :o │ │ ├── name_loc: (63,6)-(63,7) = "o" │ │ ├── operator_loc: (63,7)-(63,8) = "=" @@ -1005,11 +1073,13 @@ │ ├── rest: ∅ │ ├── posts: (length: 1) │ │ └── @ RequiredParameterNode (location: (63,11)-(63,12)) + │ │ ├── flags: ∅ │ │ └── name: :p │ ├── keywords: (length: 0) │ ├── keyword_rest: ∅ │ └── block: │ @ BlockParameterNode (location: (63,14)-(63,16)) + │ ├── flags: ∅ │ ├── name: :b │ ├── name_loc: (63,15)-(63,16) = "b" │ └── operator_loc: (63,14)-(63,15) = "&" diff --git a/test/prism/snapshots/whitequark/blockarg.txt b/test/prism/snapshots/whitequark/blockarg.txt index ce3bb106b57b34..fd0dac3cb28348 100644 --- a/test/prism/snapshots/whitequark/blockarg.txt +++ b/test/prism/snapshots/whitequark/blockarg.txt @@ -17,6 +17,7 @@ │ ├── keyword_rest: ∅ │ └── block: │ @ BlockParameterNode (location: (1,6)-(1,12)) + │ ├── flags: ∅ │ ├── name: :block │ ├── name_loc: (1,7)-(1,12) = "block" │ └── operator_loc: (1,6)-(1,7) = "&" diff --git a/test/prism/snapshots/whitequark/blockargs.txt b/test/prism/snapshots/whitequark/blockargs.txt index 6e87c70633c339..36610d66bf0f71 100644 --- a/test/prism/snapshots/whitequark/blockargs.txt +++ b/test/prism/snapshots/whitequark/blockargs.txt @@ -67,6 +67,7 @@ │ │ │ ├── keyword_rest: ∅ │ │ │ └── block: │ │ │ @ BlockParameterNode (location: (5,4)-(5,6)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (5,5)-(5,6) = "b" │ │ │ └── operator_loc: (5,4)-(5,5) = "&" @@ -100,11 +101,13 @@ │ │ │ ├── keywords: (length: 0) │ │ │ ├── keyword_rest: │ │ │ │ @ KeywordRestParameterNode (location: (7,4)-(7,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ ├── name_loc: (7,6)-(7,9) = "baz" │ │ │ │ └── operator_loc: (7,4)-(7,6) = "**" │ │ │ └── block: │ │ │ @ BlockParameterNode (location: (7,11)-(7,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (7,12)-(7,13) = "b" │ │ │ └── operator_loc: (7,11)-(7,12) = "&" @@ -135,6 +138,7 @@ │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (9,4)-(9,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: ∅ │ │ │ │ ├── name_loc: ∅ │ │ │ │ └── operator_loc: (9,4)-(9,5) = "*" @@ -143,6 +147,7 @@ │ │ │ ├── keyword_rest: ∅ │ │ │ └── block: │ │ │ @ BlockParameterNode (location: (9,7)-(9,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (9,8)-(9,9) = "b" │ │ │ └── operator_loc: (9,7)-(9,8) = "&" @@ -173,16 +178,19 @@ │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (11,4)-(11,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :r │ │ │ │ ├── name_loc: (11,5)-(11,6) = "r" │ │ │ │ └── operator_loc: (11,4)-(11,5) = "*" │ │ │ ├── posts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (11,8)-(11,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :p │ │ │ ├── keywords: (length: 0) │ │ │ ├── keyword_rest: ∅ │ │ │ └── block: │ │ │ @ BlockParameterNode (location: (11,11)-(11,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (11,12)-(11,13) = "b" │ │ │ └── operator_loc: (11,11)-(11,12) = "&" @@ -213,6 +221,7 @@ │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (13,4)-(13,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :s │ │ │ │ ├── name_loc: (13,5)-(13,6) = "s" │ │ │ │ └── operator_loc: (13,4)-(13,5) = "*" @@ -221,6 +230,7 @@ │ │ │ ├── keyword_rest: ∅ │ │ │ └── block: │ │ │ @ BlockParameterNode (location: (13,8)-(13,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (13,9)-(13,10) = "b" │ │ │ └── operator_loc: (13,8)-(13,9) = "&" @@ -251,6 +261,7 @@ │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (15,4)-(15,6)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :s │ │ │ │ ├── name_loc: (15,5)-(15,6) = "s" │ │ │ │ └── operator_loc: (15,4)-(15,5) = "*" @@ -285,6 +296,7 @@ │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (17,4)-(17,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: ∅ │ │ │ │ ├── name_loc: ∅ │ │ │ │ └── operator_loc: (17,4)-(17,5) = "*" @@ -316,6 +328,7 @@ │ │ ├── parameters: ∅ │ │ ├── locals: (length: 1) │ │ │ └── @ BlockLocalVariableNode (location: (20,0)-(20,1)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── opening_loc: (19,3)-(19,4) = "|" │ │ └── closing_loc: (21,0)-(21,1) = "|" @@ -340,6 +353,7 @@ │ │ ├── parameters: ∅ │ │ ├── locals: (length: 1) │ │ │ └── @ BlockLocalVariableNode (location: (23,5)-(23,6)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── opening_loc: (23,3)-(23,4) = "|" │ │ └── closing_loc: (23,6)-(23,7) = "|" @@ -365,6 +379,7 @@ │ │ │ @ ParametersNode (location: (25,4)-(25,9)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (25,4)-(25,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -373,6 +388,7 @@ │ │ │ ├── keyword_rest: ∅ │ │ │ └── block: │ │ │ @ BlockParameterNode (location: (25,7)-(25,9)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (25,8)-(25,9) = "b" │ │ │ └── operator_loc: (25,7)-(25,8) = "&" @@ -401,10 +417,12 @@ │ │ │ @ ParametersNode (location: (27,4)-(27,12)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (27,4)-(27,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (27,7)-(27,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: ∅ │ │ │ │ ├── name_loc: ∅ │ │ │ │ └── operator_loc: (27,7)-(27,8) = "*" @@ -413,6 +431,7 @@ │ │ │ ├── keyword_rest: ∅ │ │ │ └── block: │ │ │ @ BlockParameterNode (location: (27,10)-(27,12)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (27,11)-(27,12) = "b" │ │ │ └── operator_loc: (27,10)-(27,11) = "&" @@ -441,20 +460,24 @@ │ │ │ @ ParametersNode (location: (29,4)-(29,16)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (29,4)-(29,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (29,7)-(29,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :r │ │ │ │ ├── name_loc: (29,8)-(29,9) = "r" │ │ │ │ └── operator_loc: (29,7)-(29,8) = "*" │ │ │ ├── posts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (29,11)-(29,12)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :p │ │ │ ├── keywords: (length: 0) │ │ │ ├── keyword_rest: ∅ │ │ │ └── block: │ │ │ @ BlockParameterNode (location: (29,14)-(29,16)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (29,15)-(29,16) = "b" │ │ │ └── operator_loc: (29,14)-(29,15) = "&" @@ -483,10 +506,12 @@ │ │ │ @ ParametersNode (location: (31,4)-(31,13)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (31,4)-(31,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (31,7)-(31,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :s │ │ │ │ ├── name_loc: (31,8)-(31,9) = "s" │ │ │ │ └── operator_loc: (31,7)-(31,8) = "*" @@ -495,6 +520,7 @@ │ │ │ ├── keyword_rest: ∅ │ │ │ └── block: │ │ │ @ BlockParameterNode (location: (31,11)-(31,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (31,12)-(31,13) = "b" │ │ │ └── operator_loc: (31,11)-(31,12) = "&" @@ -523,10 +549,12 @@ │ │ │ @ ParametersNode (location: (33,4)-(33,9)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (33,4)-(33,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (33,7)-(33,9)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :s │ │ │ │ ├── name_loc: (33,8)-(33,9) = "s" │ │ │ │ └── operator_loc: (33,7)-(33,8) = "*" @@ -559,10 +587,12 @@ │ │ │ @ ParametersNode (location: (35,4)-(35,8)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (35,4)-(35,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (35,7)-(35,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: ∅ │ │ │ │ ├── name_loc: ∅ │ │ │ │ └── operator_loc: (35,7)-(35,8) = "*" @@ -595,8 +625,10 @@ │ │ │ @ ParametersNode (location: (37,4)-(37,9)) │ │ │ ├── requireds: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (37,4)-(37,5)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :a │ │ │ │ └── @ RequiredParameterNode (location: (37,7)-(37,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: @@ -630,8 +662,10 @@ │ │ │ @ ParametersNode (location: (39,4)-(39,8)) │ │ │ ├── requireds: (length: 2) │ │ │ │ ├── @ RequiredParameterNode (location: (39,4)-(39,5)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :a │ │ │ │ └── @ RequiredParameterNode (location: (39,7)-(39,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :c │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -664,9 +698,11 @@ │ │ │ @ ParametersNode (location: (41,4)-(41,14)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (41,4)-(41,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 1) │ │ │ │ └── @ OptionalParameterNode (location: (41,7)-(41,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :o │ │ │ │ ├── name_loc: (41,7)-(41,8) = "o" │ │ │ │ ├── operator_loc: (41,8)-(41,9) = "=" @@ -679,6 +715,7 @@ │ │ │ ├── keyword_rest: ∅ │ │ │ └── block: │ │ │ @ BlockParameterNode (location: (41,12)-(41,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (41,13)-(41,14) = "b" │ │ │ └── operator_loc: (41,12)-(41,13) = "&" @@ -707,9 +744,11 @@ │ │ │ @ ParametersNode (location: (43,4)-(43,21)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (43,4)-(43,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 1) │ │ │ │ └── @ OptionalParameterNode (location: (43,7)-(43,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :o │ │ │ │ ├── name_loc: (43,7)-(43,8) = "o" │ │ │ │ ├── operator_loc: (43,8)-(43,9) = "=" @@ -718,16 +757,19 @@ │ │ │ │ └── flags: decimal │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (43,12)-(43,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :r │ │ │ │ ├── name_loc: (43,13)-(43,14) = "r" │ │ │ │ └── operator_loc: (43,12)-(43,13) = "*" │ │ │ ├── posts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (43,16)-(43,17)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :p │ │ │ ├── keywords: (length: 0) │ │ │ ├── keyword_rest: ∅ │ │ │ └── block: │ │ │ @ BlockParameterNode (location: (43,19)-(43,21)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (43,20)-(43,21) = "b" │ │ │ └── operator_loc: (43,19)-(43,20) = "&" @@ -756,9 +798,11 @@ │ │ │ @ ParametersNode (location: (45,4)-(45,24)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (45,4)-(45,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 2) │ │ │ │ ├── @ OptionalParameterNode (location: (45,7)-(45,10)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── name: :o │ │ │ │ │ ├── name_loc: (45,7)-(45,8) = "o" │ │ │ │ │ ├── operator_loc: (45,8)-(45,9) = "=" @@ -766,6 +810,7 @@ │ │ │ │ │ @ IntegerNode (location: (45,9)-(45,10)) │ │ │ │ │ └── flags: decimal │ │ │ │ └── @ OptionalParameterNode (location: (45,12)-(45,16)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :o1 │ │ │ │ ├── name_loc: (45,12)-(45,14) = "o1" │ │ │ │ ├── operator_loc: (45,14)-(45,15) = "=" @@ -774,6 +819,7 @@ │ │ │ │ └── flags: decimal │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (45,18)-(45,20)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :r │ │ │ │ ├── name_loc: (45,19)-(45,20) = "r" │ │ │ │ └── operator_loc: (45,18)-(45,19) = "*" @@ -782,6 +828,7 @@ │ │ │ ├── keyword_rest: ∅ │ │ │ └── block: │ │ │ @ BlockParameterNode (location: (45,22)-(45,24)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (45,23)-(45,24) = "b" │ │ │ └── operator_loc: (45,22)-(45,23) = "&" @@ -810,9 +857,11 @@ │ │ │ @ ParametersNode (location: (47,4)-(47,17)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (47,4)-(47,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 1) │ │ │ │ └── @ OptionalParameterNode (location: (47,7)-(47,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :o │ │ │ │ ├── name_loc: (47,7)-(47,8) = "o" │ │ │ │ ├── operator_loc: (47,8)-(47,9) = "=" @@ -822,11 +871,13 @@ │ │ │ ├── rest: ∅ │ │ │ ├── posts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (47,12)-(47,13)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :p │ │ │ ├── keywords: (length: 0) │ │ │ ├── keyword_rest: ∅ │ │ │ └── block: │ │ │ @ BlockParameterNode (location: (47,15)-(47,17)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (47,16)-(47,17) = "b" │ │ │ └── operator_loc: (47,15)-(47,16) = "&" @@ -855,6 +906,7 @@ │ │ │ @ ParametersNode (location: (49,4)-(49,6)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (49,4)-(49,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: @@ -888,6 +940,7 @@ │ │ │ @ ParametersNode (location: (51,4)-(51,5)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (51,4)-(51,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -920,6 +973,7 @@ │ │ │ @ ParametersNode (location: (53,4)-(53,5)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (53,4)-(53,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -952,6 +1006,7 @@ │ │ │ @ ParametersNode (location: (55,4)-(55,5)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (55,4)-(55,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -988,6 +1043,7 @@ │ │ │ ├── posts: (length: 0) │ │ │ ├── keywords: (length: 1) │ │ │ │ └── @ OptionalKeywordParameterNode (location: (57,4)-(57,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :foo │ │ │ │ ├── name_loc: (57,4)-(57,8) = "foo:" │ │ │ │ └── value: @@ -996,6 +1052,7 @@ │ │ │ ├── keyword_rest: ∅ │ │ │ └── block: │ │ │ @ BlockParameterNode (location: (57,12)-(57,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (57,13)-(57,14) = "b" │ │ │ └── operator_loc: (57,12)-(57,13) = "&" @@ -1028,12 +1085,14 @@ │ │ │ ├── posts: (length: 0) │ │ │ ├── keywords: (length: 2) │ │ │ │ ├── @ OptionalKeywordParameterNode (location: (59,4)-(59,10)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── name: :foo │ │ │ │ │ ├── name_loc: (59,4)-(59,8) = "foo:" │ │ │ │ │ └── value: │ │ │ │ │ @ IntegerNode (location: (59,9)-(59,10)) │ │ │ │ │ └── flags: decimal │ │ │ │ └── @ OptionalKeywordParameterNode (location: (59,12)-(59,18)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :bar │ │ │ │ ├── name_loc: (59,12)-(59,16) = "bar:" │ │ │ │ └── value: @@ -1041,11 +1100,13 @@ │ │ │ │ └── flags: decimal │ │ │ ├── keyword_rest: │ │ │ │ @ KeywordRestParameterNode (location: (59,20)-(59,25)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :baz │ │ │ │ ├── name_loc: (59,22)-(59,25) = "baz" │ │ │ │ └── operator_loc: (59,20)-(59,22) = "**" │ │ │ └── block: │ │ │ @ BlockParameterNode (location: (59,27)-(59,29)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (59,28)-(59,29) = "b" │ │ │ └── operator_loc: (59,27)-(59,28) = "&" @@ -1078,6 +1139,7 @@ │ │ │ ├── posts: (length: 0) │ │ │ ├── keywords: (length: 1) │ │ │ │ └── @ RequiredKeywordParameterNode (location: (61,4)-(61,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :foo │ │ │ │ └── name_loc: (61,4)-(61,8) = "foo:" │ │ │ ├── keyword_rest: ∅ @@ -1108,6 +1170,7 @@ │ │ │ ├── requireds: (length: 0) │ │ │ ├── optionals: (length: 1) │ │ │ │ └── @ OptionalParameterNode (location: (63,4)-(63,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :o │ │ │ │ ├── name_loc: (63,4)-(63,5) = "o" │ │ │ │ ├── operator_loc: (63,5)-(63,6) = "=" @@ -1120,6 +1183,7 @@ │ │ │ ├── keyword_rest: ∅ │ │ │ └── block: │ │ │ @ BlockParameterNode (location: (63,9)-(63,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (63,10)-(63,11) = "b" │ │ │ └── operator_loc: (63,9)-(63,10) = "&" @@ -1149,6 +1213,7 @@ │ │ │ ├── requireds: (length: 0) │ │ │ ├── optionals: (length: 1) │ │ │ │ └── @ OptionalParameterNode (location: (65,4)-(65,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :o │ │ │ │ ├── name_loc: (65,4)-(65,5) = "o" │ │ │ │ ├── operator_loc: (65,5)-(65,6) = "=" @@ -1157,6 +1222,7 @@ │ │ │ │ └── flags: decimal │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (65,9)-(65,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :r │ │ │ │ ├── name_loc: (65,10)-(65,11) = "r" │ │ │ │ └── operator_loc: (65,9)-(65,10) = "*" @@ -1165,6 +1231,7 @@ │ │ │ ├── keyword_rest: ∅ │ │ │ └── block: │ │ │ @ BlockParameterNode (location: (65,13)-(65,15)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (65,14)-(65,15) = "b" │ │ │ └── operator_loc: (65,13)-(65,14) = "&" @@ -1194,6 +1261,7 @@ │ │ │ ├── requireds: (length: 0) │ │ │ ├── optionals: (length: 1) │ │ │ │ └── @ OptionalParameterNode (location: (67,4)-(67,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :o │ │ │ │ ├── name_loc: (67,4)-(67,5) = "o" │ │ │ │ ├── operator_loc: (67,5)-(67,6) = "=" @@ -1202,16 +1270,19 @@ │ │ │ │ └── flags: decimal │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (67,9)-(67,11)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :r │ │ │ │ ├── name_loc: (67,10)-(67,11) = "r" │ │ │ │ └── operator_loc: (67,9)-(67,10) = "*" │ │ │ ├── posts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (67,13)-(67,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :p │ │ │ ├── keywords: (length: 0) │ │ │ ├── keyword_rest: ∅ │ │ │ └── block: │ │ │ @ BlockParameterNode (location: (67,16)-(67,18)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (67,17)-(67,18) = "b" │ │ │ └── operator_loc: (67,16)-(67,17) = "&" @@ -1241,6 +1312,7 @@ │ │ │ ├── requireds: (length: 0) │ │ │ ├── optionals: (length: 1) │ │ │ │ └── @ OptionalParameterNode (location: (69,4)-(69,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :o │ │ │ │ ├── name_loc: (69,4)-(69,5) = "o" │ │ │ │ ├── operator_loc: (69,5)-(69,6) = "=" @@ -1250,11 +1322,13 @@ │ │ │ ├── rest: ∅ │ │ │ ├── posts: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (69,9)-(69,10)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :p │ │ │ ├── keywords: (length: 0) │ │ │ ├── keyword_rest: ∅ │ │ │ └── block: │ │ │ @ BlockParameterNode (location: (69,12)-(69,14)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (69,13)-(69,14) = "b" │ │ │ └── operator_loc: (69,12)-(69,13) = "&" diff --git a/test/prism/snapshots/whitequark/bug_435.txt b/test/prism/snapshots/whitequark/bug_435.txt index afce74425eaeda..20210c87df883d 100644 --- a/test/prism/snapshots/whitequark/bug_435.txt +++ b/test/prism/snapshots/whitequark/bug_435.txt @@ -23,6 +23,7 @@ │ │ │ │ @ ParametersNode (location: (1,6)-(1,9)) │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ └── @ RequiredParameterNode (location: (1,6)-(1,9)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :foo │ │ │ │ ├── optionals: (length: 0) │ │ │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/whitequark/bug_lambda_leakage.txt b/test/prism/snapshots/whitequark/bug_lambda_leakage.txt index 96af5544b92d5a..a8f2721cb8431f 100644 --- a/test/prism/snapshots/whitequark/bug_lambda_leakage.txt +++ b/test/prism/snapshots/whitequark/bug_lambda_leakage.txt @@ -15,6 +15,7 @@ │ │ │ @ ParametersNode (location: (1,3)-(1,8)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,3)-(1,8)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :scope │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/whitequark/endless_comparison_method.txt b/test/prism/snapshots/whitequark/endless_comparison_method.txt index c8a9a4c624595f..82f574df0d7ca2 100644 --- a/test/prism/snapshots/whitequark/endless_comparison_method.txt +++ b/test/prism/snapshots/whitequark/endless_comparison_method.txt @@ -11,6 +11,7 @@ │ │ @ ParametersNode (location: (1,7)-(1,12)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,7)-(1,12)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :other │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -47,6 +48,7 @@ │ │ @ ParametersNode (location: (3,7)-(3,12)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (3,7)-(3,12)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :other │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -83,6 +85,7 @@ │ │ @ ParametersNode (location: (5,7)-(5,12)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (5,7)-(5,12)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :other │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -119,6 +122,7 @@ │ │ @ ParametersNode (location: (7,7)-(7,12)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (7,7)-(7,12)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :other │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -155,6 +159,7 @@ │ │ @ ParametersNode (location: (9,8)-(9,13)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (9,8)-(9,13)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :other │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -191,6 +196,7 @@ │ @ ParametersNode (location: (11,7)-(11,12)) │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (11,7)-(11,12)) + │ │ ├── flags: ∅ │ │ └── name: :other │ ├── optionals: (length: 0) │ ├── rest: ∅ diff --git a/test/prism/snapshots/whitequark/endless_method.txt b/test/prism/snapshots/whitequark/endless_method.txt index ab826ccfe1135f..3d681ca459060e 100644 --- a/test/prism/snapshots/whitequark/endless_method.txt +++ b/test/prism/snapshots/whitequark/endless_method.txt @@ -29,6 +29,7 @@ │ │ @ ParametersNode (location: (3,8)-(3,9)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (3,8)-(3,9)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :x │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -111,6 +112,7 @@ │ @ ParametersNode (location: (7,12)-(7,13)) │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (7,12)-(7,13)) + │ │ ├── flags: ∅ │ │ └── name: :x │ ├── optionals: (length: 0) │ ├── rest: ∅ diff --git a/test/prism/snapshots/whitequark/endless_method_command_syntax.txt b/test/prism/snapshots/whitequark/endless_method_command_syntax.txt index c6d5e7150a75f3..c4db8a106faae8 100644 --- a/test/prism/snapshots/whitequark/endless_method_command_syntax.txt +++ b/test/prism/snapshots/whitequark/endless_method_command_syntax.txt @@ -81,6 +81,7 @@ │ │ @ ParametersNode (location: (5,8)-(5,9)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (5,8)-(5,9)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :x │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -223,6 +224,7 @@ │ │ @ ParametersNode (location: (11,12)-(11,13)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (11,12)-(11,13)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :x │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -265,6 +267,7 @@ │ │ @ ParametersNode (location: (13,12)-(13,13)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (13,12)-(13,13)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :x │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -334,6 +337,7 @@ │ @ ParametersNode (location: (15,17)-(15,18)) │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (15,17)-(15,18)) + │ │ ├── flags: ∅ │ │ └── name: :x │ ├── optionals: (length: 0) │ ├── rest: ∅ diff --git a/test/prism/snapshots/whitequark/forward_arg_with_open_args.txt b/test/prism/snapshots/whitequark/forward_arg_with_open_args.txt index 9735edb5efe6c2..75fb87e0e73eca 100644 --- a/test/prism/snapshots/whitequark/forward_arg_with_open_args.txt +++ b/test/prism/snapshots/whitequark/forward_arg_with_open_args.txt @@ -163,6 +163,7 @@ │ │ @ ParametersNode (location: (12,8)-(12,14)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (12,8)-(12,9)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -204,6 +205,7 @@ │ │ @ ParametersNode (location: (16,8)-(16,14)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (16,8)-(16,9)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -245,9 +247,11 @@ │ │ @ ParametersNode (location: (18,8)-(18,21)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (18,8)-(18,9)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (18,11)-(18,16)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (18,11)-(18,12) = "b" │ │ │ ├── operator_loc: (18,13)-(18,14) = "=" @@ -278,6 +282,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (21,8)-(21,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (21,8)-(21,9) = "b" │ │ │ ├── operator_loc: (21,10)-(21,11) = "=" @@ -324,6 +329,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (25,8)-(25,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ ├── name_loc: (25,8)-(25,9) = "b" │ │ │ ├── operator_loc: (25,10)-(25,11) = "=" @@ -369,6 +375,7 @@ │ @ ParametersNode (location: (27,8)-(27,14)) │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (27,8)-(27,9)) + │ │ ├── flags: ∅ │ │ └── name: :a │ ├── optionals: (length: 0) │ ├── rest: ∅ diff --git a/test/prism/snapshots/whitequark/forwarded_argument_with_kwrestarg.txt b/test/prism/snapshots/whitequark/forwarded_argument_with_kwrestarg.txt index 3e1f113611a4b9..ff7a0945758df8 100644 --- a/test/prism/snapshots/whitequark/forwarded_argument_with_kwrestarg.txt +++ b/test/prism/snapshots/whitequark/forwarded_argument_with_kwrestarg.txt @@ -11,6 +11,7 @@ │ @ ParametersNode (location: (1,8)-(1,20)) │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,8)-(1,16)) + │ │ ├── flags: ∅ │ │ └── name: :argument │ ├── optionals: (length: 0) │ ├── rest: ∅ @@ -18,6 +19,7 @@ │ ├── keywords: (length: 0) │ ├── keyword_rest: │ │ @ KeywordRestParameterNode (location: (1,18)-(1,20)) + │ │ ├── flags: ∅ │ │ ├── name: ∅ │ │ ├── name_loc: ∅ │ │ └── operator_loc: (1,18)-(1,20) = "**" diff --git a/test/prism/snapshots/whitequark/forwarded_argument_with_restarg.txt b/test/prism/snapshots/whitequark/forwarded_argument_with_restarg.txt index 76531aa70783af..249a6260ce9e35 100644 --- a/test/prism/snapshots/whitequark/forwarded_argument_with_restarg.txt +++ b/test/prism/snapshots/whitequark/forwarded_argument_with_restarg.txt @@ -11,10 +11,12 @@ │ @ ParametersNode (location: (1,8)-(1,19)) │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (1,8)-(1,16)) + │ │ ├── flags: ∅ │ │ └── name: :argument │ ├── optionals: (length: 0) │ ├── rest: │ │ @ RestParameterNode (location: (1,18)-(1,19)) + │ │ ├── flags: ∅ │ │ ├── name: ∅ │ │ ├── name_loc: ∅ │ │ └── operator_loc: (1,18)-(1,19) = "*" diff --git a/test/prism/snapshots/whitequark/forwarded_kwrestarg.txt b/test/prism/snapshots/whitequark/forwarded_kwrestarg.txt index 23dc2d1646ed47..bd2f55aebaa770 100644 --- a/test/prism/snapshots/whitequark/forwarded_kwrestarg.txt +++ b/test/prism/snapshots/whitequark/forwarded_kwrestarg.txt @@ -16,6 +16,7 @@ │ ├── keywords: (length: 0) │ ├── keyword_rest: │ │ @ KeywordRestParameterNode (location: (1,8)-(1,10)) + │ │ ├── flags: ∅ │ │ ├── name: ∅ │ │ ├── name_loc: ∅ │ │ └── operator_loc: (1,8)-(1,10) = "**" diff --git a/test/prism/snapshots/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt b/test/prism/snapshots/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt index a532391b3fca96..0af593e9e900ab 100644 --- a/test/prism/snapshots/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt +++ b/test/prism/snapshots/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt @@ -16,6 +16,7 @@ │ ├── keywords: (length: 0) │ ├── keyword_rest: │ │ @ KeywordRestParameterNode (location: (1,8)-(1,10)) + │ │ ├── flags: ∅ │ │ ├── name: ∅ │ │ ├── name_loc: ∅ │ │ └── operator_loc: (1,8)-(1,10) = "**" diff --git a/test/prism/snapshots/whitequark/forwarded_restarg.txt b/test/prism/snapshots/whitequark/forwarded_restarg.txt index c05180b8088b0a..43e514bde5c390 100644 --- a/test/prism/snapshots/whitequark/forwarded_restarg.txt +++ b/test/prism/snapshots/whitequark/forwarded_restarg.txt @@ -13,6 +13,7 @@ │ ├── optionals: (length: 0) │ ├── rest: │ │ @ RestParameterNode (location: (1,8)-(1,9)) + │ │ ├── flags: ∅ │ │ ├── name: ∅ │ │ ├── name_loc: ∅ │ │ └── operator_loc: (1,8)-(1,9) = "*" diff --git a/test/prism/snapshots/whitequark/kwarg.txt b/test/prism/snapshots/whitequark/kwarg.txt index ad1c1752bf2782..6f54b17f6ee378 100644 --- a/test/prism/snapshots/whitequark/kwarg.txt +++ b/test/prism/snapshots/whitequark/kwarg.txt @@ -15,6 +15,7 @@ │ ├── posts: (length: 0) │ ├── keywords: (length: 1) │ │ └── @ RequiredKeywordParameterNode (location: (1,6)-(1,10)) + │ │ ├── flags: ∅ │ │ ├── name: :foo │ │ └── name_loc: (1,6)-(1,10) = "foo:" │ ├── keyword_rest: ∅ diff --git a/test/prism/snapshots/whitequark/kwoptarg.txt b/test/prism/snapshots/whitequark/kwoptarg.txt index e1fe137c2fd7fb..dbe465e80c8940 100644 --- a/test/prism/snapshots/whitequark/kwoptarg.txt +++ b/test/prism/snapshots/whitequark/kwoptarg.txt @@ -15,6 +15,7 @@ │ ├── posts: (length: 0) │ ├── keywords: (length: 1) │ │ └── @ OptionalKeywordParameterNode (location: (1,6)-(1,12)) + │ │ ├── flags: ∅ │ │ ├── name: :foo │ │ ├── name_loc: (1,6)-(1,10) = "foo:" │ │ └── value: diff --git a/test/prism/snapshots/whitequark/kwoptarg_with_kwrestarg_and_forwarded_args.txt b/test/prism/snapshots/whitequark/kwoptarg_with_kwrestarg_and_forwarded_args.txt index 2a003a80e7da38..f39e6e44667994 100644 --- a/test/prism/snapshots/whitequark/kwoptarg_with_kwrestarg_and_forwarded_args.txt +++ b/test/prism/snapshots/whitequark/kwoptarg_with_kwrestarg_and_forwarded_args.txt @@ -15,12 +15,14 @@ │ ├── posts: (length: 0) │ ├── keywords: (length: 1) │ │ └── @ OptionalKeywordParameterNode (location: (1,6)-(1,12)) + │ │ ├── flags: ∅ │ │ ├── name: :a │ │ ├── name_loc: (1,6)-(1,8) = "a:" │ │ └── value: │ │ @ NilNode (location: (1,9)-(1,12)) │ ├── keyword_rest: │ │ @ KeywordRestParameterNode (location: (1,14)-(1,16)) + │ │ ├── flags: ∅ │ │ ├── name: ∅ │ │ ├── name_loc: ∅ │ │ └── operator_loc: (1,14)-(1,16) = "**" diff --git a/test/prism/snapshots/whitequark/kwrestarg_named.txt b/test/prism/snapshots/whitequark/kwrestarg_named.txt index 73c73087da72db..a31787e3d66dc2 100644 --- a/test/prism/snapshots/whitequark/kwrestarg_named.txt +++ b/test/prism/snapshots/whitequark/kwrestarg_named.txt @@ -16,6 +16,7 @@ │ ├── keywords: (length: 0) │ ├── keyword_rest: │ │ @ KeywordRestParameterNode (location: (1,6)-(1,11)) + │ │ ├── flags: ∅ │ │ ├── name: :foo │ │ ├── name_loc: (1,8)-(1,11) = "foo" │ │ └── operator_loc: (1,6)-(1,8) = "**" diff --git a/test/prism/snapshots/whitequark/kwrestarg_unnamed.txt b/test/prism/snapshots/whitequark/kwrestarg_unnamed.txt index be042c76095533..564dfbcd6f650e 100644 --- a/test/prism/snapshots/whitequark/kwrestarg_unnamed.txt +++ b/test/prism/snapshots/whitequark/kwrestarg_unnamed.txt @@ -16,6 +16,7 @@ │ ├── keywords: (length: 0) │ ├── keyword_rest: │ │ @ KeywordRestParameterNode (location: (1,6)-(1,8)) + │ │ ├── flags: ∅ │ │ ├── name: ∅ │ │ ├── name_loc: ∅ │ │ └── operator_loc: (1,6)-(1,8) = "**" diff --git a/test/prism/snapshots/whitequark/method_definition_in_while_cond.txt b/test/prism/snapshots/whitequark/method_definition_in_while_cond.txt index 1ca0c3e79a9b35..ca1cd594c5ccaf 100644 --- a/test/prism/snapshots/whitequark/method_definition_in_while_cond.txt +++ b/test/prism/snapshots/whitequark/method_definition_in_while_cond.txt @@ -17,6 +17,7 @@ │ │ │ ├── requireds: (length: 0) │ │ │ ├── optionals: (length: 1) │ │ │ │ └── @ OptionalParameterNode (location: (1,14)-(1,28)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :a │ │ │ │ ├── name_loc: (1,14)-(1,15) = "a" │ │ │ │ ├── operator_loc: (1,16)-(1,17) = "=" @@ -117,6 +118,7 @@ │ │ │ ├── requireds: (length: 0) │ │ │ ├── optionals: (length: 1) │ │ │ │ └── @ OptionalParameterNode (location: (5,19)-(5,33)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :a │ │ │ │ ├── name_loc: (5,19)-(5,20) = "a" │ │ │ │ ├── operator_loc: (5,21)-(5,22) = "=" diff --git a/test/prism/snapshots/whitequark/optarg.txt b/test/prism/snapshots/whitequark/optarg.txt index 5a192fc3607cf4..ed8c1be940885c 100644 --- a/test/prism/snapshots/whitequark/optarg.txt +++ b/test/prism/snapshots/whitequark/optarg.txt @@ -12,6 +12,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,6)-(1,13)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :foo │ │ │ ├── name_loc: (1,6)-(1,9) = "foo" │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" @@ -41,6 +42,7 @@ │ ├── requireds: (length: 0) │ ├── optionals: (length: 2) │ │ ├── @ OptionalParameterNode (location: (3,6)-(3,11)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :foo │ │ │ ├── name_loc: (3,6)-(3,9) = "foo" │ │ │ ├── operator_loc: (3,9)-(3,10) = "=" @@ -48,6 +50,7 @@ │ │ │ @ IntegerNode (location: (3,10)-(3,11)) │ │ │ └── flags: decimal │ │ └── @ OptionalParameterNode (location: (3,13)-(3,18)) + │ │ ├── flags: ∅ │ │ ├── name: :bar │ │ ├── name_loc: (3,13)-(3,16) = "bar" │ │ ├── operator_loc: (3,16)-(3,17) = "=" diff --git a/test/prism/snapshots/whitequark/parser_bug_272.txt b/test/prism/snapshots/whitequark/parser_bug_272.txt index 173b4df60d8c32..193c324524683b 100644 --- a/test/prism/snapshots/whitequark/parser_bug_272.txt +++ b/test/prism/snapshots/whitequark/parser_bug_272.txt @@ -27,6 +27,7 @@ │ │ @ ParametersNode (location: (1,9)-(1,10)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,9)-(1,10)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :c │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/whitequark/parser_bug_507.txt b/test/prism/snapshots/whitequark/parser_bug_507.txt index b8f9c0f83f1d07..294e78a2f15f3b 100644 --- a/test/prism/snapshots/whitequark/parser_bug_507.txt +++ b/test/prism/snapshots/whitequark/parser_bug_507.txt @@ -22,6 +22,7 @@ │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (1,7)-(1,12)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :args │ │ │ │ ├── name_loc: (1,8)-(1,12) = "args" │ │ │ │ └── operator_loc: (1,7)-(1,8) = "*" diff --git a/test/prism/snapshots/whitequark/parser_bug_645.txt b/test/prism/snapshots/whitequark/parser_bug_645.txt index 16b1e171d252af..a2d0d3d28cb7ce 100644 --- a/test/prism/snapshots/whitequark/parser_bug_645.txt +++ b/test/prism/snapshots/whitequark/parser_bug_645.txt @@ -16,6 +16,7 @@ │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 1) │ │ │ └── @ OptionalParameterNode (location: (1,4)-(1,10)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :arg │ │ │ ├── name_loc: (1,4)-(1,7) = "arg" │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" diff --git a/test/prism/snapshots/whitequark/procarg0.txt b/test/prism/snapshots/whitequark/procarg0.txt index d0dacfd387b303..09b24c2f7c4f25 100644 --- a/test/prism/snapshots/whitequark/procarg0.txt +++ b/test/prism/snapshots/whitequark/procarg0.txt @@ -24,8 +24,10 @@ │ │ │ │ └── @ MultiTargetNode (location: (1,5)-(1,15)) │ │ │ │ ├── lefts: (length: 2) │ │ │ │ │ ├── @ RequiredParameterNode (location: (1,6)-(1,9)) + │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── name: :foo │ │ │ │ │ └── @ RequiredParameterNode (location: (1,11)-(1,14)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :bar │ │ │ │ ├── rest: ∅ │ │ │ │ ├── rights: (length: 0) @@ -62,6 +64,7 @@ │ │ @ ParametersNode (location: (3,5)-(3,8)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (3,5)-(3,8)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :foo │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/whitequark/restarg_named.txt b/test/prism/snapshots/whitequark/restarg_named.txt index b61f1fb929dba1..02acbfde84dd1b 100644 --- a/test/prism/snapshots/whitequark/restarg_named.txt +++ b/test/prism/snapshots/whitequark/restarg_named.txt @@ -13,6 +13,7 @@ │ ├── optionals: (length: 0) │ ├── rest: │ │ @ RestParameterNode (location: (1,6)-(1,10)) + │ │ ├── flags: ∅ │ │ ├── name: :foo │ │ ├── name_loc: (1,7)-(1,10) = "foo" │ │ └── operator_loc: (1,6)-(1,7) = "*" diff --git a/test/prism/snapshots/whitequark/restarg_unnamed.txt b/test/prism/snapshots/whitequark/restarg_unnamed.txt index 0879ffa3ee2f68..388dad1972da9a 100644 --- a/test/prism/snapshots/whitequark/restarg_unnamed.txt +++ b/test/prism/snapshots/whitequark/restarg_unnamed.txt @@ -13,6 +13,7 @@ │ ├── optionals: (length: 0) │ ├── rest: │ │ @ RestParameterNode (location: (1,6)-(1,7)) + │ │ ├── flags: ∅ │ │ ├── name: ∅ │ │ ├── name_loc: ∅ │ │ └── operator_loc: (1,6)-(1,7) = "*" diff --git a/test/prism/snapshots/whitequark/ruby_bug_10653.txt b/test/prism/snapshots/whitequark/ruby_bug_10653.txt index a0d088d104d7dc..ed8d43d1f23273 100644 --- a/test/prism/snapshots/whitequark/ruby_bug_10653.txt +++ b/test/prism/snapshots/whitequark/ruby_bug_10653.txt @@ -132,6 +132,7 @@ │ │ │ @ ParametersNode (location: (5,17)-(5,18)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (5,17)-(5,18)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :n │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/whitequark/ruby_bug_12073.txt b/test/prism/snapshots/whitequark/ruby_bug_12073.txt index f5d11b102df746..3ac68ad707ae60 100644 --- a/test/prism/snapshots/whitequark/ruby_bug_12073.txt +++ b/test/prism/snapshots/whitequark/ruby_bug_12073.txt @@ -47,6 +47,7 @@ │ @ ParametersNode (location: (3,8)-(3,13)) │ ├── requireds: (length: 1) │ │ └── @ RequiredParameterNode (location: (3,8)-(3,13)) + │ │ ├── flags: ∅ │ │ └── name: :raise │ ├── optionals: (length: 0) │ ├── rest: ∅ diff --git a/test/prism/snapshots/whitequark/ruby_bug_15789.txt b/test/prism/snapshots/whitequark/ruby_bug_15789.txt index 245126d85d09be..d4062f8ae791da 100644 --- a/test/prism/snapshots/whitequark/ruby_bug_15789.txt +++ b/test/prism/snapshots/whitequark/ruby_bug_15789.txt @@ -27,6 +27,7 @@ │ │ │ │ ├── requireds: (length: 0) │ │ │ │ ├── optionals: (length: 1) │ │ │ │ │ └── @ OptionalParameterNode (location: (1,5)-(1,15)) + │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── name: :a │ │ │ │ │ ├── name_loc: (1,5)-(1,6) = "a" │ │ │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" @@ -89,6 +90,7 @@ │ │ │ ├── posts: (length: 0) │ │ │ ├── keywords: (length: 1) │ │ │ │ └── @ OptionalKeywordParameterNode (location: (3,5)-(3,14)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :a │ │ │ │ ├── name_loc: (3,5)-(3,7) = "a:" │ │ │ │ └── value: diff --git a/test/prism/snapshots/whitequark/ruby_bug_9669.txt b/test/prism/snapshots/whitequark/ruby_bug_9669.txt index 8f6d188acdcf0e..55e61cb46bebac 100644 --- a/test/prism/snapshots/whitequark/ruby_bug_9669.txt +++ b/test/prism/snapshots/whitequark/ruby_bug_9669.txt @@ -15,6 +15,7 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) │ │ │ └── @ RequiredKeywordParameterNode (location: (1,6)-(1,8)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :b │ │ │ └── name_loc: (1,6)-(1,8) = "b:" │ │ ├── keyword_rest: ∅ diff --git a/test/prism/snapshots/whitequark/send_lambda.txt b/test/prism/snapshots/whitequark/send_lambda.txt index 5b0aa38d3de829..552645c4621244 100644 --- a/test/prism/snapshots/whitequark/send_lambda.txt +++ b/test/prism/snapshots/whitequark/send_lambda.txt @@ -17,6 +17,7 @@ │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: │ │ │ │ @ RestParameterNode (location: (1,3)-(1,4)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: ∅ │ │ │ │ ├── name_loc: ∅ │ │ │ │ └── operator_loc: (1,3)-(1,4) = "*" diff --git a/test/prism/snapshots/whitequark/send_lambda_args.txt b/test/prism/snapshots/whitequark/send_lambda_args.txt index e5ca1e2ee726ce..30f80bd2a1da14 100644 --- a/test/prism/snapshots/whitequark/send_lambda_args.txt +++ b/test/prism/snapshots/whitequark/send_lambda_args.txt @@ -15,6 +15,7 @@ │ │ │ @ ParametersNode (location: (1,4)-(1,5)) │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ RequiredParameterNode (location: (1,4)-(1,5)) + │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :a │ │ │ ├── optionals: (length: 0) │ │ │ ├── rest: ∅ @@ -38,6 +39,7 @@ │ │ @ ParametersNode (location: (3,3)-(3,4)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (3,3)-(3,4)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ diff --git a/test/prism/snapshots/whitequark/send_lambda_args_noparen.txt b/test/prism/snapshots/whitequark/send_lambda_args_noparen.txt index b97b8647abbd11..a420d05f36f154 100644 --- a/test/prism/snapshots/whitequark/send_lambda_args_noparen.txt +++ b/test/prism/snapshots/whitequark/send_lambda_args_noparen.txt @@ -19,6 +19,7 @@ │ │ │ ├── posts: (length: 0) │ │ │ ├── keywords: (length: 1) │ │ │ │ └── @ OptionalKeywordParameterNode (location: (1,3)-(1,7)) + │ │ │ │ ├── flags: ∅ │ │ │ │ ├── name: :a │ │ │ │ ├── name_loc: (1,3)-(1,5) = "a:" │ │ │ │ └── value: @@ -46,6 +47,7 @@ │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 1) │ │ │ └── @ RequiredKeywordParameterNode (location: (3,3)-(3,5)) + │ │ │ ├── flags: ∅ │ │ │ ├── name: :a │ │ │ └── name_loc: (3,3)-(3,5) = "a:" │ │ ├── keyword_rest: ∅ diff --git a/test/prism/snapshots/whitequark/send_lambda_args_shadow.txt b/test/prism/snapshots/whitequark/send_lambda_args_shadow.txt index 388988b57307c3..4a0d2fd53e3d48 100644 --- a/test/prism/snapshots/whitequark/send_lambda_args_shadow.txt +++ b/test/prism/snapshots/whitequark/send_lambda_args_shadow.txt @@ -15,6 +15,7 @@ │ │ @ ParametersNode (location: (1,3)-(1,4)) │ │ ├── requireds: (length: 1) │ │ │ └── @ RequiredParameterNode (location: (1,3)-(1,4)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ ├── optionals: (length: 0) │ │ ├── rest: ∅ @@ -24,8 +25,10 @@ │ │ └── block: ∅ │ ├── locals: (length: 2) │ │ ├── @ BlockLocalVariableNode (location: (1,6)-(1,9)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :foo │ │ └── @ BlockLocalVariableNode (location: (1,11)-(1,14)) + │ │ ├── flags: ∅ │ │ └── name: :bar │ ├── opening_loc: (1,2)-(1,3) = "(" │ └── closing_loc: (1,14)-(1,15) = ")" diff --git a/test/prism/snapshots/whitequark/trailing_forward_arg.txt b/test/prism/snapshots/whitequark/trailing_forward_arg.txt index bced34e1bcfcb3..fa6036e4690eb5 100644 --- a/test/prism/snapshots/whitequark/trailing_forward_arg.txt +++ b/test/prism/snapshots/whitequark/trailing_forward_arg.txt @@ -11,8 +11,10 @@ │ @ ParametersNode (location: (1,8)-(1,17)) │ ├── requireds: (length: 2) │ │ ├── @ RequiredParameterNode (location: (1,8)-(1,9)) + │ │ │ ├── flags: ∅ │ │ │ └── name: :a │ │ └── @ RequiredParameterNode (location: (1,11)-(1,12)) + │ │ ├── flags: ∅ │ │ └── name: :b │ ├── optionals: (length: 0) │ ├── rest: ∅ From f165fa09e7bc36f90d3862e537f071f0e1339428 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 9 Jan 2024 11:53:47 -0800 Subject: [PATCH 012/640] [ruby/prism] address feedback https://github.com/ruby/prism/commit/ed183ad30c --- prism/prism.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 73a35c4d46d9e3..05405a4097af34 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -892,21 +892,16 @@ pm_node_flag_unset(pm_node_t *node, pm_node_flags_t flag) { */ static inline void pm_node_flag_set_repeated_parameter(pm_node_t *node) { - switch (PM_NODE_TYPE(node)) { - case PM_BLOCK_LOCAL_VARIABLE_NODE: - case PM_BLOCK_PARAMETER_NODE: - case PM_KEYWORD_REST_PARAMETER_NODE: - case PM_OPTIONAL_KEYWORD_PARAMETER_NODE: - case PM_OPTIONAL_PARAMETER_NODE: - case PM_REQUIRED_KEYWORD_PARAMETER_NODE: - case PM_REQUIRED_PARAMETER_NODE: - case PM_REST_PARAMETER_NODE: - pm_node_flag_set(node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER); - break; - default: - fprintf(stderr, "unhandled type %d\n", PM_NODE_TYPE(node)); - abort(); - }; + assert(PM_NODE_TYPE(node) == PM_BLOCK_LOCAL_VARIABLE_NODE || + PM_NODE_TYPE(node) == PM_BLOCK_PARAMETER_NODE || + PM_NODE_TYPE(node) == PM_KEYWORD_REST_PARAMETER_NODE || + PM_NODE_TYPE(node) == PM_OPTIONAL_KEYWORD_PARAMETER_NODE || + PM_NODE_TYPE(node) == PM_OPTIONAL_PARAMETER_NODE || + PM_NODE_TYPE(node) == PM_REQUIRED_KEYWORD_PARAMETER_NODE || + PM_NODE_TYPE(node) == PM_REQUIRED_PARAMETER_NODE || + PM_NODE_TYPE(node) == PM_REST_PARAMETER_NODE); + + pm_node_flag_set(node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER); } /******************************************************************************/ @@ -6016,6 +6011,9 @@ pm_parser_local_add_owned(pm_parser_t *parser, const uint8_t *start, size_t leng /** * Add a parameter name to the current scope and check whether the name of the * parameter is unique or not. + * + * Returns `true` if this is a duplicate parameter name, otherwise returns + * false. */ static bool pm_parser_parameter_name_check(pm_parser_t *parser, const pm_token_t *name) { From 82b57d7bfeefd717c10f7a5a3484aca6b3e708a3 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 8 Jan 2024 11:32:48 -0500 Subject: [PATCH 013/640] Fix memory leak when duplicating too complex object [Bug #20162] Creating a ST table then calling st_replace leaks memory because the st_replace overwrites the ST table without freeing any of the existing memory. This commit changes it to use st_copy instead. For example: RubyVM::Shape.exhaust_shapes o = Object.new o.instance_variable_set(:@a, 0) 10.times do 100_000.times { o.dup } puts `ps -o rss= -p #{$$}` end Before: 23264 33600 42672 52160 61600 71728 81056 90528 100560 109840 After: 14752 14816 15584 15584 15664 15664 15664 15664 15664 15664 --- object.c | 3 +-- test/ruby/test_shapes.rb | 13 +++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/object.c b/object.c index 9a5a8fbe8a8f9b..a0783e9ef76e90 100644 --- a/object.c +++ b/object.c @@ -302,8 +302,7 @@ rb_obj_copy_ivar(VALUE dest, VALUE obj) if (rb_shape_obj_too_complex(obj)) { // obj is TOO_COMPLEX so we can copy its iv_hash - st_table * table = rb_st_init_numtable_with_size(rb_st_table_size(ROBJECT_IV_HASH(obj))); - st_replace(table, ROBJECT_IV_HASH(obj)); + st_table *table = st_copy(ROBJECT_IV_HASH(obj)); rb_obj_convert_to_too_complex(dest, table); return; diff --git a/test/ruby/test_shapes.rb b/test/ruby/test_shapes.rb index 885b762eb94758..ee99fbad6d8acf 100644 --- a/test/ruby/test_shapes.rb +++ b/test/ruby/test_shapes.rb @@ -942,6 +942,19 @@ def test_duplicating_objects assert_shape_equal(RubyVM::Shape.of(obj), RubyVM::Shape.of(obj2)) end + def test_duplicating_too_complex_objects_memory_leak + assert_no_memory_leak([], "#{<<~'begin;'}", "#{<<~'end;'}", "[Bug #20162]", rss: true) + RubyVM::Shape.exhaust_shapes + + o = Object.new + o.instance_variable_set(:@a, 0) + begin; + 1_000_000.times do + o.dup + end + end; + end + def test_freezing_and_duplicating_object obj = Object.new.freeze obj2 = obj.dup From 015b0e2e1d312e2be60551587389c8da5c585e6f Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Wed, 10 Jan 2024 12:37:08 -0500 Subject: [PATCH 014/640] YJIT: Fix unused warnings ``` warning: unused import: `condition::Condition` --> src/asm/arm64/arg/mod.rs:13:9 | 13 | pub use condition::Condition; | ^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default warning: unused import: `rb_yjit_fix_mul_fix as rb_fix_mul_fix` --> src/cruby.rs:188:9 | 188 | pub use rb_yjit_fix_mul_fix as rb_fix_mul_fix; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused import: `rb_insn_len as raw_insn_len` --> src/cruby.rs:142:9 | 142 | pub use rb_insn_len as raw_insn_len; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default ``` Make asm public so it stops warning about unused public stuff in there. --- yjit.c | 6 ------ yjit/bindgen/src/main.rs | 1 - yjit/src/cruby.rs | 4 +--- yjit/src/cruby_bindings.inc.rs | 1 - yjit/src/lib.rs | 3 +-- 5 files changed, 2 insertions(+), 13 deletions(-) diff --git a/yjit.c b/yjit.c index 58ea3083e29406..d5071cb952858e 100644 --- a/yjit.c +++ b/yjit.c @@ -871,12 +871,6 @@ rb_yjit_fix_mod_fix(VALUE recv, VALUE obj) return rb_fix_mod_fix(recv, obj); } -VALUE -rb_yjit_fix_mul_fix(VALUE recv, VALUE obj) -{ - return rb_fix_mul_fix(recv, obj); -} - // Print the Ruby source location of some ISEQ for debugging purposes void rb_yjit_dump_iseq_loc(const rb_iseq_t *iseq, uint32_t insn_idx) diff --git a/yjit/bindgen/src/main.rs b/yjit/bindgen/src/main.rs index 88b7f6b9c5dfc9..848e9fadc484ba 100644 --- a/yjit/bindgen/src/main.rs +++ b/yjit/bindgen/src/main.rs @@ -427,7 +427,6 @@ fn main() { .allowlist_function("rb_yarv_ary_entry_internal") .allowlist_function("rb_yjit_fix_div_fix") .allowlist_function("rb_yjit_fix_mod_fix") - .allowlist_function("rb_yjit_fix_mul_fix") .allowlist_function("rb_FL_TEST") .allowlist_function("rb_FL_TEST_RAW") .allowlist_function("rb_RB_TYPE_P") diff --git a/yjit/src/cruby.rs b/yjit/src/cruby.rs index e4b5392cfe42d9..a43b053d3efbfd 100644 --- a/yjit/src/cruby.rs +++ b/yjit/src/cruby.rs @@ -139,7 +139,6 @@ extern "C" { // Renames pub use rb_insn_name as raw_insn_name; -pub use rb_insn_len as raw_insn_len; pub use rb_get_ec_cfp as get_ec_cfp; pub use rb_get_cfp_iseq as get_cfp_iseq; pub use rb_get_cfp_pc as get_cfp_pc; @@ -185,7 +184,6 @@ pub use rb_yarv_str_eql_internal as rb_str_eql_internal; pub use rb_yarv_ary_entry_internal as rb_ary_entry_internal; pub use rb_yjit_fix_div_fix as rb_fix_div_fix; pub use rb_yjit_fix_mod_fix as rb_fix_mod_fix; -pub use rb_yjit_fix_mul_fix as rb_fix_mul_fix; pub use rb_FL_TEST as FL_TEST; pub use rb_FL_TEST_RAW as FL_TEST_RAW; pub use rb_RB_TYPE_P as RB_TYPE_P; @@ -222,7 +220,7 @@ pub fn insn_len(opcode: usize) -> u32 { #[cfg(not(test))] unsafe { - raw_insn_len(VALUE(opcode)).try_into().unwrap() + rb_insn_len(VALUE(opcode)).try_into().unwrap() } } diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs index e19ac65749474a..462c9c57486b0a 100644 --- a/yjit/src/cruby_bindings.inc.rs +++ b/yjit/src/cruby_bindings.inc.rs @@ -1121,7 +1121,6 @@ extern "C" { pub fn rb_yjit_rb_ary_subseq_length(ary: VALUE, beg: ::std::os::raw::c_long) -> VALUE; pub fn rb_yjit_fix_div_fix(recv: VALUE, obj: VALUE) -> VALUE; pub fn rb_yjit_fix_mod_fix(recv: VALUE, obj: VALUE) -> VALUE; - pub fn rb_yjit_fix_mul_fix(recv: VALUE, obj: VALUE) -> VALUE; pub fn rb_yjit_dump_iseq_loc(iseq: *const rb_iseq_t, insn_idx: u32); pub fn rb_FL_TEST(obj: VALUE, flags: VALUE) -> VALUE; pub fn rb_FL_TEST_RAW(obj: VALUE, flags: VALUE) -> VALUE; diff --git a/yjit/src/lib.rs b/yjit/src/lib.rs index ce87cc250acf18..3f3d24be4b4c2a 100644 --- a/yjit/src/lib.rs +++ b/yjit/src/lib.rs @@ -3,8 +3,7 @@ #![allow(clippy::too_many_arguments)] // :shrug: #![allow(clippy::identity_op)] // Sometimes we do it for style - -mod asm; +pub mod asm; mod backend; mod codegen; mod core; From 51061b6631f639d1a3724eb54aaae5b7aed734a7 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Wed, 10 Jan 2024 10:58:54 -0500 Subject: [PATCH 015/640] [PRISM] Don't increment argc for PM_ASSOC_SPLAT_NODE Fixes ruby/prism#2087. --- prism_compile.c | 2 +- test/ruby/test_compile_prism.rb | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/prism_compile.c b/prism_compile.c index c7824cde21e1e0..ed5f1367ed1f4c 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -982,7 +982,6 @@ pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinf if (has_keyword_splat) { int cur_hash_size = 0; - orig_argc++; bool new_hash_emitted = false; for (size_t i = 0; i < len; i++) { @@ -992,6 +991,7 @@ pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinf switch (PM_NODE_TYPE(cur_node)) { case PM_ASSOC_NODE: { + orig_argc++; pm_assoc_node_t *assoc = (pm_assoc_node_t *)cur_node; PM_COMPILE_NOT_POPPED(assoc->key); diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index b02c1d09a3b2d8..99f932a238bd22 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1441,6 +1441,11 @@ def self.prism_test_call_node_splat(*); end assert_prism_eval("prism_test_call_node_splat(*[], 1, 2)") + assert_prism_eval(<<~RUBY) + def self.prism_test_call_node_splat_and_double_splat(a, b, **opts); end + prism_test_call_node_splat_and_double_splat(*[1], 2, **{}) + RUBY + assert_prism_eval(<<-CODE) class Foo def []=(a, b) From 8333845b0b95fa7195ed15688a5ef50ff66c7e1f Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 10 Jan 2024 15:17:26 -0500 Subject: [PATCH 016/640] [ruby/prism] Unary symbols that cannot be binary should drop @ https://github.com/ruby/prism/commit/d139af033f --- prism/prism.c | 56 +++++++++++++++++++++++++------- test/prism/snapshots/symbols.txt | 4 +-- 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 05405a4097af34..8274398d074f40 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -12626,14 +12626,48 @@ parse_string_part(pm_parser_t *parser) { } } +/** + * When creating a symbol, unary operators that cannot be binary operators + * automatically drop trailing `@` characters. This happens at the parser level, + * such that `~@` is parsed as `~` and `!@` is parsed as `!`. We do that here. + */ +static pm_node_t * +parse_operator_symbol(pm_parser_t *parser, const pm_token_t *opening, pm_lex_state_t next_state) { + pm_token_t closing = not_provided(parser); + pm_symbol_node_t *symbol = pm_symbol_node_create(parser, opening, &parser->current, &closing); + + const uint8_t *end = parser->current.end; + switch (parser->current.type) { + case PM_TOKEN_TILDE: + case PM_TOKEN_BANG: + if (parser->current.end[-1] == '@') end--; + break; + default: + break; + } + + if (next_state != PM_LEX_STATE_NONE) lex_state_set(parser, next_state); + parser_lex(parser); + + pm_string_shared_init(&symbol->unescaped, parser->previous.start, end); + return (pm_node_t *) symbol; +} + +/** + * Parse a symbol node. This function will get called immediately after finding + * a symbol opening token. This handles parsing bare symbols and interpolated + * symbols. + */ static pm_node_t * parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_state) { - pm_token_t opening = parser->previous; + const pm_token_t opening = parser->previous; if (lex_mode->mode != PM_LEX_STRING) { if (next_state != PM_LEX_STATE_NONE) lex_state_set(parser, next_state); switch (parser->current.type) { + case PM_CASE_OPERATOR: + return parse_operator_symbol(parser, &opening, next_state == PM_LEX_STATE_NONE ? PM_LEX_STATE_ENDFN : next_state); case PM_TOKEN_IDENTIFIER: case PM_TOKEN_CONSTANT: case PM_TOKEN_INSTANCE_VARIABLE: @@ -12645,10 +12679,6 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s case PM_CASE_KEYWORD: parser_lex(parser); break; - case PM_CASE_OPERATOR: - lex_state_set(parser, next_state == PM_LEX_STATE_NONE ? PM_LEX_STATE_ENDFN : next_state); - parser_lex(parser); - break; default: expect2(parser, PM_TOKEN_IDENTIFIER, PM_TOKEN_METHOD_NAME, PM_ERR_SYMBOL_INVALID); break; @@ -12764,8 +12794,11 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s static inline pm_node_t * parse_undef_argument(pm_parser_t *parser) { switch (parser->current.type) { + case PM_CASE_OPERATOR: { + const pm_token_t opening = not_provided(parser); + return parse_operator_symbol(parser, &opening, PM_LEX_STATE_NONE); + } case PM_CASE_KEYWORD: - case PM_CASE_OPERATOR: case PM_TOKEN_CONSTANT: case PM_TOKEN_IDENTIFIER: case PM_TOKEN_METHOD_NAME: { @@ -12799,16 +12832,17 @@ parse_undef_argument(pm_parser_t *parser) { static inline pm_node_t * parse_alias_argument(pm_parser_t *parser, bool first) { switch (parser->current.type) { - case PM_CASE_OPERATOR: + case PM_CASE_OPERATOR: { + const pm_token_t opening = not_provided(parser); + return parse_operator_symbol(parser, &opening, first ? PM_LEX_STATE_FNAME | PM_LEX_STATE_FITEM : PM_LEX_STATE_NONE); + } case PM_CASE_KEYWORD: case PM_TOKEN_CONSTANT: case PM_TOKEN_IDENTIFIER: case PM_TOKEN_METHOD_NAME: { - if (first) { - lex_state_set(parser, PM_LEX_STATE_FNAME | PM_LEX_STATE_FITEM); - } - + if (first) lex_state_set(parser, PM_LEX_STATE_FNAME | PM_LEX_STATE_FITEM); parser_lex(parser); + pm_token_t opening = not_provided(parser); pm_token_t closing = not_provided(parser); pm_symbol_node_t *symbol = pm_symbol_node_create(parser, &opening, &parser->previous, &closing); diff --git a/test/prism/snapshots/symbols.txt b/test/prism/snapshots/symbols.txt index 3f3f0578bc4f26..6ca49b72a4cfec 100644 --- a/test/prism/snapshots/symbols.txt +++ b/test/prism/snapshots/symbols.txt @@ -135,7 +135,7 @@ │ ├── opening_loc: (27,0)-(27,1) = ":" │ ├── value_loc: (27,1)-(27,3) = "~@" │ ├── closing_loc: ∅ - │ └── unescaped: "~@" + │ └── unescaped: "~" ├── @ ArrayNode (location: (29,0)-(29,16)) │ ├── flags: ∅ │ ├── elements: (length: 4) @@ -345,7 +345,7 @@ │ ├── opening_loc: (57,0)-(57,1) = ":" │ ├── value_loc: (57,1)-(57,3) = "!@" │ ├── closing_loc: ∅ - │ └── unescaped: "!@" + │ └── unescaped: "!" ├── @ SymbolNode (location: (59,0)-(59,3)) │ ├── flags: ∅ │ ├── opening_loc: (59,0)-(59,1) = ":" From 5906f6a50ed4c6d3e23595ecf5feea615f0965d5 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 10 Jan 2024 13:47:46 -0500 Subject: [PATCH 017/640] Add a GitHub workflow for prism btests --- .github/workflows/prism.yml | 129 ++++++++++++++++++++++++++++++++++++ tool/prism_btests | 35 ++++++++++ 2 files changed, 164 insertions(+) create mode 100644 .github/workflows/prism.yml create mode 100644 tool/prism_btests diff --git a/.github/workflows/prism.yml b/.github/workflows/prism.yml new file mode 100644 index 00000000000000..4bfaf92544af24 --- /dev/null +++ b/.github/workflows/prism.yml @@ -0,0 +1,129 @@ +name: Prism +on: + push: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + - '**/.document' + - '**.[1-8]' + - '**.ronn' + - '.*.yml' + pull_request: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + - '**/.document' + - '**.[1-8]' + - '**.ronn' + - '.*.yml' + merge_group: + paths-ignore: + - 'doc/**' + - '**.md' + - '**.rdoc' + - '**/.document' + - '**.[1-8]' + - '**.ronn' + - '.*.yml' + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + make: + strategy: + matrix: + # main variables included in the job name + test_task: [check] + run_opts: ['--parser=prism'] + arch: [''] + fail-fast: false + + env: + GITPULLOPTIONS: --no-tags origin ${{ github.ref }} + RUBY_DEBUG: ci + SETARCH: ${{ matrix.arch && format('setarch {0}', matrix.arch) }} + + runs-on: ubuntu-22.04 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.actor == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + sparse-checkout-cone-mode: false + sparse-checkout: /.github + + - uses: ./.github/actions/setup/ubuntu + + - uses: ./.github/actions/setup/directories + with: + srcdir: src + builddir: build + makeup: true + + - name: Run configure + env: + arch: ${{ matrix.arch }} + run: >- + $SETARCH ../src/configure -C --disable-install-doc cppflags=-DRUBY_DEBUG + ${arch:+--target=$arch-$OSTYPE --host=$arch-$OSTYPE} + + - run: $SETARCH make + + - name: make btest + run: | + make -s btest RUN_OPTS="$RUN_OPTS" BTESTS="$(cat ../src/tool/prism_btests | grep -v '^#' | tr '\n' ' ')" + timeout-minutes: 30 + env: + GNUMAKEFLAGS: '' + RUBY_TESTOPTS: '-v --tty=no' + RUN_OPTS: ${{ matrix.run_opts }} + + # - name: make test + # run: | + # $SETARCH make -s test RUN_OPTS="$RUN_OPTS" + # timeout-minutes: 30 + # env: + # GNUMAKEFLAGS: '' + # RUBY_TESTOPTS: '-v --tty=no' + # RUN_OPTS: ${{ matrix.run_opts }} + + # - name: make test-all + # run: | + # $SETARCH make -s test-all RUN_OPTS="$RUN_OPTS" + # timeout-minutes: 40 + # env: + # GNUMAKEFLAGS: '' + # RUBY_TESTOPTS: '-q --tty=no' + # RUN_OPTS: ${{ matrix.run_opts }} + + # - name: make test-spec + # run: | + # $SETARCH make -s test-spec RUN_OPTS="$RUN_OPTS" + # timeout-minutes: 10 + # env: + # GNUMAKEFLAGS: '' + # RUN_OPTS: ${{ matrix.run_opts }} + + - uses: ./.github/actions/slack + with: + label: ${{ matrix.run_opts }} + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() }} + +defaults: + run: + working-directory: build diff --git a/tool/prism_btests b/tool/prism_btests new file mode 100644 index 00000000000000..6ce76301531ab1 --- /dev/null +++ b/tool/prism_btests @@ -0,0 +1,35 @@ +../src/bootstraptest/test_attr.rb +../src/bootstraptest/test_autoload.rb +../src/bootstraptest/test_class.rb +../src/bootstraptest/test_constant_cache.rb +../src/bootstraptest/test_env.rb +../src/bootstraptest/test_eval.rb +../src/bootstraptest/test_fiber.rb +../src/bootstraptest/test_finalizer.rb +../src/bootstraptest/test_flip.rb +../src/bootstraptest/test_fork.rb +../src/bootstraptest/test_gc.rb +../src/bootstraptest/test_jump.rb +../src/bootstraptest/test_literal.rb +../src/bootstraptest/test_literal_suffix.rb +../src/bootstraptest/test_load.rb +../src/bootstraptest/test_marshal.rb +../src/bootstraptest/test_objectspace.rb +../src/bootstraptest/test_proc.rb +../src/bootstraptest/test_rjit.rb +../src/bootstraptest/test_string.rb +../src/bootstraptest/test_struct.rb +../src/bootstraptest/test_thread.rb +# ../src/bootstraptest/test_block.rb +# ../src/bootstraptest/test_exception.rb +# ../src/bootstraptest/test_flow.rb +# ../src/bootstraptest/test_insns.rb +# ../src/bootstraptest/test_io.rb +# ../src/bootstraptest/test_massign.rb +# ../src/bootstraptest/test_method.rb +# ../src/bootstraptest/test_ractor.rb +# ../src/bootstraptest/test_syntax.rb +# ../src/bootstraptest/test_yjit.rb +# ../src/bootstraptest/test_yjit_30k_ifelse.rb +# ../src/bootstraptest/test_yjit_30k_methods.rb +# ../src/bootstraptest/test_yjit_rust_port.rb From 25f5b83689fc6dd137d45b634a0cd6e8bd024728 Mon Sep 17 00:00:00 2001 From: KJ Tsanaktsidis Date: Mon, 27 Nov 2023 20:26:17 +1100 Subject: [PATCH 018/640] Fix crash when printing RGENGC_DEBUG=5 output from GC I was trying to debug an (unrelated) issue in the GC, and wanted to turn on the trace-level GC output by compiling it with -DRGENGC_DEBUG=5. Unfortunately, this actually causes a crash in newobj_init() because the code there tries to log the obj_info() of the newly created object. However, the object is not actually sufficiently set up for some of the things that obj_info() tries to do: * The instance variable table for a class is not yet initialized, and when using variable-length RVALUES, said ivar table is embedded in as-yet unitialized memory after the struct RValue. Attempting to read this, as obj_info() does, causes a crash. * T_DATA variables need to dereference their ->type field to print out the underlying C type name, which is not set up until newobj_fill() is called. To fix this, create a new method `obj_info_basic`, which dumps out only the parts of the object that are valid before the object is fully initialized. [Fixes #18795] --- gc.c | 29 ++++++++++++++++++++++++++++- internal/gc.h | 1 + 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/gc.c b/gc.c index 1150f1794dd1ef..0e4dadbdd0b39f 100644 --- a/gc.c +++ b/gc.c @@ -1427,6 +1427,7 @@ static inline void gc_prof_set_heap_info(rb_objspace_t *); #endif PRINTF_ARGS(static void gc_report_body(int level, rb_objspace_t *objspace, const char *fmt, ...), 3, 4); static const char *obj_info(VALUE obj); +static const char *obj_info_basic(VALUE obj); static const char *obj_type_name(VALUE obj); static void gc_finalize_deferred(void *dmy); @@ -2638,7 +2639,7 @@ newobj_init(VALUE klass, VALUE flags, int wb_protected, rb_objspace_t *objspace, GC_ASSERT(!SPECIAL_CONST_P(obj)); /* check alignment */ #endif - gc_report(5, objspace, "newobj: %s\n", obj_info(obj)); + gc_report(5, objspace, "newobj: %s\n", obj_info_basic(obj)); // RUBY_DEBUG_LOG("obj:%p (%s)", (void *)obj, obj_type_name(obj)); return obj; @@ -14099,6 +14100,17 @@ rb_raw_obj_info(char *const buff, const size_t buff_size, VALUE obj) return buff; } +const char * +rb_raw_obj_info_basic(char *const buff, const size_t buff_size, VALUE obj) +{ + asan_unpoisoning_object(obj) { + size_t pos = rb_raw_obj_info_common(buff, buff_size, obj); + if (pos >= buff_size) {} // truncated + } + + return buff; +} + #undef APPEND_S #undef APPEND_F #undef BUFF_ARGS @@ -14130,12 +14142,27 @@ obj_info(VALUE obj) char *const buff = obj_info_buffers[index]; return rb_raw_obj_info(buff, OBJ_INFO_BUFFERS_SIZE, obj); } + +static const char * +obj_info_basic(VALUE obj) +{ + rb_atomic_t index = atomic_inc_wraparound(&obj_info_buffers_index, OBJ_INFO_BUFFERS_NUM); + char *const buff = obj_info_buffers[index]; + return rb_raw_obj_info_basic(buff, OBJ_INFO_BUFFERS_SIZE, obj); +} #else static const char * obj_info(VALUE obj) { return obj_type_name(obj); } + +static const char * +obj_info_basic(VALUE obj) +{ + return obj_type_name(obj); +} + #endif const char * diff --git a/internal/gc.h b/internal/gc.h index 34a6043e8a1f6c..2537671855f48d 100644 --- a/internal/gc.h +++ b/internal/gc.h @@ -122,6 +122,7 @@ int ruby_get_stack_grow_direction(volatile VALUE *addr); const char *rb_obj_info(VALUE obj); const char *rb_raw_obj_info(char *const buff, const size_t buff_size, VALUE obj); +const char *rb_raw_obj_info_basic(char *const buff, const size_t buff_size, VALUE obj); size_t rb_size_pool_slot_size(unsigned char pool_id); From ef751252711ca7ecabb3e4ad9214fa0d1d63608a Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Wed, 10 Jan 2024 13:07:34 -0800 Subject: [PATCH 019/640] Make defined? for op asgn expressions to constants use "assignment" Previously, it used "expression", as that was the default. However, op asgn expressions to constants use the NODE_OP_CDECL, so recognize that node type as assignement. Fixes [Bug #20111] --- compile.c | 1 + test/ruby/test_defined.rb | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/compile.c b/compile.c index 3822646c0e7666..6e0456af354577 100644 --- a/compile.c +++ b/compile.c @@ -5951,6 +5951,7 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, case NODE_IASGN: case NODE_CDECL: case NODE_CVASGN: + case NODE_OP_CDECL: expr_type = DEFINED_ASGN; break; } diff --git a/test/ruby/test_defined.rb b/test/ruby/test_defined.rb index b9bf9393944998..0505bdada61755 100644 --- a/test/ruby/test_defined.rb +++ b/test/ruby/test_defined.rb @@ -127,6 +127,18 @@ def test_defined_matchdata assert_equal nil, defined?($2) end + def test_defined_assignment + assert_equal("assignment", defined?(a = 1)) + assert_equal("assignment", defined?(a += 1)) + assert_equal("assignment", defined?(a &&= 1)) + assert_equal("assignment", eval('defined?(A = 1)')) + assert_equal("assignment", eval('defined?(A += 1)')) + assert_equal("assignment", eval('defined?(A &&= 1)')) + assert_equal("assignment", eval('defined?(A::B = 1)')) + assert_equal("assignment", eval('defined?(A::B += 1)')) + assert_equal("assignment", eval('defined?(A::B &&= 1)')) + end + def test_defined_literal assert_equal("nil", defined?(nil)) assert_equal("true", defined?(true)) From a6ba45e9b0e224be350556299f3d890171117d9e Mon Sep 17 00:00:00 2001 From: "S.H" Date: Thu, 11 Jan 2024 09:21:55 +0900 Subject: [PATCH 020/640] Remove unnecessary semicolons (#9469) --- debug.c | 2 +- eval.c | 2 +- io.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/debug.c b/debug.c index 605a399b65e5a8..c5b92cdd10a34a 100644 --- a/debug.c +++ b/debug.c @@ -683,7 +683,7 @@ debug_log_dump(FILE *out, unsigned int n) int index = current_index - size + i; if (index < 0) index += MAX_DEBUG_LOG; VM_ASSERT(index <= MAX_DEBUG_LOG); - const char *mesg = RUBY_DEBUG_LOG_MEM_ENTRY(index);; + const char *mesg = RUBY_DEBUG_LOG_MEM_ENTRY(index); fprintf(out, "%4u: %s\n", debug_log.cnt - size + i, mesg); } } diff --git a/eval.c b/eval.c index 8a636cc5334114..aa0eae08727588 100644 --- a/eval.c +++ b/eval.c @@ -1829,7 +1829,7 @@ top_include(int argc, VALUE *argv, VALUE self) static VALUE top_using(VALUE self, VALUE module) { - const rb_cref_t *cref = CREF_NEXT(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(); diff --git a/io.c b/io.c index 90bf24507187e5..2de3e873024f47 100644 --- a/io.c +++ b/io.c @@ -2678,7 +2678,7 @@ rb_io_eof(VALUE io) READ_CHECK(fptr); #if RUBY_CRLF_ENVIRONMENT if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) { - return RBOOL(eof(fptr->fd));; + return RBOOL(eof(fptr->fd)); } #endif return RBOOL(io_fillbuf(fptr) < 0); From d5e83a0601f415bc542af2aded1e5094d4b9c48c Mon Sep 17 00:00:00 2001 From: Brave Hager Date: Wed, 10 Jan 2024 09:49:47 -0500 Subject: [PATCH 021/640] [rubygems/rubygems] Update documentation to use squiggly heredoc https://github.com/rubygems/rubygems/commit/4691b959ad --- lib/rubygems/specification.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb index a0c7faa1334dfb..169002d7c7b9e1 100644 --- a/lib/rubygems/specification.rb +++ b/lib/rubygems/specification.rb @@ -301,7 +301,7 @@ def authors=(value) # # Usage: # - # spec.description = <<-EOF + # spec.description = <<~EOF # Rake is a Make-like program implemented in Ruby. Tasks and # dependencies are specified in standard Ruby syntax. # EOF From bd9548810c5469a03c69bba19b24a673cca15988 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 10 Jan 2024 16:18:57 +0900 Subject: [PATCH 022/640] [rubygems/rubygems] Removed redundant block https://github.com/rubygems/rubygems/commit/d059b9ec4d --- test/rubygems/helper.rb | 43 +++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb index d259fbde1bc2fc..8638e0044495bf 100644 --- a/test/rubygems/helper.rb +++ b/test/rubygems/helper.rb @@ -105,39 +105,32 @@ def refute_directory_exists(path, msg = nil) refute File.directory?(path), msg end - # https://github.com/seattlerb/minitest/blob/21d9e804b63c619f602f3f4ece6c71b48974707a/lib/minitest/assertions.rb#L188 - def _synchronize - yield - end - # https://github.com/seattlerb/minitest/blob/21d9e804b63c619f602f3f4ece6c71b48974707a/lib/minitest/assertions.rb#L546 def capture_subprocess_io - _synchronize do - require "tempfile" + require "tempfile" - captured_stdout = Tempfile.new("out") - captured_stderr = Tempfile.new("err") + captured_stdout = Tempfile.new("out") + captured_stderr = Tempfile.new("err") - orig_stdout = $stdout.dup - orig_stderr = $stderr.dup - $stdout.reopen captured_stdout - $stderr.reopen captured_stderr + orig_stdout = $stdout.dup + orig_stderr = $stderr.dup + $stdout.reopen captured_stdout + $stderr.reopen captured_stderr - yield + yield - $stdout.rewind - $stderr.rewind + $stdout.rewind + $stderr.rewind - return captured_stdout.read, captured_stderr.read - ensure - $stdout.reopen orig_stdout - $stderr.reopen orig_stderr + return captured_stdout.read, captured_stderr.read + ensure + $stdout.reopen orig_stdout + $stderr.reopen orig_stderr - orig_stdout.close - orig_stderr.close - captured_stdout.close! - captured_stderr.close! - end + orig_stdout.close + orig_stderr.close + captured_stdout.close! + captured_stderr.close! end ## From 9f784915cdb0b50221b929413d9794ee8f591782 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 10 Jan 2024 16:36:58 +0900 Subject: [PATCH 023/640] [rubygems/rubygems] bin/rubocop -A test/rubygems/helper.rb https://github.com/rubygems/rubygems/commit/07ebc9f844 --- test/rubygems/helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb index 8638e0044495bf..86a496d85e6231 100644 --- a/test/rubygems/helper.rb +++ b/test/rubygems/helper.rb @@ -122,7 +122,7 @@ def capture_subprocess_io $stdout.rewind $stderr.rewind - return captured_stdout.read, captured_stderr.read + [captured_stdout.read, captured_stderr.read] ensure $stdout.reopen orig_stdout $stderr.reopen orig_stderr From 27688b6a1df7b58b539165c7d17b359db5142bd7 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 11 Jan 2024 09:33:01 +0900 Subject: [PATCH 024/640] [rubygems/rubygems] Update comment for minitest helper https://github.com/rubygems/rubygems/commit/77b0805474 --- test/rubygems/helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb index 86a496d85e6231..e6774ded38f0f3 100644 --- a/test/rubygems/helper.rb +++ b/test/rubygems/helper.rb @@ -105,7 +105,7 @@ def refute_directory_exists(path, msg = nil) refute File.directory?(path), msg end - # https://github.com/seattlerb/minitest/blob/21d9e804b63c619f602f3f4ece6c71b48974707a/lib/minitest/assertions.rb#L546 + # Originally copied from minitest/assertions.rb def capture_subprocess_io require "tempfile" From 76a8c963c7ad975b7bbfc1c4979bf7a2de15af27 Mon Sep 17 00:00:00 2001 From: KJ Tsanaktsidis Date: Fri, 18 Aug 2023 23:19:21 +1000 Subject: [PATCH 025/640] Add a test for what happens with concurent calls to waitpid Ruby 3.1 and 3.2 have a bug in their _implementation_, for which I'm backporting a fix. However, the current development branch doesn't have the issue (because the MJIT -> RJIT change refactored how waitpid worked substantially). I do however want to commit the test which verifies that waitpid works properly on master. [Fixes #19387] --- test/ruby/test_process.rb | 55 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb index 188ef75fae1775..edee62466518a4 100644 --- a/test/ruby/test_process.rb +++ b/test/ruby/test_process.rb @@ -2783,4 +2783,59 @@ def test_warmup_frees_pages assert_operator(GC.stat(:total_freed_pages), :>, 0) end; end + + def test_concurrent_group_and_pid_wait + # Use a pair of pipes that will make long_pid exit when this test exits, to avoid + # leaking temp processes. + long_rpipe, long_wpipe = IO.pipe + short_rpipe, short_wpipe = IO.pipe + # This process should run forever + long_pid = fork do + [short_rpipe, short_wpipe, long_wpipe].each(&:close) + long_rpipe.read + end + # This process will exit + short_pid = fork do + [long_rpipe, long_wpipe, short_wpipe].each(&:close) + short_rpipe.read + end + t1, t2, t3 = nil + EnvUtil.timeout(5) do + t1 = Thread.new do + Process.waitpid long_pid + end + # Wait for us to be blocking in a call to waitpid2 + Thread.pass until t1.stop? + short_wpipe.close # Make short_pid exit + + # The short pid has exited, so -1 should pick that up. + assert_equal short_pid, Process.waitpid(-1) + + # Terminate t1 for the next phase of the test. + t1.kill + t1.join + + t2 = Thread.new do + Process.waitpid -1 + rescue Errno::ECHILD + nil + end + Thread.pass until t2.stop? + t3 = Thread.new do + Process.waitpid long_pid + rescue Errno::ECHILD + nil + end + Thread.pass until t3.stop? + + # it's actually nondeterministic which of t2 or t3 will receive the wait (this + # nondeterminism comes from the behaviour of the underlying system calls) + long_wpipe.close + assert_equal [long_pid], [t2, t3].map(&:value).compact + end + ensure + [t1, t2, t3].each { _1&.kill rescue nil } + [t1, t2, t3].each { _1&.join rescue nil } + [long_rpipe, long_wpipe, short_rpipe, short_wpipe].each { _1&.close rescue nil } + end if defined?(fork) end From a9712294622381b9545ed393d68616819b5af26f Mon Sep 17 00:00:00 2001 From: S-H-GAMELINKS Date: Tue, 9 Jan 2024 00:29:06 +0900 Subject: [PATCH 026/640] Fixed return values for some node types in nd_st_key function --- parse.y | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/parse.y b/parse.y index a3a4346f5b4b43..391cafffc7822c 100644 --- a/parse.y +++ b/parse.y @@ -14966,13 +14966,19 @@ nd_st_key(struct parser_params *p, NODE *node) case NODE_STR: return RNODE_STR(node)->nd_lit; case NODE_INTEGER: + return rb_node_integer_literal_val(node); case NODE_FLOAT: + return rb_node_float_literal_val(node); case NODE_RATIONAL: + return rb_node_rational_literal_val(node); case NODE_IMAGINARY: + return rb_node_imaginary_literal_val(node); case NODE_SYM: + return rb_node_sym_string_val(node); case NODE_LINE: + return rb_node_line_lineno_val(node); case NODE_FILE: - return (VALUE)node; + return rb_node_file_path_val(node); default: rb_bug("unexpected node: %s", ruby_node_name(nd_type(node))); UNREACHABLE_RETURN(0); From 1bd98c820da46a05328d2d53b8f748f28e7ee8f7 Mon Sep 17 00:00:00 2001 From: Yusuke Endoh Date: Wed, 10 Jan 2024 19:52:53 +0900 Subject: [PATCH 027/640] Remove setaffinity of pthread for getaddrinfo It looks like `sched_getcpu(3)` returns a strange number on some (virtual?) environments. I decided to remove the setaffinity mechanism because the performance does not appear to degrade on a quick benchmark even if removed. [Bug #20172] --- ext/socket/extconf.rb | 2 -- ext/socket/raddrinfo.c | 48 ++++-------------------------------------- 2 files changed, 4 insertions(+), 46 deletions(-) diff --git a/ext/socket/extconf.rb b/ext/socket/extconf.rb index 544bed5298cfc6..4e8536fc606bc0 100644 --- a/ext/socket/extconf.rb +++ b/ext/socket/extconf.rb @@ -706,8 +706,6 @@ def %(s) s || self end have_func("pthread_create") have_func("pthread_detach") - have_func("pthread_attr_setaffinity_np") - have_func("sched_getcpu") $VPATH << '$(topdir)' << '$(top_srcdir)' create_makefile("socket") diff --git a/ext/socket/raddrinfo.c b/ext/socket/raddrinfo.c index ceaac031a2b1ec..560312741f6820 100644 --- a/ext/socket/raddrinfo.c +++ b/ext/socket/raddrinfo.c @@ -461,7 +461,7 @@ cancel_getaddrinfo(void *ptr) } static int -do_pthread_create(pthread_t *th, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) +do_pthread_create(pthread_t *th, void *(*start_routine) (void *), void *arg) { int limit = 3, ret; do { @@ -469,7 +469,7 @@ do_pthread_create(pthread_t *th, const pthread_attr_t *attr, void *(*start_routi // // https://bugs.openjdk.org/browse/JDK-8268605 // https://github.com/openjdk/jdk/commit/e35005d5ce383ddd108096a3079b17cb0bcf76f1 - ret = pthread_create(th, attr, start_routine, arg); + ret = pthread_create(th, 0, start_routine, arg); } while (ret == EAGAIN && limit-- > 0); return ret; } @@ -489,33 +489,13 @@ rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hint return EAI_MEMORY; } - pthread_attr_t attr; - if (pthread_attr_init(&attr) != 0) { - free_getaddrinfo_arg(arg); - return EAI_AGAIN; - } -#if defined(HAVE_PTHREAD_ATTR_SETAFFINITY_NP) && defined(HAVE_SCHED_GETCPU) - cpu_set_t tmp_cpu_set; - CPU_ZERO(&tmp_cpu_set); - int cpu = sched_getcpu(); - if (cpu < CPU_SETSIZE) { - CPU_SET(cpu, &tmp_cpu_set); - pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &tmp_cpu_set); - } -#endif - pthread_t th; - if (do_pthread_create(&th, &attr, do_getaddrinfo, arg) != 0) { + if (do_pthread_create(&th, do_getaddrinfo, arg) != 0) { free_getaddrinfo_arg(arg); return EAI_AGAIN; } pthread_detach(th); - int r; - if ((r = pthread_attr_destroy(&attr)) != 0) { - rb_bug_errno("pthread_attr_destroy", r); - } - rb_thread_call_without_gvl2(wait_getaddrinfo, arg, cancel_getaddrinfo, arg); int need_free = 0; @@ -721,33 +701,13 @@ rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, return EAI_MEMORY; } - pthread_attr_t attr; - if (pthread_attr_init(&attr) != 0) { - free_getnameinfo_arg(arg); - return EAI_AGAIN; - } -#if defined(HAVE_PTHREAD_ATTR_SETAFFINITY_NP) && defined(HAVE_SCHED_GETCPU) - cpu_set_t tmp_cpu_set; - CPU_ZERO(&tmp_cpu_set); - int cpu = sched_getcpu(); - if (cpu < CPU_SETSIZE) { - CPU_SET(cpu, &tmp_cpu_set); - pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &tmp_cpu_set); - } -#endif - pthread_t th; - if (do_pthread_create(&th, &attr, do_getnameinfo, arg) != 0) { + if (do_pthread_create(&th, do_getnameinfo, arg) != 0) { free_getnameinfo_arg(arg); return EAI_AGAIN; } pthread_detach(th); - int r; - if ((r = pthread_attr_destroy(&attr)) != 0) { - rb_bug_errno("pthread_attr_destroy", r); - } - rb_thread_call_without_gvl2(wait_getnameinfo, arg, cancel_getnameinfo, arg); int need_free = 0; From 94e1d3f3fadb6181301a5279a7c80d6c5ae25d51 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Tue, 9 Jan 2024 11:15:31 -0700 Subject: [PATCH 028/640] [rubygems/rubygems] include MatchMetadata in Bundler::LazySpecification I'm running into a case in my plugin where matches_current_metadata? is getting called on a lazy specification, and adding this fixes it https://github.com/rubygems/rubygems/commit/24f962cb42 --- lib/bundler/lazy_specification.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/bundler/lazy_specification.rb b/lib/bundler/lazy_specification.rb index 38aea2a4aa83eb..8669e021c218e3 100644 --- a/lib/bundler/lazy_specification.rb +++ b/lib/bundler/lazy_specification.rb @@ -4,6 +4,7 @@ module Bundler class LazySpecification + include MatchMetadata include MatchPlatform include ForcePlatform From 08e22c64b34e2809ba6cafc82615b9c1fa8185fe Mon Sep 17 00:00:00 2001 From: Kenta Murata <3959+mrkn@users.noreply.github.com> Date: Tue, 26 Dec 2023 10:25:46 +0900 Subject: [PATCH 029/640] [rubygems/rubygems] Use cache_home instead of data_home in default_spec_cache_dir https://github.com/rubygems/rubygems/commit/d2801fcfde --- lib/rubygems/defaults.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rubygems/defaults.rb b/lib/rubygems/defaults.rb index 00dc5707c396fc..19cf306f889df3 100644 --- a/lib/rubygems/defaults.rb +++ b/lib/rubygems/defaults.rb @@ -24,7 +24,7 @@ def self.default_spec_cache_dir default_spec_cache_dir = File.join Gem.user_home, ".gem", "specs" unless File.exist?(default_spec_cache_dir) - default_spec_cache_dir = File.join Gem.data_home, "gem", "specs" + default_spec_cache_dir = File.join Gem.cache_home, "gem", "specs" end default_spec_cache_dir From ff0119354ee4bd836749b171e95458affa10b064 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 10 Jan 2024 17:01:29 +0900 Subject: [PATCH 030/640] [rubygems/rubygems] bin/rubocop -A --only Performance/StringInclude https://github.com/rubygems/rubygems/commit/34df962cf4 --- lib/rubygems/commands/rdoc_command.rb | 2 +- test/rubygems/test_gem_ext_builder.rb | 2 +- test/rubygems/test_gem_source.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/rubygems/commands/rdoc_command.rb b/lib/rubygems/commands/rdoc_command.rb index 1321bc45f752cd..2303e16424130b 100644 --- a/lib/rubygems/commands/rdoc_command.rb +++ b/lib/rubygems/commands/rdoc_command.rb @@ -87,7 +87,7 @@ def execute begin doc.generate rescue Errno::ENOENT => e - match = / - /.match(e.message) + match = e.message.include?(' - ') alert_error "Unable to document #{spec.full_name}, " \ " #{match.post_match} is missing, skipping" terminate_interaction 1 if specs.length == 1 diff --git a/test/rubygems/test_gem_ext_builder.rb b/test/rubygems/test_gem_ext_builder.rb index 927e2f45e4bf1c..64ea1e5a2bb1f6 100644 --- a/test/rubygems/test_gem_ext_builder.rb +++ b/test/rubygems/test_gem_ext_builder.rb @@ -52,7 +52,7 @@ def test_class_make assert_match(/DESTDIR\\=#{ENV['DESTDIR']}$/, results) assert_match(/DESTDIR\\=#{ENV['DESTDIR']} install$/, results) - unless /nmake/.match?(results) + unless results.include?('nmake') assert_match(/^clean: destination$/, results) assert_match(/^all: destination$/, results) assert_match(/^install: destination$/, results) diff --git a/test/rubygems/test_gem_source.rb b/test/rubygems/test_gem_source.rb index 096ac36a661446..870f7b1dc2eb08 100644 --- a/test/rubygems/test_gem_source.rb +++ b/test/rubygems/test_gem_source.rb @@ -39,7 +39,7 @@ def test_cache_dir_escapes_windows_paths uri = URI.parse("file:///C:/WINDOWS/Temp/gem_repo") root = Gem.spec_cache_dir cache_dir = @source.cache_dir(uri).gsub(root, "") - assert cache_dir !~ /:/, "#{cache_dir} should not contain a :" + assert !cache_dir.include?(':'), "#{cache_dir} should not contain a :" end def test_dependency_resolver_set_bundler_api From 443e4178859ed4d2789c3e5c982647a8e10d7021 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 10 Jan 2024 17:02:03 +0900 Subject: [PATCH 031/640] [rubygems/rubygems] bin/rubocop -A --only Style/RedundantParentheses https://github.com/rubygems/rubygems/commit/7cc647c8f3 --- lib/bundler/cli/binstubs.rb | 2 +- lib/bundler/rubygems_ext.rb | 2 +- lib/rubygems/defaults.rb | 8 ++++---- test/rubygems/test_gem_safe_marshal.rb | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/bundler/cli/binstubs.rb b/lib/bundler/cli/binstubs.rb index ad41ebf4b44cfa..8ce138df96ba3e 100644 --- a/lib/bundler/cli/binstubs.rb +++ b/lib/bundler/cli/binstubs.rb @@ -45,7 +45,7 @@ def run next end - Bundler.settings.temporary(path: (Bundler.settings[:path] || Bundler.root)) do + Bundler.settings.temporary(path: Bundler.settings[:path] || Bundler.root) do installer.generate_standalone_bundler_executable_stubs(spec, installer_opts) end else diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb index e0582beba286f5..ab502e4a2e07e6 100644 --- a/lib/bundler/rubygems_ext.rb +++ b/lib/bundler/rubygems_ext.rb @@ -282,7 +282,7 @@ def match_platforms?(platform, platforms) # On universal Rubies, resolve the "universal" arch to the real CPU arch, without changing the extension directory. class BasicSpecification - if /^universal\.(?.*?)-/ =~ (CROSS_COMPILING || RUBY_PLATFORM) + if /^universal\.(?.*?)-/ =~ CROSS_COMPILING || RUBY_PLATFORM local_platform = Platform.local if local_platform.cpu == "universal" ORIGINAL_LOCAL_PLATFORM = local_platform.to_s.freeze diff --git a/lib/rubygems/defaults.rb b/lib/rubygems/defaults.rb index 19cf306f889df3..ca161a4d95bc76 100644 --- a/lib/rubygems/defaults.rb +++ b/lib/rubygems/defaults.rb @@ -112,7 +112,7 @@ def self.user_dir # The path to standard location of the user's configuration directory. def self.config_home - @config_home ||= (ENV["XDG_CONFIG_HOME"] || File.join(Gem.user_home, ".config")) + @config_home ||= ENV["XDG_CONFIG_HOME"] || File.join(Gem.user_home, ".config") end ## @@ -145,21 +145,21 @@ def self.state_file # The path to standard location of the user's cache directory. def self.cache_home - @cache_home ||= (ENV["XDG_CACHE_HOME"] || File.join(Gem.user_home, ".cache")) + @cache_home ||= ENV["XDG_CACHE_HOME"] || File.join(Gem.user_home, ".cache") end ## # The path to standard location of the user's data directory. def self.data_home - @data_home ||= (ENV["XDG_DATA_HOME"] || File.join(Gem.user_home, ".local", "share")) + @data_home ||= ENV["XDG_DATA_HOME"] || File.join(Gem.user_home, ".local", "share") end ## # The path to standard location of the user's state directory. def self.state_home - @state_home ||= (ENV["XDG_STATE_HOME"] || File.join(Gem.user_home, ".local", "state")) + @state_home ||= ENV["XDG_STATE_HOME"] || File.join(Gem.user_home, ".local", "state") end ## diff --git a/test/rubygems/test_gem_safe_marshal.rb b/test/rubygems/test_gem_safe_marshal.rb index 7f56d8d2903597..c72f72bb2a2028 100644 --- a/test/rubygems/test_gem_safe_marshal.rb +++ b/test/rubygems/test_gem_safe_marshal.rb @@ -120,7 +120,7 @@ class TestGemSafeMarshal < Gem::TestCase define_method("test_safe_load_marshal Time 2001-01-01 07:59:59 UTC") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\xC0\x00\x00\xB0\xEF\x06:\tzoneI\"\bUTC\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] } define_method("test_safe_load_marshal Time 2001-01-01 11:59:59 +0400") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x00\x00\xB0\xEF\a:\voffseti\x02@8:\tzone0", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] } define_method("test_safe_load_marshal Time 2023-08-24 10:10:39.09565 -0700") { assert_safe_load_marshal "\x04\bIu:\tTime\r\x11\xDF\x1E\x80\xA2uq*\a:\voffseti\xFE\x90\x9D:\tzoneI\"\bPDT\x06:\x06EF" } - define_method("test_safe_load_marshal Time 2023-08-24 10:10:39.098453 -0700") { assert_safe_load_marshal "\x04\bIu:\tTime\r\x11\xDF\x1E\x80\x95\x80q*\b:\n@typeI\"\fruntime\x06:\x06ET:\voffseti\xFE\x90\x9D:\tzoneI\"\bPDT\x06;\aF", permitted_ivars: { "Time" => %w[@type offset zone], "String" => %w[E @debug_created_info] }, marshal_dump_equality: (RUBY_ENGINE != "truffleruby" || RUBY_ENGINE_VERSION >= "23") } + define_method("test_safe_load_marshal Time 2023-08-24 10:10:39.098453 -0700") { assert_safe_load_marshal "\x04\bIu:\tTime\r\x11\xDF\x1E\x80\x95\x80q*\b:\n@typeI\"\fruntime\x06:\x06ET:\voffseti\xFE\x90\x9D:\tzoneI\"\bPDT\x06;\aF", permitted_ivars: { "Time" => %w[@type offset zone], "String" => %w[E @debug_created_info] }, marshal_dump_equality: RUBY_ENGINE != "truffleruby" || RUBY_ENGINE_VERSION >= "23" } def test_repeated_symbol assert_safe_load_as [:development, :development] @@ -188,7 +188,7 @@ def test_time_with_ivar pend "Marshal.load of Time with ivars is broken on jruby, see https://github.com/jruby/jruby/issues/7902" if RUBY_ENGINE == "jruby" with_const(Gem::SafeMarshal, :PERMITTED_IVARS, { "Time" => %w[@type offset zone nano_num nano_den submicro], "String" => %w[E @debug_created_info] }) do - assert_safe_load_as Time.new.tap {|t| t.instance_variable_set :@type, "runtime" }, marshal_dump_equality: (RUBY_ENGINE != "truffleruby" || RUBY_ENGINE_VERSION >= "23") + assert_safe_load_as Time.new.tap {|t| t.instance_variable_set :@type, "runtime" }, marshal_dump_equality: RUBY_ENGINE != "truffleruby" || RUBY_ENGINE_VERSION >= "23" end end From ea31461ba0cd9eb2fb68fd5b13266e75c343a471 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 10 Jan 2024 17:02:32 +0900 Subject: [PATCH 032/640] [rubygems/rubygems] bin/rubocop -A --only Style/StringLiterals https://github.com/rubygems/rubygems/commit/f25013bcc0 --- lib/rubygems/commands/rdoc_command.rb | 2 +- test/rubygems/test_gem_ext_builder.rb | 2 +- test/rubygems/test_gem_source.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/rubygems/commands/rdoc_command.rb b/lib/rubygems/commands/rdoc_command.rb index 2303e16424130b..b9470411ef82c7 100644 --- a/lib/rubygems/commands/rdoc_command.rb +++ b/lib/rubygems/commands/rdoc_command.rb @@ -87,7 +87,7 @@ def execute begin doc.generate rescue Errno::ENOENT => e - match = e.message.include?(' - ') + match = e.message.include?(" - ") alert_error "Unable to document #{spec.full_name}, " \ " #{match.post_match} is missing, skipping" terminate_interaction 1 if specs.length == 1 diff --git a/test/rubygems/test_gem_ext_builder.rb b/test/rubygems/test_gem_ext_builder.rb index 64ea1e5a2bb1f6..b1b63560209015 100644 --- a/test/rubygems/test_gem_ext_builder.rb +++ b/test/rubygems/test_gem_ext_builder.rb @@ -52,7 +52,7 @@ def test_class_make assert_match(/DESTDIR\\=#{ENV['DESTDIR']}$/, results) assert_match(/DESTDIR\\=#{ENV['DESTDIR']} install$/, results) - unless results.include?('nmake') + unless results.include?("nmake") assert_match(/^clean: destination$/, results) assert_match(/^all: destination$/, results) assert_match(/^install: destination$/, results) diff --git a/test/rubygems/test_gem_source.rb b/test/rubygems/test_gem_source.rb index 870f7b1dc2eb08..aa26dd07f08d32 100644 --- a/test/rubygems/test_gem_source.rb +++ b/test/rubygems/test_gem_source.rb @@ -39,7 +39,7 @@ def test_cache_dir_escapes_windows_paths uri = URI.parse("file:///C:/WINDOWS/Temp/gem_repo") root = Gem.spec_cache_dir cache_dir = @source.cache_dir(uri).gsub(root, "") - assert !cache_dir.include?(':'), "#{cache_dir} should not contain a :" + assert !cache_dir.include?(":"), "#{cache_dir} should not contain a :" end def test_dependency_resolver_set_bundler_api From 888a8f4318b7182addc9bf7ff096fd3c3327daba Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 10 Jan 2024 17:02:51 +0900 Subject: [PATCH 033/640] [rubygems/rubygems] bin/rubocop -A --only Style/StringLiteralsInInterpolation https://github.com/rubygems/rubygems/commit/2333f5f9c5 --- lib/rubygems/specification_policy.rb | 2 +- .../test_gem_commands_environment_command.rb | 2 +- test/rubygems/test_gem_dependency_installer.rb | 2 +- test/rubygems/test_gem_ext_builder.rb | 12 ++++++------ 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/rubygems/specification_policy.rb b/lib/rubygems/specification_policy.rb index 66558252873239..77d58638192dd5 100644 --- a/lib/rubygems/specification_policy.rb +++ b/lib/rubygems/specification_policy.rb @@ -7,7 +7,7 @@ class Gem::SpecificationPolicy VALID_NAME_PATTERN = /\A[a-zA-Z0-9\.\-\_]+\z/ # :nodoc: - SPECIAL_CHARACTERS = /\A[#{Regexp.escape('.-_')}]+/ # :nodoc: + SPECIAL_CHARACTERS = /\A[#{Regexp.escape(".-_")}]+/ # :nodoc: VALID_URI_PATTERN = %r{\Ahttps?:\/\/([^\s:@]+:[^\s:@]*@)?[A-Za-z\d\-]+(\.[A-Za-z\d\-]+)+\.?(:\d{1,5})?([\/?]\S*)?\z} # :nodoc: diff --git a/test/rubygems/test_gem_commands_environment_command.rb b/test/rubygems/test_gem_commands_environment_command.rb index f527574c070bf1..48252d84d4e49b 100644 --- a/test/rubygems/test_gem_commands_environment_command.rb +++ b/test/rubygems/test_gem_commands_environment_command.rb @@ -30,7 +30,7 @@ def test_execute assert_match(/USER INSTALLATION DIRECTORY: #{Regexp.escape Gem.user_dir}/, @ui.output) assert_match(/RUBYGEMS PREFIX: /, @ui.output) - assert_match(/RUBY EXECUTABLE:.*#{RbConfig::CONFIG['ruby_install_name']}/, + assert_match(/RUBY EXECUTABLE:.*#{RbConfig::CONFIG["ruby_install_name"]}/, @ui.output) assert_match(/GIT EXECUTABLE: #{@cmd.send(:git_path)}/, @ui.output) assert_match(/SYSTEM CONFIGURATION DIRECTORY:/, @ui.output) diff --git a/test/rubygems/test_gem_dependency_installer.rb b/test/rubygems/test_gem_dependency_installer.rb index ac84a589e5f560..9eb6049df18cd6 100644 --- a/test/rubygems/test_gem_dependency_installer.rb +++ b/test/rubygems/test_gem_dependency_installer.rb @@ -621,7 +621,7 @@ def test_install_env_shebang env = "/\\S+/env" unless Gem.win_platform? - assert_match(/\A#!#{env} #{RbConfig::CONFIG['ruby_install_name']}\n/, + assert_match(/\A#!#{env} #{RbConfig::CONFIG["ruby_install_name"]}\n/, File.read(File.join(@gemhome, "bin", "a_bin"))) end diff --git a/test/rubygems/test_gem_ext_builder.rb b/test/rubygems/test_gem_ext_builder.rb index b1b63560209015..493aaa1b530385 100644 --- a/test/rubygems/test_gem_ext_builder.rb +++ b/test/rubygems/test_gem_ext_builder.rb @@ -48,9 +48,9 @@ def test_class_make results = results.join("\n").b - assert_match(/DESTDIR\\=#{ENV['DESTDIR']} clean$/, results) - assert_match(/DESTDIR\\=#{ENV['DESTDIR']}$/, results) - assert_match(/DESTDIR\\=#{ENV['DESTDIR']} install$/, results) + assert_match(/DESTDIR\\=#{ENV["DESTDIR"]} clean$/, results) + assert_match(/DESTDIR\\=#{ENV["DESTDIR"]}$/, results) + assert_match(/DESTDIR\\=#{ENV["DESTDIR"]} install$/, results) unless results.include?("nmake") assert_match(/^clean: destination$/, results) @@ -77,9 +77,9 @@ def test_class_make_no_clean results = results.join("\n").b - assert_match(/DESTDIR\\=#{ENV['DESTDIR']} clean$/, results) - assert_match(/DESTDIR\\=#{ENV['DESTDIR']}$/, results) - assert_match(/DESTDIR\\=#{ENV['DESTDIR']} install$/, results) + assert_match(/DESTDIR\\=#{ENV["DESTDIR"]} clean$/, results) + assert_match(/DESTDIR\\=#{ENV["DESTDIR"]}$/, results) + assert_match(/DESTDIR\\=#{ENV["DESTDIR"]} install$/, results) end def test_custom_make_with_options From 983ca8e9c97b3065ce909f5595eeb1ed6bc0a85f Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 10 Jan 2024 17:03:08 +0900 Subject: [PATCH 034/640] [rubygems/rubygems] bin/rubocop -A --only Layout/SpaceBeforeFirstArg https://github.com/rubygems/rubygems/commit/cfcc33d480 --- test/rubygems/test_gem_dependency_installer.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem_dependency_installer.rb b/test/rubygems/test_gem_dependency_installer.rb index 9eb6049df18cd6..3740e523c591f9 100644 --- a/test/rubygems/test_gem_dependency_installer.rb +++ b/test/rubygems/test_gem_dependency_installer.rb @@ -198,7 +198,7 @@ def test_install_dependencies_satisfied Gem::Specification.reset FileUtils.mv @a1_gem, @tempdir - FileUtils.mv a2_gem, @tempdir # not in index + FileUtils.mv a2_gem, @tempdir # not in index FileUtils.mv @b1_gem, @tempdir inst = nil @@ -237,7 +237,7 @@ def test_install_doesnt_upgrade_installed_dependencies Gem::Specification.reset FileUtils.mv @a1_gem, @tempdir - FileUtils.mv a2_gem, @tempdir # not in index + FileUtils.mv a2_gem, @tempdir # not in index FileUtils.mv @b1_gem, @tempdir FileUtils.mv a3_gem, @tempdir From a1d5c6555efbec37a85a816c0617071ff4eccb97 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 10 Jan 2024 17:03:30 +0900 Subject: [PATCH 035/640] [rubygems/rubygems] bin/rubocop -A --only Layout/ExtraSpacing https://github.com/rubygems/rubygems/commit/39be5cd236 --- lib/bundler/cli.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index d93feb7b55ceb8..244ab55967f450 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -620,7 +620,7 @@ def inject(name, version) method_option "major", type: :boolean, banner: "If updating, prefer updating to next major version (default)" method_option "pre", type: :boolean, banner: "If updating, always choose the highest allowed version, regardless of prerelease status" method_option "strict", type: :boolean, banner: "If updating, do not allow any gem to be updated past latest --patch | --minor | --major" - method_option "conservative", type: :boolean, banner: "If updating, use bundle install conservative update behavior and do not allow shared dependencies to be updated" + method_option "conservative", type: :boolean, banner: "If updating, use bundle install conservative update behavior and do not allow shared dependencies to be updated" method_option "bundler", type: :string, lazy_default: "> 0.a", banner: "Update the locked version of bundler" def lock require_relative "cli/lock" From 0e8b1973b429d0f2ed9200ec7c68ca4349d5c425 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 10 Jan 2024 17:03:47 +0900 Subject: [PATCH 036/640] [rubygems/rubygems] bin/rubocop -A --only Style/RedundantReturn https://github.com/rubygems/rubygems/commit/ade728914f --- lib/rubygems.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rubygems.rb b/lib/rubygems.rb index fc016cf30e6913..47b1ce69d26608 100644 --- a/lib/rubygems.rb +++ b/lib/rubygems.rb @@ -1218,7 +1218,7 @@ def register_default_spec(spec) def find_unresolved_default_spec(path) default_spec = @path_to_default_spec_map[path] - return default_spec if default_spec && loaded_specs[default_spec.name] != default_spec + default_spec if default_spec && loaded_specs[default_spec.name] != default_spec end ## From acdc6abca82ddba8312e2bfd7968aaaaf3337a49 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 10 Jan 2024 18:37:37 +0900 Subject: [PATCH 037/640] [rubygems/rubygems] Disable false positive correction https://github.com/rubygems/rubygems/commit/e75cca9496 --- lib/bundler/rubygems_ext.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb index ab502e4a2e07e6..3cb4e70a56a971 100644 --- a/lib/bundler/rubygems_ext.rb +++ b/lib/bundler/rubygems_ext.rb @@ -282,7 +282,7 @@ def match_platforms?(platform, platforms) # On universal Rubies, resolve the "universal" arch to the real CPU arch, without changing the extension directory. class BasicSpecification - if /^universal\.(?.*?)-/ =~ CROSS_COMPILING || RUBY_PLATFORM + if /^universal\.(?.*?)-/ =~ (CROSS_COMPILING || RUBY_PLATFORM) # rubocop:disable Style/RedundantParentheses local_platform = Platform.local if local_platform.cpu == "universal" ORIGINAL_LOCAL_PLATFORM = local_platform.to_s.freeze From 76916217b6dcb5171a41aad07420f2d8b7d631ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 22 Dec 2023 18:15:05 +0100 Subject: [PATCH 038/640] [rubygems/rubygems] Extract `SpecSet#reset!` helper https://github.com/rubygems/rubygems/commit/41f9b4d940 --- lib/bundler/spec_set.rb | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb index ceaac2cec523d0..c8a87d0835fa33 100644 --- a/lib/bundler/spec_set.rb +++ b/lib/bundler/spec_set.rb @@ -86,8 +86,7 @@ def complete_platforms!(platforms) less_specific_platform = new_platforms.find {|platform| platform != Gem::Platform::RUBY && platform === Bundler.local_platform } platforms.delete(Bundler.local_platform) if less_specific_platform - @sorted = nil - @lookup = nil + reset! platforms end @@ -110,14 +109,14 @@ def [](key) def []=(key, value) @specs << value - @lookup = nil - @sorted = nil + + reset! end def delete(specs) specs.each {|spec| @specs.delete(spec) } - @lookup = nil - @sorted = nil + + reset! end def sort! @@ -175,8 +174,8 @@ def find_by_name_and_platform(name, platform) def delete_by_name(name) @specs.reject! {|spec| spec.name == name } - @lookup = nil - @sorted = nil + + reset! end def what_required(spec) @@ -212,6 +211,11 @@ def names private + def reset! + @sorted = nil + @lookup = nil + end + def valid_dependencies?(s) validate_deps(s) == :valid end From e90081446785273d7df8b37f0ba384c810738d0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 22 Dec 2023 18:16:01 +0100 Subject: [PATCH 039/640] [rubygems/rubygems] Make private helper private https://github.com/rubygems/rubygems/commit/de9dc90026 --- lib/bundler/definition.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 9b905db1f9aee6..316a75063992d2 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -312,10 +312,6 @@ def resolve end end - def should_complete_platforms? - !lockfile_exists? && generic_local_platform_is_ruby? && !Bundler.settings[:force_ruby_platform] - end - def spec_git_paths sources.git_sources.map {|s| File.realpath(s.path) if File.exist?(s.path) }.compact end @@ -517,6 +513,10 @@ def unlocking? private + def should_complete_platforms? + !lockfile_exists? && generic_local_platform_is_ruby? && !Bundler.settings[:force_ruby_platform] + end + def lockfile_exists? lockfile && File.exist?(lockfile) end From ab1936faf9197e0466a581de19f4023fdfe10204 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 22 Dec 2023 18:16:54 +0100 Subject: [PATCH 040/640] [rubygems/rubygems] Remove methods to clarify what they do https://github.com/rubygems/rubygems/commit/1d15d8a8ff --- lib/bundler/definition.rb | 4 ++-- lib/bundler/spec_set.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index 316a75063992d2..a19eb13428a58d 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -513,7 +513,7 @@ def unlocking? private - def should_complete_platforms? + def should_add_extra_platforms? !lockfile_exists? && generic_local_platform_is_ruby? && !Bundler.settings[:force_ruby_platform] end @@ -600,7 +600,7 @@ def start_resolution result = SpecSet.new(resolver.start) @resolved_bundler_version = result.find {|spec| spec.name == "bundler" }&.version - @platforms = result.complete_platforms!(platforms) if should_complete_platforms? + @platforms = result.add_extra_platforms!(platforms) if should_add_extra_platforms? SpecSet.new(result.for(dependencies, false, @platforms)) end diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb index c8a87d0835fa33..09bbea27c54c4a 100644 --- a/lib/bundler/spec_set.rb +++ b/lib/bundler/spec_set.rb @@ -52,7 +52,7 @@ def for(dependencies, check = false, platforms = [nil]) specs.uniq end - def complete_platforms!(platforms) + def add_extra_platforms!(platforms) return platforms.concat([Gem::Platform::RUBY]).uniq if @specs.empty? new_platforms = @specs.flat_map {|spec| spec.source.specs.search([spec.name, spec.version]).map(&:platform) }.uniq.select do |platform| From 51d2a8e983ddc25e2333706f0fc6f1c01e12fa06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 22 Dec 2023 18:27:39 +0100 Subject: [PATCH 041/640] [rubygems/rubygems] Extract a couple of helper methods https://github.com/rubygems/rubygems/commit/880a4eae7f --- lib/bundler/spec_set.rb | 49 ++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb index 09bbea27c54c4a..d241842c378008 100644 --- a/lib/bundler/spec_set.rb +++ b/lib/bundler/spec_set.rb @@ -55,29 +55,11 @@ def for(dependencies, check = false, platforms = [nil]) def add_extra_platforms!(platforms) return platforms.concat([Gem::Platform::RUBY]).uniq if @specs.empty? - new_platforms = @specs.flat_map {|spec| spec.source.specs.search([spec.name, spec.version]).map(&:platform) }.uniq.select do |platform| + new_platforms = all_platforms.select do |platform| next if platforms.include?(platform) next unless GemHelpers.generic(platform) == Gem::Platform::RUBY - new_specs = [] - - valid_platform = lookup.all? do |_, specs| - spec = specs.first - matching_specs = spec.source.specs.search([spec.name, spec.version]) - platform_spec = GemHelpers.select_best_platform_match(matching_specs, platform).find do |s| - s.matches_current_metadata? && valid_dependencies?(s) - end - - if platform_spec - new_specs << LazySpecification.from_spec(platform_spec) - true - else - false - end - end - next unless valid_platform - - @specs.concat(new_specs.uniq) + complete_platform(platform) end return platforms if new_platforms.empty? @@ -216,6 +198,33 @@ def reset! @lookup = nil end + def complete_platform(platform) + new_specs = [] + + valid_platform = lookup.all? do |_, specs| + spec = specs.first + matching_specs = spec.source.specs.search([spec.name, spec.version]) + platform_spec = GemHelpers.select_best_platform_match(matching_specs, platform).find do |s| + s.matches_current_metadata? && valid_dependencies?(s) + end + + if platform_spec + new_specs << LazySpecification.from_spec(platform_spec) + true + else + false + end + end + + @specs.concat(new_specs.uniq) if valid_platform + + valid_platform + end + + def all_platforms + @specs.flat_map {|spec| spec.source.specs.search([spec.name, spec.version]).map(&:platform) }.uniq + end + def valid_dependencies?(s) validate_deps(s) == :valid end From 7f0dbfc9c80777b0f189bdaf1b2f70f309ddab31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 22 Dec 2023 18:58:55 +0100 Subject: [PATCH 042/640] [rubygems/rubygems] Move resetting the spec set to where it becomes necessary https://github.com/rubygems/rubygems/commit/a8b547c6b1 --- lib/bundler/spec_set.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb index d241842c378008..04a1fac2bac30c 100644 --- a/lib/bundler/spec_set.rb +++ b/lib/bundler/spec_set.rb @@ -68,8 +68,6 @@ def add_extra_platforms!(platforms) less_specific_platform = new_platforms.find {|platform| platform != Gem::Platform::RUBY && platform === Bundler.local_platform } platforms.delete(Bundler.local_platform) if less_specific_platform - reset! - platforms end @@ -209,14 +207,18 @@ def complete_platform(platform) end if platform_spec - new_specs << LazySpecification.from_spec(platform_spec) + new_specs << LazySpecification.from_spec(platform_spec) unless specs.include?(platform_spec) true else false end end - @specs.concat(new_specs.uniq) if valid_platform + if valid_platform && new_specs.any? + @specs.concat(new_specs) + + reset! + end valid_platform end From 580d4a4053067dde69be81133a55bd1bf8ef65c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 22 Dec 2023 19:29:47 +0100 Subject: [PATCH 043/640] [rubygems/rubygems] Show diff on source control errors https://github.com/rubygems/rubygems/commit/d728fa1b04 --- spec/bundler/support/rubygems_ext.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/bundler/support/rubygems_ext.rb b/spec/bundler/support/rubygems_ext.rb index c242e3a5287366..0d1ad2d5289db3 100644 --- a/spec/bundler/support/rubygems_ext.rb +++ b/spec/bundler/support/rubygems_ext.rb @@ -86,7 +86,7 @@ def check_source_control_changes(success_message:, error_message:) puts success_message puts else - system("git status --porcelain") + system("git diff") puts puts error_message From b8f859f0bf21d67d962d12a99e1f2d7d2f20e3e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 22 Dec 2023 18:59:44 +0100 Subject: [PATCH 044/640] Complete missing specs for platforms after resolution If two platform specific variants have different dependencies, then resolution may fallback to the non platform specific variant. However, the platform specific variants that have the same dependencies as the non specific one can still be kept. Do a pass to complete those after resolution. --- lib/bundler/definition.rb | 2 ++ lib/bundler/spec_set.rb | 6 +++++ spec/bundler/lock/lockfile_spec.rb | 40 ++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb index a19eb13428a58d..0b0e63f77e5e4c 100644 --- a/lib/bundler/definition.rb +++ b/lib/bundler/definition.rb @@ -602,6 +602,8 @@ def start_resolution @resolved_bundler_version = result.find {|spec| spec.name == "bundler" }&.version @platforms = result.add_extra_platforms!(platforms) if should_add_extra_platforms? + result.complete_platforms!(platforms) + SpecSet.new(result.for(dependencies, false, @platforms)) end diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb index 04a1fac2bac30c..cc649abaf85dac 100644 --- a/lib/bundler/spec_set.rb +++ b/lib/bundler/spec_set.rb @@ -71,6 +71,12 @@ def add_extra_platforms!(platforms) platforms end + def complete_platforms!(platforms) + platforms.each do |platform| + complete_platform(platform) + end + end + def validate_deps(s) s.runtime_dependencies.each do |dep| next if dep.name == "bundler" diff --git a/spec/bundler/lock/lockfile_spec.rb b/spec/bundler/lock/lockfile_spec.rb index 5e996f5aaca02a..7f664abc4d8e7f 100644 --- a/spec/bundler/lock/lockfile_spec.rb +++ b/spec/bundler/lock/lockfile_spec.rb @@ -1195,6 +1195,46 @@ G end + it "adds compatible platform specific variants to the lockfile, even if resolution fallback to RUBY due to some other incompatible platform specific variant" do + simulate_platform "arm64-darwin-23" do + build_repo4 do + build_gem "google-protobuf", "3.25.1" + build_gem "google-protobuf", "3.25.1" do |s| + s.platform = "arm64-darwin-23" + end + build_gem "google-protobuf", "3.25.1" do |s| + s.platform = "x64-mingw-ucrt" + s.required_ruby_version = "> #{Gem.ruby_version}" + end + end + + gemfile <<-G + source "#{file_uri_for(gem_repo4)}" + gem "google-protobuf" + G + bundle "lock --add-platform x64-mingw-ucrt" + + expect(lockfile).to eq <<~L + GEM + remote: #{file_uri_for(gem_repo4)}/ + specs: + google-protobuf (3.25.1) + google-protobuf (3.25.1-arm64-darwin-23) + + PLATFORMS + arm64-darwin-23 + ruby + x64-mingw-ucrt + + DEPENDENCIES + google-protobuf + + BUNDLED WITH + #{Bundler::VERSION} + L + end + end + it "persists the spec's specific platform to the lockfile" do build_repo2 do build_gem "platform_specific", "1.0" do |s| From ef0705b3c2339055d9b5c669fb6192275c39020a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 5 Jan 2024 19:47:32 +0100 Subject: [PATCH 045/640] [rubygems/rubygems] Fix development dependency not being added if introduced by two gemspecs https://github.com/rubygems/rubygems/commit/adc05bf1c3 --- lib/bundler/dsl.rb | 14 ++++++------- spec/bundler/commands/install_spec.rb | 29 +++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/lib/bundler/dsl.rb b/lib/bundler/dsl.rb index 1eca749617a0da..1460b9f52f9734 100644 --- a/lib/bundler/dsl.rb +++ b/lib/bundler/dsl.rb @@ -102,9 +102,6 @@ def gem(name, *args) # if there's already a dependency with this name we try to prefer one if current = @dependencies.find {|d| d.name == dep.name } - # Always prefer the dependency from the Gemfile - @dependencies.delete(current) if current.gemspec_dev_dep? - if current.requirement != dep.requirement current_requirement_open = current.requirements_list.include?(">= 0") @@ -116,8 +113,6 @@ def gem(name, *args) Bundler.ui.warn "A gemspec development dependency (#{gemspec_dep.name}, #{gemspec_dep.requirement}) is being overridden by a Gemfile dependency (#{gemfile_dep.name}, #{gemfile_dep.requirement}).\n" \ "This behaviour may change in the future. Please remove either of them, or make sure they both have the same requirement\n" end - - return if dep.gemspec_dev_dep? else update_prompt = "" @@ -135,8 +130,13 @@ def gem(name, *args) "You specified: #{current.name} (#{current.requirement}) and #{dep.name} (#{dep.requirement})" \ "#{update_prompt}" end - elsif current.gemspec_dev_dep? || dep.gemspec_dev_dep? - return if dep.gemspec_dev_dep? + end + + # Always prefer the dependency from the Gemfile + if current.gemspec_dev_dep? + @dependencies.delete(current) + elsif dep.gemspec_dev_dep? + return elsif current.source != dep.source raise GemfileError, "You cannot specify the same gem twice coming from different sources.\n" \ "You specified that #{dep.name} (#{dep.requirement}) should come from " \ diff --git a/spec/bundler/commands/install_spec.rb b/spec/bundler/commands/install_spec.rb index 7c016ff3d8a145..f0c9aaea8edeed 100644 --- a/spec/bundler/commands/install_spec.rb +++ b/spec/bundler/commands/install_spec.rb @@ -460,6 +460,35 @@ expect(the_bundle).to include_gems("rubocop 1.37.1") end + it "includes the gem without warning if two gemspecs add it with the same requirement" do + gem1 = tmp.join("my-gem-1") + gem2 = tmp.join("my-gem-2") + + build_lib "my-gem", path: gem1 do |s| + s.add_development_dependency "rubocop", "~> 1.36.0" + end + + build_lib "my-gem-2", path: gem2 do |s| + s.add_development_dependency "rubocop", "~> 1.36.0" + end + + build_repo4 do + build_gem "rubocop", "1.36.0" + end + + gemfile <<~G + source "#{file_uri_for(gem_repo4)}" + + gemspec path: "#{gem1}" + gemspec path: "#{gem2}" + G + + bundle :install + + expect(err).to be_empty + expect(the_bundle).to include_gems("rubocop 1.36.0") + end + it "warns when a Gemfile dependency is overriding a gemspec development dependency, with different requirements" do build_lib "my-gem", path: bundled_app do |s| s.add_development_dependency "rails", ">= 5" From aa908aa0655b6c0a566675e1ef9104aae7a84925 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Tue, 26 Dec 2023 20:23:35 +0100 Subject: [PATCH 046/640] [rubygems/rubygems] Remove old condition no longer necessary https://github.com/rubygems/rubygems/commit/701980b240 --- lib/rubygems/commands/update_command.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/rubygems/commands/update_command.rb b/lib/rubygems/commands/update_command.rb index 10ae6d9a93596b..170cdd297f99d4 100644 --- a/lib/rubygems/commands/update_command.rb +++ b/lib/rubygems/commands/update_command.rb @@ -294,9 +294,7 @@ def update_rubygems_arguments # :nodoc: args << "--prefix" << Gem.prefix if Gem.prefix args << "--no-document" unless options[:document].include?("rdoc") || options[:document].include?("ri") args << "--no-format-executable" if options[:no_format_executable] - args << "--previous-version" << Gem::VERSION if - options[:system] == true || - Gem::Version.new(options[:system]) >= Gem::Version.new(2) + args << "--previous-version" << Gem::VERSION args end From 3980cebda5438b3f7803015f37c25d94c0573b5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Tue, 26 Dec 2023 20:55:39 +0100 Subject: [PATCH 047/640] [rubygems/rubygems] Make `gem update --system` respect ruby version constraints https://github.com/rubygems/rubygems/commit/36052abbe2 --- lib/rubygems/commands/update_command.rb | 2 +- .../test_gem_commands_update_command.rb | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/rubygems/commands/update_command.rb b/lib/rubygems/commands/update_command.rb index 170cdd297f99d4..144f67acc5f797 100644 --- a/lib/rubygems/commands/update_command.rb +++ b/lib/rubygems/commands/update_command.rb @@ -282,7 +282,7 @@ def update_rubygems check_oldest_rubygems version installed_gems = Gem::Specification.find_all_by_name "rubygems-update", requirement - installed_gems = update_gem("rubygems-update", version) if installed_gems.empty? || installed_gems.first.version != version + installed_gems = update_gem("rubygems-update", requirement) if installed_gems.empty? || installed_gems.first.version != version return if installed_gems.empty? install_rubygems installed_gems.first diff --git a/test/rubygems/test_gem_commands_update_command.rb b/test/rubygems/test_gem_commands_update_command.rb index 324bd9c7473932..db00bd40c976f1 100644 --- a/test/rubygems/test_gem_commands_update_command.rb +++ b/test/rubygems/test_gem_commands_update_command.rb @@ -132,6 +132,34 @@ def test_execute_system_when_latest_does_not_support_your_ruby assert_empty err end + def test_execute_system_when_latest_does_not_support_your_ruby_but_previous_one_does + spec_fetcher do |fetcher| + fetcher.download "rubygems-update", 9 do |s| + s.files = %w[setup.rb] + s.required_ruby_version = "> 9" + end + + fetcher.download "rubygems-update", 8 do |s| + s.files = %w[setup.rb] + end + end + + @cmd.options[:args] = [] + @cmd.options[:system] = true + + use_ui @ui do + @cmd.execute + end + + err = @ui.error.split "\n" + assert_empty err + + out = @ui.output.split "\n" + assert_equal "Installing RubyGems 8", out.shift + assert_equal "RubyGems system software updated", out.shift + assert_empty out + end + def test_execute_system_multiple spec_fetcher do |fetcher| fetcher.download "rubygems-update", 8 do |s| From 0156b7416cf05880460ec6a3c2cc7b7c2ea863db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Tue, 26 Dec 2023 20:21:26 +0100 Subject: [PATCH 048/640] [rubygems/rubygems] Always avoid "Updating rubygems-update" message The fact that under the hood the upgrade is done through a rubygems-update gem is an implementation detail that does not really help users to know. Plus, it reads a bit weird. https://github.com/rubygems/rubygems/commit/0fa5c50258 --- lib/rubygems/commands/update_command.rb | 2 +- test/rubygems/test_gem_commands_update_command.rb | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/lib/rubygems/commands/update_command.rb b/lib/rubygems/commands/update_command.rb index 144f67acc5f797..3d6fecaa402202 100644 --- a/lib/rubygems/commands/update_command.rb +++ b/lib/rubygems/commands/update_command.rb @@ -244,7 +244,7 @@ def update_gem(name, version = Gem::Requirement.default) @installer = Gem::DependencyInstaller.new update_options - say "Updating #{name}" unless options[:system] && options[:silent] + say "Updating #{name}" unless options[:system] begin @installer.install name, Gem::Requirement.new(version) rescue Gem::InstallError, Gem::DependencyError => e diff --git a/test/rubygems/test_gem_commands_update_command.rb b/test/rubygems/test_gem_commands_update_command.rb index db00bd40c976f1..2683840f2ed3f0 100644 --- a/test/rubygems/test_gem_commands_update_command.rb +++ b/test/rubygems/test_gem_commands_update_command.rb @@ -79,7 +79,6 @@ def test_execute_system end out = @ui.output.split "\n" - assert_equal "Updating rubygems-update", out.shift assert_equal "Installing RubyGems 9", out.shift assert_equal "RubyGems system software updated", out.shift @@ -123,7 +122,6 @@ def test_execute_system_when_latest_does_not_support_your_ruby end out = @ui.output.split "\n" - assert_equal "Updating rubygems-update", out.shift assert_empty out err = @ui.error.split "\n" @@ -179,7 +177,6 @@ def test_execute_system_multiple end out = @ui.output.split "\n" - assert_equal "Updating rubygems-update", out.shift assert_equal "Installing RubyGems 9", out.shift assert_equal "RubyGems system software updated", out.shift @@ -213,7 +210,6 @@ def test_execute_system_update_installed end out = @ui.output.split "\n" - assert_equal "Updating rubygems-update", out.shift assert_equal "Installing RubyGems 9", out.shift assert_equal "RubyGems system software updated", out.shift @@ -270,7 +266,6 @@ def test_execute_system_specific end out = @ui.output.split "\n" - assert_equal "Updating rubygems-update", out.shift assert_equal "Installing RubyGems 8", out.shift assert_equal "RubyGems system software updated", out.shift @@ -381,7 +376,6 @@ def test_execute_system_specifically_to_latest_version end out = @ui.output.split "\n" - assert_equal "Updating rubygems-update", out.shift assert_equal "Installing RubyGems 9", out.shift assert_equal "RubyGems system software updated", out.shift From f4a347b90f2f4c61641582cd60f3cf15a1e2e979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 22 Dec 2023 22:18:23 +0100 Subject: [PATCH 049/640] [rubygems/rubygems] Fix Bundler daily CI There is another place artifice usage was making the copy of vendored http in ruby-core be loaded instead of the one under test. Remove unnecessary usage of artifice. https://github.com/rubygems/rubygems/commit/d2488199b0 --- spec/bundler/commands/update_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/bundler/commands/update_spec.rb b/spec/bundler/commands/update_spec.rb index 59e7c3867c7e87..2bde5a1586d7cd 100644 --- a/spec/bundler/commands/update_spec.rb +++ b/spec/bundler/commands/update_spec.rb @@ -1380,7 +1380,7 @@ build_bundler "999.0.0" end - install_gemfile <<-G + install_gemfile <<-G, artifice: nil, env: { "BUNDLER_IGNORE_DEFAULT_GEM" => "true" } source "#{file_uri_for(gem_repo4)}" gem "rack" G From 0ebc3f7969c8ad46c22b856c12e742806b1ddde9 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 11 Jan 2024 15:02:07 +0900 Subject: [PATCH 050/640] Revert "Update files under .github other than workflows" This reverts commit ad3db6711c4aa48c82f4091342aab7394ee45736. Above commit break dependabot update since Nov, 2023. --- .github/dependabot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 70a73430d723ba..6778b0493a160f 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,6 +1,6 @@ version: 2 updates: - package-ecosystem: 'github-actions' - directory: '/.github' + directory: '/' schedule: interval: 'daily' From 505ac323e3654e57dfe338712a6a9b63fb1e5574 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 11 Jan 2024 15:21:45 +0900 Subject: [PATCH 051/640] Try to fixup ad3db6711c4aa48c82f4091342aab7394ee45736 directory value may be not support glob files from subdirectories --- .github/dependabot.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 6778b0493a160f..ef07b0fa3f2b04 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,3 +4,11 @@ updates: directory: '/' schedule: interval: 'daily' + - package-ecosystem: 'github-actions' + directory: '/.github/actions/slack' + schedule: + interval: 'daily' + - package-ecosystem: 'github-actions' + directory: '/.github/actions/setup/directories' + schedule: + interval: 'daily' From 1a66828a7e1b280e1408ff519b03eaa9626c6ab3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Jan 2024 06:03:57 +0000 Subject: [PATCH 052/640] Bump lewagon/wait-on-check-action from 1.3.1 to 1.3.3 Bumps [lewagon/wait-on-check-action](https://github.com/lewagon/wait-on-check-action) from 1.3.1 to 1.3.3. - [Release notes](https://github.com/lewagon/wait-on-check-action/releases) - [Commits](https://github.com/lewagon/wait-on-check-action/compare/e106e5c43e8ca1edea6383a39a01c5ca495fd812...595dabb3acf442d47e29c9ec9ba44db0c6bdd18f) --- updated-dependencies: - dependency-name: lewagon/wait-on-check-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/dependabot_automerge.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependabot_automerge.yml b/.github/workflows/dependabot_automerge.yml index 6259199b113b64..5858507ae73763 100644 --- a/.github/workflows/dependabot_automerge.yml +++ b/.github/workflows/dependabot_automerge.yml @@ -15,7 +15,7 @@ jobs: id: metadata - name: Wait for status checks - uses: lewagon/wait-on-check-action@e106e5c43e8ca1edea6383a39a01c5ca495fd812 # v1.3.1 + uses: lewagon/wait-on-check-action@595dabb3acf442d47e29c9ec9ba44db0c6bdd18f # v1.3.3 with: repo-token: ${{ secrets.MATZBOT_GITHUB_TOKEN }} ref: ${{ github.event.pull_request.head.sha || github.sha }} From c26fdce9eca9659800fb3a77dc53f9ade444f639 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Jan 2024 06:04:05 +0000 Subject: [PATCH 053/640] Bump ruby/setup-ruby from 1.160.0 to 1.165.1 Bumps [ruby/setup-ruby](https://github.com/ruby/setup-ruby) from 1.160.0 to 1.165.1. - [Release notes](https://github.com/ruby/setup-ruby/releases) - [Commits](https://github.com/ruby/setup-ruby/compare/036ef458ddccddb148a2b9fb67e95a22fdbf728b...360dc864d5da99d54fcb8e9148c14a84b90d3e88) --- updated-dependencies: - dependency-name: ruby/setup-ruby dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/baseruby.yml | 2 +- .github/workflows/mingw.yml | 2 +- .github/workflows/rjit-bindgen.yml | 2 +- .github/workflows/spec_guards.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/baseruby.yml b/.github/workflows/baseruby.yml index e0ed5f26430355..5ead3fa03f4883 100644 --- a/.github/workflows/baseruby.yml +++ b/.github/workflows/baseruby.yml @@ -59,7 +59,7 @@ jobs: - ruby-3.3 steps: - - uses: ruby/setup-ruby@036ef458ddccddb148a2b9fb67e95a22fdbf728b # v1.160.0 + - uses: ruby/setup-ruby@360dc864d5da99d54fcb8e9148c14a84b90d3e88 # v1.165.1 with: ruby-version: ${{ matrix.ruby }} bundler: none diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml index df879f56b6b353..c7a550c7c79251 100644 --- a/.github/workflows/mingw.yml +++ b/.github/workflows/mingw.yml @@ -74,7 +74,7 @@ jobs: steps: - name: Set up Ruby & MSYS2 - uses: ruby/setup-ruby@036ef458ddccddb148a2b9fb67e95a22fdbf728b # v1.160.0 + uses: ruby/setup-ruby@360dc864d5da99d54fcb8e9148c14a84b90d3e88 # v1.165.1 with: ruby-version: ${{ matrix.base_ruby }} diff --git a/.github/workflows/rjit-bindgen.yml b/.github/workflows/rjit-bindgen.yml index bf3c752e7b55cf..74e9df608bd276 100644 --- a/.github/workflows/rjit-bindgen.yml +++ b/.github/workflows/rjit-bindgen.yml @@ -52,7 +52,7 @@ jobs: steps: - name: Set up Ruby - uses: ruby/setup-ruby@036ef458ddccddb148a2b9fb67e95a22fdbf728b # v1.160.0 + uses: ruby/setup-ruby@360dc864d5da99d54fcb8e9148c14a84b90d3e88 # v1.165.1 with: ruby-version: '3.1' diff --git a/.github/workflows/spec_guards.yml b/.github/workflows/spec_guards.yml index 0ca66e1453b4c0..f28c91d4af6dae 100644 --- a/.github/workflows/spec_guards.yml +++ b/.github/workflows/spec_guards.yml @@ -48,7 +48,7 @@ jobs: steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - uses: ruby/setup-ruby@036ef458ddccddb148a2b9fb67e95a22fdbf728b # v1.160.0 + - uses: ruby/setup-ruby@360dc864d5da99d54fcb8e9148c14a84b90d3e88 # v1.165.1 with: ruby-version: ${{ matrix.ruby }} bundler: none From 7558625be1d1f8160e7e138a773925b75a87f283 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 11 Jan 2024 14:54:03 +0900 Subject: [PATCH 054/640] [ruby/rdoc] Respect modeline to detect parser https://github.com/ruby/rdoc/commit/485468f06f --- lib/rdoc/parser.rb | 6 ++++-- test/rdoc/test_rdoc_parser.rb | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/rdoc/parser.rb b/lib/rdoc/parser.rb index 3bb6f5d1f274ff..425105effa2151 100644 --- a/lib/rdoc/parser.rb +++ b/lib/rdoc/parser.rb @@ -125,9 +125,11 @@ def self.can_parse_by_name file_name return parser if ext_name.empty? if parser == RDoc::Parser::Simple and ext_name !~ /txt|rdoc/ then - case check_modeline file_name + case mode = check_modeline(file_name) when nil, 'rdoc' then # continue - else return nil + else + RDoc::Parser.parsers.find { |_, p| return p if mode.casecmp?(p.name[/\w+\z/]) } + return nil end end diff --git a/test/rdoc/test_rdoc_parser.rb b/test/rdoc/test_rdoc_parser.rb index 7cc3c2d9262f76..a19986bd26ee8c 100644 --- a/test/rdoc/test_rdoc_parser.rb +++ b/test/rdoc/test_rdoc_parser.rb @@ -147,10 +147,23 @@ def test_can_parse_modeline end assert_equal RDoc::Parser::Simple, @RP.can_parse(readme_ext) + end + + def test_can_parse_modeline_c + readme_inc = File.join Dir.tmpdir, "README.inc.#{$$}" + + File.open readme_inc, 'w' do |io| + io.puts "/* README.inc - -*- c -*- created at: Mon Aug 7 16:45:54 JST 1995 */" + io.puts + io.puts "/* This document explains how to make extension libraries for Ruby. */" + end + + assert_equal RDoc::Parser::C, @RP.can_parse(readme_inc) ensure - File.unlink readme_ext + File.unlink readme_inc end + ## # Selenium hides a .jar file using a .txt extension. From 563f61102b8aabcd79f4f98d33f7f43b260f32dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Jan 2024 06:23:27 +0000 Subject: [PATCH 055/640] Bump actions/cache in /.github/actions/setup/directories Bumps [actions/cache](https://github.com/actions/cache) from 3.3.1 to 3.3.2. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8...704facf57e6136b1bc63b828d79edcd491f0ee84) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/actions/setup/directories/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/setup/directories/action.yml b/.github/actions/setup/directories/action.yml index 359e5c0d37ce38..c23dd01098202a 100644 --- a/.github/actions/setup/directories/action.yml +++ b/.github/actions/setup/directories/action.yml @@ -80,7 +80,7 @@ runs: with: path: ${{ inputs.srcdir }} - - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 + - uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 with: path: ${{ inputs.srcdir }}/.downloaded-cache key: downloaded-cache From 408828064373055a1cd0beb1bbe472451750b82b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Jan 2024 06:04:00 +0000 Subject: [PATCH 056/640] Bump actions/upload-artifact from 3.1.3 to 4.0.0 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3.1.3 to 4.0.0. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/a8a3f3ad30e3422c9c7b888a15615d19a852ae32...c7d193f32edcb7bfad88892161225aeda64e9392) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/wasm.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml index 1fad62a915a151..61c9458f169427 100644 --- a/.github/workflows/wasm.yml +++ b/.github/workflows/wasm.yml @@ -136,7 +136,7 @@ jobs: - run: tar cfz ../install.tar.gz -C ../install . - name: Upload artifacts - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 with: name: ruby-wasm-install path: ${{ github.workspace }}/install.tar.gz @@ -164,7 +164,7 @@ jobs: - name: Save Pull Request number if: ${{ github.event_name == 'pull_request' }} run: echo "${{ github.event.pull_request.number }}" >> ${{ github.workspace }}/github-pr-info.txt - - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 if: ${{ github.event_name == 'pull_request' }} with: name: github-pr-info From 60844ecf2e63a4c0ff1c248908497a7b6665a42a Mon Sep 17 00:00:00 2001 From: Yusuke Endoh Date: Thu, 11 Jan 2024 17:03:22 +0900 Subject: [PATCH 057/640] Prevent a warning: ambiguous first argument --- test/ruby/test_process.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb index edee62466518a4..7e317c08402312 100644 --- a/test/ruby/test_process.rb +++ b/test/ruby/test_process.rb @@ -2816,7 +2816,7 @@ def test_concurrent_group_and_pid_wait t1.join t2 = Thread.new do - Process.waitpid -1 + Process.waitpid(-1) rescue Errno::ECHILD nil end From 78cd5b36576a55429bd15f5cabacfd4e790c0076 Mon Sep 17 00:00:00 2001 From: Yusuke Endoh Date: Thu, 11 Jan 2024 17:04:13 +0900 Subject: [PATCH 058/640] Prevent syntax warnings in test/ruby/test_regexp.rb --- test/ruby/test_regexp.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb index 0d6ab4682d0631..7206e858d04b61 100644 --- a/test/ruby/test_regexp.rb +++ b/test/ruby/test_regexp.rb @@ -716,7 +716,7 @@ def test_match_no_match_no_matchdata h = {} ObjectSpace.count_objects(h) prev_matches = h[:T_MATCH] || 0 - md = /[A-Z]/.match('1') # no match + _md = /[A-Z]/.match('1') # no match ObjectSpace.count_objects(h) new_matches = h[:T_MATCH] || 0 assert_equal prev_matches, new_matches, "Bug [#20104]" @@ -2009,11 +2009,11 @@ def test_bug_20083 # [Bug #20083] end def test_bug_20098 # [Bug #20098] - assert /a((.|.)|bc){,4}z/.match? 'abcbcbcbcz' - assert /a(b+?c*){4,5}z/.match? 'abbbccbbbccbcbcz' - assert /a(b+?(.|.)){2,3}z/.match? 'abbbcbbbcbbbcz' - assert /a(b*?(.|.)[bc]){2,5}z/.match? 'abcbbbcbcccbcz' - assert /^(?:.+){2,4}?b|b/.match? "aaaabaa" + assert(/a((.|.)|bc){,4}z/.match? 'abcbcbcbcz') + assert(/a(b+?c*){4,5}z/.match? 'abbbccbbbccbcbcz') + assert(/a(b+?(.|.)){2,3}z/.match? 'abbbcbbbcbbbcz') + assert(/a(b*?(.|.)[bc]){2,5}z/.match? 'abcbbbcbcccbcz') + assert(/^(?:.+){2,4}?b|b/.match? "aaaabaa") end def test_linear_time_p From b10aa7757e8ef9d7625a7d8cfe962f3b4e8245dd Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 11 Jan 2024 17:36:51 +0900 Subject: [PATCH 059/640] Disable to add latest label when running with --no-dry-run option --- tool/gen-github-release.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tool/gen-github-release.rb b/tool/gen-github-release.rb index fe0b459cb374a6..600a01430da6df 100755 --- a/tool/gen-github-release.rb +++ b/tool/gen-github-release.rb @@ -58,7 +58,7 @@ if ARGV[2] == "--no-dry-run" name = ARGV[1].gsub(/v/, "").gsub(/_/, ".") - client.create_release("ruby/ruby", ARGV[1], name: name, body: note) + client.create_release("ruby/ruby", ARGV[1], name: name, body: note, make_latest: "false") puts "Created a release: https://github.com/ruby/ruby/releases/tag/#{ARGV[1]}" else puts note From d6741572ef2f6ebc753749ee19a10728d0d1cdc6 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 11 Jan 2024 17:39:43 +0900 Subject: [PATCH 060/640] [ruby/rdoc] Undo accidentally deleted lines https://github.com/ruby/rdoc/commit/4e14158255 --- test/rdoc/test_rdoc_parser.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/rdoc/test_rdoc_parser.rb b/test/rdoc/test_rdoc_parser.rb index a19986bd26ee8c..fa6443f3d3ad78 100644 --- a/test/rdoc/test_rdoc_parser.rb +++ b/test/rdoc/test_rdoc_parser.rb @@ -147,6 +147,8 @@ def test_can_parse_modeline end assert_equal RDoc::Parser::Simple, @RP.can_parse(readme_ext) + ensure + File.unlink readme_ext end def test_can_parse_modeline_c @@ -163,7 +165,6 @@ def test_can_parse_modeline_c File.unlink readme_inc end - ## # Selenium hides a .jar file using a .txt extension. From 7cc8d58cc9596d1472f51a3767f6d35c736041ac Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 11 Jan 2024 17:46:09 +0900 Subject: [PATCH 061/640] Remove duplicate function `nd_st_key_val` --- parse.y | 30 +----------------------------- 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/parse.y b/parse.y index 391cafffc7822c..8eef24ebba0aec 100644 --- a/parse.y +++ b/parse.y @@ -14985,34 +14985,6 @@ nd_st_key(struct parser_params *p, NODE *node) } } -static VALUE -nd_st_key_val(struct parser_params *p, NODE *node) -{ - switch (nd_type(node)) { - case NODE_LIT: - return RNODE_LIT(node)->nd_lit; - case NODE_STR: - return RNODE_STR(node)->nd_lit; - case NODE_INTEGER: - return rb_node_integer_literal_val(node); - case NODE_FLOAT: - return rb_node_float_literal_val(node); - case NODE_RATIONAL: - return rb_node_rational_literal_val(node); - case NODE_IMAGINARY: - return rb_node_imaginary_literal_val(node); - case NODE_SYM: - return rb_node_sym_string_val(node); - case NODE_LINE: - return rb_node_line_lineno_val(node); - case NODE_FILE: - return rb_node_file_path_val(node); - default: - rb_bug("unexpected node: %s", ruby_node_name(nd_type(node))); - UNREACHABLE_RETURN(0); - } -} - static void warn_duplicate_keys(struct parser_params *p, NODE *hash) { @@ -15035,7 +15007,7 @@ warn_duplicate_keys(struct parser_params *p, NODE *hash) st_delete(literal_keys, (key = (st_data_t)nd_st_key(p, head), &key), &data)) { rb_compile_warn(p->ruby_sourcefile, nd_line((NODE *)data), "key %+"PRIsVALUE" is duplicated and overwritten on line %d", - nd_st_key_val(p, head), nd_line(head)); + nd_st_key(p, head), nd_line(head)); } st_insert(literal_keys, (st_data_t)key, (st_data_t)hash); hash = next; From 0480c073449e5116847c9e975ac794f28daef0ac Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 11 Jan 2024 18:28:53 +0900 Subject: [PATCH 062/640] Remove printf z modifier check [ci skip] VC2013 is no longer supported. --- .github/workflows/check_misc.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/workflows/check_misc.yml b/.github/workflows/check_misc.yml index 7f2d3c346ca496..ce4397b35aac02 100644 --- a/.github/workflows/check_misc.yml +++ b/.github/workflows/check_misc.yml @@ -52,14 +52,6 @@ jobs: exit $fail working-directory: include - # This should be able to be removed once old platforms are dropped. - - id: c99-check - name: Check for C99 features which may not be supported - run: | - # VC2013: z modifier for size_t is not supported. - grep -r -n --include='*.[chyS]' '%[0-9]*z[idu]' -- . && exit 1 || : - continue-on-error: true # Just show in the annotations - - id: gems run: true if: ${{ github.ref == 'refs/heads/master' }} From 3d3bc029c5b48ddfbb7c5f7b062cb364894c64af Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 11 Jan 2024 18:46:51 +0900 Subject: [PATCH 063/640] Reject encodings determined at runtime as source code encodings The encodings determined at runtime are affected by the runtime environment, such as the OS and locale, while the file contents are not. --- parse.y | 11 ++++++++++- test/ruby/test_parse.rb | 28 ++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/parse.y b/parse.y index 8eef24ebba0aec..08bd3fb97d4b84 100644 --- a/parse.y +++ b/parse.y @@ -9477,11 +9477,20 @@ parser_encode_length(struct parser_params *p, const char *name, long len) static void parser_set_encode(struct parser_params *p, const char *name) { - int idx = rb_enc_find_index(name); rb_encoding *enc; VALUE excargs[3]; + const char *wrong = 0; + switch (*name) { + case 'e': case 'E': wrong = "external"; break; + case 'i': case 'I': wrong = "internal"; break; + case 'f': case 'F': wrong = "filesystem"; break; + case 'l': case 'L': wrong = "locale"; break; + } + if (wrong && STRCASECMP(name, wrong) == 0) goto unknown; + int idx = rb_enc_find_index(name); if (idx < 0) { + unknown: excargs[1] = rb_sprintf("unknown encoding name: %s", name); error: excargs[0] = rb_eArgError; diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb index c2f02ff80943aa..858c623bcc964c 100644 --- a/test/ruby/test_parse.rb +++ b/test/ruby/test_parse.rb @@ -767,6 +767,34 @@ def test_magic_comment END end assert_equal(__ENCODING__, x) + + assert_raise(ArgumentError) do + EnvUtil.with_default_external(Encoding::US_ASCII) {eval <<-END, nil, __FILE__, __LINE__+1} +# coding = external +x = __ENCODING__ + END + end + + assert_raise(ArgumentError) do + EnvUtil.with_default_internal(Encoding::US_ASCII) {eval <<-END, nil, __FILE__, __LINE__+1} +# coding = internal +x = __ENCODING__ + END + end + + assert_raise(ArgumentError) do + eval <<-END, nil, __FILE__, __LINE__+1 +# coding = filesystem +x = __ENCODING__ + END + end + + assert_raise(ArgumentError) do + eval <<-END, nil, __FILE__, __LINE__+1 +# coding = locale +x = __ENCODING__ + END + end end def test_utf8_bom From 80f1c1e2937939d95374aee7215a68cef9c7175a Mon Sep 17 00:00:00 2001 From: Hiroya Fujinami Date: Thu, 11 Jan 2024 22:38:44 +0900 Subject: [PATCH 064/640] Remove a unused variable in i_print_name_entry (#9468) A warning for this is shown when `ONIG_DEBUG_COMPILE` is enabled. --- regparse.c | 1 - 1 file changed, 1 deletion(-) diff --git a/regparse.c b/regparse.c index 57ecd78dee785b..004e16b6d54a32 100644 --- a/regparse.c +++ b/regparse.c @@ -478,7 +478,6 @@ typedef st_data_t HashDataType; /* 1.6 st.h doesn't define st_data_t type */ static int i_print_name_entry(HashDataType key_, HashDataType e_, HashDataType arg_) { - UChar* key = (UChar *)key_; NameEntry* e = (NameEntry *)e_; void* arg = (void *)arg_; int i; From 3b9cc22536f2a72ece034881aaf568767e8e1e86 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Thu, 30 Nov 2023 17:03:59 +0100 Subject: [PATCH 065/640] [ruby/pp] Use a proper feature check to check if Data is defined https://github.com/ruby/pp/commit/ed602b9f2b --- lib/pp.rb | 2 +- test/test_pp.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pp.rb b/lib/pp.rb index 1708dee05e58af..7c4ba0e672224e 100644 --- a/lib/pp.rb +++ b/lib/pp.rb @@ -438,7 +438,7 @@ def pretty_print(q) # :nodoc: def pretty_print_cycle(q) # :nodoc: q.text sprintf("#", PP.mcall(self, Kernel, :class).name) end -end if "3.2" <= RUBY_VERSION +end if defined?(Data.define) class Range # :nodoc: def pretty_print(q) # :nodoc: diff --git a/test/test_pp.rb b/test/test_pp.rb index f6c2f65df25bcd..d7cca82a00e203 100644 --- a/test/test_pp.rb +++ b/test/test_pp.rb @@ -143,7 +143,7 @@ def test_struct assert_equal("#{a.inspect}\n", PP.pp(a, ''.dup)) end - if "3.2" <= RUBY_VERSION + if defined?(Data.define) D = Data.define(:aaa, :bbb) def test_data a = D.new("aaa", "bbb") From 62382a434561b6fe56d479b8800cf6ccf017463c Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Thu, 30 Nov 2023 17:04:39 +0100 Subject: [PATCH 066/640] [ruby/pp] Use .class.members for pretty printing Data * Data#members might not be defined, instead it might be defined on Data subclasses or a module included there. This is notably the case on TruffleRuby which defines it there for optimization purposes. In fact the mere presence of Data#members implies a megamorphic call inside, so it seems best to avoid relying on its existence. https://github.com/ruby/pp/commit/6a97d36fbb --- lib/pp.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pp.rb b/lib/pp.rb index 7c4ba0e672224e..5e5fd06cae05ba 100644 --- a/lib/pp.rb +++ b/lib/pp.rb @@ -423,7 +423,7 @@ def pretty_print_cycle(q) # :nodoc: class Data # :nodoc: def pretty_print(q) # :nodoc: q.group(1, sprintf("#') { - q.seplist(PP.mcall(self, Data, :members), lambda { q.text "," }) {|member| + q.seplist(PP.mcall(self, Kernel, :class).members, lambda { q.text "," }) {|member| q.breakable q.text member.to_s q.text '=' From 1ed3b6037566cef3d56e882eb0fcf1b14553f540 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Thu, 30 Nov 2023 17:10:40 +0100 Subject: [PATCH 067/640] [ruby/pp] Fix pretty printing a Data subclass instance when the subclass is anonymous * It would be "#" (double space) instead of "#" (like #inspect). https://github.com/ruby/pp/commit/bed72bfcb8 --- lib/pp.rb | 4 +++- test/test_pp.rb | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/pp.rb b/lib/pp.rb index 5e5fd06cae05ba..fb7aa7b41c6fd4 100644 --- a/lib/pp.rb +++ b/lib/pp.rb @@ -422,7 +422,9 @@ def pretty_print_cycle(q) # :nodoc: class Data # :nodoc: def pretty_print(q) # :nodoc: - q.group(1, sprintf("#') { + class_name = PP.mcall(self, Kernel, :class).name + class_name = " #{class_name}" if class_name + q.group(1, "#') { q.seplist(PP.mcall(self, Kernel, :class).members, lambda { q.text "," }) {|member| q.breakable q.text member.to_s diff --git a/test/test_pp.rb b/test/test_pp.rb index d7cca82a00e203..72a4f127f3f3aa 100644 --- a/test/test_pp.rb +++ b/test/test_pp.rb @@ -149,6 +149,9 @@ def test_data a = D.new("aaa", "bbb") assert_equal("#\n", PP.pp(a, ''.dup, 20)) assert_equal("#{a.inspect}\n", PP.pp(a, ''.dup)) + + b = Data.define(:a).new(42) + assert_equal("#{b.inspect}\n", PP.pp(b, ''.dup)) end end From 4e0c2f05efc9415b52b50ee65401c5b511d269e7 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Thu, 30 Nov 2023 17:19:30 +0100 Subject: [PATCH 068/640] [ruby/pp] Add TruffleRuby in CI * Only 2 cyclic tests are failing, with the ... in a slightly different place in the output. https://github.com/ruby/pp/commit/6e5c7d741e --- test/test_pp.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_pp.rb b/test/test_pp.rb index 72a4f127f3f3aa..6da2b808b9844f 100644 --- a/test/test_pp.rb +++ b/test/test_pp.rb @@ -140,7 +140,7 @@ def test_struct a = S.new(1,2) a.b = a assert_equal("#>\n", PP.pp(a, ''.dup)) - assert_equal("#{a.inspect}\n", PP.pp(a, ''.dup)) + assert_equal("#{a.inspect}\n", PP.pp(a, ''.dup)) unless RUBY_ENGINE == "truffleruby" end if defined?(Data.define) @@ -167,7 +167,7 @@ def test_anonymous end def test_withinspect - omit if RUBY_ENGINE == "jruby" + omit if RUBY_ENGINE == "jruby" or RUBY_ENGINE == "truffleruby" a = [] a << HasInspect.new(a) assert_equal("[]\n", PP.pp(a, ''.dup)) From 057df4379f856a868f588cdc769f397f5739983d Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 9 Jan 2024 13:17:17 -0500 Subject: [PATCH 069/640] Free environ when RUBY_FREE_AT_EXIT The environ is malloc'd, so it gets reported as a memory leak. This commit adds ruby_free_proctitle which frees it during shutdown when RUBY_FREE_AT_EXIT is set. STACK OF 1 INSTANCE OF 'ROOT LEAK: ': 5 dyld 0x18b7090e0 start + 2360 4 ruby 0x10000e3a8 main + 100 main.c:58 3 ruby 0x1000b4dfc ruby_options + 180 eval.c:121 2 ruby 0x1001c5f70 ruby_process_options + 200 ruby.c:3014 1 ruby 0x10035c9fc ruby_init_setproctitle + 76 setproctitle.c:105 0 libsystem_malloc.dylib 0x18b8c7b78 _malloc_zone_calloc_instrumented_or_legacy + 100 --- common.mk | 1 + internal/missing.h | 1 + missing/setproctitle.c | 42 ++++++++++++++++++++++++++++++++++++++---- vm.c | 5 +++++ 4 files changed, 45 insertions(+), 4 deletions(-) diff --git a/common.mk b/common.mk index c650c6ab7fe87d..171c7dfd30cc6c 100644 --- a/common.mk +++ b/common.mk @@ -19320,6 +19320,7 @@ vm.$(OBJEXT): $(top_srcdir)/internal/gc.h vm.$(OBJEXT): $(top_srcdir)/internal/hash.h vm.$(OBJEXT): $(top_srcdir)/internal/imemo.h vm.$(OBJEXT): $(top_srcdir)/internal/inits.h +vm.$(OBJEXT): $(top_srcdir)/internal/missing.h vm.$(OBJEXT): $(top_srcdir)/internal/numeric.h vm.$(OBJEXT): $(top_srcdir)/internal/object.h vm.$(OBJEXT): $(top_srcdir)/internal/parse.h diff --git a/internal/missing.h b/internal/missing.h index c0992a151a580c..6ca508c8f9b543 100644 --- a/internal/missing.h +++ b/internal/missing.h @@ -13,6 +13,7 @@ /* missing/setproctitle.c */ #ifndef HAVE_SETPROCTITLE extern void ruby_init_setproctitle(int argc, char *argv[]); +extern void ruby_free_proctitle(void); #endif #endif /* INTERNAL_MISSING_H */ diff --git a/missing/setproctitle.c b/missing/setproctitle.c index 6a8532381803a0..d718123802f885 100644 --- a/missing/setproctitle.c +++ b/missing/setproctitle.c @@ -80,10 +80,20 @@ static char **argv1_addr = NULL; #endif /* HAVE_SETPROCTITLE */ +#if defined(SPT_TYPE) && SPT_TYPE == SPT_REUSEARGV +# define ALLOCATE_ENVIRON 1 +#else +# define ALLOCATE_ENVIRON 0 +#endif + +#if ALLOCATE_ENVIRON +static char **orig_environ = NULL; +#endif + void compat_init_setproctitle(int argc, char *argv[]) { -#if defined(SPT_TYPE) && SPT_TYPE == SPT_REUSEARGV +#if ALLOCATE_ENVIRON extern char **environ; char *lastargv = NULL; char *lastenvp = NULL; @@ -100,9 +110,10 @@ compat_init_setproctitle(int argc, char *argv[]) return; /* Fail if we can't allocate room for the new environment */ - for (i = 0; envp[i] != NULL; i++) - ; - if ((environ = calloc(i + 1, sizeof(*environ))) == NULL) { + for (i = 0; envp[i] != NULL; i++); + + orig_environ = environ = xcalloc(i + 1, sizeof(*environ)); + if (environ == NULL) { environ = envp; /* put it back */ return; } @@ -134,6 +145,29 @@ compat_init_setproctitle(int argc, char *argv[]) #endif /* SPT_REUSEARGV */ } +void +ruby_free_proctitle(void) +{ +#if ALLOCATE_ENVIRON + extern char **environ; + + if (!orig_environ) return; /* environ is allocated by OS */ + + for (int i = 0; environ[i] != NULL; i++) { + xfree(environ[i]); + } + + /* ruby_setenv could allocate a new environ, so we need to free both environ + * orig_environ in that case. */ + if (environ != orig_environ) { + xfree(orig_environ); + orig_environ = NULL; + } + + xfree(environ); +#endif +} + #ifndef HAVE_SETPROCTITLE void diff --git a/vm.c b/vm.c index 257c517b43cf58..37d631116aa4dc 100644 --- a/vm.c +++ b/vm.c @@ -20,6 +20,7 @@ #include "internal/eval.h" #include "internal/gc.h" #include "internal/inits.h" +#include "internal/missing.h" #include "internal/object.h" #include "internal/proc.h" #include "internal/re.h" @@ -3034,6 +3035,10 @@ ruby_vm_destruct(rb_vm_t *vm) xfree(th->nt); th->nt = NULL; } + +#ifndef HAVE_SETPROCTITLE + ruby_free_proctitle(); +#endif } else { if (th) { From 6ff9f1aa51bf53024a7545844ff0f3f53111403f Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 11 Jan 2024 12:27:06 -0500 Subject: [PATCH 070/640] [ruby/prism] Provide ability to format errors https://github.com/ruby/prism/commit/27985b0e7e --- prism/extension.c | 31 +++++ prism/prism.c | 290 +++++++++++++++++++++++++++++++++++++++++ prism/prism.h | 9 ++ prism/util/pm_buffer.c | 11 ++ prism/util/pm_buffer.h | 9 ++ 5 files changed, 350 insertions(+) diff --git a/prism/extension.c b/prism/extension.c index 84c8eacd94ae02..28bea39c7f03d7 100644 --- a/prism/extension.c +++ b/prism/extension.c @@ -984,6 +984,36 @@ inspect_node(VALUE self, VALUE source) { return string; } +/** + * call-seq: + * Debug::format_errors(source) -> String + * + * Format the errors that are found when parsing the given source string. + */ +static VALUE +format_errors(VALUE self, VALUE source) { + pm_string_t input; + input_load_string(&input, source); + + pm_parser_t parser; + pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), NULL); + + pm_node_t *node = pm_parse(&parser); + pm_buffer_t buffer = { 0 }; + + pm_parser_errors_format(&parser, &buffer, true); + + rb_encoding *encoding = rb_enc_find(parser.encoding->name); + VALUE result = rb_enc_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer), encoding); + + pm_buffer_free(&buffer); + pm_node_destroy(&parser, node); + pm_parser_free(&parser); + pm_string_free(&input); + + return result; +} + /******************************************************************************/ /* Initialization of the extension */ /******************************************************************************/ @@ -1062,6 +1092,7 @@ Init_prism(void) { rb_define_singleton_method(rb_cPrismDebug, "memsize", memsize, 1); rb_define_singleton_method(rb_cPrismDebug, "profile_file", profile_file, 1); rb_define_singleton_method(rb_cPrismDebug, "inspect_node", inspect_node, 1); + rb_define_singleton_method(rb_cPrismDebug, "format_errors", format_errors, 1); // Next, initialize the other APIs. Init_prism_api_node(); diff --git a/prism/prism.c b/prism/prism.c index 8274398d074f40..c169bcadd89343 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -17659,3 +17659,293 @@ pm_serialize_parse_comments(pm_buffer_t *buffer, const uint8_t *source, size_t s #undef PM_LOCATION_NODE_VALUE #undef PM_LOCATION_NULL_VALUE #undef PM_LOCATION_TOKEN_VALUE + +/** An error that is going to be formatted into the output. */ +typedef struct { + /** A pointer to the diagnostic that was generated during parsing. */ + pm_diagnostic_t *error; + + /** The start line of the diagnostic message. */ + size_t line; + + /** The column start of the diagnostic message. */ + size_t column_start; + + /** The column end of the diagnostic message. */ + size_t column_end; +} pm_error_t; + +/** The format that will be used to format the errors into the output. */ +typedef struct { + /** The prefix that will be used for line numbers. */ + const char *number_prefix; + + /** The prefix that will be used for blank lines. */ + const char *blank_prefix; + + /** The divider that will be used between sections of source code. */ + const char *divider; + + /** The length of the blank prefix. */ + size_t blank_prefix_length; + + /** The length of the divider. */ + size_t divider_length; +} pm_error_format_t; + +#define PM_COLOR_GRAY "\033[38;5;102m" +#define PM_COLOR_RED "\033[1;31m" +#define PM_COLOR_RESET "\033[0m" + +static inline pm_error_t * +pm_parser_errors_format_sort(const pm_list_t *error_list, const pm_newline_list_t *newline_list) { + pm_error_t *errors = calloc(error_list->size, sizeof(pm_error_t)); + + for (pm_diagnostic_t *error = (pm_diagnostic_t *) error_list->head; error != NULL; error = (pm_diagnostic_t *) error->node.next) { + pm_line_column_t start = pm_newline_list_line_column(newline_list, error->location.start); + pm_line_column_t end = pm_newline_list_line_column(newline_list, error->location.end); + + // We're going to insert this error into the array in sorted order. We + // do this by finding the first error that has a line number greater + // than the current error and then inserting the current error before + // that one. + size_t index = 0; + while ( + (index < error_list->size) && + (errors[index].error != NULL) && + ( + (errors[index].line < start.line) || + (errors[index].line == start.line && errors[index].column_start < start.column) + ) + ) index++; + + // Now we're going to shift all of the errors after this one down one + // index to make room for the new error. + memcpy(&errors[index + 1], &errors[index], sizeof(pm_error_t) * (error_list->size - index - 1)); + + // Finally, we'll insert the error into the array. + size_t column_end; + if (start.line == end.line) { + column_end = end.column; + } else { + column_end = newline_list->offsets[start.line + 1] - newline_list->offsets[start.line] - 1; + } + + // Ensure we have at least one column of error. + if (start.column == column_end) column_end++; + + errors[index] = (pm_error_t) { + .error = error, + .line = start.line, + .column_start = start.column, + .column_end = column_end + }; + } + + return errors; +} + +static inline void +pm_parser_errors_format_line(const pm_parser_t *parser, const pm_newline_list_t *newline_list, const char *number_prefix, size_t line, pm_buffer_t *buffer) { + const uint8_t *start = &parser->start[newline_list->offsets[line]]; + const uint8_t *end; + + if (line + 1 > newline_list->size) { + end = parser->end; + } else { + end = &parser->start[newline_list->offsets[line + 1]]; + } + + pm_buffer_append_format(buffer, number_prefix, line + 1); + pm_buffer_append_string(buffer, (const char *) start, (size_t) (end - start)); +} + +/** + * Format the errors on the parser into the given buffer. + */ +PRISM_EXPORTED_FUNCTION void +pm_parser_errors_format(const pm_parser_t *parser, pm_buffer_t *buffer, bool colorize) { + const pm_list_t *error_list = &parser->error_list; + assert(error_list->size != 0); + + // First, we're going to sort all of the errors by line number using an + // insertion sort into a newly allocated array. + const pm_newline_list_t *newline_list = &parser->newline_list; + pm_error_t *errors = pm_parser_errors_format_sort(error_list, newline_list); + + // Now we're going to determine how we're going to format line numbers and + // blank lines based on the maximum number of digits in the line numbers + // that are going to be displayed. + pm_error_format_t error_format; + size_t max_line_number = errors[error_list->size - 1].line + 1; + + if (max_line_number < 10) { + if (colorize) { + error_format = (pm_error_format_t) { + .number_prefix = PM_COLOR_GRAY "%1zu | " PM_COLOR_RESET, + .blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET, + .divider = PM_COLOR_GRAY " ~~~~~" PM_COLOR_RESET "\n" + }; + } else { + error_format = (pm_error_format_t) { + .number_prefix = "%1zu | ", + .blank_prefix = " | ", + .divider = " ~~~~~\n" + }; + } + } else if (max_line_number < 100) { + if (colorize) { + error_format = (pm_error_format_t) { + .number_prefix = PM_COLOR_GRAY "%2zu | " PM_COLOR_RESET, + .blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET, + .divider = PM_COLOR_GRAY " ~~~~~~" PM_COLOR_RESET "\n" + }; + } else { + error_format = (pm_error_format_t) { + .number_prefix = "%2zu | ", + .blank_prefix = " | ", + .divider = " ~~~~~~\n" + }; + } + } else if (max_line_number < 1000) { + if (colorize) { + error_format = (pm_error_format_t) { + .number_prefix = PM_COLOR_GRAY "%3zu | " PM_COLOR_RESET, + .blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET, + .divider = PM_COLOR_GRAY " ~~~~~~~" PM_COLOR_RESET "\n" + }; + } else { + error_format = (pm_error_format_t) { + .number_prefix = "%3zu | ", + .blank_prefix = " | ", + .divider = " ~~~~~~~\n" + }; + } + } else if (max_line_number < 10000) { + if (colorize) { + error_format = (pm_error_format_t) { + .number_prefix = PM_COLOR_GRAY "%4zu | " PM_COLOR_RESET, + .blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET, + .divider = PM_COLOR_GRAY " ~~~~~~~~" PM_COLOR_RESET "\n" + }; + } else { + error_format = (pm_error_format_t) { + .number_prefix = "%4zu | ", + .blank_prefix = " | ", + .divider = " ~~~~~~~~\n" + }; + } + } else { + if (colorize) { + error_format = (pm_error_format_t) { + .number_prefix = PM_COLOR_GRAY "%5zu | " PM_COLOR_RESET, + .blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET, + .divider = PM_COLOR_GRAY " ~~~~~~~~" PM_COLOR_RESET "\n" + }; + } else { + error_format = (pm_error_format_t) { + .number_prefix = "%5zu | ", + .blank_prefix = " | ", + .divider = " ~~~~~~~~\n" + }; + } + } + + error_format.blank_prefix_length = strlen(error_format.blank_prefix); + error_format.divider_length = strlen(error_format.divider); + + // Now we're going to iterate through every error in our error list and + // display it. While we're iterating, we will display some padding lines of + // the source before the error to give some context. We'll be careful not to + // display the same line twice in case the errors are close enough in the + // source. + size_t last_line = (size_t) -1; + const pm_encoding_t *encoding = parser->encoding; + + for (size_t index = 0; index < error_list->size; index++) { + pm_error_t *error = &errors[index]; + + // Here we determine how many lines of padding of the source to display, + // based on the difference from the last line that was displayed. + if (error->line - last_line > 1) { + if (error->line - last_line > 2) { + if ((index != 0) && (error->line - last_line > 3)) { + pm_buffer_append_string(buffer, error_format.divider, error_format.divider_length); + } + + pm_buffer_append_string(buffer, " ", 2); + pm_parser_errors_format_line(parser, newline_list, error_format.number_prefix, error->line - 2, buffer); + } + + pm_buffer_append_string(buffer, " ", 2); + pm_parser_errors_format_line(parser, newline_list, error_format.number_prefix, error->line - 1, buffer); + } + + // If this is the first error or we're on a new line, then we'll display + // the line that has the error in it. + if ((index == 0) || (error->line != last_line)) { + if (colorize) { + pm_buffer_append_string(buffer, PM_COLOR_RED "> " PM_COLOR_RESET, 13); + } else { + pm_buffer_append_string(buffer, "> ", 2); + } + pm_parser_errors_format_line(parser, newline_list, error_format.number_prefix, error->line, buffer); + } + + // Now we'll display the actual error message. We'll do this by first + // putting the prefix to the line, then a bunch of blank spaces + // depending on the column, then as many carets as we need to display + // the width of the error, then the error message itself. + // + // Note that this doesn't take into account the width of the actual + // character when displayed in the terminal. For some east-asian + // languages or emoji, this means it can be thrown off pretty badly. We + // will need to solve this eventually. + pm_buffer_append_string(buffer, " ", 2); + pm_buffer_append_string(buffer, error_format.blank_prefix, error_format.blank_prefix_length); + + size_t column = 0; + const uint8_t *start = &parser->start[newline_list->offsets[error->line]]; + + while (column < error->column_end) { + if (column < error->column_start) { + pm_buffer_append_byte(buffer, ' '); + } else if (colorize) { + pm_buffer_append_string(buffer, PM_COLOR_RED "^" PM_COLOR_RESET, 12); + } else { + pm_buffer_append_byte(buffer, '^'); + } + + size_t char_width = encoding->char_width(start + column, parser->end - (start + column)); + column += (char_width == 0 ? 1 : char_width); + } + + pm_buffer_append_byte(buffer, ' '); + + const char *message = error->error->message; + pm_buffer_append_string(buffer, message, strlen(message)); + pm_buffer_append_byte(buffer, '\n'); + + // Here we determine how many lines of padding to display after the + // error, depending on where the next error is in source. + last_line = error->line; + size_t next_line = (index == error_list->size - 1) ? newline_list->size - 1 : errors[index + 1].line; + + if (next_line - last_line > 1) { + pm_buffer_append_string(buffer, " ", 2); + pm_parser_errors_format_line(parser, newline_list, error_format.number_prefix, ++last_line, buffer); + } + + if (next_line - last_line > 1) { + pm_buffer_append_string(buffer, " ", 2); + pm_parser_errors_format_line(parser, newline_list, error_format.number_prefix, ++last_line, buffer); + } + } + + // Finally, we'll free the array of errors that we allocated. + free(errors); +} + +#undef PM_COLOR_GRAY +#undef PM_COLOR_RED +#undef PM_COLOR_RESET diff --git a/prism/prism.h b/prism/prism.h index f4a248274fcdf5..45bfff7a11e130 100644 --- a/prism/prism.h +++ b/prism/prism.h @@ -170,6 +170,15 @@ PRISM_EXPORTED_FUNCTION bool pm_parse_success_p(const uint8_t *source, size_t si */ PRISM_EXPORTED_FUNCTION const char * pm_token_type_to_str(pm_token_type_t token_type); +/** + * Format the errors on the parser into the given buffer. + * + * @param parser The parser to format the errors for. + * @param buffer The buffer to format the errors into. + * @param colorize Whether or not to colorize the errors with ANSI escape sequences. + */ +PRISM_EXPORTED_FUNCTION void pm_parser_errors_format(const pm_parser_t *parser, pm_buffer_t *buffer, bool colorize); + /** * @mainpage * diff --git a/prism/util/pm_buffer.c b/prism/util/pm_buffer.c index 307b55d030b9ce..0ae9445428815f 100644 --- a/prism/util/pm_buffer.c +++ b/prism/util/pm_buffer.c @@ -160,6 +160,17 @@ pm_buffer_append_varsint(pm_buffer_t *buffer, int32_t value) { pm_buffer_append_varuint(buffer, unsigned_int); } +/** + * Prepend the given string to the buffer. + */ +void +pm_buffer_prepend_string(pm_buffer_t *buffer, const char *value, size_t length) { + size_t cursor = buffer->length; + pm_buffer_append_length(buffer, length); + memmove(buffer->value + length, buffer->value, cursor); + memcpy(buffer->value, value, length); +} + /** * Concatenate one buffer onto another. */ diff --git a/prism/util/pm_buffer.h b/prism/util/pm_buffer.h index ec11d05e9bd42b..f0cca84af579c0 100644 --- a/prism/util/pm_buffer.h +++ b/prism/util/pm_buffer.h @@ -128,6 +128,15 @@ void pm_buffer_append_varuint(pm_buffer_t *buffer, uint32_t value); */ void pm_buffer_append_varsint(pm_buffer_t *buffer, int32_t value); +/** + * Prepend the given string to the buffer. + * + * @param buffer The buffer to prepend to. + * @param value The string to prepend. + * @param length The length of the string to prepend. + */ +void pm_buffer_prepend_string(pm_buffer_t *buffer, const char *value, size_t length); + /** * Concatenate one buffer onto another. * From 242dc537f93a0e11d91e729823cf8df2caec6abd Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 11 Jan 2024 14:14:19 -0500 Subject: [PATCH 071/640] [ruby/prism] Exclude encodings that are dynamic https://github.com/ruby/prism/commit/6749146c0e --- prism/encoding.c | 7 ------- test/prism/encoding_test.rb | 4 +--- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/prism/encoding.c b/prism/encoding.c index 2c6d7c97772cd5..2210d7141128b6 100644 --- a/prism/encoding.c +++ b/prism/encoding.c @@ -5022,10 +5022,6 @@ pm_encoding_find(const uint8_t *start, const uint8_t *end) { ENCODING2("EUC-CN", "eucCN", PM_ENCODING_GB2312); ENCODING2("EUC-TW", "eucTW", PM_ENCODING_EUC_TW); ENCODING1("Emacs-Mule", PM_ENCODING_EMACS_MULE); - ENCODING1("external", PM_ENCODING_UTF_8); - break; - case 'F': case 'f': - ENCODING1("filesystem", PM_ENCODING_UTF_8); break; case 'G': case 'g': ENCODING1("GBK", PM_ENCODING_GBK); @@ -5071,9 +5067,6 @@ pm_encoding_find(const uint8_t *start, const uint8_t *end) { ENCODING1("KOI8-R", PM_ENCODING_KOI8_R); ENCODING1("KOI8-U", PM_ENCODING_KOI8_U); break; - case 'L': case 'l': - ENCODING1("locale", PM_ENCODING_UTF_8); - break; case 'M': case 'm': ENCODING1("macCentEuro", PM_ENCODING_MAC_CENT_EURO); ENCODING1("macCroatian", PM_ENCODING_MAC_CROATIAN); diff --git a/test/prism/encoding_test.rb b/test/prism/encoding_test.rb index e4678c6f82b831..e755cdaba2d63c 100644 --- a/test/prism/encoding_test.rb +++ b/test/prism/encoding_test.rb @@ -137,9 +137,7 @@ class EncodingTest < TestCase # These test that we're correctly parsing codepoints for each alias of each # encoding that prism supports. encodings.each do |encoding, range| - encoding.names.each do |name| - next if name == "locale" - + (encoding.names - %w[external internal filesystem locale]).each do |name| define_method(:"test_encoding_#{name}") do assert_encoding(encoding, name, range) end From 72be7860170d2ccec7713a2b0ef43da133799d71 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 11 Jan 2024 14:19:41 -0500 Subject: [PATCH 072/640] [ruby/prism] Allow fsl comment to set to false https://github.com/ruby/prism/commit/b4db7bb703 --- prism/prism.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/prism/prism.c b/prism/prism.c index c169bcadd89343..96725b1ee048f4 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -6361,8 +6361,10 @@ parser_lex_magic_comment_encoding(pm_parser_t *parser) { */ static void parser_lex_magic_comment_frozen_string_literal_value(pm_parser_t *parser, const uint8_t *start, const uint8_t *end) { - if (start + 4 <= end && pm_strncasecmp(start, (const uint8_t *) "true", 4) == 0) { + if ((start + 4 <= end) && pm_strncasecmp(start, (const uint8_t *) "true", 4) == 0) { parser->frozen_string_literal = true; + } else if ((start + 5 <= end) && pm_strncasecmp(start, (const uint8_t *) "false", 5) == 0) { + parser->frozen_string_literal = false; } } From f2149dc094a92bd1aa29622f9585247d491f7a08 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 10 Jan 2024 16:27:00 -0800 Subject: [PATCH 073/640] [PRISM] Support repeated required parameter names. Fixes: https://github.com/ruby/prism/issues/2062 This patch only fixes positional parameters, we still need to fix the other cases spelled out in test/prism/fixtures/repeat_parameters.txt --- prism_compile.c | 17 +++++------------ test/ruby/test_compile_prism.rb | 4 ++++ 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index ed5f1367ed1f4c..9594be70659592 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -5582,7 +5582,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } if (requireds_list) { - int number_of_anonymous_locals = 0; for (size_t i = 0; i < requireds_list->size; i++) { // For each MultiTargetNode, we're going to have one // additional anonymous local not represented in the locals table @@ -5592,19 +5591,11 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, table_size++; } else if (PM_NODE_TYPE_P(required, PM_REQUIRED_PARAMETER_NODE)) { - if (pm_constant_id_lookup(scope_node, ((pm_required_parameter_node_t *)required)->name) == rb_intern("_")) { - number_of_anonymous_locals++; + if (PM_NODE_FLAG_P(required, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + table_size++; } } } - - // For each anonymous local we also want to increase the size - // of the locals table. Prism's locals table accounts for all - // anonymous locals as 1, so we need to increase the table size - // by the number of anonymous locals - 1 - if (number_of_anonymous_locals > 1) { - table_size += (number_of_anonymous_locals - 1); - } } if (posts_list) { @@ -5686,7 +5677,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, case PM_REQUIRED_PARAMETER_NODE: { pm_required_parameter_node_t * param = (pm_required_parameter_node_t *)required; - pm_insert_local_index(param->name, local_index, index_lookup_table, local_table_for_iseq, scope_node); + if (!PM_NODE_FLAG_P(required, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + pm_insert_local_index(param->name, local_index, index_lookup_table, local_table_for_iseq, scope_node); + } break; } default: { diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 99f932a238bd22..835b3b819b8c0b 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1299,6 +1299,10 @@ def self.prism_test_def_node(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, CODE end + def test_repeated_method_params + assert_prism_eval("def self.foo(_a, _a); _a; end; foo(1, 2)") + end + def test_method_parameters assert_prism_eval(<<-CODE) def self.prism_test_method_parameters(a, b=1, *c, d:, e: 2, **f, &g) From 45dd8edf82d2648fed51b0e65f6fc1cf4473038d Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Thu, 11 Jan 2024 12:27:50 -0500 Subject: [PATCH 074/640] [PRISM] Fix splat inside of aset Fixes ruby/prism#2146. --- prism_compile.c | 10 +++++++++- test/ruby/test_compile_prism.rb | 7 +++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/prism_compile.c b/prism_compile.c index 9594be70659592..cbae85b9f40cc5 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2645,9 +2645,17 @@ pm_compile_call(rb_iseq_t *iseq, const pm_call_node_t *call_node, LINK_ANCHOR *c } if (pm_node->flags & PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE) { - if (!popped) { + if (flags & VM_CALL_ARGS_SPLAT) { + ADD_INSN(ret, &dummy_line_node, dup); + ADD_INSN1(ret, &dummy_line_node, putobject, INT2FIX(-1)); + ADD_SEND_WITH_FLAG(ret, &dummy_line_node, idAREF, INT2FIX(1), INT2FIX(0)); + ADD_INSN1(ret, &dummy_line_node, setn, INT2FIX(orig_argc + 2)); + ADD_INSN (ret, &dummy_line_node, pop); + } + else if (!popped) { ADD_INSN1(ret, &dummy_line_node, setn, INT2FIX(orig_argc + 1)); } + ADD_SEND_R(ret, &dummy_line_node, method_id, INT2FIX(orig_argc), block_iseq, INT2FIX(flags), kw_arg); PM_POP_UNLESS_POPPED; } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 835b3b819b8c0b..71155979036e40 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1484,6 +1484,13 @@ def foo.[]=(k,v); 42; end foo.[]=(1,2) CODE + # With splat inside of []= + assert_prism_eval(<<~RUBY) + obj = Object.new + def obj.[]=(a, b); 10; end + obj[*[1]] = 3 + RUBY + assert_prism_eval(<<-CODE) def self.prism_opt_var_trail_hash(a = nil, *b, c, **d); end prism_opt_var_trail_hash("a") From 44d0c5ae3f1e1586f9dac07dd19f65b80fb8e2b4 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 11 Jan 2024 13:51:32 -0500 Subject: [PATCH 075/640] [PRISM] Raise syntax errors when found --- common.mk | 2 ++ iseq.c | 38 ++++++++++++++++++++++++++++---------- test/ruby/test_iseq.rb | 11 +++++++---- 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/common.mk b/common.mk index 171c7dfd30cc6c..5a929fc937fbef 100644 --- a/common.mk +++ b/common.mk @@ -8495,6 +8495,7 @@ iseq.$(OBJEXT): $(top_srcdir)/internal/fixnum.h iseq.$(OBJEXT): $(top_srcdir)/internal/gc.h iseq.$(OBJEXT): $(top_srcdir)/internal/hash.h iseq.$(OBJEXT): $(top_srcdir)/internal/imemo.h +iseq.$(OBJEXT): $(top_srcdir)/internal/io.h iseq.$(OBJEXT): $(top_srcdir)/internal/numeric.h iseq.$(OBJEXT): $(top_srcdir)/internal/parse.h iseq.$(OBJEXT): $(top_srcdir)/internal/rational.h @@ -8702,6 +8703,7 @@ iseq.$(OBJEXT): {$(VPATH)}internal/value_type.h iseq.$(OBJEXT): {$(VPATH)}internal/variable.h iseq.$(OBJEXT): {$(VPATH)}internal/warning_push.h iseq.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +iseq.$(OBJEXT): {$(VPATH)}io.h iseq.$(OBJEXT): {$(VPATH)}iseq.c iseq.$(OBJEXT): {$(VPATH)}iseq.h iseq.$(OBJEXT): {$(VPATH)}method.h diff --git a/iseq.c b/iseq.c index 27c5bb5d82d907..f2911b43f26962 100644 --- a/iseq.c +++ b/iseq.c @@ -28,6 +28,7 @@ #include "internal/file.h" #include "internal/gc.h" #include "internal/hash.h" +#include "internal/io.h" #include "internal/ruby_parser.h" #include "internal/sanitizers.h" #include "internal/symbol.h" @@ -1404,19 +1405,36 @@ static void iseqw_s_compile_prism_compile(pm_parser_t *parser, VALUE opt, rb_iseq_t *iseq, VALUE file, VALUE path, int first_lineno) { pm_node_t *node = pm_parse(parser); - rb_code_location_t code_location; - pm_code_location(&code_location, &parser->newline_list, &node->location); - rb_compile_option_t option; - make_compile_option(&option, opt); - prepare_iseq_build(iseq, rb_fstring_lit(""), file, path, first_lineno, &code_location, -1, NULL, 0, ISEQ_TYPE_TOP, Qnil, &option); + if (parser->error_list.size > 0) { + pm_buffer_t buffer = { 0 }; + pm_parser_errors_format(parser, &buffer, rb_stderr_tty_p()); - pm_scope_node_t scope_node; - pm_scope_node_init(node, &scope_node, NULL, parser); - rb_iseq_compile_prism_node(iseq, &scope_node, parser); + pm_buffer_prepend_string(&buffer, "syntax errors found\n", 20); + VALUE error = rb_exc_new(rb_eSyntaxError, pm_buffer_value(&buffer), pm_buffer_length(&buffer)); - finish_iseq_build(iseq); - pm_node_destroy(parser, node); + pm_buffer_free(&buffer); + pm_node_destroy(parser, node); + + // TODO: We need to set the backtrace based on the ISEQ. + // VALUE path = pathobj_path(ISEQ_BODY(iseq)->location.pathobj); + // rb_funcallv(error, rb_intern("set_backtrace"), 1, &path); + rb_exc_raise(error); + } else { + rb_code_location_t code_location; + pm_code_location(&code_location, &parser->newline_list, &node->location); + + rb_compile_option_t option; + make_compile_option(&option, opt); + prepare_iseq_build(iseq, rb_fstring_lit(""), file, path, first_lineno, &code_location, -1, NULL, 0, ISEQ_TYPE_TOP, Qnil, &option); + + pm_scope_node_t scope_node; + pm_scope_node_init(node, &scope_node, NULL, parser); + rb_iseq_compile_prism_node(iseq, &scope_node, parser); + + finish_iseq_build(iseq); + pm_node_destroy(parser, node); + } } static VALUE diff --git a/test/ruby/test_iseq.rb b/test/ruby/test_iseq.rb index b0896511d8337f..f5c0b8205718dc 100644 --- a/test/ruby/test_iseq.rb +++ b/test/ruby/test_iseq.rb @@ -801,12 +801,15 @@ def test_ibf_bignum def test_compile_prism_with_file Tempfile.create(%w"test_iseq .rb") do |f| - f.puts "name = 'Prism'; puts 'hello" + f.puts "name = 'Prism'; puts 'hello'" f.close - assert_nothing_raised(SyntaxError) { - RubyVM::InstructionSequence.compile_prism(f.path) - } + assert_nothing_raised(TypeError) do + begin + RubyVM::InstructionSequence.compile_prism(f.path) + rescue SyntaxError + end + end end end end From 76a207e5420b9ecdcc62c0d571f869c022d5d36e Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 11 Jan 2024 15:47:15 -0500 Subject: [PATCH 076/640] [ruby/prism] Fix nested default value error https://github.com/ruby/prism/commit/ef26b283de --- prism/prism.c | 98 +++++++++++++++++++++++++---------- prism/util/pm_constant_pool.c | 23 ++++---- prism/util/pm_constant_pool.h | 7 +++ 3 files changed, 91 insertions(+), 37 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 96725b1ee048f4..570b86ab1d84f0 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -5932,6 +5932,33 @@ pm_parser_scope_push(pm_parser_t *parser, bool closed) { return true; } +/** + * Save the current param name as the return value and set it to the given + * constant id. + */ +static inline pm_constant_id_t +pm_parser_current_param_name_set(pm_parser_t *parser, pm_constant_id_t current_param_name) { + pm_constant_id_t saved_param_name = parser->current_param_name; + parser->current_param_name = current_param_name; + return saved_param_name; +} + +/** + * Save the current param name as the return value and clear it. + */ +static inline pm_constant_id_t +pm_parser_current_param_name_unset(pm_parser_t *parser) { + return pm_parser_current_param_name_set(parser, PM_CONSTANT_ID_UNSET); +} + +/** + * Restore the current param name from the given value. + */ +static inline void +pm_parser_current_param_name_restore(pm_parser_t *parser, pm_constant_id_t saved_param_name) { + parser->current_param_name = saved_param_name; +} + /** * Check if any of the currently visible scopes contain a local variable * described by the given constant id. @@ -11715,8 +11742,8 @@ parse_parameters( if (accept1(parser, PM_TOKEN_EQUAL)) { pm_token_t operator = parser->previous; context_push(parser, PM_CONTEXT_DEFAULT_PARAMS); - pm_constant_id_t old_param_name = parser->current_param_name; - parser->current_param_name = pm_parser_constant_id_token(parser, &name); + + pm_constant_id_t saved_param_name = pm_parser_current_param_name_set(parser, pm_parser_constant_id_token(parser, &name)); pm_node_t *value = parse_value_expression(parser, binding_power, false, PM_ERR_PARAMETER_NO_DEFAULT); pm_optional_parameter_node_t *param = pm_optional_parameter_node_create(parser, &name, &operator, value); @@ -11725,7 +11752,7 @@ parse_parameters( } pm_parameters_node_optionals_append(params, param); - parser->current_param_name = old_param_name; + pm_parser_current_param_name_restore(parser, saved_param_name); context_pop(parser); // If parsing the value of the parameter resulted in error recovery, @@ -11793,11 +11820,13 @@ parse_parameters( if (token_begins_expression_p(parser->current.type)) { context_push(parser, PM_CONTEXT_DEFAULT_PARAMS); - pm_constant_id_t old_param_name = parser->current_param_name; - parser->current_param_name = pm_parser_constant_id_token(parser, &local); + + pm_constant_id_t saved_param_name = pm_parser_current_param_name_set(parser, pm_parser_constant_id_token(parser, &local)); pm_node_t *value = parse_value_expression(parser, binding_power, false, PM_ERR_PARAMETER_NO_DEFAULT_KW); - parser->current_param_name = old_param_name; + + pm_parser_current_param_name_restore(parser, saved_param_name); context_pop(parser); + param = (pm_node_t *) pm_optional_keyword_parameter_node_create(parser, &name, value); } else { @@ -12142,8 +12171,10 @@ parse_block(pm_parser_t *parser) { pm_token_t opening = parser->previous; accept1(parser, PM_TOKEN_NEWLINE); + pm_constant_id_t saved_param_name = pm_parser_current_param_name_unset(parser); pm_accepts_block_stack_push(parser, true); pm_parser_scope_push(parser, false); + pm_block_parameters_node_t *block_parameters = NULL; if (accept1(parser, PM_TOKEN_PIPE)) { @@ -12207,6 +12238,8 @@ parse_block(pm_parser_t *parser) { pm_constant_id_list_t locals = parser->current_scope->locals; pm_parser_scope_pop(parser); pm_accepts_block_stack_pop(parser); + pm_parser_current_param_name_restore(parser, saved_param_name); + return pm_block_node_create(parser, &locals, locals_body_index, &opening, parameters, statements, &parser->previous); } @@ -14910,8 +14943,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_token_t operator = parser->previous; pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_NOT, true, PM_ERR_EXPECT_EXPRESSION_AFTER_LESS_LESS); - pm_constant_id_t old_param_name = parser->current_param_name; - parser->current_param_name = 0; + pm_constant_id_t saved_param_name = pm_parser_current_param_name_unset(parser); pm_parser_scope_push(parser, true); accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON); @@ -14928,11 +14960,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CLASS_TERM); - pm_constant_id_list_t locals = parser->current_scope->locals; + pm_parser_scope_pop(parser); - parser->current_param_name = old_param_name; pm_do_loop_stack_pop(parser); + pm_parser_current_param_name_restore(parser, saved_param_name); + return (pm_node_t *) pm_singleton_class_node_create(parser, &locals, &class_keyword, &operator, expression, statements, &parser->previous); } @@ -14958,9 +14991,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b superclass = NULL; } - pm_constant_id_t old_param_name = parser->current_param_name; - parser->current_param_name = 0; + pm_constant_id_t saved_param_name = pm_parser_current_param_name_unset(parser); pm_parser_scope_push(parser, true); + if (inheritance_operator.type != PM_TOKEN_NOT_PROVIDED) { expect2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_ERR_CLASS_UNEXPECTED_END); } else { @@ -14986,9 +15019,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } pm_constant_id_list_t locals = parser->current_scope->locals; + pm_parser_scope_pop(parser); - parser->current_param_name = old_param_name; pm_do_loop_stack_pop(parser); + pm_parser_current_param_name_restore(parser, saved_param_name); if (!PM_NODE_TYPE_P(constant_path, PM_CONSTANT_PATH_NODE) && !(PM_NODE_TYPE_P(constant_path, PM_CONSTANT_READ_NODE))) { pm_parser_err_node(parser, constant_path, PM_ERR_CLASS_NAME); @@ -15003,18 +15037,21 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_token_t operator = not_provided(parser); pm_token_t name = (pm_token_t) { .type = PM_TOKEN_MISSING, .start = def_keyword.end, .end = def_keyword.end }; - // This context is necessary for lexing `...` in a bare params correctly. - // It must be pushed before lexing the first param, so it is here. + // This context is necessary for lexing `...` in a bare params + // correctly. It must be pushed before lexing the first param, so it + // is here. context_push(parser, PM_CONTEXT_DEF_PARAMS); + pm_constant_id_t saved_param_name; + parser_lex(parser); - pm_constant_id_t old_param_name = parser->current_param_name; switch (parser->current.type) { case PM_CASE_OPERATOR: + saved_param_name = pm_parser_current_param_name_unset(parser); pm_parser_scope_push(parser, true); - parser->current_param_name = 0; lex_state_set(parser, PM_LEX_STATE_ENDFN); parser_lex(parser); + name = parser->previous; break; case PM_TOKEN_IDENTIFIER: { @@ -15023,17 +15060,18 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (match2(parser, PM_TOKEN_DOT, PM_TOKEN_COLON_COLON)) { receiver = parse_variable_call(parser); + saved_param_name = pm_parser_current_param_name_unset(parser); pm_parser_scope_push(parser, true); - parser->current_param_name = 0; lex_state_set(parser, PM_LEX_STATE_FNAME); parser_lex(parser); operator = parser->previous; name = parse_method_definition_name(parser); } else { + saved_param_name = pm_parser_current_param_name_unset(parser); pm_refute_numbered_parameter(parser, parser->previous.start, parser->previous.end); pm_parser_scope_push(parser, true); - parser->current_param_name = 0; + name = parser->previous; } @@ -15050,9 +15088,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b case PM_TOKEN_KEYWORD___FILE__: case PM_TOKEN_KEYWORD___LINE__: case PM_TOKEN_KEYWORD___ENCODING__: { + saved_param_name = pm_parser_current_param_name_unset(parser); pm_parser_scope_push(parser, true); - parser->current_param_name = 0; parser_lex(parser); + pm_token_t identifier = parser->previous; if (match2(parser, PM_TOKEN_DOT, PM_TOKEN_COLON_COLON)) { @@ -15124,8 +15163,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b operator = parser->previous; receiver = (pm_node_t *) pm_parentheses_node_create(parser, &lparen, expression, &rparen); + saved_param_name = pm_parser_current_param_name_unset(parser); pm_parser_scope_push(parser, true); - parser->current_param_name = 0; // To push `PM_CONTEXT_DEF_PARAMS` again is for the same reason as described the above. context_push(parser, PM_CONTEXT_DEF_PARAMS); @@ -15133,8 +15172,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b break; } default: + saved_param_name = pm_parser_current_param_name_unset(parser); pm_parser_scope_push(parser, true); - parser->current_param_name = 0; + name = parse_method_definition_name(parser); break; } @@ -15249,8 +15289,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } pm_constant_id_list_t locals = parser->current_scope->locals; - parser->current_param_name = old_param_name; + pm_parser_scope_pop(parser); + pm_parser_current_param_name_restore(parser, saved_param_name); return (pm_node_t *) pm_def_node_create( parser, @@ -15478,9 +15519,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_parser_err_token(parser, &name, PM_ERR_MODULE_NAME); } - pm_constant_id_t old_param_name = parser->current_param_name; - parser->current_param_name = 0; + pm_constant_id_t saved_param_name = pm_parser_current_param_name_unset(parser); pm_parser_scope_push(parser, true); + accept2(parser, PM_TOKEN_SEMICOLON, PM_TOKEN_NEWLINE); pm_node_t *statements = NULL; @@ -15497,7 +15538,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_constant_id_list_t locals = parser->current_scope->locals; pm_parser_scope_pop(parser); - parser->current_param_name = old_param_name; + pm_parser_current_param_name_restore(parser, saved_param_name); expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_MODULE_TERM); @@ -16164,7 +16205,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b parser_lex(parser); pm_token_t operator = parser->previous; + pm_constant_id_t saved_param_name = pm_parser_current_param_name_unset(parser); pm_parser_scope_push(parser, false); + pm_block_parameters_node_t *block_parameters; switch (parser->current.type) { @@ -16243,8 +16286,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b } pm_constant_id_list_t locals = parser->current_scope->locals; + pm_parser_scope_pop(parser); pm_accepts_block_stack_pop(parser); + pm_parser_current_param_name_restore(parser, saved_param_name); + return (pm_node_t *) pm_lambda_node_create(parser, &locals, locals_body_index, &operator, &opening, &parser->previous, parameters, body); } case PM_TOKEN_UPLUS: { diff --git a/prism/util/pm_constant_pool.c b/prism/util/pm_constant_pool.c index e06682eb48317a..7b8ed0654dceb8 100644 --- a/prism/util/pm_constant_pool.c +++ b/prism/util/pm_constant_pool.c @@ -124,13 +124,13 @@ pm_constant_pool_resize(pm_constant_pool_t *pool) { // If an id is set on this constant, then we know we have content here. // In this case we need to insert it into the next constant pool. - if (bucket->id != 0) { + if (bucket->id != PM_CONSTANT_ID_UNSET) { uint32_t next_index = bucket->hash & mask; // This implements linear scanning to find the next available slot // in case this index is already taken. We don't need to bother // comparing the values since we know that the hash is unique. - while (next_buckets[next_index].id != 0) { + while (next_buckets[next_index].id != PM_CONSTANT_ID_UNSET) { next_index = (next_index + 1) & mask; } @@ -177,7 +177,7 @@ pm_constant_pool_init(pm_constant_pool_t *pool, uint32_t capacity) { */ pm_constant_t * pm_constant_pool_id_to_constant(const pm_constant_pool_t *pool, pm_constant_id_t constant_id) { - assert(constant_id > 0 && constant_id <= pool->size); + assert(constant_id != PM_CONSTANT_ID_UNSET && constant_id <= pool->size); return &pool->constants[constant_id - 1]; } @@ -187,7 +187,7 @@ pm_constant_pool_id_to_constant(const pm_constant_pool_t *pool, pm_constant_id_t static inline pm_constant_id_t pm_constant_pool_insert(pm_constant_pool_t *pool, const uint8_t *start, size_t length, pm_constant_pool_bucket_type_t type) { if (pool->size >= (pool->capacity / 4 * 3)) { - if (!pm_constant_pool_resize(pool)) return 0; + if (!pm_constant_pool_resize(pool)) return PM_CONSTANT_ID_UNSET; } assert(is_power_of_two(pool->capacity)); @@ -197,7 +197,7 @@ pm_constant_pool_insert(pm_constant_pool_t *pool, const uint8_t *start, size_t l uint32_t index = hash & mask; pm_constant_pool_bucket_t *bucket; - while (bucket = &pool->buckets[index], bucket->id != 0) { + while (bucket = &pool->buckets[index], bucket->id != PM_CONSTANT_ID_UNSET) { // If there is a collision, then we need to check if the content is the // same as the content we are trying to insert. If it is, then we can // return the id of the existing constant. @@ -248,8 +248,8 @@ pm_constant_pool_insert(pm_constant_pool_t *pool, const uint8_t *start, size_t l } /** - * Insert a constant into a constant pool. Returns the id of the constant, or 0 - * if any potential calls to resize fail. + * Insert a constant into a constant pool. Returns the id of the constant, or + * PM_CONSTANT_ID_UNSET if any potential calls to resize fail. */ pm_constant_id_t pm_constant_pool_insert_shared(pm_constant_pool_t *pool, const uint8_t *start, size_t length) { @@ -258,8 +258,8 @@ pm_constant_pool_insert_shared(pm_constant_pool_t *pool, const uint8_t *start, s /** * Insert a constant into a constant pool from memory that is now owned by the - * constant pool. Returns the id of the constant, or 0 if any potential calls to - * resize fail. + * constant pool. Returns the id of the constant, or PM_CONSTANT_ID_UNSET if any + * potential calls to resize fail. */ pm_constant_id_t pm_constant_pool_insert_owned(pm_constant_pool_t *pool, const uint8_t *start, size_t length) { @@ -268,7 +268,8 @@ pm_constant_pool_insert_owned(pm_constant_pool_t *pool, const uint8_t *start, si /** * Insert a constant into a constant pool from memory that is constant. Returns - * the id of the constant, or 0 if any potential calls to resize fail. + * the id of the constant, or PM_CONSTANT_ID_UNSET if any potential calls to + * resize fail. */ pm_constant_id_t pm_constant_pool_insert_constant(pm_constant_pool_t *pool, const uint8_t *start, size_t length) { @@ -286,7 +287,7 @@ pm_constant_pool_free(pm_constant_pool_t *pool) { pm_constant_pool_bucket_t *bucket = &pool->buckets[index]; // If an id is set on this constant, then we know we have content here. - if (bucket->id != 0 && bucket->type == PM_CONSTANT_POOL_BUCKET_OWNED) { + if (bucket->id != PM_CONSTANT_ID_UNSET && bucket->type == PM_CONSTANT_POOL_BUCKET_OWNED) { pm_constant_t *constant = &pool->constants[bucket->id - 1]; free((void *) constant->start); } diff --git a/prism/util/pm_constant_pool.h b/prism/util/pm_constant_pool.h index ae5a88fbde3ec5..3743d9f58d2137 100644 --- a/prism/util/pm_constant_pool.h +++ b/prism/util/pm_constant_pool.h @@ -18,6 +18,13 @@ #include #include +/** + * When we allocate constants into the pool, we reserve 0 to mean that the slot + * is not yet filled. This constant is reused in other places to indicate the + * lack of a constant id. + */ +#define PM_CONSTANT_ID_UNSET 0 + /** * A constant id is a unique identifier for a constant in the constant pool. */ From eb8df2fa7aa7b008bd8dbce765694635a564e8f9 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Thu, 11 Jan 2024 12:52:14 -0800 Subject: [PATCH 077/640] Update Kernel#load documentation to remove phrase related to protection Code loaded via Kernel#load can modify the global namespace even if the wrap parameter is provided. Fixes [Bug #19990] --- load.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/load.c b/load.c index d962d08b37fbae..f0c62dc7071460 100644 --- a/load.c +++ b/load.c @@ -883,9 +883,8 @@ rb_load_protect(VALUE fname, int wrap, int *pstate) * LoadError will be raised. * * If the optional _wrap_ parameter is +true+, the loaded script will - * be executed under an anonymous module, protecting the calling - * program's global namespace. If the optional _wrap_ parameter is a - * module, the loaded script will be executed under the given module. + * be executed under an anonymous module. If the optional _wrap_ parameter + * is a module, the loaded script will be executed under the given module. * In no circumstance will any local variables in the loaded file be * propagated to the loading environment. */ From 371256775f56881fc6a4d41d47afa63e00199c0d Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 11 Jan 2024 14:50:09 -0800 Subject: [PATCH 078/640] Anonymous rest nodes should increase the local table size When we calculate the local table size, we need to account for anonymous "rest" parameters. Since they don't have a name, they won't be in the "locals" table that Prism provides, but we need to reserve room for them anyway. Fixes: https://github.com/ruby/prism/issues/2154 --- prism_compile.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index cbae85b9f40cc5..7bba3be0a100e5 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -5606,6 +5606,18 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } } + // If we have an anonymous "rest" node, we'll need to increase the local + // table size to take it in to account. + // def m(foo, *, bar) + // ^ + if (parameters_node && parameters_node->rest) { + if (!(PM_NODE_TYPE_P(parameters_node->rest, PM_IMPLICIT_REST_NODE))) { + if (!((pm_rest_parameter_node_t *)parameters_node->rest)->name) { + table_size++; + } + } + } + if (posts_list) { for (size_t i = 0; i < posts_list->size; i++) { // For each MultiTargetNode, we're going to have one From 18573b8d054f655e3e8b24902985bf4028f88810 Mon Sep 17 00:00:00 2001 From: John Hawthorn Date: Thu, 11 Jan 2024 11:57:03 -0800 Subject: [PATCH 079/640] Avoid reading unused lvars in Primitive.cexpr Previously on builds with optimizations disabled, this could result in an out of bounds read. When we had all of: * built with -O0 * Leaf builtin * Primitive.mandatory_only * "no args builtin", called by vm_call_single_noarg_inline_builti * The stack is escaped to the heap via binding or a proc This is because mk_builtin_loader generated reads for all locals regardless of whether they were used and in the case we generated a mandatory_only iseq that would include more variables than were actually available. On optimized builds, the invalid accesses would be optimized away, and this also was often unnoticed as the invalid access would just hit another part of the stack unless it had been escaped to the heap. The fix here is imperfect, as this could have false positives, but since Primitive.cexpr! is only available within the cruby codebase itself that's probably fine as a proper fix would be much more challenging (the only false positives we found were in rjit.rb). Fixes [Bug #20178] Co-authored-by: Adam Hess --- bootstraptest/test_method.rb | 9 +++++++++ tool/mk_builtin_loader.rb | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/bootstraptest/test_method.rb b/bootstraptest/test_method.rb index 04c9eb2d11425e..964bf39d98b801 100644 --- a/bootstraptest/test_method.rb +++ b/bootstraptest/test_method.rb @@ -1190,3 +1190,12 @@ def test2 o, args, block test2 o1, [], block $result.join } + +assert_equal 'ok', %q{ + def foo + binding + ["ok"].first + end + foo + foo +}, '[Bug #20178]' diff --git a/tool/mk_builtin_loader.rb b/tool/mk_builtin_loader.rb index 5ab427ca9b2931..95600e6a3bdc55 100644 --- a/tool/mk_builtin_loader.rb +++ b/tool/mk_builtin_loader.rb @@ -263,11 +263,17 @@ def collect_iseq iseq_ary def generate_cexpr(ofile, lineno, line_file, body_lineno, text, locals, func_name) f = StringIO.new + + # Avoid generating fetches of lvars we don't need. This is imperfect as it + # will match text inside strings or other false positives. + local_candidates = text.scan(/[a-zA-Z_][a-zA-Z0-9_]*/) + f.puts '{' lineno += 1 # locals is nil outside methods locals&.reverse_each&.with_index{|param, i| next unless Symbol === param + next unless local_candidates.include?(param.to_s) f.puts "MAYBE_UNUSED(const VALUE) #{param} = rb_vm_lvar(ec, #{-3 - i});" lineno += 1 } From f5237e105a42a7c1be6d9b697fe2ff742a165b31 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Jan 2024 02:10:14 +0000 Subject: [PATCH 080/640] Bump actions/cache in /.github/actions/setup/directories Bumps [actions/cache](https://github.com/actions/cache) from 3.3.2 to 3.3.3. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/704facf57e6136b1bc63b828d79edcd491f0ee84...e12d46a63a90f2fae62d114769bbf2a179198b5c) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/actions/setup/directories/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/setup/directories/action.yml b/.github/actions/setup/directories/action.yml index c23dd01098202a..d699ea9e05b8ca 100644 --- a/.github/actions/setup/directories/action.yml +++ b/.github/actions/setup/directories/action.yml @@ -80,7 +80,7 @@ runs: with: path: ${{ inputs.srcdir }} - - uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 + - uses: actions/cache@e12d46a63a90f2fae62d114769bbf2a179198b5c # v3.3.3 with: path: ${{ inputs.srcdir }}/.downloaded-cache key: downloaded-cache From 1e9fac4dbc173af9301537e1f5b7ea291b9ecb22 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Jan 2024 02:36:28 +0000 Subject: [PATCH 081/640] Bump actions/cache from 3.3.2 to 3.3.3 Bumps [actions/cache](https://github.com/actions/cache) from 3.3.2 to 3.3.3. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/704facf57e6136b1bc63b828d79edcd491f0ee84...e12d46a63a90f2fae62d114769bbf2a179198b5c) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/windows.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index b2b3640fd66fe5..a31545fe5a37a5 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -96,7 +96,7 @@ jobs: ${{ steps.find-tools.outputs.needs }} if: ${{ steps.find-tools.outputs.needs != '' }} - - uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 + - uses: actions/cache@e12d46a63a90f2fae62d114769bbf2a179198b5c # v3.3.3 with: path: C:\vcpkg\downloads key: ${{ runner.os }}-vcpkg-download-${{ env.OS_VER }}-${{ github.sha }} @@ -104,7 +104,7 @@ jobs: ${{ runner.os }}-vcpkg-download-${{ env.OS_VER }}- ${{ runner.os }}-vcpkg-download- - - uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 + - uses: actions/cache@e12d46a63a90f2fae62d114769bbf2a179198b5c # v3.3.3 with: path: C:\vcpkg\installed key: ${{ runner.os }}-vcpkg-installed-${{ env.OS_VER }}-${{ github.sha }} From 6a45320c256f25e9fcdf9d969a45b85c885e28f2 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 12 Jan 2024 14:55:57 +0900 Subject: [PATCH 082/640] Truncate only prefix. Don't remove v from like preview1 --- tool/gen-github-release.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tool/gen-github-release.rb b/tool/gen-github-release.rb index 600a01430da6df..e36aadcfa7e014 100755 --- a/tool/gen-github-release.rb +++ b/tool/gen-github-release.rb @@ -57,7 +57,7 @@ note << "https://github.com/ruby/ruby/compare/#{ARGV[0]}...#{ARGV[1]}\n\n" if ARGV[2] == "--no-dry-run" - name = ARGV[1].gsub(/v/, "").gsub(/_/, ".") + name = ARGV[1].gsub(/^v/, "").gsub(/_/, ".") client.create_release("ruby/ruby", ARGV[1], name: name, body: note, make_latest: "false") puts "Created a release: https://github.com/ruby/ruby/releases/tag/#{ARGV[1]}" else From 4ba8f0dc993953d3ddda6328e3ef17a2fc2cbde5 Mon Sep 17 00:00:00 2001 From: KJ Tsanaktsidis Date: Sun, 12 Nov 2023 13:24:55 +1100 Subject: [PATCH 083/640] Pass down "stack start" variables from closer to the top of the stack The implementation of `native_thread_init_stack` for the various threading models can use the address of a local variable as part of the calculation of the machine stack extents: * pthreads uses it as a lower-bound on the start of the stack, because glibc (and maybe other libcs) can store its own data on the stack before calling into user code on thread creation. * win32 uses it as an argument to VirtualQuery, which gets the extent of the memory mapping which contains the variable However, the local being used for this is actually allocated _inside_ the `native_thread_init_stack` frame; that means the caller might allocate a VALUE on the stack that actually lies outside the bounds stored in machine.stack_{start,end}. A local variable from one level above the topmost frame that stores VALUEs on the stack must be drilled down into the call to `native_thread_init_stack` to be used in the calculation. This probably doesn't _really_ matter for the win32 case (they'll be in the same memory mapping so VirtualQuery should return the same thing), but definitely could matter for the pthreads case. [Bug #20001] --- eval.c | 4 ++-- include/ruby/internal/interpreter.h | 2 +- internal/inits.h | 2 +- thread.c | 4 ++-- thread_none.c | 4 ++-- thread_pthread.c | 21 ++++++++++++++++----- thread_win32.c | 12 ++++++------ vm.c | 4 ++-- vm_core.h | 2 +- 9 files changed, 33 insertions(+), 22 deletions(-) diff --git a/eval.c b/eval.c index aa0eae08727588..6424aed1dcda67 100644 --- a/eval.c +++ b/eval.c @@ -70,7 +70,7 @@ ruby_setup(void) if (GET_VM()) return 0; - ruby_init_stack((void *)&state); + ruby_init_stack(&state); /* * Disable THP early before mallocs happen because we want this to @@ -79,7 +79,7 @@ ruby_setup(void) #if defined(__linux__) && defined(PR_SET_THP_DISABLE) prctl(PR_SET_THP_DISABLE, 1, 0, 0, 0); #endif - Init_BareVM(); + Init_BareVM(&state); Init_heap(); rb_vm_encoded_insn_data_table_init(); Init_vm_objects(); diff --git a/include/ruby/internal/interpreter.h b/include/ruby/internal/interpreter.h index 662d39c0ec5702..d36d61ba54d295 100644 --- a/include/ruby/internal/interpreter.h +++ b/include/ruby/internal/interpreter.h @@ -141,7 +141,7 @@ void ruby_show_copyright(void); * * @param[in] addr A pointer somewhere on the stack, near its bottom. */ -void ruby_init_stack(volatile VALUE *addr); +void ruby_init_stack(volatile void *addr); /** * Initializes the VM and builtin libraries. diff --git a/internal/inits.h b/internal/inits.h index 03e180f77bd026..a2b2eea96f7a88 100644 --- a/internal/inits.h +++ b/internal/inits.h @@ -29,7 +29,7 @@ int Init_enc_set_filesystem_encoding(void); void Init_newline(void); /* vm.c */ -void Init_BareVM(void); +void Init_BareVM(void *local_in_parent_frame); void Init_vm_objects(void); /* vm_backtrace.c */ diff --git a/thread.c b/thread.c index 070d1bbdfaba88..e7a9d7cd9bdcc7 100644 --- a/thread.c +++ b/thread.c @@ -522,9 +522,9 @@ static VALUE rb_threadptr_raise(rb_thread_t *, int, VALUE *); static VALUE rb_thread_to_s(VALUE thread); void -ruby_thread_init_stack(rb_thread_t *th) +ruby_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame) { - native_thread_init_stack(th); + native_thread_init_stack(th, local_in_parent_frame); } const VALUE * diff --git a/thread_none.c b/thread_none.c index 4d53d3bf4d89c4..767b929cf9105f 100644 --- a/thread_none.c +++ b/thread_none.c @@ -140,12 +140,12 @@ ruby_mn_threads_params(void) } void -ruby_init_stack(volatile VALUE *addr) +ruby_init_stack(volatile void *addr) { } static int -native_thread_init_stack(rb_thread_t *th) +native_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame) { #if defined(__wasm__) && !defined(__EMSCRIPTEN__) th->ec->machine.stack_start = (VALUE *)rb_wasm_stack_get_base(); diff --git a/thread_pthread.c b/thread_pthread.c index 6d2f55a9573ed7..a6a6c9d127e3c6 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -1964,7 +1964,7 @@ reserve_stack(volatile char *limit, size_t size) #undef ruby_init_stack void -ruby_init_stack(volatile VALUE *addr) +ruby_init_stack(volatile void *addr) { native_main_thread.id = pthread_self(); @@ -2049,7 +2049,7 @@ ruby_init_stack(volatile VALUE *addr) {int err = (expr); if (err) {rb_bug_errno(#expr, err);}} static int -native_thread_init_stack(rb_thread_t *th) +native_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame) { rb_nativethread_id_t curr = pthread_self(); @@ -2064,8 +2064,8 @@ native_thread_init_stack(rb_thread_t *th) size_t size; if (get_stack(&start, &size) == 0) { - uintptr_t diff = (uintptr_t)start - (uintptr_t)&curr; - th->ec->machine.stack_start = (VALUE *)&curr; + uintptr_t diff = (uintptr_t)start - (uintptr_t)local_in_parent_frame; + th->ec->machine.stack_start = (uintptr_t)local_in_parent_frame; th->ec->machine.stack_maxsize = size - diff; } } @@ -2185,8 +2185,19 @@ native_thread_create_dedicated(rb_thread_t *th) static void call_thread_start_func_2(rb_thread_t *th) { - native_thread_init_stack(th); + /* Capture the address of a local in this stack frame to mark the beginning of the + machine stack for this thread. This is required even if we can tell the real + stack beginning from the pthread API in native_thread_init_stack, because + glibc stores some of its own data on the stack before calling into user code + on a new thread, and replacing that data on fiber-switch would break it (see + bug #13887) */ + VALUE stack_start = 0; + VALUE *stack_start_addr = &stack_start; + native_thread_init_stack(th, stack_start_addr); thread_start_func_2(th, th->ec->machine.stack_start); + + /* Ensure that stack_start really was spilled to the stack */ + RB_GC_GUARD(stack_start) } static void * diff --git a/thread_win32.c b/thread_win32.c index bd983e0bd9fb62..e92472cea947d4 100644 --- a/thread_win32.c +++ b/thread_win32.c @@ -582,7 +582,7 @@ rb_native_cond_destroy(rb_nativethread_cond_t *cond) } void -ruby_init_stack(volatile VALUE *addr) +ruby_init_stack(volatile void *addr) { } @@ -594,20 +594,20 @@ COMPILER_WARNING_PUSH COMPILER_WARNING_IGNORED(-Wmaybe-uninitialized) #endif static inline SIZE_T -query_memory_basic_info(PMEMORY_BASIC_INFORMATION mi) +query_memory_basic_info(PMEMORY_BASIC_INFORMATION mi, void *local_in_parent_frame) { - return VirtualQuery(mi, mi, sizeof(*mi)); + return VirtualQuery(local_in_parent_frame, mi, sizeof(*mi)); } COMPILER_WARNING_POP static void -native_thread_init_stack(rb_thread_t *th) +native_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame) { MEMORY_BASIC_INFORMATION mi; char *base, *end; DWORD size, space; - CHECK_ERR(query_memory_basic_info(&mi)); + CHECK_ERR(query_memory_basic_info(&mi, local_in_parent_frame)); base = mi.AllocationBase; end = mi.BaseAddress; end += mi.RegionSize; @@ -638,7 +638,7 @@ thread_start_func_1(void *th_ptr) rb_thread_t *th = th_ptr; volatile HANDLE thread_id = th->nt->thread_id; - native_thread_init_stack(th); + native_thread_init_stack(th, &th); th->nt->interrupt_event = CreateEvent(0, TRUE, FALSE, 0); /* run */ diff --git a/vm.c b/vm.c index 37d631116aa4dc..945e7b91f7c501 100644 --- a/vm.c +++ b/vm.c @@ -4174,7 +4174,7 @@ rb_vm_set_progname(VALUE filename) extern const struct st_hash_type rb_fstring_hash_type; void -Init_BareVM(void) +Init_BareVM(void *local_in_parent_frame) { /* VM bootstrap: phase 1 */ rb_vm_t * vm = ruby_mimmalloc(sizeof(*vm)); @@ -4204,7 +4204,7 @@ Init_BareVM(void) th_init(th, 0, vm); rb_ractor_set_current_ec(th->ractor, th->ec); - ruby_thread_init_stack(th); + ruby_thread_init_stack(th, local_in_parent_frame); // setup ractor system rb_native_mutex_initialize(&vm->ractor.sync.lock); diff --git a/vm_core.h b/vm_core.h index 354603514ebb46..91cfae77e9e7ee 100644 --- a/vm_core.h +++ b/vm_core.h @@ -1842,7 +1842,7 @@ rb_control_frame_t *rb_vm_get_binding_creatable_next_cfp(const rb_execution_cont VALUE *rb_vm_svar_lep(const rb_execution_context_t *ec, const rb_control_frame_t *cfp); int rb_vm_get_sourceline(const rb_control_frame_t *); void rb_vm_stack_to_heap(rb_execution_context_t *ec); -void ruby_thread_init_stack(rb_thread_t *th); +void ruby_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame); rb_thread_t * ruby_thread_from_native(void); int ruby_thread_set_native(rb_thread_t *th); int rb_vm_control_frame_id_and_class(const rb_control_frame_t *cfp, ID *idp, ID *called_idp, VALUE *klassp); From 6185cfdf38e26026c6d38220eeca48689e54cdcf Mon Sep 17 00:00:00 2001 From: KJ Tsanaktsidis Date: Sun, 12 Nov 2023 13:34:43 +1100 Subject: [PATCH 084/640] Make stack bounds detection work with ASAN Where a local variable is used as part of the stack bounds detection, it has to actually be on the stack. ASAN can put local variable on "fake stacks", however, with addresses in different memory mappings. This completely destroys the stack bounds calculation, and can lead to e.g. things not getting GC marked on the machine stack or stackoverflow checks that always fail. The __asan_addr_is_in_fake_stack helper can be used to get the _real_ stack address of such variables, and thus perform the stack size calculation properly [Bug #20001] --- internal/sanitizers.h | 26 ++++++++++++++++++++++++++ thread_pthread.c | 10 +++++----- thread_win32.c | 3 ++- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/internal/sanitizers.h b/internal/sanitizers.h index 7b7d166c747d4e..6b2a1319251a8d 100644 --- a/internal/sanitizers.h +++ b/internal/sanitizers.h @@ -64,6 +64,8 @@ # define __asan_poison_memory_region(x, y) # define __asan_unpoison_memory_region(x, y) # define __asan_region_is_poisoned(x, y) 0 +# define __asan_get_current_fake_stack() NULL +# define __asan_addr_is_in_fake_stack(fake_stack, slot, start, end) NULL #endif #if !__has_feature(memory_sanitizer) @@ -183,4 +185,28 @@ asan_unpoison_object(VALUE obj, bool newobj_p) asan_unpoison_memory_region(ptr, SIZEOF_VALUE, newobj_p); } + +/*! + * Checks if the given pointer is on an ASAN fake stack. If so, it returns the + * address this variable has on the real frame; if not, it returns the origin + * address unmodified. + * + * n.b. - _dereferencing_ the returned address is meaningless and should not + * be done; even though ASAN reserves space for the variable in both the real and + * fake stacks, the _value_ of that variable is only in the fake stack. + * + * n.b. - this only works for addresses passed in from local variables on the same + * thread, because the ASAN fake stacks are threadlocal. + * + * \param[in] slot the address of some local variable + * \retval a pointer to something from that frame on the _real_ machine stack + */ +static inline void * +asan_get_real_stack_addr(void* slot) +{ + VALUE *addr; + addr = __asan_addr_is_in_fake_stack(__asan_get_current_fake_stack(), slot, NULL, NULL); + return addr ? addr : slot; +} + #endif /* INTERNAL_SANITIZERS_H */ diff --git a/thread_pthread.c b/thread_pthread.c index a6a6c9d127e3c6..af50d50699a584 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -12,6 +12,7 @@ #ifdef THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION #include "internal/gc.h" +#include "internal/sanitizers.h" #include "rjit.h" #ifdef HAVE_SYS_RESOURCE_H @@ -1967,6 +1968,7 @@ void ruby_init_stack(volatile void *addr) { native_main_thread.id = pthread_self(); + addr = asan_get_real_stack_addr((void *)addr); #if MAINSTACKADDR_AVAILABLE if (native_main_thread.stack_maxsize) return; @@ -2065,7 +2067,7 @@ native_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame) if (get_stack(&start, &size) == 0) { uintptr_t diff = (uintptr_t)start - (uintptr_t)local_in_parent_frame; - th->ec->machine.stack_start = (uintptr_t)local_in_parent_frame; + th->ec->machine.stack_start = asan_get_real_stack_addr(local_in_parent_frame); th->ec->machine.stack_maxsize = size - diff; } } @@ -2192,12 +2194,10 @@ call_thread_start_func_2(rb_thread_t *th) on a new thread, and replacing that data on fiber-switch would break it (see bug #13887) */ VALUE stack_start = 0; - VALUE *stack_start_addr = &stack_start; + VALUE *stack_start_addr = asan_get_real_stack_addr(&stack_start); + native_thread_init_stack(th, stack_start_addr); thread_start_func_2(th, th->ec->machine.stack_start); - - /* Ensure that stack_start really was spilled to the stack */ - RB_GC_GUARD(stack_start) } static void * diff --git a/thread_win32.c b/thread_win32.c index e92472cea947d4..c2945420032835 100644 --- a/thread_win32.c +++ b/thread_win32.c @@ -11,6 +11,7 @@ #ifdef THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION +#include "internal/sanitizers.h" #include #define TIME_QUANTUM_USEC (10 * 1000) @@ -596,7 +597,7 @@ COMPILER_WARNING_IGNORED(-Wmaybe-uninitialized) static inline SIZE_T query_memory_basic_info(PMEMORY_BASIC_INFORMATION mi, void *local_in_parent_frame) { - return VirtualQuery(local_in_parent_frame, mi, sizeof(*mi)); + return VirtualQuery(asan_get_real_stack_addr(local_in_parent_frame), mi, sizeof(*mi)); } COMPILER_WARNING_POP From 179228cd83a926efcd79ca5d0c6ed6af0c2389c0 Mon Sep 17 00:00:00 2001 From: KJ Tsanaktsidis Date: Sun, 12 Nov 2023 14:47:15 +1100 Subject: [PATCH 085/640] Allow each_stack_location to accept context for the callback This is preparing for a more specialised, asan-aware version of gc_mark_maybe which needs some additional context passed through. [Bug #20001] --- gc.c | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/gc.c b/gc.c index 0e4dadbdd0b39f..6831fd6e14e872 100644 --- a/gc.c +++ b/gc.c @@ -6548,32 +6548,38 @@ ruby_stack_check(void) return stack_check(GET_EC(), STACKFRAME_FOR_CALL_CFUNC); } -ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(static void each_location(rb_objspace_t *objspace, register const VALUE *x, register long n, void (*cb)(rb_objspace_t *, VALUE))); +ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(static void each_location(rb_objspace_t *objspace, register const VALUE *x, register long n, void *ctx, void (*cb)(rb_objspace_t *, void *, VALUE))); static void -each_location(rb_objspace_t *objspace, register const VALUE *x, register long n, void (*cb)(rb_objspace_t *, VALUE)) +each_location(rb_objspace_t *objspace, register const VALUE *x, register long n, void *ctx, void (*cb)(rb_objspace_t *, void *, VALUE)) { VALUE v; while (n--) { v = *x; - cb(objspace, v); + cb(objspace, ctx, v); x++; } } static void -gc_mark_locations(rb_objspace_t *objspace, const VALUE *start, const VALUE *end, void (*cb)(rb_objspace_t *, VALUE)) +gc_mark_locations(rb_objspace_t *objspace, const VALUE *start, const VALUE *end, void *ctx, void (*cb)(rb_objspace_t *, void *, VALUE)) { long n; if (end <= start) return; n = end - start; - each_location(objspace, start, n, cb); + each_location(objspace, start, n, ctx, cb); +} + +static void +gc_mark_maybe_cb(rb_objspace_t *objspace, void *ctx, VALUE obj) +{ + gc_mark_maybe(objspace, obj); } void rb_gc_mark_locations(const VALUE *start, const VALUE *end) { - gc_mark_locations(&rb_objspace, start, end, gc_mark_maybe); + gc_mark_locations(&rb_objspace, start, end, NULL, gc_mark_maybe_cb); } void @@ -6819,7 +6825,8 @@ mark_const_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl) #endif static void each_stack_location(rb_objspace_t *objspace, const rb_execution_context_t *ec, - const VALUE *stack_start, const VALUE *stack_end, void (*cb)(rb_objspace_t *, VALUE)); + const VALUE *stack_start, const VALUE *stack_end, void *ctx, + void (*cb)(rb_objspace_t *, void *, VALUE)); #if defined(__wasm__) @@ -6839,10 +6846,10 @@ static void mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec) { emscripten_scan_stack(rb_mark_locations); - each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe); + each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe_cb); emscripten_scan_registers(rb_mark_locations); - each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe); + each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe_cb); } # else // use Asyncify version @@ -6852,10 +6859,10 @@ mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec VALUE *stack_start, *stack_end; SET_STACK_END; GET_STACK_BOUNDS(stack_start, stack_end, 1); - each_stack_location(objspace, ec, stack_start, stack_end, gc_mark_maybe); + each_stack_location(objspace, ec, stack_start, stack_end, gc_mark_maybe_cb); rb_wasm_scan_locals(rb_mark_locations); - each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe); + each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe_cb); } # endif @@ -6882,40 +6889,41 @@ mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec SET_STACK_END; GET_STACK_BOUNDS(stack_start, stack_end, 1); - each_location(objspace, save_regs_gc_mark.v, numberof(save_regs_gc_mark.v), gc_mark_maybe); + each_location(objspace, save_regs_gc_mark.v, numberof(save_regs_gc_mark.v), NULL, gc_mark_maybe_cb); - each_stack_location(objspace, ec, stack_start, stack_end, gc_mark_maybe); + each_stack_location(objspace, ec, stack_start, stack_end, NULL, gc_mark_maybe_cb); } #endif static void -each_machine_stack_value(const rb_execution_context_t *ec, void (*cb)(rb_objspace_t *, VALUE)) +each_machine_stack_value(const rb_execution_context_t *ec, void *ctx, void (*cb)(rb_objspace_t *, void *, VALUE)) { rb_objspace_t *objspace = &rb_objspace; VALUE *stack_start, *stack_end; GET_STACK_BOUNDS(stack_start, stack_end, 0); RUBY_DEBUG_LOG("ec->th:%u stack_start:%p stack_end:%p", rb_ec_thread_ptr(ec)->serial, stack_start, stack_end); - each_stack_location(objspace, ec, stack_start, stack_end, cb); + each_stack_location(objspace, ec, stack_start, stack_end, ctx, cb); } void rb_gc_mark_machine_stack(const rb_execution_context_t *ec) { - each_machine_stack_value(ec, gc_mark_maybe); + each_machine_stack_value(ec, NULL, gc_mark_maybe_cb); } static void each_stack_location(rb_objspace_t *objspace, const rb_execution_context_t *ec, - const VALUE *stack_start, const VALUE *stack_end, void (*cb)(rb_objspace_t *, VALUE)) + const VALUE *stack_start, const VALUE *stack_end, void *ctx, + void (*cb)(rb_objspace_t *, void *, VALUE)) { - gc_mark_locations(objspace, stack_start, stack_end, cb); + gc_mark_locations(objspace, stack_start, stack_end, ctx, cb); #if defined(__mc68000__) gc_mark_locations(objspace, (VALUE*)((char*)stack_start + 2), - (VALUE*)((char*)stack_end - 2), cb); + (VALUE*)((char*)stack_end - 2), ctx, cb); #endif } From bdafad879093ef16a9a649154c4b2e4ebf492656 Mon Sep 17 00:00:00 2001 From: KJ Tsanaktsidis Date: Sun, 12 Nov 2023 14:57:10 +1100 Subject: [PATCH 086/640] Define special macros for asan/msan being enabled __has_feature is a clang-ism, and GCC has a different way to tell if sanitizers are enabled. For this reason, I don't want to spray __has_feature all over the codebase for other places where conditional compilation based on sanitizers is required. [Bug #20001] --- internal/sanitizers.h | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/internal/sanitizers.h b/internal/sanitizers.h index 6b2a1319251a8d..d444903aa0b36e 100644 --- a/internal/sanitizers.h +++ b/internal/sanitizers.h @@ -16,11 +16,15 @@ #endif #ifdef HAVE_SANITIZER_ASAN_INTERFACE_H -# include +# if __has_feature(address_sanitizer) +# define RUBY_ASAN_ENABLED +# include +# endif #endif #ifdef HAVE_SANITIZER_MSAN_INTERFACE_H # if __has_feature(memory_sanitizer) +# define RUBY_MSAN_ENABLED # include # endif #endif @@ -29,10 +33,10 @@ #include "ruby/ruby.h" /* for VALUE */ #if 0 -#elif __has_feature(memory_sanitizer) && __has_feature(address_sanitizer) +#elif defined(RUBY_ASAN_ENABLED) && defined(RUBY_MSAN_ENABLED) # define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \ __attribute__((__no_sanitize__("memory, address"), __noinline__)) x -#elif __has_feature(address_sanitizer) +#elif defined(RUBY_ASAN_ENABLED) # define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \ __attribute__((__no_sanitize__("address"), __noinline__)) x #elif defined(NO_SANITIZE_ADDRESS) @@ -60,7 +64,7 @@ # define NO_SANITIZE(x, y) y #endif -#if !__has_feature(address_sanitizer) +#ifndef RUBY_ASAN_ENABLED # define __asan_poison_memory_region(x, y) # define __asan_unpoison_memory_region(x, y) # define __asan_region_is_poisoned(x, y) 0 @@ -68,7 +72,7 @@ # define __asan_addr_is_in_fake_stack(fake_stack, slot, start, end) NULL #endif -#if !__has_feature(memory_sanitizer) +#ifndef RUBY_MSAN_ENABLED # define __msan_allocated_memory(x, y) ((void)(x), (void)(y)) # define __msan_poison(x, y) ((void)(x), (void)(y)) # define __msan_unpoison(x, y) ((void)(x), (void)(y)) @@ -123,12 +127,12 @@ asan_poison_object(VALUE obj) asan_poison_memory_region(ptr, SIZEOF_VALUE); } -#if !__has_feature(address_sanitizer) -#define asan_poison_object_if(ptr, obj) ((void)(ptr), (void)(obj)) -#else +#ifdef RUBY_ASAN_ENABLED #define asan_poison_object_if(ptr, obj) do { \ if (ptr) asan_poison_object(obj); \ } while (0) +#else +#define asan_poison_object_if(ptr, obj) ((void)(ptr), (void)(obj)) #endif /*! From d10bc3a2b8300cffc383e10c3730871e851be24c Mon Sep 17 00:00:00 2001 From: KJ Tsanaktsidis Date: Sun, 12 Nov 2023 16:19:31 +1100 Subject: [PATCH 087/640] Mark asan fake stacks during machine stack marking ASAN leaves a pointer to the fake frame on the stack; we can use the __asan_addr_is_in_fake_stack API to work out the extent of the fake stack and thus mark any VALUEs contained therein. [Bug #20001] --- common.mk | 43 +++++++++++++++++++++++++++++ ext/objspace/depend | 1 + ext/ripper/depend | 1 + ext/socket/depend | 15 +++++++++++ gc.c | 33 ++++++++++++++++++----- internal/sanitizers.h | 63 +++++++++++++++++++++++++++++++++++++++++++ thread.c | 3 +++ vm_core.h | 5 ++++ 8 files changed, 157 insertions(+), 7 deletions(-) diff --git a/common.mk b/common.mk index 5a929fc937fbef..90903b9b7aaeb7 100644 --- a/common.mk +++ b/common.mk @@ -2000,6 +2000,7 @@ array.$(OBJEXT): $(top_srcdir)/internal/numeric.h array.$(OBJEXT): $(top_srcdir)/internal/object.h array.$(OBJEXT): $(top_srcdir)/internal/proc.h array.$(OBJEXT): $(top_srcdir)/internal/rational.h +array.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h array.$(OBJEXT): $(top_srcdir)/internal/serial.h array.$(OBJEXT): $(top_srcdir)/internal/static_assert.h array.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -2213,6 +2214,7 @@ ast.$(OBJEXT): $(top_srcdir)/internal/numeric.h ast.$(OBJEXT): $(top_srcdir)/internal/parse.h ast.$(OBJEXT): $(top_srcdir)/internal/rational.h ast.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +ast.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h ast.$(OBJEXT): $(top_srcdir)/internal/serial.h ast.$(OBJEXT): $(top_srcdir)/internal/static_assert.h ast.$(OBJEXT): $(top_srcdir)/internal/symbol.h @@ -2648,6 +2650,7 @@ builtin.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h builtin.$(OBJEXT): $(top_srcdir)/internal/compilers.h builtin.$(OBJEXT): $(top_srcdir)/internal/gc.h builtin.$(OBJEXT): $(top_srcdir)/internal/imemo.h +builtin.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h builtin.$(OBJEXT): $(top_srcdir)/internal/serial.h builtin.$(OBJEXT): $(top_srcdir)/internal/static_assert.h builtin.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -2877,6 +2880,7 @@ class.$(OBJEXT): $(top_srcdir)/internal/gc.h class.$(OBJEXT): $(top_srcdir)/internal/hash.h class.$(OBJEXT): $(top_srcdir)/internal/imemo.h class.$(OBJEXT): $(top_srcdir)/internal/object.h +class.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h class.$(OBJEXT): $(top_srcdir)/internal/serial.h class.$(OBJEXT): $(top_srcdir)/internal/static_assert.h class.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -3274,6 +3278,7 @@ compile.$(OBJEXT): $(top_srcdir)/internal/object.h compile.$(OBJEXT): $(top_srcdir)/internal/rational.h compile.$(OBJEXT): $(top_srcdir)/internal/re.h compile.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +compile.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h compile.$(OBJEXT): $(top_srcdir)/internal/serial.h compile.$(OBJEXT): $(top_srcdir)/internal/static_assert.h compile.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -3527,6 +3532,7 @@ complex.$(OBJEXT): $(top_srcdir)/internal/math.h complex.$(OBJEXT): $(top_srcdir)/internal/numeric.h complex.$(OBJEXT): $(top_srcdir)/internal/object.h complex.$(OBJEXT): $(top_srcdir)/internal/rational.h +complex.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h complex.$(OBJEXT): $(top_srcdir)/internal/serial.h complex.$(OBJEXT): $(top_srcdir)/internal/static_assert.h complex.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -3971,6 +3977,7 @@ debug.$(OBJEXT): $(top_srcdir)/internal/class.h debug.$(OBJEXT): $(top_srcdir)/internal/compilers.h debug.$(OBJEXT): $(top_srcdir)/internal/gc.h debug.$(OBJEXT): $(top_srcdir)/internal/imemo.h +debug.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h debug.$(OBJEXT): $(top_srcdir)/internal/serial.h debug.$(OBJEXT): $(top_srcdir)/internal/signal.h debug.$(OBJEXT): $(top_srcdir)/internal/static_assert.h @@ -4348,6 +4355,7 @@ dir.$(OBJEXT): $(top_srcdir)/internal/gc.h dir.$(OBJEXT): $(top_srcdir)/internal/imemo.h dir.$(OBJEXT): $(top_srcdir)/internal/io.h dir.$(OBJEXT): $(top_srcdir)/internal/object.h +dir.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h dir.$(OBJEXT): $(top_srcdir)/internal/serial.h dir.$(OBJEXT): $(top_srcdir)/internal/static_assert.h dir.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -6271,6 +6279,7 @@ enumerator.$(OBJEXT): $(top_srcdir)/internal/imemo.h enumerator.$(OBJEXT): $(top_srcdir)/internal/numeric.h enumerator.$(OBJEXT): $(top_srcdir)/internal/range.h enumerator.$(OBJEXT): $(top_srcdir)/internal/rational.h +enumerator.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h enumerator.$(OBJEXT): $(top_srcdir)/internal/serial.h enumerator.$(OBJEXT): $(top_srcdir)/internal/static_assert.h enumerator.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -6483,6 +6492,7 @@ error.$(OBJEXT): $(top_srcdir)/internal/io.h error.$(OBJEXT): $(top_srcdir)/internal/load.h error.$(OBJEXT): $(top_srcdir)/internal/object.h error.$(OBJEXT): $(top_srcdir)/internal/process.h +error.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h error.$(OBJEXT): $(top_srcdir)/internal/serial.h error.$(OBJEXT): $(top_srcdir)/internal/static_assert.h error.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -6699,6 +6709,7 @@ eval.$(OBJEXT): $(top_srcdir)/internal/imemo.h eval.$(OBJEXT): $(top_srcdir)/internal/inits.h eval.$(OBJEXT): $(top_srcdir)/internal/io.h eval.$(OBJEXT): $(top_srcdir)/internal/object.h +eval.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h eval.$(OBJEXT): $(top_srcdir)/internal/serial.h eval.$(OBJEXT): $(top_srcdir)/internal/static_assert.h eval.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -7434,6 +7445,7 @@ goruby.$(OBJEXT): $(top_srcdir)/internal/imemo.h goruby.$(OBJEXT): $(top_srcdir)/internal/numeric.h goruby.$(OBJEXT): $(top_srcdir)/internal/rational.h goruby.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +goruby.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h goruby.$(OBJEXT): $(top_srcdir)/internal/serial.h goruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h goruby.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -7670,6 +7682,7 @@ hash.$(OBJEXT): $(top_srcdir)/internal/hash.h hash.$(OBJEXT): $(top_srcdir)/internal/imemo.h hash.$(OBJEXT): $(top_srcdir)/internal/object.h hash.$(OBJEXT): $(top_srcdir)/internal/proc.h +hash.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h hash.$(OBJEXT): $(top_srcdir)/internal/serial.h hash.$(OBJEXT): $(top_srcdir)/internal/st.h hash.$(OBJEXT): $(top_srcdir)/internal/static_assert.h @@ -8082,6 +8095,7 @@ io.$(OBJEXT): $(top_srcdir)/internal/io.h io.$(OBJEXT): $(top_srcdir)/internal/numeric.h io.$(OBJEXT): $(top_srcdir)/internal/object.h io.$(OBJEXT): $(top_srcdir)/internal/process.h +io.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h io.$(OBJEXT): $(top_srcdir)/internal/serial.h io.$(OBJEXT): $(top_srcdir)/internal/static_assert.h io.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -8756,6 +8770,7 @@ load.$(OBJEXT): $(top_srcdir)/internal/numeric.h load.$(OBJEXT): $(top_srcdir)/internal/parse.h load.$(OBJEXT): $(top_srcdir)/internal/rational.h load.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +load.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h load.$(OBJEXT): $(top_srcdir)/internal/serial.h load.$(OBJEXT): $(top_srcdir)/internal/static_assert.h load.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -9485,6 +9500,7 @@ marshal.$(OBJEXT): $(top_srcdir)/internal/hash.h marshal.$(OBJEXT): $(top_srcdir)/internal/imemo.h marshal.$(OBJEXT): $(top_srcdir)/internal/numeric.h marshal.$(OBJEXT): $(top_srcdir)/internal/object.h +marshal.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h marshal.$(OBJEXT): $(top_srcdir)/internal/serial.h marshal.$(OBJEXT): $(top_srcdir)/internal/static_assert.h marshal.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -9869,6 +9885,7 @@ memory_view.$(OBJEXT): $(top_srcdir)/internal/compilers.h memory_view.$(OBJEXT): $(top_srcdir)/internal/gc.h memory_view.$(OBJEXT): $(top_srcdir)/internal/hash.h memory_view.$(OBJEXT): $(top_srcdir)/internal/imemo.h +memory_view.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h memory_view.$(OBJEXT): $(top_srcdir)/internal/serial.h memory_view.$(OBJEXT): $(top_srcdir)/internal/static_assert.h memory_view.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -10080,6 +10097,7 @@ miniinit.$(OBJEXT): $(top_srcdir)/internal/imemo.h miniinit.$(OBJEXT): $(top_srcdir)/internal/numeric.h miniinit.$(OBJEXT): $(top_srcdir)/internal/rational.h miniinit.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h miniinit.$(OBJEXT): $(top_srcdir)/internal/serial.h miniinit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h miniinit.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -10328,6 +10346,7 @@ node.$(OBJEXT): $(top_srcdir)/internal/compilers.h node.$(OBJEXT): $(top_srcdir)/internal/gc.h node.$(OBJEXT): $(top_srcdir)/internal/hash.h node.$(OBJEXT): $(top_srcdir)/internal/imemo.h +node.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h node.$(OBJEXT): $(top_srcdir)/internal/serial.h node.$(OBJEXT): $(top_srcdir)/internal/static_assert.h node.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -10535,6 +10554,7 @@ node_dump.$(OBJEXT): $(top_srcdir)/internal/imemo.h node_dump.$(OBJEXT): $(top_srcdir)/internal/numeric.h node_dump.$(OBJEXT): $(top_srcdir)/internal/rational.h node_dump.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +node_dump.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h node_dump.$(OBJEXT): $(top_srcdir)/internal/serial.h node_dump.$(OBJEXT): $(top_srcdir)/internal/static_assert.h node_dump.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -10743,6 +10763,7 @@ numeric.$(OBJEXT): $(top_srcdir)/internal/imemo.h numeric.$(OBJEXT): $(top_srcdir)/internal/numeric.h numeric.$(OBJEXT): $(top_srcdir)/internal/object.h numeric.$(OBJEXT): $(top_srcdir)/internal/rational.h +numeric.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h numeric.$(OBJEXT): $(top_srcdir)/internal/serial.h numeric.$(OBJEXT): $(top_srcdir)/internal/static_assert.h numeric.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -10956,6 +10977,7 @@ object.$(OBJEXT): $(top_srcdir)/internal/imemo.h object.$(OBJEXT): $(top_srcdir)/internal/inits.h object.$(OBJEXT): $(top_srcdir)/internal/numeric.h object.$(OBJEXT): $(top_srcdir)/internal/object.h +object.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h object.$(OBJEXT): $(top_srcdir)/internal/serial.h object.$(OBJEXT): $(top_srcdir)/internal/st.h object.$(OBJEXT): $(top_srcdir)/internal/static_assert.h @@ -11170,6 +11192,7 @@ pack.$(OBJEXT): $(top_srcdir)/internal/bits.h pack.$(OBJEXT): $(top_srcdir)/internal/compilers.h pack.$(OBJEXT): $(top_srcdir)/internal/gc.h pack.$(OBJEXT): $(top_srcdir)/internal/imemo.h +pack.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h pack.$(OBJEXT): $(top_srcdir)/internal/serial.h pack.$(OBJEXT): $(top_srcdir)/internal/static_assert.h pack.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -11389,6 +11412,7 @@ parse.$(OBJEXT): $(top_srcdir)/internal/parse.h parse.$(OBJEXT): $(top_srcdir)/internal/rational.h parse.$(OBJEXT): $(top_srcdir)/internal/re.h parse.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +parse.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h parse.$(OBJEXT): $(top_srcdir)/internal/serial.h parse.$(OBJEXT): $(top_srcdir)/internal/static_assert.h parse.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -12641,6 +12665,7 @@ proc.$(OBJEXT): $(top_srcdir)/internal/gc.h proc.$(OBJEXT): $(top_srcdir)/internal/imemo.h proc.$(OBJEXT): $(top_srcdir)/internal/object.h proc.$(OBJEXT): $(top_srcdir)/internal/proc.h +proc.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h proc.$(OBJEXT): $(top_srcdir)/internal/serial.h proc.$(OBJEXT): $(top_srcdir)/internal/static_assert.h proc.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -12885,6 +12910,7 @@ process.$(OBJEXT): $(top_srcdir)/internal/io.h process.$(OBJEXT): $(top_srcdir)/internal/numeric.h process.$(OBJEXT): $(top_srcdir)/internal/object.h process.$(OBJEXT): $(top_srcdir)/internal/process.h +process.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h process.$(OBJEXT): $(top_srcdir)/internal/serial.h process.$(OBJEXT): $(top_srcdir)/internal/static_assert.h process.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -13107,6 +13133,7 @@ ractor.$(OBJEXT): $(top_srcdir)/internal/hash.h ractor.$(OBJEXT): $(top_srcdir)/internal/imemo.h ractor.$(OBJEXT): $(top_srcdir)/internal/numeric.h ractor.$(OBJEXT): $(top_srcdir)/internal/rational.h +ractor.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h ractor.$(OBJEXT): $(top_srcdir)/internal/serial.h ractor.$(OBJEXT): $(top_srcdir)/internal/static_assert.h ractor.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -13729,6 +13756,7 @@ rational.$(OBJEXT): $(top_srcdir)/internal/imemo.h rational.$(OBJEXT): $(top_srcdir)/internal/numeric.h rational.$(OBJEXT): $(top_srcdir)/internal/object.h rational.$(OBJEXT): $(top_srcdir)/internal/rational.h +rational.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h rational.$(OBJEXT): $(top_srcdir)/internal/serial.h rational.$(OBJEXT): $(top_srcdir)/internal/static_assert.h rational.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -13935,6 +13963,7 @@ re.$(OBJEXT): $(top_srcdir)/internal/imemo.h re.$(OBJEXT): $(top_srcdir)/internal/object.h re.$(OBJEXT): $(top_srcdir)/internal/ractor.h re.$(OBJEXT): $(top_srcdir)/internal/re.h +re.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h re.$(OBJEXT): $(top_srcdir)/internal/serial.h re.$(OBJEXT): $(top_srcdir)/internal/static_assert.h re.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -15118,6 +15147,7 @@ rjit.$(OBJEXT): $(top_srcdir)/internal/gc.h rjit.$(OBJEXT): $(top_srcdir)/internal/hash.h rjit.$(OBJEXT): $(top_srcdir)/internal/imemo.h rjit.$(OBJEXT): $(top_srcdir)/internal/process.h +rjit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h rjit.$(OBJEXT): $(top_srcdir)/internal/serial.h rjit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h rjit.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -15647,6 +15677,7 @@ ruby.$(OBJEXT): $(top_srcdir)/internal/object.h ruby.$(OBJEXT): $(top_srcdir)/internal/parse.h ruby.$(OBJEXT): $(top_srcdir)/internal/rational.h ruby.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +ruby.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h ruby.$(OBJEXT): $(top_srcdir)/internal/serial.h ruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h ruby.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -16065,6 +16096,7 @@ scheduler.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h scheduler.$(OBJEXT): $(top_srcdir)/internal/compilers.h scheduler.$(OBJEXT): $(top_srcdir)/internal/gc.h scheduler.$(OBJEXT): $(top_srcdir)/internal/imemo.h +scheduler.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h scheduler.$(OBJEXT): $(top_srcdir)/internal/serial.h scheduler.$(OBJEXT): $(top_srcdir)/internal/static_assert.h scheduler.$(OBJEXT): $(top_srcdir)/internal/thread.h @@ -16429,6 +16461,7 @@ shape.$(OBJEXT): $(top_srcdir)/internal/error.h shape.$(OBJEXT): $(top_srcdir)/internal/gc.h shape.$(OBJEXT): $(top_srcdir)/internal/imemo.h shape.$(OBJEXT): $(top_srcdir)/internal/object.h +shape.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h shape.$(OBJEXT): $(top_srcdir)/internal/serial.h shape.$(OBJEXT): $(top_srcdir)/internal/static_assert.h shape.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -17645,6 +17678,7 @@ struct.$(OBJEXT): $(top_srcdir)/internal/hash.h struct.$(OBJEXT): $(top_srcdir)/internal/imemo.h struct.$(OBJEXT): $(top_srcdir)/internal/object.h struct.$(OBJEXT): $(top_srcdir)/internal/proc.h +struct.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h struct.$(OBJEXT): $(top_srcdir)/internal/serial.h struct.$(OBJEXT): $(top_srcdir)/internal/static_assert.h struct.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -17855,6 +17889,7 @@ symbol.$(OBJEXT): $(top_srcdir)/internal/gc.h symbol.$(OBJEXT): $(top_srcdir)/internal/hash.h symbol.$(OBJEXT): $(top_srcdir)/internal/imemo.h symbol.$(OBJEXT): $(top_srcdir)/internal/object.h +symbol.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h symbol.$(OBJEXT): $(top_srcdir)/internal/serial.h symbol.$(OBJEXT): $(top_srcdir)/internal/static_assert.h symbol.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -18076,6 +18111,7 @@ thread.$(OBJEXT): $(top_srcdir)/internal/imemo.h thread.$(OBJEXT): $(top_srcdir)/internal/io.h thread.$(OBJEXT): $(top_srcdir)/internal/object.h thread.$(OBJEXT): $(top_srcdir)/internal/proc.h +thread.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h thread.$(OBJEXT): $(top_srcdir)/internal/serial.h thread.$(OBJEXT): $(top_srcdir)/internal/signal.h thread.$(OBJEXT): $(top_srcdir)/internal/static_assert.h @@ -18329,6 +18365,7 @@ time.$(OBJEXT): $(top_srcdir)/internal/hash.h time.$(OBJEXT): $(top_srcdir)/internal/imemo.h time.$(OBJEXT): $(top_srcdir)/internal/numeric.h time.$(OBJEXT): $(top_srcdir)/internal/rational.h +time.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h time.$(OBJEXT): $(top_srcdir)/internal/serial.h time.$(OBJEXT): $(top_srcdir)/internal/static_assert.h time.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -18892,6 +18929,7 @@ variable.$(OBJEXT): $(top_srcdir)/internal/hash.h variable.$(OBJEXT): $(top_srcdir)/internal/imemo.h variable.$(OBJEXT): $(top_srcdir)/internal/object.h variable.$(OBJEXT): $(top_srcdir)/internal/re.h +variable.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h variable.$(OBJEXT): $(top_srcdir)/internal/serial.h variable.$(OBJEXT): $(top_srcdir)/internal/static_assert.h variable.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -19104,6 +19142,7 @@ version.$(OBJEXT): $(top_srcdir)/internal/cmdlineopt.h version.$(OBJEXT): $(top_srcdir)/internal/compilers.h version.$(OBJEXT): $(top_srcdir)/internal/gc.h version.$(OBJEXT): $(top_srcdir)/internal/imemo.h +version.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h version.$(OBJEXT): $(top_srcdir)/internal/serial.h version.$(OBJEXT): $(top_srcdir)/internal/static_assert.h version.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -19592,6 +19631,7 @@ vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/compilers.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/error.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/gc.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/imemo.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/serial.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/static_assert.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -19821,6 +19861,7 @@ vm_dump.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/compilers.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/gc.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/imemo.h +vm_dump.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/serial.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/static_assert.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -20049,6 +20090,7 @@ vm_sync.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/compilers.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/gc.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/imemo.h +vm_sync.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/serial.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/static_assert.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/thread.h @@ -20257,6 +20299,7 @@ vm_trace.$(OBJEXT): $(top_srcdir)/internal/compilers.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/gc.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/hash.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/imemo.h +vm_trace.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/serial.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/static_assert.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/symbol.h diff --git a/ext/objspace/depend b/ext/objspace/depend index 85e99a71b4149a..aa0c5c5d7dd1b9 100644 --- a/ext/objspace/depend +++ b/ext/objspace/depend @@ -182,6 +182,7 @@ object_tracing.o: $(top_srcdir)/internal/basic_operators.h object_tracing.o: $(top_srcdir)/internal/compilers.h object_tracing.o: $(top_srcdir)/internal/gc.h object_tracing.o: $(top_srcdir)/internal/imemo.h +object_tracing.o: $(top_srcdir)/internal/sanitizers.h object_tracing.o: $(top_srcdir)/internal/serial.h object_tracing.o: $(top_srcdir)/internal/static_assert.h object_tracing.o: $(top_srcdir)/internal/vm.h diff --git a/ext/ripper/depend b/ext/ripper/depend index a07825fd405de8..3b9b890de8347a 100644 --- a/ext/ripper/depend +++ b/ext/ripper/depend @@ -593,6 +593,7 @@ ripper.o: $(top_srcdir)/internal/parse.h ripper.o: $(top_srcdir)/internal/rational.h ripper.o: $(top_srcdir)/internal/re.h ripper.o: $(top_srcdir)/internal/ruby_parser.h +ripper.o: $(top_srcdir)/internal/sanitizers.h ripper.o: $(top_srcdir)/internal/serial.h ripper.o: $(top_srcdir)/internal/static_assert.h ripper.o: $(top_srcdir)/internal/string.h diff --git a/ext/socket/depend b/ext/socket/depend index 3db153bb1ccbf5..e95555ea921a41 100644 --- a/ext/socket/depend +++ b/ext/socket/depend @@ -199,6 +199,7 @@ ancdata.o: $(top_srcdir)/internal/error.h ancdata.o: $(top_srcdir)/internal/gc.h ancdata.o: $(top_srcdir)/internal/imemo.h ancdata.o: $(top_srcdir)/internal/io.h +ancdata.o: $(top_srcdir)/internal/sanitizers.h ancdata.o: $(top_srcdir)/internal/serial.h ancdata.o: $(top_srcdir)/internal/static_assert.h ancdata.o: $(top_srcdir)/internal/string.h @@ -408,6 +409,7 @@ basicsocket.o: $(top_srcdir)/internal/error.h basicsocket.o: $(top_srcdir)/internal/gc.h basicsocket.o: $(top_srcdir)/internal/imemo.h basicsocket.o: $(top_srcdir)/internal/io.h +basicsocket.o: $(top_srcdir)/internal/sanitizers.h basicsocket.o: $(top_srcdir)/internal/serial.h basicsocket.o: $(top_srcdir)/internal/static_assert.h basicsocket.o: $(top_srcdir)/internal/string.h @@ -617,6 +619,7 @@ constants.o: $(top_srcdir)/internal/error.h constants.o: $(top_srcdir)/internal/gc.h constants.o: $(top_srcdir)/internal/imemo.h constants.o: $(top_srcdir)/internal/io.h +constants.o: $(top_srcdir)/internal/sanitizers.h constants.o: $(top_srcdir)/internal/serial.h constants.o: $(top_srcdir)/internal/static_assert.h constants.o: $(top_srcdir)/internal/string.h @@ -827,6 +830,7 @@ ifaddr.o: $(top_srcdir)/internal/error.h ifaddr.o: $(top_srcdir)/internal/gc.h ifaddr.o: $(top_srcdir)/internal/imemo.h ifaddr.o: $(top_srcdir)/internal/io.h +ifaddr.o: $(top_srcdir)/internal/sanitizers.h ifaddr.o: $(top_srcdir)/internal/serial.h ifaddr.o: $(top_srcdir)/internal/static_assert.h ifaddr.o: $(top_srcdir)/internal/string.h @@ -1036,6 +1040,7 @@ init.o: $(top_srcdir)/internal/error.h init.o: $(top_srcdir)/internal/gc.h init.o: $(top_srcdir)/internal/imemo.h init.o: $(top_srcdir)/internal/io.h +init.o: $(top_srcdir)/internal/sanitizers.h init.o: $(top_srcdir)/internal/serial.h init.o: $(top_srcdir)/internal/static_assert.h init.o: $(top_srcdir)/internal/string.h @@ -1245,6 +1250,7 @@ ipsocket.o: $(top_srcdir)/internal/error.h ipsocket.o: $(top_srcdir)/internal/gc.h ipsocket.o: $(top_srcdir)/internal/imemo.h ipsocket.o: $(top_srcdir)/internal/io.h +ipsocket.o: $(top_srcdir)/internal/sanitizers.h ipsocket.o: $(top_srcdir)/internal/serial.h ipsocket.o: $(top_srcdir)/internal/static_assert.h ipsocket.o: $(top_srcdir)/internal/string.h @@ -1454,6 +1460,7 @@ option.o: $(top_srcdir)/internal/error.h option.o: $(top_srcdir)/internal/gc.h option.o: $(top_srcdir)/internal/imemo.h option.o: $(top_srcdir)/internal/io.h +option.o: $(top_srcdir)/internal/sanitizers.h option.o: $(top_srcdir)/internal/serial.h option.o: $(top_srcdir)/internal/static_assert.h option.o: $(top_srcdir)/internal/string.h @@ -1663,6 +1670,7 @@ raddrinfo.o: $(top_srcdir)/internal/error.h raddrinfo.o: $(top_srcdir)/internal/gc.h raddrinfo.o: $(top_srcdir)/internal/imemo.h raddrinfo.o: $(top_srcdir)/internal/io.h +raddrinfo.o: $(top_srcdir)/internal/sanitizers.h raddrinfo.o: $(top_srcdir)/internal/serial.h raddrinfo.o: $(top_srcdir)/internal/static_assert.h raddrinfo.o: $(top_srcdir)/internal/string.h @@ -1872,6 +1880,7 @@ socket.o: $(top_srcdir)/internal/error.h socket.o: $(top_srcdir)/internal/gc.h socket.o: $(top_srcdir)/internal/imemo.h socket.o: $(top_srcdir)/internal/io.h +socket.o: $(top_srcdir)/internal/sanitizers.h socket.o: $(top_srcdir)/internal/serial.h socket.o: $(top_srcdir)/internal/static_assert.h socket.o: $(top_srcdir)/internal/string.h @@ -2081,6 +2090,7 @@ sockssocket.o: $(top_srcdir)/internal/error.h sockssocket.o: $(top_srcdir)/internal/gc.h sockssocket.o: $(top_srcdir)/internal/imemo.h sockssocket.o: $(top_srcdir)/internal/io.h +sockssocket.o: $(top_srcdir)/internal/sanitizers.h sockssocket.o: $(top_srcdir)/internal/serial.h sockssocket.o: $(top_srcdir)/internal/static_assert.h sockssocket.o: $(top_srcdir)/internal/string.h @@ -2290,6 +2300,7 @@ tcpserver.o: $(top_srcdir)/internal/error.h tcpserver.o: $(top_srcdir)/internal/gc.h tcpserver.o: $(top_srcdir)/internal/imemo.h tcpserver.o: $(top_srcdir)/internal/io.h +tcpserver.o: $(top_srcdir)/internal/sanitizers.h tcpserver.o: $(top_srcdir)/internal/serial.h tcpserver.o: $(top_srcdir)/internal/static_assert.h tcpserver.o: $(top_srcdir)/internal/string.h @@ -2499,6 +2510,7 @@ tcpsocket.o: $(top_srcdir)/internal/error.h tcpsocket.o: $(top_srcdir)/internal/gc.h tcpsocket.o: $(top_srcdir)/internal/imemo.h tcpsocket.o: $(top_srcdir)/internal/io.h +tcpsocket.o: $(top_srcdir)/internal/sanitizers.h tcpsocket.o: $(top_srcdir)/internal/serial.h tcpsocket.o: $(top_srcdir)/internal/static_assert.h tcpsocket.o: $(top_srcdir)/internal/string.h @@ -2708,6 +2720,7 @@ udpsocket.o: $(top_srcdir)/internal/error.h udpsocket.o: $(top_srcdir)/internal/gc.h udpsocket.o: $(top_srcdir)/internal/imemo.h udpsocket.o: $(top_srcdir)/internal/io.h +udpsocket.o: $(top_srcdir)/internal/sanitizers.h udpsocket.o: $(top_srcdir)/internal/serial.h udpsocket.o: $(top_srcdir)/internal/static_assert.h udpsocket.o: $(top_srcdir)/internal/string.h @@ -2917,6 +2930,7 @@ unixserver.o: $(top_srcdir)/internal/error.h unixserver.o: $(top_srcdir)/internal/gc.h unixserver.o: $(top_srcdir)/internal/imemo.h unixserver.o: $(top_srcdir)/internal/io.h +unixserver.o: $(top_srcdir)/internal/sanitizers.h unixserver.o: $(top_srcdir)/internal/serial.h unixserver.o: $(top_srcdir)/internal/static_assert.h unixserver.o: $(top_srcdir)/internal/string.h @@ -3126,6 +3140,7 @@ unixsocket.o: $(top_srcdir)/internal/error.h unixsocket.o: $(top_srcdir)/internal/gc.h unixsocket.o: $(top_srcdir)/internal/imemo.h unixsocket.o: $(top_srcdir)/internal/io.h +unixsocket.o: $(top_srcdir)/internal/sanitizers.h unixsocket.o: $(top_srcdir)/internal/serial.h unixsocket.o: $(top_srcdir)/internal/static_assert.h unixsocket.o: $(top_srcdir)/internal/string.h diff --git a/gc.c b/gc.c index 6831fd6e14e872..a16b68e2e765b2 100644 --- a/gc.c +++ b/gc.c @@ -6828,6 +6828,25 @@ static void each_stack_location(rb_objspace_t *objspace, const rb_execution_cont const VALUE *stack_start, const VALUE *stack_end, void *ctx, void (*cb)(rb_objspace_t *, void *, VALUE)); +static void +gc_mark_machine_stack_location_maybe(rb_objspace_t *objspace, void *ctx, VALUE obj) +{ + gc_mark_maybe(objspace, obj); +#ifdef RUBY_ASAN_ENABLED + rb_execution_context_t *ec = ctx; + void *fake_frame_start; + void *fake_frame_end; + bool is_fake_frame = asan_get_fake_stack_extents( + ec->thread_ptr->asan_fake_stack_handle, obj, + ec->machine.stack_start, ec->machine.stack_end, + &fake_frame_start, &fake_frame_end + ); + if (is_fake_frame) { + each_stack_location(objspace, ec, fake_frame_start, fake_frame_end, NULL, gc_mark_maybe_cb); + } +#endif +} + #if defined(__wasm__) @@ -6846,10 +6865,10 @@ static void mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec) { emscripten_scan_stack(rb_mark_locations); - each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe_cb); + each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], NULL, gc_mark_maybe_cb); emscripten_scan_registers(rb_mark_locations); - each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe_cb); + each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], NULL, gc_mark_maybe_cb); } # else // use Asyncify version @@ -6859,10 +6878,10 @@ mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec VALUE *stack_start, *stack_end; SET_STACK_END; GET_STACK_BOUNDS(stack_start, stack_end, 1); - each_stack_location(objspace, ec, stack_start, stack_end, gc_mark_maybe_cb); + each_stack_location(objspace, ec, stack_start, stack_end, NULL, gc_mark_maybe_cb); rb_wasm_scan_locals(rb_mark_locations); - each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe_cb); + each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], NULL, gc_mark_maybe_cb); } # endif @@ -6889,9 +6908,9 @@ mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec SET_STACK_END; GET_STACK_BOUNDS(stack_start, stack_end, 1); - each_location(objspace, save_regs_gc_mark.v, numberof(save_regs_gc_mark.v), NULL, gc_mark_maybe_cb); + each_location(objspace, save_regs_gc_mark.v, numberof(save_regs_gc_mark.v), (void *)ec, gc_mark_machine_stack_location_maybe); - each_stack_location(objspace, ec, stack_start, stack_end, NULL, gc_mark_maybe_cb); + each_stack_location(objspace, ec, stack_start, stack_end, (void *)ec, gc_mark_machine_stack_location_maybe); } #endif @@ -6909,7 +6928,7 @@ each_machine_stack_value(const rb_execution_context_t *ec, void *ctx, void (*cb) void rb_gc_mark_machine_stack(const rb_execution_context_t *ec) { - each_machine_stack_value(ec, NULL, gc_mark_maybe_cb); + each_machine_stack_value(ec, (void *)ec, gc_mark_machine_stack_location_maybe); } static void diff --git a/internal/sanitizers.h b/internal/sanitizers.h index d444903aa0b36e..3fc31b350e8d10 100644 --- a/internal/sanitizers.h +++ b/internal/sanitizers.h @@ -213,4 +213,67 @@ asan_get_real_stack_addr(void* slot) return addr ? addr : slot; } +/*! + * Gets the current thread's fake stack handle, which can be passed into get_fake_stack_extents + * + * \retval An opaque value which can be passed to asan_get_fake_stack_extents + */ +static inline void * +asan_get_thread_fake_stack_handle(void) +{ + return __asan_get_current_fake_stack(); +} + +/*! + * Checks if the given VALUE _actually_ represents a pointer to an ASAN fake stack. + * + * If the given slot _is_ actually a reference to an ASAN fake stack, and that fake stack + * contains the real values for the passed-in range of machine stack addresses, returns true + * and the range of the fake stack through the outparams. + * + * Otherwise, returns false, and sets the outparams to NULL. + * + * Note that this function expects "start" to be > "end" on downward-growing stack architectures; + * + * \param[in] thread_fake_stack_handle The asan fake stack reference for the thread we're scanning + * \param[in] slot The value on the machine stack we want to inspect + * \param[in] machine_stack_start The extents of the real machine stack on which slot lives + * \param[in] machine_stack_end The extents of the real machine stack on which slot lives + * \param[out] fake_stack_start_out The extents of the fake stack which contains real VALUEs + * \param[out] fake_stack_end_out The extents of the fake stack which contains real VALUEs + * \return Whether slot is a pointer to a fake stack for the given machine stack range +*/ + +static inline bool +asan_get_fake_stack_extents(void *thread_fake_stack_handle, VALUE slot, + void *machine_stack_start, void *machine_stack_end, + void **fake_stack_start_out, void **fake_stack_end_out) +{ + /* the ifdef is needed here to suppress a warning about fake_frame_{start/end} being + uninitialized if __asan_addr_is_in_fake_stack is an empty macro */ +#ifdef RUBY_ASAN_ENABLED + void *fake_frame_start; + void *fake_frame_end; + void *real_stack_frame = __asan_addr_is_in_fake_stack( + thread_fake_stack_handle, (void *)slot, &fake_frame_start, &fake_frame_end + ); + if (real_stack_frame) { + bool in_range; +#if STACK_GROW_DIRECTION < 0 + in_range = machine_stack_start >= real_stack_frame && real_stack_frame >= machine_stack_end; +#else + in_range = machine_stack_start <= real_stack_frame && real_stack_frame <= machine_stack_end; +#endif + if (in_range) { + *fake_stack_start_out = fake_frame_start; + *fake_stack_end_out = fake_frame_end; + return true; + } + } +#endif + *fake_stack_start_out = 0; + *fake_stack_end_out = 0; + return false; +} + #endif /* INTERNAL_SANITIZERS_H */ diff --git a/thread.c b/thread.c index e7a9d7cd9bdcc7..27a6ffb95589d1 100644 --- a/thread.c +++ b/thread.c @@ -525,6 +525,9 @@ void ruby_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame) { native_thread_init_stack(th, local_in_parent_frame); +#ifdef RUBY_ASAN_ENABLED + th->asan_fake_stack_handle = asan_get_thread_fake_stack_handle(); +#endif } const VALUE * diff --git a/vm_core.h b/vm_core.h index 91cfae77e9e7ee..9557004dbc8594 100644 --- a/vm_core.h +++ b/vm_core.h @@ -94,6 +94,7 @@ extern int ruby_assert_critical_section_entered; #include "internal.h" #include "internal/array.h" #include "internal/basic_operators.h" +#include "internal/sanitizers.h" #include "internal/serial.h" #include "internal/vm.h" #include "method.h" @@ -1155,6 +1156,10 @@ typedef struct rb_thread_struct { void **specific_storage; struct rb_ext_config ext_config; + +#ifdef RUBY_ASAN_ENABLED + void *asan_fake_stack_handle; +#endif } rb_thread_t; static inline unsigned int From 51ba65493905fe066e6745c745c5ada069d629a2 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 12 Jan 2024 15:26:50 +0900 Subject: [PATCH 088/640] Set prerelease flag if tag includes preview or rc --- tool/gen-github-release.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tool/gen-github-release.rb b/tool/gen-github-release.rb index e36aadcfa7e014..cdb66080d93470 100755 --- a/tool/gen-github-release.rb +++ b/tool/gen-github-release.rb @@ -58,7 +58,8 @@ if ARGV[2] == "--no-dry-run" name = ARGV[1].gsub(/^v/, "").gsub(/_/, ".") - client.create_release("ruby/ruby", ARGV[1], name: name, body: note, make_latest: "false") + prerelease = ARGV[1].match?(/rc|preview/) ? true : false + client.create_release("ruby/ruby", ARGV[1], name: name, body: note, make_latest: "false", prerelease: prerelease) puts "Created a release: https://github.com/ruby/ruby/releases/tag/#{ARGV[1]}" else puts note From 18d85af9698522d6ce356a070a9bd01906a8aaed Mon Sep 17 00:00:00 2001 From: git Date: Fri, 12 Jan 2024 06:58:39 +0000 Subject: [PATCH 089/640] Update bundled gems list as of 2024-01-12 --- NEWS.md | 1 + gems/bundled_gems | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 4caa78d8216fa4..6e2dcc6d247add 100644 --- a/NEWS.md +++ b/NEWS.md @@ -30,6 +30,7 @@ The following default gems are updated. The following bundled gems are updated. +* minitest 5.21.1 * net-ftp 0.3.4 * net-imap 0.4.9.1 * net-smtp 0.4.0.1 diff --git a/gems/bundled_gems b/gems/bundled_gems index caa0469c54e138..22a52318f39137 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -5,7 +5,7 @@ # - repository-url: URL from where clone for test # - revision: revision in repository-url to test # if `revision` is not given, "v"+`version` or `version` will be used. -minitest 5.20.0 https://github.com/minitest/minitest +minitest 5.21.1 https://github.com/minitest/minitest power_assert 2.0.3 https://github.com/ruby/power_assert rake 13.1.0 https://github.com/ruby/rake test-unit 3.6.1 https://github.com/test-unit/test-unit From 688a6ff51053ddebaf4c34dbf74ac0e5f026157b Mon Sep 17 00:00:00 2001 From: KJ Tsanaktsidis Date: Fri, 12 Jan 2024 17:32:16 +1100 Subject: [PATCH 090/640] Revert "Mark asan fake stacks during machine stack marking" This reverts commit d10bc3a2b8300cffc383e10c3730871e851be24c. --- common.mk | 43 ----------------------------- ext/objspace/depend | 1 - ext/ripper/depend | 1 - ext/socket/depend | 15 ----------- gc.c | 33 +++++------------------ internal/sanitizers.h | 63 ------------------------------------------- thread.c | 3 --- vm_core.h | 5 ---- 8 files changed, 7 insertions(+), 157 deletions(-) diff --git a/common.mk b/common.mk index 90903b9b7aaeb7..5a929fc937fbef 100644 --- a/common.mk +++ b/common.mk @@ -2000,7 +2000,6 @@ array.$(OBJEXT): $(top_srcdir)/internal/numeric.h array.$(OBJEXT): $(top_srcdir)/internal/object.h array.$(OBJEXT): $(top_srcdir)/internal/proc.h array.$(OBJEXT): $(top_srcdir)/internal/rational.h -array.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h array.$(OBJEXT): $(top_srcdir)/internal/serial.h array.$(OBJEXT): $(top_srcdir)/internal/static_assert.h array.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -2214,7 +2213,6 @@ ast.$(OBJEXT): $(top_srcdir)/internal/numeric.h ast.$(OBJEXT): $(top_srcdir)/internal/parse.h ast.$(OBJEXT): $(top_srcdir)/internal/rational.h ast.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h -ast.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h ast.$(OBJEXT): $(top_srcdir)/internal/serial.h ast.$(OBJEXT): $(top_srcdir)/internal/static_assert.h ast.$(OBJEXT): $(top_srcdir)/internal/symbol.h @@ -2650,7 +2648,6 @@ builtin.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h builtin.$(OBJEXT): $(top_srcdir)/internal/compilers.h builtin.$(OBJEXT): $(top_srcdir)/internal/gc.h builtin.$(OBJEXT): $(top_srcdir)/internal/imemo.h -builtin.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h builtin.$(OBJEXT): $(top_srcdir)/internal/serial.h builtin.$(OBJEXT): $(top_srcdir)/internal/static_assert.h builtin.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -2880,7 +2877,6 @@ class.$(OBJEXT): $(top_srcdir)/internal/gc.h class.$(OBJEXT): $(top_srcdir)/internal/hash.h class.$(OBJEXT): $(top_srcdir)/internal/imemo.h class.$(OBJEXT): $(top_srcdir)/internal/object.h -class.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h class.$(OBJEXT): $(top_srcdir)/internal/serial.h class.$(OBJEXT): $(top_srcdir)/internal/static_assert.h class.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -3278,7 +3274,6 @@ compile.$(OBJEXT): $(top_srcdir)/internal/object.h compile.$(OBJEXT): $(top_srcdir)/internal/rational.h compile.$(OBJEXT): $(top_srcdir)/internal/re.h compile.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h -compile.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h compile.$(OBJEXT): $(top_srcdir)/internal/serial.h compile.$(OBJEXT): $(top_srcdir)/internal/static_assert.h compile.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -3532,7 +3527,6 @@ complex.$(OBJEXT): $(top_srcdir)/internal/math.h complex.$(OBJEXT): $(top_srcdir)/internal/numeric.h complex.$(OBJEXT): $(top_srcdir)/internal/object.h complex.$(OBJEXT): $(top_srcdir)/internal/rational.h -complex.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h complex.$(OBJEXT): $(top_srcdir)/internal/serial.h complex.$(OBJEXT): $(top_srcdir)/internal/static_assert.h complex.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -3977,7 +3971,6 @@ debug.$(OBJEXT): $(top_srcdir)/internal/class.h debug.$(OBJEXT): $(top_srcdir)/internal/compilers.h debug.$(OBJEXT): $(top_srcdir)/internal/gc.h debug.$(OBJEXT): $(top_srcdir)/internal/imemo.h -debug.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h debug.$(OBJEXT): $(top_srcdir)/internal/serial.h debug.$(OBJEXT): $(top_srcdir)/internal/signal.h debug.$(OBJEXT): $(top_srcdir)/internal/static_assert.h @@ -4355,7 +4348,6 @@ dir.$(OBJEXT): $(top_srcdir)/internal/gc.h dir.$(OBJEXT): $(top_srcdir)/internal/imemo.h dir.$(OBJEXT): $(top_srcdir)/internal/io.h dir.$(OBJEXT): $(top_srcdir)/internal/object.h -dir.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h dir.$(OBJEXT): $(top_srcdir)/internal/serial.h dir.$(OBJEXT): $(top_srcdir)/internal/static_assert.h dir.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -6279,7 +6271,6 @@ enumerator.$(OBJEXT): $(top_srcdir)/internal/imemo.h enumerator.$(OBJEXT): $(top_srcdir)/internal/numeric.h enumerator.$(OBJEXT): $(top_srcdir)/internal/range.h enumerator.$(OBJEXT): $(top_srcdir)/internal/rational.h -enumerator.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h enumerator.$(OBJEXT): $(top_srcdir)/internal/serial.h enumerator.$(OBJEXT): $(top_srcdir)/internal/static_assert.h enumerator.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -6492,7 +6483,6 @@ error.$(OBJEXT): $(top_srcdir)/internal/io.h error.$(OBJEXT): $(top_srcdir)/internal/load.h error.$(OBJEXT): $(top_srcdir)/internal/object.h error.$(OBJEXT): $(top_srcdir)/internal/process.h -error.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h error.$(OBJEXT): $(top_srcdir)/internal/serial.h error.$(OBJEXT): $(top_srcdir)/internal/static_assert.h error.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -6709,7 +6699,6 @@ eval.$(OBJEXT): $(top_srcdir)/internal/imemo.h eval.$(OBJEXT): $(top_srcdir)/internal/inits.h eval.$(OBJEXT): $(top_srcdir)/internal/io.h eval.$(OBJEXT): $(top_srcdir)/internal/object.h -eval.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h eval.$(OBJEXT): $(top_srcdir)/internal/serial.h eval.$(OBJEXT): $(top_srcdir)/internal/static_assert.h eval.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -7445,7 +7434,6 @@ goruby.$(OBJEXT): $(top_srcdir)/internal/imemo.h goruby.$(OBJEXT): $(top_srcdir)/internal/numeric.h goruby.$(OBJEXT): $(top_srcdir)/internal/rational.h goruby.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h -goruby.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h goruby.$(OBJEXT): $(top_srcdir)/internal/serial.h goruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h goruby.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -7682,7 +7670,6 @@ hash.$(OBJEXT): $(top_srcdir)/internal/hash.h hash.$(OBJEXT): $(top_srcdir)/internal/imemo.h hash.$(OBJEXT): $(top_srcdir)/internal/object.h hash.$(OBJEXT): $(top_srcdir)/internal/proc.h -hash.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h hash.$(OBJEXT): $(top_srcdir)/internal/serial.h hash.$(OBJEXT): $(top_srcdir)/internal/st.h hash.$(OBJEXT): $(top_srcdir)/internal/static_assert.h @@ -8095,7 +8082,6 @@ io.$(OBJEXT): $(top_srcdir)/internal/io.h io.$(OBJEXT): $(top_srcdir)/internal/numeric.h io.$(OBJEXT): $(top_srcdir)/internal/object.h io.$(OBJEXT): $(top_srcdir)/internal/process.h -io.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h io.$(OBJEXT): $(top_srcdir)/internal/serial.h io.$(OBJEXT): $(top_srcdir)/internal/static_assert.h io.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -8770,7 +8756,6 @@ load.$(OBJEXT): $(top_srcdir)/internal/numeric.h load.$(OBJEXT): $(top_srcdir)/internal/parse.h load.$(OBJEXT): $(top_srcdir)/internal/rational.h load.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h -load.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h load.$(OBJEXT): $(top_srcdir)/internal/serial.h load.$(OBJEXT): $(top_srcdir)/internal/static_assert.h load.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -9500,7 +9485,6 @@ marshal.$(OBJEXT): $(top_srcdir)/internal/hash.h marshal.$(OBJEXT): $(top_srcdir)/internal/imemo.h marshal.$(OBJEXT): $(top_srcdir)/internal/numeric.h marshal.$(OBJEXT): $(top_srcdir)/internal/object.h -marshal.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h marshal.$(OBJEXT): $(top_srcdir)/internal/serial.h marshal.$(OBJEXT): $(top_srcdir)/internal/static_assert.h marshal.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -9885,7 +9869,6 @@ memory_view.$(OBJEXT): $(top_srcdir)/internal/compilers.h memory_view.$(OBJEXT): $(top_srcdir)/internal/gc.h memory_view.$(OBJEXT): $(top_srcdir)/internal/hash.h memory_view.$(OBJEXT): $(top_srcdir)/internal/imemo.h -memory_view.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h memory_view.$(OBJEXT): $(top_srcdir)/internal/serial.h memory_view.$(OBJEXT): $(top_srcdir)/internal/static_assert.h memory_view.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -10097,7 +10080,6 @@ miniinit.$(OBJEXT): $(top_srcdir)/internal/imemo.h miniinit.$(OBJEXT): $(top_srcdir)/internal/numeric.h miniinit.$(OBJEXT): $(top_srcdir)/internal/rational.h miniinit.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h -miniinit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h miniinit.$(OBJEXT): $(top_srcdir)/internal/serial.h miniinit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h miniinit.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -10346,7 +10328,6 @@ node.$(OBJEXT): $(top_srcdir)/internal/compilers.h node.$(OBJEXT): $(top_srcdir)/internal/gc.h node.$(OBJEXT): $(top_srcdir)/internal/hash.h node.$(OBJEXT): $(top_srcdir)/internal/imemo.h -node.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h node.$(OBJEXT): $(top_srcdir)/internal/serial.h node.$(OBJEXT): $(top_srcdir)/internal/static_assert.h node.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -10554,7 +10535,6 @@ node_dump.$(OBJEXT): $(top_srcdir)/internal/imemo.h node_dump.$(OBJEXT): $(top_srcdir)/internal/numeric.h node_dump.$(OBJEXT): $(top_srcdir)/internal/rational.h node_dump.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h -node_dump.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h node_dump.$(OBJEXT): $(top_srcdir)/internal/serial.h node_dump.$(OBJEXT): $(top_srcdir)/internal/static_assert.h node_dump.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -10763,7 +10743,6 @@ numeric.$(OBJEXT): $(top_srcdir)/internal/imemo.h numeric.$(OBJEXT): $(top_srcdir)/internal/numeric.h numeric.$(OBJEXT): $(top_srcdir)/internal/object.h numeric.$(OBJEXT): $(top_srcdir)/internal/rational.h -numeric.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h numeric.$(OBJEXT): $(top_srcdir)/internal/serial.h numeric.$(OBJEXT): $(top_srcdir)/internal/static_assert.h numeric.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -10977,7 +10956,6 @@ object.$(OBJEXT): $(top_srcdir)/internal/imemo.h object.$(OBJEXT): $(top_srcdir)/internal/inits.h object.$(OBJEXT): $(top_srcdir)/internal/numeric.h object.$(OBJEXT): $(top_srcdir)/internal/object.h -object.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h object.$(OBJEXT): $(top_srcdir)/internal/serial.h object.$(OBJEXT): $(top_srcdir)/internal/st.h object.$(OBJEXT): $(top_srcdir)/internal/static_assert.h @@ -11192,7 +11170,6 @@ pack.$(OBJEXT): $(top_srcdir)/internal/bits.h pack.$(OBJEXT): $(top_srcdir)/internal/compilers.h pack.$(OBJEXT): $(top_srcdir)/internal/gc.h pack.$(OBJEXT): $(top_srcdir)/internal/imemo.h -pack.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h pack.$(OBJEXT): $(top_srcdir)/internal/serial.h pack.$(OBJEXT): $(top_srcdir)/internal/static_assert.h pack.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -11412,7 +11389,6 @@ parse.$(OBJEXT): $(top_srcdir)/internal/parse.h parse.$(OBJEXT): $(top_srcdir)/internal/rational.h parse.$(OBJEXT): $(top_srcdir)/internal/re.h parse.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h -parse.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h parse.$(OBJEXT): $(top_srcdir)/internal/serial.h parse.$(OBJEXT): $(top_srcdir)/internal/static_assert.h parse.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -12665,7 +12641,6 @@ proc.$(OBJEXT): $(top_srcdir)/internal/gc.h proc.$(OBJEXT): $(top_srcdir)/internal/imemo.h proc.$(OBJEXT): $(top_srcdir)/internal/object.h proc.$(OBJEXT): $(top_srcdir)/internal/proc.h -proc.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h proc.$(OBJEXT): $(top_srcdir)/internal/serial.h proc.$(OBJEXT): $(top_srcdir)/internal/static_assert.h proc.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -12910,7 +12885,6 @@ process.$(OBJEXT): $(top_srcdir)/internal/io.h process.$(OBJEXT): $(top_srcdir)/internal/numeric.h process.$(OBJEXT): $(top_srcdir)/internal/object.h process.$(OBJEXT): $(top_srcdir)/internal/process.h -process.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h process.$(OBJEXT): $(top_srcdir)/internal/serial.h process.$(OBJEXT): $(top_srcdir)/internal/static_assert.h process.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -13133,7 +13107,6 @@ ractor.$(OBJEXT): $(top_srcdir)/internal/hash.h ractor.$(OBJEXT): $(top_srcdir)/internal/imemo.h ractor.$(OBJEXT): $(top_srcdir)/internal/numeric.h ractor.$(OBJEXT): $(top_srcdir)/internal/rational.h -ractor.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h ractor.$(OBJEXT): $(top_srcdir)/internal/serial.h ractor.$(OBJEXT): $(top_srcdir)/internal/static_assert.h ractor.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -13756,7 +13729,6 @@ rational.$(OBJEXT): $(top_srcdir)/internal/imemo.h rational.$(OBJEXT): $(top_srcdir)/internal/numeric.h rational.$(OBJEXT): $(top_srcdir)/internal/object.h rational.$(OBJEXT): $(top_srcdir)/internal/rational.h -rational.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h rational.$(OBJEXT): $(top_srcdir)/internal/serial.h rational.$(OBJEXT): $(top_srcdir)/internal/static_assert.h rational.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -13963,7 +13935,6 @@ re.$(OBJEXT): $(top_srcdir)/internal/imemo.h re.$(OBJEXT): $(top_srcdir)/internal/object.h re.$(OBJEXT): $(top_srcdir)/internal/ractor.h re.$(OBJEXT): $(top_srcdir)/internal/re.h -re.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h re.$(OBJEXT): $(top_srcdir)/internal/serial.h re.$(OBJEXT): $(top_srcdir)/internal/static_assert.h re.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -15147,7 +15118,6 @@ rjit.$(OBJEXT): $(top_srcdir)/internal/gc.h rjit.$(OBJEXT): $(top_srcdir)/internal/hash.h rjit.$(OBJEXT): $(top_srcdir)/internal/imemo.h rjit.$(OBJEXT): $(top_srcdir)/internal/process.h -rjit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h rjit.$(OBJEXT): $(top_srcdir)/internal/serial.h rjit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h rjit.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -15677,7 +15647,6 @@ ruby.$(OBJEXT): $(top_srcdir)/internal/object.h ruby.$(OBJEXT): $(top_srcdir)/internal/parse.h ruby.$(OBJEXT): $(top_srcdir)/internal/rational.h ruby.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h -ruby.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h ruby.$(OBJEXT): $(top_srcdir)/internal/serial.h ruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h ruby.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -16096,7 +16065,6 @@ scheduler.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h scheduler.$(OBJEXT): $(top_srcdir)/internal/compilers.h scheduler.$(OBJEXT): $(top_srcdir)/internal/gc.h scheduler.$(OBJEXT): $(top_srcdir)/internal/imemo.h -scheduler.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h scheduler.$(OBJEXT): $(top_srcdir)/internal/serial.h scheduler.$(OBJEXT): $(top_srcdir)/internal/static_assert.h scheduler.$(OBJEXT): $(top_srcdir)/internal/thread.h @@ -16461,7 +16429,6 @@ shape.$(OBJEXT): $(top_srcdir)/internal/error.h shape.$(OBJEXT): $(top_srcdir)/internal/gc.h shape.$(OBJEXT): $(top_srcdir)/internal/imemo.h shape.$(OBJEXT): $(top_srcdir)/internal/object.h -shape.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h shape.$(OBJEXT): $(top_srcdir)/internal/serial.h shape.$(OBJEXT): $(top_srcdir)/internal/static_assert.h shape.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -17678,7 +17645,6 @@ struct.$(OBJEXT): $(top_srcdir)/internal/hash.h struct.$(OBJEXT): $(top_srcdir)/internal/imemo.h struct.$(OBJEXT): $(top_srcdir)/internal/object.h struct.$(OBJEXT): $(top_srcdir)/internal/proc.h -struct.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h struct.$(OBJEXT): $(top_srcdir)/internal/serial.h struct.$(OBJEXT): $(top_srcdir)/internal/static_assert.h struct.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -17889,7 +17855,6 @@ symbol.$(OBJEXT): $(top_srcdir)/internal/gc.h symbol.$(OBJEXT): $(top_srcdir)/internal/hash.h symbol.$(OBJEXT): $(top_srcdir)/internal/imemo.h symbol.$(OBJEXT): $(top_srcdir)/internal/object.h -symbol.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h symbol.$(OBJEXT): $(top_srcdir)/internal/serial.h symbol.$(OBJEXT): $(top_srcdir)/internal/static_assert.h symbol.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -18111,7 +18076,6 @@ thread.$(OBJEXT): $(top_srcdir)/internal/imemo.h thread.$(OBJEXT): $(top_srcdir)/internal/io.h thread.$(OBJEXT): $(top_srcdir)/internal/object.h thread.$(OBJEXT): $(top_srcdir)/internal/proc.h -thread.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h thread.$(OBJEXT): $(top_srcdir)/internal/serial.h thread.$(OBJEXT): $(top_srcdir)/internal/signal.h thread.$(OBJEXT): $(top_srcdir)/internal/static_assert.h @@ -18365,7 +18329,6 @@ time.$(OBJEXT): $(top_srcdir)/internal/hash.h time.$(OBJEXT): $(top_srcdir)/internal/imemo.h time.$(OBJEXT): $(top_srcdir)/internal/numeric.h time.$(OBJEXT): $(top_srcdir)/internal/rational.h -time.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h time.$(OBJEXT): $(top_srcdir)/internal/serial.h time.$(OBJEXT): $(top_srcdir)/internal/static_assert.h time.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -18929,7 +18892,6 @@ variable.$(OBJEXT): $(top_srcdir)/internal/hash.h variable.$(OBJEXT): $(top_srcdir)/internal/imemo.h variable.$(OBJEXT): $(top_srcdir)/internal/object.h variable.$(OBJEXT): $(top_srcdir)/internal/re.h -variable.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h variable.$(OBJEXT): $(top_srcdir)/internal/serial.h variable.$(OBJEXT): $(top_srcdir)/internal/static_assert.h variable.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -19142,7 +19104,6 @@ version.$(OBJEXT): $(top_srcdir)/internal/cmdlineopt.h version.$(OBJEXT): $(top_srcdir)/internal/compilers.h version.$(OBJEXT): $(top_srcdir)/internal/gc.h version.$(OBJEXT): $(top_srcdir)/internal/imemo.h -version.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h version.$(OBJEXT): $(top_srcdir)/internal/serial.h version.$(OBJEXT): $(top_srcdir)/internal/static_assert.h version.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -19631,7 +19592,6 @@ vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/compilers.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/error.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/gc.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/imemo.h -vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/serial.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/static_assert.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -19861,7 +19821,6 @@ vm_dump.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/compilers.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/gc.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/imemo.h -vm_dump.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/serial.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/static_assert.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -20090,7 +20049,6 @@ vm_sync.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/compilers.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/gc.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/imemo.h -vm_sync.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/serial.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/static_assert.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/thread.h @@ -20299,7 +20257,6 @@ vm_trace.$(OBJEXT): $(top_srcdir)/internal/compilers.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/gc.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/hash.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/imemo.h -vm_trace.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/serial.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/static_assert.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/symbol.h diff --git a/ext/objspace/depend b/ext/objspace/depend index aa0c5c5d7dd1b9..85e99a71b4149a 100644 --- a/ext/objspace/depend +++ b/ext/objspace/depend @@ -182,7 +182,6 @@ object_tracing.o: $(top_srcdir)/internal/basic_operators.h object_tracing.o: $(top_srcdir)/internal/compilers.h object_tracing.o: $(top_srcdir)/internal/gc.h object_tracing.o: $(top_srcdir)/internal/imemo.h -object_tracing.o: $(top_srcdir)/internal/sanitizers.h object_tracing.o: $(top_srcdir)/internal/serial.h object_tracing.o: $(top_srcdir)/internal/static_assert.h object_tracing.o: $(top_srcdir)/internal/vm.h diff --git a/ext/ripper/depend b/ext/ripper/depend index 3b9b890de8347a..a07825fd405de8 100644 --- a/ext/ripper/depend +++ b/ext/ripper/depend @@ -593,7 +593,6 @@ ripper.o: $(top_srcdir)/internal/parse.h ripper.o: $(top_srcdir)/internal/rational.h ripper.o: $(top_srcdir)/internal/re.h ripper.o: $(top_srcdir)/internal/ruby_parser.h -ripper.o: $(top_srcdir)/internal/sanitizers.h ripper.o: $(top_srcdir)/internal/serial.h ripper.o: $(top_srcdir)/internal/static_assert.h ripper.o: $(top_srcdir)/internal/string.h diff --git a/ext/socket/depend b/ext/socket/depend index e95555ea921a41..3db153bb1ccbf5 100644 --- a/ext/socket/depend +++ b/ext/socket/depend @@ -199,7 +199,6 @@ ancdata.o: $(top_srcdir)/internal/error.h ancdata.o: $(top_srcdir)/internal/gc.h ancdata.o: $(top_srcdir)/internal/imemo.h ancdata.o: $(top_srcdir)/internal/io.h -ancdata.o: $(top_srcdir)/internal/sanitizers.h ancdata.o: $(top_srcdir)/internal/serial.h ancdata.o: $(top_srcdir)/internal/static_assert.h ancdata.o: $(top_srcdir)/internal/string.h @@ -409,7 +408,6 @@ basicsocket.o: $(top_srcdir)/internal/error.h basicsocket.o: $(top_srcdir)/internal/gc.h basicsocket.o: $(top_srcdir)/internal/imemo.h basicsocket.o: $(top_srcdir)/internal/io.h -basicsocket.o: $(top_srcdir)/internal/sanitizers.h basicsocket.o: $(top_srcdir)/internal/serial.h basicsocket.o: $(top_srcdir)/internal/static_assert.h basicsocket.o: $(top_srcdir)/internal/string.h @@ -619,7 +617,6 @@ constants.o: $(top_srcdir)/internal/error.h constants.o: $(top_srcdir)/internal/gc.h constants.o: $(top_srcdir)/internal/imemo.h constants.o: $(top_srcdir)/internal/io.h -constants.o: $(top_srcdir)/internal/sanitizers.h constants.o: $(top_srcdir)/internal/serial.h constants.o: $(top_srcdir)/internal/static_assert.h constants.o: $(top_srcdir)/internal/string.h @@ -830,7 +827,6 @@ ifaddr.o: $(top_srcdir)/internal/error.h ifaddr.o: $(top_srcdir)/internal/gc.h ifaddr.o: $(top_srcdir)/internal/imemo.h ifaddr.o: $(top_srcdir)/internal/io.h -ifaddr.o: $(top_srcdir)/internal/sanitizers.h ifaddr.o: $(top_srcdir)/internal/serial.h ifaddr.o: $(top_srcdir)/internal/static_assert.h ifaddr.o: $(top_srcdir)/internal/string.h @@ -1040,7 +1036,6 @@ init.o: $(top_srcdir)/internal/error.h init.o: $(top_srcdir)/internal/gc.h init.o: $(top_srcdir)/internal/imemo.h init.o: $(top_srcdir)/internal/io.h -init.o: $(top_srcdir)/internal/sanitizers.h init.o: $(top_srcdir)/internal/serial.h init.o: $(top_srcdir)/internal/static_assert.h init.o: $(top_srcdir)/internal/string.h @@ -1250,7 +1245,6 @@ ipsocket.o: $(top_srcdir)/internal/error.h ipsocket.o: $(top_srcdir)/internal/gc.h ipsocket.o: $(top_srcdir)/internal/imemo.h ipsocket.o: $(top_srcdir)/internal/io.h -ipsocket.o: $(top_srcdir)/internal/sanitizers.h ipsocket.o: $(top_srcdir)/internal/serial.h ipsocket.o: $(top_srcdir)/internal/static_assert.h ipsocket.o: $(top_srcdir)/internal/string.h @@ -1460,7 +1454,6 @@ option.o: $(top_srcdir)/internal/error.h option.o: $(top_srcdir)/internal/gc.h option.o: $(top_srcdir)/internal/imemo.h option.o: $(top_srcdir)/internal/io.h -option.o: $(top_srcdir)/internal/sanitizers.h option.o: $(top_srcdir)/internal/serial.h option.o: $(top_srcdir)/internal/static_assert.h option.o: $(top_srcdir)/internal/string.h @@ -1670,7 +1663,6 @@ raddrinfo.o: $(top_srcdir)/internal/error.h raddrinfo.o: $(top_srcdir)/internal/gc.h raddrinfo.o: $(top_srcdir)/internal/imemo.h raddrinfo.o: $(top_srcdir)/internal/io.h -raddrinfo.o: $(top_srcdir)/internal/sanitizers.h raddrinfo.o: $(top_srcdir)/internal/serial.h raddrinfo.o: $(top_srcdir)/internal/static_assert.h raddrinfo.o: $(top_srcdir)/internal/string.h @@ -1880,7 +1872,6 @@ socket.o: $(top_srcdir)/internal/error.h socket.o: $(top_srcdir)/internal/gc.h socket.o: $(top_srcdir)/internal/imemo.h socket.o: $(top_srcdir)/internal/io.h -socket.o: $(top_srcdir)/internal/sanitizers.h socket.o: $(top_srcdir)/internal/serial.h socket.o: $(top_srcdir)/internal/static_assert.h socket.o: $(top_srcdir)/internal/string.h @@ -2090,7 +2081,6 @@ sockssocket.o: $(top_srcdir)/internal/error.h sockssocket.o: $(top_srcdir)/internal/gc.h sockssocket.o: $(top_srcdir)/internal/imemo.h sockssocket.o: $(top_srcdir)/internal/io.h -sockssocket.o: $(top_srcdir)/internal/sanitizers.h sockssocket.o: $(top_srcdir)/internal/serial.h sockssocket.o: $(top_srcdir)/internal/static_assert.h sockssocket.o: $(top_srcdir)/internal/string.h @@ -2300,7 +2290,6 @@ tcpserver.o: $(top_srcdir)/internal/error.h tcpserver.o: $(top_srcdir)/internal/gc.h tcpserver.o: $(top_srcdir)/internal/imemo.h tcpserver.o: $(top_srcdir)/internal/io.h -tcpserver.o: $(top_srcdir)/internal/sanitizers.h tcpserver.o: $(top_srcdir)/internal/serial.h tcpserver.o: $(top_srcdir)/internal/static_assert.h tcpserver.o: $(top_srcdir)/internal/string.h @@ -2510,7 +2499,6 @@ tcpsocket.o: $(top_srcdir)/internal/error.h tcpsocket.o: $(top_srcdir)/internal/gc.h tcpsocket.o: $(top_srcdir)/internal/imemo.h tcpsocket.o: $(top_srcdir)/internal/io.h -tcpsocket.o: $(top_srcdir)/internal/sanitizers.h tcpsocket.o: $(top_srcdir)/internal/serial.h tcpsocket.o: $(top_srcdir)/internal/static_assert.h tcpsocket.o: $(top_srcdir)/internal/string.h @@ -2720,7 +2708,6 @@ udpsocket.o: $(top_srcdir)/internal/error.h udpsocket.o: $(top_srcdir)/internal/gc.h udpsocket.o: $(top_srcdir)/internal/imemo.h udpsocket.o: $(top_srcdir)/internal/io.h -udpsocket.o: $(top_srcdir)/internal/sanitizers.h udpsocket.o: $(top_srcdir)/internal/serial.h udpsocket.o: $(top_srcdir)/internal/static_assert.h udpsocket.o: $(top_srcdir)/internal/string.h @@ -2930,7 +2917,6 @@ unixserver.o: $(top_srcdir)/internal/error.h unixserver.o: $(top_srcdir)/internal/gc.h unixserver.o: $(top_srcdir)/internal/imemo.h unixserver.o: $(top_srcdir)/internal/io.h -unixserver.o: $(top_srcdir)/internal/sanitizers.h unixserver.o: $(top_srcdir)/internal/serial.h unixserver.o: $(top_srcdir)/internal/static_assert.h unixserver.o: $(top_srcdir)/internal/string.h @@ -3140,7 +3126,6 @@ unixsocket.o: $(top_srcdir)/internal/error.h unixsocket.o: $(top_srcdir)/internal/gc.h unixsocket.o: $(top_srcdir)/internal/imemo.h unixsocket.o: $(top_srcdir)/internal/io.h -unixsocket.o: $(top_srcdir)/internal/sanitizers.h unixsocket.o: $(top_srcdir)/internal/serial.h unixsocket.o: $(top_srcdir)/internal/static_assert.h unixsocket.o: $(top_srcdir)/internal/string.h diff --git a/gc.c b/gc.c index a16b68e2e765b2..6831fd6e14e872 100644 --- a/gc.c +++ b/gc.c @@ -6828,25 +6828,6 @@ static void each_stack_location(rb_objspace_t *objspace, const rb_execution_cont const VALUE *stack_start, const VALUE *stack_end, void *ctx, void (*cb)(rb_objspace_t *, void *, VALUE)); -static void -gc_mark_machine_stack_location_maybe(rb_objspace_t *objspace, void *ctx, VALUE obj) -{ - gc_mark_maybe(objspace, obj); -#ifdef RUBY_ASAN_ENABLED - rb_execution_context_t *ec = ctx; - void *fake_frame_start; - void *fake_frame_end; - bool is_fake_frame = asan_get_fake_stack_extents( - ec->thread_ptr->asan_fake_stack_handle, obj, - ec->machine.stack_start, ec->machine.stack_end, - &fake_frame_start, &fake_frame_end - ); - if (is_fake_frame) { - each_stack_location(objspace, ec, fake_frame_start, fake_frame_end, NULL, gc_mark_maybe_cb); - } -#endif -} - #if defined(__wasm__) @@ -6865,10 +6846,10 @@ static void mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec) { emscripten_scan_stack(rb_mark_locations); - each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], NULL, gc_mark_maybe_cb); + each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe_cb); emscripten_scan_registers(rb_mark_locations); - each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], NULL, gc_mark_maybe_cb); + each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe_cb); } # else // use Asyncify version @@ -6878,10 +6859,10 @@ mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec VALUE *stack_start, *stack_end; SET_STACK_END; GET_STACK_BOUNDS(stack_start, stack_end, 1); - each_stack_location(objspace, ec, stack_start, stack_end, NULL, gc_mark_maybe_cb); + each_stack_location(objspace, ec, stack_start, stack_end, gc_mark_maybe_cb); rb_wasm_scan_locals(rb_mark_locations); - each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], NULL, gc_mark_maybe_cb); + each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe_cb); } # endif @@ -6908,9 +6889,9 @@ mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec SET_STACK_END; GET_STACK_BOUNDS(stack_start, stack_end, 1); - each_location(objspace, save_regs_gc_mark.v, numberof(save_regs_gc_mark.v), (void *)ec, gc_mark_machine_stack_location_maybe); + each_location(objspace, save_regs_gc_mark.v, numberof(save_regs_gc_mark.v), NULL, gc_mark_maybe_cb); - each_stack_location(objspace, ec, stack_start, stack_end, (void *)ec, gc_mark_machine_stack_location_maybe); + each_stack_location(objspace, ec, stack_start, stack_end, NULL, gc_mark_maybe_cb); } #endif @@ -6928,7 +6909,7 @@ each_machine_stack_value(const rb_execution_context_t *ec, void *ctx, void (*cb) void rb_gc_mark_machine_stack(const rb_execution_context_t *ec) { - each_machine_stack_value(ec, (void *)ec, gc_mark_machine_stack_location_maybe); + each_machine_stack_value(ec, NULL, gc_mark_maybe_cb); } static void diff --git a/internal/sanitizers.h b/internal/sanitizers.h index 3fc31b350e8d10..d444903aa0b36e 100644 --- a/internal/sanitizers.h +++ b/internal/sanitizers.h @@ -213,67 +213,4 @@ asan_get_real_stack_addr(void* slot) return addr ? addr : slot; } -/*! - * Gets the current thread's fake stack handle, which can be passed into get_fake_stack_extents - * - * \retval An opaque value which can be passed to asan_get_fake_stack_extents - */ -static inline void * -asan_get_thread_fake_stack_handle(void) -{ - return __asan_get_current_fake_stack(); -} - -/*! - * Checks if the given VALUE _actually_ represents a pointer to an ASAN fake stack. - * - * If the given slot _is_ actually a reference to an ASAN fake stack, and that fake stack - * contains the real values for the passed-in range of machine stack addresses, returns true - * and the range of the fake stack through the outparams. - * - * Otherwise, returns false, and sets the outparams to NULL. - * - * Note that this function expects "start" to be > "end" on downward-growing stack architectures; - * - * \param[in] thread_fake_stack_handle The asan fake stack reference for the thread we're scanning - * \param[in] slot The value on the machine stack we want to inspect - * \param[in] machine_stack_start The extents of the real machine stack on which slot lives - * \param[in] machine_stack_end The extents of the real machine stack on which slot lives - * \param[out] fake_stack_start_out The extents of the fake stack which contains real VALUEs - * \param[out] fake_stack_end_out The extents of the fake stack which contains real VALUEs - * \return Whether slot is a pointer to a fake stack for the given machine stack range -*/ - -static inline bool -asan_get_fake_stack_extents(void *thread_fake_stack_handle, VALUE slot, - void *machine_stack_start, void *machine_stack_end, - void **fake_stack_start_out, void **fake_stack_end_out) -{ - /* the ifdef is needed here to suppress a warning about fake_frame_{start/end} being - uninitialized if __asan_addr_is_in_fake_stack is an empty macro */ -#ifdef RUBY_ASAN_ENABLED - void *fake_frame_start; - void *fake_frame_end; - void *real_stack_frame = __asan_addr_is_in_fake_stack( - thread_fake_stack_handle, (void *)slot, &fake_frame_start, &fake_frame_end - ); - if (real_stack_frame) { - bool in_range; -#if STACK_GROW_DIRECTION < 0 - in_range = machine_stack_start >= real_stack_frame && real_stack_frame >= machine_stack_end; -#else - in_range = machine_stack_start <= real_stack_frame && real_stack_frame <= machine_stack_end; -#endif - if (in_range) { - *fake_stack_start_out = fake_frame_start; - *fake_stack_end_out = fake_frame_end; - return true; - } - } -#endif - *fake_stack_start_out = 0; - *fake_stack_end_out = 0; - return false; -} - #endif /* INTERNAL_SANITIZERS_H */ diff --git a/thread.c b/thread.c index 27a6ffb95589d1..e7a9d7cd9bdcc7 100644 --- a/thread.c +++ b/thread.c @@ -525,9 +525,6 @@ void ruby_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame) { native_thread_init_stack(th, local_in_parent_frame); -#ifdef RUBY_ASAN_ENABLED - th->asan_fake_stack_handle = asan_get_thread_fake_stack_handle(); -#endif } const VALUE * diff --git a/vm_core.h b/vm_core.h index 9557004dbc8594..91cfae77e9e7ee 100644 --- a/vm_core.h +++ b/vm_core.h @@ -94,7 +94,6 @@ extern int ruby_assert_critical_section_entered; #include "internal.h" #include "internal/array.h" #include "internal/basic_operators.h" -#include "internal/sanitizers.h" #include "internal/serial.h" #include "internal/vm.h" #include "method.h" @@ -1156,10 +1155,6 @@ typedef struct rb_thread_struct { void **specific_storage; struct rb_ext_config ext_config; - -#ifdef RUBY_ASAN_ENABLED - void *asan_fake_stack_handle; -#endif } rb_thread_t; static inline unsigned int From 33a03cb236057b1dc044fc76bf51b263d6cbda81 Mon Sep 17 00:00:00 2001 From: KJ Tsanaktsidis Date: Fri, 12 Jan 2024 17:32:16 +1100 Subject: [PATCH 091/640] Revert "Define special macros for asan/msan being enabled" This reverts commit bdafad879093ef16a9a649154c4b2e4ebf492656. --- internal/sanitizers.h | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/internal/sanitizers.h b/internal/sanitizers.h index d444903aa0b36e..6b2a1319251a8d 100644 --- a/internal/sanitizers.h +++ b/internal/sanitizers.h @@ -16,15 +16,11 @@ #endif #ifdef HAVE_SANITIZER_ASAN_INTERFACE_H -# if __has_feature(address_sanitizer) -# define RUBY_ASAN_ENABLED -# include -# endif +# include #endif #ifdef HAVE_SANITIZER_MSAN_INTERFACE_H # if __has_feature(memory_sanitizer) -# define RUBY_MSAN_ENABLED # include # endif #endif @@ -33,10 +29,10 @@ #include "ruby/ruby.h" /* for VALUE */ #if 0 -#elif defined(RUBY_ASAN_ENABLED) && defined(RUBY_MSAN_ENABLED) +#elif __has_feature(memory_sanitizer) && __has_feature(address_sanitizer) # define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \ __attribute__((__no_sanitize__("memory, address"), __noinline__)) x -#elif defined(RUBY_ASAN_ENABLED) +#elif __has_feature(address_sanitizer) # define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \ __attribute__((__no_sanitize__("address"), __noinline__)) x #elif defined(NO_SANITIZE_ADDRESS) @@ -64,7 +60,7 @@ # define NO_SANITIZE(x, y) y #endif -#ifndef RUBY_ASAN_ENABLED +#if !__has_feature(address_sanitizer) # define __asan_poison_memory_region(x, y) # define __asan_unpoison_memory_region(x, y) # define __asan_region_is_poisoned(x, y) 0 @@ -72,7 +68,7 @@ # define __asan_addr_is_in_fake_stack(fake_stack, slot, start, end) NULL #endif -#ifndef RUBY_MSAN_ENABLED +#if !__has_feature(memory_sanitizer) # define __msan_allocated_memory(x, y) ((void)(x), (void)(y)) # define __msan_poison(x, y) ((void)(x), (void)(y)) # define __msan_unpoison(x, y) ((void)(x), (void)(y)) @@ -127,12 +123,12 @@ asan_poison_object(VALUE obj) asan_poison_memory_region(ptr, SIZEOF_VALUE); } -#ifdef RUBY_ASAN_ENABLED +#if !__has_feature(address_sanitizer) +#define asan_poison_object_if(ptr, obj) ((void)(ptr), (void)(obj)) +#else #define asan_poison_object_if(ptr, obj) do { \ if (ptr) asan_poison_object(obj); \ } while (0) -#else -#define asan_poison_object_if(ptr, obj) ((void)(ptr), (void)(obj)) #endif /*! From ac0ba3c07ee3f700b0b45176a7bdd322d8773e27 Mon Sep 17 00:00:00 2001 From: KJ Tsanaktsidis Date: Fri, 12 Jan 2024 17:32:16 +1100 Subject: [PATCH 092/640] Revert "Allow each_stack_location to accept context for the callback" This reverts commit 179228cd83a926efcd79ca5d0c6ed6af0c2389c0. --- gc.c | 46 +++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/gc.c b/gc.c index 6831fd6e14e872..0e4dadbdd0b39f 100644 --- a/gc.c +++ b/gc.c @@ -6548,38 +6548,32 @@ ruby_stack_check(void) return stack_check(GET_EC(), STACKFRAME_FOR_CALL_CFUNC); } -ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(static void each_location(rb_objspace_t *objspace, register const VALUE *x, register long n, void *ctx, void (*cb)(rb_objspace_t *, void *, VALUE))); +ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(static void each_location(rb_objspace_t *objspace, register const VALUE *x, register long n, void (*cb)(rb_objspace_t *, VALUE))); static void -each_location(rb_objspace_t *objspace, register const VALUE *x, register long n, void *ctx, void (*cb)(rb_objspace_t *, void *, VALUE)) +each_location(rb_objspace_t *objspace, register const VALUE *x, register long n, void (*cb)(rb_objspace_t *, VALUE)) { VALUE v; while (n--) { v = *x; - cb(objspace, ctx, v); + cb(objspace, v); x++; } } static void -gc_mark_locations(rb_objspace_t *objspace, const VALUE *start, const VALUE *end, void *ctx, void (*cb)(rb_objspace_t *, void *, VALUE)) +gc_mark_locations(rb_objspace_t *objspace, const VALUE *start, const VALUE *end, void (*cb)(rb_objspace_t *, VALUE)) { long n; if (end <= start) return; n = end - start; - each_location(objspace, start, n, ctx, cb); -} - -static void -gc_mark_maybe_cb(rb_objspace_t *objspace, void *ctx, VALUE obj) -{ - gc_mark_maybe(objspace, obj); + each_location(objspace, start, n, cb); } void rb_gc_mark_locations(const VALUE *start, const VALUE *end) { - gc_mark_locations(&rb_objspace, start, end, NULL, gc_mark_maybe_cb); + gc_mark_locations(&rb_objspace, start, end, gc_mark_maybe); } void @@ -6825,8 +6819,7 @@ mark_const_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl) #endif static void each_stack_location(rb_objspace_t *objspace, const rb_execution_context_t *ec, - const VALUE *stack_start, const VALUE *stack_end, void *ctx, - void (*cb)(rb_objspace_t *, void *, VALUE)); + const VALUE *stack_start, const VALUE *stack_end, void (*cb)(rb_objspace_t *, VALUE)); #if defined(__wasm__) @@ -6846,10 +6839,10 @@ static void mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec) { emscripten_scan_stack(rb_mark_locations); - each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe_cb); + each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe); emscripten_scan_registers(rb_mark_locations); - each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe_cb); + each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe); } # else // use Asyncify version @@ -6859,10 +6852,10 @@ mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec VALUE *stack_start, *stack_end; SET_STACK_END; GET_STACK_BOUNDS(stack_start, stack_end, 1); - each_stack_location(objspace, ec, stack_start, stack_end, gc_mark_maybe_cb); + each_stack_location(objspace, ec, stack_start, stack_end, gc_mark_maybe); rb_wasm_scan_locals(rb_mark_locations); - each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe_cb); + each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe); } # endif @@ -6889,41 +6882,40 @@ mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec SET_STACK_END; GET_STACK_BOUNDS(stack_start, stack_end, 1); - each_location(objspace, save_regs_gc_mark.v, numberof(save_regs_gc_mark.v), NULL, gc_mark_maybe_cb); + each_location(objspace, save_regs_gc_mark.v, numberof(save_regs_gc_mark.v), gc_mark_maybe); - each_stack_location(objspace, ec, stack_start, stack_end, NULL, gc_mark_maybe_cb); + each_stack_location(objspace, ec, stack_start, stack_end, gc_mark_maybe); } #endif static void -each_machine_stack_value(const rb_execution_context_t *ec, void *ctx, void (*cb)(rb_objspace_t *, void *, VALUE)) +each_machine_stack_value(const rb_execution_context_t *ec, void (*cb)(rb_objspace_t *, VALUE)) { rb_objspace_t *objspace = &rb_objspace; VALUE *stack_start, *stack_end; GET_STACK_BOUNDS(stack_start, stack_end, 0); RUBY_DEBUG_LOG("ec->th:%u stack_start:%p stack_end:%p", rb_ec_thread_ptr(ec)->serial, stack_start, stack_end); - each_stack_location(objspace, ec, stack_start, stack_end, ctx, cb); + each_stack_location(objspace, ec, stack_start, stack_end, cb); } void rb_gc_mark_machine_stack(const rb_execution_context_t *ec) { - each_machine_stack_value(ec, NULL, gc_mark_maybe_cb); + each_machine_stack_value(ec, gc_mark_maybe); } static void each_stack_location(rb_objspace_t *objspace, const rb_execution_context_t *ec, - const VALUE *stack_start, const VALUE *stack_end, void *ctx, - void (*cb)(rb_objspace_t *, void *, VALUE)) + const VALUE *stack_start, const VALUE *stack_end, void (*cb)(rb_objspace_t *, VALUE)) { - gc_mark_locations(objspace, stack_start, stack_end, ctx, cb); + gc_mark_locations(objspace, stack_start, stack_end, cb); #if defined(__mc68000__) gc_mark_locations(objspace, (VALUE*)((char*)stack_start + 2), - (VALUE*)((char*)stack_end - 2), ctx, cb); + (VALUE*)((char*)stack_end - 2), cb); #endif } From 6af0f442c7d16ab526c0e6859aa97ff217b73f99 Mon Sep 17 00:00:00 2001 From: KJ Tsanaktsidis Date: Fri, 12 Jan 2024 17:32:16 +1100 Subject: [PATCH 093/640] Revert "Make stack bounds detection work with ASAN" This reverts commit 6185cfdf38e26026c6d38220eeca48689e54cdcf. --- internal/sanitizers.h | 26 -------------------------- thread_pthread.c | 10 +++++----- thread_win32.c | 3 +-- 3 files changed, 6 insertions(+), 33 deletions(-) diff --git a/internal/sanitizers.h b/internal/sanitizers.h index 6b2a1319251a8d..7b7d166c747d4e 100644 --- a/internal/sanitizers.h +++ b/internal/sanitizers.h @@ -64,8 +64,6 @@ # define __asan_poison_memory_region(x, y) # define __asan_unpoison_memory_region(x, y) # define __asan_region_is_poisoned(x, y) 0 -# define __asan_get_current_fake_stack() NULL -# define __asan_addr_is_in_fake_stack(fake_stack, slot, start, end) NULL #endif #if !__has_feature(memory_sanitizer) @@ -185,28 +183,4 @@ asan_unpoison_object(VALUE obj, bool newobj_p) asan_unpoison_memory_region(ptr, SIZEOF_VALUE, newobj_p); } - -/*! - * Checks if the given pointer is on an ASAN fake stack. If so, it returns the - * address this variable has on the real frame; if not, it returns the origin - * address unmodified. - * - * n.b. - _dereferencing_ the returned address is meaningless and should not - * be done; even though ASAN reserves space for the variable in both the real and - * fake stacks, the _value_ of that variable is only in the fake stack. - * - * n.b. - this only works for addresses passed in from local variables on the same - * thread, because the ASAN fake stacks are threadlocal. - * - * \param[in] slot the address of some local variable - * \retval a pointer to something from that frame on the _real_ machine stack - */ -static inline void * -asan_get_real_stack_addr(void* slot) -{ - VALUE *addr; - addr = __asan_addr_is_in_fake_stack(__asan_get_current_fake_stack(), slot, NULL, NULL); - return addr ? addr : slot; -} - #endif /* INTERNAL_SANITIZERS_H */ diff --git a/thread_pthread.c b/thread_pthread.c index af50d50699a584..a6a6c9d127e3c6 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -12,7 +12,6 @@ #ifdef THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION #include "internal/gc.h" -#include "internal/sanitizers.h" #include "rjit.h" #ifdef HAVE_SYS_RESOURCE_H @@ -1968,7 +1967,6 @@ void ruby_init_stack(volatile void *addr) { native_main_thread.id = pthread_self(); - addr = asan_get_real_stack_addr((void *)addr); #if MAINSTACKADDR_AVAILABLE if (native_main_thread.stack_maxsize) return; @@ -2067,7 +2065,7 @@ native_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame) if (get_stack(&start, &size) == 0) { uintptr_t diff = (uintptr_t)start - (uintptr_t)local_in_parent_frame; - th->ec->machine.stack_start = asan_get_real_stack_addr(local_in_parent_frame); + th->ec->machine.stack_start = (uintptr_t)local_in_parent_frame; th->ec->machine.stack_maxsize = size - diff; } } @@ -2194,10 +2192,12 @@ call_thread_start_func_2(rb_thread_t *th) on a new thread, and replacing that data on fiber-switch would break it (see bug #13887) */ VALUE stack_start = 0; - VALUE *stack_start_addr = asan_get_real_stack_addr(&stack_start); - + VALUE *stack_start_addr = &stack_start; native_thread_init_stack(th, stack_start_addr); thread_start_func_2(th, th->ec->machine.stack_start); + + /* Ensure that stack_start really was spilled to the stack */ + RB_GC_GUARD(stack_start) } static void * diff --git a/thread_win32.c b/thread_win32.c index c2945420032835..e92472cea947d4 100644 --- a/thread_win32.c +++ b/thread_win32.c @@ -11,7 +11,6 @@ #ifdef THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION -#include "internal/sanitizers.h" #include #define TIME_QUANTUM_USEC (10 * 1000) @@ -597,7 +596,7 @@ COMPILER_WARNING_IGNORED(-Wmaybe-uninitialized) static inline SIZE_T query_memory_basic_info(PMEMORY_BASIC_INFORMATION mi, void *local_in_parent_frame) { - return VirtualQuery(asan_get_real_stack_addr(local_in_parent_frame), mi, sizeof(*mi)); + return VirtualQuery(local_in_parent_frame, mi, sizeof(*mi)); } COMPILER_WARNING_POP From 396e94666ba1646cb0fd1459eeae3f2e7ddd2658 Mon Sep 17 00:00:00 2001 From: KJ Tsanaktsidis Date: Fri, 12 Jan 2024 17:32:16 +1100 Subject: [PATCH 094/640] Revert "Pass down "stack start" variables from closer to the top of the stack" This reverts commit 4ba8f0dc993953d3ddda6328e3ef17a2fc2cbde5. --- eval.c | 4 ++-- include/ruby/internal/interpreter.h | 2 +- internal/inits.h | 2 +- thread.c | 4 ++-- thread_none.c | 4 ++-- thread_pthread.c | 21 +++++---------------- thread_win32.c | 12 ++++++------ vm.c | 4 ++-- vm_core.h | 2 +- 9 files changed, 22 insertions(+), 33 deletions(-) diff --git a/eval.c b/eval.c index 6424aed1dcda67..aa0eae08727588 100644 --- a/eval.c +++ b/eval.c @@ -70,7 +70,7 @@ ruby_setup(void) if (GET_VM()) return 0; - ruby_init_stack(&state); + ruby_init_stack((void *)&state); /* * Disable THP early before mallocs happen because we want this to @@ -79,7 +79,7 @@ ruby_setup(void) #if defined(__linux__) && defined(PR_SET_THP_DISABLE) prctl(PR_SET_THP_DISABLE, 1, 0, 0, 0); #endif - Init_BareVM(&state); + Init_BareVM(); Init_heap(); rb_vm_encoded_insn_data_table_init(); Init_vm_objects(); diff --git a/include/ruby/internal/interpreter.h b/include/ruby/internal/interpreter.h index d36d61ba54d295..662d39c0ec5702 100644 --- a/include/ruby/internal/interpreter.h +++ b/include/ruby/internal/interpreter.h @@ -141,7 +141,7 @@ void ruby_show_copyright(void); * * @param[in] addr A pointer somewhere on the stack, near its bottom. */ -void ruby_init_stack(volatile void *addr); +void ruby_init_stack(volatile VALUE *addr); /** * Initializes the VM and builtin libraries. diff --git a/internal/inits.h b/internal/inits.h index a2b2eea96f7a88..03e180f77bd026 100644 --- a/internal/inits.h +++ b/internal/inits.h @@ -29,7 +29,7 @@ int Init_enc_set_filesystem_encoding(void); void Init_newline(void); /* vm.c */ -void Init_BareVM(void *local_in_parent_frame); +void Init_BareVM(void); void Init_vm_objects(void); /* vm_backtrace.c */ diff --git a/thread.c b/thread.c index e7a9d7cd9bdcc7..070d1bbdfaba88 100644 --- a/thread.c +++ b/thread.c @@ -522,9 +522,9 @@ static VALUE rb_threadptr_raise(rb_thread_t *, int, VALUE *); static VALUE rb_thread_to_s(VALUE thread); void -ruby_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame) +ruby_thread_init_stack(rb_thread_t *th) { - native_thread_init_stack(th, local_in_parent_frame); + native_thread_init_stack(th); } const VALUE * diff --git a/thread_none.c b/thread_none.c index 767b929cf9105f..4d53d3bf4d89c4 100644 --- a/thread_none.c +++ b/thread_none.c @@ -140,12 +140,12 @@ ruby_mn_threads_params(void) } void -ruby_init_stack(volatile void *addr) +ruby_init_stack(volatile VALUE *addr) { } static int -native_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame) +native_thread_init_stack(rb_thread_t *th) { #if defined(__wasm__) && !defined(__EMSCRIPTEN__) th->ec->machine.stack_start = (VALUE *)rb_wasm_stack_get_base(); diff --git a/thread_pthread.c b/thread_pthread.c index a6a6c9d127e3c6..6d2f55a9573ed7 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -1964,7 +1964,7 @@ reserve_stack(volatile char *limit, size_t size) #undef ruby_init_stack void -ruby_init_stack(volatile void *addr) +ruby_init_stack(volatile VALUE *addr) { native_main_thread.id = pthread_self(); @@ -2049,7 +2049,7 @@ ruby_init_stack(volatile void *addr) {int err = (expr); if (err) {rb_bug_errno(#expr, err);}} static int -native_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame) +native_thread_init_stack(rb_thread_t *th) { rb_nativethread_id_t curr = pthread_self(); @@ -2064,8 +2064,8 @@ native_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame) size_t size; if (get_stack(&start, &size) == 0) { - uintptr_t diff = (uintptr_t)start - (uintptr_t)local_in_parent_frame; - th->ec->machine.stack_start = (uintptr_t)local_in_parent_frame; + uintptr_t diff = (uintptr_t)start - (uintptr_t)&curr; + th->ec->machine.stack_start = (VALUE *)&curr; th->ec->machine.stack_maxsize = size - diff; } } @@ -2185,19 +2185,8 @@ native_thread_create_dedicated(rb_thread_t *th) static void call_thread_start_func_2(rb_thread_t *th) { - /* Capture the address of a local in this stack frame to mark the beginning of the - machine stack for this thread. This is required even if we can tell the real - stack beginning from the pthread API in native_thread_init_stack, because - glibc stores some of its own data on the stack before calling into user code - on a new thread, and replacing that data on fiber-switch would break it (see - bug #13887) */ - VALUE stack_start = 0; - VALUE *stack_start_addr = &stack_start; - native_thread_init_stack(th, stack_start_addr); + native_thread_init_stack(th); thread_start_func_2(th, th->ec->machine.stack_start); - - /* Ensure that stack_start really was spilled to the stack */ - RB_GC_GUARD(stack_start) } static void * diff --git a/thread_win32.c b/thread_win32.c index e92472cea947d4..bd983e0bd9fb62 100644 --- a/thread_win32.c +++ b/thread_win32.c @@ -582,7 +582,7 @@ rb_native_cond_destroy(rb_nativethread_cond_t *cond) } void -ruby_init_stack(volatile void *addr) +ruby_init_stack(volatile VALUE *addr) { } @@ -594,20 +594,20 @@ COMPILER_WARNING_PUSH COMPILER_WARNING_IGNORED(-Wmaybe-uninitialized) #endif static inline SIZE_T -query_memory_basic_info(PMEMORY_BASIC_INFORMATION mi, void *local_in_parent_frame) +query_memory_basic_info(PMEMORY_BASIC_INFORMATION mi) { - return VirtualQuery(local_in_parent_frame, mi, sizeof(*mi)); + return VirtualQuery(mi, mi, sizeof(*mi)); } COMPILER_WARNING_POP static void -native_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame) +native_thread_init_stack(rb_thread_t *th) { MEMORY_BASIC_INFORMATION mi; char *base, *end; DWORD size, space; - CHECK_ERR(query_memory_basic_info(&mi, local_in_parent_frame)); + CHECK_ERR(query_memory_basic_info(&mi)); base = mi.AllocationBase; end = mi.BaseAddress; end += mi.RegionSize; @@ -638,7 +638,7 @@ thread_start_func_1(void *th_ptr) rb_thread_t *th = th_ptr; volatile HANDLE thread_id = th->nt->thread_id; - native_thread_init_stack(th, &th); + native_thread_init_stack(th); th->nt->interrupt_event = CreateEvent(0, TRUE, FALSE, 0); /* run */ diff --git a/vm.c b/vm.c index 945e7b91f7c501..37d631116aa4dc 100644 --- a/vm.c +++ b/vm.c @@ -4174,7 +4174,7 @@ rb_vm_set_progname(VALUE filename) extern const struct st_hash_type rb_fstring_hash_type; void -Init_BareVM(void *local_in_parent_frame) +Init_BareVM(void) { /* VM bootstrap: phase 1 */ rb_vm_t * vm = ruby_mimmalloc(sizeof(*vm)); @@ -4204,7 +4204,7 @@ Init_BareVM(void *local_in_parent_frame) th_init(th, 0, vm); rb_ractor_set_current_ec(th->ractor, th->ec); - ruby_thread_init_stack(th, local_in_parent_frame); + ruby_thread_init_stack(th); // setup ractor system rb_native_mutex_initialize(&vm->ractor.sync.lock); diff --git a/vm_core.h b/vm_core.h index 91cfae77e9e7ee..354603514ebb46 100644 --- a/vm_core.h +++ b/vm_core.h @@ -1842,7 +1842,7 @@ rb_control_frame_t *rb_vm_get_binding_creatable_next_cfp(const rb_execution_cont VALUE *rb_vm_svar_lep(const rb_execution_context_t *ec, const rb_control_frame_t *cfp); int rb_vm_get_sourceline(const rb_control_frame_t *); void rb_vm_stack_to_heap(rb_execution_context_t *ec); -void ruby_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame); +void ruby_thread_init_stack(rb_thread_t *th); rb_thread_t * ruby_thread_from_native(void); int ruby_thread_set_native(rb_thread_t *th); int rb_vm_control_frame_id_and_class(const rb_control_frame_t *cfp, ID *idp, ID *called_idp, VALUE *klassp); From 80feecd6a36ec640f2fab212a015281e920dc092 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 12 Jan 2024 18:14:26 +0900 Subject: [PATCH 095/640] Don't use cat command on native Windows --- spec/ruby/core/io/close_read_spec.rb | 3 ++- spec/ruby/core/io/close_write_spec.rb | 14 +++++++++----- spec/ruby/core/io/lineno_spec.rb | 6 ++++-- spec/ruby/core/io/stat_spec.rb | 3 ++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/spec/ruby/core/io/close_read_spec.rb b/spec/ruby/core/io/close_read_spec.rb index 26454bfddd1635..e700e85bd99919 100644 --- a/spec/ruby/core/io/close_read_spec.rb +++ b/spec/ruby/core/io/close_read_spec.rb @@ -4,7 +4,8 @@ describe "IO#close_read" do before :each do - @io = IO.popen 'cat', "r+" + cmd = platform_is(:windows) ? 'rem' : 'cat' + @io = IO.popen cmd, "r+" @path = tmp('io.close.txt') end diff --git a/spec/ruby/core/io/close_write_spec.rb b/spec/ruby/core/io/close_write_spec.rb index 14835e4e2c08bf..70610a3e9d6dc9 100644 --- a/spec/ruby/core/io/close_write_spec.rb +++ b/spec/ruby/core/io/close_write_spec.rb @@ -3,7 +3,8 @@ describe "IO#close_write" do before :each do - @io = IO.popen 'cat', 'r+' + cmd = platform_is(:windows) ? 'rem' : 'cat' + @io = IO.popen cmd, 'r+' @path = tmp('io.close.txt') end @@ -48,12 +49,15 @@ io.should.closed? end - it "flushes and closes the write stream" do - @io.puts '12345' + # Windows didn't have command like cat + platform_is_not :windows do + it "flushes and closes the write stream" do + @io.puts '12345' - @io.close_write + @io.close_write - @io.read.should == "12345\n" + @io.read.should == "12345\n" + end end it "does nothing on closed stream" do diff --git a/spec/ruby/core/io/lineno_spec.rb b/spec/ruby/core/io/lineno_spec.rb index 9a4ad908800843..e82cdd9f17ecab 100644 --- a/spec/ruby/core/io/lineno_spec.rb +++ b/spec/ruby/core/io/lineno_spec.rb @@ -26,7 +26,8 @@ end it "raises an IOError on a duplexed stream with the read side closed" do - IO.popen('cat', 'r+') do |p| + cmd = platform_is(:windows) ? 'rem' : 'cat' + IO.popen(cmd, 'r+') do |p| p.close_read -> { p.lineno }.should raise_error(IOError) end @@ -70,7 +71,8 @@ end it "raises an IOError on a duplexed stream with the read side closed" do - IO.popen('cat', 'r+') do |p| + cmd = platform_is(:windows) ? 'rem' : 'cat' + IO.popen(cmd, 'r+') do |p| p.close_read -> { p.lineno = 0 }.should raise_error(IOError) end diff --git a/spec/ruby/core/io/stat_spec.rb b/spec/ruby/core/io/stat_spec.rb index 58eba02b8fb9c0..717c45d0a3fe6d 100644 --- a/spec/ruby/core/io/stat_spec.rb +++ b/spec/ruby/core/io/stat_spec.rb @@ -3,7 +3,8 @@ describe "IO#stat" do before :each do - @io = IO.popen 'cat', "r+" + cmd = platform_is(:windows) ? 'rem' : 'cat' + @io = IO.popen cmd, "r+" end after :each do From 3103ed4159240e99614c9789bc0f869574a1f9db Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 12 Jan 2024 18:20:25 +0900 Subject: [PATCH 096/640] Use timeout instead of sleep on Windows --- spec/ruby/core/process/waitpid_spec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/ruby/core/process/waitpid_spec.rb b/spec/ruby/core/process/waitpid_spec.rb index f7cf1a45a81402..a02147b663c364 100644 --- a/spec/ruby/core/process/waitpid_spec.rb +++ b/spec/ruby/core/process/waitpid_spec.rb @@ -2,7 +2,8 @@ describe "Process.waitpid" do it "returns nil when the process has not yet completed and WNOHANG is specified" do - pid = spawn("sleep 5") + cmd = platform_is(:windows) ? "timeout" : "sleep" + pid = spawn("#{cmd} 5") begin Process.waitpid(pid, Process::WNOHANG).should == nil Process.kill("KILL", pid) From 3113bc8d445c4c24ed3827adfc50bb88c99b6364 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 12 Jan 2024 18:50:31 +0900 Subject: [PATCH 097/640] stat command is not provided on Windows --- spec/ruby/core/file/atime_spec.rb | 3 +++ spec/ruby/core/file/ctime_spec.rb | 3 +++ spec/ruby/core/file/mtime_spec.rb | 3 +++ 3 files changed, 9 insertions(+) diff --git a/spec/ruby/core/file/atime_spec.rb b/spec/ruby/core/file/atime_spec.rb index 1b47576e6b996f..e47e70e5acf35b 100644 --- a/spec/ruby/core/file/atime_spec.rb +++ b/spec/ruby/core/file/atime_spec.rb @@ -27,6 +27,9 @@ else File.atime(__FILE__).usec.should == 0 end + rescue Errno::ENOENT => e + # Native Windows don't have stat command. + skip e.message end end end diff --git a/spec/ruby/core/file/ctime_spec.rb b/spec/ruby/core/file/ctime_spec.rb index d17ba1a77f29a0..718f26d5cc9f8d 100644 --- a/spec/ruby/core/file/ctime_spec.rb +++ b/spec/ruby/core/file/ctime_spec.rb @@ -22,6 +22,9 @@ else File.ctime(__FILE__).usec.should == 0 end + rescue Errno::ENOENT => e + # Windows don't have stat command. + skip e.message end end diff --git a/spec/ruby/core/file/mtime_spec.rb b/spec/ruby/core/file/mtime_spec.rb index 5304bbf057bb1d..0e9c95caee310a 100644 --- a/spec/ruby/core/file/mtime_spec.rb +++ b/spec/ruby/core/file/mtime_spec.rb @@ -26,6 +26,9 @@ else File.mtime(__FILE__).usec.should == 0 end + rescue Errno::ENOENT => e + # Windows don't have stat command. + skip e.message end end end From 0a27142cf14635abfe1befadb86c1db25de6c2ca Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 12 Jan 2024 18:51:16 +0900 Subject: [PATCH 098/640] Ignore windows_31j module with mswin --- spec/ruby/core/kernel/require_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/ruby/core/kernel/require_spec.rb b/spec/ruby/core/kernel/require_spec.rb index 896afb840a6bbb..4029e68725cc31 100644 --- a/spec/ruby/core/kernel/require_spec.rb +++ b/spec/ruby/core/kernel/require_spec.rb @@ -26,7 +26,7 @@ features = out.lines.map { |line| File.basename(line.chomp, '.*') } # Ignore CRuby internals - features -= %w[encdb transdb windows_1252] + features -= %w[encdb transdb windows_1252 windows_31j] features.reject! { |feature| feature.end_with?('-fake') } features.sort.should == provided.sort From 5fa3259b130cc8fab2475ce2400b8d21f311dc7b Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 12 Jan 2024 19:09:02 +0900 Subject: [PATCH 099/640] Ruby 3.3 is always failed at spec/mspec/lib/mspec/runner/actions/constants_leak_checker.rb --- .github/workflows/spec_guards.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/spec_guards.yml b/.github/workflows/spec_guards.yml index f28c91d4af6dae..381a84d91751e9 100644 --- a/.github/workflows/spec_guards.yml +++ b/.github/workflows/spec_guards.yml @@ -43,7 +43,7 @@ jobs: - ruby-3.0 - ruby-3.1 - ruby-3.2 - - ruby-3.3 + # - ruby-3.3 steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 From c3b2436154015bab6b94f132b60bdb1fbba02426 Mon Sep 17 00:00:00 2001 From: yui-knk Date: Fri, 12 Jan 2024 12:56:08 +0900 Subject: [PATCH 100/640] `set_yylval_literal` is not used --- parse.y | 6 ------ 1 file changed, 6 deletions(-) diff --git a/parse.y b/parse.y index 08bd3fb97d4b84..2a2cfbe9cf7c74 100644 --- a/parse.y +++ b/parse.y @@ -7017,11 +7017,6 @@ do { \ set_yylval_node(NEW_STR(x, &_cur_loc)); \ RB_OBJ_WRITTEN(p->ast, Qnil, x); \ } while(0) -# define set_yylval_literal(x) \ -do { \ - set_yylval_node(NEW_LIT(x, &_cur_loc)); \ - RB_OBJ_WRITTEN(p->ast, Qnil, x); \ -} while(0) # define set_yylval_num(x) (yylval.num = (x)) # define set_yylval_id(x) (yylval.id = (x)) # define set_yylval_name(x) (yylval.id = (x)) @@ -7036,7 +7031,6 @@ ripper_yylval_id(struct parser_params *p, ID x) # define set_yylval_num(x) (yylval.val = ripper_new_yylval(p, (x), 0, 0)) # define set_yylval_id(x) (void)(x) # define set_yylval_name(x) (void)(yylval.val = ripper_yylval_id(p, x)) -# define set_yylval_literal(x) add_mark_object(p, (x)) # define set_yylval_node(x) (yylval.val = ripper_new_yylval(p, 0, 0, STR_NEW(p->lex.ptok, p->lex.pcur-p->lex.ptok))) # define yylval_id() yylval.id # define _cur_loc NULL_LOC /* dummy */ From 52d9e55903b2e72022ba90079cb23c6f2cd03af5 Mon Sep 17 00:00:00 2001 From: yui-knk Date: Thu, 11 Jan 2024 21:27:19 +0900 Subject: [PATCH 101/640] Statically allocate parser config --- ext/ripper/ripper_init.c.tmpl | 25 +- internal/ruby_parser.h | 3 +- node.c | 10 - parse.y | 24 -- ruby_parser.c | 441 ++++++++++++++++++---------------- rubyparser.h | 6 +- universal_parser.c | 4 +- 7 files changed, 244 insertions(+), 269 deletions(-) diff --git a/ext/ripper/ripper_init.c.tmpl b/ext/ripper/ripper_init.c.tmpl index 5c1a4e5bb5d6fc..b2caef2bd5bbc8 100644 --- a/ext/ripper/ripper_init.c.tmpl +++ b/ext/ripper/ripper_init.c.tmpl @@ -115,10 +115,7 @@ ripper_s_allocate(VALUE klass) &parser_data_type, r); #ifdef UNIVERSAL_PARSER - rb_parser_config_t *config; - config = rb_ruby_parser_config_new(ruby_xmalloc); - rb_parser_config_initialize(config); - r->p = rb_ruby_parser_allocate(config); + r->p = rb_parser_params_allocate(); #else r->p = rb_ruby_ripper_parser_allocate(); #endif @@ -260,11 +257,11 @@ parser_dedent_string0(VALUE a) } static VALUE -parser_config_free(VALUE a) +parser_free(VALUE a) { - rb_parser_config_t *config = (void *)a; + struct parser_params *p = (void *)a; - rb_ruby_parser_config_free(config); + rb_ruby_parser_free(p); return Qnil; } #endif @@ -283,17 +280,14 @@ static VALUE parser_dedent_string(VALUE self, VALUE input, VALUE width) { struct parser_params *p; - rb_parser_config_t *config; struct dedent_string_arg args; - config = rb_ruby_parser_config_new(ruby_xmalloc); - rb_parser_config_initialize(config); - p = rb_ruby_parser_new(config); + p = rb_parser_params_new(); args.p = p; args.input = input; args.width = width; - return rb_ensure(parser_dedent_string0, (VALUE)&args, parser_config_free, (VALUE)config); + return rb_ensure(parser_dedent_string0, (VALUE)&args, parser_free, (VALUE)p); } #else static VALUE @@ -530,17 +524,14 @@ static VALUE ripper_lex_state_name(VALUE self, VALUE state) { struct parser_params *p; - rb_parser_config_t *config; struct lex_state_name_arg args; - config = rb_ruby_parser_config_new(ruby_xmalloc); - rb_parser_config_initialize(config); - p = rb_ruby_parser_new(config); + p = rb_parser_params_new(); args.p = p; args.state = state; - return rb_ensure(lex_state_name0, (VALUE)&args, parser_config_free, (VALUE)config); + return rb_ensure(lex_state_name0, (VALUE)&args, parser_free, (VALUE)p); } #else static VALUE diff --git a/internal/ruby_parser.h b/internal/ruby_parser.h index 54e25276ee5b99..ddff2c364d7dee 100644 --- a/internal/ruby_parser.h +++ b/internal/ruby_parser.h @@ -12,7 +12,8 @@ RUBY_SYMBOL_EXPORT_BEGIN #ifdef UNIVERSAL_PARSER -void rb_parser_config_initialize(rb_parser_config_t *config); +rb_parser_t *rb_parser_params_allocate(void); +rb_parser_t *rb_parser_params_new(void); #endif VALUE rb_parser_set_context(VALUE, const struct rb_iseq_struct *, int); VALUE rb_parser_new(void); diff --git a/node.c b/node.c index e7644aeae3510b..9521238e38fb76 100644 --- a/node.c +++ b/node.c @@ -426,18 +426,8 @@ void rb_ast_free(rb_ast_t *ast) { if (ast->node_buffer) { -#ifdef UNIVERSAL_PARSER - rb_parser_config_t *config = ast->node_buffer->config; -#endif - rb_node_buffer_free(ast, ast->node_buffer); ast->node_buffer = 0; -#ifdef UNIVERSAL_PARSER - config->counter--; - if (config->counter <= 0) { - rb_ruby_parser_config_free(config); - } -#endif } } diff --git a/parse.y b/parse.y index 2a2cfbe9cf7c74..23ca4c8ddc88e8 100644 --- a/parse.y +++ b/parse.y @@ -15905,9 +15905,6 @@ rb_ruby_parser_free(void *ptr) { struct parser_params *p = (struct parser_params*)ptr; struct local_vars *local, *prev; -#ifdef UNIVERSAL_PARSER - rb_parser_config_t *config = p->config; -#endif if (p->tokenbuf) { ruby_sized_xfree(p->tokenbuf, p->toksiz); @@ -15926,13 +15923,6 @@ rb_ruby_parser_free(void *ptr) } } xfree(ptr); - -#ifdef UNIVERSAL_PARSER - config->counter--; - if (config->counter <= 0) { - rb_ruby_parser_config_free(config); - } -#endif } size_t @@ -15950,20 +15940,6 @@ rb_ruby_parser_memsize(const void *ptr) return size; } -#ifdef UNIVERSAL_PARSER -rb_parser_config_t * -rb_ruby_parser_config_new(void *(*malloc)(size_t size)) -{ - return (rb_parser_config_t *)malloc(sizeof(rb_parser_config_t)); -} - -void -rb_ruby_parser_config_free(rb_parser_config_t *config) -{ - config->free(config); -} -#endif - #ifndef UNIVERSAL_PARSER #ifndef RIPPER static const rb_data_type_t parser_data_type = { diff --git a/ruby_parser.c b/ruby_parser.c index 739bd3a86575d6..9f9b68064607b1 100644 --- a/ruby_parser.c +++ b/ruby_parser.c @@ -569,6 +569,18 @@ tmpbuf_parser_heap(void *buf, rb_imemo_tmpbuf_t *old_heap, size_t cnt) return rb_imemo_tmpbuf_parser_heap(buf, old_heap, cnt); } +static VALUE +arg_error(void) +{ + return rb_eArgError; +} + +static VALUE +ruby_vm_frozen_core(void) +{ + return rb_mRubyVMFrozenCore; +} + static int special_const_p(VALUE obj) { @@ -601,235 +613,242 @@ str_coderange_scan_restartable(const char *s, const char *e, void *enc, int *cr) } VALUE rb_io_gets_internal(VALUE io); +extern VALUE rb_eArgError; extern VALUE rb_mRubyVMFrozenCore; VALUE rb_node_case_when_optimizable_literal(const NODE *const node); -void -rb_parser_config_initialize(rb_parser_config_t *config) -{ - config->counter = 0; - - config->malloc = ruby_xmalloc; - config->calloc = ruby_xcalloc; - config->realloc = ruby_xrealloc; - config->free = ruby_xfree; - config->alloc_n = ruby_xmalloc2; - config->alloc = ruby_xmalloc; - config->realloc_n = ruby_xrealloc2; - config->zalloc = zalloc; - config->rb_memmove = memmove2; - config->nonempty_memcpy = nonempty_memcpy; - config->xmalloc_mul_add = rb_xmalloc_mul_add; - - config->tmpbuf_parser_heap = tmpbuf_parser_heap; - config->ast_new = ast_new; - - config->compile_callback = rb_suppress_tracing; - config->reg_named_capture_assign = reg_named_capture_assign; - - config->obj_freeze = rb_obj_freeze; - config->obj_hide = rb_obj_hide; - config->obj_frozen = obj_frozen; - config->type_p = type_p; - config->obj_freeze_raw = OBJ_FREEZE_RAW; - - config->fixnum_p = fixnum_p; - config->symbol_p = symbol_p; - - config->attr_get = rb_attr_get; - - config->ary_new = rb_ary_new; - config->ary_push = rb_ary_push; - config->ary_new_from_args = rb_ary_new_from_args; - config->ary_pop = rb_ary_pop; - config->ary_last = rb_ary_last; - config->ary_unshift = rb_ary_unshift; - config->ary_new2 = rb_ary_new2; - config->ary_entry = rb_ary_entry; - config->ary_join = rb_ary_join; - config->ary_reverse = rb_ary_reverse; - config->ary_clear = rb_ary_clear; - config->ary_modify = rb_ary_modify; - config->array_len = rb_array_len; - config->array_aref = RARRAY_AREF; - - config->sym_intern_ascii_cstr = rb_sym_intern_ascii_cstr; - config->make_temporary_id = rb_make_temporary_id; - config->is_local_id = is_local_id2; - config->is_attrset_id = is_attrset_id2; - config->is_global_name_punct = is_global_name_punct; - config->id_type = id_type; - config->id_attrset = rb_id_attrset; - config->intern = rb_intern; - config->intern2 = rb_intern2; - config->intern3 = intern3; - config->intern_str = rb_intern_str; - config->is_notop_id = is_notop_id2; - config->enc_symname_type = enc_symname_type; - config->str_intern = rb_str_intern; - config->id2name = rb_id2name; - config->id2str = rb_id2str; - config->id2sym = rb_id2sym; - config->sym2id = rb_sym2id; - - config->str_catf = rb_str_catf; - config->str_cat_cstr = rb_str_cat_cstr; - config->str_subseq = rb_str_subseq; - config->str_dup = rb_str_dup; - config->str_new_frozen = rb_str_new_frozen; - config->str_buf_new = rb_str_buf_new; - config->str_buf_cat = rb_str_buf_cat; - config->str_modify = rb_str_modify; - config->str_set_len = rb_str_set_len; - config->str_cat = rb_str_cat; - config->str_resize = rb_str_resize; - config->str_new = rb_str_new; - config->str_new_cstr = rb_str_new_cstr; - config->fstring = rb_fstring; - config->is_ascii_string = is_ascii_string2; - config->enc_str_new = enc_str_new; - config->enc_str_buf_cat = enc_str_buf_cat; - config->str_buf_append = rb_str_buf_append; - config->str_vcatf = rb_str_vcatf; - config->string_value_cstr = rb_string_value_cstr; - config->rb_sprintf = rb_sprintf; - config->rstring_ptr = RSTRING_PTR; - config->rstring_end = RSTRING_END; - config->rstring_len = RSTRING_LEN; - config->filesystem_str_new_cstr = rb_filesystem_str_new_cstr; - config->obj_as_string = rb_obj_as_string; - - config->hash_clear = rb_hash_clear; - config->hash_new = rb_hash_new; - config->hash_aset = rb_hash_aset; - config->hash_lookup = rb_hash_lookup; - config->hash_delete = rb_hash_delete; - config->ident_hash_new = rb_ident_hash_new; - - config->num2int = rb_num2int_inline; - config->int2num = rb_int2num_inline; - - config->stderr_tty_p = rb_stderr_tty_p; - config->write_error_str = rb_write_error_str; - config->default_rs = default_rs; - config->io_write = rb_io_write; - config->io_flush = rb_io_flush; - config->io_puts = rb_io_puts; - config->io_gets_internal= rb_io_gets_internal; - - config->debug_output_stdout = rb_ractor_stdout; - config->debug_output_stderr = rb_ractor_stderr; - - config->is_usascii_enc = is_usascii_enc; - config->enc_isalnum = enc_isalnum; - config->enc_precise_mbclen = enc_precise_mbclen; - config->mbclen_charfound_p = mbclen_charfound_p; - config->enc_name = enc_name; - config->enc_prev_char = enc_prev_char; - config->enc_get = enc_get; - config->enc_asciicompat = enc_asciicompat; - config->utf8_encoding = utf8_encoding; - config->enc_associate = enc_associate; - config->ascii8bit_encoding = ascii8bit_encoding; - config->enc_codelen = enc_codelen; - config->enc_mbcput = enc_mbcput; - config->char_to_option_kcode = rb_char_to_option_kcode; - config->ascii8bit_encindex = rb_ascii8bit_encindex; - config->enc_find_index = rb_enc_find_index; - config->enc_from_index = enc_from_index; - config->enc_associate_index = rb_enc_associate_index; - config->enc_isspace = enc_isspace; - config->enc_coderange_7bit = ENC_CODERANGE_7BIT; - config->enc_coderange_unknown = ENC_CODERANGE_UNKNOWN; - config->enc_compatible = enc_compatible; - config->enc_from_encoding = enc_from_encoding; - config->encoding_get = encoding_get; - config->encoding_set = encoding_set; - config->encoding_is_ascii8bit = encoding_is_ascii8bit; - config->usascii_encoding = usascii_encoding; - - config->ractor_make_shareable = rb_ractor_make_shareable; - - config->local_defined = local_defined; - config->dvar_defined = dvar_defined; - - config->literal_cmp = literal_cmp; - config->literal_hash = literal_hash; - - config->syntax_error_append = syntax_error_append; - config->raise = rb_raise; - config->syntax_error_new = syntax_error_new; - - config->errinfo = rb_errinfo; - config->set_errinfo = rb_set_errinfo; - config->exc_raise = rb_exc_raise; - config->make_exception = rb_make_exception; - - config->sized_xfree = ruby_sized_xfree; - config->sized_realloc_n = ruby_sized_realloc_n; - config->obj_write = obj_write; - config->obj_written = obj_written; - config->gc_register_mark_object = rb_gc_register_mark_object; - config->gc_guard = gc_guard; - config->gc_mark = rb_gc_mark; - config->gc_mark_movable = rb_gc_mark_movable; - config->gc_location = rb_gc_location; - - config->reg_compile = rb_reg_compile; - config->reg_check_preprocess = rb_reg_check_preprocess; - config->memcicmp = rb_memcicmp; - - config->compile_warn = rb_compile_warn; - config->compile_warning = rb_compile_warning; - config->bug = rb_bug; - config->fatal = rb_fatal; - config->verbose = ruby_verbose2; - config->errno_ptr = rb_errno_ptr2; - - config->make_backtrace = rb_make_backtrace; - - config->scan_hex = ruby_scan_hex; - config->scan_oct = ruby_scan_oct; - config->scan_digits = ruby_scan_digits; - config->strtod = ruby_strtod; - - config->rbool = rbool; - config->undef_p = undef_p; - config->rtest = rtest; - config->nil_p = nil_p; - config->qnil = Qnil; - config->qtrue = Qtrue; - config->qfalse = Qfalse; - config->qundef = Qundef; - config->eArgError = rb_eArgError; - config->mRubyVMFrozenCore = rb_mRubyVMFrozenCore; - config->long2int = rb_long2int; - config->special_const_p = special_const_p; - config->builtin_type = builtin_type; - - config->node_case_when_optimizable_literal = rb_node_case_when_optimizable_literal; +rb_parser_config_t rb_global_parser_config = (rb_parser_config_t) { + .counter = 0, + + .malloc = ruby_xmalloc, + .calloc = ruby_xcalloc, + .realloc = ruby_xrealloc, + .free = ruby_xfree, + .alloc_n = ruby_xmalloc2, + .alloc = ruby_xmalloc, + .realloc_n = ruby_xrealloc2, + .zalloc = zalloc, + .rb_memmove = memmove2, + .nonempty_memcpy = nonempty_memcpy, + .xmalloc_mul_add = rb_xmalloc_mul_add, + + .tmpbuf_parser_heap = tmpbuf_parser_heap, + .ast_new = ast_new, + + .compile_callback = rb_suppress_tracing, + .reg_named_capture_assign = reg_named_capture_assign, + + .obj_freeze = rb_obj_freeze, + .obj_hide = rb_obj_hide, + .obj_frozen = obj_frozen, + .type_p = type_p, + .obj_freeze_raw = OBJ_FREEZE_RAW, + + .fixnum_p = fixnum_p, + .symbol_p = symbol_p, + + .attr_get = rb_attr_get, + + .ary_new = rb_ary_new, + .ary_push = rb_ary_push, + .ary_new_from_args = rb_ary_new_from_args, + .ary_pop = rb_ary_pop, + .ary_last = rb_ary_last, + .ary_unshift = rb_ary_unshift, + .ary_new2 = rb_ary_new2, + .ary_entry = rb_ary_entry, + .ary_join = rb_ary_join, + .ary_reverse = rb_ary_reverse, + .ary_clear = rb_ary_clear, + .ary_modify = rb_ary_modify, + .array_len = rb_array_len, + .array_aref = RARRAY_AREF, + + .sym_intern_ascii_cstr = rb_sym_intern_ascii_cstr, + .make_temporary_id = rb_make_temporary_id, + .is_local_id = is_local_id2, + .is_attrset_id = is_attrset_id2, + .is_global_name_punct = is_global_name_punct, + .id_type = id_type, + .id_attrset = rb_id_attrset, + .intern = rb_intern, + .intern2 = rb_intern2, + .intern3 = intern3, + .intern_str = rb_intern_str, + .is_notop_id = is_notop_id2, + .enc_symname_type = enc_symname_type, + .str_intern = rb_str_intern, + .id2name = rb_id2name, + .id2str = rb_id2str, + .id2sym = rb_id2sym, + .sym2id = rb_sym2id, + + .str_catf = rb_str_catf, + .str_cat_cstr = rb_str_cat_cstr, + .str_subseq = rb_str_subseq, + .str_dup = rb_str_dup, + .str_new_frozen = rb_str_new_frozen, + .str_buf_new = rb_str_buf_new, + .str_buf_cat = rb_str_buf_cat, + .str_modify = rb_str_modify, + .str_set_len = rb_str_set_len, + .str_cat = rb_str_cat, + .str_resize = rb_str_resize, + .str_new = rb_str_new, + .str_new_cstr = rb_str_new_cstr, + .fstring = rb_fstring, + .is_ascii_string = is_ascii_string2, + .enc_str_new = enc_str_new, + .enc_str_buf_cat = enc_str_buf_cat, + .str_buf_append = rb_str_buf_append, + .str_vcatf = rb_str_vcatf, + .string_value_cstr = rb_string_value_cstr, + .rb_sprintf = rb_sprintf, + .rstring_ptr = RSTRING_PTR, + .rstring_end = RSTRING_END, + .rstring_len = RSTRING_LEN, + .filesystem_str_new_cstr = rb_filesystem_str_new_cstr, + .obj_as_string = rb_obj_as_string, + + .hash_clear = rb_hash_clear, + .hash_new = rb_hash_new, + .hash_aset = rb_hash_aset, + .hash_delete = rb_hash_delete, + .hash_lookup = rb_hash_lookup, + .ident_hash_new = rb_ident_hash_new, + + .num2int = rb_num2int_inline, + .int2num = rb_int2num_inline, + + .stderr_tty_p = rb_stderr_tty_p, + .write_error_str = rb_write_error_str, + .default_rs = default_rs, + .io_write = rb_io_write, + .io_flush = rb_io_flush, + .io_puts = rb_io_puts, + .io_gets_internal = rb_io_gets_internal, + + .debug_output_stdout = rb_ractor_stdout, + .debug_output_stderr = rb_ractor_stderr, + + .is_usascii_enc = is_usascii_enc, + .enc_isalnum = enc_isalnum, + .enc_precise_mbclen = enc_precise_mbclen, + .mbclen_charfound_p = mbclen_charfound_p, + .enc_name = enc_name, + .enc_prev_char = enc_prev_char, + .enc_get = enc_get, + .enc_asciicompat = enc_asciicompat, + .utf8_encoding = utf8_encoding, + .enc_associate = enc_associate, + .ascii8bit_encoding = ascii8bit_encoding, + .enc_codelen = enc_codelen, + .enc_mbcput = enc_mbcput, + .char_to_option_kcode = rb_char_to_option_kcode, + .ascii8bit_encindex = rb_ascii8bit_encindex, + .enc_find_index = rb_enc_find_index, + .enc_from_index = enc_from_index, + .enc_associate_index = rb_enc_associate_index, + .enc_isspace = enc_isspace, + .enc_coderange_7bit = ENC_CODERANGE_7BIT, + .enc_coderange_unknown = ENC_CODERANGE_UNKNOWN, + .enc_compatible = enc_compatible, + .enc_from_encoding = enc_from_encoding, + .encoding_get = encoding_get, + .encoding_set = encoding_set, + .encoding_is_ascii8bit = encoding_is_ascii8bit, + .usascii_encoding = usascii_encoding, + + .ractor_make_shareable = rb_ractor_make_shareable, + + .local_defined = local_defined, + .dvar_defined = dvar_defined, + + .literal_cmp = literal_cmp, + .literal_hash = literal_hash, + + .syntax_error_append = syntax_error_append, + .raise = rb_raise, + .syntax_error_new = syntax_error_new, + + .errinfo = rb_errinfo, + .set_errinfo = rb_set_errinfo, + .exc_raise = rb_exc_raise, + .make_exception = rb_make_exception, + + .sized_xfree = ruby_sized_xfree, + .sized_realloc_n = ruby_sized_realloc_n, + .obj_write = obj_write, + .obj_written = obj_written, + .gc_register_mark_object = rb_gc_register_mark_object, + .gc_guard = gc_guard, + .gc_mark = rb_gc_mark, + .gc_mark_movable = rb_gc_mark_movable, + .gc_location = rb_gc_location, + + .reg_compile = rb_reg_compile, + .reg_check_preprocess = rb_reg_check_preprocess, + .memcicmp = rb_memcicmp, + + .compile_warn = rb_compile_warn, + .compile_warning = rb_compile_warning, + .bug = rb_bug, + .fatal = rb_fatal, + .verbose = ruby_verbose2, + .errno_ptr = rb_errno_ptr2, + + .make_backtrace = rb_make_backtrace, + + .scan_hex = ruby_scan_hex, + .scan_oct = ruby_scan_oct, + .scan_digits = ruby_scan_digits, + .strtod = ruby_strtod, + + .rbool = rbool, + .undef_p = undef_p, + .rtest = rtest, + .nil_p = nil_p, + .qnil = Qnil, + .qtrue = Qtrue, + .qfalse = Qfalse, + .qundef = Qundef, + .eArgError = arg_error, + .mRubyVMFrozenCore = ruby_vm_frozen_core, + .long2int = rb_long2int, + .special_const_p = special_const_p, + .builtin_type = builtin_type, + + .node_case_when_optimizable_literal = rb_node_case_when_optimizable_literal, /* For Ripper */ - config->static_id2sym = static_id2sym; - config->str_coderange_scan_restartable = str_coderange_scan_restartable; + .static_id2sym = static_id2sym, + .str_coderange_scan_restartable = str_coderange_scan_restartable, +}; + +rb_parser_t * +rb_parser_params_allocate(void) +{ + return rb_ruby_parser_allocate(&rb_global_parser_config); +} + +rb_parser_t * +rb_parser_params_new(void) +{ + return rb_ruby_parser_new(&rb_global_parser_config); } VALUE rb_parser_new(void) { struct ruby_parser *parser; - rb_parser_config_t *config; rb_parser_t *parser_params; - config = rb_ruby_parser_config_new(ruby_xmalloc); - rb_parser_config_initialize(config); - /* * Create parser_params ahead of vparser because * rb_ruby_parser_new can run GC so if create vparser * first, parser_mark tries to mark not initialized parser_params. */ - parser_params = rb_ruby_parser_new(config); + parser_params = rb_parser_params_new(); VALUE vparser = TypedData_Make_Struct(0, struct ruby_parser, &ruby_parser_data_type, parser); parser->parser_params = parser_params; diff --git a/rubyparser.h b/rubyparser.h index 4b37cf688347b8..e78df79e7ab0d1 100644 --- a/rubyparser.h +++ b/rubyparser.h @@ -1425,8 +1425,8 @@ typedef struct rb_parser_config_struct { VALUE qtrue; VALUE qfalse; VALUE qundef; - VALUE eArgError; - VALUE mRubyVMFrozenCore; + VALUE (*eArgError)(void); + VALUE (*mRubyVMFrozenCore)(void); int (*long2int)(long); int (*special_const_p)(VALUE); int (*builtin_type)(VALUE); @@ -1447,8 +1447,6 @@ void rb_ruby_parser_free(void *ptr); rb_ast_t* rb_ruby_parser_compile_string(rb_parser_t *p, const char *f, VALUE s, int line); #ifdef UNIVERSAL_PARSER -rb_parser_config_t *rb_ruby_parser_config_new(void *(*malloc)(size_t size)); -void rb_ruby_parser_config_free(rb_parser_config_t *config); rb_parser_t *rb_ruby_parser_allocate(rb_parser_config_t *config); rb_parser_t *rb_ruby_parser_new(rb_parser_config_t *config); #endif diff --git a/universal_parser.c b/universal_parser.c index 9e067b6424aeee..6107b09995a33f 100644 --- a/universal_parser.c +++ b/universal_parser.c @@ -326,8 +326,8 @@ struct rb_imemo_tmpbuf_struct { #define Qfalse p->config->qfalse #undef Qundef #define Qundef p->config->qundef -#define rb_eArgError p->config->eArgError -#define rb_mRubyVMFrozenCore p->config->mRubyVMFrozenCore +#define rb_eArgError p->config->eArgError() +#define rb_mRubyVMFrozenCore p->config->mRubyVMFrozenCore() #undef rb_long2int #define rb_long2int p->config->long2int #undef SPECIAL_CONST_P From b35e21b3889e95cf727f2da49abb881c3466bc75 Mon Sep 17 00:00:00 2001 From: yui-knk Date: Fri, 12 Jan 2024 07:38:02 +0900 Subject: [PATCH 102/640] Remove reference counter from rb_parser_config It's allocated outside of parser then no need to track reference count in rb_parser_config. --- node.c | 1 - parse.y | 1 - ruby_parser.c | 2 -- rubyparser.h | 8 -------- 4 files changed, 12 deletions(-) diff --git a/node.c b/node.c index 9521238e38fb76..79ef00f1b76944 100644 --- a/node.c +++ b/node.c @@ -321,7 +321,6 @@ rb_ast_t * rb_ast_new(rb_parser_config_t *config) { node_buffer_t *nb = rb_node_buffer_new(config); - config->counter++; return config->ast_new((VALUE)nb); } #else diff --git a/parse.y b/parse.y index 23ca4c8ddc88e8..6ebb237181f72d 100644 --- a/parse.y +++ b/parse.y @@ -15970,7 +15970,6 @@ rb_ruby_parser_allocate(rb_parser_config_t *config) /* parser_initialize expects fields to be set to 0 */ rb_parser_t *p = (rb_parser_t *)config->calloc(1, sizeof(rb_parser_t)); p->config = config; - p->config->counter++; return p; } diff --git a/ruby_parser.c b/ruby_parser.c index 9f9b68064607b1..47dc54df6cc62f 100644 --- a/ruby_parser.c +++ b/ruby_parser.c @@ -618,8 +618,6 @@ extern VALUE rb_mRubyVMFrozenCore; VALUE rb_node_case_when_optimizable_literal(const NODE *const node); rb_parser_config_t rb_global_parser_config = (rb_parser_config_t) { - .counter = 0, - .malloc = ruby_xmalloc, .calloc = ruby_xcalloc, .realloc = ruby_xrealloc, diff --git a/rubyparser.h b/rubyparser.h index e78df79e7ab0d1..974a03992ca57e 100644 --- a/rubyparser.h +++ b/rubyparser.h @@ -1194,14 +1194,6 @@ typedef struct rb_imemo_tmpbuf_struct rb_imemo_tmpbuf_t; #ifdef UNIVERSAL_PARSER typedef struct rb_parser_config_struct { - /* - * Reference counter. - * This is needed because both parser and ast refer - * same config pointer. - * We can remove this, once decuple parser and ast from Ruby GC. - */ - int counter; - /* Memory */ void *(*malloc)(size_t size); void *(*calloc)(size_t number, size_t size); From 731fee04c29b31d780b1bfeb878a43355658daa7 Mon Sep 17 00:00:00 2001 From: yui-knk Date: Sun, 7 Jan 2024 10:49:18 +0900 Subject: [PATCH 103/640] Use `BUILTIN_TYPE` because SPECIAL_CONST or not is already checked --- ruby_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruby_parser.c b/ruby_parser.c index 47dc54df6cc62f..31008e2f756ccc 100644 --- a/ruby_parser.c +++ b/ruby_parser.c @@ -17,7 +17,7 @@ compile_negative_numeric(VALUE val) } #endif } - switch (OBJ_BUILTIN_TYPE(val)) { + switch (BUILTIN_TYPE(val)) { case T_BIGNUM: BIGNUM_NEGATE(val); val = rb_big_norm(val); From 5a471784ca45379672db46aef759087148ad4877 Mon Sep 17 00:00:00 2001 From: yui-knk Date: Sun, 7 Jan 2024 11:00:59 +0900 Subject: [PATCH 104/640] Restore unknown case This existed before 1b8d01136c3ff6c60325c7609d61e19ac42acd9f. --- common.mk | 2 ++ ruby_parser.c | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/common.mk b/common.mk index 5a929fc937fbef..c4b6dec1533680 100644 --- a/common.mk +++ b/common.mk @@ -15876,6 +15876,7 @@ ruby_parser.$(OBJEXT): $(top_srcdir)/internal/bignum.h ruby_parser.$(OBJEXT): $(top_srcdir)/internal/bits.h ruby_parser.$(OBJEXT): $(top_srcdir)/internal/compilers.h ruby_parser.$(OBJEXT): $(top_srcdir)/internal/complex.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/error.h ruby_parser.$(OBJEXT): $(top_srcdir)/internal/fixnum.h ruby_parser.$(OBJEXT): $(top_srcdir)/internal/imemo.h ruby_parser.$(OBJEXT): $(top_srcdir)/internal/numeric.h @@ -15883,6 +15884,7 @@ ruby_parser.$(OBJEXT): $(top_srcdir)/internal/rational.h ruby_parser.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h ruby_parser.$(OBJEXT): $(top_srcdir)/internal/serial.h ruby_parser.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/string.h ruby_parser.$(OBJEXT): $(top_srcdir)/internal/vm.h ruby_parser.$(OBJEXT): {$(VPATH)}assert.h ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/assume.h diff --git a/ruby_parser.c b/ruby_parser.c index 31008e2f756ccc..286756840c612b 100644 --- a/ruby_parser.c +++ b/ruby_parser.c @@ -3,6 +3,7 @@ #include "internal/ruby_parser.h" #include "rubyparser.h" +#include "internal/error.h" static VALUE compile_negative_numeric(VALUE val) @@ -16,6 +17,7 @@ compile_negative_numeric(VALUE val) return DBL2NUM(-RFLOAT_VALUE(val)); } #endif + goto unknown; } switch (BUILTIN_TYPE(val)) { case T_BIGNUM: @@ -32,8 +34,10 @@ compile_negative_numeric(VALUE val) case T_FLOAT: val = DBL2NUM(-RFLOAT_VALUE(val)); break; + unknown: default: - val = LONG2FIX(-FIX2LONG(val)); + rb_bug("unknown literal type (%s) passed to compile_negative_numeric", + rb_builtin_class_name(val)); break; } return val; @@ -145,7 +149,6 @@ rb_node_imaginary_literal_val(const NODE *n) #include "internal/compile.h" #include "internal/complex.h" #include "internal/encoding.h" -#include "internal/error.h" #include "internal/gc.h" #include "internal/hash.h" #include "internal/io.h" From 631eb2a110fbf3446882747e7e5d8c0be8473904 Mon Sep 17 00:00:00 2001 From: yui-knk Date: Thu, 11 Jan 2024 18:40:11 +0900 Subject: [PATCH 105/640] Rename node value functions They don't compile nodes then remove compile_ prefix. `compile_numeric_literal` always returns integer then use integer instead of numeric. --- ruby_parser.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/ruby_parser.c b/ruby_parser.c index 286756840c612b..23cb9ddd726e8d 100644 --- a/ruby_parser.c +++ b/ruby_parser.c @@ -6,7 +6,7 @@ #include "internal/error.h" static VALUE -compile_negative_numeric(VALUE val) +negative_numeric(VALUE val) { if (FIXNUM_P(val)) { return LONG2FIX(-FIX2LONG(val)); @@ -25,18 +25,18 @@ compile_negative_numeric(VALUE val) val = rb_big_norm(val); break; case T_RATIONAL: - RATIONAL_SET_NUM(val, compile_negative_numeric(RRATIONAL(val)->num)); + RATIONAL_SET_NUM(val, negative_numeric(RRATIONAL(val)->num)); break; case T_COMPLEX: - RCOMPLEX_SET_REAL(val, compile_negative_numeric(RCOMPLEX(val)->real)); - RCOMPLEX_SET_IMAG(val, compile_negative_numeric(RCOMPLEX(val)->imag)); + RCOMPLEX_SET_REAL(val, negative_numeric(RCOMPLEX(val)->real)); + RCOMPLEX_SET_IMAG(val, negative_numeric(RCOMPLEX(val)->imag)); break; case T_FLOAT: val = DBL2NUM(-RFLOAT_VALUE(val)); break; unknown: default: - rb_bug("unknown literal type (%s) passed to compile_negative_numeric", + rb_bug("unknown literal type (%s) passed to negative_numeric", rb_builtin_class_name(val)); break; } @@ -44,7 +44,7 @@ compile_negative_numeric(VALUE val) } static VALUE -compile_numeric_literal(const char *val, int base) +integer_value(const char *val, int base) { return rb_cstr_to_inum(val, base, FALSE); } @@ -53,9 +53,9 @@ VALUE rb_node_integer_literal_val(const NODE *n) { const rb_node_integer_t *node = RNODE_INTEGER(n); - VALUE val = compile_numeric_literal(node->val, node->base); + VALUE val = integer_value(node->val, node->base); if (node->minus) { - val = compile_negative_numeric(val); + val = negative_numeric(val); } return val; } @@ -73,7 +73,7 @@ rb_node_float_literal_val(const NODE *n) } static VALUE -compile_rational_literal(const char *node_val, int base, int seen_point) +rational_value(const char *node_val, int base, int seen_point) { VALUE lit; char* val = strdup(node_val); @@ -83,10 +83,10 @@ compile_rational_literal(const char *node_val, int base, int seen_point) size_t fraclen = len-seen_point-1; memmove(point, point+1, fraclen+1); - lit = rb_rational_new(compile_numeric_literal(val, base), rb_int_positive_pow(10, fraclen)); + lit = rb_rational_new(integer_value(val, base), rb_int_positive_pow(10, fraclen)); } else { - lit = rb_rational_raw1(compile_numeric_literal(val, base)); + lit = rb_rational_raw1(integer_value(val, base)); } free(val); @@ -100,10 +100,10 @@ rb_node_rational_literal_val(const NODE *n) VALUE lit; const rb_node_rational_t *node = RNODE_RATIONAL(n); - lit = compile_rational_literal(node->val, node->base, node->seen_point); + lit = rational_value(node->val, node->base, node->seen_point); if (node->minus) { - lit = compile_negative_numeric(lit); + lit = negative_numeric(lit); } return lit; @@ -119,7 +119,7 @@ rb_node_imaginary_literal_val(const NODE *n) switch (type) { case integer_literal: - lit = compile_numeric_literal(node->val, node->base); + lit = integer_value(node->val, node->base); break; case float_literal:{ double d = strtod(node->val, 0); @@ -127,7 +127,7 @@ rb_node_imaginary_literal_val(const NODE *n) break; } case rational_literal: - lit = compile_rational_literal(node->val, node->base, node->seen_point); + lit = rational_value(node->val, node->base, node->seen_point); break; default: rb_bug("unreachable"); @@ -136,7 +136,7 @@ rb_node_imaginary_literal_val(const NODE *n) lit = rb_complex_raw(INT2FIX(0), lit); if (node->minus) { - lit = compile_negative_numeric(lit); + lit = negative_numeric(lit); } return lit; } From 517e0d87bd3e9c5b2e36764c3774c75dea19fbba Mon Sep 17 00:00:00 2001 From: yui-knk Date: Thu, 11 Jan 2024 18:42:52 +0900 Subject: [PATCH 106/640] Move node value functions closer to other similar functions --- ruby_parser.c | 272 +++++++++++++++++++++++++------------------------- 1 file changed, 136 insertions(+), 136 deletions(-) diff --git a/ruby_parser.c b/ruby_parser.c index 23cb9ddd726e8d..a76a8231f5c780 100644 --- a/ruby_parser.c +++ b/ruby_parser.c @@ -5,142 +5,6 @@ #include "rubyparser.h" #include "internal/error.h" -static VALUE -negative_numeric(VALUE val) -{ - if (FIXNUM_P(val)) { - return LONG2FIX(-FIX2LONG(val)); - } - if (SPECIAL_CONST_P(val)) { -#if USE_FLONUM - if (FLONUM_P(val)) { - return DBL2NUM(-RFLOAT_VALUE(val)); - } -#endif - goto unknown; - } - switch (BUILTIN_TYPE(val)) { - case T_BIGNUM: - BIGNUM_NEGATE(val); - val = rb_big_norm(val); - break; - case T_RATIONAL: - RATIONAL_SET_NUM(val, negative_numeric(RRATIONAL(val)->num)); - break; - case T_COMPLEX: - RCOMPLEX_SET_REAL(val, negative_numeric(RCOMPLEX(val)->real)); - RCOMPLEX_SET_IMAG(val, negative_numeric(RCOMPLEX(val)->imag)); - break; - case T_FLOAT: - val = DBL2NUM(-RFLOAT_VALUE(val)); - break; - unknown: - default: - rb_bug("unknown literal type (%s) passed to negative_numeric", - rb_builtin_class_name(val)); - break; - } - return val; -} - -static VALUE -integer_value(const char *val, int base) -{ - return rb_cstr_to_inum(val, base, FALSE); -} - -VALUE -rb_node_integer_literal_val(const NODE *n) -{ - const rb_node_integer_t *node = RNODE_INTEGER(n); - VALUE val = integer_value(node->val, node->base); - if (node->minus) { - val = negative_numeric(val); - } - return val; -} - -VALUE -rb_node_float_literal_val(const NODE *n) -{ - const rb_node_float_t *node = RNODE_FLOAT(n); - double d = strtod(node->val, 0); - if (node->minus) { - d = -d; - } - VALUE val = DBL2NUM(d); - return val; -} - -static VALUE -rational_value(const char *node_val, int base, int seen_point) -{ - VALUE lit; - char* val = strdup(node_val); - if (seen_point > 0) { - int len = (int)(strlen(val)); - char *point = &val[seen_point]; - size_t fraclen = len-seen_point-1; - memmove(point, point+1, fraclen+1); - - lit = rb_rational_new(integer_value(val, base), rb_int_positive_pow(10, fraclen)); - } - else { - lit = rb_rational_raw1(integer_value(val, base)); - } - - free(val); - - return lit; -} - -VALUE -rb_node_rational_literal_val(const NODE *n) -{ - VALUE lit; - const rb_node_rational_t *node = RNODE_RATIONAL(n); - - lit = rational_value(node->val, node->base, node->seen_point); - - if (node->minus) { - lit = negative_numeric(lit); - } - - return lit; -} - -VALUE -rb_node_imaginary_literal_val(const NODE *n) -{ - VALUE lit; - const rb_node_imaginary_t *node = RNODE_IMAGINARY(n); - - enum rb_numeric_type type = node->type; - - switch (type) { - case integer_literal: - lit = integer_value(node->val, node->base); - break; - case float_literal:{ - double d = strtod(node->val, 0); - lit = DBL2NUM(d); - break; - } - case rational_literal: - lit = rational_value(node->val, node->base, node->seen_point); - break; - default: - rb_bug("unreachable"); - } - - lit = rb_complex_raw(INT2FIX(0), lit); - - if (node->minus) { - lit = negative_numeric(lit); - } - return lit; -} - #ifdef UNIVERSAL_PARSER #include "internal.h" @@ -984,6 +848,142 @@ rb_parser_set_yydebug(VALUE vparser, VALUE flag) } #endif +static VALUE +negative_numeric(VALUE val) +{ + if (FIXNUM_P(val)) { + return LONG2FIX(-FIX2LONG(val)); + } + if (SPECIAL_CONST_P(val)) { +#if USE_FLONUM + if (FLONUM_P(val)) { + return DBL2NUM(-RFLOAT_VALUE(val)); + } +#endif + goto unknown; + } + switch (BUILTIN_TYPE(val)) { + case T_BIGNUM: + BIGNUM_NEGATE(val); + val = rb_big_norm(val); + break; + case T_RATIONAL: + RATIONAL_SET_NUM(val, negative_numeric(RRATIONAL(val)->num)); + break; + case T_COMPLEX: + RCOMPLEX_SET_REAL(val, negative_numeric(RCOMPLEX(val)->real)); + RCOMPLEX_SET_IMAG(val, negative_numeric(RCOMPLEX(val)->imag)); + break; + case T_FLOAT: + val = DBL2NUM(-RFLOAT_VALUE(val)); + break; + unknown: + default: + rb_bug("unknown literal type (%s) passed to negative_numeric", + rb_builtin_class_name(val)); + break; + } + return val; +} + +static VALUE +integer_value(const char *val, int base) +{ + return rb_cstr_to_inum(val, base, FALSE); +} + +static VALUE +rational_value(const char *node_val, int base, int seen_point) +{ + VALUE lit; + char* val = strdup(node_val); + if (seen_point > 0) { + int len = (int)(strlen(val)); + char *point = &val[seen_point]; + size_t fraclen = len-seen_point-1; + memmove(point, point+1, fraclen+1); + + lit = rb_rational_new(integer_value(val, base), rb_int_positive_pow(10, fraclen)); + } + else { + lit = rb_rational_raw1(integer_value(val, base)); + } + + free(val); + + return lit; +} + +VALUE +rb_node_integer_literal_val(const NODE *n) +{ + const rb_node_integer_t *node = RNODE_INTEGER(n); + VALUE val = integer_value(node->val, node->base); + if (node->minus) { + val = negative_numeric(val); + } + return val; +} + +VALUE +rb_node_float_literal_val(const NODE *n) +{ + const rb_node_float_t *node = RNODE_FLOAT(n); + double d = strtod(node->val, 0); + if (node->minus) { + d = -d; + } + VALUE val = DBL2NUM(d); + return val; +} + +VALUE +rb_node_rational_literal_val(const NODE *n) +{ + VALUE lit; + const rb_node_rational_t *node = RNODE_RATIONAL(n); + + lit = rational_value(node->val, node->base, node->seen_point); + + if (node->minus) { + lit = negative_numeric(lit); + } + + return lit; +} + +VALUE +rb_node_imaginary_literal_val(const NODE *n) +{ + VALUE lit; + const rb_node_imaginary_t *node = RNODE_IMAGINARY(n); + + enum rb_numeric_type type = node->type; + + switch (type) { + case integer_literal: + lit = integer_value(node->val, node->base); + break; + case float_literal:{ + double d = strtod(node->val, 0); + lit = DBL2NUM(d); + break; + } + case rational_literal: + lit = rational_value(node->val, node->base, node->seen_point); + break; + default: + rb_bug("unreachable"); + } + + lit = rb_complex_raw(INT2FIX(0), lit); + + if (node->minus) { + lit = negative_numeric(lit); + } + return lit; +} + VALUE rb_node_sym_string_val(const NODE *node) { From 8292b01c66ade80f20ea02f0d512d28ed074f290 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 12 Jan 2024 22:44:56 +0900 Subject: [PATCH 107/640] [DOC] Mark up the class name `fatal` --- error.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/error.c b/error.c index f972ac807bc569..104e659ddefee7 100644 --- a/error.c +++ b/error.c @@ -3134,7 +3134,7 @@ syserr_eqq(VALUE self, VALUE exc) /* * Document-class: fatal * - * fatal is an Exception that is raised when Ruby has encountered a fatal + * +fatal+ is an Exception that is raised when Ruby has encountered a fatal * error and must exit. */ From 524770d3dc8f44a5caca5533f22297d1e0dd5d32 Mon Sep 17 00:00:00 2001 From: S-H-GAMELINKS Date: Fri, 12 Jan 2024 00:43:50 +0900 Subject: [PATCH 108/640] Suppress warnings in parser_set_encode function --- parse.y | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/parse.y b/parse.y index 6ebb237181f72d..568a8c27e7f374 100644 --- a/parse.y +++ b/parse.y @@ -9473,6 +9473,7 @@ parser_set_encode(struct parser_params *p, const char *name) { rb_encoding *enc; VALUE excargs[3]; + int idx = 0; const char *wrong = 0; switch (*name) { @@ -9482,7 +9483,7 @@ parser_set_encode(struct parser_params *p, const char *name) case 'l': case 'L': wrong = "locale"; break; } if (wrong && STRCASECMP(name, wrong) == 0) goto unknown; - int idx = rb_enc_find_index(name); + idx = rb_enc_find_index(name); if (idx < 0) { unknown: excargs[1] = rb_sprintf("unknown encoding name: %s", name); From 16624ef463f214367720b7cf486e43e48a2df4e6 Mon Sep 17 00:00:00 2001 From: ywenc Date: Fri, 12 Jan 2024 10:41:58 -0500 Subject: [PATCH 109/640] YJIT: expandarray for non-arrays (#9495) * YJIT: expandarray for non-arrays Co-authored-by: John Hawthorn * Skip the new test on RJIT * Increment counter for to_ary exit --------- Co-authored-by: John Hawthorn Co-authored-by: Takashi Kokubun --- bootstraptest/test_yjit.rb | 17 +++++++++++ yjit/src/codegen.rs | 62 ++++++++++++++++++++++++++++---------- yjit/src/cruby.rs | 1 + yjit/src/stats.rs | 2 +- 4 files changed, 65 insertions(+), 17 deletions(-) diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index aaf70e7b93a352..0e8c4a0a0658f4 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -2494,6 +2494,23 @@ def obj.to_ary expandarray_not_array(obj) } +assert_equal '[1, 2]', %q{ + class NilClass + private + def to_ary + [1, 2] + end + end + + def expandarray_redefined_nilclass + a, b = nil + [a, b] + end + + expandarray_redefined_nilclass + expandarray_redefined_nilclass +} unless rjit_enabled? + assert_equal '[1, 2, nil]', %q{ def expandarray_rhs_too_small a, b, c = [1, 2] diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 7e44c3add0c420..4e23cf10b1d491 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -1637,18 +1637,6 @@ fn gen_expandarray( let array_opnd = asm.stack_opnd(0); - // If the array operand is nil, just push on nils - if asm.ctx.get_opnd_type(array_opnd.into()) == Type::Nil { - asm.stack_pop(1); // pop after using the type info - // special case for a, b = nil pattern - // push N nils onto the stack - for _ in 0..num { - let push_opnd = asm.stack_push(Type::Nil); - asm.mov(push_opnd, Qnil.into()); - } - return Some(KeepCompiling); - } - // Defer compilation so we can specialize on a runtime `self` if !jit.at_current_insn() { defer_compilation(jit, asm, ocb); @@ -1657,10 +1645,52 @@ fn gen_expandarray( let comptime_recv = jit.peek_at_stack(&asm.ctx, 0); - // If the comptime receiver is not an array, bail - if comptime_recv.class_of() != unsafe { rb_cArray } { - gen_counter_incr(asm, Counter::expandarray_comptime_not_array); - return None; + // If the comptime receiver is not an array + if !unsafe { RB_TYPE_P(comptime_recv, RUBY_T_ARRAY) } { + // at compile time, ensure to_ary is not defined + let target_cme = unsafe { rb_callable_method_entry_or_negative(comptime_recv.class_of(), ID!(to_ary)) }; + let cme_def_type = unsafe { get_cme_def_type(target_cme) }; + + // if to_ary is defined, return can't compile so to_ary can be called + if cme_def_type != VM_METHOD_TYPE_UNDEF { + gen_counter_incr(asm, Counter::expandarray_to_ary); + return None; + } + + // invalidate compile block if to_ary is later defined + jit.assume_method_lookup_stable(asm, ocb, target_cme); + + jit_guard_known_klass( + jit, + asm, + ocb, + comptime_recv.class_of(), + array_opnd, + array_opnd.into(), + comptime_recv, + SEND_MAX_DEPTH, + Counter::expandarray_not_array, + ); + + let opnd = asm.stack_pop(1); // pop after using the type info + + // If we don't actually want any values, then just keep going + if num == 0 { + return Some(KeepCompiling); + } + + // load opnd to avoid a race because we are also pushing onto the stack + let opnd = asm.load(opnd); + + for _ in 1..num { + let push_opnd = asm.stack_push(Type::Nil); + asm.mov(push_opnd, Qnil.into()); + } + + let push_opnd = asm.stack_push(Type::Unknown); + asm.mov(push_opnd, opnd); + + return Some(KeepCompiling); } // Get the compile-time array length diff --git a/yjit/src/cruby.rs b/yjit/src/cruby.rs index a43b053d3efbfd..ac0bdf68856f1d 100644 --- a/yjit/src/cruby.rs +++ b/yjit/src/cruby.rs @@ -781,6 +781,7 @@ pub(crate) mod ids { name: max content: b"max" name: hash content: b"hash" name: respond_to_missing content: b"respond_to_missing?" + name: to_ary content: b"to_ary" } } diff --git a/yjit/src/stats.rs b/yjit/src/stats.rs index ba1479e1528648..bf918aeb75a4b3 100644 --- a/yjit/src/stats.rs +++ b/yjit/src/stats.rs @@ -469,7 +469,7 @@ make_counters! { expandarray_splat, expandarray_postarg, expandarray_not_array, - expandarray_comptime_not_array, + expandarray_to_ary, expandarray_chain_max_depth, // getblockparam From 2d9db72d37e570dcfc5e8b0b74476360cae96056 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 11 Jan 2024 17:05:42 -0500 Subject: [PATCH 110/640] Write to constant path, call, and index in rescue When compiling a rescue reference, you can write to a constant path, a call, or an index. In these cases we need to compile the prefix expression first, then handle actually doing the write/call. --- prism_compile.c | 296 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 265 insertions(+), 31 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 7bba3be0a100e5..cab2af42e93ea0 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -207,21 +207,21 @@ parse_string_encoded(const pm_node_t *node, const pm_string_t *string, const pm_ } static inline ID -parse_symbol(const uint8_t *start, const uint8_t *end, pm_parser_t *parser) +parse_symbol(const uint8_t *start, const uint8_t *end, const pm_parser_t *parser) { rb_encoding *enc = rb_enc_from_index(rb_enc_find_index(parser->encoding->name)); return rb_intern3((const char *) start, end - start, enc); } static inline ID -parse_string_symbol(const pm_string_t *string, pm_parser_t *parser) +parse_string_symbol(const pm_string_t *string, const pm_parser_t *parser) { const uint8_t *start = pm_string_source(string); return parse_symbol(start, start + pm_string_length(string), parser); } static inline ID -parse_location_symbol(pm_location_t *location, pm_parser_t *parser) +parse_location_symbol(const pm_location_t *location, const pm_parser_t *parser) { return parse_symbol(location->start, location->end, parser); } @@ -326,7 +326,7 @@ pm_new_regex(pm_regular_expression_node_t * cast, const pm_parser_t * parser) { * literal values can be compiled into a literal array. */ static inline VALUE -pm_static_literal_value(const pm_node_t *node, pm_scope_node_t *scope_node, pm_parser_t *parser) +pm_static_literal_value(const pm_node_t *node, const pm_scope_node_t *scope_node, const pm_parser_t *parser) { // Every node that comes into this function should already be marked as // static literal. If it's not, then we have a bug somewhere. @@ -1147,6 +1147,118 @@ pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinf return orig_argc; } +/** + * A callinfo struct basically mirrors the information that is going to be + * passed to a callinfo object that will be used on a send instruction. We use + * it to communicate the information between the function that derives it and + * the function that uses it. + */ +typedef struct { + int argc; + int flags; + struct rb_callinfo_kwarg *kwargs; +} pm_callinfo_t; + +/** + * Derive the callinfo from the given arguments node. It assumes the pointer to + * the callinfo struct is zeroed memory. + */ +static void +pm_arguments_node_callinfo(pm_callinfo_t *callinfo, const pm_arguments_node_t *node, const pm_scope_node_t *scope_node, const pm_parser_t *parser) +{ + if (node == NULL) { + if (callinfo->flags & VM_CALL_FCALL) { + callinfo->flags |= VM_CALL_VCALL; + } + } else { + const pm_node_list_t *arguments = &node->arguments; + bool has_splat = false; + + for (size_t argument_index = 0; argument_index < arguments->size; argument_index++) { + const pm_node_t *argument = arguments->nodes[argument_index]; + + switch (PM_NODE_TYPE(argument)) { + case PM_KEYWORD_HASH_NODE: { + pm_keyword_hash_node_t *keyword_hash = (pm_keyword_hash_node_t *) argument; + size_t elements_size = keyword_hash->elements.size; + + if (PM_NODE_FLAG_P(node, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT)) { + for (size_t element_index = 0; element_index < elements_size; element_index++) { + const pm_node_t *element = keyword_hash->elements.nodes[element_index]; + + switch (PM_NODE_TYPE(element)) { + case PM_ASSOC_NODE: + callinfo->argc++; + break; + case PM_ASSOC_SPLAT_NODE: + if (elements_size > 1) callinfo->flags |= VM_CALL_KW_SPLAT_MUT; + callinfo->flags |= VM_CALL_KW_SPLAT; + break; + default: + rb_bug("Unknown type in keyword argument %s\n", pm_node_type_to_str(PM_NODE_TYPE(element))); + } + } + break; + } else if (PM_NODE_FLAG_P(keyword_hash, PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS)) { + // We need to first figure out if all elements of the + // KeywordHashNode are AssocNode nodes with symbol keys. If + // they are all symbol keys then we can pass them as keyword + // arguments. + callinfo->flags |= VM_CALL_KWARG; + + callinfo->kwargs = rb_xmalloc_mul_add(elements_size, sizeof(VALUE), sizeof(struct rb_callinfo_kwarg)); + callinfo->kwargs->references = 0; + callinfo->kwargs->keyword_len = (int) elements_size; + + VALUE *keywords = callinfo->kwargs->keywords; + for (size_t element_index = 0; element_index < elements_size; element_index++) { + pm_assoc_node_t *assoc = (pm_assoc_node_t *) keyword_hash->elements.nodes[element_index]; + keywords[element_index] = pm_static_literal_value(assoc->key, scope_node, parser); + } + } else { + // If they aren't all symbol keys then we need to construct + // a new hash and pass that as an argument. + callinfo->argc++; + callinfo->flags |= VM_CALL_KW_SPLAT; + + if (elements_size > 1) { + // A new hash will be created for the keyword arguments + // in this case, so mark the method as passing mutable + // keyword splat. + callinfo->flags |= VM_CALL_KW_SPLAT_MUT; + } + } + break; + } + case PM_SPLAT_NODE: { + // Splat nodes add a splat flag and can change the way the + // arguments are loaded by combining them into a single array. + callinfo->flags |= VM_CALL_ARGS_SPLAT; + if (((pm_splat_node_t *) argument)->expression != NULL) callinfo->argc++; + has_splat = true; + break; + } + case PM_FORWARDING_ARGUMENTS_NODE: { + // Forwarding arguments indicate that a splat and a block are + // present, and increase the argument count by one. + callinfo->flags |= VM_CALL_ARGS_BLOCKARG | VM_CALL_ARGS_SPLAT; + callinfo->argc++; + break; + } + default: { + // A regular argument increases the argument count by one. If + // there is a splat and this is the last argument, then the + // argument count becomes 1 because it gets grouped into a + // single array. + callinfo->argc++; + if (has_splat && (argument_index == arguments->size - 1)) callinfo->argc = 1; + break; + } + } + } + } +} + static void pm_compile_index_and_or_write_node(bool and_node, pm_node_t *receiver, pm_node_t *value, pm_arguments_node_t *arguments, pm_node_t *block, LINK_ANCHOR *const ret, rb_iseq_t *iseq, int lineno, const uint8_t * src, bool popped, pm_scope_node_t *scope_node, pm_parser_t *parser) { @@ -3234,6 +3346,20 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, return; } + case PM_CALL_TARGET_NODE: { + // Call targets can be used to indirectly call a method in places like + // rescue references, for loops, and multiple assignment. In those + // circumstances, it's necessary to first compile the receiver, then to + // compile the method call itself. + // + // Therefore in the main switch case here where we're compiling a call + // target, we're only going to compile the receiver. Then wherever + // we've called into pm_compile_node when we're compiling call targets, + // we'll need to make sure we compile the method call as well. + pm_call_target_node_t *cast = (pm_call_target_node_t*) node; + PM_COMPILE_NOT_POPPED(cast->receiver); + return; + } case PM_CASE_NODE: { pm_case_node_t *case_node = (pm_case_node_t *)node; bool has_predicate = case_node->predicate; @@ -3731,13 +3857,23 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } ADD_INSN1(ret, &dummy_line_node, setconstant, child_name); - return ; + return; } case PM_CONSTANT_PATH_TARGET_NODE: { - pm_constant_path_target_node_t *cast = (pm_constant_path_target_node_t *)node; + // Constant path targets can be used to indirectly write a constant in + // places like rescue references, for loops, and multiple assignment. In + // those circumstances, it's necessary to first compile the parent, then + // to compile the child. + // + // Therefore in the main switch case here where we're compiling a + // constant path target, we're only going to compile the parent. Then + // wherever we've called into pm_compile_node when we're compiling + // constant path targets, we'll need to make sure we compile the child + // as well. + pm_constant_path_target_node_t *cast = (pm_constant_path_target_node_t *) node; if (cast->parent) { - PM_COMPILE(cast->parent); + PM_COMPILE_NOT_POPPED(cast->parent); } return; @@ -4379,6 +4515,33 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, return; } + case PM_INDEX_TARGET_NODE: { + // Index targets can be used to indirectly call a method in places like + // rescue references, for loops, and multiple assignment. In those + // circumstances, it's necessary to first compile the receiver and + // arguments, then to compile the method call itself. + // + // Therefore in the main switch case here where we're compiling a index + // target, we're only going to compile the receiver and arguments. Then + // wherever we've called into pm_compile_node when we're compiling index + // targets, we'll need to make sure we compile the method call as well. + // + // Note that index target nodes can have blocks attached to them in the + // form of the & operator. These blocks should almost always be compiled + // _after_ the value that is being written is added to the argument + // list, so we don't compile them here. Therefore at the places where + // these nodes are handled, blocks also need to be handled. + pm_index_target_node_t *cast = (pm_index_target_node_t*) node; + PM_COMPILE_NOT_POPPED(cast->receiver); + + if (cast->arguments != NULL) { + int flags; + struct rb_callinfo_kwarg *keywords = NULL; + pm_setup_args(cast->arguments, &flags, &keywords, iseq, ret, src, false, scope_node, dummy_line_node, parser); + } + + return; + } case PM_INSTANCE_VARIABLE_AND_WRITE_NODE: { pm_instance_variable_and_write_node_t *instance_variable_and_write_node = (pm_instance_variable_and_write_node_t*) node; @@ -5371,49 +5534,120 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, return; } case PM_RESCUE_NODE: { - LABEL *excep_match = NEW_LABEL(lineno); - LABEL *rescue_end = NEW_LABEL(lineno); - - ISEQ_COMPILE_DATA(iseq)->end_label = rescue_end; - - pm_rescue_node_t *rescue_node = (pm_rescue_node_t *)node; + pm_rescue_node_t *cast = (pm_rescue_node_t *) node; iseq_set_exception_local_table(iseq); - pm_node_list_t exception_list = rescue_node->exceptions; - if (exception_list.size > 0) { - for (size_t i = 0; i < exception_list.size; i++) { + // First, establish the labels that we need to be able to jump to within + // this compilation block. + LABEL *exception_match_label = NEW_LABEL(lineno); + LABEL *rescue_end_label = NEW_LABEL(lineno); + ISEQ_COMPILE_DATA(iseq)->end_label = rescue_end_label; + + // Next, compile each of the exceptions that we're going to be + // handling. For each one, we'll add instructions to check if the + // exception matches the raised one, and if it does then jump to the + // exception_match_label label. Otherwise it will fall through to the + // subsequent check. If there are no exceptions, we'll only check + // StandardError. + pm_node_list_t *exceptions = &cast->exceptions; + + if (exceptions->size > 0) { + for (size_t index = 0; index < exceptions->size; index++) { ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0); - PM_COMPILE(exception_list.nodes[i]); + PM_COMPILE(exceptions->nodes[index]); ADD_INSN1(ret, &dummy_line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE)); - ADD_INSN1(ret, &dummy_line_node, branchif, excep_match); + ADD_INSN1(ret, &dummy_line_node, branchif, exception_match_label); } } else { ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0); ADD_INSN1(ret, &dummy_line_node, putobject, rb_eStandardError); ADD_INSN1(ret, &dummy_line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE)); - ADD_INSN1(ret, &dummy_line_node, branchif, excep_match); + ADD_INSN1(ret, &dummy_line_node, branchif, exception_match_label); } - ADD_INSN1(ret, &dummy_line_node, jump, rescue_end); - ADD_LABEL(ret, excep_match); + // If none of the exceptions that we are matching against matched, then + // we'll jump straight to the rescue_end_label label. + ADD_INSN1(ret, &dummy_line_node, jump, rescue_end_label); + + // Here we have the exception_match_label, which is where the + // control-flow goes in the case that one of the exceptions matched. + // Here we will compile the instructions to handle the exception. + ADD_LABEL(ret, exception_match_label); ADD_TRACE(ret, RUBY_EVENT_RESCUE); - if (rescue_node->reference) { - ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0); - PM_COMPILE((pm_node_t *)rescue_node->reference); - } - if (rescue_node->statements) { - PM_COMPILE((pm_node_t *)rescue_node->statements); + // If we have a reference to the exception, then we'll compile the write + // into the instruction sequence. This can look quite different + // depending on the kind of write being performed. + if (cast->reference) { + switch (PM_NODE_TYPE(cast->reference)) { + case PM_CALL_TARGET_NODE: { + // begin; rescue => Foo.bar; end + const pm_call_target_node_t *reference = (const pm_call_target_node_t *) cast->reference; + ID method_id = pm_constant_id_lookup(scope_node, reference->name); + + PM_COMPILE((pm_node_t *) reference); + ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0); + + ADD_SEND(ret, &dummy_line_node, method_id, INT2NUM(1)); + ADD_INSN(ret, &dummy_line_node, pop); + break; + } + case PM_CONSTANT_PATH_TARGET_NODE: { + // begin; rescue => Foo::Bar; end + const pm_constant_path_target_node_t *reference = (const pm_constant_path_target_node_t *) cast->reference; + const pm_constant_read_node_t *constant = (const pm_constant_read_node_t *) reference->child; + + PM_COMPILE((pm_node_t *) reference); + ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0); + + ADD_INSN(ret, &dummy_line_node, swap); + ADD_INSN1(ret, &dummy_line_node, setconstant, ID2SYM(pm_constant_id_lookup(scope_node, constant->name))); + break; + } + case PM_INDEX_TARGET_NODE: { + // begin; rescue => foo[:bar]; end + const pm_index_target_node_t *reference = (const pm_index_target_node_t *) cast->reference; + + pm_callinfo_t callinfo = { 0 }; + pm_arguments_node_callinfo(&callinfo, reference->arguments, scope_node, parser); + + PM_COMPILE((pm_node_t *) reference); + ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0); + + if (reference->block != NULL) { + callinfo.flags |= VM_CALL_ARGS_BLOCKARG; + PM_COMPILE_NOT_POPPED((pm_node_t *) reference->block); + } + + ADD_SEND_R(ret, &dummy_line_node, idASET, INT2FIX(callinfo.argc + 1), NULL, INT2FIX(callinfo.flags), callinfo.kwargs); + ADD_INSN(ret, &dummy_line_node, pop); + break; + } + default: + // Indirectly writing to a variable or constant. + ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0); + PM_COMPILE((pm_node_t *) cast->reference); + break; + } } - else { + + // If we have statements to execute, we'll compile them here. Otherwise + // we'll push nil onto the stack. + if (cast->statements) { + PM_COMPILE((pm_node_t *) cast->statements); + } else { PM_PUTNIL; } ADD_INSN(ret, &dummy_line_node, leave); - ADD_LABEL(ret, rescue_end); - if (rescue_node->consequent) { - PM_COMPILE((pm_node_t *)rescue_node->consequent); + // Here we'll insert the rescue_end_label label, which is jumped to if + // none of the exceptions matched. It will cause the control-flow to + // either jump to the next rescue clause or it will fall through to the + // subsequent instruction returning the raised error. + ADD_LABEL(ret, rescue_end_label); + if (cast->consequent) { + PM_COMPILE((pm_node_t *) cast->consequent); } else { ADD_GETLOCAL(ret, &dummy_line_node, 1, 0); } From 8b8dcc7af174def5216044019c1d3e42edfdc7cf Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 11 Jan 2024 16:05:21 -0800 Subject: [PATCH 111/640] Handle mmap failures for redblack tree cache The redblack tree cache is totally optional, so if we can't allocate room for the cache, then just pretend as if the cache is full if mmap fails --- shape.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/shape.c b/shape.c index 4cd4acd7f99d6b..8d8314db331d44 100644 --- a/shape.c +++ b/shape.c @@ -1233,6 +1233,14 @@ Init_default_shapes(void) rb_shape_tree_ptr->shape_cache = (redblack_node_t *)mmap(NULL, rb_size_mul_or_raise(REDBLACK_CACHE_SIZE, sizeof(redblack_node_t), rb_eRuntimeError), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); rb_shape_tree_ptr->cache_size = 0; + + // If mmap fails, then give up on the redblack tree cache. + // We set the cache size such that the redblack node allocators think + // the cache is full. + if (GET_SHAPE_TREE()->shape_cache == MAP_FAILED) { + GET_SHAPE_TREE()->shape_cache = 0; + GET_SHAPE_TREE()->cache_size = REDBLACK_CACHE_SIZE; + } #endif // Shapes by size pool From 0462b1b350b0f86ce4cfebc195fe0f24005d28f4 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Fri, 12 Jan 2024 10:40:23 -0500 Subject: [PATCH 112/640] [PRISM] Fix splat in when Fixes ruby/prism#2147. --- prism_compile.c | 17 ++++++++++++++--- test/ruby/test_compile_prism.rb | 11 +++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index cab2af42e93ea0..b2352328437615 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -3380,9 +3380,20 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_when_node_t *when_node = (pm_when_node_t *)conditions.nodes[i]; for (size_t i = 0; i < when_node->conditions.size; i++) { - PM_COMPILE_NOT_POPPED(when_node->conditions.nodes[i]); - ADD_INSN1(ret, &dummy_line_node, topn, INT2FIX(1)); - ADD_SEND_WITH_FLAG(ret, &dummy_line_node, idEqq, INT2NUM(1), INT2FIX(VM_CALL_FCALL | VM_CALL_ARGS_SIMPLE)); + pm_node_t *condition_node = when_node->conditions.nodes[i]; + + if (PM_NODE_TYPE_P(condition_node, PM_SPLAT_NODE)) { + ADD_INSN (ret, &dummy_line_node, dup); + PM_COMPILE_NOT_POPPED(condition_node); + ADD_INSN1(ret, &dummy_line_node, splatarray, Qfalse); + ADD_INSN1(ret, &dummy_line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE | VM_CHECKMATCH_ARRAY)); + } + else { + PM_COMPILE_NOT_POPPED(condition_node); + ADD_INSN1(ret, &dummy_line_node, topn, INT2FIX(1)); + ADD_SEND_WITH_FLAG(ret, &dummy_line_node, idEqq, INT2NUM(1), INT2FIX(VM_CALL_FCALL | VM_CALL_ARGS_SIMPLE)); + } + ADD_INSNL(ret, &dummy_line_node, branchif, label); } } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 71155979036e40..965f3d3c91373a 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -767,6 +767,17 @@ def self.prism_test_case_node end prism_test_case_node CODE + + # Test splat in when + assert_prism_eval(<<~RUBY) + ary = [1, 2] + case 1 + when *ary + :ok + else + :ng + end + RUBY end def test_ElseNode From e59dd7094f281e3167fc8fe29ab0e92e7b66027a Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Fri, 12 Jan 2024 11:30:36 -0500 Subject: [PATCH 113/640] Pass more T_DATA to obj_free() under RUBY_FREE_AT_EXIT T_DATA without a pointer or free function may still have ivars set on them that need to be freed. The following leaked generic ivars for example: converter = Encoding::Converter.allocate converter.instance_variable_set(:@foo, 1) STACK OF 1 INSTANCE OF 'ROOT LEAK: ': 12 miniruby 0x10286ec50 ivar_set + 140 variable.c:1850 11 miniruby 0x102876afc generic_ivar_set + 136 variable.c:1668 --- gc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gc.c b/gc.c index 0e4dadbdd0b39f..6245e2083be0a5 100644 --- a/gc.c +++ b/gc.c @@ -4684,7 +4684,7 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace) void *poisoned = asan_unpoison_object_temporary(vp); switch (BUILTIN_TYPE(vp)) { case T_DATA: - if (!DATA_PTR(p) || !RANY(p)->as.data.dfree) break; + if (!rb_free_at_exit && (!DATA_PTR(p) || !RANY(p)->as.data.dfree)) break; if (rb_obj_is_thread(vp)) break; if (rb_obj_is_mutex(vp)) break; if (rb_obj_is_fiber(vp)) break; From 84f14ff08925889964cd5e7ed0bfc9ee8fcefce2 Mon Sep 17 00:00:00 2001 From: Jemma Issroff Date: Fri, 15 Dec 2023 16:28:29 -0500 Subject: [PATCH 114/640] [PRISM] Pre-concatenate Strings in InterpolatedStringNode This commit concatenates String VALUEs within InterpolatedStringNodes to allow us to preserve frozenness of concatenated strings such as `"a""b"` Co-authored-by: Aaron Patterson --- prism_compile.c | 59 ++++++++++++++++++++++++--------- test/ruby/test_compile_prism.rb | 11 ++++++ 2 files changed, 55 insertions(+), 15 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index b2352328437615..c87f57f78a7ae6 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -730,30 +730,62 @@ pm_compile_while(rb_iseq_t *iseq, int lineno, pm_node_flags_t flags, enum pm_nod return; } -static void +static int pm_interpolated_node_compile(pm_node_list_t *parts, rb_iseq_t *iseq, NODE dummy_line_node, LINK_ANCHOR *const ret, const uint8_t *src, bool popped, pm_scope_node_t *scope_node, pm_parser_t *parser) { + int number_of_items_pushed = 0; size_t parts_size = parts->size; if (parts_size > 0) { + VALUE current_string = Qnil; for (size_t index = 0; index < parts_size; index++) { pm_node_t *part = parts->nodes[index]; if (PM_NODE_TYPE_P(part, PM_STRING_NODE)) { - pm_string_node_t *string_node = (pm_string_node_t *) part; - ADD_INSN1(ret, &dummy_line_node, putobject, parse_string(&string_node->unescaped, parser)); + pm_string_node_t *string_node = (pm_string_node_t *)part; + VALUE string_value = parse_string(&string_node->unescaped, parser); + if (RTEST(current_string)) { + current_string = rb_str_concat(current_string, string_value); + } + else { + current_string = string_value; + } } else { + if (RTEST(current_string)) { + if (parser->frozen_string_literal) { + ADD_INSN1(ret, &dummy_line_node, putobject, rb_str_freeze(current_string)); + } + else { + ADD_INSN1(ret, &dummy_line_node, putstring, current_string); + } + current_string = Qnil; + number_of_items_pushed++; + } PM_COMPILE_NOT_POPPED(part); PM_DUP; ADD_INSN1(ret, &dummy_line_node, objtostring, new_callinfo(iseq, idTo_s, 0, VM_CALL_FCALL | VM_CALL_ARGS_SIMPLE , NULL, FALSE)); ADD_INSN(ret, &dummy_line_node, anytostring); + + number_of_items_pushed++; + } + } + + if (RTEST(current_string)) { + if (parser->frozen_string_literal) { + ADD_INSN1(ret, &dummy_line_node, putobject, rb_str_freeze(current_string)); + } + else { + ADD_INSN1(ret, &dummy_line_node, putstring, current_string); } + current_string = Qnil; + number_of_items_pushed++; } } else { PM_PUTNIL; } + return number_of_items_pushed; } // This recurses through scopes and finds the local index at any scope level @@ -4706,11 +4738,10 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } case PM_INTERPOLATED_STRING_NODE: { pm_interpolated_string_node_t *interp_string_node = (pm_interpolated_string_node_t *) node; - pm_interpolated_node_compile(&interp_string_node->parts, iseq, dummy_line_node, ret, src, popped, scope_node, parser); + int number_of_items_pushed = pm_interpolated_node_compile(&interp_string_node->parts, iseq, dummy_line_node, ret, src, popped, scope_node, parser); - size_t parts_size = interp_string_node->parts.size; - if (parts_size > 1) { - ADD_INSN1(ret, &dummy_line_node, concatstrings, INT2FIX((int)(parts_size))); + if (number_of_items_pushed > 1) { + ADD_INSN1(ret, &dummy_line_node, concatstrings, INT2FIX(number_of_items_pushed)); } PM_POP_IF_POPPED; @@ -4718,11 +4749,10 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } case PM_INTERPOLATED_SYMBOL_NODE: { pm_interpolated_symbol_node_t *interp_symbol_node = (pm_interpolated_symbol_node_t *) node; - pm_interpolated_node_compile(&interp_symbol_node->parts, iseq, dummy_line_node, ret, src, popped, scope_node, parser); + int number_of_items_pushed = pm_interpolated_node_compile(&interp_symbol_node->parts, iseq, dummy_line_node, ret, src, popped, scope_node, parser); - size_t parts_size = interp_symbol_node->parts.size; - if (parts_size > 1) { - ADD_INSN1(ret, &dummy_line_node, concatstrings, INT2FIX((int)(parts_size))); + if (number_of_items_pushed > 1) { + ADD_INSN1(ret, &dummy_line_node, concatstrings, INT2FIX(number_of_items_pushed)); } if (!popped) { @@ -4737,11 +4767,10 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, case PM_INTERPOLATED_X_STRING_NODE: { pm_interpolated_x_string_node_t *interp_x_string_node = (pm_interpolated_x_string_node_t *) node; PM_PUTSELF; - pm_interpolated_node_compile(&interp_x_string_node->parts, iseq, dummy_line_node, ret, src, false, scope_node, parser); + int number_of_items_pushed = pm_interpolated_node_compile(&interp_x_string_node->parts, iseq, dummy_line_node, ret, src, false, scope_node, parser); - size_t parts_size = interp_x_string_node->parts.size; - if (parts_size > 1) { - ADD_INSN1(ret, &dummy_line_node, concatstrings, INT2FIX((int)(parts_size))); + if (number_of_items_pushed > 1) { + ADD_INSN1(ret, &dummy_line_node, concatstrings, INT2FIX(number_of_items_pushed)); } ADD_SEND_WITH_FLAG(ret, &dummy_line_node, idBackquote, INT2NUM(1), INT2FIX(VM_CALL_FCALL | VM_CALL_ARGS_SIMPLE)); diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 965f3d3c91373a..78800fed7ca68e 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -589,6 +589,17 @@ def test_InterpolatedStringNode assert_prism_eval('$pit = 1; "1 #$pit 1"') assert_prism_eval('"1 #{1 + 2} 1"') assert_prism_eval('"Prism" "::" "TestCompilePrism"') + assert_prism_eval('("a""b").frozen?') + assert_prism_eval(<<-CODE) + # frozen_string_literal: true + + ("a""b").frozen? + CODE + assert_prism_eval(<<-CODE) + # frozen_string_literal: true + + ("a""b""#{1}").frozen? + CODE end def test_InterpolatedSymbolNode From a0a100db4943f37060fe6c59f4546262ae3dfc59 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 8 Jan 2024 13:32:05 -0800 Subject: [PATCH 115/640] Update test/ruby/test_compile_prism.rb Co-authored-by: Ufuk Kayserilioglu --- test/ruby/test_compile_prism.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 78800fed7ca68e..ac13f26e7c6104 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -600,6 +600,11 @@ def test_InterpolatedStringNode ("a""b""#{1}").frozen? CODE + assert_prism_eval(<<-CODE) + # frozen_string_literal: true + + ("a""#{1}""b").frozen? + CODE end def test_InterpolatedSymbolNode From 774eef692cc9708b22959ef57b8472a375772189 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 8 Jan 2024 13:32:35 -0800 Subject: [PATCH 116/640] Always freeze strings that are in the instructions Any objects that the instructions reference should be frozen. Co-Authored-By: Matt Valentine-House --- prism_compile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index c87f57f78a7ae6..5006ce50e859e6 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -757,7 +757,7 @@ pm_interpolated_node_compile(pm_node_list_t *parts, rb_iseq_t *iseq, NODE dummy_ ADD_INSN1(ret, &dummy_line_node, putobject, rb_str_freeze(current_string)); } else { - ADD_INSN1(ret, &dummy_line_node, putstring, current_string); + ADD_INSN1(ret, &dummy_line_node, putstring, rb_str_freeze(current_string)); } current_string = Qnil; number_of_items_pushed++; @@ -776,7 +776,7 @@ pm_interpolated_node_compile(pm_node_list_t *parts, rb_iseq_t *iseq, NODE dummy_ ADD_INSN1(ret, &dummy_line_node, putobject, rb_str_freeze(current_string)); } else { - ADD_INSN1(ret, &dummy_line_node, putstring, current_string); + ADD_INSN1(ret, &dummy_line_node, putstring, rb_str_freeze(current_string)); } current_string = Qnil; number_of_items_pushed++; From aad246feba1579cc3c34f8309845692e2f11babd Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Tue, 9 Jan 2024 20:04:20 +0100 Subject: [PATCH 117/640] s/SafeStringValue/StringValue/ The macro SafeStringValue() became just StringValue() in c5c05460ac2, and it is deprecated nowadays. This patch replaces remaining macro usage. Some occurrences are left in ext/stringio and ext/win32ole, they should be fixed upstream. The macro itself is not deleted, because it may be used in extensions. --- dir.c | 2 +- hash.c | 8 ++++---- internal/imemo.h | 2 +- io.c | 14 +++++++------- process.c | 4 ++-- vm_eval.c | 6 +++--- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/dir.c b/dir.c index 96c1a455b3cd68..c972a6ce401da2 100644 --- a/dir.c +++ b/dir.c @@ -3509,7 +3509,7 @@ 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); + StringValue(user); rb_must_asciicompat(user); u = StringValueCStr(user); if (*u) { diff --git a/hash.c b/hash.c index 2ccd3cd008a41d..6a23f169571a53 100644 --- a/hash.c +++ b/hash.c @@ -4898,7 +4898,7 @@ static inline const char * env_name(volatile VALUE *s) { const char *name; - SafeStringValue(*s); + StringValue(*s); get_env_ptr(name, *s); return name; } @@ -5375,8 +5375,8 @@ env_aset(VALUE nm, VALUE val) env_delete(nm); return Qnil; } - SafeStringValue(nm); - SafeStringValue(val); + StringValue(nm); + StringValue(val); /* nm can be modified in `val.to_str`, don't get `name` before * check for `val` */ get_env_ptr(name, nm); @@ -6239,7 +6239,7 @@ env_rassoc(VALUE dmy, VALUE obj) static VALUE env_key(VALUE dmy, VALUE value) { - SafeStringValue(value); + StringValue(value); VALUE str = Qnil; ENV_LOCK(); diff --git a/internal/imemo.h b/internal/imemo.h index 65335285abc7d8..22dc4571944082 100644 --- a/internal/imemo.h +++ b/internal/imemo.h @@ -213,7 +213,7 @@ rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString(VALUE str) void *dst; size_t len; - SafeStringValue(str); + StringValue(str); /* create tmpbuf to keep the pointer before xmalloc */ imemo = rb_imemo_tmpbuf_auto_free_pointer(); tmpbuf = (rb_imemo_tmpbuf_t *)imemo; diff --git a/io.c b/io.c index 2de3e873024f47..bcad437339c24a 100644 --- a/io.c +++ b/io.c @@ -5121,7 +5121,7 @@ rb_io_ungetbyte(VALUE io, VALUE b) b = rb_str_new((const char *)&c, 1); break; default: - SafeStringValue(b); + StringValue(b); } io_ungetbyte(b, fptr); return Qnil; @@ -5183,7 +5183,7 @@ rb_io_ungetc(VALUE io, VALUE c) c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr)); } else { - SafeStringValue(c); + StringValue(c); } if (NEED_READCONV(fptr)) { SET_BINARY_MODE(fptr); @@ -6834,7 +6834,7 @@ rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash, else { const char *p; - SafeStringValue(vmode); + StringValue(vmode); p = StringValueCStr(vmode); fmode = rb_io_modestr_fmode(p); oflags = rb_io_fmode_oflags(fmode); @@ -7950,7 +7950,7 @@ rb_io_popen(VALUE pname, VALUE pmode, VALUE env, VALUE opt) RB_GC_GUARD(tmp); } else { - SafeStringValue(pname); + StringValue(pname); execarg_obj = Qnil; if (!is_popen_fork(pname)) execarg_obj = rb_execarg_new(1, &pname, TRUE, FALSE); @@ -8155,7 +8155,7 @@ rb_io_s_sysopen(int argc, VALUE *argv, VALUE _) else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int"))) oflags = NUM2INT(intmode); else { - SafeStringValue(vmode); + StringValue(vmode); oflags = rb_io_modestr_oflags(StringValueCStr(vmode)); } if (NIL_P(vperm)) perm = 0666; @@ -10569,7 +10569,7 @@ rb_f_backquote(VALUE obj, VALUE str) VALUE result; rb_io_t *fptr; - SafeStringValue(str); + StringValue(str); rb_last_status_clear(); port = pipe_open_s(str, "r", FMODE_READABLE|DEFAULT_TEXTMODE, NULL); if (NIL_P(port)) return rb_str_new(0,0); @@ -11575,7 +11575,7 @@ rb_f_syscall(int argc, VALUE *argv, VALUE _) VALUE v = rb_check_string_type(argv[i]); if (!NIL_P(v)) { - SafeStringValue(v); + StringValue(v); rb_str_modify(v); arg[i] = (VALUE)StringValueCStr(v); } diff --git a/process.c b/process.c index 6d40f72284a0eb..eeafc4c48382bb 100644 --- a/process.c +++ b/process.c @@ -2482,12 +2482,12 @@ rb_check_argv(int argc, VALUE *argv) } prog = RARRAY_AREF(tmp, 0); argv[0] = RARRAY_AREF(tmp, 1); - SafeStringValue(prog); + StringValue(prog); StringValueCStr(prog); prog = rb_str_new_frozen(prog); } for (i = 0; i < argc; i++) { - SafeStringValue(argv[i]); + StringValue(argv[i]); argv[i] = rb_str_new_frozen(argv[i]); StringValueCStr(argv[i]); } diff --git a/vm_eval.c b/vm_eval.c index 937f0582c4a6a7..3322cf8451ea65 100644 --- a/vm_eval.c +++ b/vm_eval.c @@ -1787,7 +1787,7 @@ rb_f_eval(int argc, const VALUE *argv, VALUE self) int line = 1; rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline); - SafeStringValue(src); + StringValue(src); if (argc >= 3) { StringValue(vfile); } @@ -1981,7 +1981,7 @@ static VALUE eval_under(VALUE self, int singleton, VALUE src, VALUE file, int line) { rb_cref_t *cref = vm_cref_push(GET_EC(), self, NULL, FALSE, singleton); - SafeStringValue(src); + StringValue(src); return eval_string_with_cref(self, src, cref, file, line); } @@ -2000,7 +2000,7 @@ specific_eval(int argc, const VALUE *argv, VALUE self, int singleton, int kw_spl rb_check_arity(argc, 1, 3); code = argv[0]; - SafeStringValue(code); + StringValue(code); if (argc > 2) line = NUM2INT(argv[2]); if (argc > 1) { From 2c27a3a0dd6a922c215758b2bf0635a7986f0eab Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 12 Jan 2024 12:16:13 -0800 Subject: [PATCH 118/640] Fix splat assigns with no lefties We still need to emit an expand array even if there's no "left side" variables Fixes: https://github.com/ruby/prism/issues/2153 --- prism_compile.c | 10 ++++------ test/ruby/test_compile_prism.rb | 4 ++++ tool/prism_btests | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 5006ce50e859e6..3afc6ae5db8a0d 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -5137,12 +5137,10 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, PM_NODE_TYPE_P(cast->rest, PM_SPLAT_NODE) && (((pm_splat_node_t *)cast->rest)->expression)); - if (cast->lefts.size) { - int flag = (int) (bool) cast->rights.size || has_rest_expression; - ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(cast->lefts.size), INT2FIX(flag)); - for (size_t index = 0; index < cast->lefts.size; index++) { - PM_COMPILE_NOT_POPPED(cast->lefts.nodes[index]); - } + int flag = (int) (bool) cast->rights.size || has_rest_expression; + ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(cast->lefts.size), INT2FIX(flag)); + for (size_t index = 0; index < cast->lefts.size; index++) { + PM_COMPILE_NOT_POPPED(cast->lefts.nodes[index]); } if (has_rest_expression) { diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index ac13f26e7c6104..87221289e2930a 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1330,6 +1330,10 @@ def test_repeated_method_params assert_prism_eval("def self.foo(_a, _a); _a; end; foo(1, 2)") end + def test_splat_params_with_no_lefties + assert_prism_eval("def self.foo(v, (*)); v; end; foo(1, [2, 3, 4])") + end + def test_method_parameters assert_prism_eval(<<-CODE) def self.prism_test_method_parameters(a, b=1, *c, d:, e: 2, **f, &g) diff --git a/tool/prism_btests b/tool/prism_btests index 6ce76301531ab1..2eda5e624e3d9d 100644 --- a/tool/prism_btests +++ b/tool/prism_btests @@ -20,7 +20,7 @@ ../src/bootstraptest/test_string.rb ../src/bootstraptest/test_struct.rb ../src/bootstraptest/test_thread.rb -# ../src/bootstraptest/test_block.rb +../src/bootstraptest/test_block.rb # ../src/bootstraptest/test_exception.rb # ../src/bootstraptest/test_flow.rb # ../src/bootstraptest/test_insns.rb From 206388b19eb3e1d98ee77821a96705c97c86eb06 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Fri, 12 Jan 2024 15:32:24 -0500 Subject: [PATCH 119/640] Fix ruby_free_proctitle It is undefined behaviour to free environ as it is managed by the system. This caused RUBY_FREE_AT_EXIT to double free on systems like Linux. This commit changes it to only free orig_environ, which is enough to make both Valgrind and macOS leaks tools to not detect memory leaks. --- missing/setproctitle.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/missing/setproctitle.c b/missing/setproctitle.c index d718123802f885..f90886671c2476 100644 --- a/missing/setproctitle.c +++ b/missing/setproctitle.c @@ -153,18 +153,16 @@ ruby_free_proctitle(void) if (!orig_environ) return; /* environ is allocated by OS */ - for (int i = 0; environ[i] != NULL; i++) { - xfree(environ[i]); - } - - /* ruby_setenv could allocate a new environ, so we need to free both environ - * orig_environ in that case. */ + /* ruby_setenv could allocate a new environ, so we need to free orig_environ + * in that case. */ if (environ != orig_environ) { + for (int i = 0; orig_environ[i] != NULL; i++) { + xfree(orig_environ[i]); + } + xfree(orig_environ); orig_environ = NULL; } - - xfree(environ); #endif } From 475663f0399248011f2392817ef4d89ec07baae4 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 12 Jan 2024 14:21:35 -0800 Subject: [PATCH 120/640] Only intern constants upon compilation entry Before this commit the Prism compiler would try to intern constants every time it re-entered. This pool of constants is "constant" (there is only one pool per parser instance), so we should do it only once: upon the top level entry to the compiler. This change does just that: it populates the interned constants once. Fixes: https://github.com/ruby/prism/issues/2152 --- iseq.c | 10 ++++++++++ prism_compile.c | 9 --------- tool/prism_btests | 4 ++-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/iseq.c b/iseq.c index f2911b43f26962..3b87cdcc782e51 100644 --- a/iseq.c +++ b/iseq.c @@ -1430,10 +1430,20 @@ iseqw_s_compile_prism_compile(pm_parser_t *parser, VALUE opt, rb_iseq_t *iseq, V pm_scope_node_t scope_node; pm_scope_node_init(node, &scope_node, NULL, parser); + + ID *constants = calloc(parser->constant_pool.size, sizeof(ID)); + rb_encoding *encoding = rb_enc_find(parser->encoding->name); + for (uint32_t index = 0; index < parser->constant_pool.size; index++) { + pm_constant_t *constant = &parser->constant_pool.constants[index]; + constants[index] = rb_intern3((const char *) constant->start, constant->length, encoding); + } + scope_node.constants = constants; + rb_iseq_compile_prism_node(iseq, &scope_node, parser); finish_iseq_build(iseq); pm_node_destroy(parser, node); + free(constants); } } diff --git a/prism_compile.c b/prism_compile.c index 3afc6ae5db8a0d..a9d417550f3af8 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -6794,25 +6794,16 @@ rb_translate_prism(pm_parser_t *parser, rb_iseq_t *iseq, pm_scope_node_t *scope_ { RUBY_ASSERT(ISEQ_COMPILE_DATA(iseq)); - ID *constants = calloc(parser->constant_pool.size, sizeof(ID)); - rb_encoding *encoding = rb_enc_find(parser->encoding->name); - for (uint32_t index = 0; index < parser->constant_pool.size; index++) { - pm_constant_t *constant = &parser->constant_pool.constants[index]; - constants[index] = rb_intern3((const char *) constant->start, constant->length, encoding); - } - st_table *index_lookup_table = st_init_numtable(); pm_constant_id_list_t *locals = &scope_node->locals; for (size_t i = 0; i < locals->size; i++) { st_insert(index_lookup_table, locals->ids[i], i); } - scope_node->constants = constants; scope_node->index_lookup_table = index_lookup_table; pm_compile_node(iseq, (pm_node_t *)scope_node, ret, scope_node->base.location.start, false, (pm_scope_node_t *)scope_node); iseq_set_sequence(iseq, ret); - free(constants); return Qnil; } diff --git a/tool/prism_btests b/tool/prism_btests index 2eda5e624e3d9d..e14f0d3cf9524a 100644 --- a/tool/prism_btests +++ b/tool/prism_btests @@ -30,6 +30,6 @@ # ../src/bootstraptest/test_ractor.rb # ../src/bootstraptest/test_syntax.rb # ../src/bootstraptest/test_yjit.rb -# ../src/bootstraptest/test_yjit_30k_ifelse.rb -# ../src/bootstraptest/test_yjit_30k_methods.rb +../src/bootstraptest/test_yjit_30k_ifelse.rb +../src/bootstraptest/test_yjit_30k_methods.rb # ../src/bootstraptest/test_yjit_rust_port.rb From b0e0a2a64d969eb306811bbf5f4d33cc2c1f62a0 Mon Sep 17 00:00:00 2001 From: Iztok Fister Jr Date: Sat, 13 Jan 2024 01:01:30 +0100 Subject: [PATCH 121/640] [DOC] Fix two minor typos on manual page --- man/ruby.1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/man/ruby.1 b/man/ruby.1 index a2b69c3cd65e1e..a0cda14641bb45 100644 --- a/man/ruby.1 +++ b/man/ruby.1 @@ -101,10 +101,10 @@ different character encodings, without dependence on Unicode. .It Sy "Bignums" With built-in bignums, you can for example calculate factorial(400). .Pp -.It Sy "Reflection and domain specific languages" +.It Sy "Reflection and domain-specific languages" Class is also an instance of the Class class. Definition of classes and methods is an expression just as 1+1 is. So your programs can even write and modify programs. -Thus you can write your application in your own programming language on top of Ruby. +Thus, you can write your application in your own programming language on top of Ruby. .Pp .It Sy "Exception handling" As in Java(tm). @@ -455,7 +455,7 @@ Enable compiler debug mode (same as .It Sy parsetree Print a textual representation of the Ruby AST for the program. .It Sy parsetree_with_comment -Print a textual representation of the Ruby AST for the program, but with each node annoted with the associated Ruby source code. +Print a textual representation of the Ruby AST for the program, but with each node annotated with the associated Ruby source code. .It Sy insns Print a list of disassembled bytecode instructions. .It Sy insns_without_opt From 08d4e5ebef3d372ca52de95d8ed896d7def8de49 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Thu, 28 Dec 2023 12:30:03 +1300 Subject: [PATCH 122/640] [ruby/openssl] Add more methods to `SocketForwarder`. https://github.com/ruby/openssl/commit/39eaa9f677 --- ext/openssl/lib/openssl/ssl.rb | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb index e557b8b483f77e..ccc945f2f2d556 100644 --- a/ext/openssl/lib/openssl/ssl.rb +++ b/ext/openssl/lib/openssl/ssl.rb @@ -252,6 +252,14 @@ def peeraddr to_io.peeraddr end + def local_address + to_io.local_address + end + + def remote_address + to_io.remote_address + end + def setsockopt(level, optname, optval) to_io.setsockopt(level, optname, optval) end @@ -271,6 +279,26 @@ def closed? def do_not_reverse_lookup=(flag) to_io.do_not_reverse_lookup = flag end + + def close_on_exec=(value) + to_io.close_on_exec = value + end + + def close_on_exec? + to_io.close_on_exec? + end + + def wait(*args) + to_io.wait(*args) + end + + def wait_readable(*args) + to_io.wait_readable(*args) + end + + def wait_writable(*args) + to_io.wait_writable(*args) + end end def verify_certificate_identity(cert, hostname) From f7178045bb11fc3722a98082ed81e1ec39c4940f Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Mon, 1 Jan 2024 22:50:32 +1300 Subject: [PATCH 123/640] [ruby/openssl] Add support for `gets(chomp: true)`. https://github.com/ruby/openssl/commit/8aa3849cff --- ext/openssl/lib/openssl/buffering.rb | 8 ++++++-- test/openssl/test_pair.rb | 11 +++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/ext/openssl/lib/openssl/buffering.rb b/ext/openssl/lib/openssl/buffering.rb index 9570f14f375632..68aa7bc97048b1 100644 --- a/ext/openssl/lib/openssl/buffering.rb +++ b/ext/openssl/lib/openssl/buffering.rb @@ -229,7 +229,7 @@ def read_nonblock(maxlen, buf=nil, exception: true) # # Unlike IO#gets the separator must be provided if a limit is provided. - def gets(eol=$/, limit=nil) + def gets(eol=$/, limit=nil, chomp: false) idx = @rbuffer.index(eol) until @eof break if idx @@ -244,7 +244,11 @@ def gets(eol=$/, limit=nil) if size && limit && limit >= 0 size = [size, limit].min end - consume_rbuff(size) + line = consume_rbuff(size) + if chomp && line + line.chomp!(eol) + end + line end ## diff --git a/test/openssl/test_pair.rb b/test/openssl/test_pair.rb index 14786100df5177..b616883925b210 100644 --- a/test/openssl/test_pair.rb +++ b/test/openssl/test_pair.rb @@ -115,6 +115,17 @@ def test_gets } end + def test_gets_chomp + ssl_pair {|s1, s2| + s1 << "line1\r\nline2\r\nline3\r\n" + s1.close + + assert_equal("line1", s2.gets("\r\n", chomp: true)) + assert_equal("line2\r\n", s2.gets("\r\n", chomp: false)) + assert_equal("line3", s2.gets(chomp: true)) + } + end + def test_gets_eof_limit ssl_pair {|s1, s2| s1.write("hello") From 3edb7f1a0747b92ccc22f881e0a74530c0a7036e Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 11 Jan 2024 22:46:49 +0900 Subject: [PATCH 124/640] [DOC] Documentize known_errors --- .document | 3 ++ error.c | 64 ++++++++++++++++++++-------------- template/Makefile.in | 11 +++++- template/known_errors.inc.tmpl | 8 +++-- 4 files changed, 57 insertions(+), 29 deletions(-) diff --git a/.document b/.document index e875e42546727b..0665d415b9ba89 100644 --- a/.document +++ b/.document @@ -31,6 +31,9 @@ trace_point.rb warning.rb yjit.rb +# Errno::* +known_errors.inc + # the lib/ directory (which has its own .document file) lib diff --git a/error.c b/error.c index 104e659ddefee7..447e845e5e50a0 100644 --- a/error.c +++ b/error.c @@ -2703,37 +2703,45 @@ rb_free_warning(void) } static VALUE -set_syserr(int n, const char *name) +setup_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); + VALUE 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, (st_data_t)error); + return error; +} + +static VALUE +set_syserr(int n, const char *name) +{ + st_data_t error; - rb_define_const(error, "Errno", INT2NUM(n)); - st_add_direct(syserr_tbl, n, error); + if (!st_lookup(syserr_tbl, n, &error)) { + return setup_syserr(n, name); } else { - rb_define_const(rb_mErrno, name, error); + VALUE errclass = (VALUE)error; + rb_define_const(rb_mErrno, name, errclass); + return errclass; } - return error; } static VALUE @@ -2742,12 +2750,12 @@ 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[DECIMAL_SIZE_OF(n) + sizeof("E-")]; snprintf(name, sizeof(name), "E%03d", n); - error = set_syserr(n, name); + return setup_syserr(n, name); } - return error; + return (VALUE)error; } /* @@ -3840,9 +3848,13 @@ rb_check_copyable(VALUE obj, VALUE orig) void Init_syserr(void) { - rb_eNOERROR = set_syserr(0, "NOERROR"); + rb_eNOERROR = setup_syserr(0, "NOERROR"); +#if 0 + /* No error */ + rb_define_const(rb_mErrno, "NOERROR", rb_eNOERROR); +#endif #define defined_error(name, num) set_syserr((num), (name)); -#define undefined_error(name) set_syserr(0, (name)); +#define undefined_error(name) rb_define_const(rb_mErrno, (name), rb_eNameError); #include "known_errors.inc" #undef defined_error #undef undefined_error diff --git a/template/Makefile.in b/template/Makefile.in index 8c462f20fb42e5..5b6cd87b06ab3b 100644 --- a/template/Makefile.in +++ b/template/Makefile.in @@ -575,7 +575,16 @@ update-benchmark-driver: $(BENCHMARK_DRIVER_GIT_URL) benchmark-driver $(GIT_OPTS) update-known-errors: - errno --list | cut -d' ' -f1 | sort -u - $(srcdir)/defs/known_errors.def | \ + errno --list | \ + $(BASERUBY) -nl -e 'BEGIN {errs = {}}' \ + -e '/^(E[A-Z_0-9]+)(?: +(?:\d+ +)?(.+))?/ =~ $$_ && errs[$$1] ||= $$2' \ + -e 'END {' \ + -e 'errs.delete("ELAST")' \ + -e 'errs = errs.sort' \ + -e 'errs << ["ELAST", "Largest errno"]' \ + -e 'errs.each {|e,d| puts sprintf("%-15s %s", e, d).strip}' \ + -e '}' \ + $(srcdir)/defs/known_errors.def - | \ $(IFCHANGE) $(srcdir)/defs/known_errors.def - INSNS = optinsn.inc optunifs.inc insns.inc insns_info.inc \ diff --git a/template/known_errors.inc.tmpl b/template/known_errors.inc.tmpl index c3aee7747718de..4d453395cafb70 100644 --- a/template/known_errors.inc.tmpl +++ b/template/known_errors.inc.tmpl @@ -4,8 +4,12 @@ * template/known_errors.inc.tmpl and defs/known_errors.def. */ -% error_names = ARGF.read.split(/\s+/) -% error_names.each do |name| +% error_names = ARGF.readlines.map {|line| [$1, $2] if /\A([A-Z]\S+)(?:\s+(\S.*))?/ =~ line}.compact +% error_names.each do |name, doc| +#if 0 + /* <% if doc %>"<%= doc %>"<% else %>\<%= name %><% end %> error */ + rb_define_const(rb_mErrno, "<%=name%>", e<%=name%>); +#endif #ifdef <%=name%> defined_error("<%=name%>", <%=name%>) #else From 573bfb3a148905f64dbe7633c833feead8e28683 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sat, 13 Jan 2024 00:05:34 +0900 Subject: [PATCH 125/640] [DOC] Add known_errors documents Incorporate from The Open Group. https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html --- defs/known_errors.def | 164 +++++++++++++++++++++--------------------- 1 file changed, 82 insertions(+), 82 deletions(-) diff --git a/defs/known_errors.def b/defs/known_errors.def index e9694cfbda684b..14b3cff2658908 100644 --- a/defs/known_errors.def +++ b/defs/known_errors.def @@ -1,57 +1,57 @@ -E2BIG -EACCES -EADDRINUSE -EADDRNOTAVAIL +E2BIG Argument list too long +EACCES Permission denied +EADDRINUSE Address in use +EADDRNOTAVAIL Address not available EADV -EAFNOSUPPORT -EAGAIN -EALREADY +EAFNOSUPPORT Address family not supported +EAGAIN Resource unavailable, try again (may be the same value as [EWOULDBLOCK]) +EALREADY Connection already in progress EAUTH EBADARCH EBADE EBADEXEC -EBADF +EBADF Bad file descriptor EBADFD EBADMACHO -EBADMSG +EBADMSG Bad message EBADR EBADRPC EBADRQC EBADSLT EBFONT -EBUSY -ECANCELED +EBUSY Device or resource busy +ECANCELED Operation canceled ECAPMODE -ECHILD +ECHILD No child processes ECHRNG ECOMM -ECONNABORTED -ECONNREFUSED -ECONNRESET -EDEADLK +ECONNABORTED Connection aborted +ECONNREFUSED Connection refused +ECONNRESET Connection reset +EDEADLK Resource deadlock would occur EDEADLOCK -EDESTADDRREQ +EDESTADDRREQ Destination address required EDEVERR -EDOM +EDOM Mathematics argument out of domain of function EDOOFUS EDOTDOT -EDQUOT -EEXIST -EFAULT -EFBIG +EDQUOT Reserved +EEXIST File exists +EFAULT Bad address +EFBIG File too large EFTYPE EHOSTDOWN -EHOSTUNREACH +EHOSTUNREACH Host is unreachable EHWPOISON -EIDRM -EILSEQ -EINPROGRESS -EINTR -EINVAL -EIO +EIDRM Identifier removed +EILSEQ Illegal byte sequence +EINPROGRESS Operation in progress +EINTR Interrupted function +EINVAL Invalid argument +EIO I/O error EIPSEC -EISCONN -EISDIR +EISCONN Socket is connected +EISDIR Is a directory EISNAM EKEYEXPIRED EKEYREJECTED @@ -60,98 +60,98 @@ EL2HLT EL2NSYNC EL3HLT EL3RST -ELAST ELIBACC ELIBBAD ELIBEXEC ELIBMAX ELIBSCN ELNRNG -ELOOP +ELOOP Too many levels of symbolic links EMEDIUMTYPE -EMFILE -EMLINK -EMSGSIZE -EMULTIHOP -ENAMETOOLONG +EMFILE File descriptor value too large +EMLINK Too many links +EMSGSIZE Message too large +EMULTIHOP Reserved +ENAMETOOLONG Filename too long ENAVAIL ENEEDAUTH -ENETDOWN -ENETRESET -ENETUNREACH -ENFILE +ENETDOWN Network is down +ENETRESET Connection aborted by network +ENETUNREACH Network unreachable +ENFILE Too many files open in system ENOANO ENOATTR -ENOBUFS +ENOBUFS No buffer space available ENOCSI -ENODATA -ENODEV -ENOENT -ENOEXEC +ENODATA [OB XSR] [Option Start] No message is available on the STREAM head read queue [Option End] +ENODEV No such device +ENOENT No such file or directory +ENOEXEC Executable file format error ENOKEY -ENOLCK -ENOLINK +ENOLCK No locks available +ENOLINK Reserved ENOMEDIUM -ENOMEM -ENOMSG +ENOMEM Not enough space +ENOMSG No message of the desired type ENONET ENOPKG ENOPOLICY -ENOPROTOOPT -ENOSPC -ENOSR -ENOSTR -ENOSYS +ENOPROTOOPT Protocol not available +ENOSPC No space left on device +ENOSR [OB XSR] [Option Start] No STREAM resources [Option End] +ENOSTR [OB XSR] [Option Start] Not a STREAM [Option End] +ENOSYS Functionality not supported ENOTBLK ENOTCAPABLE -ENOTCONN -ENOTDIR -ENOTEMPTY +ENOTCONN The socket is not connected +ENOTDIR Not a directory or a symbolic link to a directory +ENOTEMPTY Directory not empty ENOTNAM -ENOTRECOVERABLE -ENOTSOCK -ENOTSUP -ENOTTY +ENOTRECOVERABLE State not recoverable +ENOTSOCK Not a socket +ENOTSUP Not supported (may be the same value as [EOPNOTSUPP]) +ENOTTY Inappropriate I/O control operation ENOTUNIQ -ENXIO -EOPNOTSUPP -EOVERFLOW -EOWNERDEAD -EPERM +ENXIO No such device or address +EOPNOTSUPP Operation not supported on socket (may be the same value as [ENOTSUP]) +EOVERFLOW Value too large to be stored in data type +EOWNERDEAD Previous owner died +EPERM Operation not permitted EPFNOSUPPORT -EPIPE +EPIPE Broken pipe EPROCLIM EPROCUNAVAIL EPROGMISMATCH EPROGUNAVAIL -EPROTO -EPROTONOSUPPORT -EPROTOTYPE +EPROTO Protocol error +EPROTONOSUPPORT Protocol not supported +EPROTOTYPE Protocol wrong type for socket EPWROFF EQFULL -ERANGE +ERANGE Result too large EREMCHG EREMOTE EREMOTEIO ERESTART ERFKILL -EROFS +EROFS Read-only file system ERPCMISMATCH ESHLIBVERS ESHUTDOWN ESOCKTNOSUPPORT -ESPIPE -ESRCH +ESPIPE Invalid seek +ESRCH No such process ESRMNT -ESTALE +ESTALE Reserved ESTRPIPE -ETIME -ETIMEDOUT +ETIME [OB XSR] [Option Start] Stream ioctl() timeout [Option End] +ETIMEDOUT Connection timed out ETOOMANYREFS -ETXTBSY +ETXTBSY Text file busy EUCLEAN EUNATCH EUSERS -EWOULDBLOCK -EXDEV +EWOULDBLOCK Operation would block (may be the same value as [EAGAIN]) +EXDEV Cross-device link EXFULL +ELAST Largest errno From d999ed3a2f83fa223223e059eae0f361303ae07e Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sat, 13 Jan 2024 16:34:32 +0900 Subject: [PATCH 126/640] Fix typo --- error.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/error.c b/error.c index 447e845e5e50a0..16006b483ffbc5 100644 --- a/error.c +++ b/error.c @@ -3854,7 +3854,7 @@ Init_syserr(void) rb_define_const(rb_mErrno, "NOERROR", rb_eNOERROR); #endif #define defined_error(name, num) set_syserr((num), (name)); -#define undefined_error(name) rb_define_const(rb_mErrno, (name), rb_eNameError); +#define undefined_error(name) rb_define_const(rb_mErrno, (name), rb_eNOERROR); #include "known_errors.inc" #undef defined_error #undef undefined_error From b92c8934a29c9cb62f3d05eef74117a06c2cd8a8 Mon Sep 17 00:00:00 2001 From: yui-knk Date: Sat, 13 Jan 2024 17:37:31 +0900 Subject: [PATCH 127/640] Lrama v0.6.1 --- tool/lrama/NEWS.md | 46 +++ tool/lrama/lib/lrama/command.rb | 20 +- tool/lrama/lib/lrama/context.rb | 24 +- tool/lrama/lib/lrama/grammar.rb | 16 +- tool/lrama/lib/lrama/grammar/binding.rb | 24 ++ .../lib/lrama/grammar/code/rule_action.rb | 2 +- .../lib/lrama/grammar/parameterizing_rule.rb | 9 +- .../grammar/parameterizing_rule/resolver.rb | 39 +++ .../lrama/grammar/parameterizing_rule/rhs.rb | 15 + .../lrama/grammar/parameterizing_rule/rule.rb | 16 + .../grammar/parameterizing_rule_builder.rb | 34 -- .../grammar/parameterizing_rule_resolver.rb | 30 -- .../parameterizing_rule_rhs_builder.rb | 53 --- tool/lrama/lib/lrama/grammar/percent_code.rb | 6 +- tool/lrama/lib/lrama/grammar/rule_builder.rb | 84 +++-- tool/lrama/lib/lrama/grammar/type.rb | 14 +- tool/lrama/lib/lrama/lexer.rb | 9 +- tool/lrama/lib/lrama/lexer/grammar_file.rb | 2 +- tool/lrama/lib/lrama/lexer/token.rb | 5 + .../lib/lrama/lexer/token/instantiate_rule.rb | 9 +- tool/lrama/lib/lrama/output.rb | 4 +- tool/lrama/lib/lrama/parser.rb | 314 +++++++++--------- tool/lrama/lib/lrama/version.rb | 2 +- 23 files changed, 429 insertions(+), 348 deletions(-) create mode 100644 tool/lrama/lib/lrama/grammar/binding.rb create mode 100644 tool/lrama/lib/lrama/grammar/parameterizing_rule/resolver.rb create mode 100644 tool/lrama/lib/lrama/grammar/parameterizing_rule/rhs.rb create mode 100644 tool/lrama/lib/lrama/grammar/parameterizing_rule/rule.rb delete mode 100644 tool/lrama/lib/lrama/grammar/parameterizing_rule_builder.rb delete mode 100644 tool/lrama/lib/lrama/grammar/parameterizing_rule_resolver.rb delete mode 100644 tool/lrama/lib/lrama/grammar/parameterizing_rule_rhs_builder.rb diff --git a/tool/lrama/NEWS.md b/tool/lrama/NEWS.md index 0af278fc067db7..c4a0f28f5b4eea 100644 --- a/tool/lrama/NEWS.md +++ b/tool/lrama/NEWS.md @@ -1,5 +1,49 @@ # NEWS for Lrama +## Lrama 0.6.1 (2024-01-13) + +### Nested parameterizing rules + +Allow to pass an instantiated rule to other parameterizing rules. + +``` +%rule constant(X) : X + ; + +%rule option(Y) : /* empty */ + | Y + ; + +%% + +program : option(constant(number)) // Nested rule + ; +%% +``` + +Allow to use nested parameterizing rules when define parameterizing rules. + +``` +%rule option(x) : /* empty */ + | X + ; + +%rule double(Y) : Y Y + ; + +%rule double_opt(A) : option(double(A)) // Nested rule + ; + +%% + +program : double_opt(number) + ; + +%% +``` + +https://github.com/ruby/lrama/pull/337 + ## Lrama 0.6.0 (2023-12-25) ### User defined parameterizing rules @@ -20,6 +64,8 @@ stmt: pair(ODD, EVEN) ; ``` +https://github.com/ruby/lrama/pull/285 + ## Lrama 0.5.11 (2023-12-02) ### Type specification of parameterizing rules diff --git a/tool/lrama/lib/lrama/command.rb b/tool/lrama/lib/lrama/command.rb index b6b1fd27666f95..a39eed139baea0 100644 --- a/tool/lrama/lib/lrama/command.rb +++ b/tool/lrama/lib/lrama/command.rb @@ -1,14 +1,28 @@ module Lrama class Command def run(argv) - options = OptionParser.new.parse(argv) + begin + options = OptionParser.new.parse(argv) + rescue => e + message = e.message + message = message.gsub(/.+/, "\e[1m\\&\e[m") if Exception.to_tty? + abort message + end Report::Duration.enable if options.trace_opts[:time] warning = Lrama::Warning.new text = options.y.read options.y.close if options.y != STDIN - grammar = Lrama::Parser.new(text, options.grammar_file, options.debug).parse + parser = Lrama::Parser.new(text, options.grammar_file, options.debug) + begin + grammar = parser.parse + rescue => e + raise e if options.debug + message = e.message + message = message.gsub(/.+/, "\e[1m\\&\e[m") if Exception.to_tty? + abort message + end states = Lrama::States.new(grammar, warning, trace_state: (options.trace_opts[:automaton] || options.trace_opts[:closure])) states.compute context = Lrama::Context.new(states) @@ -39,7 +53,7 @@ def run(argv) end if warning.has_error? - exit 1 + exit false end end end diff --git a/tool/lrama/lib/lrama/context.rb b/tool/lrama/lib/lrama/context.rb index 895290a2bb2107..245c91a199d544 100644 --- a/tool/lrama/lib/lrama/context.rb +++ b/tool/lrama/lib/lrama/context.rb @@ -9,7 +9,7 @@ class Context BaseMin = -Float::INFINITY # TODO: It might be better to pass `states` to Output directly? - attr_reader :states + attr_reader :states, :yylast, :yypact_ninf, :yytable_ninf, :yydefact, :yydefgoto def initialize(states) @states = states @@ -41,15 +41,11 @@ def yysymbol_kind_t def yyfinal @states.states.find do |state| state.items.find do |item| - item.rule.lhs.id.s_value == "$accept" && item.end_of_rule? + item.rule.lhs.accept_symbol? && item.end_of_rule? end end.id end - def yylast - @yylast - end - # Number of terms def yyntokens @states.terms.count @@ -119,30 +115,14 @@ def yytname end end - def yypact_ninf - @yypact_ninf - end - - def yytable_ninf - @yytable_ninf - end - def yypact @base[0...yynstates] end - def yydefact - @yydefact - end - def yypgoto @base[yynstates..-1] end - def yydefgoto - @yydefgoto - end - def yytable @table end diff --git a/tool/lrama/lib/lrama/grammar.rb b/tool/lrama/lib/lrama/grammar.rb index 8fed581f6b9f14..9c500b381d47d7 100644 --- a/tool/lrama/lib/lrama/grammar.rb +++ b/tool/lrama/lib/lrama/grammar.rb @@ -1,4 +1,5 @@ require "lrama/grammar/auxiliary" +require "lrama/grammar/binding" require "lrama/grammar/code" require "lrama/grammar/counter" require "lrama/grammar/error_token" @@ -8,9 +9,6 @@ require "lrama/grammar/reference" require "lrama/grammar/rule" require "lrama/grammar/rule_builder" -require "lrama/grammar/parameterizing_rule_builder" -require "lrama/grammar/parameterizing_rule_resolver" -require "lrama/grammar/parameterizing_rule_rhs_builder" require "lrama/grammar/parameterizing_rule" require "lrama/grammar/symbol" require "lrama/grammar/type" @@ -40,7 +38,7 @@ def initialize(rule_counter) @rule_builders = [] @rules = [] @sym_to_rules = {} - @parameterizing_resolver = ParameterizingRuleResolver.new + @parameterizing_rule_resolver = ParameterizingRule::Resolver.new @empty_symbol = nil @eof_symbol = nil @error_symbol = nil @@ -52,7 +50,7 @@ def initialize(rule_counter) end def add_percent_code(id:, code:) - @percent_codes << PercentCode.new(id, code) + @percent_codes << PercentCode.new(id.s_value, code.s_value) end def add_printer(ident_or_tags:, token_code:, lineno:) @@ -134,8 +132,8 @@ def add_rule_builder(builder) @rule_builders << builder end - def add_parameterizing_rule_builder(builder) - @parameterizing_resolver.add_parameterizing_rule_builder(builder) + def add_parameterizing_rule(rule) + @parameterizing_rule_resolver.add_parameterizing_rule(rule) end def prologue_first_lineno=(prologue_first_lineno) @@ -171,7 +169,7 @@ def prepare # TODO: More validation methods # - # * Validaiton for no_declared_type_reference + # * Validation for no_declared_type_reference def validate! validate_symbol_number_uniqueness! validate_symbol_alias_name_uniqueness! @@ -319,7 +317,7 @@ def compute_first_set def setup_rules @rule_builders.each do |builder| - builder.setup_rules(@parameterizing_resolver) + builder.setup_rules(@parameterizing_rule_resolver) end end diff --git a/tool/lrama/lib/lrama/grammar/binding.rb b/tool/lrama/lib/lrama/grammar/binding.rb new file mode 100644 index 00000000000000..e5ea3fb037c21b --- /dev/null +++ b/tool/lrama/lib/lrama/grammar/binding.rb @@ -0,0 +1,24 @@ +module Lrama + class Grammar + class Binding + attr_reader :actual_args, :count + + def initialize(parameterizing_rule, actual_args) + @parameters = parameterizing_rule.parameters + @actual_args = actual_args + @parameter_to_arg = @parameters.zip(actual_args).map do |param, arg| + [param.s_value, arg] + end.to_h + end + + def resolve_symbol(symbol) + if symbol.is_a?(Lexer::Token::InstantiateRule) + resolved_args = symbol.args.map { |arg| resolve_symbol(arg) } + Lrama::Lexer::Token::InstantiateRule.new(s_value: symbol.s_value, location: symbol.location, args: resolved_args, lhs_tag: symbol.lhs_tag) + else + @parameter_to_arg[symbol.s_value] || symbol + end + end + end + end +end diff --git a/tool/lrama/lib/lrama/grammar/code/rule_action.rb b/tool/lrama/lib/lrama/grammar/code/rule_action.rb index 8a67b732e625c8..76169b91ede76b 100644 --- a/tool/lrama/lib/lrama/grammar/code/rule_action.rb +++ b/tool/lrama/lib/lrama/grammar/code/rule_action.rb @@ -22,7 +22,7 @@ def initialize(type:, token_code:, rule:) # For the semantic action of original rule: # # "Rule" class: keyword_class { $1 } tSTRING { $2 + $3 } keyword_end { $class = $1 + $keyword_end } - # "Position in grammar" $1 $2 $3 $4 $5 $6 + # "Position in grammar" $1 $2 $3 $4 $5 # "Index for yyvsp" -4 -3 -2 -1 0 # # diff --git a/tool/lrama/lib/lrama/grammar/parameterizing_rule.rb b/tool/lrama/lib/lrama/grammar/parameterizing_rule.rb index aa8865d53d042f..d371805f4b303f 100644 --- a/tool/lrama/lib/lrama/grammar/parameterizing_rule.rb +++ b/tool/lrama/lib/lrama/grammar/parameterizing_rule.rb @@ -1,6 +1,3 @@ -module Lrama - class Grammar - class ParameterizingRule < Struct.new(:rules, :token, keyword_init: true) - end - end -end +require_relative 'parameterizing_rule/resolver' +require_relative 'parameterizing_rule/rhs' +require_relative 'parameterizing_rule/rule' diff --git a/tool/lrama/lib/lrama/grammar/parameterizing_rule/resolver.rb b/tool/lrama/lib/lrama/grammar/parameterizing_rule/resolver.rb new file mode 100644 index 00000000000000..f5de9d0bf39825 --- /dev/null +++ b/tool/lrama/lib/lrama/grammar/parameterizing_rule/resolver.rb @@ -0,0 +1,39 @@ +module Lrama + class Grammar + class ParameterizingRule + class Resolver + attr_accessor :created_lhs_list + + def initialize + @rules = [] + @created_lhs_list = [] + end + + def add_parameterizing_rule(rule) + @rules << rule + end + + def defined?(token) + !select_rules(token).empty? + end + + def find(token) + select_rules(token).last + end + + def created_lhs(lhs_s_value) + @created_lhs_list.select { |created_lhs| created_lhs.s_value == lhs_s_value }.last + end + + private + + def select_rules(token) + @rules.select do |rule| + rule.name == token.rule_name && + rule.required_parameters_count == token.args_count + end + end + end + end + end +end diff --git a/tool/lrama/lib/lrama/grammar/parameterizing_rule/rhs.rb b/tool/lrama/lib/lrama/grammar/parameterizing_rule/rhs.rb new file mode 100644 index 00000000000000..7f50be873c2438 --- /dev/null +++ b/tool/lrama/lib/lrama/grammar/parameterizing_rule/rhs.rb @@ -0,0 +1,15 @@ +module Lrama + class Grammar + class ParameterizingRule + class Rhs + attr_accessor :symbols, :user_code, :precedence_sym + + def initialize + @symbols = [] + @user_code = nil + @precedence_sym = nil + end + end + end + end +end diff --git a/tool/lrama/lib/lrama/grammar/parameterizing_rule/rule.rb b/tool/lrama/lib/lrama/grammar/parameterizing_rule/rule.rb new file mode 100644 index 00000000000000..9c1d46e4f52601 --- /dev/null +++ b/tool/lrama/lib/lrama/grammar/parameterizing_rule/rule.rb @@ -0,0 +1,16 @@ +module Lrama + class Grammar + class ParameterizingRule + class Rule + attr_reader :name, :parameters, :rhs_list, :required_parameters_count + + def initialize(name, parameters, rhs_list) + @name = name + @parameters = parameters + @rhs_list = rhs_list + @required_parameters_count = parameters.count + end + end + end + end +end diff --git a/tool/lrama/lib/lrama/grammar/parameterizing_rule_builder.rb b/tool/lrama/lib/lrama/grammar/parameterizing_rule_builder.rb deleted file mode 100644 index 94566a80e1b363..00000000000000 --- a/tool/lrama/lib/lrama/grammar/parameterizing_rule_builder.rb +++ /dev/null @@ -1,34 +0,0 @@ -module Lrama - class Grammar - class ParameterizingRuleBuilder - attr_reader :name, :parameters, :rhs - - def initialize(name, parameters, rhs) - @name = name - @parameters = parameters - @rhs = rhs - @required_parameters_count = parameters.count - end - - def build_rules(token, actual_args, rule_counter, lhs_tag, line, rule_builders) - validate_argument_number!(token) - lhs = lhs(actual_args) - @rhs.map do |rhs| - rhs.build_rules(token, actual_args, parameters, rule_counter, lhs, lhs_tag, line, rule_builders) - end.flatten - end - - private - - def validate_argument_number!(token) - unless @required_parameters_count == token.args.count - raise "Invalid number of arguments. expect: #{@required_parameters_count} actual: #{token.args.count}" - end - end - - def lhs(actual_args) - Lrama::Lexer::Token::Ident.new(s_value: "#{name}_#{actual_args.map(&:s_value).join('_')}") - end - end - end -end diff --git a/tool/lrama/lib/lrama/grammar/parameterizing_rule_resolver.rb b/tool/lrama/lib/lrama/grammar/parameterizing_rule_resolver.rb deleted file mode 100644 index 9d92a412ef3db4..00000000000000 --- a/tool/lrama/lib/lrama/grammar/parameterizing_rule_resolver.rb +++ /dev/null @@ -1,30 +0,0 @@ -module Lrama - class Grammar - class ParameterizingRuleResolver - def initialize - @parameterizing_rule_builders = [] - end - - def add_parameterizing_rule_builder(builder) - @parameterizing_rule_builders << builder - end - - def defined?(name) - !rule_builders(name).empty? - end - - def build_rules(token, rule_counter, lhs_tag, line) - builder = rule_builders(token.s_value).last - raise "Unknown parameterizing rule #{token.s_value} at line #{token.line}" unless builder - - builder.build_rules(token, token.args, rule_counter, lhs_tag, line, @parameterizing_rule_builders) - end - - private - - def rule_builders(name) - @parameterizing_rule_builders.select { |builder| builder.name == name } - end - end - end -end diff --git a/tool/lrama/lib/lrama/grammar/parameterizing_rule_rhs_builder.rb b/tool/lrama/lib/lrama/grammar/parameterizing_rule_rhs_builder.rb deleted file mode 100644 index 9d15fb1880fbfe..00000000000000 --- a/tool/lrama/lib/lrama/grammar/parameterizing_rule_rhs_builder.rb +++ /dev/null @@ -1,53 +0,0 @@ -module Lrama - class Grammar - class ParameterizingRuleRhsBuilder - attr_accessor :symbols, :user_code, :precedence_sym - - def initialize - @symbols = [] - @user_code = nil - @precedence_sym = nil - end - - def build_rules(token, actual_args, parameters, rule_counter, lhs, lhs_tag, line, rule_builders) - nested_rules = build_nested_rules(token, actual_args, parameters, rule_counter, lhs_tag, line, rule_builders) - rule = Rule.new(id: rule_counter.increment, _lhs: lhs, _rhs: rhs(token, actual_args, parameters, nested_rules.last), lhs_tag: lhs_tag, token_code: user_code, precedence_sym: precedence_sym, lineno: line) - ParameterizingRule.new(rules: nested_rules.map(&:rules) + [rule], token: lhs) - end - - private - - def build_nested_rules(token, actual_args, parameters, rule_counter, lhs_tag, line, rule_builders) - symbols.each_with_index.map do |sym, i| - next unless sym.is_a?(Lexer::Token::InstantiateRule) - - builder = rule_builders.select { |builder| builder.name == sym.s_value }.last - raise "Unknown parameterizing rule #{token.s_value} at line #{token.line}" unless builder - - builder.build_rules(sym, nested_actual_args(actual_args, parameters, i), rule_counter, lhs_tag, line, rule_builders) - end.flatten.compact - end - - def nested_actual_args(actual_args, parameters, idx) - symbols[idx].args.map do |arg| - i = parameters.index { |parameter| parameter.s_value == arg.s_value } - i.nil? ? arg : actual_args[i] - end - end - - def rhs(token, actual_args, parameters, nested_rule) - symbols.map do |sym| - if sym.is_a?(Lexer::Token::InstantiateRule) - sym.args.map do |arg| - idx = parameters.index { |parameter| parameter.s_value == arg.s_value } - idx.nil? ? sym : nested_rule&.token - end - else - idx = parameters.index { |parameter| parameter.s_value == sym.s_value } - idx.nil? ? sym : actual_args[idx] - end - end.flatten - end - end - end -end diff --git a/tool/lrama/lib/lrama/grammar/percent_code.rb b/tool/lrama/lib/lrama/grammar/percent_code.rb index 5faa3a582bfe02..8cbc5aef2ccf5b 100644 --- a/tool/lrama/lib/lrama/grammar/percent_code.rb +++ b/tool/lrama/lib/lrama/grammar/percent_code.rb @@ -1,10 +1,10 @@ module Lrama class Grammar class PercentCode - attr_reader :id, :code + attr_reader :name, :code - def initialize(id, code) - @id = id + def initialize(name, code) + @name = name @code = code end end diff --git a/tool/lrama/lib/lrama/grammar/rule_builder.rb b/tool/lrama/lib/lrama/grammar/rule_builder.rb index c17a4048d80dea..757554f46d041c 100644 --- a/tool/lrama/lib/lrama/grammar/rule_builder.rb +++ b/tool/lrama/lib/lrama/grammar/rule_builder.rb @@ -3,21 +3,22 @@ module Lrama class Grammar class RuleBuilder - attr_accessor :lhs, :lhs_tag, :line - attr_reader :rhs, :user_code, :precedence_sym + attr_accessor :lhs, :line + attr_reader :lhs_tag, :rhs, :user_code, :precedence_sym - def initialize(rule_counter, midrule_action_counter, position_in_original_rule_rhs = nil, skip_preprocess_references: false) + def initialize(rule_counter, midrule_action_counter, position_in_original_rule_rhs = nil, lhs_tag: nil, skip_preprocess_references: false) @rule_counter = rule_counter @midrule_action_counter = midrule_action_counter @position_in_original_rule_rhs = position_in_original_rule_rhs @skip_preprocess_references = skip_preprocess_references @lhs = nil + @lhs_tag = lhs_tag @rhs = [] - @lhs_tag = nil @user_code = nil @precedence_sym = nil @line = nil + @rule_builders_for_parameterizing_rules = [] @rule_builders_for_derived_rules = [] end @@ -33,7 +34,7 @@ def add_rhs(rhs) def user_code=(user_code) if !@line - @line = user_code.line + @line = user_code&.line end flush_user_code @@ -51,14 +52,14 @@ def complete_input freeze_rhs end - def setup_rules(parameterizing_resolver) + def setup_rules(parameterizing_rule_resolver) preprocess_references unless @skip_preprocess_references - process_rhs(parameterizing_resolver) + process_rhs(parameterizing_rule_resolver) build_rules end def rules - @parameterizing_rules + @midrule_action_rules + @rules + @parameterizing_rules + @old_parameterizing_rules + @midrule_action_rules + @rules end private @@ -75,10 +76,13 @@ def build_rules tokens = @replaced_rhs rule = Rule.new( - id: @rule_counter.increment, _lhs: lhs, _rhs: tokens, token_code: user_code, + id: @rule_counter.increment, _lhs: lhs, _rhs: tokens, lhs_tag: lhs_tag, token_code: user_code, position_in_original_rule_rhs: @position_in_original_rule_rhs, precedence_sym: precedence_sym, lineno: line ) @rules = [rule] + @parameterizing_rules = @rule_builders_for_parameterizing_rules.map do |rule_builder| + rule_builder.rules + end.flatten @midrule_action_rules = @rule_builders_for_derived_rules.map do |rule_builder| rule_builder.rules end.flatten @@ -89,11 +93,11 @@ def build_rules # rhs is a mixture of variety type of tokens like `Ident`, `InstantiateRule`, `UserCode` and so on. # `#process_rhs` replaces some kind of tokens to `Ident` so that all `@replaced_rhs` are `Ident` or `Char`. - def process_rhs(parameterizing_resolver) + def process_rhs(parameterizing_rule_resolver) return if @replaced_rhs @replaced_rhs = [] - @parameterizing_rules = [] + @old_parameterizing_rules = [] rhs.each_with_index do |token, i| case token @@ -102,26 +106,46 @@ def process_rhs(parameterizing_resolver) when Lrama::Lexer::Token::Ident @replaced_rhs << token when Lrama::Lexer::Token::InstantiateRule - if parameterizing_resolver.defined?(token.rule_name) - parameterizing = parameterizing_resolver.build_rules(token, @rule_counter, @lhs_tag, line) - @parameterizing_rules = @parameterizing_rules + parameterizing.map(&:rules).flatten - @replaced_rhs = @replaced_rhs + parameterizing.map(&:token).flatten.uniq + if parameterizing_rule_resolver.defined?(token) + parameterizing_rule = parameterizing_rule_resolver.find(token) + raise "Unexpected token. #{token}" unless parameterizing_rule + + bindings = Binding.new(parameterizing_rule, token.args) + lhs_s_value = lhs_s_value(token, bindings) + if (created_lhs = parameterizing_rule_resolver.created_lhs(lhs_s_value)) + @replaced_rhs << created_lhs + else + lhs_token = Lrama::Lexer::Token::Ident.new(s_value: lhs_s_value, location: token.location) + @replaced_rhs << lhs_token + parameterizing_rule_resolver.created_lhs_list << lhs_token + parameterizing_rule.rhs_list.each do |r| + rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, i, lhs_tag: token.lhs_tag, skip_preprocess_references: true) + rule_builder.lhs = lhs_token + r.symbols.each { |sym| rule_builder.add_rhs(bindings.resolve_symbol(sym)) } + rule_builder.line = line + rule_builder.user_code = r.user_code + rule_builder.precedence_sym = r.precedence_sym + rule_builder.complete_input + rule_builder.setup_rules(parameterizing_rule_resolver) + @rule_builders_for_parameterizing_rules << rule_builder + end + end else # TODO: Delete when the standard library will defined as a grammar file. - parameterizing = ParameterizingRules::Builder.new(token, @rule_counter, @lhs_tag, user_code, precedence_sym, line) - @parameterizing_rules = @parameterizing_rules + parameterizing.build - @replaced_rhs << parameterizing.build_token + parameterizing_rule = ParameterizingRules::Builder.new(token, @rule_counter, token.lhs_tag, user_code, precedence_sym, line) + @old_parameterizing_rules = @old_parameterizing_rules + parameterizing_rule.build + @replaced_rhs << parameterizing_rule.build_token end when Lrama::Lexer::Token::UserCode prefix = token.referred ? "@" : "$@" new_token = Lrama::Lexer::Token::Ident.new(s_value: prefix + @midrule_action_counter.increment.to_s) @replaced_rhs << new_token - rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, i, skip_preprocess_references: true) + rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, i, lhs_tag: lhs_tag, skip_preprocess_references: true) rule_builder.lhs = new_token rule_builder.user_code = token rule_builder.complete_input - rule_builder.setup_rules(parameterizing_resolver) + rule_builder.setup_rules(parameterizing_rule_resolver) @rule_builders_for_derived_rules << rule_builder else @@ -130,6 +154,18 @@ def process_rhs(parameterizing_resolver) end end + def lhs_s_value(token, bindings) + s_values = token.args.map do |arg| + resolved = bindings.resolve_symbol(arg) + if resolved.is_a?(Lexer::Token::InstantiateRule) + [resolved.s_value, resolved.args.map(&:s_value)] + else + resolved.s_value + end + end + "#{token.rule_name}_#{s_values.join('_')}" + end + def numberize_references # Bison n'th component is 1-origin (rhs + [user_code]).compact.each.with_index(1) do |token, i| @@ -144,13 +180,11 @@ def numberize_references candidates = rhs.each_with_index.select {|token, i| token.referred_by?(ref_name) } if candidates.size >= 2 - location = token.location.partial_location(ref.first_column, ref.last_column) - raise location.generate_error_message("Referring symbol `#{ref_name}` is duplicated.") + token.invalid_ref(ref, "Referring symbol `#{ref_name}` is duplicated.") end unless (referring_symbol = candidates.first) - location = token.location.partial_location(ref.first_column, ref.last_column) - raise location.generate_error_message("Referring symbol `#{ref_name}` is not found.") + token.invalid_ref(ref, "Referring symbol `#{ref_name}` is not found.") end ref.index = referring_symbol[1] + 1 @@ -163,7 +197,7 @@ def numberize_references if ref.index # TODO: Prohibit $0 even so Bison allows it? # See: https://www.gnu.org/software/bison/manual/html_node/Actions.html - raise "Can not refer following component. #{ref.index} >= #{i}. #{token}" if ref.index >= i + token.invalid_ref(ref, "Can not refer following component. #{ref.index} >= #{i}.") if ref.index >= i rhs[ref.index - 1].referred = true end end diff --git a/tool/lrama/lib/lrama/grammar/type.rb b/tool/lrama/lib/lrama/grammar/type.rb index 6861d9f846c283..6b4b0961a14177 100644 --- a/tool/lrama/lib/lrama/grammar/type.rb +++ b/tool/lrama/lib/lrama/grammar/type.rb @@ -1,6 +1,18 @@ module Lrama class Grammar - class Type < Struct.new(:id, :tag, keyword_init: true) + class Type + attr_reader :id, :tag + + def initialize(id:, tag:) + @id = id + @tag = tag + end + + def ==(other) + self.class == other.class && + self.id == other.id && + self.tag == other.tag + end end end end diff --git a/tool/lrama/lib/lrama/lexer.rb b/tool/lrama/lib/lrama/lexer.rb index 4f394a9815f553..746d50cee5c221 100644 --- a/tool/lrama/lib/lrama/lexer.rb +++ b/tool/lrama/lib/lrama/lexer.rb @@ -5,9 +5,8 @@ module Lrama class Lexer - attr_reader :head_line, :head_column - attr_accessor :status - attr_accessor :end_symbol + attr_reader :head_line, :head_column, :line + attr_accessor :status, :end_symbol SYMBOLS = ['%{', '%}', '%%', '{', '}', '\[', '\]', '\(', '\)', '\,', ':', '\|', ';'] PERCENT_TOKENS = %w( @@ -50,10 +49,6 @@ def next_token end end - def line - @line - end - def column @scanner.pos - @head end diff --git a/tool/lrama/lib/lrama/lexer/grammar_file.rb b/tool/lrama/lib/lrama/lexer/grammar_file.rb index 2200bcbf289c2c..6be07670041453 100644 --- a/tool/lrama/lib/lrama/lexer/grammar_file.rb +++ b/tool/lrama/lib/lrama/lexer/grammar_file.rb @@ -5,7 +5,7 @@ class GrammarFile def initialize(path, text) @path = path - @text = text + @text = text.freeze end def ==(other) diff --git a/tool/lrama/lib/lrama/lexer/token.rb b/tool/lrama/lib/lrama/lexer/token.rb index 22b798376a1730..5278e98725b297 100644 --- a/tool/lrama/lib/lrama/lexer/token.rb +++ b/tool/lrama/lib/lrama/lexer/token.rb @@ -46,6 +46,11 @@ def last_line def last_column location.last_column end + + def invalid_ref(ref, message) + location = self.location.partial_location(ref.first_column, ref.last_column) + raise location.generate_error_message(message) + end end end end diff --git a/tool/lrama/lib/lrama/lexer/token/instantiate_rule.rb b/tool/lrama/lib/lrama/lexer/token/instantiate_rule.rb index 9b703dd9d29db4..1c4d1095c8f22b 100644 --- a/tool/lrama/lib/lrama/lexer/token/instantiate_rule.rb +++ b/tool/lrama/lib/lrama/lexer/token/instantiate_rule.rb @@ -2,16 +2,21 @@ module Lrama class Lexer class Token class InstantiateRule < Token - attr_accessor :args + attr_reader :args, :lhs_tag - def initialize(s_value:, alias_name: nil, location: nil, args: []) + def initialize(s_value:, alias_name: nil, location: nil, args: [], lhs_tag: nil) super s_value: s_value, alias_name: alias_name, location: location @args = args + @lhs_tag = lhs_tag end def rule_name s_value end + + def args_count + args.count + end end end end diff --git a/tool/lrama/lib/lrama/output.rb b/tool/lrama/lib/lrama/output.rb index f67208509764c8..936a3de8d10102 100644 --- a/tool/lrama/lib/lrama/output.rb +++ b/tool/lrama/lib/lrama/output.rb @@ -352,9 +352,9 @@ def b4_cpp_guard__b4_spec_mapped_header_file # b4_percent_code_get def percent_code(name) @grammar.percent_codes.select do |percent_code| - percent_code.id.s_value == name + percent_code.name == name end.map do |percent_code| - percent_code.code.s_value + percent_code.code end.join end diff --git a/tool/lrama/lib/lrama/parser.rb b/tool/lrama/lib/lrama/parser.rb index 797851e8816a28..9434b18cc5519b 100644 --- a/tool/lrama/lib/lrama/parser.rb +++ b/tool/lrama/lib/lrama/parser.rb @@ -734,11 +734,11 @@ def raise_parse_error(error_message, location) ##### State transition tables begin ### racc_action_table = [ - 85, 44, 86, 145, 144, 67, 44, 44, 145, 187, - 67, 67, 44, 6, 187, 7, 67, 147, 196, 44, - 143, 43, 147, 188, 58, 163, 164, 165, 188, 3, + 85, 44, 86, 145, 144, 67, 44, 44, 145, 188, + 67, 67, 44, 6, 188, 7, 67, 147, 199, 44, + 143, 43, 147, 189, 58, 163, 164, 165, 189, 3, 44, 40, 43, 8, 67, 63, 34, 44, 148, 43, - 41, 87, 40, 148, 189, 47, 44, 80, 43, 189, + 41, 87, 40, 148, 190, 47, 44, 80, 43, 190, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 47, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 9, 44, 47, 43, 13, 14, 15, 16, 17, @@ -750,22 +750,23 @@ def raise_parse_error(error_message, location) 43, 43, 67, 173, 44, 44, 43, 43, 67, 173, 44, 44, 43, 43, 67, 173, 44, 44, 43, 43, 67, 67, 44, 44, 43, 43, 67, 67, 44, 44, - 43, 43, 67, 67, 44, 44, 43, 43, 67, 67, - 44, 44, 43, 43, 67, 67, 163, 164, 165, 83, - 44, 44, 43, 43, 141, 190, 142, 191, 205, 54, - 191, 55, 76, 77, 81, 83, 88, 88, 88, 90, - 96, 100, 101, 104, 104, 104, 104, 107, 110, 111, - 113, 115, 116, 117, 118, 119, 122, 126, 127, 128, - 131, 132, 133, 135, 150, 152, 153, 154, 155, 156, - 157, 158, 131, 160, 168, 169, 178, 182, 183, 185, - 178, 83, 182, 201, 203, 83, 207, 83 ] + 43, 43, 67, 67, 44, 44, 179, 43, 67, 67, + 44, 44, 179, 43, 67, 67, 44, 44, 179, 43, + 67, 163, 164, 165, 83, 44, 141, 43, 142, 192, + 54, 193, 163, 164, 165, 208, 210, 193, 193, 55, + 76, 77, 81, 83, 88, 88, 88, 90, 96, 100, + 101, 104, 104, 104, 104, 107, 110, 111, 113, 115, + 116, 117, 118, 119, 122, 126, 127, 128, 131, 132, + 133, 135, 150, 152, 153, 154, 155, 156, 157, 158, + 131, 160, 168, 169, 178, 183, 184, 186, 191, 178, + 83, 183, 205, 207, 83, 212, 83 ] racc_action_check = [ 42, 130, 42, 130, 129, 130, 159, 177, 159, 177, - 159, 177, 193, 2, 193, 2, 193, 130, 187, 26, - 129, 26, 159, 177, 26, 187, 187, 187, 193, 1, + 159, 177, 196, 2, 196, 2, 196, 130, 188, 26, + 129, 26, 159, 177, 26, 188, 188, 188, 196, 1, 27, 9, 27, 3, 27, 27, 7, 14, 130, 14, - 13, 42, 35, 159, 177, 15, 57, 35, 57, 193, + 13, 42, 35, 159, 177, 15, 57, 35, 57, 196, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 16, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 4, 58, 17, 58, 4, 4, 4, 4, 4, @@ -777,110 +778,113 @@ def raise_parse_error(error_message, location) 170, 98, 170, 170, 174, 104, 174, 104, 174, 174, 175, 106, 175, 106, 175, 175, 62, 63, 62, 63, 62, 63, 101, 103, 101, 103, 101, 103, 123, 148, - 123, 148, 123, 148, 160, 189, 160, 189, 160, 189, - 191, 196, 191, 196, 191, 196, 146, 146, 146, 146, - 120, 124, 120, 124, 125, 179, 125, 179, 202, 24, - 202, 25, 32, 33, 38, 39, 46, 48, 49, 50, - 56, 60, 61, 68, 73, 74, 75, 76, 82, 83, - 89, 91, 92, 93, 94, 95, 99, 107, 108, 109, - 110, 111, 112, 114, 134, 136, 137, 138, 139, 140, - 141, 142, 143, 145, 149, 151, 157, 162, 166, 176, - 185, 186, 190, 192, 197, 201, 206, 207 ] + 123, 148, 123, 148, 160, 190, 160, 190, 160, 190, + 191, 193, 191, 193, 191, 193, 199, 120, 199, 120, + 199, 146, 146, 146, 146, 124, 125, 124, 125, 180, + 24, 180, 181, 181, 181, 202, 206, 202, 206, 25, + 32, 33, 38, 39, 46, 48, 49, 50, 56, 60, + 61, 68, 73, 74, 75, 76, 82, 83, 89, 91, + 92, 93, 94, 95, 99, 107, 108, 109, 110, 111, + 112, 114, 134, 136, 137, 138, 139, 140, 141, 142, + 143, 145, 149, 151, 157, 162, 166, 176, 179, 186, + 187, 192, 195, 200, 205, 211, 212 ] racc_action_pointer = [ nil, 29, 3, 33, 62, nil, nil, 29, nil, 27, nil, nil, nil, 34, 34, 26, 41, 54, 76, 63, - nil, 81, nil, 88, 170, 172, 16, 27, 93, 94, - 100, 101, 187, 191, nil, 38, nil, nil, 172, 151, - nil, nil, -5, nil, nil, nil, 177, nil, 178, 179, - 180, nil, nil, nil, nil, nil, 192, 43, 69, nil, - 195, 194, 143, 144, nil, nil, nil, nil, 195, 108, - 114, nil, nil, 196, 197, 198, 173, nil, nil, nil, - nil, nil, 172, 204, nil, nil, nil, nil, nil, 208, - nil, 209, 210, 211, 212, 213, 120, nil, 126, 209, - nil, 149, nil, 150, 132, nil, 138, 212, 207, 217, - 181, 176, 220, nil, 221, nil, nil, nil, nil, nil, - 177, nil, nil, 155, 178, 149, nil, nil, nil, -18, - -2, nil, nil, nil, 204, nil, 205, 206, 207, 208, - 209, 194, 226, 193, nil, 199, 135, nil, 156, 214, - nil, 215, nil, nil, 107, 113, 119, 197, nil, 3, - 161, nil, 229, nil, nil, nil, 236, nil, nil, nil, - 125, nil, nil, nil, 131, 137, 201, 4, nil, 150, - nil, nil, nil, nil, nil, 201, 197, -16, nil, 162, - 234, 167, 223, 9, nil, nil, 168, 242, nil, nil, - nil, 201, 153, nil, nil, nil, 226, 203, nil ] + nil, 81, nil, 88, 171, 180, 16, 27, 93, 94, + 100, 101, 195, 199, nil, 38, nil, nil, 180, 159, + nil, nil, -5, nil, nil, nil, 185, nil, 186, 187, + 188, nil, nil, nil, nil, nil, 200, 43, 69, nil, + 203, 202, 143, 144, nil, nil, nil, nil, 203, 108, + 114, nil, nil, 204, 205, 206, 181, nil, nil, nil, + nil, nil, 180, 212, nil, nil, nil, nil, nil, 216, + nil, 217, 218, 219, 220, 221, 120, nil, 126, 217, + nil, 149, nil, 150, 132, nil, 138, 220, 215, 225, + 189, 184, 228, nil, 229, nil, nil, nil, nil, nil, + 174, nil, nil, 155, 182, 151, nil, nil, nil, -18, + -2, nil, nil, nil, 212, nil, 213, 214, 215, 216, + 217, 202, 234, 201, nil, 207, 140, nil, 156, 222, + nil, 223, nil, nil, 107, 113, 119, 205, nil, 3, + 161, nil, 237, nil, nil, nil, 244, nil, nil, nil, + 125, nil, nil, nil, 131, 137, 209, 4, nil, 214, + 154, 151, nil, nil, nil, nil, 210, 206, -16, nil, + 162, 167, 243, 168, nil, 232, 9, nil, nil, 173, + 251, nil, 160, nil, nil, 210, 161, nil, nil, nil, + nil, 235, 212, nil ] racc_action_default = [ - -2, -128, -8, -128, -128, -3, -4, -128, 209, -128, - -9, -10, -11, -128, -128, -128, -128, -128, -128, -128, - -23, -128, -27, -128, -128, -128, -128, -128, -128, -128, - -128, -128, -128, -128, -7, -113, -88, -90, -128, -110, - -112, -12, -117, -86, -87, -116, -14, -77, -15, -16, - -128, -20, -24, -28, -31, -34, -37, -43, -128, -46, - -63, -38, -67, -128, -70, -72, -73, -125, -39, -80, - -128, -83, -85, -40, -41, -42, -128, -5, -1, -89, - -114, -91, -128, -128, -13, -118, -119, -120, -74, -128, - -17, -128, -128, -128, -128, -128, -128, -47, -44, -65, - -64, -128, -71, -68, -128, -84, -81, -128, -128, -128, - -96, -128, -128, -78, -128, -21, -25, -29, -32, -35, - -45, -48, -66, -69, -82, -128, -50, -6, -115, -92, - -93, -97, -111, -75, -128, -18, -128, -128, -128, -128, - -128, -128, -128, -96, -95, -86, -110, -101, -128, -128, - -79, -128, -22, -26, -128, -128, -128, -54, -51, -94, - -128, -98, -126, -105, -106, -107, -128, -104, -76, -19, - -30, -121, -123, -124, -33, -36, -49, -52, -55, -128, - -108, -99, -127, -102, -122, -54, -110, -86, -59, -128, - -126, -128, -128, -53, -56, -57, -128, -128, -62, -100, - -109, -110, -128, -60, -103, -58, -128, -110, -61 ] + -2, -130, -8, -130, -130, -3, -4, -130, 214, -130, + -9, -10, -11, -130, -130, -130, -130, -130, -130, -130, + -23, -130, -27, -130, -130, -130, -130, -130, -130, -130, + -130, -130, -130, -130, -7, -115, -88, -90, -130, -112, + -114, -12, -119, -86, -87, -118, -14, -77, -15, -16, + -130, -20, -24, -28, -31, -34, -37, -43, -130, -46, + -63, -38, -67, -130, -70, -72, -73, -127, -39, -80, + -130, -83, -85, -40, -41, -42, -130, -5, -1, -89, + -116, -91, -130, -130, -13, -120, -121, -122, -74, -130, + -17, -130, -130, -130, -130, -130, -130, -47, -44, -65, + -64, -130, -71, -68, -130, -84, -81, -130, -130, -130, + -96, -130, -130, -78, -130, -21, -25, -29, -32, -35, + -45, -48, -66, -69, -82, -130, -50, -6, -117, -92, + -93, -97, -113, -75, -130, -18, -130, -130, -130, -130, + -130, -130, -130, -96, -95, -86, -112, -101, -130, -130, + -79, -130, -22, -26, -130, -130, -130, -54, -51, -94, + -130, -98, -128, -105, -106, -107, -130, -104, -76, -19, + -30, -123, -125, -126, -33, -36, -49, -52, -55, -86, + -130, -108, -99, -129, -102, -124, -54, -112, -86, -59, + -130, -130, -128, -130, -110, -130, -53, -56, -57, -130, + -130, -62, -130, -100, -109, -112, -130, -60, -111, -103, + -58, -130, -112, -61 ] racc_goto_table = [ - 64, 45, 57, 62, 105, 82, 97, 162, 106, 177, - 179, 1, 181, 60, 2, 72, 72, 72, 72, 130, - 184, 4, 35, 36, 184, 184, 68, 73, 74, 75, - 46, 48, 49, 78, 98, 102, 64, 193, 5, 103, - 199, 105, 124, 33, 60, 60, 202, 97, 195, 79, - 108, 10, 159, 170, 174, 175, 72, 72, 11, 105, - 12, 42, 84, 114, 151, 91, 136, 92, 137, 97, - 93, 138, 120, 94, 64, 139, 102, 123, 95, 140, - 56, 61, 99, 60, 121, 60, 125, 176, 197, 206, - 112, 72, 149, 72, 89, 134, 102, 129, 166, 192, - 109, nil, nil, 146, nil, nil, nil, 60, nil, nil, - nil, 72, 161, nil, nil, nil, nil, nil, nil, nil, - nil, 167, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, 146, 180, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - 186, nil, 194, nil, nil, nil, nil, nil, nil, nil, - nil, nil, 198, nil, 200, nil, 186, 204, nil, 180, - nil, nil, nil, 208 ] + 82, 62, 57, 45, 97, 64, 105, 162, 182, 36, + 177, 1, 2, 180, 106, 60, 4, 72, 72, 72, + 72, 130, 185, 46, 48, 49, 185, 185, 68, 73, + 74, 75, 35, 78, 98, 79, 5, 103, 203, 196, + 102, 64, 194, 105, 202, 97, 60, 60, 124, 198, + 33, 108, 206, 10, 159, 170, 174, 175, 72, 72, + 11, 105, 12, 42, 84, 114, 151, 97, 91, 136, + 92, 137, 120, 93, 138, 123, 94, 139, 95, 64, + 140, 102, 56, 61, 99, 60, 121, 60, 125, 176, + 200, 211, 112, 72, 149, 72, 89, 134, 129, 166, + 195, 102, 109, nil, nil, nil, nil, 161, 146, 60, + nil, nil, nil, 72, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, 167, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, 146, 181, nil, + nil, nil, nil, nil, nil, nil, nil, nil, 197, nil, + nil, nil, nil, nil, nil, 187, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, 209, nil, 201, 181, + nil, 204, nil, 213, 187, nil, nil, 181 ] racc_goto_check = [ - 40, 34, 32, 46, 53, 41, 33, 42, 52, 39, - 43, 1, 59, 34, 2, 34, 34, 34, 34, 58, - 63, 3, 4, 54, 63, 63, 31, 31, 31, 31, - 14, 14, 14, 5, 32, 40, 40, 39, 6, 46, - 59, 53, 52, 7, 34, 34, 43, 33, 42, 54, - 8, 9, 58, 20, 20, 20, 34, 34, 10, 53, - 11, 12, 13, 15, 16, 17, 18, 21, 22, 33, - 23, 24, 32, 25, 40, 26, 40, 46, 27, 28, - 29, 30, 35, 34, 36, 34, 37, 38, 44, 45, - 48, 34, 49, 34, 50, 51, 40, 57, 60, 61, - 62, nil, nil, 40, nil, nil, nil, 34, nil, nil, - nil, 34, 41, nil, nil, nil, nil, nil, nil, nil, - nil, 40, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, 40, 40, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - 40, nil, 41, nil, nil, nil, nil, nil, nil, nil, - nil, nil, 40, nil, 40, nil, 40, 41, nil, 40, - nil, nil, nil, 41 ] + 41, 46, 32, 34, 33, 40, 53, 42, 59, 54, + 39, 1, 2, 43, 52, 34, 3, 34, 34, 34, + 34, 58, 63, 14, 14, 14, 63, 63, 31, 31, + 31, 31, 4, 5, 32, 54, 6, 46, 59, 39, + 40, 40, 42, 53, 43, 33, 34, 34, 52, 42, + 7, 8, 43, 9, 58, 20, 20, 20, 34, 34, + 10, 53, 11, 12, 13, 15, 16, 33, 17, 18, + 21, 22, 32, 23, 24, 46, 25, 26, 27, 40, + 28, 40, 29, 30, 35, 34, 36, 34, 37, 38, + 44, 45, 48, 34, 49, 34, 50, 51, 57, 60, + 61, 40, 62, nil, nil, nil, nil, 41, 40, 34, + nil, nil, nil, 34, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, 40, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, 40, 40, nil, + nil, nil, nil, nil, nil, nil, nil, nil, 41, nil, + nil, nil, nil, nil, nil, 40, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, 41, nil, 40, 40, + nil, 40, nil, 41, 40, nil, nil, 40 ] racc_goto_pointer = [ - nil, 11, 14, 19, 13, -2, 36, 37, -27, 47, - 54, 56, 47, 20, 15, -27, -71, 14, -49, nil, - -101, 15, -48, 17, -46, 19, -43, 23, -40, 54, - 54, -2, -24, -51, -13, 22, -15, -21, -70, -148, - -27, -34, -139, -150, -100, -114, -24, nil, 2, -41, - 47, -18, -62, -65, 14, nil, nil, -13, -91, -150, - -49, -84, 20, -150 ] + nil, 11, 12, 14, 23, -2, 34, 44, -26, 49, + 56, 58, 49, 22, 8, -25, -69, 17, -46, nil, + -99, 18, -45, 20, -43, 22, -41, 23, -39, 56, + 56, 0, -24, -53, -11, 24, -13, -19, -68, -147, + -22, -39, -139, -147, -99, -116, -26, nil, 4, -39, + 49, -16, -56, -63, 0, nil, nil, -12, -89, -154, + -48, -84, 22, -148 ] racc_goto_default = [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, @@ -1002,28 +1006,30 @@ def raise_parse_error(error_message, location) 1, 89, :_reduce_none, 1, 90, :_reduce_108, 3, 90, :_reduce_109, + 2, 90, :_reduce_110, + 4, 90, :_reduce_111, 0, 88, :_reduce_none, - 3, 88, :_reduce_111, + 3, 88, :_reduce_113, 1, 103, :_reduce_none, 0, 52, :_reduce_none, - 0, 109, :_reduce_114, - 3, 52, :_reduce_115, + 0, 109, :_reduce_116, + 3, 52, :_reduce_117, 1, 59, :_reduce_none, 0, 60, :_reduce_none, 1, 60, :_reduce_none, 1, 60, :_reduce_none, 1, 60, :_reduce_none, - 1, 67, :_reduce_121, - 2, 67, :_reduce_122, + 1, 67, :_reduce_123, + 2, 67, :_reduce_124, 1, 110, :_reduce_none, 1, 110, :_reduce_none, - 1, 94, :_reduce_125, + 1, 94, :_reduce_127, 0, 106, :_reduce_none, 1, 106, :_reduce_none ] -racc_reduce_n = 128 +racc_reduce_n = 130 -racc_shift_n = 209 +racc_shift_n = 214 racc_token_table = { false => 0, @@ -1568,8 +1574,8 @@ def _reduce_48(val, _values, result) module_eval(<<'.,.,', 'parser.y', 207) def _reduce_49(val, _values, result) - builder = Grammar::ParameterizingRuleBuilder.new(val[1].s_value, val[3], val[6]) - @grammar.add_parameterizing_rule_builder(builder) + rule = Grammar::ParameterizingRule::Rule.new(val[1].s_value, val[3], val[6]) + @grammar.add_parameterizing_rule(rule) result end @@ -1610,7 +1616,7 @@ def _reduce_53(val, _values, result) module_eval(<<'.,.,', 'parser.y', 227) def _reduce_54(val, _values, result) reset_precs - result = Grammar::ParameterizingRuleRhsBuilder.new + result = Grammar::ParameterizingRule::Rhs.new result end @@ -1619,7 +1625,7 @@ def _reduce_54(val, _values, result) module_eval(<<'.,.,', 'parser.y', 232) def _reduce_55(val, _values, result) reset_precs - result = Grammar::ParameterizingRuleRhsBuilder.new + result = Grammar::ParameterizingRule::Rhs.new result end @@ -1933,10 +1939,9 @@ def _reduce_98(val, _values, result) module_eval(<<'.,.,', 'parser.y', 410) def _reduce_99(val, _values, result) - token = Lrama::Lexer::Token::InstantiateRule.new(s_value: val[2], location: @lexer.location, args: [val[1]]) + token = Lrama::Lexer::Token::InstantiateRule.new(s_value: val[2], location: @lexer.location, args: [val[1]], lhs_tag: val[3]) builder = val[0] builder.add_rhs(token) - builder.lhs_tag = val[3] builder.line = val[1].first_line result = builder @@ -1944,12 +1949,11 @@ def _reduce_99(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 419) +module_eval(<<'.,.,', 'parser.y', 418) def _reduce_100(val, _values, result) - token = Lrama::Lexer::Token::InstantiateRule.new(s_value: val[1].s_value, location: @lexer.location, args: val[3]) + token = Lrama::Lexer::Token::InstantiateRule.new(s_value: val[1].s_value, location: @lexer.location, args: val[3], lhs_tag: val[5]) builder = val[0] builder.add_rhs(token) - builder.lhs_tag = val[5] builder.line = val[1].first_line result = builder @@ -1957,7 +1961,7 @@ def _reduce_100(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 428) +module_eval(<<'.,.,', 'parser.y', 426) def _reduce_101(val, _values, result) if @prec_seen on_action_error("multiple User_code after %prec", val[0]) if @code_after_prec @@ -1969,7 +1973,7 @@ def _reduce_101(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 436) +module_eval(<<'.,.,', 'parser.y', 434) def _reduce_102(val, _values, result) end_c_declaration @@ -1977,7 +1981,7 @@ def _reduce_102(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 440) +module_eval(<<'.,.,', 'parser.y', 438) def _reduce_103(val, _values, result) user_code = val[3] user_code.alias_name = val[6] @@ -1989,7 +1993,7 @@ def _reduce_103(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 448) +module_eval(<<'.,.,', 'parser.y', 446) def _reduce_104(val, _values, result) sym = @grammar.find_symbol_by_id!(val[2]) @prec_seen = true @@ -2007,35 +2011,49 @@ def _reduce_104(val, _values, result) # reduce 107 omitted -module_eval(<<'.,.,', 'parser.y', 459) +module_eval(<<'.,.,', 'parser.y', 457) def _reduce_108(val, _values, result) result = [val[0]] result end .,., -module_eval(<<'.,.,', 'parser.y', 460) +module_eval(<<'.,.,', 'parser.y', 458) def _reduce_109(val, _values, result) result = val[0].append(val[2]) result end .,., -# reduce 110 omitted +module_eval(<<'.,.,', 'parser.y', 459) + def _reduce_110(val, _values, result) + result = [Lrama::Lexer::Token::InstantiateRule.new(s_value: val[1].s_value, location: @lexer.location, args: val[0])] + result + end +.,., -module_eval(<<'.,.,', 'parser.y', 463) +module_eval(<<'.,.,', 'parser.y', 460) def _reduce_111(val, _values, result) - result = val[1].s_value + result = [Lrama::Lexer::Token::InstantiateRule.new(s_value: val[0].s_value, location: @lexer.location, args: val[2])] result end .,., # reduce 112 omitted -# reduce 113 omitted +module_eval(<<'.,.,', 'parser.y', 463) + def _reduce_113(val, _values, result) + result = val[1].s_value + result + end +.,., + +# reduce 114 omitted + +# reduce 115 omitted module_eval(<<'.,.,', 'parser.y', 470) - def _reduce_114(val, _values, result) + def _reduce_116(val, _values, result) begin_c_declaration('\Z') @grammar.epilogue_first_lineno = @lexer.line + 1 @@ -2044,7 +2062,7 @@ def _reduce_114(val, _values, result) .,., module_eval(<<'.,.,', 'parser.y', 475) - def _reduce_115(val, _values, result) + def _reduce_117(val, _values, result) end_c_declaration @grammar.epilogue = val[2].s_value @@ -2052,44 +2070,44 @@ def _reduce_115(val, _values, result) end .,., -# reduce 116 omitted - -# reduce 117 omitted - # reduce 118 omitted # reduce 119 omitted # reduce 120 omitted +# reduce 121 omitted + +# reduce 122 omitted + module_eval(<<'.,.,', 'parser.y', 486) - def _reduce_121(val, _values, result) + def _reduce_123(val, _values, result) result = [val[0]] result end .,., module_eval(<<'.,.,', 'parser.y', 487) - def _reduce_122(val, _values, result) + def _reduce_124(val, _values, result) result = val[0].append(val[1]) result end .,., -# reduce 123 omitted +# reduce 125 omitted -# reduce 124 omitted +# reduce 126 omitted module_eval(<<'.,.,', 'parser.y', 492) - def _reduce_125(val, _values, result) + def _reduce_127(val, _values, result) result = Lrama::Lexer::Token::Ident.new(s_value: val[0]) result end .,., -# reduce 126 omitted +# reduce 128 omitted -# reduce 127 omitted +# reduce 129 omitted def _reduce_none(val, _values, result) val[0] diff --git a/tool/lrama/lib/lrama/version.rb b/tool/lrama/lib/lrama/version.rb index 8ec2c458a11a70..406939918ce543 100644 --- a/tool/lrama/lib/lrama/version.rb +++ b/tool/lrama/lib/lrama/version.rb @@ -1,3 +1,3 @@ module Lrama - VERSION = "0.6.0".freeze + VERSION = "0.6.1".freeze end From ccd45a1399a9eed7c59120874d0d37bd3ce9d73d Mon Sep 17 00:00:00 2001 From: yui-knk Date: Sat, 13 Jan 2024 13:54:13 +0900 Subject: [PATCH 128/640] Stop using Array to manage dummy `end` token locations Before this commit, Array is used to store token locations which expect `end` token, e.g. `class` and `module`. This commit introduces dedicated struct to manage them so that dependency on Ruby Object is reduced. --- parse.y | 63 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/parse.y b/parse.y index 568a8c27e7f374..339efb329725f5 100644 --- a/parse.y +++ b/parse.y @@ -527,6 +527,11 @@ typedef struct token_info { struct token_info *next; } token_info; +typedef struct end_expect_token_locations { + const rb_code_position_t *pos; + struct end_expect_token_locations *prev; +} end_expect_token_locations_t; + /* Structure of Lexer Buffer: @@ -639,8 +644,11 @@ struct parser_params { VALUE error_buffer; VALUE debug_lines; const struct rb_iseq_struct *parent_iseq; - /* store specific keyword locations to generate dummy end token */ - VALUE end_expect_token_locations; + /* + * Store specific keyword locations to generate dummy end token. + * Refer to the tail of list element. + */ + end_expect_token_locations_t *end_expect_token_locations; /* id for terms */ int token_id; /* Array for term tokens */ @@ -703,8 +711,15 @@ static void debug_end_expect_token_locations(struct parser_params *p, const char *name) { if(p->debug) { - VALUE mesg = rb_sprintf("%s: ", name); - rb_str_catf(mesg, " %"PRIsVALUE"\n", p->end_expect_token_locations); + VALUE mesg = rb_sprintf("%s: [", name); + int i = 0; + for (end_expect_token_locations_t *loc = p->end_expect_token_locations; loc; loc = loc->prev) { + if (i > 0) + rb_str_cat_cstr(mesg, ", "); + rb_str_catf(mesg, "[%d, %d]", loc->pos->lineno, loc->pos->column); + i++; + } + rb_str_cat_cstr(mesg, "]\n"); flush_debug_buffer(p, p->debug_output, mesg); } } @@ -712,24 +727,33 @@ debug_end_expect_token_locations(struct parser_params *p, const char *name) static void push_end_expect_token_locations(struct parser_params *p, const rb_code_position_t *pos) { - if(NIL_P(p->end_expect_token_locations)) return; - rb_ary_push(p->end_expect_token_locations, rb_ary_new_from_args(2, INT2NUM(pos->lineno), INT2NUM(pos->column))); + if(!p->error_tolerant) return; + + end_expect_token_locations_t *locations; + locations = ALLOC(end_expect_token_locations_t); + locations->pos = pos; + locations->prev = p->end_expect_token_locations; + p->end_expect_token_locations = locations; + debug_end_expect_token_locations(p, "push_end_expect_token_locations"); } static void pop_end_expect_token_locations(struct parser_params *p) { - if(NIL_P(p->end_expect_token_locations)) return; - rb_ary_pop(p->end_expect_token_locations); + if(!p->end_expect_token_locations) return; + + end_expect_token_locations_t *locations = p->end_expect_token_locations->prev; + ruby_sized_xfree(p->end_expect_token_locations, sizeof(end_expect_token_locations_t)); + p->end_expect_token_locations = locations; + debug_end_expect_token_locations(p, "pop_end_expect_token_locations"); } -static VALUE +static end_expect_token_locations_t * peek_end_expect_token_locations(struct parser_params *p) { - if(NIL_P(p->end_expect_token_locations)) return Qnil; - return rb_ary_last(0, 0, p->end_expect_token_locations); + return p->end_expect_token_locations; } static ID @@ -10560,14 +10584,14 @@ parse_ident(struct parser_params *p, int c, int cmd_state) } #ifndef RIPPER - if (!NIL_P(peek_end_expect_token_locations(p))) { - VALUE end_loc; + if (peek_end_expect_token_locations(p)) { + const rb_code_position_t *end_pos; int lineno, column; int beg_pos = (int)(p->lex.ptok - p->lex.pbeg); - end_loc = peek_end_expect_token_locations(p); - lineno = NUM2INT(rb_ary_entry(end_loc, 0)); - column = NUM2INT(rb_ary_entry(end_loc, 1)); + end_pos = peek_end_expect_token_locations(p)->pos; + lineno = end_pos->lineno; + column = end_pos->column; if (p->debug) { rb_parser_printf(p, "enforce_keyword_end check. current: (%d, %d), peek: (%d, %d)\n", @@ -10692,7 +10716,7 @@ parser_yylex(struct parser_params *p) case -1: /* end of script. */ p->eofp = 1; #ifndef RIPPER - if (!NIL_P(p->end_expect_token_locations) && RARRAY_LEN(p->end_expect_token_locations) > 0) { + if (p->end_expect_token_locations) { pop_end_expect_token_locations(p); RUBY_SET_YYLLOC_OF_DUMMY_END(*p->yylloc); return tDUMNY_END; @@ -15856,7 +15880,7 @@ parser_initialize(struct parser_params *p) p->parsing_thread = Qnil; #else p->error_buffer = Qfalse; - p->end_expect_token_locations = Qnil; + p->end_expect_token_locations = NULL; p->token_id = 0; p->tokens = Qnil; #endif @@ -15887,7 +15911,6 @@ rb_ruby_parser_mark(void *ptr) #ifndef RIPPER rb_gc_mark(p->debug_lines); rb_gc_mark(p->error_buffer); - rb_gc_mark(p->end_expect_token_locations); rb_gc_mark(p->tokens); #else rb_gc_mark(p->value); @@ -16012,8 +16035,6 @@ void rb_ruby_parser_error_tolerant(rb_parser_t *p) { p->error_tolerant = 1; - // TODO - p->end_expect_token_locations = rb_ary_new(); } void From 9ba2558b76e5b0d871132c38a85055c4746c34de Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sat, 13 Jan 2024 20:33:33 +0900 Subject: [PATCH 129/640] Fix possible out-of-bounds access --- ruby.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruby.c b/ruby.c index a5794199ec513d..16db56bd62215d 100644 --- a/ruby.c +++ b/ruby.c @@ -2487,7 +2487,7 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) static void warn_cr_in_shebang(const char *str, long len) { - if (str[len-1] == '\n' && str[len-2] == '\r') { + if (len > 1 && str[len-1] == '\n' && str[len-2] == '\r') { rb_warn("shebang line ending with \\r may cause problems"); } } From 55335eab80d763fb11d621c041d23aaf8f4857c6 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sat, 13 Jan 2024 23:41:20 +0900 Subject: [PATCH 130/640] Use STATIC_ASSERT --- random.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/random.c b/random.c index 5cd2d917a4d584..ab33600792fdbe 100644 --- a/random.c +++ b/random.c @@ -73,7 +73,7 @@ #include "ruby/random.h" #include "ruby/ractor.h" -typedef int int_must_be_32bit_at_least[sizeof(int) * CHAR_BIT < 32 ? -1 : 1]; +STATIC_ASSERT(int_must_be_32bit_at_least, sizeof(int) * CHAR_BIT >= 32); #include "missing/mt19937.c" From 4e5754a459ea10c73381b3009bb889e83077575c Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 14 Jan 2024 00:24:14 +0900 Subject: [PATCH 131/640] Add test for `Errno` constants --- test/ruby/test_exception.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/ruby/test_exception.rb b/test/ruby/test_exception.rb index b3951c7e513817..84c750bf329e8a 100644 --- a/test/ruby/test_exception.rb +++ b/test/ruby/test_exception.rb @@ -540,6 +540,14 @@ def test_errno assert_equal(Encoding.find("locale"), Errno::EINVAL.new.message.encoding) end + def test_errno_constants + assert_equal [:NOERROR], Errno.constants.grep_v(/\AE/) + all_assertions_foreach("should be a subclass of SystemCallError", *Errno.constants) do |c| + e = Errno.const_get(c) + assert_operator e, :<, SystemCallError, proc {e.ancestors.inspect} + end + end + def test_too_many_args_in_eval bug5720 = '[ruby-core:41520]' arg_string = (0...140000).to_a.join(", ") From 0610f555ea4f3ba571482f90393fe8c0701cd58a Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 14 Jan 2024 17:55:11 +0900 Subject: [PATCH 132/640] Constify `rb_global_parser_config` --- node.c | 4 ++-- node.h | 4 ++-- parse.y | 6 +++--- ruby_parser.c | 2 +- rubyparser.h | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/node.c b/node.c index 79ef00f1b76944..9844401331977d 100644 --- a/node.c +++ b/node.c @@ -53,7 +53,7 @@ init_node_buffer_list(node_buffer_list_t * nb, node_buffer_elem_t *head, void *x #ifdef UNIVERSAL_PARSER static node_buffer_t * -rb_node_buffer_new(rb_parser_config_t *config) +rb_node_buffer_new(const rb_parser_config_t *config) #else static node_buffer_t * rb_node_buffer_new(void) @@ -318,7 +318,7 @@ rb_ast_delete_node(rb_ast_t *ast, NODE *n) #ifdef UNIVERSAL_PARSER rb_ast_t * -rb_ast_new(rb_parser_config_t *config) +rb_ast_new(const rb_parser_config_t *config) { node_buffer_t *nb = rb_node_buffer_new(config); return config->ast_new((VALUE)nb); diff --git a/node.h b/node.h index d8d104975a19de..009d39b8566817 100644 --- a/node.h +++ b/node.h @@ -43,14 +43,14 @@ struct node_buffer_struct { // Array, whose entry is array VALUE tokens; #ifdef UNIVERSAL_PARSER - rb_parser_config_t *config; + const rb_parser_config_t *config; #endif }; RUBY_SYMBOL_EXPORT_BEGIN #ifdef UNIVERSAL_PARSER -rb_ast_t *rb_ast_new(rb_parser_config_t *config); +rb_ast_t *rb_ast_new(const rb_parser_config_t *config); #else rb_ast_t *rb_ast_new(void); #endif diff --git a/parse.y b/parse.y index 339efb329725f5..7cb92b88e3385b 100644 --- a/parse.y +++ b/parse.y @@ -611,7 +611,7 @@ struct parser_params { struct lex_context ctxt; #ifdef UNIVERSAL_PARSER - rb_parser_config_t *config; + const rb_parser_config_t *config; #endif /* compile_option */ signed int frozen_string_literal:2; /* -1: not specified, 0: false, 1: true */ @@ -15989,7 +15989,7 @@ rb_reserved_word(const char *str, unsigned int len) #ifdef UNIVERSAL_PARSER rb_parser_t * -rb_ruby_parser_allocate(rb_parser_config_t *config) +rb_ruby_parser_allocate(const rb_parser_config_t *config) { /* parser_initialize expects fields to be set to 0 */ rb_parser_t *p = (rb_parser_t *)config->calloc(1, sizeof(rb_parser_t)); @@ -15998,7 +15998,7 @@ rb_ruby_parser_allocate(rb_parser_config_t *config) } rb_parser_t * -rb_ruby_parser_new(rb_parser_config_t *config) +rb_ruby_parser_new(const rb_parser_config_t *config) { /* parser_initialize expects fields to be set to 0 */ rb_parser_t *p = rb_ruby_parser_allocate(config); diff --git a/ruby_parser.c b/ruby_parser.c index a76a8231f5c780..d932b0f7bef9ba 100644 --- a/ruby_parser.c +++ b/ruby_parser.c @@ -484,7 +484,7 @@ extern VALUE rb_eArgError; extern VALUE rb_mRubyVMFrozenCore; VALUE rb_node_case_when_optimizable_literal(const NODE *const node); -rb_parser_config_t rb_global_parser_config = (rb_parser_config_t) { +static const rb_parser_config_t rb_global_parser_config = { .malloc = ruby_xmalloc, .calloc = ruby_xcalloc, .realloc = ruby_xrealloc, diff --git a/rubyparser.h b/rubyparser.h index 974a03992ca57e..2bd93bf0b2a6a6 100644 --- a/rubyparser.h +++ b/rubyparser.h @@ -1439,8 +1439,8 @@ void rb_ruby_parser_free(void *ptr); rb_ast_t* rb_ruby_parser_compile_string(rb_parser_t *p, const char *f, VALUE s, int line); #ifdef UNIVERSAL_PARSER -rb_parser_t *rb_ruby_parser_allocate(rb_parser_config_t *config); -rb_parser_t *rb_ruby_parser_new(rb_parser_config_t *config); +rb_parser_t *rb_ruby_parser_allocate(const rb_parser_config_t *config); +rb_parser_t *rb_ruby_parser_new(const rb_parser_config_t *config); #endif long rb_parser_string_length(rb_parser_string_t *str); From 338eb0065bd81ba8ae8b9402abc94804a24594cc Mon Sep 17 00:00:00 2001 From: NAITOH Jun Date: Sat, 13 Jan 2024 06:22:32 +0900 Subject: [PATCH 133/640] [ruby/strscan] StringScanner#captures: Return nil not "" for unmached capture (https://github.com/ruby/strscan/pull/72) fix https://github.com/ruby/strscan/issues/70 If there is no substring matching the group (s[3]), the behavior is different. If there is no substring matching the group, the corresponding element (s[3]) should be nil. ``` s = StringScanner.new('foobarbaz') #=> # s.scan /(foo)(bar)(BAZ)?/ #=> "foobar" s[0] #=> "foobar" s[1] #=> "foo" s[2] #=> "bar" s[3] #=> nil s.captures #=> ["foo", "bar", ""] s.captures.compact #=> ["foo", "bar", ""] ``` ``` s = StringScanner.new('foobarbaz') #=> # s.scan /(foo)(bar)(BAZ)?/ #=> "foobar" s[0] #=> "foobar" s[1] #=> "foo" s[2] #=> "bar" s[3] #=> nil s.captures #=> ["foo", "bar", nil] s.captures.compact #=> ["foo", "bar"] ``` https://docs.ruby-lang.org/ja/latest/method/MatchData/i/captures.html ``` /(foo)(bar)(BAZ)?/ =~ "foobarbaz" #=> 0 $~.to_a #=> ["foobar", "foo", "bar", nil] $~.captures #=> ["foo", "bar", nil] $~.captures.compact #=> ["foo", "bar"] ``` * StringScanner#captures is not yet documented. https://docs.ruby-lang.org/ja/latest/class/StringScanner.html https://github.com/ruby/strscan/commit/1fbfdd3c6f --- ext/strscan/strscan.c | 18 +++++++++++------- test/strscan/test_stringscanner.rb | 4 ++-- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/ext/strscan/strscan.c b/ext/strscan/strscan.c index a2bf56ce4fe111..7dbd971ae98d33 100644 --- a/ext/strscan/strscan.c +++ b/ext/strscan/strscan.c @@ -1243,10 +1243,10 @@ strscan_size(VALUE self) * If nothing was priorly matched, it returns nil. * * s = StringScanner.new("Fri Dec 12 1975 14:39") - * s.scan(/(\w+) (\w+) (\d+) /) # -> "Fri Dec 12 " - * s.captures # -> ["Fri", "Dec", "12"] - * s.scan(/(\w+) (\w+) (\d+) /) # -> nil - * s.captures # -> nil + * s.scan(/(\w+) (\w+) (\d+) (1980)?/) # -> "Fri Dec 12 " + * s.captures # -> ["Fri", "Dec", "12", nil] + * s.scan(/(\w+) (\w+) (\d+) (1980)?/) # -> nil + * s.captures # -> nil */ static VALUE strscan_captures(VALUE self) @@ -1262,9 +1262,13 @@ strscan_captures(VALUE self) new_ary = rb_ary_new2(num_regs); for (i = 1; i < num_regs; i++) { - VALUE str = extract_range(p, - adjust_register_position(p, p->regs.beg[i]), - adjust_register_position(p, p->regs.end[i])); + VALUE str; + if (p->regs.beg[i] == -1) + str = Qnil; + else + str = extract_range(p, + adjust_register_position(p, p->regs.beg[i]), + adjust_register_position(p, p->regs.end[i])); rb_ary_push(new_ary, str); } diff --git a/test/strscan/test_stringscanner.rb b/test/strscan/test_stringscanner.rb index 2fce4c3e748cf9..29626b159f7032 100644 --- a/test/strscan/test_stringscanner.rb +++ b/test/strscan/test_stringscanner.rb @@ -737,8 +737,8 @@ def test_size def test_captures s = create_string_scanner("Timestamp: Fri Dec 12 1975 14:39") s.scan("Timestamp: ") - s.scan(/(\w+) (\w+) (\d+) /) - assert_equal(["Fri", "Dec", "12"], s.captures) + s.scan(/(\w+) (\w+) (\d+) (1980)?/) + assert_equal(["Fri", "Dec", "12", nil], s.captures) s.scan(/(\w+) (\w+) (\d+) /) assert_nil(s.captures) end From 772413245f782f538413a69a270ec75ee8b77f18 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 14 Jan 2024 17:53:22 +0900 Subject: [PATCH 134/640] Skip checking for symbol leaks in libruby.a linking extensions The libruby.a linking extension libraries contain symbols exported from extension libraries, and is not subject of test-leaked-globals. --- template/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/Makefile.in b/template/Makefile.in index 5b6cd87b06ab3b..61f420d96639dd 100644 --- a/template/Makefile.in +++ b/template/Makefile.in @@ -643,7 +643,7 @@ un-runnable: $(ECHO) cannot make runnable, configure with --enable-load-relative. $(Q) exit 1 -LIBRUBY_FOR_LEAKED_GLOBALS = $(enable_shared:no=) +LIBRUBY_FOR_LEAKED_GLOBALS = $(enable_shared:no=$(EXTSTATIC:static=)) yes-test-basic: $(DOT_WAIT) test-leaked-globals leaked-globals: test-leaked-globals yes-test-leaked-globals-precheck: $(COMMONOBJS) prog $(tooldir)/leaked-globals From 5c823aa686a5549649df4af86d173bebed2418e1 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Sun, 14 Jan 2024 11:41:02 -0800 Subject: [PATCH 135/640] Support keyword splatting nil nil is treated similarly to the empty hash in this case, passing no keywords and not calling any conversion methods. Fixes [Bug #20064] Co-authored-by: Nobuyoshi Nakada --- NEWS.md | 6 ++++++ compile.c | 1 + test/ruby/test_backtrace.rb | 2 +- test/ruby/test_keyword.rb | 38 +++++++++++++++++++++++++++++++++++++ vm.c | 4 +++- vm_args.c | 4 ++++ vm_insnhelper.c | 12 +++++++----- 7 files changed, 60 insertions(+), 7 deletions(-) diff --git a/NEWS.md b/NEWS.md index 6e2dcc6d247add..be0c14797e316e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -9,6 +9,11 @@ Note that each entry is kept to a minimum, see links for details. * `it` is added to reference a block parameter. [[Feature #18980]] +* Keyword splatting `nil` when calling methods is now supported. + `**nil` is treated similar to `**{}`, passing no keywords, + and not calling any conversion methods. + [[Bug #20064]] + ## Core classes updates Note: We're only listing outstanding class updates. @@ -57,3 +62,4 @@ See GitHub releases like [GitHub Releases of Logger](https://github.com/ruby/log ## JIT [Feature #18980]: https://bugs.ruby-lang.org/issues/18980 +[Bug #20064]: https://bugs.ruby-lang.org/issues/20064 diff --git a/compile.c b/compile.c index 6e0456af354577..2d7e81d54e8fac 100644 --- a/compile.c +++ b/compile.c @@ -5079,6 +5079,7 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int meth int last_kw = !RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next; /* foo( ..., **kw) */ int only_kw = last_kw && first_kw; /* foo(1,2,3, **kw) */ + empty_kw = empty_kw || nd_type_p(kw, NODE_NIL); /* foo( ..., **nil, ...) */ if (empty_kw) { if (only_kw && method_call_keywords) { /* **{} appears at the only keyword argument in method call, diff --git a/test/ruby/test_backtrace.rb b/test/ruby/test_backtrace.rb index d35dead95bbab8..844ec0e30c57ed 100644 --- a/test/ruby/test_backtrace.rb +++ b/test/ruby/test_backtrace.rb @@ -378,7 +378,7 @@ class << obj def test_core_backtrace_hash_merge e = assert_raise(TypeError) do - {**nil} + {**1} end assert_not_match(/\Acore#/, e.backtrace_locations[0].base_label) end diff --git a/test/ruby/test_keyword.rb b/test/ruby/test_keyword.rb index 9aca787dff5294..7849fe285ab9b2 100644 --- a/test/ruby/test_keyword.rb +++ b/test/ruby/test_keyword.rb @@ -182,6 +182,44 @@ def test_method_parameters [:keyrest, :kw], [:block, :b]], method(:f9).parameters) end + def test_keyword_splat_nil + # cfunc call + assert_equal(nil, p(**nil)) + + def self.a0; end + assert_equal(nil, a0(**nil)) + assert_equal(nil, :a0.to_proc.call(self, **nil)) + + def self.o(x=1); x end + assert_equal(1, o(**nil)) + assert_equal(2, o(2, **nil)) + assert_equal(1, o(*nil, **nil)) + assert_equal(1, o(**nil, **nil)) + assert_equal({a: 1}, o(a: 1, **nil)) + assert_equal({a: 1}, o(**nil, a: 1)) + + # symproc call + assert_equal(1, :o.to_proc.call(self, **nil)) + + def self.s(*a); a end + assert_equal([], s(**nil)) + assert_equal([1], s(1, **nil)) + assert_equal([], s(*nil, **nil)) + + def self.kws(**a); a end + assert_equal({}, kws(**nil)) + assert_equal({}, kws(*nil, **nil)) + + def self.skws(*a, **kw); [a, kw] end + assert_equal([[], {}], skws(**nil)) + assert_equal([[1], {}], skws(1, **nil)) + assert_equal([[], {}], skws(*nil, **nil)) + + assert_equal({}, {**nil}) + assert_equal({a: 1}, {a: 1, **nil}) + assert_equal({a: 1}, {**nil, a: 1}) + end + def test_lambda f = ->(str: "foo", num: 424242) { [str, num] } assert_equal(["foo", 424242], f[]) diff --git a/vm.c b/vm.c index 37d631116aa4dc..a2a17f8fe7578d 100644 --- a/vm.c +++ b/vm.c @@ -3666,7 +3666,9 @@ kwmerge_i(VALUE key, VALUE value, VALUE hash) static VALUE m_core_hash_merge_kwd(VALUE recv, VALUE hash, VALUE kw) { - REWIND_CFP(hash = core_hash_merge_kwd(hash, kw)); + if (!NIL_P(kw)) { + REWIND_CFP(hash = core_hash_merge_kwd(hash, kw)); + } return hash; } diff --git a/vm_args.c b/vm_args.c index eda46aa92c1660..37b765a41d1d0f 100644 --- a/vm_args.c +++ b/vm_args.c @@ -434,6 +434,10 @@ fill_keys_values(st_data_t key, st_data_t val, st_data_t ptr) static inline int ignore_keyword_hash_p(VALUE keyword_hash, const rb_iseq_t * const iseq, unsigned int * kw_flag, VALUE * converted_keyword_hash) { + if (keyword_hash == Qnil) { + return 1; + } + if (!RB_TYPE_P(keyword_hash, T_HASH)) { keyword_hash = rb_to_hash_type(keyword_hash); } diff --git a/vm_insnhelper.c b/vm_insnhelper.c index d81a121c1f7779..63567e8f8710f1 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -2668,8 +2668,10 @@ static inline VALUE vm_caller_setup_keyword_hash(const struct rb_callinfo *ci, VALUE keyword_hash) { if (UNLIKELY(!RB_TYPE_P(keyword_hash, T_HASH))) { - /* Convert a non-hash keyword splat to a new hash */ - keyword_hash = rb_hash_dup(rb_to_hash_type(keyword_hash)); + if (keyword_hash != Qnil) { + /* Convert a non-hash keyword splat to a new hash */ + keyword_hash = rb_hash_dup(rb_to_hash_type(keyword_hash)); + } } else if (!IS_ARGS_KW_SPLAT_MUT(ci)) { /* Convert a hash keyword splat to a new hash unless @@ -2699,7 +2701,7 @@ CALLER_SETUP_ARG(struct rb_control_frame_struct *restrict cfp, if (vm_caller_setup_arg_splat(cfp, calling, ary, max_args)) return; // put kw - if (!RHASH_EMPTY_P(kwh)) { + if (kwh != Qnil && !RHASH_EMPTY_P(kwh)) { if (UNLIKELY(calling->heap_argv)) { rb_ary_push(calling->heap_argv, kwh); ((struct RHash *)kwh)->basic.flags |= RHASH_PASS_AS_KEYWORDS; @@ -2770,7 +2772,7 @@ CALLER_SETUP_ARG(struct rb_control_frame_struct *restrict cfp, VM_ASSERT(calling->kw_splat == 1); VALUE kwh = vm_caller_setup_keyword_hash(ci, cfp->sp[-1]); - if (RHASH_EMPTY_P(kwh)) { + if (kwh == Qnil || RHASH_EMPTY_P(kwh)) { cfp->sp--; calling->argc--; calling->kw_splat = 0; @@ -3596,7 +3598,7 @@ vm_call_cfunc_only_splat_kw(rb_execution_context_t *ec, rb_control_frame_t *reg_ RB_DEBUG_COUNTER_INC(ccf_cfunc_only_splat_kw); VALUE keyword_hash = reg_cfp->sp[-1]; - if (RB_TYPE_P(keyword_hash, T_HASH) && RHASH_EMPTY_P(keyword_hash)) { + if (keyword_hash == Qnil || (RB_TYPE_P(keyword_hash, T_HASH) && RHASH_EMPTY_P(keyword_hash))) { return vm_call_cfunc_array_argv(ec, reg_cfp, calling, 1, 0); } From c5cf4d4e129f64cb69aaf0a829aed068ef1943c4 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Mon, 15 Jan 2024 10:47:13 +1300 Subject: [PATCH 136/640] Improve behavioural consistency of unallocated (zero length) `IO::Buffer`. (#9532) This makes the behaviour of IO::Buffer.new(0) and IO::Buffer.new.slice(0, 0) consistent. Fixes https://bugs.ruby-lang.org/issues/19542 and https://bugs.ruby-lang.org/issues/18805. --- io_buffer.c | 14 ++++++-------- test/ruby/test_io_buffer.rb | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/io_buffer.c b/io_buffer.c index 7e580c86336118..7715aa0d372dc6 100644 --- a/io_buffer.c +++ b/io_buffer.c @@ -854,11 +854,10 @@ io_buffer_get_bytes_for_writing(struct rb_io_buffer *buffer, void **base, size_t if (buffer->base) { *base = buffer->base; *size = buffer->size; - - return; + } else { + *base = NULL; + *size = 0; } - - rb_raise(rb_eIOBufferAllocationError, "The buffer is not allocated!"); } void @@ -880,11 +879,10 @@ io_buffer_get_bytes_for_reading(struct rb_io_buffer *buffer, const void **base, if (buffer->base) { *base = buffer->base; *size = buffer->size; - - return; + } else { + *base = NULL; + *size = 0; } - - rb_raise(rb_eIOBufferAllocationError, "The buffer is not allocated!"); } void diff --git a/test/ruby/test_io_buffer.rb b/test/ruby/test_io_buffer.rb index 321b6534ee2861..7a58ec0c5a86cf 100644 --- a/test/ruby/test_io_buffer.rb +++ b/test/ruby/test_io_buffer.rb @@ -199,6 +199,14 @@ def test_compare_different_size assert_positive buffer2 <=> buffer1 end + def test_compare_zero_length + buffer1 = IO::Buffer.new(0) + buffer2 = IO::Buffer.new(1) + + assert_negative buffer1 <=> buffer2 + assert_positive buffer2 <=> buffer1 + end + def test_slice buffer = IO::Buffer.new(128) slice = buffer.slice(8, 32) @@ -270,6 +278,14 @@ def test_get_string end end + def test_zero_length_get_string + buffer = IO::Buffer.new.slice(0, 0) + assert_equal "", buffer.get_string + + buffer = IO::Buffer.new(0) + assert_equal "", buffer.get_string + end + # We check that values are correctly round tripped. RANGES = { :U8 => [0, 2**8-1], @@ -316,6 +332,13 @@ def test_get_set_values end end + def test_zero_length_get_set_values + buffer = IO::Buffer.new(0) + + assert_equal [], buffer.get_values([], 0) + assert_equal 0, buffer.set_values([], 0, []) + end + def test_values buffer = IO::Buffer.new(128) @@ -340,6 +363,12 @@ def test_each end end + def test_zero_length_each + buffer = IO::Buffer.new(0) + + assert_equal [], buffer.each(:U8).to_a + end + def test_each_byte string = "The quick brown fox jumped over the lazy dog." buffer = IO::Buffer.for(string) @@ -347,6 +376,12 @@ def test_each_byte assert_equal string.bytes, buffer.each_byte.to_a end + def test_zero_length_each_byte + buffer = IO::Buffer.new(0) + + assert_equal [], buffer.each_byte.to_a + end + def test_clear buffer = IO::Buffer.new(16) buffer.set_string("Hello World!") From dde21a7967960e24377b01941cea6c30c17fa01d Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 14 Jan 2024 23:44:18 +0900 Subject: [PATCH 137/640] Explicitly convert between `VALUE` and `st_data_t` --- hash.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hash.c b/hash.c index 6a23f169571a53..91f1e73a393b8d 100644 --- a/hash.c +++ b/hash.c @@ -844,7 +844,9 @@ ar_general_foreach(VALUE hash, st_foreach_check_callback_func *func, st_update_c if (ar_cleared_entry(hash, i)) continue; ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i); - enum st_retval retval = (*func)(pair->key, pair->val, arg, 0); + st_data_t key = (st_data_t)pair->key; + st_data_t val = (st_data_t)pair->val; + enum st_retval retval = (*func)(key, val, arg, 0); ensure_ar_table(hash); /* pair may be not valid here because of theap */ @@ -856,14 +858,12 @@ ar_general_foreach(VALUE hash, st_foreach_check_callback_func *func, st_update_c return 0; case ST_REPLACE: if (replace) { - VALUE key = pair->key; - VALUE val = pair->val; retval = (*replace)(&key, &val, arg, TRUE); // TODO: pair should be same as pair before. - ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i); - pair->key = key; - pair->val = val; + pair = RHASH_AR_TABLE_REF(hash, i); + pair->key = (VALUE)key; + pair->val = (VALUE)val; } break; case ST_DELETE: From 9c3299896e7ea0aa1d9cc0d4786d7be2908ca9be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 02:42:28 +0000 Subject: [PATCH 138/640] Bump actions/upload-artifact from 4.0.0 to 4.1.0 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.0.0 to 4.1.0. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/c7d193f32edcb7bfad88892161225aeda64e9392...1eb3cb2b3e0f29609092a73eb033bb759a334595) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/wasm.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml index 61c9458f169427..c6ab3ffa40c921 100644 --- a/.github/workflows/wasm.yml +++ b/.github/workflows/wasm.yml @@ -136,7 +136,7 @@ jobs: - run: tar cfz ../install.tar.gz -C ../install . - name: Upload artifacts - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 with: name: ruby-wasm-install path: ${{ github.workspace }}/install.tar.gz @@ -164,7 +164,7 @@ jobs: - name: Save Pull Request number if: ${{ github.event_name == 'pull_request' }} run: echo "${{ github.event.pull_request.number }}" >> ${{ github.workspace }}/github-pr-info.txt - - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + - uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 if: ${{ github.event_name == 'pull_request' }} with: name: github-pr-info From e0312f90bbf5a6c0af5140ea94c67911515a147b Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Wed, 20 Dec 2023 17:55:50 -0800 Subject: [PATCH 139/640] [ruby/pp] Print beginless ranges properly Instead of displaying the start of the range as nil https://github.com/ruby/pp/commit/1df210d903 --- lib/pp.rb | 2 +- test/test_pp.rb | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/pp.rb b/lib/pp.rb index fb7aa7b41c6fd4..f04b7bf0cc9cb8 100644 --- a/lib/pp.rb +++ b/lib/pp.rb @@ -444,7 +444,7 @@ def pretty_print_cycle(q) # :nodoc: class Range # :nodoc: def pretty_print(q) # :nodoc: - q.pp self.begin + q.pp self.begin if self.begin q.breakable '' q.text(self.exclude_end? ? '...' : '..') q.breakable '' diff --git a/test/test_pp.rb b/test/test_pp.rb index 6da2b808b9844f..26e730fd009ffd 100644 --- a/test/test_pp.rb +++ b/test/test_pp.rb @@ -28,6 +28,13 @@ def o.method end assert_equal(%(""\n), PP.pp(o, "".dup)) end + + def test_range + assert_equal("0..1\n", PP.pp(0..1, "".dup)) + assert_equal("0...1\n", PP.pp(0...1, "".dup)) + assert_equal("0...\n", PP.pp(0..., "".dup)) + assert_equal("...1\n", PP.pp(...1, "".dup)) + end end class HasInspect From 7c6d7fbc28904b9814a18cc06796e0f12552778a Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Fri, 12 Jan 2024 13:04:59 -0500 Subject: [PATCH 140/640] [PRISM] Fix case without predicate Fixes ruby/prism#2149. --- prism_compile.c | 44 +++++++++++++++------------------ test/ruby/test_compile_prism.rb | 10 ++++++++ 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index a9d417550f3af8..79a122059f1628 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -3408,42 +3408,38 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, for (size_t i = 0; i < conditions.size; i++) { label = NEW_LABEL(lineno); conditions_labels[i] = label; - if (has_predicate) { - pm_when_node_t *when_node = (pm_when_node_t *)conditions.nodes[i]; + pm_when_node_t *when_node = (pm_when_node_t *)conditions.nodes[i]; - for (size_t i = 0; i < when_node->conditions.size; i++) { - pm_node_t *condition_node = when_node->conditions.nodes[i]; + for (size_t i = 0; i < when_node->conditions.size; i++) { + pm_node_t *condition_node = when_node->conditions.nodes[i]; - if (PM_NODE_TYPE_P(condition_node, PM_SPLAT_NODE)) { - ADD_INSN (ret, &dummy_line_node, dup); - PM_COMPILE_NOT_POPPED(condition_node); - ADD_INSN1(ret, &dummy_line_node, splatarray, Qfalse); - ADD_INSN1(ret, &dummy_line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE | VM_CHECKMATCH_ARRAY)); - } - else { - PM_COMPILE_NOT_POPPED(condition_node); + if (PM_NODE_TYPE_P(condition_node, PM_SPLAT_NODE)) { + ADD_INSN (ret, &dummy_line_node, dup); + PM_COMPILE_NOT_POPPED(condition_node); + ADD_INSN1(ret, &dummy_line_node, splatarray, Qfalse); + ADD_INSN1(ret, &dummy_line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE | VM_CHECKMATCH_ARRAY)); + } + else { + PM_COMPILE_NOT_POPPED(condition_node); + if (has_predicate) { ADD_INSN1(ret, &dummy_line_node, topn, INT2FIX(1)); ADD_SEND_WITH_FLAG(ret, &dummy_line_node, idEqq, INT2NUM(1), INT2FIX(VM_CALL_FCALL | VM_CALL_ARGS_SIMPLE)); } - - ADD_INSNL(ret, &dummy_line_node, branchif, label); } - } - else { - ADD_INSNL(ret, &dummy_line_node, jump, label); - PM_PUTNIL; + + ADD_INSNL(ret, &dummy_line_node, branchif, label); } } if (has_predicate) { PM_POP; + } - if (case_node->consequent) { - PM_COMPILE((pm_node_t *)case_node->consequent); - } - else { - PM_PUTNIL_UNLESS_POPPED; - } + if (case_node->consequent) { + PM_COMPILE((pm_node_t *)case_node->consequent); + } + else { + PM_PUTNIL_UNLESS_POPPED; } ADD_INSNL(ret, &dummy_line_node, jump, end_label); diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 87221289e2930a..ca76a69accf8f3 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -794,6 +794,16 @@ def self.prism_test_case_node :ng end RUBY + + # Test case without predicate + assert_prism_eval(<<~RUBY) + case + when 1 == 2 + :ng + else + :ok + end + RUBY end def test_ElseNode From 5e61cc26c9f4b926ea6472675d3851b5fd684824 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Mon, 15 Jan 2024 07:32:48 -0800 Subject: [PATCH 141/640] YJIT: Optimize Integer#succ (#9519) --- bootstraptest/test_yjit.rb | 5 +++++ yjit.rb | 1 + yjit/src/codegen.rs | 31 +++++++++++++++++++++++++++++++ yjit/src/stats.rs | 3 +++ 4 files changed, 40 insertions(+) diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index 0e8c4a0a0658f4..70a5501be20fe4 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -4347,3 +4347,8 @@ def entry entry } + +# Integer succ and overflow +assert_equal '[2, 4611686018427387904]', %q{ + [1.succ, 4611686018427387903.succ] +} diff --git a/yjit.rb b/yjit.rb index a96db9b64159d1..84d4d99b1f480a 100644 --- a/yjit.rb +++ b/yjit.rb @@ -284,6 +284,7 @@ def _print_stats_reasons(stats, out) # :nodoc: opt_mod opt_mult opt_plus + opt_succ setlocal ].each do |insn| print_counters(stats, out: out, prefix: "#{insn}_", prompt: "#{insn} exit reasons:", optional: true) diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 4e23cf10b1d491..4c94ae9ed8699d 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -4610,6 +4610,36 @@ fn jit_rb_int_equal( true } +fn jit_rb_int_succ( + _jit: &mut JITState, + asm: &mut Assembler, + _ocb: &mut OutlinedCb, + _ci: *const rb_callinfo, + _cme: *const rb_callable_method_entry_t, + _block: Option, + _argc: i32, + _known_recv_class: *const VALUE, +) -> bool { + // Guard the receiver is fixnum + let recv_type = asm.ctx.get_opnd_type(StackOpnd(0)); + let recv = asm.stack_pop(1); + if recv_type != Type::Fixnum { + asm_comment!(asm, "guard object is fixnum"); + asm.test(recv, Opnd::Imm(RUBY_FIXNUM_FLAG as i64)); + asm.jz(Target::side_exit(Counter::opt_succ_not_fixnum)); + } + + asm_comment!(asm, "Integer#succ"); + let out_val = asm.add(recv, Opnd::Imm(2)); // 2 is untagged Fixnum 1 + asm.jo(Target::side_exit(Counter::opt_succ_overflow)); + + // Push the output onto the stack + let dst = asm.stack_push(Type::Fixnum); + asm.mov(dst, out_val); + + true +} + fn jit_rb_int_div( jit: &mut JITState, asm: &mut Assembler, @@ -8852,6 +8882,7 @@ pub fn yjit_reg_method_codegen_fns() { yjit_reg_method(rb_cInteger, "==", jit_rb_int_equal); yjit_reg_method(rb_cInteger, "===", jit_rb_int_equal); + yjit_reg_method(rb_cInteger, "succ", jit_rb_int_succ); yjit_reg_method(rb_cInteger, "/", jit_rb_int_div); yjit_reg_method(rb_cInteger, "<<", jit_rb_int_lshift); yjit_reg_method(rb_cInteger, "[]", jit_rb_int_aref); diff --git a/yjit/src/stats.rs b/yjit/src/stats.rs index bf918aeb75a4b3..f4c53a50f99f7b 100644 --- a/yjit/src/stats.rs +++ b/yjit/src/stats.rs @@ -444,6 +444,9 @@ make_counters! { opt_minus_overflow, opt_mult_overflow, + opt_succ_not_fixnum, + opt_succ_overflow, + opt_mod_zero, opt_div_zero, From cc7b19e048aae4fb6ee75edf8498008042c42ee1 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 15 Jan 2024 11:27:31 -0500 Subject: [PATCH 142/640] [DOC] Improve docs for GC.compact --- gc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/gc.c b/gc.c index 6245e2083be0a5..a4de9573402bbe 100644 --- a/gc.c +++ b/gc.c @@ -11108,16 +11108,16 @@ heap_check_moved_i(void *vstart, void *vend, size_t stride, void *data) /* * call-seq: - * GC.compact + * GC.compact -> hash * - * This function compacts objects together in Ruby's heap. It eliminates + * This function compacts objects together in Ruby's heap. It eliminates * unused space (or fragmentation) in the heap by moving objects in to that - * unused space. This function returns a hash which contains statistics about - * which objects were moved. See GC.latest_compact_info for details - * about compaction statistics. + * unused space. * - * This method is implementation specific and not expected to be implemented - * in any implementation besides MRI. + * The returned +hash+ contains statistics about the objects that were moved; + * see GC.latest_compact_info. + * + * This method is only expected to work on CRuby. * * To test whether \GC compaction is supported, use the idiom: * From 6a175902f4fe31cf7617406e17d11deb9fccec32 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 15 Jan 2024 10:28:39 -0500 Subject: [PATCH 143/640] [PRISM] Fix keyword splat inside of array Fixes ruby/prism#2155. --- prism_compile.c | 94 ++++++++++++++++++++++++++++++++- test/ruby/test_compile_prism.rb | 3 ++ 2 files changed, 95 insertions(+), 2 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 79a122059f1628..38fbbb443a4fea 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -3097,12 +3097,102 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, PM_POP_IF_POPPED; } else { + bool has_kw_splat = false; + for (size_t index = 0; index < elements->size; index++) { - PM_COMPILE(elements->nodes[index]); + pm_node_t *element_node = elements->nodes[index]; + + switch (PM_NODE_TYPE(element_node)) { + case PM_KEYWORD_HASH_NODE: { + has_kw_splat = true; + pm_keyword_hash_node_t *keyword_arg = (pm_keyword_hash_node_t *)element_node; + size_t len = keyword_arg->elements.size; + + int cur_hash_size = 0; + + bool new_hash_emitted = false; + for (size_t i = 0; i < len; i++) { + pm_node_t *cur_node = keyword_arg->elements.nodes[i]; + + pm_node_type_t cur_type = PM_NODE_TYPE(cur_node); + + switch (PM_NODE_TYPE(cur_node)) { + case PM_ASSOC_NODE: { + pm_assoc_node_t *assoc = (pm_assoc_node_t *)cur_node; + + PM_COMPILE(assoc->key); + PM_COMPILE(assoc->value); + cur_hash_size++; + + // If we're at the last keyword arg, or the last assoc node of this "set", + // then we want to either construct a newhash or merge onto previous hashes + if (i == (len - 1) || !PM_NODE_TYPE_P(keyword_arg->elements.nodes[i + 1], cur_type)) { + if (new_hash_emitted) { + ADD_SEND(ret, &dummy_line_node, id_core_hash_merge_ptr, INT2FIX(cur_hash_size * 2 + 1)); + } + else { + if (!popped) { + ADD_INSN1(ret, &dummy_line_node, newhash, INT2FIX(cur_hash_size * 2)); + cur_hash_size = 0; + new_hash_emitted = true; + } + } + } + + break; + } + case PM_ASSOC_SPLAT_NODE: { + if (len > 1) { + ADD_INSN1(ret, &dummy_line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + if (i == 0) { + if (!popped) { + ADD_INSN1(ret, &dummy_line_node, newhash, INT2FIX(0)); + new_hash_emitted = true; + } + } + else { + PM_SWAP; + } + } + + pm_assoc_splat_node_t *assoc_splat = (pm_assoc_splat_node_t *)cur_node; + PM_COMPILE(assoc_splat->value); + + if (len > 1) { + ADD_SEND(ret, &dummy_line_node, id_core_hash_merge_kwd, INT2FIX(2)); + } + + if ((i < len - 1) && !PM_NODE_TYPE_P(keyword_arg->elements.nodes[i + 1], cur_type)) { + ADD_INSN1(ret, &dummy_line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + PM_SWAP; + } + + cur_hash_size = 0; + break; + } + default: { + rb_bug("Unknown type in keyword argument %s\n", pm_node_type_to_str(PM_NODE_TYPE(cur_node))); + } + } + } + + break; + } + default: { + PM_COMPILE(element_node); + + break; + } + } } if (!popped) { - ADD_INSN1(ret, &dummy_line_node, newarray, INT2FIX(elements->size)); + if (has_kw_splat) { + ADD_INSN1(ret, &dummy_line_node, newarraykwsplat, INT2FIX(elements->size)); + } + else { + ADD_INSN1(ret, &dummy_line_node, newarray, INT2FIX(elements->size)); + } } } } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index ca76a69accf8f3..b6ff666fb9af68 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -702,6 +702,9 @@ def test_ArrayNode assert_prism_eval("[-1, true, 0, *1..2, 3, 4, *5..6, 7, 8, *9..11]") assert_prism_eval("a = [1,2]; [0, *a, 3, 4, *5..6, 7, 8, *9..11]") assert_prism_eval("[[*1..2], 3, *4..5]") + + # Test keyword splat inside of array + assert_prism_eval("[**{x: 'hello'}]") end def test_AssocNode From 6a1bf4cf1b069de0aaa55bc327f0b9b1ee1f5ed0 Mon Sep 17 00:00:00 2001 From: Maxime Chevalier-Boisvert Date: Mon, 15 Jan 2024 17:35:29 -0500 Subject: [PATCH 144/640] YJIT: optimized codegen for String#length (#9543) Minor optimization for programs doing string processing. --- yjit/src/codegen.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 4c94ae9ed8699d..e626a71d881540 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -4811,6 +4811,33 @@ fn jit_rb_str_uplus( true } +fn jit_rb_str_length( + _jit: &mut JITState, + asm: &mut Assembler, + _ocb: &mut OutlinedCb, + _ci: *const rb_callinfo, + _cme: *const rb_callable_method_entry_t, + _block: Option, + _argc: i32, + _known_recv_class: *const VALUE, +) -> bool { + asm_comment!(asm, "String#length"); + extern "C" { + fn rb_str_length(str: VALUE) -> VALUE; + } + + // This function cannot allocate or raise an exceptions + let recv = asm.stack_opnd(0); + let ret_opnd = asm.ccall(rb_str_length as *const u8, vec![recv]); + asm.stack_pop(1); // Keep recv on stack during ccall for GC + + // Should be guaranteed to be a fixnum on 64-bit systems + let out_opnd = asm.stack_push(Type::Fixnum); + asm.mov(out_opnd, ret_opnd); + + true +} + fn jit_rb_str_bytesize( _jit: &mut JITState, asm: &mut Assembler, @@ -8890,6 +8917,8 @@ pub fn yjit_reg_method_codegen_fns() { yjit_reg_method(rb_cString, "empty?", jit_rb_str_empty_p); yjit_reg_method(rb_cString, "to_s", jit_rb_str_to_s); yjit_reg_method(rb_cString, "to_str", jit_rb_str_to_s); + yjit_reg_method(rb_cString, "length", jit_rb_str_length); + yjit_reg_method(rb_cString, "size", jit_rb_str_length); yjit_reg_method(rb_cString, "bytesize", jit_rb_str_bytesize); yjit_reg_method(rb_cString, "getbyte", jit_rb_str_getbyte); yjit_reg_method(rb_cString, "<<", jit_rb_str_concat); From 0abbab9eb16baf0995deaab2fbb3850ace50bdd9 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 15 Jan 2024 22:46:21 +0900 Subject: [PATCH 145/640] [Bug #20184] Test for low memory --- test/ruby/test_process.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb index 7e317c08402312..0e417f0fef6517 100644 --- a/test/ruby/test_process.rb +++ b/test/ruby/test_process.rb @@ -2838,4 +2838,11 @@ def test_concurrent_group_and_pid_wait [t1, t2, t3].each { _1&.join rescue nil } [long_rpipe, long_wpipe, short_rpipe, short_wpipe].each { _1&.close rescue nil } end if defined?(fork) + + def test_low_memory_startup + omit "JIT enabled" if %w[YJIT RJIT].any? {|n| RubyVM.const_defined?(n) and RubyVM.const_get(n).enabled?} + (25..27).each {|i| as = 1< e + omit e.message + end end From be7c91db44d6b8dba8fa11ff782965b4bfa0b3c8 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Tue, 16 Jan 2024 12:43:53 +0900 Subject: [PATCH 146/640] Do not pollute toplevel namespace --- spec/ruby/library/shellwords/shellwords_spec.rb | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/spec/ruby/library/shellwords/shellwords_spec.rb b/spec/ruby/library/shellwords/shellwords_spec.rb index 2975fd99742740..fe86b6faab0db8 100644 --- a/spec/ruby/library/shellwords/shellwords_spec.rb +++ b/spec/ruby/library/shellwords/shellwords_spec.rb @@ -1,34 +1,33 @@ require_relative '../../spec_helper' require 'shellwords' -include Shellwords describe "Shellwords#shellwords" do it "honors quoted strings" do - shellwords('a "b b" a').should == ['a', 'b b', 'a'] + Shellwords.shellwords('a "b b" a').should == ['a', 'b b', 'a'] end it "honors escaped double quotes" do - shellwords('a "\"b\" c" d').should == ['a', '"b" c', 'd'] + Shellwords.shellwords('a "\"b\" c" d').should == ['a', '"b" c', 'd'] end it "honors escaped single quotes" do - shellwords("a \"'b' c\" d").should == ['a', "'b' c", 'd'] + Shellwords.shellwords("a \"'b' c\" d").should == ['a', "'b' c", 'd'] end it "honors escaped spaces" do - shellwords('a b\ c d').should == ['a', 'b c', 'd'] + Shellwords.shellwords('a b\ c d').should == ['a', 'b c', 'd'] end it "raises ArgumentError when double quoted strings are misquoted" do - -> { shellwords('a "b c d e') }.should raise_error(ArgumentError) + -> { Shellwords.shellwords('a "b c d e') }.should raise_error(ArgumentError) end it "raises ArgumentError when single quoted strings are misquoted" do - -> { shellwords("a 'b c d e") }.should raise_error(ArgumentError) + -> { Shellwords.shellwords("a 'b c d e") }.should raise_error(ArgumentError) end # https://bugs.ruby-lang.org/issues/10055 it "matches POSIX sh behavior for backslashes within double quoted strings" do - shellsplit('printf "%s\n"').should == ['printf', '%s\n'] + Shellwords.shellsplit('printf "%s\n"').should == ['printf', '%s\n'] end end From 924f3907c073636ad679fc077c84e9b18c46dc85 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Tue, 16 Jan 2024 12:44:28 +0900 Subject: [PATCH 147/640] Enable spec_guards with 3.3 --- .github/workflows/spec_guards.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/spec_guards.yml b/.github/workflows/spec_guards.yml index 381a84d91751e9..f28c91d4af6dae 100644 --- a/.github/workflows/spec_guards.yml +++ b/.github/workflows/spec_guards.yml @@ -43,7 +43,7 @@ jobs: - ruby-3.0 - ruby-3.1 - ruby-3.2 - # - ruby-3.3 + - ruby-3.3 steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 From 26cf40aaa08e74bfcfd1f4ee75a7c19c6efbac06 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 16 Jan 2024 15:54:01 +0900 Subject: [PATCH 148/640] Always enabled leakchecker by ruby/mspec --- common.mk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/common.mk b/common.mk index c4b6dec1533680..24481b035a7d91 100644 --- a/common.mk +++ b/common.mk @@ -43,6 +43,9 @@ RUBYLIB = $(PATH_SEPARATOR) RUBYOPT = - RUN_OPTS = --disable-gems +# Enabld leakcheckers by ruby/mspec +CHECK_LEAKS = true + # GITPULLOPTIONS = --no-tags PRISM_SRCDIR = $(srcdir)/prism From c5d54e1db19225b2c05e74c7fa6bf36846c08de3 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 16 Jan 2024 16:29:14 +0900 Subject: [PATCH 149/640] We don't need to sync mutex_m --- tool/sync_default_gems.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb index 280b709c11b4b0..58e15848cc73e0 100755 --- a/tool/sync_default_gems.rb +++ b/tool/sync_default_gems.rb @@ -43,7 +43,6 @@ module SyncDefaultGems irb: 'ruby/irb', json: 'flori/json', logger: 'ruby/logger', - mutex_m: "ruby/mutex_m", nkf: "ruby/nkf", observer: "ruby/observer", open3: "ruby/open3", From b68dab2d0fbc7b84749d1c8447c003cabbb70a51 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 11 Jan 2024 14:00:41 +0900 Subject: [PATCH 150/640] Extract getoptlong as bundled gems --- gems/bundled_gems | 1 + lib/getoptlong.gemspec | 30 -- lib/getoptlong.rb | 867 ---------------------------------------- test/test_getoptlong.rb | 163 -------- 4 files changed, 1 insertion(+), 1060 deletions(-) delete mode 100644 lib/getoptlong.gemspec delete mode 100644 lib/getoptlong.rb delete mode 100644 test/test_getoptlong.rb diff --git a/gems/bundled_gems b/gems/bundled_gems index 22a52318f39137..42ebcb82316d93 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -22,3 +22,4 @@ typeprof 0.21.9 https://github.com/ruby/typeprof debug 1.9.1 https://github.com/ruby/debug racc 1.7.3 https://github.com/ruby/racc mutex_m 0.2.0 https://github.com/ruby/mutex_m +getoptlong 0.2.1 https://github.com/ruby/getoptlong diff --git a/lib/getoptlong.gemspec b/lib/getoptlong.gemspec deleted file mode 100644 index c2f65dcaab7317..00000000000000 --- a/lib/getoptlong.gemspec +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: true - -name = File.basename(__FILE__, ".gemspec") -version = ["lib", Array.new(name.count("-")+1, ".").join("/")].find do |dir| - break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line| - /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1 - end rescue nil -end - -Gem::Specification.new do |spec| - spec.name = name - spec.version = version - spec.authors = ["Yukihiro Matsumoto"] - spec.email = ["matz@ruby-lang.org"] - - spec.summary = %q{GetoptLong for Ruby} - spec.description = spec.summary - spec.homepage = "https://github.com/ruby/getoptlong" - spec.licenses = ["Ruby", "BSD-2-Clause"] - - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = spec.homepage - - # Specify which files should be added to the gem when it is released. - # The `git ls-files -z` loads the files in the RubyGem that have been added into git. - spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do - `git ls-files -z 2>#{IO::NULL}`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } - end - spec.require_paths = ["lib"] -end diff --git a/lib/getoptlong.rb b/lib/getoptlong.rb deleted file mode 100644 index c825962160ed0e..00000000000000 --- a/lib/getoptlong.rb +++ /dev/null @@ -1,867 +0,0 @@ -# frozen_string_literal: true -# -# GetoptLong for Ruby -# -# Copyright (C) 1998, 1999, 2000 Motoyuki Kasahara. -# -# You may redistribute and/or modify this library under the same license -# terms as Ruby. - -# \Class \GetoptLong provides parsing both for options -# and for regular arguments. -# -# Using \GetoptLong, you can define options for your program. -# The program can then capture and respond to whatever options -# are included in the command that executes the program. -# -# A simple example: file simple.rb: -# -# :include: ../sample/getoptlong/simple.rb -# -# If you are somewhat familiar with options, -# you may want to skip to this -# {full example}[#class-GetoptLong-label-Full+Example]. -# -# == Options -# -# A \GetoptLong option has: -# -# - A string option name. -# - Zero or more string aliases for the name. -# - An option type. -# -# Options may be defined by calling singleton method GetoptLong.new, -# which returns a new \GetoptLong object. -# Options may then be processed by calling other methods -# such as GetoptLong#each. -# -# === Option Name and Aliases -# -# In the array that defines an option, -# the first element is the string option name. -# Often the name takes the 'long' form, beginning with two hyphens. -# -# The option name may have any number of aliases, -# which are defined by additional string elements. -# -# The name and each alias must be of one of two forms: -# -# - Two hyphens, followed by one or more letters. -# - One hyphen, followed by a single letter. -# -# File aliases.rb: -# -# :include: ../sample/getoptlong/aliases.rb -# -# An option may be cited by its name, -# or by any of its aliases; -# the parsed option always reports the name, not an alias: -# -# $ ruby aliases.rb -a -p --xxx --aaa -x -# -# Output: -# -# ["--xxx", ""] -# ["--xxx", ""] -# ["--xxx", ""] -# ["--xxx", ""] -# ["--xxx", ""] -# -# -# An option may also be cited by an abbreviation of its name or any alias, -# as long as that abbreviation is unique among the options. -# -# File abbrev.rb: -# -# :include: ../sample/getoptlong/abbrev.rb -# -# Command line: -# -# $ ruby abbrev.rb --xxx --xx --xyz --xy -# -# Output: -# -# ["--xxx", ""] -# ["--xxx", ""] -# ["--xyz", ""] -# ["--xyz", ""] -# -# This command line raises GetoptLong::AmbiguousOption: -# -# $ ruby abbrev.rb --x -# -# === Repetition -# -# An option may be cited more than once: -# -# $ ruby abbrev.rb --xxx --xyz --xxx --xyz -# -# Output: -# -# ["--xxx", ""] -# ["--xyz", ""] -# ["--xxx", ""] -# ["--xyz", ""] -# -# === Treating Remaining Options as Arguments -# -# A option-like token that appears -# anywhere after the token -- is treated as an ordinary argument, -# and is not processed as an option: -# -# $ ruby abbrev.rb --xxx --xyz -- --xxx --xyz -# -# Output: -# -# ["--xxx", ""] -# ["--xyz", ""] -# -# === Option Types -# -# Each option definition includes an option type, -# which controls whether the option takes an argument. -# -# File types.rb: -# -# :include: ../sample/getoptlong/types.rb -# -# Note that an option type has to do with the option argument -# (whether it is required, optional, or forbidden), -# not with whether the option itself is required. -# -# ==== Option with Required Argument -# -# An option of type GetoptLong::REQUIRED_ARGUMENT -# must be followed by an argument, which is associated with that option: -# -# $ ruby types.rb --xxx foo -# -# Output: -# -# ["--xxx", "foo"] -# -# If the option is not last, its argument is whatever follows it -# (even if the argument looks like another option): -# -# $ ruby types.rb --xxx --yyy -# -# Output: -# -# ["--xxx", "--yyy"] -# -# If the option is last, an exception is raised: -# -# $ ruby types.rb -# # Raises GetoptLong::MissingArgument -# -# ==== Option with Optional Argument -# -# An option of type GetoptLong::OPTIONAL_ARGUMENT -# may be followed by an argument, which if given is associated with that option. -# -# If the option is last, it does not have an argument: -# -# $ ruby types.rb --yyy -# -# Output: -# -# ["--yyy", ""] -# -# If the option is followed by another option, it does not have an argument: -# -# $ ruby types.rb --yyy --zzz -# -# Output: -# -# ["--yyy", ""] -# ["--zzz", ""] -# -# Otherwise the option is followed by its argument, which is associated -# with that option: -# -# $ ruby types.rb --yyy foo -# -# Output: -# -# ["--yyy", "foo"] -# -# ==== Option with No Argument -# -# An option of type GetoptLong::NO_ARGUMENT takes no argument: -# -# ruby types.rb --zzz foo -# -# Output: -# -# ["--zzz", ""] -# -# === ARGV -# -# You can process options either with method #each and a block, -# or with method #get. -# -# During processing, each found option is removed, along with its argument -# if there is one. -# After processing, each remaining element was neither an option -# nor the argument for an option. -# -# File argv.rb: -# -# :include: ../sample/getoptlong/argv.rb -# -# Command line: -# -# $ ruby argv.rb --xxx Foo --yyy Bar Baz --zzz Bat Bam -# -# Output: -# -# Original ARGV: ["--xxx", "Foo", "--yyy", "Bar", "Baz", "--zzz", "Bat", "Bam"] -# ["--xxx", "Foo"] -# ["--yyy", "Bar"] -# ["--zzz", ""] -# Remaining ARGV: ["Baz", "Bat", "Bam"] -# -# === Ordering -# -# There are three settings that control the way the options -# are interpreted: -# -# - +PERMUTE+. -# - +REQUIRE_ORDER+. -# - +RETURN_IN_ORDER+. -# -# The initial setting for a new \GetoptLong object is +REQUIRE_ORDER+ -# if environment variable +POSIXLY_CORRECT+ is defined, +PERMUTE+ otherwise. -# -# ==== PERMUTE Ordering -# -# In the +PERMUTE+ ordering, options and other, non-option, -# arguments may appear in any order and any mixture. -# -# File permute.rb: -# -# :include: ../sample/getoptlong/permute.rb -# -# Command line: -# -# $ ruby permute.rb Foo --zzz Bar --xxx Baz --yyy Bat Bam --xxx Bag Bah -# -# Output: -# -# Original ARGV: ["Foo", "--zzz", "Bar", "--xxx", "Baz", "--yyy", "Bat", "Bam", "--xxx", "Bag", "Bah"] -# ["--zzz", ""] -# ["--xxx", "Baz"] -# ["--yyy", "Bat"] -# ["--xxx", "Bag"] -# Remaining ARGV: ["Foo", "Bar", "Bam", "Bah"] -# -# ==== REQUIRE_ORDER Ordering -# -# In the +REQUIRE_ORDER+ ordering, all options precede all non-options; -# that is, each word after the first non-option word -# is treated as a non-option word (even if it begins with a hyphen). -# -# File require_order.rb: -# -# :include: ../sample/getoptlong/require_order.rb -# -# Command line: -# -# $ ruby require_order.rb --xxx Foo Bar --xxx Baz --yyy Bat -zzz -# -# Output: -# -# Original ARGV: ["--xxx", "Foo", "Bar", "--xxx", "Baz", "--yyy", "Bat", "-zzz"] -# ["--xxx", "Foo"] -# Remaining ARGV: ["Bar", "--xxx", "Baz", "--yyy", "Bat", "-zzz"] -# -# ==== RETURN_IN_ORDER Ordering -# -# In the +RETURN_IN_ORDER+ ordering, every word is treated as an option. -# A word that begins with a hyphen (or two) is treated in the usual way; -# a word +word+ that does not so begin is treated as an option -# whose name is an empty string, and whose value is +word+. -# -# File return_in_order.rb: -# -# :include: ../sample/getoptlong/return_in_order.rb -# -# Command line: -# -# $ ruby return_in_order.rb Foo --xxx Bar Baz --zzz Bat Bam -# -# Output: -# -# Original ARGV: ["Foo", "--xxx", "Bar", "Baz", "--zzz", "Bat", "Bam"] -# ["", "Foo"] -# ["--xxx", "Bar"] -# ["", "Baz"] -# ["--zzz", ""] -# ["", "Bat"] -# ["", "Bam"] -# Remaining ARGV: [] -# -# === Full Example -# -# File fibonacci.rb: -# -# :include: ../sample/getoptlong/fibonacci.rb -# -# Command line: -# -# $ ruby fibonacci.rb -# -# Output: -# -# Option --number is required. -# Usage: -# -# -n n, --number n: -# Compute Fibonacci number for n. -# -v [boolean], --verbose [boolean]: -# Show intermediate results; default is 'false'. -# -h, --help: -# Show this help. -# -# Command line: -# -# $ ruby fibonacci.rb --number -# -# Raises GetoptLong::MissingArgument: -# -# fibonacci.rb: option `--number' requires an argument -# -# Command line: -# -# $ ruby fibonacci.rb --number 6 -# -# Output: -# -# 8 -# -# Command line: -# -# $ ruby fibonacci.rb --number 6 --verbose -# -# Output: -# 1 -# 2 -# 3 -# 5 -# 8 -# -# Command line: -# -# $ ruby fibonacci.rb --number 6 --verbose yes -# -# Output: -# -# --verbose argument must be true or false -# Usage: -# -# -n n, --number n: -# Compute Fibonacci number for n. -# -v [boolean], --verbose [boolean]: -# Show intermediate results; default is 'false'. -# -h, --help: -# Show this help. -# -class GetoptLong - # Version. - VERSION = "0.2.1" - - # - # Orderings. - # - ORDERINGS = [REQUIRE_ORDER = 0, PERMUTE = 1, RETURN_IN_ORDER = 2] - - # - # Argument flags. - # - ARGUMENT_FLAGS = [NO_ARGUMENT = 0, REQUIRED_ARGUMENT = 1, - OPTIONAL_ARGUMENT = 2] - - # - # Status codes. - # - STATUS_YET, STATUS_STARTED, STATUS_TERMINATED = 0, 1, 2 - - # - # Error types. - # - class Error < StandardError; end - class AmbiguousOption < Error; end - class NeedlessArgument < Error; end - class MissingArgument < Error; end - class InvalidOption < Error; end - - # - # Returns a new \GetoptLong object based on the given +arguments+. - # See {Options}[#class-GetoptLong-label-Options]. - # - # Example: - # - # :include: ../sample/getoptlong/simple.rb - # - # Raises an exception if: - # - # - Any of +arguments+ is not an array. - # - Any option name or alias is not a string. - # - Any option type is invalid. - # - def initialize(*arguments) - # - # Current ordering. - # - if ENV.include?('POSIXLY_CORRECT') - @ordering = REQUIRE_ORDER - else - @ordering = PERMUTE - end - - # - # Hash table of option names. - # Keys of the table are option names, and their values are canonical - # names of the options. - # - @canonical_names = Hash.new - - # - # Hash table of argument flags. - # Keys of the table are option names, and their values are argument - # flags of the options. - # - @argument_flags = Hash.new - - # - # Whether error messages are output to $stderr. - # - @quiet = false - - # - # Status code. - # - @status = STATUS_YET - - # - # Error code. - # - @error = nil - - # - # Error message. - # - @error_message = nil - - # - # Rest of catenated short options. - # - @rest_singles = '' - - # - # List of non-option-arguments. - # Append them to ARGV when option processing is terminated. - # - @non_option_arguments = Array.new - - if 0 < arguments.length - set_options(*arguments) - end - end - - # Sets the ordering; see {Ordering}[#class-GetoptLong-label-Ordering]; - # returns the new ordering. - # - # If the given +ordering+ is +PERMUTE+ and environment variable - # +POSIXLY_CORRECT+ is defined, sets the ordering to +REQUIRE_ORDER+; - # otherwise sets the ordering to +ordering+: - # - # options = GetoptLong.new - # options.ordering == GetoptLong::PERMUTE # => true - # options.ordering = GetoptLong::RETURN_IN_ORDER - # options.ordering == GetoptLong::RETURN_IN_ORDER # => true - # ENV['POSIXLY_CORRECT'] = 'true' - # options.ordering = GetoptLong::PERMUTE - # options.ordering == GetoptLong::REQUIRE_ORDER # => true - # - # Raises an exception if +ordering+ is invalid. - # - def ordering=(ordering) - # - # The method is failed if option processing has already started. - # - if @status != STATUS_YET - set_error(ArgumentError, "argument error") - raise RuntimeError, - "invoke ordering=, but option processing has already started" - end - - # - # Check ordering. - # - if !ORDERINGS.include?(ordering) - raise ArgumentError, "invalid ordering `#{ordering}'" - end - if ordering == PERMUTE && ENV.include?('POSIXLY_CORRECT') - @ordering = REQUIRE_ORDER - else - @ordering = ordering - end - end - - # - # Returns the ordering setting. - # - attr_reader :ordering - - # - # Replaces existing options with those given by +arguments+, - # which have the same form as the arguments to ::new; - # returns +self+. - # - # Raises an exception if option processing has begun. - # - def set_options(*arguments) - # - # The method is failed if option processing has already started. - # - if @status != STATUS_YET - raise RuntimeError, - "invoke set_options, but option processing has already started" - end - - # - # Clear tables of option names and argument flags. - # - @canonical_names.clear - @argument_flags.clear - - arguments.each do |arg| - if !arg.is_a?(Array) - raise ArgumentError, "the option list contains non-Array argument" - end - - # - # Find an argument flag and it set to `argument_flag'. - # - argument_flag = nil - arg.each do |i| - if ARGUMENT_FLAGS.include?(i) - if argument_flag != nil - raise ArgumentError, "too many argument-flags" - end - argument_flag = i - end - end - - raise ArgumentError, "no argument-flag" if argument_flag == nil - - canonical_name = nil - arg.each do |i| - # - # Check an option name. - # - next if i == argument_flag - begin - if !i.is_a?(String) || i !~ /\A-([^-]|-.+)\z/ - raise ArgumentError, "an invalid option `#{i}'" - end - if (@canonical_names.include?(i)) - raise ArgumentError, "option redefined `#{i}'" - end - rescue - @canonical_names.clear - @argument_flags.clear - raise - end - - # - # Register the option (`i') to the `@canonical_names' and - # `@canonical_names' Hashes. - # - if canonical_name == nil - canonical_name = i - end - @canonical_names[i] = canonical_name - @argument_flags[i] = argument_flag - end - raise ArgumentError, "no option name" if canonical_name == nil - end - return self - end - - # - # Sets quiet mode and returns the given argument: - # - # - When +false+ or +nil+, error messages are written to $stdout. - # - Otherwise, error messages are not written. - # - attr_writer :quiet - - # - # Returns the quiet mode setting. - # - attr_reader :quiet - alias quiet? quiet - - # - # Terminate option processing; - # returns +nil+ if processing has already terminated; - # otherwise returns +self+. - # - def terminate - return nil if @status == STATUS_TERMINATED - raise RuntimeError, "an error has occurred" if @error != nil - - @status = STATUS_TERMINATED - @non_option_arguments.reverse_each do |argument| - ARGV.unshift(argument) - end - - @canonical_names = nil - @argument_flags = nil - @rest_singles = nil - @non_option_arguments = nil - - return self - end - - # - # Returns +true+ if option processing has terminated, +false+ otherwise. - # - def terminated? - return @status == STATUS_TERMINATED - end - - # - # \Set an error (a protected method). - # - def set_error(type, message) - $stderr.print("#{$0}: #{message}\n") if !@quiet - - @error = type - @error_message = message - @canonical_names = nil - @argument_flags = nil - @rest_singles = nil - @non_option_arguments = nil - - raise type, message - end - protected :set_error - - # - # Returns whether option processing has failed. - # - attr_reader :error - alias error? error - - # Return the appropriate error message in POSIX-defined format. - # If no error has occurred, returns +nil+. - # - def error_message - return @error_message - end - - # - # Returns the next option as a 2-element array containing: - # - # - The option name (the name itself, not an alias). - # - The option value. - # - # Returns +nil+ if there are no more options. - # - def get - option_name, option_argument = nil, '' - - # - # Check status. - # - return nil if @error != nil - case @status - when STATUS_YET - @status = STATUS_STARTED - when STATUS_TERMINATED - return nil - end - - # - # Get next option argument. - # - if 0 < @rest_singles.length - argument = '-' + @rest_singles - elsif (ARGV.length == 0) - terminate - return nil - elsif @ordering == PERMUTE - while 0 < ARGV.length && ARGV[0] !~ /\A-./ - @non_option_arguments.push(ARGV.shift) - end - if ARGV.length == 0 - terminate - return nil - end - argument = ARGV.shift - elsif @ordering == REQUIRE_ORDER - if (ARGV[0] !~ /\A-./) - terminate - return nil - end - argument = ARGV.shift - else - argument = ARGV.shift - end - - # - # Check the special argument `--'. - # `--' indicates the end of the option list. - # - if argument == '--' && @rest_singles.length == 0 - terminate - return nil - end - - # - # Check for long and short options. - # - if argument =~ /\A(--[^=]+)/ && @rest_singles.length == 0 - # - # This is a long style option, which start with `--'. - # - pattern = $1 - if @canonical_names.include?(pattern) - option_name = pattern - else - # - # The option `option_name' is not registered in `@canonical_names'. - # It may be an abbreviated. - # - matches = [] - @canonical_names.each_key do |key| - if key.index(pattern) == 0 - option_name = key - matches << key - end - end - if 2 <= matches.length - set_error(AmbiguousOption, "option `#{argument}' is ambiguous between #{matches.join(', ')}") - elsif matches.length == 0 - set_error(InvalidOption, "unrecognized option `#{argument}'") - end - end - - # - # Check an argument to the option. - # - if @argument_flags[option_name] == REQUIRED_ARGUMENT - if argument =~ /=(.*)/m - option_argument = $1 - elsif 0 < ARGV.length - option_argument = ARGV.shift - else - set_error(MissingArgument, - "option `#{argument}' requires an argument") - end - elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT - if argument =~ /=(.*)/m - option_argument = $1 - elsif 0 < ARGV.length && ARGV[0] !~ /\A-./ - option_argument = ARGV.shift - else - option_argument = '' - end - elsif argument =~ /=(.*)/m - set_error(NeedlessArgument, - "option `#{option_name}' doesn't allow an argument") - end - - elsif argument =~ /\A(-(.))(.*)/m - # - # This is a short style option, which start with `-' (not `--'). - # Short options may be catenated (e.g. `-l -g' is equivalent to - # `-lg'). - # - option_name, ch, @rest_singles = $1, $2, $3 - - if @canonical_names.include?(option_name) - # - # The option `option_name' is found in `@canonical_names'. - # Check its argument. - # - if @argument_flags[option_name] == REQUIRED_ARGUMENT - if 0 < @rest_singles.length - option_argument = @rest_singles - @rest_singles = '' - elsif 0 < ARGV.length - option_argument = ARGV.shift - else - # 1003.2 specifies the format of this message. - set_error(MissingArgument, "option requires an argument -- #{ch}") - end - elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT - if 0 < @rest_singles.length - option_argument = @rest_singles - @rest_singles = '' - elsif 0 < ARGV.length && ARGV[0] !~ /\A-./ - option_argument = ARGV.shift - else - option_argument = '' - end - end - else - # - # This is an invalid option. - # 1003.2 specifies the format of this message. - # - if ENV.include?('POSIXLY_CORRECT') - set_error(InvalidOption, "invalid option -- #{ch}") - else - set_error(InvalidOption, "invalid option -- #{ch}") - end - end - else - # - # This is a non-option argument. - # Only RETURN_IN_ORDER fell into here. - # - return '', argument - end - - return @canonical_names[option_name], option_argument - end - alias get_option get - - # - # Calls the given block with each option; - # each option is a 2-element array containing: - # - # - The option name (the name itself, not an alias). - # - The option value. - # - # Example: - # - # :include: ../sample/getoptlong/each.rb - # - # Command line: - # - # ruby each.rb -xxx Foo -x Bar --yyy Baz -y Bat --zzz - # - # Output: - # - # Original ARGV: ["-xxx", "Foo", "-x", "Bar", "--yyy", "Baz", "-y", "Bat", "--zzz"] - # ["--xxx", "xx"] - # ["--xxx", "Bar"] - # ["--yyy", "Baz"] - # ["--yyy", "Bat"] - # ["--zzz", ""] - # Remaining ARGV: ["Foo"] - # - def each - loop do - option_name, option_argument = get_option - break if option_name == nil - yield option_name, option_argument - end - end - alias each_option each -end diff --git a/test/test_getoptlong.rb b/test/test_getoptlong.rb deleted file mode 100644 index 0cd370b6c7556a..00000000000000 --- a/test/test_getoptlong.rb +++ /dev/null @@ -1,163 +0,0 @@ -require 'test/unit' -require 'getoptlong' - -class TestGetoptLong < Test::Unit::TestCase - - def verify(test_argv, expected_remaining_argv, expected_options) - # Save ARGV and replace it with a test ARGV. - argv_saved = ARGV.dup - ARGV.replace(test_argv) - # Define options. - opts = GetoptLong.new( - ['--xxx', '-x', '--aaa', '-a', GetoptLong::REQUIRED_ARGUMENT], - ['--yyy', '-y', '--bbb', '-b', GetoptLong::OPTIONAL_ARGUMENT], - ['--zzz', '-z', '--ccc', '-c', GetoptLong::NO_ARGUMENT] - ) - opts.quiet = true - # Gather options. - actual_options = [] - opts.each do |opt, arg| - actual_options << "#{opt}: #{arg}" - end - # Save remaining test ARGV and restore original ARGV. - actual_remaining_argv = ARGV.dup - ARGV.replace(argv_saved) - # Assert. - assert_equal(expected_remaining_argv, actual_remaining_argv, 'ARGV') - assert_equal(expected_options, actual_options, 'Options') - end - - def test_no_options - expected_options = [] - expected_argv = %w[foo bar] - argv = %w[foo bar] - verify(argv, expected_argv, expected_options) - end - - def test_required_argument - expected_options = [ - '--xxx: arg' - ] - expected_argv = %w[foo bar] - options = %w[--xxx --xx --x -x --aaa --aa --a -a] - options.each do |option| - argv = ['foo', option, 'arg', 'bar'] - verify(argv, expected_argv, expected_options) - end - end - - def test_required_argument_missing - options = %w[--xxx --xx --x -x --aaa --aa --a -a] - options.each do |option| - argv = [option] - e = assert_raise(GetoptLong::MissingArgument) do - verify(argv, [], []) - end - assert_match('requires an argument', e.message) - end - end - - def test_optional_argument - expected_options = [ - '--yyy: arg' - ] - expected_argv = %w[foo bar] - options = %w[--yyy --y --y -y --bbb --bb --b -b] - options.each do |option| - argv = ['foo', 'bar', option, 'arg'] - verify(argv, expected_argv, expected_options) - end - end - - def test_optional_argument_missing - expected_options = [ - '--yyy: ' - ] - expected_argv = %w[foo bar] - options = %w[--yyy --y --y -y --bbb --bb --b -b] - options.each do |option| - argv = ['foo', 'bar', option] - verify(argv, expected_argv, expected_options) - end - end - - def test_no_argument - expected_options = [ - '--zzz: ' - ] - expected_argv = %w[foo bar] - options = %w[--zzz --zz --z -z --ccc --cc --c -c] - options.each do |option| - argv = ['foo', option, 'bar'] - verify(argv, expected_argv, expected_options) - end - end - - def test_new_with_empty_array - e = assert_raise(ArgumentError) do - GetoptLong.new([]) - end - assert_match(/no argument-flag/, e.message) - end - - def test_new_with_bad_array - e = assert_raise(ArgumentError) do - GetoptLong.new('foo') - end - assert_match(/option list contains non-Array argument/, e.message) - end - - def test_new_with_empty_subarray - e = assert_raise(ArgumentError) do - GetoptLong.new([[]]) - end - assert_match(/no argument-flag/, e.message) - end - - def test_new_with_bad_subarray - e = assert_raise(ArgumentError) do - GetoptLong.new([1]) - end - assert_match(/no option name/, e.message) - end - - def test_new_with_invalid_option - invalid_options = %w[verbose -verbose -- +] - invalid_options.each do |invalid_option| - e = assert_raise(ArgumentError, invalid_option.to_s) do - arguments = [ - [invalid_option, '-v', GetoptLong::NO_ARGUMENT] - ] - GetoptLong.new(*arguments) - end - assert_match(/invalid option/, e.message) - end - end - - def test_new_with_invalid_alias - invalid_aliases = %w[v - -- +] - invalid_aliases.each do |invalid_alias| - e = assert_raise(ArgumentError, invalid_alias.to_s) do - arguments = [ - ['--verbose', invalid_alias, GetoptLong::NO_ARGUMENT] - ] - GetoptLong.new(*arguments) - end - assert_match(/invalid option/, e.message) - end - end - - def test_new_with_invalid_flag - invalid_flags = ['foo'] - invalid_flags.each do |invalid_flag| - e = assert_raise(ArgumentError, invalid_flag.to_s) do - arguments = [ - ['--verbose', '-v', invalid_flag] - ] - GetoptLong.new(*arguments) - end - assert_match(/no argument-flag/, e.message) - end - end - -end From b3ff564967e2752e7b3f95b30581e57e5d195656 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 11 Jan 2024 14:17:53 +0900 Subject: [PATCH 151/640] spec/mspec/tool/wrap_with_guard.rb 'ruby_version_is ""..."3.4"' spec/ruby/library/getoptlong/**/*.rb --- .../library/getoptlong/each_option_spec.rb | 11 +- spec/ruby/library/getoptlong/each_spec.rb | 11 +- .../library/getoptlong/error_message_spec.rb | 35 ++-- .../library/getoptlong/get_option_spec.rb | 11 +- spec/ruby/library/getoptlong/get_spec.rb | 11 +- .../library/getoptlong/initialize_spec.rb | 41 ++--- spec/ruby/library/getoptlong/ordering_spec.rb | 57 +++---- .../library/getoptlong/set_options_spec.rb | 151 +++++++++--------- .../ruby/library/getoptlong/terminate_spec.rb | 47 +++--- .../library/getoptlong/terminated_spec.rb | 23 +-- 10 files changed, 214 insertions(+), 184 deletions(-) diff --git a/spec/ruby/library/getoptlong/each_option_spec.rb b/spec/ruby/library/getoptlong/each_option_spec.rb index c6d82af86d4107..87dd825264c4d6 100644 --- a/spec/ruby/library/getoptlong/each_option_spec.rb +++ b/spec/ruby/library/getoptlong/each_option_spec.rb @@ -1,7 +1,10 @@ require_relative '../../spec_helper' -require 'getoptlong' -require_relative 'shared/each' -describe "GetoptLong#each_option" do - it_behaves_like :getoptlong_each, :each_option +ruby_version_is ""..."3.4" do + require 'getoptlong' + require_relative 'shared/each' + + describe "GetoptLong#each_option" do + it_behaves_like :getoptlong_each, :each_option + end end diff --git a/spec/ruby/library/getoptlong/each_spec.rb b/spec/ruby/library/getoptlong/each_spec.rb index d9022f02af2ace..d40b17d8cb6055 100644 --- a/spec/ruby/library/getoptlong/each_spec.rb +++ b/spec/ruby/library/getoptlong/each_spec.rb @@ -1,7 +1,10 @@ require_relative '../../spec_helper' -require 'getoptlong' -require_relative 'shared/each' -describe "GetoptLong#each" do - it_behaves_like :getoptlong_each, :each +ruby_version_is ""..."3.4" do + require 'getoptlong' + require_relative 'shared/each' + + describe "GetoptLong#each" do + it_behaves_like :getoptlong_each, :each + end end diff --git a/spec/ruby/library/getoptlong/error_message_spec.rb b/spec/ruby/library/getoptlong/error_message_spec.rb index 1ed9419f6cc7df..bcca728720be20 100644 --- a/spec/ruby/library/getoptlong/error_message_spec.rb +++ b/spec/ruby/library/getoptlong/error_message_spec.rb @@ -1,23 +1,26 @@ require_relative '../../spec_helper' -require 'getoptlong' -describe "GetoptLong#error_message" do - it "returns nil if no error occurred" do - opts = GetoptLong.new - opts.error_message.should == nil - end +ruby_version_is ""..."3.4" do + require 'getoptlong' - it "returns the error message of the last error that occurred" do - argv [] do + describe "GetoptLong#error_message" do + it "returns nil if no error occurred" do opts = GetoptLong.new - opts.quiet = true - opts.get - -> { - opts.ordering = GetoptLong::PERMUTE - }.should raise_error(ArgumentError) { |e| - e.message.should == "argument error" - opts.error_message.should == "argument error" - } + opts.error_message.should == nil + end + + it "returns the error message of the last error that occurred" do + argv [] do + opts = GetoptLong.new + opts.quiet = true + opts.get + -> { + opts.ordering = GetoptLong::PERMUTE + }.should raise_error(ArgumentError) { |e| + e.message.should == "argument error" + opts.error_message.should == "argument error" + } + end end end end diff --git a/spec/ruby/library/getoptlong/get_option_spec.rb b/spec/ruby/library/getoptlong/get_option_spec.rb index 3cb20443796f0e..f8f81bce50ec2d 100644 --- a/spec/ruby/library/getoptlong/get_option_spec.rb +++ b/spec/ruby/library/getoptlong/get_option_spec.rb @@ -1,7 +1,10 @@ require_relative '../../spec_helper' -require 'getoptlong' -require_relative 'shared/get' -describe "GetoptLong#get_option" do - it_behaves_like :getoptlong_get, :get_option +ruby_version_is ""..."3.4" do + require 'getoptlong' + require_relative 'shared/get' + + describe "GetoptLong#get_option" do + it_behaves_like :getoptlong_get, :get_option + end end diff --git a/spec/ruby/library/getoptlong/get_spec.rb b/spec/ruby/library/getoptlong/get_spec.rb index a8ec586fc9d115..bb901dff786a9d 100644 --- a/spec/ruby/library/getoptlong/get_spec.rb +++ b/spec/ruby/library/getoptlong/get_spec.rb @@ -1,7 +1,10 @@ require_relative '../../spec_helper' -require 'getoptlong' -require_relative 'shared/get' -describe "GetoptLong#get" do - it_behaves_like :getoptlong_get, :get +ruby_version_is ""..."3.4" do + require 'getoptlong' + require_relative 'shared/get' + + describe "GetoptLong#get" do + it_behaves_like :getoptlong_get, :get + end end diff --git a/spec/ruby/library/getoptlong/initialize_spec.rb b/spec/ruby/library/getoptlong/initialize_spec.rb index 782edbd981c544..f0e5d605b263ad 100644 --- a/spec/ruby/library/getoptlong/initialize_spec.rb +++ b/spec/ruby/library/getoptlong/initialize_spec.rb @@ -1,28 +1,31 @@ require_relative '../../spec_helper' -require 'getoptlong' -describe "GetoptLong#initialize" do - it "sets ordering to REQUIRE_ORDER if ENV['POSIXLY_CORRECT'] is set" do - begin - old_env_value = ENV["POSIXLY_CORRECT"] - ENV["POSIXLY_CORRECT"] = "" +ruby_version_is ""..."3.4" do + require 'getoptlong' - opt = GetoptLong.new - opt.ordering.should == GetoptLong::REQUIRE_ORDER - ensure - ENV["POSIXLY_CORRECT"] = old_env_value + describe "GetoptLong#initialize" do + it "sets ordering to REQUIRE_ORDER if ENV['POSIXLY_CORRECT'] is set" do + begin + old_env_value = ENV["POSIXLY_CORRECT"] + ENV["POSIXLY_CORRECT"] = "" + + opt = GetoptLong.new + opt.ordering.should == GetoptLong::REQUIRE_ORDER + ensure + ENV["POSIXLY_CORRECT"] = old_env_value + end end - end - it "sets ordering to PERMUTE if ENV['POSIXLY_CORRECT'] is not set" do - begin - old_env_value = ENV["POSIXLY_CORRECT"] - ENV["POSIXLY_CORRECT"] = nil + it "sets ordering to PERMUTE if ENV['POSIXLY_CORRECT'] is not set" do + begin + old_env_value = ENV["POSIXLY_CORRECT"] + ENV["POSIXLY_CORRECT"] = nil - opt = GetoptLong.new - opt.ordering.should == GetoptLong::PERMUTE - ensure - ENV["POSIXLY_CORRECT"] = old_env_value + opt = GetoptLong.new + opt.ordering.should == GetoptLong::PERMUTE + ensure + ENV["POSIXLY_CORRECT"] = old_env_value + end end end end diff --git a/spec/ruby/library/getoptlong/ordering_spec.rb b/spec/ruby/library/getoptlong/ordering_spec.rb index 695d1cafa7511f..b0b5b9be54f035 100644 --- a/spec/ruby/library/getoptlong/ordering_spec.rb +++ b/spec/ruby/library/getoptlong/ordering_spec.rb @@ -1,38 +1,41 @@ require_relative '../../spec_helper' -require 'getoptlong' -describe "GetoptLong#ordering=" do - it "raises an ArgumentError if called after processing has started" do - argv [ "--size", "10k", "--verbose" ] do - opts = GetoptLong.new([ '--size', GetoptLong::REQUIRED_ARGUMENT ], - [ '--verbose', GetoptLong::NO_ARGUMENT ]) - opts.quiet = true - opts.get +ruby_version_is ""..."3.4" do + require 'getoptlong' - -> { - opts.ordering = GetoptLong::PERMUTE - }.should raise_error(ArgumentError) + describe "GetoptLong#ordering=" do + it "raises an ArgumentError if called after processing has started" do + argv [ "--size", "10k", "--verbose" ] do + opts = GetoptLong.new([ '--size', GetoptLong::REQUIRED_ARGUMENT ], + [ '--verbose', GetoptLong::NO_ARGUMENT ]) + opts.quiet = true + opts.get + + -> { + opts.ordering = GetoptLong::PERMUTE + }.should raise_error(ArgumentError) + end end - end - it "raises an ArgumentError if given an invalid value" do - opts = GetoptLong.new + it "raises an ArgumentError if given an invalid value" do + opts = GetoptLong.new - -> { - opts.ordering = 12345 - }.should raise_error(ArgumentError) - end + -> { + opts.ordering = 12345 + }.should raise_error(ArgumentError) + end - it "does not allow changing ordering to PERMUTE if ENV['POSIXLY_CORRECT'] is set" do - begin - old_env_value = ENV['POSIXLY_CORRECT'] - ENV['POSIXLY_CORRECT'] = "" + it "does not allow changing ordering to PERMUTE if ENV['POSIXLY_CORRECT'] is set" do + begin + old_env_value = ENV['POSIXLY_CORRECT'] + ENV['POSIXLY_CORRECT'] = "" - opts = GetoptLong.new - opts.ordering = GetoptLong::PERMUTE - opts.ordering.should == GetoptLong::REQUIRE_ORDER - ensure - ENV['POSIXLY_CORRECT'] = old_env_value + opts = GetoptLong.new + opts.ordering = GetoptLong::PERMUTE + opts.ordering.should == GetoptLong::REQUIRE_ORDER + ensure + ENV['POSIXLY_CORRECT'] = old_env_value + end end end end diff --git a/spec/ruby/library/getoptlong/set_options_spec.rb b/spec/ruby/library/getoptlong/set_options_spec.rb index 36b9c579c41d9c..0e77696a9515d1 100644 --- a/spec/ruby/library/getoptlong/set_options_spec.rb +++ b/spec/ruby/library/getoptlong/set_options_spec.rb @@ -1,98 +1,101 @@ require_relative '../../spec_helper' -require 'getoptlong' -describe "GetoptLong#set_options" do - before :each do - @opts = GetoptLong.new - end +ruby_version_is ""..."3.4" do + require 'getoptlong' + + describe "GetoptLong#set_options" do + before :each do + @opts = GetoptLong.new + end - it "allows setting command line options" do - argv ["--size", "10k", "-v", "arg1", "arg2"] do - @opts.set_options( - ["--size", GetoptLong::REQUIRED_ARGUMENT], - ["--verbose", "-v", GetoptLong::NO_ARGUMENT] - ) + it "allows setting command line options" do + argv ["--size", "10k", "-v", "arg1", "arg2"] do + @opts.set_options( + ["--size", GetoptLong::REQUIRED_ARGUMENT], + ["--verbose", "-v", GetoptLong::NO_ARGUMENT] + ) - @opts.get.should == ["--size", "10k"] - @opts.get.should == ["--verbose", ""] - @opts.get.should == nil + @opts.get.should == ["--size", "10k"] + @opts.get.should == ["--verbose", ""] + @opts.get.should == nil + end end - end - it "discards previously defined command line options" do - argv ["--size", "10k", "-v", "arg1", "arg2"] do - @opts.set_options( - ["--size", GetoptLong::REQUIRED_ARGUMENT], - ["--verbose", "-v", GetoptLong::NO_ARGUMENT] - ) + it "discards previously defined command line options" do + argv ["--size", "10k", "-v", "arg1", "arg2"] do + @opts.set_options( + ["--size", GetoptLong::REQUIRED_ARGUMENT], + ["--verbose", "-v", GetoptLong::NO_ARGUMENT] + ) - @opts.set_options( - ["-s", "--size", GetoptLong::REQUIRED_ARGUMENT], - ["-v", GetoptLong::NO_ARGUMENT] - ) + @opts.set_options( + ["-s", "--size", GetoptLong::REQUIRED_ARGUMENT], + ["-v", GetoptLong::NO_ARGUMENT] + ) - @opts.get.should == ["-s", "10k"] - @opts.get.should == ["-v", ""] - @opts.get.should == nil + @opts.get.should == ["-s", "10k"] + @opts.get.should == ["-v", ""] + @opts.get.should == nil + end end - end - it "raises an ArgumentError if too many argument flags where given" do - argv [] do - -> { - @opts.set_options(["--size", GetoptLong::NO_ARGUMENT, GetoptLong::REQUIRED_ARGUMENT]) - }.should raise_error(ArgumentError) + it "raises an ArgumentError if too many argument flags where given" do + argv [] do + -> { + @opts.set_options(["--size", GetoptLong::NO_ARGUMENT, GetoptLong::REQUIRED_ARGUMENT]) + }.should raise_error(ArgumentError) + end end - end - it "raises a RuntimeError if processing has already started" do - argv [] do - @opts.get - -> { - @opts.set_options() - }.should raise_error(RuntimeError) + it "raises a RuntimeError if processing has already started" do + argv [] do + @opts.get + -> { + @opts.set_options() + }.should raise_error(RuntimeError) + end end - end - it "raises an ArgumentError if no argument flag was given" do - argv [] do - -> { - @opts.set_options(["--size"]) - }.should raise_error(ArgumentError) + it "raises an ArgumentError if no argument flag was given" do + argv [] do + -> { + @opts.set_options(["--size"]) + }.should raise_error(ArgumentError) + end end - end - it "raises an ArgumentError if one of the given arguments is not an Array" do - argv [] do - -> { - @opts.set_options( - ["--size", GetoptLong::REQUIRED_ARGUMENT], - "test") - }.should raise_error(ArgumentError) + it "raises an ArgumentError if one of the given arguments is not an Array" do + argv [] do + -> { + @opts.set_options( + ["--size", GetoptLong::REQUIRED_ARGUMENT], + "test") + }.should raise_error(ArgumentError) + end end - end - it "raises an ArgumentError if the same option is given twice" do - argv [] do - -> { - @opts.set_options( - ["--size", GetoptLong::NO_ARGUMENT], - ["--size", GetoptLong::OPTIONAL_ARGUMENT]) - }.should raise_error(ArgumentError) + it "raises an ArgumentError if the same option is given twice" do + argv [] do + -> { + @opts.set_options( + ["--size", GetoptLong::NO_ARGUMENT], + ["--size", GetoptLong::OPTIONAL_ARGUMENT]) + }.should raise_error(ArgumentError) - -> { - @opts.set_options( - ["--size", GetoptLong::NO_ARGUMENT], - ["-s", "--size", GetoptLong::OPTIONAL_ARGUMENT]) - }.should raise_error(ArgumentError) + -> { + @opts.set_options( + ["--size", GetoptLong::NO_ARGUMENT], + ["-s", "--size", GetoptLong::OPTIONAL_ARGUMENT]) + }.should raise_error(ArgumentError) + end end - end - it "raises an ArgumentError if the given option is invalid" do - argv [] do - -> { - @opts.set_options(["-size", GetoptLong::NO_ARGUMENT]) - }.should raise_error(ArgumentError) + it "raises an ArgumentError if the given option is invalid" do + argv [] do + -> { + @opts.set_options(["-size", GetoptLong::NO_ARGUMENT]) + }.should raise_error(ArgumentError) + end end end end diff --git a/spec/ruby/library/getoptlong/terminate_spec.rb b/spec/ruby/library/getoptlong/terminate_spec.rb index a12d1df2ef6b88..f767fcaa0a392d 100644 --- a/spec/ruby/library/getoptlong/terminate_spec.rb +++ b/spec/ruby/library/getoptlong/terminate_spec.rb @@ -1,30 +1,33 @@ require_relative '../../spec_helper' -require 'getoptlong' -describe "GetoptLong#terminate" do - before :each do - @opts = GetoptLong.new( - [ '--size', '-s', GetoptLong::REQUIRED_ARGUMENT ], - [ '--verbose', '-v', GetoptLong::NO_ARGUMENT ], - [ '--query', '-q', GetoptLong::NO_ARGUMENT ], - [ '--check', '--valid', '-c', GetoptLong::NO_ARGUMENT ] - ) - end +ruby_version_is ""..."3.4" do + require 'getoptlong' - it "terminates option processing" do - argv [ "--size", "10k", "-v", "-q", "a.txt", "b.txt" ] do - @opts.get.should == [ "--size", "10k" ] - @opts.terminate - @opts.get.should == nil + describe "GetoptLong#terminate" do + before :each do + @opts = GetoptLong.new( + [ '--size', '-s', GetoptLong::REQUIRED_ARGUMENT ], + [ '--verbose', '-v', GetoptLong::NO_ARGUMENT ], + [ '--query', '-q', GetoptLong::NO_ARGUMENT ], + [ '--check', '--valid', '-c', GetoptLong::NO_ARGUMENT ] + ) end - end - it "returns self when option processing is terminated" do - @opts.terminate.should == @opts - end + it "terminates option processing" do + argv [ "--size", "10k", "-v", "-q", "a.txt", "b.txt" ] do + @opts.get.should == [ "--size", "10k" ] + @opts.terminate + @opts.get.should == nil + end + end - it "returns nil when option processing was already terminated" do - @opts.terminate - @opts.terminate.should == nil + it "returns self when option processing is terminated" do + @opts.terminate.should == @opts + end + + it "returns nil when option processing was already terminated" do + @opts.terminate + @opts.terminate.should == nil + end end end diff --git a/spec/ruby/library/getoptlong/terminated_spec.rb b/spec/ruby/library/getoptlong/terminated_spec.rb index 6108a7f6e908e8..06c2ce71f4e116 100644 --- a/spec/ruby/library/getoptlong/terminated_spec.rb +++ b/spec/ruby/library/getoptlong/terminated_spec.rb @@ -1,17 +1,20 @@ require_relative '../../spec_helper' -require 'getoptlong' -describe "GetoptLong#terminated?" do - it "returns true if option processing has terminated" do - argv [ "--size", "10k" ] do - opts = GetoptLong.new(["--size", GetoptLong::REQUIRED_ARGUMENT]) - opts.should_not.terminated? +ruby_version_is ""..."3.4" do + require 'getoptlong' - opts.get.should == ["--size", "10k"] - opts.should_not.terminated? + describe "GetoptLong#terminated?" do + it "returns true if option processing has terminated" do + argv [ "--size", "10k" ] do + opts = GetoptLong.new(["--size", GetoptLong::REQUIRED_ARGUMENT]) + opts.should_not.terminated? - opts.get.should == nil - opts.should.terminated? + opts.get.should == ["--size", "10k"] + opts.should_not.terminated? + + opts.get.should == nil + opts.should.terminated? + end end end end From 326288c5a578b1f853d17155fe3e00eaabaff0c6 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 11 Jan 2024 16:34:58 +0900 Subject: [PATCH 152/640] Document about getoptlong at Ruby 3.4 --- doc/maintainers.md | 7 ++----- doc/standard_library.rdoc | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/doc/maintainers.md b/doc/maintainers.md index e8790342096f21..1a3f5ec2fb8939 100644 --- a/doc/maintainers.md +++ b/doc/maintainers.md @@ -154,11 +154,6 @@ have commit right, others don't. * https://github.com/ruby/forwardable * https://rubygems.org/gems/forwardable -#### lib/getoptlong.rb -* *unmaintained* -* https://github.com/ruby/getoptlong -* https://rubygems.org/gems/getoptlong - #### lib/ipaddr.rb * Akinori MUSHA (knu) * https://github.com/ruby/ipaddr @@ -485,6 +480,8 @@ have commit right, others don't. #### mutex_m * https://github.com/ruby/mutex_m +#### lib/getoptlong.rb +* https://github.com/ruby/getoptlong ## Platform Maintainers ### mswin64 (Microsoft Windows) diff --git a/doc/standard_library.rdoc b/doc/standard_library.rdoc index d0a7ba42077036..7c102372d7169f 100644 --- a/doc/standard_library.rdoc +++ b/doc/standard_library.rdoc @@ -48,7 +48,6 @@ 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 -GetoptLong:: Parse command line options similar to the GNU C getopt_long() IPAddr:: Provides methods to manipulate IPv4 and IPv6 IP addresses IRB:: Interactive Ruby command-line tool for REPL (Read Eval Print Loop) OptionParser:: Ruby-oriented class for command-line option analysis @@ -130,3 +129,4 @@ TypeProf:: A type analysis tool for Ruby code based on abstract interpretation DEBUGGER__:: Debugging functionality for Ruby Racc:: A LALR(1) parser generator written in Ruby. Mutex_m:: Mixin to extend objects to be handled like a Mutex +GetoptLong:: Parse command line options similar to the GNU C getopt_long() From 3f5016178cb81536e800a9121b3804e36c9af93c Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 16 Jan 2024 16:30:11 +0900 Subject: [PATCH 153/640] We don't need to sync getoptlong --- tool/sync_default_gems.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb index 58e15848cc73e0..d1b761078ec03b 100755 --- a/tool/sync_default_gems.rb +++ b/tool/sync_default_gems.rb @@ -38,7 +38,6 @@ module SyncDefaultGems fileutils: 'ruby/fileutils', find: "ruby/find", forwardable: "ruby/forwardable", - getoptlong: "ruby/getoptlong", ipaddr: 'ruby/ipaddr', irb: 'ruby/irb', json: 'flori/json', From 4b6936aa047158c98a9ac8861d51e5e09229f8c0 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 16 Jan 2024 16:30:32 +0900 Subject: [PATCH 154/640] Unbundled samples for getoptlong --- sample/getoptlong/abbrev.rb | 9 ---- sample/getoptlong/aliases.rb | 8 ---- sample/getoptlong/argv.rb | 12 ------ sample/getoptlong/each.rb | 12 ------ sample/getoptlong/fibonacci.rb | 62 ---------------------------- sample/getoptlong/permute.rb | 12 ------ sample/getoptlong/require_order.rb | 13 ------ sample/getoptlong/return_in_order.rb | 13 ------ sample/getoptlong/simple.rb | 7 ---- sample/getoptlong/types.rb | 10 ----- 10 files changed, 158 deletions(-) delete mode 100644 sample/getoptlong/abbrev.rb delete mode 100644 sample/getoptlong/aliases.rb delete mode 100644 sample/getoptlong/argv.rb delete mode 100644 sample/getoptlong/each.rb delete mode 100644 sample/getoptlong/fibonacci.rb delete mode 100644 sample/getoptlong/permute.rb delete mode 100644 sample/getoptlong/require_order.rb delete mode 100644 sample/getoptlong/return_in_order.rb delete mode 100644 sample/getoptlong/simple.rb delete mode 100644 sample/getoptlong/types.rb diff --git a/sample/getoptlong/abbrev.rb b/sample/getoptlong/abbrev.rb deleted file mode 100644 index 9b89863626cc87..00000000000000 --- a/sample/getoptlong/abbrev.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'getoptlong' - -options = GetoptLong.new( - ['--xxx', GetoptLong::NO_ARGUMENT], - ['--xyz', GetoptLong::NO_ARGUMENT] -) -options.each do |option, argument| - p [option, argument] -end diff --git a/sample/getoptlong/aliases.rb b/sample/getoptlong/aliases.rb deleted file mode 100644 index 895254c6ae8550..00000000000000 --- a/sample/getoptlong/aliases.rb +++ /dev/null @@ -1,8 +0,0 @@ -require 'getoptlong' - -options = GetoptLong.new( - ['--xxx', '-x', '--aaa', '-a', '-p', GetoptLong::NO_ARGUMENT] -) -options.each do |option, argument| - p [option, argument] -end diff --git a/sample/getoptlong/argv.rb b/sample/getoptlong/argv.rb deleted file mode 100644 index 8efcad22ea6fbe..00000000000000 --- a/sample/getoptlong/argv.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'getoptlong' - -options = GetoptLong.new( - ['--xxx', GetoptLong::REQUIRED_ARGUMENT], - ['--yyy', GetoptLong::OPTIONAL_ARGUMENT], - ['--zzz', GetoptLong::NO_ARGUMENT] -) -puts "Original ARGV: #{ARGV}" -options.each do |option, argument| - p [option, argument] -end -puts "Remaining ARGV: #{ARGV}" diff --git a/sample/getoptlong/each.rb b/sample/getoptlong/each.rb deleted file mode 100644 index 661e0a968f33b5..00000000000000 --- a/sample/getoptlong/each.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'getoptlong' - -options = GetoptLong.new( - ['--xxx', '-x', GetoptLong::REQUIRED_ARGUMENT], - ['--yyy', '-y', GetoptLong::OPTIONAL_ARGUMENT], - ['--zzz', '-z',GetoptLong::NO_ARGUMENT] -) -puts "Original ARGV: #{ARGV}" -options.each do |option, argument| - p [option, argument] -end -puts "Remaining ARGV: #{ARGV}" diff --git a/sample/getoptlong/fibonacci.rb b/sample/getoptlong/fibonacci.rb deleted file mode 100644 index 24a2aab3c35e72..00000000000000 --- a/sample/getoptlong/fibonacci.rb +++ /dev/null @@ -1,62 +0,0 @@ -require 'getoptlong' - -options = GetoptLong.new( - ['--number', '-n', GetoptLong::REQUIRED_ARGUMENT], - ['--verbose', '-v', GetoptLong::OPTIONAL_ARGUMENT], - ['--help', '-h', GetoptLong::NO_ARGUMENT] -) - -def help(status = 0) - puts <<~HELP - Usage: - - -n n, --number n: - Compute Fibonacci number for n. - -v [boolean], --verbose [boolean]: - Show intermediate results; default is 'false'. - -h, --help: - Show this help. - HELP - exit(status) -end - -def print_fibonacci (number) - return 0 if number == 0 - return 1 if number == 1 or number == 2 - i = 0 - j = 1 - (2..number).each do - k = i + j - i = j - j = k - puts j if @verbose - end - puts j unless @verbose -end - -options.each do |option, argument| - case option - when '--number' - @number = argument.to_i - when '--verbose' - @verbose = if argument.empty? - true - elsif argument.match(/true/i) - true - elsif argument.match(/false/i) - false - else - puts '--verbose argument must be true or false' - help(255) - end - when '--help' - help - end -end - -unless @number - puts 'Option --number is required.' - help(255) -end - -print_fibonacci(@number) diff --git a/sample/getoptlong/permute.rb b/sample/getoptlong/permute.rb deleted file mode 100644 index 8efcad22ea6fbe..00000000000000 --- a/sample/getoptlong/permute.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'getoptlong' - -options = GetoptLong.new( - ['--xxx', GetoptLong::REQUIRED_ARGUMENT], - ['--yyy', GetoptLong::OPTIONAL_ARGUMENT], - ['--zzz', GetoptLong::NO_ARGUMENT] -) -puts "Original ARGV: #{ARGV}" -options.each do |option, argument| - p [option, argument] -end -puts "Remaining ARGV: #{ARGV}" diff --git a/sample/getoptlong/require_order.rb b/sample/getoptlong/require_order.rb deleted file mode 100644 index 357f667905755e..00000000000000 --- a/sample/getoptlong/require_order.rb +++ /dev/null @@ -1,13 +0,0 @@ -require 'getoptlong' - -options = GetoptLong.new( - ['--xxx', GetoptLong::REQUIRED_ARGUMENT], - ['--yyy', GetoptLong::OPTIONAL_ARGUMENT], - ['--zzz', GetoptLong::NO_ARGUMENT] -) -options.ordering = GetoptLong::REQUIRE_ORDER -puts "Original ARGV: #{ARGV}" -options.each do |option, argument| - p [option, argument] -end -puts "Remaining ARGV: #{ARGV}" diff --git a/sample/getoptlong/return_in_order.rb b/sample/getoptlong/return_in_order.rb deleted file mode 100644 index 91ce1ef9963d12..00000000000000 --- a/sample/getoptlong/return_in_order.rb +++ /dev/null @@ -1,13 +0,0 @@ -require 'getoptlong' - -options = GetoptLong.new( - ['--xxx', GetoptLong::REQUIRED_ARGUMENT], - ['--yyy', GetoptLong::OPTIONAL_ARGUMENT], - ['--zzz', GetoptLong::NO_ARGUMENT] -) -options.ordering = GetoptLong::RETURN_IN_ORDER -puts "Original ARGV: #{ARGV}" -options.each do |option, argument| - p [option, argument] -end -puts "Remaining ARGV: #{ARGV}" diff --git a/sample/getoptlong/simple.rb b/sample/getoptlong/simple.rb deleted file mode 100644 index 1af6447632e3f6..00000000000000 --- a/sample/getoptlong/simple.rb +++ /dev/null @@ -1,7 +0,0 @@ -require 'getoptlong' - -options = GetoptLong.new( - ['--number', '-n', GetoptLong::REQUIRED_ARGUMENT], - ['--verbose', '-v', GetoptLong::OPTIONAL_ARGUMENT], - ['--help', '-h', GetoptLong::NO_ARGUMENT] -) diff --git a/sample/getoptlong/types.rb b/sample/getoptlong/types.rb deleted file mode 100644 index ac74bfe12ed133..00000000000000 --- a/sample/getoptlong/types.rb +++ /dev/null @@ -1,10 +0,0 @@ -require 'getoptlong' - -options = GetoptLong.new( - ['--xxx', GetoptLong::REQUIRED_ARGUMENT], - ['--yyy', GetoptLong::OPTIONAL_ARGUMENT], - ['--zzz', GetoptLong::NO_ARGUMENT] -) -options.each do |option, argument| - p [option, argument] -end From ee405518d4ce50e15a16bafc315616badf7e2e60 Mon Sep 17 00:00:00 2001 From: git Date: Tue, 16 Jan 2024 08:07:41 +0000 Subject: [PATCH 155/640] Update bundled gems list at 4b6936aa047158c98a9ac8861d51e5 [ci skip] --- NEWS.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index be0c14797e316e..f277eafa2c1298 100644 --- a/NEWS.md +++ b/NEWS.md @@ -43,9 +43,10 @@ The following bundled gems are updated. * typeprof 0.21.9 * debug 1.9.1 -The following bundled gem is promoted from default gems. +The following bundled gems are promoted from default gems. * mutex_m 0.2.0 +* getoptlong 0.2.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. From 9f02680015d21013fa83587d8c912d2af621bb57 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 16 Jan 2024 17:09:04 +0900 Subject: [PATCH 156/640] Removed sample code for net-imap. net-imap is alread extracted as bundled gems --- sample/net-imap.rb | 167 --------------------------------------------- 1 file changed, 167 deletions(-) delete mode 100644 sample/net-imap.rb diff --git a/sample/net-imap.rb b/sample/net-imap.rb deleted file mode 100644 index b93ecb746e6996..00000000000000 --- a/sample/net-imap.rb +++ /dev/null @@ -1,167 +0,0 @@ -require 'net/imap' -require "getoptlong" - -$stdout.sync = true -$port = nil -$user = ENV["USER"] || ENV["LOGNAME"] -$auth = "login" -$ssl = false -$starttls = false - -def usage - < - - --help print this message - --port=PORT specifies port - --user=USER specifies user - --auth=AUTH specifies auth type - --starttls use starttls - --ssl use ssl -EOF -end - -begin - require 'io/console' -rescue LoadError - def _noecho(&block) - system("stty", "-echo") - begin - yield STDIN - ensure - system("stty", "echo") - end - end -else - def _noecho(&block) - STDIN.noecho(&block) - end -end - -def get_password - print "password: " - begin - return _noecho(&:gets).chomp - ensure - puts - end -end - -def get_command - printf("%s@%s> ", $user, $host) - if line = gets - return line.strip.split(/\s+/) - else - return nil - end -end - -parser = GetoptLong.new -parser.set_options(['--debug', GetoptLong::NO_ARGUMENT], - ['--help', GetoptLong::NO_ARGUMENT], - ['--port', GetoptLong::REQUIRED_ARGUMENT], - ['--user', GetoptLong::REQUIRED_ARGUMENT], - ['--auth', GetoptLong::REQUIRED_ARGUMENT], - ['--starttls', GetoptLong::NO_ARGUMENT], - ['--ssl', GetoptLong::NO_ARGUMENT]) -begin - parser.each_option do |name, arg| - case name - when "--port" - $port = arg - when "--user" - $user = arg - when "--auth" - $auth = arg - when "--ssl" - $ssl = true - when "--starttls" - $starttls = true - when "--debug" - Net::IMAP.debug = true - when "--help" - usage - exit - end - end -rescue - abort usage -end - -$host = ARGV.shift -unless $host - abort usage -end - -imap = Net::IMAP.new($host, :port => $port, :ssl => $ssl) -begin - imap.starttls if $starttls - class << password = method(:get_password) - alias to_str call - end - imap.authenticate($auth, $user, password) - while true - cmd, *args = get_command - break unless cmd - begin - case cmd - when "list" - for mbox in imap.list("", args[0] || "*") - if mbox.attr.include?(Net::IMAP::NOSELECT) - prefix = "!" - elsif mbox.attr.include?(Net::IMAP::MARKED) - prefix = "*" - else - prefix = " " - end - print prefix, mbox.name, "\n" - end - when "select" - imap.select(args[0] || "inbox") - print "ok\n" - when "close" - imap.close - print "ok\n" - when "summary" - unless messages = imap.responses["EXISTS"][-1] - puts "not selected" - next - end - if messages > 0 - for data in imap.fetch(1..-1, ["ENVELOPE"]) - print data.seqno, ": ", data.attr["ENVELOPE"].subject, "\n" - end - else - puts "no message" - end - when "fetch" - if args[0] - data = imap.fetch(args[0].to_i, ["RFC822.HEADER", "RFC822.TEXT"])[0] - puts data.attr["RFC822.HEADER"] - puts data.attr["RFC822.TEXT"] - else - puts "missing argument" - end - when "logout", "exit", "quit" - break - when "help", "?" - print < Date: Tue, 16 Jan 2024 20:29:06 +0900 Subject: [PATCH 157/640] Set `CHECK_LEAKS` in spec/default.mspec Because of `.NOEXPORT:` in template/Makefile.in, variables in common.mk will not be exported. --- common.mk | 3 --- spec/default.mspec | 4 ++++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/common.mk b/common.mk index 24481b035a7d91..c4b6dec1533680 100644 --- a/common.mk +++ b/common.mk @@ -43,9 +43,6 @@ RUBYLIB = $(PATH_SEPARATOR) RUBYOPT = - RUN_OPTS = --disable-gems -# Enabld leakcheckers by ruby/mspec -CHECK_LEAKS = true - # GITPULLOPTIONS = --no-tags PRISM_SRCDIR = $(srcdir)/prism diff --git a/spec/default.mspec b/spec/default.mspec index e2ad19e1173ade..3b5024f0c6f088 100644 --- a/spec/default.mspec +++ b/spec/default.mspec @@ -3,6 +3,10 @@ $VERBOSE = false if (opt = ENV["RUBYOPT"]) and (opt = opt.dup).sub!(/(?:\A|\s)-w(?=\z|\s)/, '') ENV["RUBYOPT"] = opt end + +# Enabld leakcheckers by ruby/mspec +ENV["CHECK_LEAKS"] ||= "true" + require "./rbconfig" unless defined?(RbConfig) require_relative "../tool/test-coverage" if ENV.key?("COVERAGE") load File.dirname(__FILE__) + '/ruby/default.mspec' From d6b6e14c87d5c956dd92287e01d48cf1c2ca4301 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Tue, 16 Jan 2024 22:13:16 +0900 Subject: [PATCH 158/640] Specify ruby mode [ci skip] --- spec/ruby/default.mspec | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/ruby/default.mspec b/spec/ruby/default.mspec index a0dc69c03d30e4..1e8f8893aa1f9c 100644 --- a/spec/ruby/default.mspec +++ b/spec/ruby/default.mspec @@ -1,3 +1,4 @@ +# -*- ruby -*- # Configuration file for Ruby >= 2.0 implementations. class MSpecScript From 0520e9675b91ea559da1ae5eda9db378fbdbca52 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 15 Jan 2024 15:08:39 -0500 Subject: [PATCH 159/640] [PRISM] Fix defined? for chained calls Fixes ruby/prism#2148. --- prism_compile.c | 6 ++++-- test/ruby/test_compile_prism.rb | 9 +++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 38fbbb443a4fea..6a0d56c051ee68 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2607,8 +2607,10 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co pm_compile_defined_expr0(iseq, call_node->receiver, ret, src, popped, scope_node, dummy_line_node, lineno, true, lfinish, true); if (PM_NODE_TYPE_P(call_node->receiver, PM_CALL_NODE)) { ADD_INSNL(ret, &dummy_line_node, branchunless, lfinish[2]); - ID method_id = pm_constant_id_lookup(scope_node, call_node->name); - pm_compile_call(iseq, (const pm_call_node_t *)call_node->receiver, ret, src, popped, scope_node, method_id, NULL); + + const pm_call_node_t *receiver = (const pm_call_node_t *)call_node->receiver; + ID method_id = pm_constant_id_lookup(scope_node, receiver->name); + pm_compile_call(iseq, receiver, ret, src, popped, scope_node, method_id, NULL); } else { ADD_INSNL(ret, &dummy_line_node, branchunless, lfinish[1]); diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index b6ff666fb9af68..3b33908c5243d5 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -209,6 +209,15 @@ def test_DefinedNode assert_prism_eval("defined?(a(itself))") assert_prism_eval("defined?(itself(itself))") + + # Method chain on a constant + assert_prism_eval(<<~RUBY) + class PrismDefinedNode + def m1; end + end + + defined?(PrismDefinedNode.new.m1) + RUBY end def test_GlobalVariableReadNode From ade56737e2273847426214035c0ff2340b43799a Mon Sep 17 00:00:00 2001 From: tompng Date: Tue, 16 Jan 2024 02:44:53 +0900 Subject: [PATCH 160/640] Fix coderange of invalid_encoding_string.<<(ord) Appending valid encoding character can change coderange from invalid to valid. Example: "\x95".force_encoding('sjis')<<0x5C will be a valid string "\x{955C}" --- string.c | 6 +++++- test/ruby/test_string.rb | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/string.c b/string.c index bb830fc06c7bbc..5eda835f4b36a3 100644 --- a/string.c +++ b/string.c @@ -3522,8 +3522,12 @@ rb_str_concat(VALUE str1, VALUE str2) } rb_str_resize(str1, pos+len); memcpy(RSTRING_PTR(str1) + pos, buf, len); - if (cr == ENC_CODERANGE_7BIT && code > 127) + if (cr == ENC_CODERANGE_7BIT && code > 127) { cr = ENC_CODERANGE_VALID; + } + else if (cr == ENC_CODERANGE_BROKEN) { + cr = ENC_CODERANGE_UNKNOWN; + } ENC_CODERANGE_SET(str1, cr); } return str1; diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb index 4aa119f8fd139e..42f2544b5a8692 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -301,6 +301,9 @@ def test_LSHIFT # '<<' assert_raise(RangeError, bug) {S("a".force_encoding(Encoding::UTF_8)) << -1} assert_raise(RangeError, bug) {S("a".force_encoding(Encoding::UTF_8)) << 0x81308130} assert_nothing_raised {S("a".force_encoding(Encoding::GB18030)) << 0x81308130} + + s = "\x95".force_encoding(Encoding::SJIS).tap(&:valid_encoding?) + assert_predicate(s << 0x5c, :valid_encoding?) end def test_MATCH # '=~' From 3d45b743e4beccb3ec176ede0f52102ff3795b03 Mon Sep 17 00:00:00 2001 From: Matt Valentine-House Date: Mon, 15 Jan 2024 20:41:37 +0000 Subject: [PATCH 161/640] Replace pm_lookup_local_index with lookup_local_index_with_depth --- prism_compile.c | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 6a0d56c051ee68..1ef8ff637baf2f 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -813,18 +813,6 @@ pm_lookup_local_index_any_scope(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm return scope_node->local_table_for_iseq_size - (int)local_index; } -static int -pm_lookup_local_index(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm_constant_id_t constant_id) -{ - st_data_t local_index; - - if (!st_lookup(scope_node->index_lookup_table, constant_id, &local_index)) { - rb_bug("Local with constant_id %u does not exist", (unsigned int)constant_id); - } - - return scope_node->local_table_for_iseq_size - (int)local_index; -} - static int pm_lookup_local_index_with_depth(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm_constant_id_t constant_id, uint32_t depth) { @@ -2129,7 +2117,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t // of a pattern. For example, foo in bar. This results in the value // being matched being written to that local variable. pm_local_variable_target_node_t *cast = (pm_local_variable_target_node_t *) node; - int index = pm_lookup_local_index(iseq, scope_node, cast->name); + int index = pm_lookup_local_index_with_depth(iseq, scope_node, cast->name, 0); // If this local variable is being written from within an alternation // pattern, then it cannot actually be added to the local table since @@ -5137,7 +5125,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_TARGET_NODE)); pm_local_variable_target_node_t *local_target = (pm_local_variable_target_node_t *) target; - int index = pm_lookup_local_index(iseq, scope_node, local_target->name); + int index = pm_lookup_local_index_with_depth(iseq, scope_node, local_target->name, 0); ADD_INSN1(ret, &dummy_line_node, putobject, rb_id2sym(pm_constant_id_lookup(scope_node, local_target->name))); ADD_SEND(ret, &dummy_line_node, idAREF, INT2FIX(1)); @@ -5154,7 +5142,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_TARGET_NODE)); pm_local_variable_target_node_t *local_target = (pm_local_variable_target_node_t *) target; - int index = pm_lookup_local_index(iseq, scope_node, local_target->name); + int index = pm_lookup_local_index_with_depth(iseq, scope_node, local_target->name, 0); if (((size_t) targets_index) < (targets_count - 1)) { PM_DUP; @@ -5177,7 +5165,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_TARGET_NODE)); pm_local_variable_target_node_t *local_target = (pm_local_variable_target_node_t *) target; - int index = pm_lookup_local_index(iseq, scope_node, local_target->name); + int index = pm_lookup_local_index_with_depth(iseq, scope_node, local_target->name, 0); PM_PUTNIL; ADD_SETLOCAL(ret, &dummy_line_node, index, (int) local_target->depth); @@ -5214,7 +5202,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } case PM_REQUIRED_PARAMETER_NODE: { pm_required_parameter_node_t *required_parameter_node = (pm_required_parameter_node_t *)node; - int index = pm_lookup_local_index(iseq, scope_node, required_parameter_node->name); + int index = pm_lookup_local_index_with_depth(iseq, scope_node, required_parameter_node->name, 0); ADD_SETLOCAL(ret, &dummy_line_node, index, 0); return; @@ -5475,7 +5463,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_optional_parameter_node_t *optional_parameter_node = (pm_optional_parameter_node_t *)node; PM_COMPILE_NOT_POPPED(optional_parameter_node->value); - int index = pm_lookup_local_index(iseq, scope_node, optional_parameter_node->name); + int index = pm_lookup_local_index_with_depth(iseq, scope_node, optional_parameter_node->name, 0); ADD_SETLOCAL(ret, &dummy_line_node, index, 0); @@ -6426,7 +6414,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, PM_NODE_TYPE_P(value, PM_RANGE_NODE)) { LABEL *end_label = NEW_LABEL(nd_line(&dummy_line_node)); - int index = pm_lookup_local_index(iseq, scope_node, name); + int index = pm_lookup_local_index_with_depth(iseq, scope_node, name, 0); int kw_bits_idx = table_size - body->param.keyword->bits_start; ADD_INSN2(ret, &dummy_line_node, checkkeyword, INT2FIX(kw_bits_idx + VM_ENV_DATA_SIZE - 1), INT2FIX(i)); ADD_INSNL(ret, &dummy_line_node, branchif, end_label); From f4b299a1ed036234c0144797acba555c9feb3c6e Mon Sep 17 00:00:00 2001 From: Matt Valentine-House Date: Mon, 15 Jan 2024 20:59:11 +0000 Subject: [PATCH 162/640] Bind index & depth together into pm_local_index_t --- prism_compile.c | 59 +++++++++++++++++++++++++++---------------------- prism_compile.h | 12 ++++++++++ 2 files changed, 44 insertions(+), 27 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 1ef8ff637baf2f..9d92017bebfd92 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -813,15 +813,20 @@ pm_lookup_local_index_any_scope(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm return scope_node->local_table_for_iseq_size - (int)local_index; } -static int +static pm_local_index_t pm_lookup_local_index_with_depth(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm_constant_id_t constant_id, uint32_t depth) { + pm_local_index_t lindex = {0}; + for(uint32_t i = 0; i < depth; i++) { scope_node = scope_node->previous; iseq = (rb_iseq_t *)ISEQ_BODY(iseq)->parent_iseq; } - return pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, NULL); + lindex.level = (int)depth; + lindex.index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, NULL); + + return lindex; } // This returns the CRuby ID which maps to the pm_constant_id_t @@ -2117,7 +2122,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t // of a pattern. For example, foo in bar. This results in the value // being matched being written to that local variable. pm_local_variable_target_node_t *cast = (pm_local_variable_target_node_t *) node; - int index = pm_lookup_local_index_with_depth(iseq, scope_node, cast->name, 0); + pm_local_index_t index = pm_lookup_local_index_with_depth(iseq, scope_node, cast->name, cast->depth); // If this local variable is being written from within an alternation // pattern, then it cannot actually be added to the local table since @@ -2133,7 +2138,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t } } - ADD_SETLOCAL(ret, &line.node, index, (int) cast->depth); + ADD_SETLOCAL(ret, &line.node, index.index, index.level); ADD_INSNL(ret, &line.node, jump, matched_label); break; } @@ -4887,8 +4892,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_constant_id_t constant_id = local_variable_and_write_node->name; int depth = local_variable_and_write_node->depth + scope_node->local_depth_offset; - int local_index = pm_lookup_local_index_with_depth(iseq, scope_node, constant_id, depth); - ADD_GETLOCAL(ret, &dummy_line_node, local_index, depth); + pm_local_index_t local_index = pm_lookup_local_index_with_depth(iseq, scope_node, constant_id, depth); + ADD_GETLOCAL(ret, &dummy_line_node, local_index.index, local_index.level); PM_DUP_UNLESS_POPPED; @@ -4900,7 +4905,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, PM_DUP_UNLESS_POPPED; - ADD_SETLOCAL(ret, &dummy_line_node, local_index, depth); + ADD_SETLOCAL(ret, &dummy_line_node, local_index.index, local_index.level); ADD_LABEL(ret, end_label); return; @@ -4911,8 +4916,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_constant_id_t constant_id = local_variable_operator_write_node->name; int depth = local_variable_operator_write_node->depth + scope_node->local_depth_offset; - int local_index = pm_lookup_local_index_with_depth(iseq, scope_node, constant_id, depth); - ADD_GETLOCAL(ret, &dummy_line_node, local_index, depth); + pm_local_index_t local_index = pm_lookup_local_index_with_depth(iseq, scope_node, constant_id, depth); + ADD_GETLOCAL(ret, &dummy_line_node, local_index.index, local_index.level); PM_COMPILE_NOT_POPPED(local_variable_operator_write_node->value); ID method_id = pm_constant_id_lookup(scope_node, local_variable_operator_write_node->operator); @@ -4922,7 +4927,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, PM_DUP_UNLESS_POPPED; - ADD_SETLOCAL(ret, &dummy_line_node, local_index, depth); + ADD_SETLOCAL(ret, &dummy_line_node, local_index.index, local_index.level); return; } @@ -4937,8 +4942,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_constant_id_t constant_id = local_variable_or_write_node->name; int depth = local_variable_or_write_node->depth + scope_node->local_depth_offset; - int local_index = pm_lookup_local_index_with_depth(iseq, scope_node, constant_id, depth); - ADD_GETLOCAL(ret, &dummy_line_node, local_index, depth); + pm_local_index_t local_index = pm_lookup_local_index_with_depth(iseq, scope_node, constant_id, depth); + ADD_GETLOCAL(ret, &dummy_line_node, local_index.index, local_index.level); PM_DUP_UNLESS_POPPED; @@ -4951,7 +4956,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, PM_DUP_UNLESS_POPPED; - ADD_SETLOCAL(ret, &dummy_line_node, local_index, depth); + ADD_SETLOCAL(ret, &dummy_line_node, local_index.index, local_index.level); ADD_LABEL(ret, end_label); return; @@ -4960,8 +4965,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_local_variable_read_node_t *local_read_node = (pm_local_variable_read_node_t *) node; if (!popped) { - int index = pm_lookup_local_index_with_depth(iseq, scope_node, local_read_node->name, local_read_node->depth); - ADD_GETLOCAL(ret, &dummy_line_node, index, local_read_node->depth + scope_node->local_depth_offset); + pm_local_index_t index = pm_lookup_local_index_with_depth(iseq, scope_node, local_read_node->name, local_read_node->depth); + ADD_GETLOCAL(ret, &dummy_line_node, index.index, local_read_node->depth + scope_node->local_depth_offset); } return; } @@ -5125,12 +5130,12 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_TARGET_NODE)); pm_local_variable_target_node_t *local_target = (pm_local_variable_target_node_t *) target; - int index = pm_lookup_local_index_with_depth(iseq, scope_node, local_target->name, 0); + pm_local_index_t index = pm_lookup_local_index_with_depth(iseq, scope_node, local_target->name, local_target->depth); ADD_INSN1(ret, &dummy_line_node, putobject, rb_id2sym(pm_constant_id_lookup(scope_node, local_target->name))); ADD_SEND(ret, &dummy_line_node, idAREF, INT2FIX(1)); ADD_LABEL(ret, fail_label); - ADD_SETLOCAL(ret, &dummy_line_node, index, (int) local_target->depth); + ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); PM_POP_IF_POPPED; return; } @@ -5142,14 +5147,14 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_TARGET_NODE)); pm_local_variable_target_node_t *local_target = (pm_local_variable_target_node_t *) target; - int index = pm_lookup_local_index_with_depth(iseq, scope_node, local_target->name, 0); + pm_local_index_t index = pm_lookup_local_index_with_depth(iseq, scope_node, local_target->name, local_target->depth); if (((size_t) targets_index) < (targets_count - 1)) { PM_DUP; } ADD_INSN1(ret, &dummy_line_node, putobject, rb_id2sym(pm_constant_id_lookup(scope_node, local_target->name))); ADD_SEND(ret, &dummy_line_node, idAREF, INT2FIX(1)); - ADD_SETLOCAL(ret, &dummy_line_node, index, (int) local_target->depth); + ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); } // Since we matched successfully, now we'll jump to the end. @@ -5165,10 +5170,10 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_TARGET_NODE)); pm_local_variable_target_node_t *local_target = (pm_local_variable_target_node_t *) target; - int index = pm_lookup_local_index_with_depth(iseq, scope_node, local_target->name, 0); + pm_local_index_t index = pm_lookup_local_index_with_depth(iseq, scope_node, local_target->name, local_target->depth); PM_PUTNIL; - ADD_SETLOCAL(ret, &dummy_line_node, index, (int) local_target->depth); + ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); } // Finally, we can push the end label for either case. @@ -5202,9 +5207,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } case PM_REQUIRED_PARAMETER_NODE: { pm_required_parameter_node_t *required_parameter_node = (pm_required_parameter_node_t *)node; - int index = pm_lookup_local_index_with_depth(iseq, scope_node, required_parameter_node->name, 0); + pm_local_index_t index = pm_lookup_local_index_with_depth(iseq, scope_node, required_parameter_node->name, 0); - ADD_SETLOCAL(ret, &dummy_line_node, index, 0); + ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); return; } case PM_MULTI_TARGET_NODE: { @@ -5463,9 +5468,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_optional_parameter_node_t *optional_parameter_node = (pm_optional_parameter_node_t *)node; PM_COMPILE_NOT_POPPED(optional_parameter_node->value); - int index = pm_lookup_local_index_with_depth(iseq, scope_node, optional_parameter_node->name, 0); + pm_local_index_t index = pm_lookup_local_index_with_depth(iseq, scope_node, optional_parameter_node->name, 0); - ADD_SETLOCAL(ret, &dummy_line_node, index, 0); + ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); return; } @@ -6414,12 +6419,12 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, PM_NODE_TYPE_P(value, PM_RANGE_NODE)) { LABEL *end_label = NEW_LABEL(nd_line(&dummy_line_node)); - int index = pm_lookup_local_index_with_depth(iseq, scope_node, name, 0); + pm_local_index_t index = pm_lookup_local_index_with_depth(iseq, scope_node, name, 0); int kw_bits_idx = table_size - body->param.keyword->bits_start; ADD_INSN2(ret, &dummy_line_node, checkkeyword, INT2FIX(kw_bits_idx + VM_ENV_DATA_SIZE - 1), INT2FIX(i)); ADD_INSNL(ret, &dummy_line_node, branchif, end_label); PM_COMPILE(value); - ADD_SETLOCAL(ret, &dummy_line_node, index, 0); + ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); ADD_LABEL(ret, end_label); } diff --git a/prism_compile.h b/prism_compile.h index ed0c7b4c915b01..0b3a6fb826933c 100644 --- a/prism_compile.h +++ b/prism_compile.h @@ -1,5 +1,17 @@ #include "prism/prism.h" +/** + * the getlocal and setlocal instructions require two parameters. level is how + * many hops up the iseq stack one needs to go before finding the correct local + * table. The index is the index in that table where our variable is. + * + * Because these are always calculated and used together, we'll bind them + * together as a tuple. + */ +typedef struct pm_local_index_struct { + int index, level; +} pm_local_index_t; + // ScopeNodes are helper nodes, and will never be part of the AST. We manually // declare them here to avoid generating them. typedef struct pm_scope_node { From da383c0d7496b7e65fae8da4b26ad3265175bcc8 Mon Sep 17 00:00:00 2001 From: Matt Valentine-House Date: Mon, 15 Jan 2024 21:32:17 +0000 Subject: [PATCH 163/640] Return pm_local_index_t when looking up local indexes instead of returning the index and updating found_depth in the parent scope --- prism_compile.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 9d92017bebfd92..91b21be4c04582 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -791,9 +791,14 @@ pm_interpolated_node_compile(pm_node_list_t *parts, rb_iseq_t *iseq, NODE dummy_ // This recurses through scopes and finds the local index at any scope level // It also takes a pointer to depth, and increments depth appropriately // according to the depth of the local -static int +static pm_local_index_t pm_lookup_local_index_any_scope(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm_constant_id_t constant_id, int *found_depth) { + int level = 0; + pm_local_index_t lindex = {0}; + if (found_depth) { + level = *found_depth; + } if (!scope_node) { // We have recursed up all scope nodes // and have not found the local yet @@ -805,28 +810,27 @@ pm_lookup_local_index_any_scope(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm if (!st_lookup(scope_node->index_lookup_table, constant_id, &local_index)) { // Local does not exist at this level, continue recursing up if (found_depth) { + level++; (*found_depth)++; + RUBY_ASSERT(level == *found_depth); } return pm_lookup_local_index_any_scope(iseq, scope_node->previous, constant_id, found_depth); } - return scope_node->local_table_for_iseq_size - (int)local_index; + lindex.level = level; + lindex.index = scope_node->local_table_for_iseq_size - (int)local_index; + return lindex; } static pm_local_index_t pm_lookup_local_index_with_depth(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm_constant_id_t constant_id, uint32_t depth) { - pm_local_index_t lindex = {0}; - for(uint32_t i = 0; i < depth; i++) { scope_node = scope_node->previous; iseq = (rb_iseq_t *)ISEQ_BODY(iseq)->parent_iseq; } - lindex.level = (int)depth; - lindex.index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, NULL); - - return lindex; + return pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, (int *)&depth); } // This returns the CRuby ID which maps to the pm_constant_id_t @@ -4975,9 +4979,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_constant_id_t constant_id = local_write_node->name; int found_depth = 0; - int index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, &found_depth); + pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, &found_depth); - ADD_SETLOCAL(ret, &dummy_line_node, index, found_depth); + ADD_SETLOCAL(ret, &dummy_line_node, index.index, found_depth); return; } case PM_LOCAL_VARIABLE_WRITE_NODE: { @@ -4989,9 +4993,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_constant_id_t constant_id = local_write_node->name; int found_depth = 0; - int index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, &found_depth); + pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, &found_depth); - ADD_SETLOCAL(ret, &dummy_line_node, index, found_depth); + ADD_SETLOCAL(ret, &dummy_line_node, index.index, found_depth); return; } case PM_MATCH_LAST_LINE_NODE: { From 0d705b342f27446176e0eddd1ba883dce4b20f08 Mon Sep 17 00:00:00 2001 From: Matt Valentine-House Date: Mon, 15 Jan 2024 21:42:16 +0000 Subject: [PATCH 164/640] Remove the found_depth pointer Now that we're returning pm_local_index_t --- prism_compile.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 91b21be4c04582..00fcda6b83c0eb 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -792,13 +792,14 @@ pm_interpolated_node_compile(pm_node_list_t *parts, rb_iseq_t *iseq, NODE dummy_ // It also takes a pointer to depth, and increments depth appropriately // according to the depth of the local static pm_local_index_t -pm_lookup_local_index_any_scope(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm_constant_id_t constant_id, int *found_depth) +pm_lookup_local_index_any_scope(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm_constant_id_t constant_id, int start_depth) { - int level = 0; pm_local_index_t lindex = {0}; - if (found_depth) { - level = *found_depth; + int level = 0; + if (start_depth) { + level = start_depth; } + if (!scope_node) { // We have recursed up all scope nodes // and have not found the local yet @@ -809,12 +810,8 @@ pm_lookup_local_index_any_scope(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm if (!st_lookup(scope_node->index_lookup_table, constant_id, &local_index)) { // Local does not exist at this level, continue recursing up - if (found_depth) { - level++; - (*found_depth)++; - RUBY_ASSERT(level == *found_depth); - } - return pm_lookup_local_index_any_scope(iseq, scope_node->previous, constant_id, found_depth); + level++; + return pm_lookup_local_index_any_scope(iseq, scope_node->previous, constant_id, level); } lindex.level = level; @@ -830,7 +827,7 @@ pm_lookup_local_index_with_depth(rb_iseq_t *iseq, pm_scope_node_t *scope_node, p iseq = (rb_iseq_t *)ISEQ_BODY(iseq)->parent_iseq; } - return pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, (int *)&depth); + return pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, depth); } // This returns the CRuby ID which maps to the pm_constant_id_t @@ -4978,10 +4975,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_local_variable_target_node_t *local_write_node = (pm_local_variable_target_node_t *) node; pm_constant_id_t constant_id = local_write_node->name; - int found_depth = 0; - pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, &found_depth); + pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, NULL); - ADD_SETLOCAL(ret, &dummy_line_node, index.index, found_depth); + ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); return; } case PM_LOCAL_VARIABLE_WRITE_NODE: { @@ -4992,10 +4988,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_constant_id_t constant_id = local_write_node->name; - int found_depth = 0; - pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, &found_depth); + pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, NULL); - ADD_SETLOCAL(ret, &dummy_line_node, index.index, found_depth); + ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); return; } case PM_MATCH_LAST_LINE_NODE: { From 1b97f61168cb399a6b2145a3be118df04651ef5c Mon Sep 17 00:00:00 2001 From: Matt Valentine-House Date: Mon, 15 Jan 2024 22:03:04 +0000 Subject: [PATCH 165/640] Remove pm_lookup_local_index_with_depth --- prism_compile.c | 44 +++++++++++++++----------------------------- 1 file changed, 15 insertions(+), 29 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 00fcda6b83c0eb..5d3e215c72884b 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -811,7 +811,7 @@ pm_lookup_local_index_any_scope(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm if (!st_lookup(scope_node->index_lookup_table, constant_id, &local_index)) { // Local does not exist at this level, continue recursing up level++; - return pm_lookup_local_index_any_scope(iseq, scope_node->previous, constant_id, level); + return pm_lookup_local_index_any_scope((rb_iseq_t *)ISEQ_BODY(iseq)->parent_iseq, scope_node->previous, constant_id, level); } lindex.level = level; @@ -819,17 +819,6 @@ pm_lookup_local_index_any_scope(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm return lindex; } -static pm_local_index_t -pm_lookup_local_index_with_depth(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm_constant_id_t constant_id, uint32_t depth) -{ - for(uint32_t i = 0; i < depth; i++) { - scope_node = scope_node->previous; - iseq = (rb_iseq_t *)ISEQ_BODY(iseq)->parent_iseq; - } - - return pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, depth); -} - // This returns the CRuby ID which maps to the pm_constant_id_t // // Constant_ids in prism are indexes of the constants in prism's constant pool. @@ -2123,7 +2112,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t // of a pattern. For example, foo in bar. This results in the value // being matched being written to that local variable. pm_local_variable_target_node_t *cast = (pm_local_variable_target_node_t *) node; - pm_local_index_t index = pm_lookup_local_index_with_depth(iseq, scope_node, cast->name, cast->depth); + pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, cast->name, 0); // If this local variable is being written from within an alternation // pattern, then it cannot actually be added to the local table since @@ -4892,8 +4881,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, LABEL *end_label = NEW_LABEL(lineno); pm_constant_id_t constant_id = local_variable_and_write_node->name; - int depth = local_variable_and_write_node->depth + scope_node->local_depth_offset; - pm_local_index_t local_index = pm_lookup_local_index_with_depth(iseq, scope_node, constant_id, depth); + pm_local_index_t local_index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, local_variable_and_write_node->depth); ADD_GETLOCAL(ret, &dummy_line_node, local_index.index, local_index.level); PM_DUP_UNLESS_POPPED; @@ -4915,9 +4903,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_local_variable_operator_write_node_t *local_variable_operator_write_node = (pm_local_variable_operator_write_node_t*) node; pm_constant_id_t constant_id = local_variable_operator_write_node->name; + pm_local_index_t local_index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, 0); - int depth = local_variable_operator_write_node->depth + scope_node->local_depth_offset; - pm_local_index_t local_index = pm_lookup_local_index_with_depth(iseq, scope_node, constant_id, depth); ADD_GETLOCAL(ret, &dummy_line_node, local_index.index, local_index.level); PM_COMPILE_NOT_POPPED(local_variable_operator_write_node->value); @@ -4942,8 +4929,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, ADD_INSNL(ret, &dummy_line_node, branchunless, set_label); pm_constant_id_t constant_id = local_variable_or_write_node->name; - int depth = local_variable_or_write_node->depth + scope_node->local_depth_offset; - pm_local_index_t local_index = pm_lookup_local_index_with_depth(iseq, scope_node, constant_id, depth); + pm_local_index_t local_index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, 0); ADD_GETLOCAL(ret, &dummy_line_node, local_index.index, local_index.level); PM_DUP_UNLESS_POPPED; @@ -4966,8 +4952,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_local_variable_read_node_t *local_read_node = (pm_local_variable_read_node_t *) node; if (!popped) { - pm_local_index_t index = pm_lookup_local_index_with_depth(iseq, scope_node, local_read_node->name, local_read_node->depth); - ADD_GETLOCAL(ret, &dummy_line_node, index.index, local_read_node->depth + scope_node->local_depth_offset); + pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, local_read_node->name, 0); + ADD_GETLOCAL(ret, &dummy_line_node, index.index, index.level); } return; } @@ -4975,7 +4961,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_local_variable_target_node_t *local_write_node = (pm_local_variable_target_node_t *) node; pm_constant_id_t constant_id = local_write_node->name; - pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, NULL); + pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, 0); ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); return; @@ -4988,7 +4974,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_constant_id_t constant_id = local_write_node->name; - pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, NULL); + pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, 0); ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); return; @@ -5129,7 +5115,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_TARGET_NODE)); pm_local_variable_target_node_t *local_target = (pm_local_variable_target_node_t *) target; - pm_local_index_t index = pm_lookup_local_index_with_depth(iseq, scope_node, local_target->name, local_target->depth); + pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, local_target->name, 0); ADD_INSN1(ret, &dummy_line_node, putobject, rb_id2sym(pm_constant_id_lookup(scope_node, local_target->name))); ADD_SEND(ret, &dummy_line_node, idAREF, INT2FIX(1)); @@ -5146,7 +5132,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_TARGET_NODE)); pm_local_variable_target_node_t *local_target = (pm_local_variable_target_node_t *) target; - pm_local_index_t index = pm_lookup_local_index_with_depth(iseq, scope_node, local_target->name, local_target->depth); + pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, local_target->name, 0); if (((size_t) targets_index) < (targets_count - 1)) { PM_DUP; @@ -5169,7 +5155,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_TARGET_NODE)); pm_local_variable_target_node_t *local_target = (pm_local_variable_target_node_t *) target; - pm_local_index_t index = pm_lookup_local_index_with_depth(iseq, scope_node, local_target->name, local_target->depth); + pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, local_target->name, 0); PM_PUTNIL; ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); @@ -5206,7 +5192,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } case PM_REQUIRED_PARAMETER_NODE: { pm_required_parameter_node_t *required_parameter_node = (pm_required_parameter_node_t *)node; - pm_local_index_t index = pm_lookup_local_index_with_depth(iseq, scope_node, required_parameter_node->name, 0); + pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, required_parameter_node->name, 0); ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); return; @@ -5467,7 +5453,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_optional_parameter_node_t *optional_parameter_node = (pm_optional_parameter_node_t *)node; PM_COMPILE_NOT_POPPED(optional_parameter_node->value); - pm_local_index_t index = pm_lookup_local_index_with_depth(iseq, scope_node, optional_parameter_node->name, 0); + pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, optional_parameter_node->name, 0); ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); @@ -6418,7 +6404,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, PM_NODE_TYPE_P(value, PM_RANGE_NODE)) { LABEL *end_label = NEW_LABEL(nd_line(&dummy_line_node)); - pm_local_index_t index = pm_lookup_local_index_with_depth(iseq, scope_node, name, 0); + pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, name, 0); int kw_bits_idx = table_size - body->param.keyword->bits_start; ADD_INSN2(ret, &dummy_line_node, checkkeyword, INT2FIX(kw_bits_idx + VM_ENV_DATA_SIZE - 1), INT2FIX(i)); ADD_INSNL(ret, &dummy_line_node, branchif, end_label); From 543bd7f3dbc06c4a43bb52aa459383dc97cebe77 Mon Sep 17 00:00:00 2001 From: Matt Valentine-House Date: Mon, 15 Jan 2024 22:11:32 +0000 Subject: [PATCH 166/640] Remove scope_node->local_depth_offset --- prism_compile.c | 9 --------- prism_compile.h | 5 ----- 2 files changed, 14 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 5d3e215c72884b..e145053f312128 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2314,12 +2314,10 @@ pm_scope_node_init(const pm_node_t *node, pm_scope_node_t *scope, pm_scope_node_ scope->parameters = NULL; scope->body = NULL; scope->constants = NULL; - scope->local_depth_offset = 0; scope->local_table_for_iseq_size = 0; if (previous) { scope->constants = previous->constants; - scope->local_depth_offset = previous->local_depth_offset; } scope->index_lookup_table = NULL; @@ -2330,7 +2328,6 @@ pm_scope_node_init(const pm_node_t *node, pm_scope_node_t *scope, pm_scope_node_ pm_block_node_t *cast = (pm_block_node_t *) node; scope->body = cast->body; scope->locals = cast->locals; - scope->local_depth_offset = 0; scope->parameters = cast->parameters; break; } @@ -2349,19 +2346,16 @@ pm_scope_node_init(const pm_node_t *node, pm_scope_node_t *scope, pm_scope_node_ } case PM_ENSURE_NODE: { scope->body = (pm_node_t *)node; - scope->local_depth_offset += 1; break; } case PM_FOR_NODE: { pm_for_node_t *cast = (pm_for_node_t *)node; scope->body = (pm_node_t *)cast->statements; - scope->local_depth_offset += 1; break; } case PM_INTERPOLATED_REGULAR_EXPRESSION_NODE: { RUBY_ASSERT(node->flags & PM_REGULAR_EXPRESSION_FLAGS_ONCE); scope->body = (pm_node_t *)node; - scope->local_depth_offset += 1; break; } case PM_LAMBDA_NODE: { @@ -2380,7 +2374,6 @@ pm_scope_node_init(const pm_node_t *node, pm_scope_node_t *scope, pm_scope_node_ case PM_POST_EXECUTION_NODE: { pm_post_execution_node_t *cast = (pm_post_execution_node_t *) node; scope->body = (pm_node_t *) cast->statements; - scope->local_depth_offset += 2; break; } case PM_PROGRAM_NODE: { @@ -2392,13 +2385,11 @@ pm_scope_node_init(const pm_node_t *node, pm_scope_node_t *scope, pm_scope_node_ case PM_RESCUE_NODE: { pm_rescue_node_t *cast = (pm_rescue_node_t *)node; scope->body = (pm_node_t *)cast->statements; - scope->local_depth_offset += 1; break; } case PM_RESCUE_MODIFIER_NODE: { pm_rescue_modifier_node_t *cast = (pm_rescue_modifier_node_t *)node; scope->body = (pm_node_t *)cast->rescue_expression; - scope->local_depth_offset += 1; break; } case PM_SINGLETON_CLASS_NODE: { diff --git a/prism_compile.h b/prism_compile.h index 0b3a6fb826933c..578eed0243dc7e 100644 --- a/prism_compile.h +++ b/prism_compile.h @@ -30,11 +30,6 @@ typedef struct pm_scope_node { ID *constants; st_table *index_lookup_table; - - // Some locals are defined at higher scopes than they are used. We can use - // this offset to control which parent scopes local table we should be - // referencing from the current scope. - unsigned int local_depth_offset; } pm_scope_node_t; void pm_scope_node_init(const pm_node_t *node, pm_scope_node_t *scope, pm_scope_node_t *previous, pm_parser_t *parser); From fef8ccff11a5f48eef9f11f61ff0baa165acfaff Mon Sep 17 00:00:00 2001 From: Matt Valentine-House Date: Mon, 15 Jan 2024 22:32:30 +0000 Subject: [PATCH 167/640] Rename pm_lookup_local_index_any_scope Now it's the only local lookup function we can just call it pm_lookup_local_index --- prism_compile.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index e145053f312128..808c6ece8f5a60 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -792,7 +792,7 @@ pm_interpolated_node_compile(pm_node_list_t *parts, rb_iseq_t *iseq, NODE dummy_ // It also takes a pointer to depth, and increments depth appropriately // according to the depth of the local static pm_local_index_t -pm_lookup_local_index_any_scope(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm_constant_id_t constant_id, int start_depth) +pm_lookup_local_index(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm_constant_id_t constant_id, int start_depth) { pm_local_index_t lindex = {0}; int level = 0; @@ -811,7 +811,7 @@ pm_lookup_local_index_any_scope(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm if (!st_lookup(scope_node->index_lookup_table, constant_id, &local_index)) { // Local does not exist at this level, continue recursing up level++; - return pm_lookup_local_index_any_scope((rb_iseq_t *)ISEQ_BODY(iseq)->parent_iseq, scope_node->previous, constant_id, level); + return pm_lookup_local_index((rb_iseq_t *)ISEQ_BODY(iseq)->parent_iseq, scope_node->previous, constant_id, level); } lindex.level = level; @@ -2112,7 +2112,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t // of a pattern. For example, foo in bar. This results in the value // being matched being written to that local variable. pm_local_variable_target_node_t *cast = (pm_local_variable_target_node_t *) node; - pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, cast->name, 0); + pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, cast->name, 0); // If this local variable is being written from within an alternation // pattern, then it cannot actually be added to the local table since @@ -4872,7 +4872,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, LABEL *end_label = NEW_LABEL(lineno); pm_constant_id_t constant_id = local_variable_and_write_node->name; - pm_local_index_t local_index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, local_variable_and_write_node->depth); + pm_local_index_t local_index = pm_lookup_local_index(iseq, scope_node, constant_id, local_variable_and_write_node->depth); ADD_GETLOCAL(ret, &dummy_line_node, local_index.index, local_index.level); PM_DUP_UNLESS_POPPED; @@ -4894,7 +4894,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_local_variable_operator_write_node_t *local_variable_operator_write_node = (pm_local_variable_operator_write_node_t*) node; pm_constant_id_t constant_id = local_variable_operator_write_node->name; - pm_local_index_t local_index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, 0); + pm_local_index_t local_index = pm_lookup_local_index(iseq, scope_node, constant_id, 0); ADD_GETLOCAL(ret, &dummy_line_node, local_index.index, local_index.level); @@ -4920,7 +4920,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, ADD_INSNL(ret, &dummy_line_node, branchunless, set_label); pm_constant_id_t constant_id = local_variable_or_write_node->name; - pm_local_index_t local_index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, 0); + pm_local_index_t local_index = pm_lookup_local_index(iseq, scope_node, constant_id, 0); ADD_GETLOCAL(ret, &dummy_line_node, local_index.index, local_index.level); PM_DUP_UNLESS_POPPED; @@ -4943,7 +4943,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_local_variable_read_node_t *local_read_node = (pm_local_variable_read_node_t *) node; if (!popped) { - pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, local_read_node->name, 0); + pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, local_read_node->name, 0); ADD_GETLOCAL(ret, &dummy_line_node, index.index, index.level); } return; @@ -4952,7 +4952,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_local_variable_target_node_t *local_write_node = (pm_local_variable_target_node_t *) node; pm_constant_id_t constant_id = local_write_node->name; - pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, 0); + pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, constant_id, 0); ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); return; @@ -4965,7 +4965,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_constant_id_t constant_id = local_write_node->name; - pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, constant_id, 0); + pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, constant_id, 0); ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); return; @@ -5106,7 +5106,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_TARGET_NODE)); pm_local_variable_target_node_t *local_target = (pm_local_variable_target_node_t *) target; - pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, local_target->name, 0); + pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, local_target->name, 0); ADD_INSN1(ret, &dummy_line_node, putobject, rb_id2sym(pm_constant_id_lookup(scope_node, local_target->name))); ADD_SEND(ret, &dummy_line_node, idAREF, INT2FIX(1)); @@ -5123,7 +5123,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_TARGET_NODE)); pm_local_variable_target_node_t *local_target = (pm_local_variable_target_node_t *) target; - pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, local_target->name, 0); + pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, local_target->name, 0); if (((size_t) targets_index) < (targets_count - 1)) { PM_DUP; @@ -5146,7 +5146,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_TARGET_NODE)); pm_local_variable_target_node_t *local_target = (pm_local_variable_target_node_t *) target; - pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, local_target->name, 0); + pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, local_target->name, 0); PM_PUTNIL; ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); @@ -5183,7 +5183,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } case PM_REQUIRED_PARAMETER_NODE: { pm_required_parameter_node_t *required_parameter_node = (pm_required_parameter_node_t *)node; - pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, required_parameter_node->name, 0); + pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, required_parameter_node->name, 0); ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); return; @@ -5444,7 +5444,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_optional_parameter_node_t *optional_parameter_node = (pm_optional_parameter_node_t *)node; PM_COMPILE_NOT_POPPED(optional_parameter_node->value); - pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, optional_parameter_node->name, 0); + pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, optional_parameter_node->name, 0); ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); @@ -6395,7 +6395,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, PM_NODE_TYPE_P(value, PM_RANGE_NODE)) { LABEL *end_label = NEW_LABEL(nd_line(&dummy_line_node)); - pm_local_index_t index = pm_lookup_local_index_any_scope(iseq, scope_node, name, 0); + pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, name, 0); int kw_bits_idx = table_size - body->param.keyword->bits_start; ADD_INSN2(ret, &dummy_line_node, checkkeyword, INT2FIX(kw_bits_idx + VM_ENV_DATA_SIZE - 1), INT2FIX(i)); ADD_INSNL(ret, &dummy_line_node, branchif, end_label); From 6283ae8d369bd2f8a022bb69bc5b742c58529dec Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Tue, 16 Jan 2024 23:59:55 +0900 Subject: [PATCH 168/640] [ruby/stringio] Update the coderange after overwrite Fix https://bugs.ruby-lang.org/issues/20185 https://github.com/ruby/stringio/commit/8230552a46 --- ext/stringio/stringio.c | 6 ++++++ test/stringio/test_stringio.rb | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c index 74e2b95c99ca46..4eb15117875cb3 100644 --- a/ext/stringio/stringio.c +++ b/ext/stringio/stringio.c @@ -1464,8 +1464,14 @@ strio_write(VALUE self, VALUE str) } } else { + int cr0 = ENC_CODERANGE(ptr->string); + int cr = ENC_CODERANGE_UNKNOWN; + if (rb_enc_asciicompat(enc) && rb_enc_asciicompat(enc2)) { + cr = ENC_CODERANGE_AND(cr0, ENC_CODERANGE(str)); + } strio_extend(ptr, ptr->pos, len); memmove(RSTRING_PTR(ptr->string)+ptr->pos, RSTRING_PTR(str), len); + if (cr != cr0) ENC_CODERANGE_SET(ptr->string, cr); } RB_GC_GUARD(str); ptr->pos += len; diff --git a/test/stringio/test_stringio.rb b/test/stringio/test_stringio.rb index 216b06d3ad071d..15fcc21146308b 100644 --- a/test/stringio/test_stringio.rb +++ b/test/stringio/test_stringio.rb @@ -953,6 +953,16 @@ def test_binary_encoding_read_and_default_internal $VERBOSE = verbose end + def test_coderange_after_overwrite + s = StringIO.new("".b) + + s.write("a=b&c=d") + s.rewind + assert_predicate(s.string, :ascii_only?) + s.write "\u{431 43e 433 443 441}" + assert_not_predicate(s.string, :ascii_only?) + end + def assert_string(content, encoding, str, mesg = nil) assert_equal([content, encoding], [str, str.encoding], mesg) end From c5e43da426eb79e87ec963837a4cbb0a4ed9396d Mon Sep 17 00:00:00 2001 From: TSUYUSATO Kitsune Date: Wed, 17 Jan 2024 00:37:22 +0900 Subject: [PATCH 169/640] [ruby/prism] Correct the "ambiguous first argument" condition Fix https://github.com/ruby/prism/pull/2182 This change reflects this line: https://github.com/ruby/ruby/blob/6283ae8d369bd2f8a022bb69bc5b742c58529dec/parse.y#L11124. https://github.com/ruby/prism/commit/a52588ff37 --- prism/prism.c | 5 +- test/prism/fixtures/hashes.txt | 2 + test/prism/snapshots/hashes.txt | 216 +++++++++++++++++--------------- 3 files changed, 121 insertions(+), 102 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 570b86ab1d84f0..bbeb3cffe96934 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -8972,11 +8972,12 @@ parser_lex(pm_parser_t *parser) { } bool spcarg = lex_state_spcarg_p(parser, space_seen); - if (spcarg) { + bool is_beg = lex_state_beg_p(parser); + if (!is_beg && spcarg) { pm_parser_warn_token(parser, &parser->current, PM_WARN_AMBIGUOUS_FIRST_ARGUMENT_MINUS); } - if (lex_state_beg_p(parser) || spcarg) { + if (is_beg || spcarg) { lex_state_set(parser, PM_LEX_STATE_BEG); LEX(pm_char_is_decimal_digit(peek(parser)) ? PM_TOKEN_UMINUS_NUM : PM_TOKEN_UMINUS); } diff --git a/test/prism/fixtures/hashes.txt b/test/prism/fixtures/hashes.txt index 443b2359c62c02..0afb8db496d1f2 100644 --- a/test/prism/fixtures/hashes.txt +++ b/test/prism/fixtures/hashes.txt @@ -24,3 +24,5 @@ tap do b = 1 { a:, b:, c:, D: } end + +{ a: -1 } diff --git a/test/prism/snapshots/hashes.txt b/test/prism/snapshots/hashes.txt index b468da8e95469c..741fb8939b88b9 100644 --- a/test/prism/snapshots/hashes.txt +++ b/test/prism/snapshots/hashes.txt @@ -1,8 +1,8 @@ -@ ProgramNode (location: (1,0)-(26,3)) +@ ProgramNode (location: (1,0)-(28,9)) ├── locals: [:a] └── statements: - @ StatementsNode (location: (1,0)-(26,3)) - └── body: (length: 9) + @ StatementsNode (location: (1,0)-(28,9)) + └── body: (length: 10) ├── @ HashNode (location: (1,0)-(1,2)) │ ├── opening_loc: (1,0)-(1,1) = "{" │ ├── elements: (length: 0) @@ -267,100 +267,116 @@ │ │ @ IntegerNode (location: (22,4)-(22,5)) │ │ └── flags: decimal │ └── operator_loc: (22,2)-(22,3) = "=" - └── @ CallNode (location: (23,0)-(26,3)) - ├── flags: ignore_visibility - ├── receiver: ∅ - ├── call_operator_loc: ∅ - ├── name: :tap - ├── message_loc: (23,0)-(23,3) = "tap" - ├── opening_loc: ∅ - ├── arguments: ∅ - ├── closing_loc: ∅ - └── block: - @ BlockNode (location: (23,4)-(26,3)) - ├── locals: [:b] - ├── locals_body_index: 0 - ├── parameters: ∅ - ├── body: - │ @ StatementsNode (location: (24,2)-(25,20)) - │ └── body: (length: 2) - │ ├── @ LocalVariableWriteNode (location: (24,2)-(24,7)) - │ │ ├── name: :b - │ │ ├── depth: 0 - │ │ ├── name_loc: (24,2)-(24,3) = "b" - │ │ ├── value: - │ │ │ @ IntegerNode (location: (24,6)-(24,7)) - │ │ │ └── flags: decimal - │ │ └── operator_loc: (24,4)-(24,5) = "=" - │ └── @ HashNode (location: (25,2)-(25,20)) - │ ├── opening_loc: (25,2)-(25,3) = "{" - │ ├── elements: (length: 4) - │ │ ├── @ AssocNode (location: (25,4)-(25,6)) - │ │ │ ├── key: - │ │ │ │ @ SymbolNode (location: (25,4)-(25,6)) - │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ ├── value_loc: (25,4)-(25,5) = "a" - │ │ │ │ ├── closing_loc: (25,5)-(25,6) = ":" - │ │ │ │ └── unescaped: "a" - │ │ │ ├── value: - │ │ │ │ @ ImplicitNode (location: (25,4)-(25,6)) - │ │ │ │ └── value: - │ │ │ │ @ LocalVariableReadNode (location: (25,4)-(25,6)) - │ │ │ │ ├── name: :a - │ │ │ │ └── depth: 1 - │ │ │ └── operator_loc: ∅ - │ │ ├── @ AssocNode (location: (25,8)-(25,10)) - │ │ │ ├── key: - │ │ │ │ @ SymbolNode (location: (25,8)-(25,10)) - │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ ├── value_loc: (25,8)-(25,9) = "b" - │ │ │ │ ├── closing_loc: (25,9)-(25,10) = ":" - │ │ │ │ └── unescaped: "b" - │ │ │ ├── value: - │ │ │ │ @ ImplicitNode (location: (25,8)-(25,10)) - │ │ │ │ └── value: - │ │ │ │ @ LocalVariableReadNode (location: (25,8)-(25,10)) - │ │ │ │ ├── name: :b - │ │ │ │ └── depth: 0 - │ │ │ └── operator_loc: ∅ - │ │ ├── @ AssocNode (location: (25,12)-(25,14)) - │ │ │ ├── key: - │ │ │ │ @ SymbolNode (location: (25,12)-(25,14)) - │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ ├── value_loc: (25,12)-(25,13) = "c" - │ │ │ │ ├── closing_loc: (25,13)-(25,14) = ":" - │ │ │ │ └── unescaped: "c" - │ │ │ ├── value: - │ │ │ │ @ ImplicitNode (location: (25,12)-(25,14)) - │ │ │ │ └── value: - │ │ │ │ @ CallNode (location: (25,12)-(25,14)) - │ │ │ │ ├── flags: ignore_visibility - │ │ │ │ ├── receiver: ∅ - │ │ │ │ ├── call_operator_loc: ∅ - │ │ │ │ ├── name: :c - │ │ │ │ ├── message_loc: (25,12)-(25,13) = "c" - │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ ├── arguments: ∅ - │ │ │ │ ├── closing_loc: ∅ - │ │ │ │ └── block: ∅ - │ │ │ └── operator_loc: ∅ - │ │ └── @ AssocNode (location: (25,16)-(25,18)) - │ │ ├── key: - │ │ │ @ SymbolNode (location: (25,16)-(25,18)) - │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: ∅ - │ │ │ ├── value_loc: (25,16)-(25,17) = "D" - │ │ │ ├── closing_loc: (25,17)-(25,18) = ":" - │ │ │ └── unescaped: "D" - │ │ ├── value: - │ │ │ @ ImplicitNode (location: (25,16)-(25,18)) - │ │ │ └── value: - │ │ │ @ ConstantReadNode (location: (25,16)-(25,18)) - │ │ │ └── name: :D - │ │ └── operator_loc: ∅ - │ └── closing_loc: (25,19)-(25,20) = "}" - ├── opening_loc: (23,4)-(23,6) = "do" - └── closing_loc: (26,0)-(26,3) = "end" + ├── @ CallNode (location: (23,0)-(26,3)) + │ ├── flags: ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :tap + │ ├── message_loc: (23,0)-(23,3) = "tap" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ └── block: + │ @ BlockNode (location: (23,4)-(26,3)) + │ ├── locals: [:b] + │ ├── locals_body_index: 0 + │ ├── parameters: ∅ + │ ├── body: + │ │ @ StatementsNode (location: (24,2)-(25,20)) + │ │ └── body: (length: 2) + │ │ ├── @ LocalVariableWriteNode (location: (24,2)-(24,7)) + │ │ │ ├── name: :b + │ │ │ ├── depth: 0 + │ │ │ ├── name_loc: (24,2)-(24,3) = "b" + │ │ │ ├── value: + │ │ │ │ @ IntegerNode (location: (24,6)-(24,7)) + │ │ │ │ └── flags: decimal + │ │ │ └── operator_loc: (24,4)-(24,5) = "=" + │ │ └── @ HashNode (location: (25,2)-(25,20)) + │ │ ├── opening_loc: (25,2)-(25,3) = "{" + │ │ ├── elements: (length: 4) + │ │ │ ├── @ AssocNode (location: (25,4)-(25,6)) + │ │ │ │ ├── key: + │ │ │ │ │ @ SymbolNode (location: (25,4)-(25,6)) + │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ │ ├── value_loc: (25,4)-(25,5) = "a" + │ │ │ │ │ ├── closing_loc: (25,5)-(25,6) = ":" + │ │ │ │ │ └── unescaped: "a" + │ │ │ │ ├── value: + │ │ │ │ │ @ ImplicitNode (location: (25,4)-(25,6)) + │ │ │ │ │ └── value: + │ │ │ │ │ @ LocalVariableReadNode (location: (25,4)-(25,6)) + │ │ │ │ │ ├── name: :a + │ │ │ │ │ └── depth: 1 + │ │ │ │ └── operator_loc: ∅ + │ │ │ ├── @ AssocNode (location: (25,8)-(25,10)) + │ │ │ │ ├── key: + │ │ │ │ │ @ SymbolNode (location: (25,8)-(25,10)) + │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ │ ├── value_loc: (25,8)-(25,9) = "b" + │ │ │ │ │ ├── closing_loc: (25,9)-(25,10) = ":" + │ │ │ │ │ └── unescaped: "b" + │ │ │ │ ├── value: + │ │ │ │ │ @ ImplicitNode (location: (25,8)-(25,10)) + │ │ │ │ │ └── value: + │ │ │ │ │ @ LocalVariableReadNode (location: (25,8)-(25,10)) + │ │ │ │ │ ├── name: :b + │ │ │ │ │ └── depth: 0 + │ │ │ │ └── operator_loc: ∅ + │ │ │ ├── @ AssocNode (location: (25,12)-(25,14)) + │ │ │ │ ├── key: + │ │ │ │ │ @ SymbolNode (location: (25,12)-(25,14)) + │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ │ ├── value_loc: (25,12)-(25,13) = "c" + │ │ │ │ │ ├── closing_loc: (25,13)-(25,14) = ":" + │ │ │ │ │ └── unescaped: "c" + │ │ │ │ ├── value: + │ │ │ │ │ @ ImplicitNode (location: (25,12)-(25,14)) + │ │ │ │ │ └── value: + │ │ │ │ │ @ CallNode (location: (25,12)-(25,14)) + │ │ │ │ │ ├── flags: ignore_visibility + │ │ │ │ │ ├── receiver: ∅ + │ │ │ │ │ ├── call_operator_loc: ∅ + │ │ │ │ │ ├── name: :c + │ │ │ │ │ ├── message_loc: (25,12)-(25,13) = "c" + │ │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ │ ├── arguments: ∅ + │ │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ │ └── block: ∅ + │ │ │ │ └── operator_loc: ∅ + │ │ │ └── @ AssocNode (location: (25,16)-(25,18)) + │ │ │ ├── key: + │ │ │ │ @ SymbolNode (location: (25,16)-(25,18)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── value_loc: (25,16)-(25,17) = "D" + │ │ │ │ ├── closing_loc: (25,17)-(25,18) = ":" + │ │ │ │ └── unescaped: "D" + │ │ │ ├── value: + │ │ │ │ @ ImplicitNode (location: (25,16)-(25,18)) + │ │ │ │ └── value: + │ │ │ │ @ ConstantReadNode (location: (25,16)-(25,18)) + │ │ │ │ └── name: :D + │ │ │ └── operator_loc: ∅ + │ │ └── closing_loc: (25,19)-(25,20) = "}" + │ ├── opening_loc: (23,4)-(23,6) = "do" + │ └── closing_loc: (26,0)-(26,3) = "end" + └── @ HashNode (location: (28,0)-(28,9)) + ├── opening_loc: (28,0)-(28,1) = "{" + ├── elements: (length: 1) + │ └── @ AssocNode (location: (28,2)-(28,7)) + │ ├── key: + │ │ @ SymbolNode (location: (28,2)-(28,4)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: ∅ + │ │ ├── value_loc: (28,2)-(28,3) = "a" + │ │ ├── closing_loc: (28,3)-(28,4) = ":" + │ │ └── unescaped: "a" + │ ├── value: + │ │ @ IntegerNode (location: (28,5)-(28,7)) + │ │ └── flags: decimal + │ └── operator_loc: ∅ + └── closing_loc: (28,8)-(28,9) = "}" From 1caa881a56fc0543b2fb4819b6d894008b0ae5a9 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 15 Jan 2024 13:32:12 -0500 Subject: [PATCH 170/640] [PRISM] Fix splat assignment Fixes ruby/prism#2177 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 808c6ece8f5a60..e53a0d1cbb13cf 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -5320,6 +5320,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } } else if (rest_expression) { + ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(0), INT2FIX(1)); PM_COMPILE(rest_expression); } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 3b33908c5243d5..cd521e67662cb6 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -538,6 +538,7 @@ def test_MultiWriteNode assert_prism_eval("(a, b, c), *, (d, e) = [1, 3], 4, 5, [6, 7]; b") assert_prism_eval("(a, b, c), *, (d, e) = [1, 3], 4, 5, [6, 7]; d") assert_prism_eval("((a, *, b), *, (c, *, (d, *, e, f, g))), *, ((h, i, *, j), *, (k, l, m, *, n, o, p), q, r) = 1; a") + assert_prism_eval("*a = 1; a") assert_prism_eval("_, {}[:foo] = 1") assert_prism_eval("_, {}[:foo], _ = 1") assert_prism_eval("_, {}[:foo], _ = 1") From 70a8ed0775e7a9215bcc6cdf4f6d85da321af304 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 16 Jan 2024 11:09:00 -0500 Subject: [PATCH 171/640] [PRISM] Don't allocate labels when not needed The labels lstart, lend, lcont are only needed when there is a rescue clause. They are not needed when there is only an ensure clause or neither. --- prism_compile.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index e53a0d1cbb13cf..9560232c1f7cba 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -3201,12 +3201,11 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, case PM_BEGIN_NODE: { pm_begin_node_t *begin_node = (pm_begin_node_t *) node; rb_iseq_t *child_iseq; - LABEL *lstart = NEW_LABEL(lineno); - LABEL *lend = NEW_LABEL(lineno); - LABEL *lcont = NEW_LABEL(lineno); - if (begin_node->rescue_clause) { + LABEL *lstart = NEW_LABEL(lineno); + LABEL *lend = NEW_LABEL(lineno); + LABEL *lcont = NEW_LABEL(lineno); pm_scope_node_t rescue_scope_node; pm_scope_node_init((pm_node_t *)begin_node->rescue_clause, &rescue_scope_node, scope_node, parser); @@ -3292,14 +3291,12 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } if (!begin_node->rescue_clause && !begin_node->ensure_clause) { - ADD_LABEL(ret, lstart); if (begin_node->statements) { PM_COMPILE((pm_node_t *)begin_node->statements); } else { PM_PUTNIL_UNLESS_POPPED; } - ADD_LABEL(ret, lend); } return; } From 7bd7030a96cdc106e347e0d48cfacfb80fb0f8db Mon Sep 17 00:00:00 2001 From: Matt Valentine-House Date: Tue, 16 Jan 2024 16:06:18 +0000 Subject: [PATCH 172/640] [PRISM] Replace local lookup recursion with loop --- prism_compile.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 9560232c1f7cba..88362fa7ac2e36 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -795,23 +795,18 @@ static pm_local_index_t pm_lookup_local_index(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm_constant_id_t constant_id, int start_depth) { pm_local_index_t lindex = {0}; - int level = 0; - if (start_depth) { - level = start_depth; - } - - if (!scope_node) { - // We have recursed up all scope nodes - // and have not found the local yet - rb_bug("Local with constant_id %u does not exist", (unsigned int)constant_id); - } - + int level = (start_depth) ? start_depth : 0; st_data_t local_index; - if (!st_lookup(scope_node->index_lookup_table, constant_id, &local_index)) { - // Local does not exist at this level, continue recursing up + while(!st_lookup(scope_node->index_lookup_table, constant_id, &local_index)) { level++; - return pm_lookup_local_index((rb_iseq_t *)ISEQ_BODY(iseq)->parent_iseq, scope_node->previous, constant_id, level); + if (scope_node->previous) { + scope_node = scope_node->previous; + } else { + // We have recursed up all scope nodes + // and have not found the local yet + rb_bug("Local with constant_id %u does not exist", (unsigned int)constant_id); + } } lindex.level = level; From 07b9b53459d1842e7066b248d48ef4952c6868d3 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 16 Jan 2024 10:30:31 -0500 Subject: [PATCH 173/640] [PRISM] Fix crash with empty ensure blocks Fixes ruby/prism#2179. --- prism_compile.c | 4 +++- test/ruby/test_compile_prism.rb | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/prism_compile.c b/prism_compile.c index 88362fa7ac2e36..722dabf8ab142b 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -3247,14 +3247,16 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, PM_PUTNIL_UNLESS_POPPED; } } + ADD_LABEL(ret, eend); + ADD_LABEL(ret, econt); + if (!popped) { PM_NOP; } pm_statements_node_t *statements = begin_node->ensure_clause->statements; if (statements) { PM_COMPILE((pm_node_t *)statements); - ADD_LABEL(ret, econt); PM_POP_UNLESS_POPPED; } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index cd521e67662cb6..bc9f0b3aba7a87 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -962,6 +962,22 @@ def self.prism_test_ensure_node end prism_test_ensure_node CODE + + # Test empty ensure block + assert_prism_eval(<<~RUBY) + res = [] + + begin + begin + raise + ensure + end + rescue + res << "rescue" + end + + res + RUBY end def test_NextNode From 8bf12d7b2ffe61596da2d1d2fb8e54120cfb230b Mon Sep 17 00:00:00 2001 From: Jemma Issroff Date: Wed, 10 Jan 2024 13:21:15 -0800 Subject: [PATCH 174/640] [ruby/prism] First pass at documenting information about the CRuby compiler https://github.com/ruby/prism/commit/b575914b2f --- lib/prism/prism.gemspec | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/prism/prism.gemspec b/lib/prism/prism.gemspec index 9f5cea4e20afb2..ba3f17882f6002 100644 --- a/lib/prism/prism.gemspec +++ b/lib/prism/prism.gemspec @@ -24,6 +24,7 @@ Gem::Specification.new do |spec| "docs/build_system.md", "docs/building.md", "docs/configuration.md", + "docs/cruby_compilation.md", "docs/design.md", "docs/encoding.md", "docs/fuzzing.md", From d124124c1613ec5e6b4770252e16d714f7b05e91 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 16 Jan 2024 13:54:27 -0500 Subject: [PATCH 175/640] [ruby/prism] Fix up gemspec https://github.com/ruby/prism/commit/82e3126762 --- lib/prism/prism.gemspec | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/prism/prism.gemspec b/lib/prism/prism.gemspec index ba3f17882f6002..a6da1b5318d008 100644 --- a/lib/prism/prism.gemspec +++ b/lib/prism/prism.gemspec @@ -22,7 +22,6 @@ Gem::Specification.new do |spec| "README.md", "config.yml", "docs/build_system.md", - "docs/building.md", "docs/configuration.md", "docs/cruby_compilation.md", "docs/design.md", From 8cbba87ca85b388bb896d9732973e8e1555e5b93 Mon Sep 17 00:00:00 2001 From: Cameron Dutro Date: Mon, 15 Jan 2024 12:03:53 -0800 Subject: [PATCH 176/640] [ruby/prism] Add parse options to JavaScript's parsePrism function https://github.com/ruby/prism/commit/d7fe7c7ae7 --- lib/prism/ffi.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb index 4c42e5061b5378..43f414504c966a 100644 --- a/lib/prism/ffi.rb +++ b/lib/prism/ffi.rb @@ -296,7 +296,7 @@ def dump_options(options) values << 0 end - template << "L" + template << "l" values << options.fetch(:line, 1) template << "L" From 7b6731b1bb7c8fab72580f92450eea6e4cc3d943 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 16 Jan 2024 10:16:14 -0500 Subject: [PATCH 177/640] [ruby/prism] Provide abstract methods in Prism::Node To make typechecking easier. https://github.com/ruby/prism/commit/8f96877d7a --- prism/templates/lib/prism/node.rb.erb | 38 +++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/prism/templates/lib/prism/node.rb.erb b/prism/templates/lib/prism/node.rb.erb index 4a10dfcecf4f15..d7259c1269e5f1 100644 --- a/prism/templates/lib/prism/node.rb.erb +++ b/prism/templates/lib/prism/node.rb.erb @@ -36,6 +36,44 @@ module Prism def to_dot DotVisitor.new.tap { |visitor| accept(visitor) }.to_dot end + + # -------------------------------------------------------------------------- + # :section: Node interface + # These methods are effectively abstract methods that must be implemented by + # the various subclasses of Node. They are here to make it easier to work + # with typecheckers. + # -------------------------------------------------------------------------- + + # Accepts a visitor and calls back into the specialized visit function. + def accept(visitor) + raise NoMethodError, "undefined method `accept' for #{inspect}" + end + + # Returns an array of child nodes, including `nil`s in the place of optional + # nodes that were not present. + def child_nodes + raise NoMethodError, "undefined method `#{__method__}' for #{inspect}" + end + + alias deconstruct child_nodes + + # Returns an array of child nodes, excluding any `nil`s in the place of + # optional nodes that were not present. + def compact_child_nodes + raise NoMethodError, "undefined method `compact_child_nodes' for #{inspect}" + end + + # Returns an array of child nodes and locations that could potentially have + # comments attached to them. + def comment_targets + raise NoMethodError, "undefined method `comment_targets' for #{inspect}" + end + + # Returns a symbol symbolizing the type of node that this represents. This + # is particularly useful for case statements and array comparisons. + def type + raise NoMethodError, "undefined method `type' for #{inspect}" + end end <%- nodes.each do |node| -%> From 5471f99eead4dd77f1d418eca04d7656bb97f01d Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 16 Jan 2024 15:22:03 -0500 Subject: [PATCH 178/640] [PRISM] Fix memory leak when compiling file There is a memory leak when passing a file to RubyVM::InstructionSequence.compile_prism because it does not free the mapped file. For example: require "tempfile" Tempfile.create(%w"test_iseq .rb") do |f| f.puts "name = 'Prism'; puts 'hello'" f.close 10.times do 1_000.times do RubyVM::InstructionSequence.compile_prism(f) end puts `ps -o rss= -p #{$$}` end end Before: 27968 44848 61408 77872 94144 110432 126640 142816 159200 175584 After: 11504 12144 12592 13072 13488 13664 14064 14368 14704 15168 --- iseq.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/iseq.c b/iseq.c index 3b87cdcc782e51..28c2d4f80b2068 100644 --- a/iseq.c +++ b/iseq.c @@ -1477,23 +1477,26 @@ iseqw_s_compile_prism(int argc, VALUE *argv, VALUE self) pm_parser_t parser; + pm_string_t input; if (RB_TYPE_P(src, T_FILE)) { FilePathValue(src); file = rb_fstring(src); /* rb_io_t->pathv gets frozen anyways */ - pm_string_t input; pm_string_mapped_init(&input, RSTRING_PTR(file)); - - pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), &options); } else { - pm_parser_init(&parser, (const uint8_t *) RSTRING_PTR(src), RSTRING_LEN(src), &options); + input.source = (const uint8_t *)RSTRING_PTR(src); + input.length = RSTRING_LEN(src); + input.type = PM_STRING_SHARED; } + pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), &options); + rb_iseq_t *iseq = iseq_alloc(); iseqw_s_compile_prism_compile(&parser, opt, iseq, file, path, start_line); pm_parser_free(&parser); pm_options_free(&options); + pm_string_free(&input); return iseqw_new(iseq); } From 2bf9970101c87bcece5401ca7a7c7e4d54cb64aa Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Tue, 16 Jan 2024 16:24:54 -0500 Subject: [PATCH 179/640] YJIT: Finer breakdown for block_arg counters For example, on `lobsters` the block_arg reason was at ~10%. With this change it shows that 6% of that is `send_cfunc_block_arg`. --- yjit/src/codegen.rs | 10 +++++----- yjit/src/stats.rs | 5 +++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index e626a71d881540..2c3e61356c6a02 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -5605,7 +5605,7 @@ fn gen_send_cfunc( // Nothing to do } _ => { - gen_counter_incr(asm, Counter::send_block_arg); + gen_counter_incr(asm, Counter::send_cfunc_block_arg); return None; } } @@ -7009,7 +7009,7 @@ fn exit_if_unsupported_block_arg_type( Some(Some(Type::TProc)) } _ => { - gen_counter_incr(asm, Counter::send_block_arg); + gen_counter_incr(asm, Counter::send_iseq_block_arg_type); None } } @@ -7341,7 +7341,7 @@ fn gen_send_general( let ivar_name = unsafe { get_cme_def_body_attr_id(cme) }; if flags & VM_CALL_ARGS_BLOCKARG != 0 { - gen_counter_incr(asm, Counter::send_block_arg); + gen_counter_incr(asm, Counter::send_getter_block_arg); return None; } @@ -7373,7 +7373,7 @@ fn gen_send_general( gen_counter_incr(asm, Counter::send_cfunc_tracing); return None; } else if flags & VM_CALL_ARGS_BLOCKARG != 0 { - gen_counter_incr(asm, Counter::send_block_arg); + gen_counter_incr(asm, Counter::send_attrset_block_arg); return None; } else { let ivar_name = unsafe { get_cme_def_body_attr_id(cme) }; @@ -7396,7 +7396,7 @@ fn gen_send_general( // Send family of methods, e.g. call/apply VM_METHOD_TYPE_OPTIMIZED => { if flags & VM_CALL_ARGS_BLOCKARG != 0 { - gen_counter_incr(asm, Counter::send_block_arg); + gen_counter_incr(asm, Counter::send_optimized_block_arg); return None; } diff --git a/yjit/src/stats.rs b/yjit/src/stats.rs index f4c53a50f99f7b..924628e13acedf 100644 --- a/yjit/src/stats.rs +++ b/yjit/src/stats.rs @@ -319,14 +319,17 @@ make_counters! { send_private_not_fcall, send_cfunc_ruby_array_varg, send_cfunc_argc_mismatch, + send_cfunc_block_arg, send_cfunc_toomany_args, send_cfunc_tracing, send_cfunc_kwargs, send_cfunc_splat_with_kw, send_cfunc_splat_send, send_attrset_kwargs, + send_attrset_block_arg, send_iseq_tailcall, send_iseq_arity_error, + send_iseq_block_arg_type, send_iseq_clobbering_block_arg, send_iseq_leaf_builtin_block_arg_block_param, send_iseq_only_keywords, @@ -343,6 +346,7 @@ make_counters! { send_iseq_too_many_kwargs, send_not_implemented_method, send_getter_arity, + send_getter_block_arg, send_args_splat_non_iseq, send_args_splat_ivar, send_args_splat_attrset, @@ -371,6 +375,7 @@ make_counters! { send_iseq_has_rest_opt_and_block, send_bmethod_ractor, send_bmethod_block_arg, + send_optimized_block_arg, invokesuper_defined_class_mismatch, invokesuper_kw_splat, From 4e2eca3be0ef6d4114acdc2527330dfd81d8ff4b Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 11 Jan 2024 11:32:49 +0900 Subject: [PATCH 180/640] Extract base64 as bundled gems --- gems/bundled_gems | 1 + lib/base64.gemspec | 28 --- lib/base64.rb | 363 ------------------------------------- test/base64/test_base64.rb | 115 ------------ 4 files changed, 1 insertion(+), 506 deletions(-) delete mode 100644 lib/base64.gemspec delete mode 100644 lib/base64.rb delete mode 100644 test/base64/test_base64.rb diff --git a/gems/bundled_gems b/gems/bundled_gems index 42ebcb82316d93..6c3ece4d2b63a1 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -23,3 +23,4 @@ debug 1.9.1 https://github.com/ruby/debug racc 1.7.3 https://github.com/ruby/racc mutex_m 0.2.0 https://github.com/ruby/mutex_m getoptlong 0.2.1 https://github.com/ruby/getoptlong +base64 0.2.0 https://github.com/ruby/base64 diff --git a/lib/base64.gemspec b/lib/base64.gemspec deleted file mode 100644 index 4e0b31c76bc0fa..00000000000000 --- a/lib/base64.gemspec +++ /dev/null @@ -1,28 +0,0 @@ -name = File.basename(__FILE__, ".gemspec") -version = ["lib", Array.new(name.count("-")+1).join("/")].find do |dir| - break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line| - /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1 - end rescue nil -end - -Gem::Specification.new do |spec| - spec.name = name - spec.version = version - spec.authors = ["Yusuke Endoh"] - spec.email = ["mame@ruby-lang.org"] - - spec.summary = %q{Support for encoding and decoding binary data using a Base64 representation.} - spec.description = %q{Support for encoding and decoding binary data using a Base64 representation.} - spec.homepage = "https://github.com/ruby/base64" - spec.required_ruby_version = Gem::Requirement.new(">= 2.4") - spec.licenses = ["Ruby", "BSD-2-Clause"] - - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = spec.homepage - spec.metadata["changelog_uri"] = spec.homepage + "/releases" - - spec.files = ["README.md", "LICENSE.txt", "lib/base64.rb"] - spec.bindir = "exe" - spec.executables = [] - spec.require_paths = ["lib"] -end diff --git a/lib/base64.rb b/lib/base64.rb deleted file mode 100644 index cd2ecc18ea0ae7..00000000000000 --- a/lib/base64.rb +++ /dev/null @@ -1,363 +0,0 @@ -# frozen_string_literal: true -# -# \Module \Base64 provides methods for: -# -# - Encoding a binary string (containing non-ASCII characters) -# as a string of printable ASCII characters. -# - Decoding such an encoded string. -# -# \Base64 is commonly used in contexts where binary data -# is not allowed or supported: -# -# - Images in HTML or CSS files, or in URLs. -# - Email attachments. -# -# A \Base64-encoded string is about one-third larger that its source. -# See the {Wikipedia article}[https://en.wikipedia.org/wiki/Base64] -# for more information. -# -# This module provides three pairs of encode/decode methods. -# Your choices among these methods should depend on: -# -# - Which character set is to be used for encoding and decoding. -# - Whether "padding" is to be used. -# - Whether encoded strings are to contain newlines. -# -# Note: Examples on this page assume that the including program has executed: -# -# require 'base64' -# -# == Encoding Character Sets -# -# A \Base64-encoded string consists only of characters from a 64-character set: -# -# - ('A'..'Z'). -# - ('a'..'z'). -# - ('0'..'9'). -# - =, the 'padding' character. -# - Either: -# - %w[+ /]: -# {RFC-2045-compliant}[https://datatracker.ietf.org/doc/html/rfc2045]; -# _not_ safe for URLs. -# - %w[- _]: -# {RFC-4648-compliant}[https://datatracker.ietf.org/doc/html/rfc4648]; -# safe for URLs. -# -# If you are working with \Base64-encoded strings that will come from -# or be put into URLs, you should choose this encoder-decoder pair -# of RFC-4648-compliant methods: -# -# - Base64.urlsafe_encode64 and Base64.urlsafe_decode64. -# -# Otherwise, you may choose any of the pairs in this module, -# including the pair above, or the RFC-2045-compliant pairs: -# -# - Base64.encode64 and Base64.decode64. -# - Base64.strict_encode64 and Base64.strict_decode64. -# -# == Padding -# -# \Base64-encoding changes a triplet of input bytes -# into a quartet of output characters. -# -# Padding in Encode Methods -# -# Padding -- extending an encoded string with zero, one, or two trailing -# = characters -- is performed by methods Base64.encode64, -# Base64.strict_encode64, and, by default, Base64.urlsafe_encode64: -# -# Base64.encode64('s') # => "cw==\n" -# Base64.strict_encode64('s') # => "cw==" -# Base64.urlsafe_encode64('s') # => "cw==" -# Base64.urlsafe_encode64('s', padding: false) # => "cw" -# -# When padding is performed, the encoded string is always of length 4n, -# where +n+ is a non-negative integer: -# -# - Input bytes of length 3n generate unpadded output characters -# of length 4n: -# -# # n = 1: 3 bytes => 4 characters. -# Base64.strict_encode64('123') # => "MDEy" -# # n = 2: 6 bytes => 8 characters. -# Base64.strict_encode64('123456') # => "MDEyMzQ1" -# -# - Input bytes of length 3n+1 generate padded output characters -# of length 4(n+1), with two padding characters at the end: -# -# # n = 1: 4 bytes => 8 characters. -# Base64.strict_encode64('1234') # => "MDEyMw==" -# # n = 2: 7 bytes => 12 characters. -# Base64.strict_encode64('1234567') # => "MDEyMzQ1Ng==" -# -# - Input bytes of length 3n+2 generate padded output characters -# of length 4(n+1), with one padding character at the end: -# -# # n = 1: 5 bytes => 8 characters. -# Base64.strict_encode64('12345') # => "MDEyMzQ=" -# # n = 2: 8 bytes => 12 characters. -# Base64.strict_encode64('12345678') # => "MDEyMzQ1Njc=" -# -# When padding is suppressed, for a positive integer n: -# -# - Input bytes of length 3n generate unpadded output characters -# of length 4n: -# -# # n = 1: 3 bytes => 4 characters. -# Base64.urlsafe_encode64('123', padding: false) # => "MDEy" -# # n = 2: 6 bytes => 8 characters. -# Base64.urlsafe_encode64('123456', padding: false) # => "MDEyMzQ1" -# -# - Input bytes of length 3n+1 generate unpadded output characters -# of length 4n+2, with two padding characters at the end: -# -# # n = 1: 4 bytes => 6 characters. -# Base64.urlsafe_encode64('1234', padding: false) # => "MDEyMw" -# # n = 2: 7 bytes => 10 characters. -# Base64.urlsafe_encode64('1234567', padding: false) # => "MDEyMzQ1Ng" -# -# - Input bytes of length 3n+2 generate unpadded output characters -# of length 4n+3, with one padding character at the end: -# -# # n = 1: 5 bytes => 7 characters. -# Base64.urlsafe_encode64('12345', padding: false) # => "MDEyMzQ" -# # m = 2: 8 bytes => 11 characters. -# Base64.urlsafe_encode64('12345678', padding: false) # => "MDEyMzQ1Njc" -# -# Padding in Decode Methods -# -# All of the \Base64 decode methods support (but do not require) padding. -# -# \Method Base64.decode64 does not check the size of the padding: -# -# Base64.decode64("MDEyMzQ1Njc") # => "01234567" -# Base64.decode64("MDEyMzQ1Njc=") # => "01234567" -# Base64.decode64("MDEyMzQ1Njc==") # => "01234567" -# -# \Method Base64.strict_decode64 strictly enforces padding size: -# -# Base64.strict_decode64("MDEyMzQ1Njc") # Raises ArgumentError -# Base64.strict_decode64("MDEyMzQ1Njc=") # => "01234567" -# Base64.strict_decode64("MDEyMzQ1Njc==") # Raises ArgumentError -# -# \Method Base64.urlsafe_decode64 allows padding in +str+, -# which if present, must be correct: -# see {Padding}[Base64.html#module-Base64-label-Padding], above: -# -# Base64.urlsafe_decode64("MDEyMzQ1Njc") # => "01234567" -# Base64.urlsafe_decode64("MDEyMzQ1Njc=") # => "01234567" -# Base64.urlsafe_decode64("MDEyMzQ1Njc==") # Raises ArgumentError. -# -# == Newlines -# -# An encoded string returned by Base64.encode64 or Base64.urlsafe_encode64 -# has an embedded newline character -# after each 60-character sequence, and, if non-empty, at the end: -# -# # No newline if empty. -# encoded = Base64.encode64("\x00" * 0) -# encoded.index("\n") # => nil -# -# # Newline at end of short output. -# encoded = Base64.encode64("\x00" * 1) -# encoded.size # => 4 -# encoded.index("\n") # => 4 -# -# # Newline at end of longer output. -# encoded = Base64.encode64("\x00" * 45) -# encoded.size # => 60 -# encoded.index("\n") # => 60 -# -# # Newlines embedded and at end of still longer output. -# encoded = Base64.encode64("\x00" * 46) -# encoded.size # => 65 -# encoded.rindex("\n") # => 65 -# encoded.split("\n").map {|s| s.size } # => [60, 4] -# -# The string to be encoded may itself contain newlines, -# which are encoded as \Base64: -# -# # Base64.encode64("\n\n\n") # => "CgoK\n" -# s = "This is line 1\nThis is line 2\n" -# Base64.encode64(s) # => "VGhpcyBpcyBsaW5lIDEKVGhpcyBpcyBsaW5lIDIK\n" -# -module Base64 - - VERSION = "0.2.0" - - module_function - - # Returns a string containing the RFC-2045-compliant \Base64-encoding of +bin+. - # - # Per RFC 2045, the returned string may contain the URL-unsafe characters - # + or /; - # see {Encoding Character Set}[Base64.html#module-Base64-label-Encoding+Character+Sets] above: - # - # Base64.encode64("\xFB\xEF\xBE") # => "++++\n" - # Base64.encode64("\xFF\xFF\xFF") # => "////\n" - # - # The returned string may include padding; - # see {Padding}[Base64.html#module-Base64-label-Padding] above. - # - # Base64.encode64('*') # => "Kg==\n" - # - # The returned string ends with a newline character, and if sufficiently long - # will have one or more embedded newline characters; - # see {Newlines}[Base64.html#module-Base64-label-Newlines] above: - # - # Base64.encode64('*') # => "Kg==\n" - # Base64.encode64('*' * 46) - # # => "KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq\nKg==\n" - # - # The string to be encoded may itself contain newlines, - # which will be encoded as ordinary \Base64: - # - # Base64.encode64("\n\n\n") # => "CgoK\n" - # s = "This is line 1\nThis is line 2\n" - # Base64.encode64(s) # => "VGhpcyBpcyBsaW5lIDEKVGhpcyBpcyBsaW5lIDIK\n" - # - def encode64(bin) - [bin].pack("m") - end - - # Returns a string containing the decoding of an RFC-2045-compliant - # \Base64-encoded string +str+: - # - # s = "VGhpcyBpcyBsaW5lIDEKVGhpcyBpcyBsaW5lIDIK\n" - # Base64.decode64(s) # => "This is line 1\nThis is line 2\n" - # - # Non-\Base64 characters in +str+ are ignored; - # see {Encoding Character Set}[Base64.html#module-Base64-label-Encoding+Character+Sets] above: - # these include newline characters and characters - and /: - # - # Base64.decode64("\x00\n-_") # => "" - # - # Padding in +str+ (even if incorrect) is ignored: - # - # Base64.decode64("MDEyMzQ1Njc") # => "01234567" - # Base64.decode64("MDEyMzQ1Njc=") # => "01234567" - # Base64.decode64("MDEyMzQ1Njc==") # => "01234567" - # - def decode64(str) - str.unpack1("m") - end - - # Returns a string containing the RFC-2045-compliant \Base64-encoding of +bin+. - # - # Per RFC 2045, the returned string may contain the URL-unsafe characters - # + or /; - # see {Encoding Character Set}[Base64.html#module-Base64-label-Encoding+Character+Sets] above: - # - # Base64.strict_encode64("\xFB\xEF\xBE") # => "++++\n" - # Base64.strict_encode64("\xFF\xFF\xFF") # => "////\n" - # - # The returned string may include padding; - # see {Padding}[Base64.html#module-Base64-label-Padding] above. - # - # Base64.strict_encode64('*') # => "Kg==\n" - # - # The returned string will have no newline characters, regardless of its length; - # see {Newlines}[Base64.html#module-Base64-label-Newlines] above: - # - # Base64.strict_encode64('*') # => "Kg==" - # Base64.strict_encode64('*' * 46) - # # => "KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKg==" - # - # The string to be encoded may itself contain newlines, - # which will be encoded as ordinary \Base64: - # - # Base64.strict_encode64("\n\n\n") # => "CgoK" - # s = "This is line 1\nThis is line 2\n" - # Base64.strict_encode64(s) # => "VGhpcyBpcyBsaW5lIDEKVGhpcyBpcyBsaW5lIDIK" - # - def strict_encode64(bin) - [bin].pack("m0") - end - - # Returns a string containing the decoding of an RFC-2045-compliant - # \Base64-encoded string +str+: - # - # s = "VGhpcyBpcyBsaW5lIDEKVGhpcyBpcyBsaW5lIDIK" - # Base64.strict_decode64(s) # => "This is line 1\nThis is line 2\n" - # - # Non-\Base64 characters in +str+ not allowed; - # see {Encoding Character Set}[Base64.html#module-Base64-label-Encoding+Character+Sets] above: - # these include newline characters and characters - and /: - # - # Base64.strict_decode64("\n") # Raises ArgumentError - # Base64.strict_decode64('-') # Raises ArgumentError - # Base64.strict_decode64('_') # Raises ArgumentError - # - # Padding in +str+, if present, must be correct: - # - # Base64.strict_decode64("MDEyMzQ1Njc") # Raises ArgumentError - # Base64.strict_decode64("MDEyMzQ1Njc=") # => "01234567" - # Base64.strict_decode64("MDEyMzQ1Njc==") # Raises ArgumentError - # - def strict_decode64(str) - str.unpack1("m0") - end - - # Returns the RFC-4648-compliant \Base64-encoding of +bin+. - # - # Per RFC 4648, the returned string will not contain the URL-unsafe characters - # + or /, - # but instead may contain the URL-safe characters - # - and _; - # see {Encoding Character Set}[Base64.html#module-Base64-label-Encoding+Character+Sets] above: - # - # Base64.urlsafe_encode64("\xFB\xEF\xBE") # => "----" - # Base64.urlsafe_encode64("\xFF\xFF\xFF") # => "____" - # - # By default, the returned string may have padding; - # see {Padding}[Base64.html#module-Base64-label-Padding], above: - # - # Base64.urlsafe_encode64('*') # => "Kg==" - # - # Optionally, you can suppress padding: - # - # Base64.urlsafe_encode64('*', padding: false) # => "Kg" - # - # The returned string will have no newline characters, regardless of its length; - # see {Newlines}[Base64.html#module-Base64-label-Newlines] above: - # - # Base64.urlsafe_encode64('*') # => "Kg==" - # Base64.urlsafe_encode64('*' * 46) - # # => "KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKg==" - # - def urlsafe_encode64(bin, padding: true) - str = strict_encode64(bin) - str.chomp!("==") or str.chomp!("=") unless padding - str.tr!("+/", "-_") - str - end - - # Returns the decoding of an RFC-4648-compliant \Base64-encoded string +str+: - # - # +str+ may not contain non-Base64 characters; - # see {Encoding Character Set}[Base64.html#module-Base64-label-Encoding+Character+Sets] above: - # - # Base64.urlsafe_decode64('+') # Raises ArgumentError. - # Base64.urlsafe_decode64('/') # Raises ArgumentError. - # Base64.urlsafe_decode64("\n") # Raises ArgumentError. - # - # Padding in +str+, if present, must be correct: - # see {Padding}[Base64.html#module-Base64-label-Padding], above: - # - # Base64.urlsafe_decode64("MDEyMzQ1Njc") # => "01234567" - # Base64.urlsafe_decode64("MDEyMzQ1Njc=") # => "01234567" - # Base64.urlsafe_decode64("MDEyMzQ1Njc==") # Raises ArgumentError. - # - def urlsafe_decode64(str) - # NOTE: RFC 4648 does say nothing about unpadded input, but says that - # "the excess pad characters MAY also be ignored", so it is inferred that - # unpadded input is also acceptable. - if !str.end_with?("=") && str.length % 4 != 0 - str = str.ljust((str.length + 3) & ~3, "=") - str.tr!("-_", "+/") - else - str = str.tr("-_", "+/") - end - strict_decode64(str) - end -end diff --git a/test/base64/test_base64.rb b/test/base64/test_base64.rb deleted file mode 100644 index ce716043a8eadb..00000000000000 --- a/test/base64/test_base64.rb +++ /dev/null @@ -1,115 +0,0 @@ -# coding: US-ASCII -# frozen_string_literal: true -require "test/unit" -require "base64" - -class TestBase64 < Test::Unit::TestCase - def test_sample - assert_equal("U2VuZCByZWluZm9yY2VtZW50cw==\n", Base64.encode64('Send reinforcements')) - assert_equal('Send reinforcements', Base64.decode64("U2VuZCByZWluZm9yY2VtZW50cw==\n")) - assert_equal( - "Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBjb2RlcnMKdG8gbGVhcm4g\nUnVieQ==\n", - Base64.encode64("Now is the time for all good coders\nto learn Ruby")) - assert_equal( - "Now is the time for all good coders\nto learn Ruby", - Base64.decode64("Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBjb2RlcnMKdG8gbGVhcm4g\nUnVieQ==\n")) - assert_equal( - "VGhpcyBpcyBsaW5lIG9uZQpUaGlzIGlzIGxpbmUgdHdvClRoaXMgaXMgbGlu\nZSB0aHJlZQpBbmQgc28gb24uLi4K\n", - Base64.encode64("This is line one\nThis is line two\nThis is line three\nAnd so on...\n")) - assert_equal( - "This is line one\nThis is line two\nThis is line three\nAnd so on...\n", - Base64.decode64("VGhpcyBpcyBsaW5lIG9uZQpUaGlzIGlzIGxpbmUgdHdvClRoaXMgaXMgbGluZSB0aHJlZQpBbmQgc28gb24uLi4K")) - end - - def test_encode64 - assert_equal("", Base64.encode64("")) - assert_equal("AA==\n", Base64.encode64("\0")) - assert_equal("AAA=\n", Base64.encode64("\0\0")) - assert_equal("AAAA\n", Base64.encode64("\0\0\0")) - assert_equal("/w==\n", Base64.encode64("\377")) - assert_equal("//8=\n", Base64.encode64("\377\377")) - assert_equal("////\n", Base64.encode64("\377\377\377")) - assert_equal("/+8=\n", Base64.encode64("\xff\xef")) - end - - def test_decode64 - assert_equal("", Base64.decode64("")) - assert_equal("\0", Base64.decode64("AA==\n")) - assert_equal("\0\0", Base64.decode64("AAA=\n")) - assert_equal("\0\0\0", Base64.decode64("AAAA\n")) - assert_equal("\377", Base64.decode64("/w==\n")) - assert_equal("\377\377", Base64.decode64("//8=\n")) - assert_equal("\377\377\377", Base64.decode64("////\n")) - assert_equal("\xff\xef", Base64.decode64("/+8=\n")) - end - - def test_strict_encode64 - assert_equal("", Base64.strict_encode64("")) - assert_equal("AA==", Base64.strict_encode64("\0")) - assert_equal("AAA=", Base64.strict_encode64("\0\0")) - assert_equal("AAAA", Base64.strict_encode64("\0\0\0")) - assert_equal("/w==", Base64.strict_encode64("\377")) - assert_equal("//8=", Base64.strict_encode64("\377\377")) - assert_equal("////", Base64.strict_encode64("\377\377\377")) - assert_equal("/+8=", Base64.strict_encode64("\xff\xef")) - end - - def test_strict_decode64 - assert_equal("", Base64.strict_decode64("")) - assert_equal("\0", Base64.strict_decode64("AA==")) - assert_equal("\0\0", Base64.strict_decode64("AAA=")) - assert_equal("\0\0\0", Base64.strict_decode64("AAAA")) - assert_equal("\377", Base64.strict_decode64("/w==")) - assert_equal("\377\377", Base64.strict_decode64("//8=")) - assert_equal("\377\377\377", Base64.strict_decode64("////")) - assert_equal("\xff\xef", Base64.strict_decode64("/+8=")) - - assert_raise(ArgumentError) { Base64.strict_decode64("^") } - assert_raise(ArgumentError) { Base64.strict_decode64("A") } - assert_raise(ArgumentError) { Base64.strict_decode64("A^") } - assert_raise(ArgumentError) { Base64.strict_decode64("AA") } - assert_raise(ArgumentError) { Base64.strict_decode64("AA=") } - assert_raise(ArgumentError) { Base64.strict_decode64("AA===") } - assert_raise(ArgumentError) { Base64.strict_decode64("AA=x") } - assert_raise(ArgumentError) { Base64.strict_decode64("AAA") } - assert_raise(ArgumentError) { Base64.strict_decode64("AAA^") } - assert_raise(ArgumentError) { Base64.strict_decode64("AB==") } - assert_raise(ArgumentError) { Base64.strict_decode64("AAB=") } - end - - def test_urlsafe_encode64 - assert_equal("", Base64.urlsafe_encode64("")) - assert_equal("AA==", Base64.urlsafe_encode64("\0")) - assert_equal("AAA=", Base64.urlsafe_encode64("\0\0")) - assert_equal("AAAA", Base64.urlsafe_encode64("\0\0\0")) - assert_equal("_w==", Base64.urlsafe_encode64("\377")) - assert_equal("__8=", Base64.urlsafe_encode64("\377\377")) - assert_equal("____", Base64.urlsafe_encode64("\377\377\377")) - assert_equal("_-8=", Base64.urlsafe_encode64("\xff\xef")) - end - - def test_urlsafe_encode64_unpadded - assert_equal("", Base64.urlsafe_encode64("", padding: false)) - assert_equal("AA", Base64.urlsafe_encode64("\0", padding: false)) - assert_equal("AAA", Base64.urlsafe_encode64("\0\0", padding: false)) - assert_equal("AAAA", Base64.urlsafe_encode64("\0\0\0", padding: false)) - end - - def test_urlsafe_decode64 - assert_equal("", Base64.urlsafe_decode64("")) - assert_equal("\0", Base64.urlsafe_decode64("AA==")) - assert_equal("\0\0", Base64.urlsafe_decode64("AAA=")) - assert_equal("\0\0\0", Base64.urlsafe_decode64("AAAA")) - assert_equal("\377", Base64.urlsafe_decode64("_w==")) - assert_equal("\377\377", Base64.urlsafe_decode64("__8=")) - assert_equal("\377\377\377", Base64.urlsafe_decode64("____")) - assert_equal("\xff\xef", Base64.urlsafe_decode64("_+8=")) - end - - def test_urlsafe_decode64_unpadded - assert_equal("\0", Base64.urlsafe_decode64("AA")) - assert_equal("\0\0", Base64.urlsafe_decode64("AAA")) - assert_equal("\0\0\0", Base64.urlsafe_decode64("AAAA")) - assert_raise(ArgumentError) { Base64.urlsafe_decode64("AA=") } - end -end From 05e798269fd4471fbc87f3e4de7728b28b6a0915 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 11 Jan 2024 11:33:40 +0900 Subject: [PATCH 181/640] Document about base64 at Ruby 3.4 --- doc/maintainers.md | 8 +++----- doc/standard_library.rdoc | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/doc/maintainers.md b/doc/maintainers.md index 1a3f5ec2fb8939..32aa64dce150fb 100644 --- a/doc/maintainers.md +++ b/doc/maintainers.md @@ -77,11 +77,6 @@ have commit right, others don't. * https://github.com/ruby/abbrev * https://rubygems.org/gems/abbrev -#### lib/base64.rb -* Yusuke Endoh (mame) -* https://github.com/ruby/base64 -* https://rubygems.org/gems/base64 - #### lib/benchmark.rb * *unmaintained* * https://github.com/ruby/benchmark @@ -483,6 +478,9 @@ have commit right, others don't. #### lib/getoptlong.rb * https://github.com/ruby/getoptlong +#### lib/base64.rb +* https://github.com/ruby/base64 + ## Platform Maintainers ### mswin64 (Microsoft Windows) * NAKAMURA Usaku (usa) diff --git a/doc/standard_library.rdoc b/doc/standard_library.rdoc index 7c102372d7169f..68fc34de01eb65 100644 --- a/doc/standard_library.rdoc +++ b/doc/standard_library.rdoc @@ -34,7 +34,6 @@ Socket:: Access underlying OS socket implementations == Libraries Abbrev:: Calculates a set of unique abbreviations for a given set of strings -Base64:: Support for encoding and decoding binary data using a Base64 representation Benchmark:: Provides methods to measure and report the time used to execute code Bundler:: Manage your Ruby application's gem dependencies CGI:: Support for the Common Gateway Interface protocol @@ -130,3 +129,4 @@ DEBUGGER__:: Debugging functionality for Ruby Racc:: A LALR(1) parser generator written in Ruby. Mutex_m:: Mixin to extend objects to be handled like a Mutex GetoptLong:: Parse command line options similar to the GNU C getopt_long() +Base64:: Support for encoding and decoding binary data using a Base64 representation From afb30eb2654253c938fbf47dbb6e24c2a3b74625 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 11 Jan 2024 11:34:25 +0900 Subject: [PATCH 182/640] spec/mspec/tool/wrap_with_guard.rb 'ruby_version_is ""..."3.4"' spec/ruby/library/base64/**/*_spec.rb --- spec/ruby/library/base64/decode64_spec.rb | 41 +++++----- spec/ruby/library/base64/encode64_spec.rb | 33 ++++---- .../library/base64/strict_decode64_spec.rb | 77 ++++++++++--------- .../library/base64/strict_encode64_spec.rb | 27 ++++--- .../library/base64/urlsafe_decode64_spec.rb | 27 ++++--- .../library/base64/urlsafe_encode64_spec.rb | 29 +++---- 6 files changed, 126 insertions(+), 108 deletions(-) diff --git a/spec/ruby/library/base64/decode64_spec.rb b/spec/ruby/library/base64/decode64_spec.rb index 6dd33dddfe2e2a..c587c82d28f088 100644 --- a/spec/ruby/library/base64/decode64_spec.rb +++ b/spec/ruby/library/base64/decode64_spec.rb @@ -1,29 +1,32 @@ require_relative '../../spec_helper' -require 'base64' +ruby_version_is ""..."3.4" do -describe "Base64#decode64" do - it "returns the Base64-decoded version of the given string" do - Base64.decode64("U2VuZCByZWluZm9yY2VtZW50cw==\n").should == "Send reinforcements" - end + require 'base64' - it "returns the Base64-decoded version of the given shared string" do - Base64.decode64("base64: U2VuZCByZWluZm9yY2VtZW50cw==\n".split(" ").last).should == "Send reinforcements" - end + describe "Base64#decode64" do + it "returns the Base64-decoded version of the given string" do + Base64.decode64("U2VuZCByZWluZm9yY2VtZW50cw==\n").should == "Send reinforcements" + end - it "returns the Base64-decoded version of the given string with wrong padding" do - Base64.decode64("XU2VuZCByZWluZm9yY2VtZW50cw===").should == "]M\x95\xB9\x90\x81\xC9\x95\xA5\xB9\x99\xBD\xC9\x8D\x95\xB5\x95\xB9\xD1\xCC".b - end + it "returns the Base64-decoded version of the given shared string" do + Base64.decode64("base64: U2VuZCByZWluZm9yY2VtZW50cw==\n".split(" ").last).should == "Send reinforcements" + end - it "returns the Base64-decoded version of the given string that contains an invalid character" do - Base64.decode64("%3D").should == "\xDC".b - end + it "returns the Base64-decoded version of the given string with wrong padding" do + Base64.decode64("XU2VuZCByZWluZm9yY2VtZW50cw===").should == "]M\x95\xB9\x90\x81\xC9\x95\xA5\xB9\x99\xBD\xC9\x8D\x95\xB5\x95\xB9\xD1\xCC".b + end - it "returns a binary encoded string" do - Base64.decode64("SEk=").encoding.should == Encoding::BINARY - end + it "returns the Base64-decoded version of the given string that contains an invalid character" do + Base64.decode64("%3D").should == "\xDC".b + end + + it "returns a binary encoded string" do + Base64.decode64("SEk=").encoding.should == Encoding::BINARY + end - it "decodes without padding suffix ==" do - Base64.decode64("eyJrZXkiOnsibiI6InR0dCJ9fQ").should == "{\"key\":{\"n\":\"ttt\"}}" + it "decodes without padding suffix ==" do + Base64.decode64("eyJrZXkiOnsibiI6InR0dCJ9fQ").should == "{\"key\":{\"n\":\"ttt\"}}" + end end end diff --git a/spec/ruby/library/base64/encode64_spec.rb b/spec/ruby/library/base64/encode64_spec.rb index 64de6257bc86ed..e31c6604f0a347 100644 --- a/spec/ruby/library/base64/encode64_spec.rb +++ b/spec/ruby/library/base64/encode64_spec.rb @@ -1,23 +1,26 @@ require_relative '../../spec_helper' -require 'base64' +ruby_version_is ""..."3.4" do -describe "Base64#encode64" do - it "returns the Base64-encoded version of the given string" do - Base64.encode64("Now is the time for all good coders\nto learn Ruby").should == - "Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBjb2RlcnMKdG8gbGVhcm4g\nUnVieQ==\n" - end + require 'base64' - it "returns the Base64-encoded version of the given string" do - Base64.encode64('Send reinforcements').should == "U2VuZCByZWluZm9yY2VtZW50cw==\n" - end + describe "Base64#encode64" do + it "returns the Base64-encoded version of the given string" do + Base64.encode64("Now is the time for all good coders\nto learn Ruby").should == + "Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBjb2RlcnMKdG8gbGVhcm4g\nUnVieQ==\n" + end - it "returns the Base64-encoded version of the given shared string" do - Base64.encode64("Now is the time for all good coders\nto learn Ruby".split("\n").last).should == - "dG8gbGVhcm4gUnVieQ==\n" - end + it "returns the Base64-encoded version of the given string" do + Base64.encode64('Send reinforcements').should == "U2VuZCByZWluZm9yY2VtZW50cw==\n" + end + + it "returns the Base64-encoded version of the given shared string" do + Base64.encode64("Now is the time for all good coders\nto learn Ruby".split("\n").last).should == + "dG8gbGVhcm4gUnVieQ==\n" + end - it "returns a US_ASCII encoded string" do - Base64.encode64("HI").encoding.should == Encoding::US_ASCII + it "returns a US_ASCII encoded string" do + Base64.encode64("HI").encoding.should == Encoding::US_ASCII + end end end diff --git a/spec/ruby/library/base64/strict_decode64_spec.rb b/spec/ruby/library/base64/strict_decode64_spec.rb index d258223c827277..f4dd3a60fe979c 100644 --- a/spec/ruby/library/base64/strict_decode64_spec.rb +++ b/spec/ruby/library/base64/strict_decode64_spec.rb @@ -1,41 +1,44 @@ require_relative '../../spec_helper' -require 'base64' - -describe "Base64#strict_decode64" do - it "returns the Base64-decoded version of the given string" do - Base64.strict_decode64("U2VuZCByZWluZm9yY2VtZW50cw==").should == "Send reinforcements" - end - - it "returns the Base64-decoded version of the given shared string" do - Base64.strict_decode64("base64: U2VuZCByZWluZm9yY2VtZW50cw==".split(" ").last).should == "Send reinforcements" - end - - it "raises ArgumentError when the given string contains CR" do - -> do - Base64.strict_decode64("U2VuZCByZWluZm9yY2VtZW50cw==\r") - end.should raise_error(ArgumentError) - end - - it "raises ArgumentError when the given string contains LF" do - -> do - Base64.strict_decode64("U2VuZCByZWluZm9yY2VtZW50cw==\n") - end.should raise_error(ArgumentError) - end - - it "raises ArgumentError when the given string has wrong padding" do - -> do - Base64.strict_decode64("=U2VuZCByZWluZm9yY2VtZW50cw==") - end.should raise_error(ArgumentError) - end - - it "raises ArgumentError when the given string contains an invalid character" do - -> do - Base64.strict_decode64("%3D") - end.should raise_error(ArgumentError) - end - - it "returns a binary encoded string" do - Base64.strict_decode64("SEk=").encoding.should == Encoding::BINARY +ruby_version_is ""..."3.4" do + + require 'base64' + + describe "Base64#strict_decode64" do + it "returns the Base64-decoded version of the given string" do + Base64.strict_decode64("U2VuZCByZWluZm9yY2VtZW50cw==").should == "Send reinforcements" + end + + it "returns the Base64-decoded version of the given shared string" do + Base64.strict_decode64("base64: U2VuZCByZWluZm9yY2VtZW50cw==".split(" ").last).should == "Send reinforcements" + end + + it "raises ArgumentError when the given string contains CR" do + -> do + Base64.strict_decode64("U2VuZCByZWluZm9yY2VtZW50cw==\r") + end.should raise_error(ArgumentError) + end + + it "raises ArgumentError when the given string contains LF" do + -> do + Base64.strict_decode64("U2VuZCByZWluZm9yY2VtZW50cw==\n") + end.should raise_error(ArgumentError) + end + + it "raises ArgumentError when the given string has wrong padding" do + -> do + Base64.strict_decode64("=U2VuZCByZWluZm9yY2VtZW50cw==") + end.should raise_error(ArgumentError) + end + + it "raises ArgumentError when the given string contains an invalid character" do + -> do + Base64.strict_decode64("%3D") + end.should raise_error(ArgumentError) + end + + it "returns a binary encoded string" do + Base64.strict_decode64("SEk=").encoding.should == Encoding::BINARY + end end end diff --git a/spec/ruby/library/base64/strict_encode64_spec.rb b/spec/ruby/library/base64/strict_encode64_spec.rb index 7cabcf190cc100..c7f9f12a9692fd 100644 --- a/spec/ruby/library/base64/strict_encode64_spec.rb +++ b/spec/ruby/library/base64/strict_encode64_spec.rb @@ -1,19 +1,22 @@ require_relative '../../spec_helper' -require 'base64' +ruby_version_is ""..."3.4" do -describe "Base64#strict_encode64" do - it "returns the Base64-encoded version of the given string" do - Base64.strict_encode64("Now is the time for all good coders\nto learn Ruby").should == - "Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBjb2RlcnMKdG8gbGVhcm4gUnVieQ==" - end + require 'base64' - it "returns the Base64-encoded version of the given shared string" do - Base64.strict_encode64("Now is the time for all good coders\nto learn Ruby".split("\n").last).should == - "dG8gbGVhcm4gUnVieQ==" - end + describe "Base64#strict_encode64" do + it "returns the Base64-encoded version of the given string" do + Base64.strict_encode64("Now is the time for all good coders\nto learn Ruby").should == + "Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBjb2RlcnMKdG8gbGVhcm4gUnVieQ==" + end + + it "returns the Base64-encoded version of the given shared string" do + Base64.strict_encode64("Now is the time for all good coders\nto learn Ruby".split("\n").last).should == + "dG8gbGVhcm4gUnVieQ==" + end - it "returns a US_ASCII encoded string" do - Base64.strict_encode64("HI").encoding.should == Encoding::US_ASCII + it "returns a US_ASCII encoded string" do + Base64.strict_encode64("HI").encoding.should == Encoding::US_ASCII + end end end diff --git a/spec/ruby/library/base64/urlsafe_decode64_spec.rb b/spec/ruby/library/base64/urlsafe_decode64_spec.rb index 1b813ee1b943da..f9a46787f71758 100644 --- a/spec/ruby/library/base64/urlsafe_decode64_spec.rb +++ b/spec/ruby/library/base64/urlsafe_decode64_spec.rb @@ -1,19 +1,22 @@ require_relative '../../spec_helper' -require 'base64' +ruby_version_is ""..."3.4" do -describe "Base64#urlsafe_decode64" do - it "uses '_' instead of '/'" do - decoded = Base64.urlsafe_decode64("V2hlcmUgYW0gST8gV2hvIGFtIEk_IEFtIEk_IEk_") - decoded.should == 'Where am I? Who am I? Am I? I?' - end + require 'base64' - it "uses '-' instead of '+'" do - decoded = Base64.urlsafe_decode64('IkJlaW5nIGRpc2ludGVncmF0ZWQgbWFrZXMgbWUgdmUtcnkgYW4tZ3J5ISIgPGh1ZmYsIGh1ZmY-') - decoded.should == '"Being disintegrated makes me ve-ry an-gry!" ' - end + describe "Base64#urlsafe_decode64" do + it "uses '_' instead of '/'" do + decoded = Base64.urlsafe_decode64("V2hlcmUgYW0gST8gV2hvIGFtIEk_IEFtIEk_IEk_") + decoded.should == 'Where am I? Who am I? Am I? I?' + end + + it "uses '-' instead of '+'" do + decoded = Base64.urlsafe_decode64('IkJlaW5nIGRpc2ludGVncmF0ZWQgbWFrZXMgbWUgdmUtcnkgYW4tZ3J5ISIgPGh1ZmYsIGh1ZmY-') + decoded.should == '"Being disintegrated makes me ve-ry an-gry!" ' + end - it "does not require padding" do - Base64.urlsafe_decode64("MQ").should == "1" + it "does not require padding" do + Base64.urlsafe_decode64("MQ").should == "1" + end end end diff --git a/spec/ruby/library/base64/urlsafe_encode64_spec.rb b/spec/ruby/library/base64/urlsafe_encode64_spec.rb index de1f235ceab035..0c7b08757eef3b 100644 --- a/spec/ruby/library/base64/urlsafe_encode64_spec.rb +++ b/spec/ruby/library/base64/urlsafe_encode64_spec.rb @@ -1,20 +1,23 @@ require_relative '../../spec_helper' -require 'base64' +ruby_version_is ""..."3.4" do -describe "Base64#urlsafe_encode64" do - it "uses '_' instead of '/'" do - encoded = Base64.urlsafe_encode64('Where am I? Who am I? Am I? I?') - encoded.should == "V2hlcmUgYW0gST8gV2hvIGFtIEk_IEFtIEk_IEk_" - end + require 'base64' - it "uses '-' instead of '+'" do - encoded = Base64.urlsafe_encode64('"Being disintegrated makes me ve-ry an-gry!" ') - encoded.should == 'IkJlaW5nIGRpc2ludGVncmF0ZWQgbWFrZXMgbWUgdmUtcnkgYW4tZ3J5ISIgPGh1ZmYsIGh1ZmY-' - end + describe "Base64#urlsafe_encode64" do + it "uses '_' instead of '/'" do + encoded = Base64.urlsafe_encode64('Where am I? Who am I? Am I? I?') + encoded.should == "V2hlcmUgYW0gST8gV2hvIGFtIEk_IEFtIEk_IEk_" + end + + it "uses '-' instead of '+'" do + encoded = Base64.urlsafe_encode64('"Being disintegrated makes me ve-ry an-gry!" ') + encoded.should == 'IkJlaW5nIGRpc2ludGVncmF0ZWQgbWFrZXMgbWUgdmUtcnkgYW4tZ3J5ISIgPGh1ZmYsIGh1ZmY-' + end - it "makes padding optional" do - Base64.urlsafe_encode64("1", padding: false).should == "MQ" - Base64.urlsafe_encode64("1").should == "MQ==" + it "makes padding optional" do + Base64.urlsafe_encode64("1", padding: false).should == "MQ" + Base64.urlsafe_encode64("1").should == "MQ==" + end end end From 42aa24a24c2a3ea2868e0a2d31d5cd6a7513b007 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 16 Jan 2024 17:25:44 +0900 Subject: [PATCH 183/640] No longer needed to sync base64 --- tool/sync_default_gems.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb index d1b761078ec03b..d403a01667d6f7 100755 --- a/tool/sync_default_gems.rb +++ b/tool/sync_default_gems.rb @@ -20,7 +20,6 @@ module SyncDefaultGems "resolv-replace": "ruby/resolv-replace", English: "ruby/English", abbrev: "ruby/abbrev", - base64: "ruby/base64", benchmark: "ruby/benchmark", bigdecimal: "ruby/bigdecimal", cgi: "ruby/cgi", From 6c016a4197c233b08a038e3ae7bc919bb16fdd8a Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 16 Jan 2024 19:07:10 +0900 Subject: [PATCH 184/640] Inject base64 for basic auth examples of bundler --- spec/bundler/support/artifice/endpoint_500.rb | 2 +- spec/bundler/support/artifice/helpers/endpoint.rb | 2 +- spec/bundler/support/artifice/windows.rb | 2 +- tool/bundler/test_gems.rb | 1 + 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/spec/bundler/support/artifice/endpoint_500.rb b/spec/bundler/support/artifice/endpoint_500.rb index d8ab6b65bcf871..b1ed1964c83d0e 100644 --- a/spec/bundler/support/artifice/endpoint_500.rb +++ b/spec/bundler/support/artifice/endpoint_500.rb @@ -2,7 +2,7 @@ require_relative "../path" -$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{mustermann,rack,tilt,sinatra,ruby2_keywords}-*/lib")].map(&:to_s)) +$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{mustermann,rack,tilt,sinatra,ruby2_keywords,base64}-*/lib")].map(&:to_s)) require "sinatra/base" diff --git a/spec/bundler/support/artifice/helpers/endpoint.rb b/spec/bundler/support/artifice/helpers/endpoint.rb index be52df69365ff3..83ba1be0fc019b 100644 --- a/spec/bundler/support/artifice/helpers/endpoint.rb +++ b/spec/bundler/support/artifice/helpers/endpoint.rb @@ -2,7 +2,7 @@ require_relative "../../path" -$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{mustermann,rack,tilt,sinatra,ruby2_keywords}-*/lib")].map(&:to_s)) +$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{mustermann,rack,tilt,sinatra,ruby2_keywords,base64}-*/lib")].map(&:to_s)) require "sinatra/base" diff --git a/spec/bundler/support/artifice/windows.rb b/spec/bundler/support/artifice/windows.rb index 4d90e0a4266c63..fea991c071d6b7 100644 --- a/spec/bundler/support/artifice/windows.rb +++ b/spec/bundler/support/artifice/windows.rb @@ -2,7 +2,7 @@ require_relative "../path" -$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{mustermann,rack,tilt,sinatra,ruby2_keywords}-*/lib")].map(&:to_s)) +$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{mustermann,rack,tilt,sinatra,ruby2_keywords,base64}-*/lib")].map(&:to_s)) require "sinatra/base" diff --git a/tool/bundler/test_gems.rb b/tool/bundler/test_gems.rb index aa1cfd09a50936..32cb6b34eef43d 100644 --- a/tool/bundler/test_gems.rb +++ b/tool/bundler/test_gems.rb @@ -3,6 +3,7 @@ source "https://rubygems.org" gem "rack", "~> 2.0" +gem "base64" gem "webrick", "1.7.0" gem "rack-test", "~> 1.1" gem "compact_index", "~> 0.15.0" From 88bb09b3beb4c9efbfad874aef2dc1faf6bea4e5 Mon Sep 17 00:00:00 2001 From: git Date: Tue, 16 Jan 2024 23:29:01 +0000 Subject: [PATCH 185/640] Update bundled gems list at 6c016a4197c233b08a038e3ae7bc91 [ci skip] --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index f277eafa2c1298..f7c634425b5121 100644 --- a/NEWS.md +++ b/NEWS.md @@ -47,6 +47,7 @@ The following bundled gems are promoted from default gems. * mutex_m 0.2.0 * getoptlong 0.2.1 +* base64 0.2.0 See GitHub releases like [GitHub Releases of Logger](https://github.com/ruby/logger/releases) or changelog for details of the default gems or bundled gems. From b4ed5b7dfe9ca01ef48922d1b2c154767b7e4e86 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Tue, 16 Jan 2024 15:54:17 -0800 Subject: [PATCH 186/640] Bump the required BASERUBY version to 2.7 (#9566) [[Misc #16671]](https://bugs.ruby-lang.org/issues/16671) --- .github/workflows/baseruby.yml | 4 +--- .github/workflows/mingw.yml | 4 ++-- .github/workflows/windows.yml | 5 +++++ configure.ac | 4 ++-- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/baseruby.yml b/.github/workflows/baseruby.yml index 5ead3fa03f4883..674b42b8b70608 100644 --- a/.github/workflows/baseruby.yml +++ b/.github/workflows/baseruby.yml @@ -50,9 +50,7 @@ jobs: strategy: matrix: ruby: - - ruby-2.5 -# - ruby-2.6 -# - ruby-2.7 + - ruby-2.7 - ruby-3.0 - ruby-3.1 - ruby-3.2 diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml index c7a550c7c79251..5ed71716f9fc04 100644 --- a/.github/workflows/mingw.yml +++ b/.github/workflows/mingw.yml @@ -59,7 +59,7 @@ jobs: include: # To mitigate flakiness of MinGW CI, we test only one runtime that newer MSYS2 uses. - msystem: 'UCRT64' - base_ruby: head + baseruby: '2.7' test_task: 'check' test-all-opts: '--name=!/TestObjSpace#test_reachable_objects_during_iteration/' fail-fast: false @@ -76,7 +76,7 @@ jobs: - name: Set up Ruby & MSYS2 uses: ruby/setup-ruby@360dc864d5da99d54fcb8e9148c14a84b90d3e88 # v1.165.1 with: - ruby-version: ${{ matrix.base_ruby }} + ruby-version: ${{ matrix.baseruby }} - name: where check run: | diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index a31545fe5a37a5..c8d61be7630a5d 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -133,6 +133,7 @@ jobs: builddir: build - name: setup env + # Available Ruby versions: https://github.com/actions/runner-images/blob/main/images/windows/Windows2019-Readme.md#ruby # %TEMP% is inconsistent with %TMP% and test-all expects they are consistent. # https://github.com/actions/virtual-environments/issues/712#issuecomment-613004302 run: | @@ -146,10 +147,14 @@ jobs: set TEMP=%USERPROFILE%\AppData\Local\Temp set MAKEFLAGS=l set /a TEST_JOBS=(15 * %NUMBER_OF_PROCESSORS% / 10) > nul + set PATH=C:\hostedtoolcache\windows\Ruby\2.7.8\x64\bin;%PATH% set | C:\msys64\usr\bin\sort > new.env C:\msys64\usr\bin\comm -13 old.env new.env >> %GITHUB_ENV% del *.env + - name: baseruby version + run: ruby -v + - name: compiler version run: cl diff --git a/configure.ac b/configure.ac index 277c8747c0001e..54d0b5b47428a4 100644 --- a/configure.ac +++ b/configure.ac @@ -75,8 +75,8 @@ AC_ARG_WITH(baseruby, [ AC_PATH_PROG([BASERUBY], [ruby], [false]) ]) -# BASERUBY must be >= 2.5.0. Note that `"2.5.0" > "2.5"` is true. -AS_IF([test "$HAVE_BASERUBY" != no -a "`RUBYOPT=- $BASERUBY --disable=gems -e 'print 42 if RUBY_VERSION > "2.5"' 2>/dev/null`" = 42], [ +# BASERUBY must be >= 2.7.0. Note that `"2.7.0" > "2.7"` is true. +AS_IF([test "$HAVE_BASERUBY" != no -a "`RUBYOPT=- $BASERUBY --disable=gems -e 'print 42 if RUBY_VERSION > "2.7"' 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 From cf8fb9429511068c69ce70da7f7818c7441c280b Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 17 Jan 2024 09:01:56 +0900 Subject: [PATCH 187/640] CHECK_LEAKS is always enabled with 01459f1 --- .github/workflows/annocheck.yml | 2 -- .github/workflows/compilers.yml | 2 -- .github/workflows/spec_guards.yml | 2 -- 3 files changed, 6 deletions(-) diff --git a/.github/workflows/annocheck.yml b/.github/workflows/annocheck.yml index aa871662544cff..da39efa9e36c1b 100644 --- a/.github/workflows/annocheck.yml +++ b/.github/workflows/annocheck.yml @@ -111,8 +111,6 @@ jobs: ### test-spec doesn't work: https://github.com/ruby/ruby/actions/runs/4340193212/jobs/7578505652 # - run: make test-spec - # env: - # CHECK_LEAKS: true - run: make test-annocheck diff --git a/.github/workflows/compilers.yml b/.github/workflows/compilers.yml index 233f4c5db396a6..95a89a1a9762f8 100644 --- a/.github/workflows/compilers.yml +++ b/.github/workflows/compilers.yml @@ -278,8 +278,6 @@ jobs: if: ${{ matrix.entry.check }} - run: make test-spec - env: - CHECK_LEAKS: true if: ${{ matrix.entry.check }} - run: make test-annocheck diff --git a/.github/workflows/spec_guards.yml b/.github/workflows/spec_guards.yml index f28c91d4af6dae..fb479304236382 100644 --- a/.github/workflows/spec_guards.yml +++ b/.github/workflows/spec_guards.yml @@ -57,8 +57,6 @@ jobs: - run: ruby ../mspec/bin/mspec working-directory: spec/ruby - env: - CHECK_LEAKS: true - uses: ./.github/actions/slack with: From 8ae24e6b085121c6d3de61b45cf089849fe4a177 Mon Sep 17 00:00:00 2001 From: Colin Kelley Date: Wed, 19 Jul 2023 12:32:12 -0700 Subject: [PATCH 188/640] [ruby/psych] issue #443: quote Y and N when dumping https://github.com/ruby/psych/commit/93c8fb443a --- ext/psych/lib/psych/visitors/yaml_tree.rb | 2 +- test/psych/test_string.rb | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/ext/psych/lib/psych/visitors/yaml_tree.rb b/ext/psych/lib/psych/visitors/yaml_tree.rb index 4abdda31d6d2f8..318f5f892b28b7 100644 --- a/ext/psych/lib/psych/visitors/yaml_tree.rb +++ b/ext/psych/lib/psych/visitors/yaml_tree.rb @@ -267,7 +267,7 @@ def visit_String o tag = 'tag:yaml.org,2002:str' plain = false quote = false - elsif o == 'y' || o == 'n' + elsif o == 'y' || o == 'Y' || o == 'n' || o == 'N' style = Nodes::Scalar::DOUBLE_QUOTED elsif @line_width && o.length > @line_width style = Nodes::Scalar::FOLDED diff --git a/test/psych/test_string.rb b/test/psych/test_string.rb index 0dc34b3083d641..c996a8fc2dc197 100644 --- a/test/psych/test_string.rb +++ b/test/psych/test_string.rb @@ -24,10 +24,19 @@ def initialize # "ambiguity" in the emitted document def test_y_is_quoted assert_match(/"y"/, Psych.dump("y")) + assert_match(/"Y"/, Psych.dump("Y")) end def test_n_is_quoted assert_match(/"n"/, Psych.dump("n")) + assert_match(/"N"/, Psych.dump("N")) + end + + def test_all_yaml_1_1_booleans_are_quoted + yaml_1_1_booleans = %w[y Y yes Yes YES n N no No NO true True TRUE false False FALSE on On ON off Off OFF] # from https://yaml.org/type/bool.html + yaml_1_1_booleans.each do |boolean| + assert_match(/"#{boolean}"|'#{boolean}'/, Psych.dump(boolean)) + end end def test_string_with_newline From 77593495f7b08301eeb0b4a22cb07b7a6461cd8f Mon Sep 17 00:00:00 2001 From: Colin Kelley Date: Wed, 19 Jul 2023 13:14:10 -0700 Subject: [PATCH 189/640] [ruby/psych] issue #443: drop special tests for y, Y, n, N since they covered in the more general test https://github.com/ruby/psych/commit/6750b35402 --- test/psych/test_string.rb | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/test/psych/test_string.rb b/test/psych/test_string.rb index c996a8fc2dc197..84ae5cbb451e44 100644 --- a/test/psych/test_string.rb +++ b/test/psych/test_string.rb @@ -17,20 +17,11 @@ def initialize end end - # 'y' and 'n' are kind of ambiguous. Syck treated y and n literals in + # 'y', 'Y', 'n', 'N' are kind of ambiguous. Syck treated those literals in # YAML documents as strings. But this is not what the YAML 1.1 spec says. # YAML 1.1 says they should be treated as booleans. When we're dumping # documents, we know it's a string, so adding quotes will eliminate the # "ambiguity" in the emitted document - def test_y_is_quoted - assert_match(/"y"/, Psych.dump("y")) - assert_match(/"Y"/, Psych.dump("Y")) - end - - def test_n_is_quoted - assert_match(/"n"/, Psych.dump("n")) - assert_match(/"N"/, Psych.dump("N")) - end def test_all_yaml_1_1_booleans_are_quoted yaml_1_1_booleans = %w[y Y yes Yes YES n N no No NO true True TRUE false False FALSE on On ON off Off OFF] # from https://yaml.org/type/bool.html From 1addb3955c456b01bb029b30dd6343298da0729d Mon Sep 17 00:00:00 2001 From: Mark Young Date: Thu, 21 Dec 2023 10:13:49 +0000 Subject: [PATCH 190/640] [ruby/psych] Provide a 'Changelog' link on rubygems.org/gems/psych By providing a 'changelog_uri' in the metadata of the gemspec a 'Changelog' link will be shown on https://rubygems.org/gems/psych which makes it quick and easy for someone to check on the changes introduced with a new version. Details of this functionality can be found on https://guides.rubygems.org/specification-reference/ https://github.com/ruby/psych/commit/28ef10edcf --- ext/psych/psych.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/psych/psych.gemspec b/ext/psych/psych.gemspec index 34f70095d32d1d..a3fc53a8b92113 100644 --- a/ext/psych/psych.gemspec +++ b/ext/psych/psych.gemspec @@ -76,5 +76,5 @@ DESCRIPTION end s.metadata['msys2_mingw_dependencies'] = 'libyaml' - + s.metadata['changelog_uri'] = s.homepage + '/releases' end From e37a37e696fdb97a3028f04d8439c010d52adb62 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Tue, 16 Jan 2024 17:23:46 -0800 Subject: [PATCH 191/640] Drop obsoleted BUILTIN_ATTR_NO_GC attribute The thing that has used this in the past was very buggy, and we've never revisied it. Let's remove it until we need it again. --- compile.c | 3 --- lib/ruby_vm/rjit/insn_compiler.rb | 11 ++++------- rjit_c.rb | 1 - tool/mk_builtin_loader.rb | 2 +- tool/rjit/bindgen.rb | 1 - vm_core.h | 4 +--- yjit/src/codegen.rs | 11 ++++------- yjit/src/cruby_bindings.inc.rs | 3 +-- 8 files changed, 11 insertions(+), 25 deletions(-) diff --git a/compile.c b/compile.c index 2d7e81d54e8fac..0aa9a7051190ab 100644 --- a/compile.c +++ b/compile.c @@ -8636,9 +8636,6 @@ compile_builtin_attr(rb_iseq_t *iseq, const NODE *node) if (strcmp(RSTRING_PTR(string), "leaf") == 0) { ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_LEAF; } - else if (strcmp(RSTRING_PTR(string), "no_gc") == 0) { - ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_NO_GC; - } else { goto unknown_arg; } diff --git a/lib/ruby_vm/rjit/insn_compiler.rb b/lib/ruby_vm/rjit/insn_compiler.rb index c3a3e31f2451e8..6440944944e34d 100644 --- a/lib/ruby_vm/rjit/insn_compiler.rb +++ b/lib/ruby_vm/rjit/insn_compiler.rb @@ -4924,13 +4924,10 @@ def jit_leaf_builtin_func(jit, ctx, asm, flags, iseq) asm.comment('inlined leaf builtin') - # Skip this if it doesn't trigger GC - if iseq.body.builtin_attrs & C::BUILTIN_ATTR_NO_GC == 0 - # The callee may allocate, e.g. Integer#abs on a Bignum. - # Save SP for GC, save PC for allocation tracing, and prepare - # for global invalidation after GC's VM lock contention. - jit_prepare_routine_call(jit, ctx, asm) - end + # The callee may allocate, e.g. Integer#abs on a Bignum. + # Save SP for GC, save PC for allocation tracing, and prepare + # for global invalidation after GC's VM lock contention. + jit_prepare_routine_call(jit, ctx, asm) # Call the builtin func (ec, recv, arg1, arg2, ...) asm.mov(C_ARGS[0], EC) diff --git a/rjit_c.rb b/rjit_c.rb index 61ae3b04a7e410..f660e879eeecf0 100644 --- a/rjit_c.rb +++ b/rjit_c.rb @@ -364,7 +364,6 @@ def rb_iseqw_to_iseq(iseqw) C::BOP_OR = Primitive.cexpr! %q{ SIZET2NUM(BOP_OR) } C::BOP_PLUS = Primitive.cexpr! %q{ SIZET2NUM(BOP_PLUS) } C::BUILTIN_ATTR_LEAF = Primitive.cexpr! %q{ SIZET2NUM(BUILTIN_ATTR_LEAF) } - C::BUILTIN_ATTR_NO_GC = Primitive.cexpr! %q{ SIZET2NUM(BUILTIN_ATTR_NO_GC) } C::HASH_REDEFINED_OP_FLAG = Primitive.cexpr! %q{ SIZET2NUM(HASH_REDEFINED_OP_FLAG) } C::INTEGER_REDEFINED_OP_FLAG = Primitive.cexpr! %q{ SIZET2NUM(INTEGER_REDEFINED_OP_FLAG) } C::INVALID_SHAPE_ID = Primitive.cexpr! %q{ SIZET2NUM(INVALID_SHAPE_ID) } diff --git a/tool/mk_builtin_loader.rb b/tool/mk_builtin_loader.rb index 95600e6a3bdc55..8cfae1380240ce 100644 --- a/tool/mk_builtin_loader.rb +++ b/tool/mk_builtin_loader.rb @@ -6,7 +6,7 @@ SUBLIBS = {} REQUIRED = {} -BUILTIN_ATTRS = %w[leaf no_gc] +BUILTIN_ATTRS = %w[leaf] def string_literal(lit, str = []) while lit diff --git a/tool/rjit/bindgen.rb b/tool/rjit/bindgen.rb index bf33d92bd20855..4022726302b5ff 100755 --- a/tool/rjit/bindgen.rb +++ b/tool/rjit/bindgen.rb @@ -396,7 +396,6 @@ def push_target(target) BOP_OR BOP_PLUS BUILTIN_ATTR_LEAF - BUILTIN_ATTR_NO_GC HASH_REDEFINED_OP_FLAG INTEGER_REDEFINED_OP_FLAG INVALID_SHAPE_ID diff --git a/vm_core.h b/vm_core.h index 354603514ebb46..724b3e32ad8124 100644 --- a/vm_core.h +++ b/vm_core.h @@ -365,10 +365,8 @@ enum rb_iseq_type { enum rb_builtin_attr { // The iseq does not call methods. BUILTIN_ATTR_LEAF = 0x01, - // The iseq does not allocate objects. - BUILTIN_ATTR_NO_GC = 0x02, // This iseq only contains single `opt_invokebuiltin_delegate_leave` instruction with 0 arguments. - BUILTIN_ATTR_SINGLE_NOARG_INLINE = 0x04, + BUILTIN_ATTR_SINGLE_NOARG_INLINE = 0x02, }; typedef VALUE (*rb_jit_func_t)(struct rb_execution_context_struct *, struct rb_control_frame_struct *); diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 2c3e61356c6a02..1ccb55d3b4d35a 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -6294,13 +6294,10 @@ fn gen_send_iseq( asm_comment!(asm, "inlined leaf builtin"); gen_counter_incr(asm, Counter::num_send_leaf_builtin); - // Skip this if it doesn't trigger GC - if builtin_attrs & BUILTIN_ATTR_NO_GC == 0 { - // The callee may allocate, e.g. Integer#abs on a Bignum. - // Save SP for GC, save PC for allocation tracing, and prepare - // for global invalidation after GC's VM lock contention. - jit_prepare_routine_call(jit, asm); - } + // The callee may allocate, e.g. Integer#abs on a Bignum. + // Save SP for GC, save PC for allocation tracing, and prepare + // for global invalidation after GC's VM lock contention. + jit_prepare_routine_call(jit, asm); // Call the builtin func (ec, recv, arg1, arg2, ...) let mut args = vec![EC]; diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs index 462c9c57486b0a..0870c35874acdf 100644 --- a/yjit/src/cruby_bindings.inc.rs +++ b/yjit/src/cruby_bindings.inc.rs @@ -448,8 +448,7 @@ pub struct iseq_inline_cvar_cache_entry { pub entry: *mut rb_cvar_class_tbl_entry, } pub const BUILTIN_ATTR_LEAF: rb_builtin_attr = 1; -pub const BUILTIN_ATTR_NO_GC: rb_builtin_attr = 2; -pub const BUILTIN_ATTR_SINGLE_NOARG_INLINE: rb_builtin_attr = 4; +pub const BUILTIN_ATTR_SINGLE_NOARG_INLINE: rb_builtin_attr = 2; pub type rb_builtin_attr = u32; #[repr(C)] #[derive(Debug, Copy, Clone)] From 8642a573e6d1091fefbb552bb714ebcf8da66289 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Tue, 16 Jan 2024 17:31:26 -0800 Subject: [PATCH 192/640] Rename BUILTIN_ATTR_SINGLE_NOARG_INLINE to BUILTIN_ATTR_SINGLE_NOARG_LEAF The attribute was created when the other attribute was called BUILTIN_ATTR_INLINE. Now that the original attribute is renamed to BUILTIN_ATTR_LEAF, it's only confusing that we call it "_INLINE". --- compile.c | 2 +- vm_core.h | 2 +- vm_insnhelper.c | 6 +++--- vm_trace.c | 2 +- yjit/src/cruby_bindings.inc.rs | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compile.c b/compile.c index 0aa9a7051190ab..5c69c860e0f131 100644 --- a/compile.c +++ b/compile.c @@ -3847,7 +3847,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal iobj->insn_id = BIN(opt_invokebuiltin_delegate_leave); const struct rb_builtin_function *bf = (const struct rb_builtin_function *)iobj->operands[0]; if (iobj == (INSN *)list && bf->argc == 0 && (iseq->body->builtin_attrs & BUILTIN_ATTR_LEAF)) { - iseq->body->builtin_attrs |= BUILTIN_ATTR_SINGLE_NOARG_INLINE; + iseq->body->builtin_attrs |= BUILTIN_ATTR_SINGLE_NOARG_LEAF; } } } diff --git a/vm_core.h b/vm_core.h index 724b3e32ad8124..7cd8fa76c5ad17 100644 --- a/vm_core.h +++ b/vm_core.h @@ -366,7 +366,7 @@ enum rb_builtin_attr { // The iseq does not call methods. BUILTIN_ATTR_LEAF = 0x01, // This iseq only contains single `opt_invokebuiltin_delegate_leave` instruction with 0 arguments. - BUILTIN_ATTR_SINGLE_NOARG_INLINE = 0x02, + BUILTIN_ATTR_SINGLE_NOARG_LEAF = 0x02, }; typedef VALUE (*rb_jit_func_t)(struct rb_execution_context_struct *, struct rb_control_frame_struct *); diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 63567e8f8710f1..97776f7a695b86 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -2925,7 +2925,7 @@ vm_call_iseq_setup_kwparm_nokwarg(rb_execution_context_t *ec, rb_control_frame_t static VALUE builtin_invoker0(rb_execution_context_t *ec, VALUE self, const VALUE *argv, rb_insn_func_t funcptr); static VALUE -vm_call_single_noarg_inline_builtin(rb_execution_context_t *ec, rb_control_frame_t *cfp, +vm_call_single_noarg_leaf_builtin(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling) { const struct rb_builtin_function *bf = calling->cc->aux_.bf; @@ -2955,11 +2955,11 @@ vm_callee_setup_arg(rb_execution_context_t *ec, struct rb_calling_info *calling, VM_ASSERT(cc == calling->cc); if (cacheable_ci && vm_call_iseq_optimizable_p(ci, cc)) { - if ((iseq->body->builtin_attrs & BUILTIN_ATTR_SINGLE_NOARG_INLINE) && + if ((iseq->body->builtin_attrs & BUILTIN_ATTR_SINGLE_NOARG_LEAF) && !(ruby_vm_event_flags & (RUBY_EVENT_C_CALL | RUBY_EVENT_C_RETURN))) { VM_ASSERT(iseq->body->builtin_attrs & BUILTIN_ATTR_LEAF); vm_cc_bf_set(cc, (void *)iseq->body->iseq_encoded[1]); - CC_SET_FASTPATH(cc, vm_call_single_noarg_inline_builtin, true); + CC_SET_FASTPATH(cc, vm_call_single_noarg_leaf_builtin, true); } else { CC_SET_FASTPATH(cc, vm_call_iseq_setup_func(ci, param_size, local_size), true); diff --git a/vm_trace.c b/vm_trace.c index 02008166e40a29..fb896fd423486a 100644 --- a/vm_trace.c +++ b/vm_trace.c @@ -1273,7 +1273,7 @@ rb_tracepoint_enable_for_target(VALUE tpval, VALUE target, VALUE target_line) rb_hash_aset(tp->local_target_set, (VALUE)iseq, Qtrue); if ((tp->events & (RUBY_EVENT_CALL | RUBY_EVENT_RETURN)) && - iseq->body->builtin_attrs & BUILTIN_ATTR_SINGLE_NOARG_INLINE) { + iseq->body->builtin_attrs & BUILTIN_ATTR_SINGLE_NOARG_LEAF) { rb_clear_bf_ccs(); } diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs index 0870c35874acdf..d71441c0bed462 100644 --- a/yjit/src/cruby_bindings.inc.rs +++ b/yjit/src/cruby_bindings.inc.rs @@ -448,7 +448,7 @@ pub struct iseq_inline_cvar_cache_entry { pub entry: *mut rb_cvar_class_tbl_entry, } pub const BUILTIN_ATTR_LEAF: rb_builtin_attr = 1; -pub const BUILTIN_ATTR_SINGLE_NOARG_INLINE: rb_builtin_attr = 2; +pub const BUILTIN_ATTR_SINGLE_NOARG_LEAF: rb_builtin_attr = 2; pub type rb_builtin_attr = u32; #[repr(C)] #[derive(Debug, Copy, Clone)] From 2c3876be942a3ca3d93d04889c3533dcd47706df Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jan 2024 02:22:23 +0000 Subject: [PATCH 193/640] Bump ruby/setup-ruby from 1.165.1 to 1.167.0 Bumps [ruby/setup-ruby](https://github.com/ruby/setup-ruby) from 1.165.1 to 1.167.0. - [Release notes](https://github.com/ruby/setup-ruby/releases) - [Commits](https://github.com/ruby/setup-ruby/compare/360dc864d5da99d54fcb8e9148c14a84b90d3e88...b203567269b5bbc256dbc1c84f7495913f977353) --- updated-dependencies: - dependency-name: ruby/setup-ruby dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/baseruby.yml | 2 +- .github/workflows/mingw.yml | 2 +- .github/workflows/rjit-bindgen.yml | 2 +- .github/workflows/spec_guards.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/baseruby.yml b/.github/workflows/baseruby.yml index 674b42b8b70608..a77fe3c56fd727 100644 --- a/.github/workflows/baseruby.yml +++ b/.github/workflows/baseruby.yml @@ -57,7 +57,7 @@ jobs: - ruby-3.3 steps: - - uses: ruby/setup-ruby@360dc864d5da99d54fcb8e9148c14a84b90d3e88 # v1.165.1 + - uses: ruby/setup-ruby@b203567269b5bbc256dbc1c84f7495913f977353 # v1.167.0 with: ruby-version: ${{ matrix.ruby }} bundler: none diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml index 5ed71716f9fc04..fecdd39fd818e9 100644 --- a/.github/workflows/mingw.yml +++ b/.github/workflows/mingw.yml @@ -74,7 +74,7 @@ jobs: steps: - name: Set up Ruby & MSYS2 - uses: ruby/setup-ruby@360dc864d5da99d54fcb8e9148c14a84b90d3e88 # v1.165.1 + uses: ruby/setup-ruby@b203567269b5bbc256dbc1c84f7495913f977353 # v1.167.0 with: ruby-version: ${{ matrix.baseruby }} diff --git a/.github/workflows/rjit-bindgen.yml b/.github/workflows/rjit-bindgen.yml index 74e9df608bd276..b64e34b4c19809 100644 --- a/.github/workflows/rjit-bindgen.yml +++ b/.github/workflows/rjit-bindgen.yml @@ -52,7 +52,7 @@ jobs: steps: - name: Set up Ruby - uses: ruby/setup-ruby@360dc864d5da99d54fcb8e9148c14a84b90d3e88 # v1.165.1 + uses: ruby/setup-ruby@b203567269b5bbc256dbc1c84f7495913f977353 # v1.167.0 with: ruby-version: '3.1' diff --git a/.github/workflows/spec_guards.yml b/.github/workflows/spec_guards.yml index fb479304236382..eb9e38bd8e3143 100644 --- a/.github/workflows/spec_guards.yml +++ b/.github/workflows/spec_guards.yml @@ -48,7 +48,7 @@ jobs: steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - uses: ruby/setup-ruby@360dc864d5da99d54fcb8e9148c14a84b90d3e88 # v1.165.1 + - uses: ruby/setup-ruby@b203567269b5bbc256dbc1c84f7495913f977353 # v1.167.0 with: ruby-version: ${{ matrix.ruby }} bundler: none From bf254b4de12b458deeb7937219be9389c8542704 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 17 Jan 2024 12:39:23 +0900 Subject: [PATCH 194/640] Omit low-memory test on old platforms --- test/ruby/test_process.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb index 0e417f0fef6517..3d20d6eff5bbcb 100644 --- a/test/ruby/test_process.rb +++ b/test/ruby/test_process.rb @@ -2841,7 +2841,10 @@ def test_concurrent_group_and_pid_wait def test_low_memory_startup omit "JIT enabled" if %w[YJIT RJIT].any? {|n| RubyVM.const_defined?(n) and RubyVM.const_get(n).enabled?} - (25..27).each {|i| as = 1< e omit e.message end From 6b11cfe0bca2dfa05612dc0c1b0672f56bea4d98 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jan 2024 02:34:36 +0000 Subject: [PATCH 195/640] Bump actions/cache in /.github/actions/setup/directories Bumps [actions/cache](https://github.com/actions/cache) from 3.3.3 to 4.0.0. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/e12d46a63a90f2fae62d114769bbf2a179198b5c...13aacd865c20de90d75de3b17ebe84f7a17d57d2) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/actions/setup/directories/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/setup/directories/action.yml b/.github/actions/setup/directories/action.yml index d699ea9e05b8ca..f3d7a1f3308396 100644 --- a/.github/actions/setup/directories/action.yml +++ b/.github/actions/setup/directories/action.yml @@ -80,7 +80,7 @@ runs: with: path: ${{ inputs.srcdir }} - - uses: actions/cache@e12d46a63a90f2fae62d114769bbf2a179198b5c # v3.3.3 + - uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 with: path: ${{ inputs.srcdir }}/.downloaded-cache key: downloaded-cache From 42168802618381b7b6308acc290aabdf61c10116 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jan 2024 02:22:18 +0000 Subject: [PATCH 196/640] Bump actions/cache from 3.3.3 to 4.0.0 Bumps [actions/cache](https://github.com/actions/cache) from 3.3.3 to 4.0.0. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/e12d46a63a90f2fae62d114769bbf2a179198b5c...13aacd865c20de90d75de3b17ebe84f7a17d57d2) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/windows.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index c8d61be7630a5d..098d709bb7dc46 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -96,7 +96,7 @@ jobs: ${{ steps.find-tools.outputs.needs }} if: ${{ steps.find-tools.outputs.needs != '' }} - - uses: actions/cache@e12d46a63a90f2fae62d114769bbf2a179198b5c # v3.3.3 + - uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 with: path: C:\vcpkg\downloads key: ${{ runner.os }}-vcpkg-download-${{ env.OS_VER }}-${{ github.sha }} @@ -104,7 +104,7 @@ jobs: ${{ runner.os }}-vcpkg-download-${{ env.OS_VER }}- ${{ runner.os }}-vcpkg-download- - - uses: actions/cache@e12d46a63a90f2fae62d114769bbf2a179198b5c # v3.3.3 + - uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 with: path: C:\vcpkg\installed key: ${{ runner.os }}-vcpkg-installed-${{ env.OS_VER }}-${{ github.sha }} From 6215b5ba9811ae1a1e631f01a88fd5b32043effa Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 17 Jan 2024 11:26:12 +0900 Subject: [PATCH 197/640] Fix off-by-one error of argc Fix ruby/ruby#9562 --- ruby.c | 4 ++-- test/ruby/test_rubyoptions.rb | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ruby.c b/ruby.c index 16db56bd62215d..047a90c3a1441b 100644 --- a/ruby.c +++ b/ruby.c @@ -1369,14 +1369,14 @@ proc_long_options(ruby_cmdline_options_t *opt, const char *s, long argc, char ** (((allow_envopt) || !envopt) ? (void)0 : \ rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: --" name)) # define need_argument(name, s, needs_arg, next_arg) \ - ((*(s) ? !*++(s) : (next_arg) && (!argc || !((s) = argv[1]) || (--argc, ++argv, 0))) && (needs_arg) ? \ + ((*(s) ? !*++(s) : (next_arg) && (argc <= 1 || !((s) = argv[1]) || (--argc, ++argv, 0))) && (needs_arg) ? \ rb_raise(rb_eRuntimeError, "missing argument for --" name) \ : (void)0) # define is_option_with_arg(name, allow_hyphen, allow_envopt) \ is_option_with_optarg(name, allow_hyphen, allow_envopt, Qtrue, Qtrue) # define is_option_with_optarg(name, allow_hyphen, allow_envopt, needs_arg, next_arg) \ (strncmp((name), s, n = sizeof(name) - 1) == 0 && is_option_end(s[n], (allow_hyphen)) && \ - (s[n] != '-' || s[n+1]) ? \ + (s[n] != '-' || (s[n] && s[n+1])) ? \ (check_envopt(name, (allow_envopt)), s += n, \ need_argument(name, s, needs_arg, next_arg), 1) : 0) diff --git a/test/ruby/test_rubyoptions.rb b/test/ruby/test_rubyoptions.rb index b8327d15b5d4a5..e98bd9fb17e63d 100644 --- a/test/ruby/test_rubyoptions.rb +++ b/test/ruby/test_rubyoptions.rb @@ -541,6 +541,16 @@ def test_sflag /invalid name for global variable - -# \(NameError\)/) end + def test_option_missing_argument + assert_in_out_err(%w(-0 --enable), "", [], /missing argument for --enable/) + assert_in_out_err(%w(-0 --disable), "", [], /missing argument for --disable/) + assert_in_out_err(%w(-0 --dump), "", [], /missing argument for --dump/) + assert_in_out_err(%w(-0 --encoding), "", [], /missing argument for --encoding/) + assert_in_out_err(%w(-0 --external-encoding), "", [], /missing argument for --external-encoding/) + assert_in_out_err(%w(-0 --internal-encoding), "", [], /missing argument for --internal-encoding/) + assert_in_out_err(%w(-0 --backtrace-limit), "", [], /missing argument for --backtrace-limit/) + end + def test_assignment_in_conditional Tempfile.create(["test_ruby_test_rubyoption", ".rb"]) {|t| t.puts "if a = 1" From c68ce6f7f5e6020409cfe689ba5946f284828d4b Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 15 Jan 2024 10:20:16 +0900 Subject: [PATCH 198/640] Skip checking for symbol leaks in libruby.so linking extensions The libruby.so linking extension libraries contain symbols exported from extension libraries, and is not subject of test-leaked-globals. --- template/Makefile.in | 3 ++- tool/leaked-globals | 13 +++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/template/Makefile.in b/template/Makefile.in index 61f420d96639dd..ae1bbd8f24ee50 100644 --- a/template/Makefile.in +++ b/template/Makefile.in @@ -643,7 +643,7 @@ un-runnable: $(ECHO) cannot make runnable, configure with --enable-load-relative. $(Q) exit 1 -LIBRUBY_FOR_LEAKED_GLOBALS = $(enable_shared:no=$(EXTSTATIC:static=)) +LIBRUBY_FOR_LEAKED_GLOBALS = $(enable_shared:no=) yes-test-basic: $(DOT_WAIT) test-leaked-globals leaked-globals: test-leaked-globals yes-test-leaked-globals-precheck: $(COMMONOBJS) prog $(tooldir)/leaked-globals @@ -653,6 +653,7 @@ yes-test-leaked-globals: yes-test-leaked-globals-precheck $(Q) $(XRUBY) $(tooldir)/leaked-globals \ SOEXT=$(SOEXT) NM="$(NM) -Pgp" SYMBOL_PREFIX=$(SYMBOL_PREFIX) \ SYMBOLS_IN_EMPTYLIB="@XSYMBOLS_IN_EMPTYLIB@" \ + EXTSTATIC="$(EXTSTATIC)" \ PLATFORM=$(hdrdir)/ruby/$(PLATFORM_DIR).h $(srcdir)/configure.ac \ $(COMMONOBJS) $(LIBRUBY_FOR_LEAKED_GLOBALS:yes=$(LIBRUBY_SO)) $(ACTIONS_ENDGROUP) diff --git a/tool/leaked-globals b/tool/leaked-globals index 87089ebd812d3c..ee75f78d1d73f2 100755 --- a/tool/leaked-globals +++ b/tool/leaked-globals @@ -13,12 +13,15 @@ until ARGV.empty? soext = $1 when /\A SYMBOLS_IN_EMPTYLIB=(.*)/x SYMBOLS_IN_EMPTYLIB = $1.split(" ") + when /\A EXTSTATIC=(.+)?/x + EXTSTATIC = true else break end ARGV.shift end SYMBOLS_IN_EMPTYLIB ||= nil +EXTSTATIC ||= false config = ARGV.shift count = 0 @@ -56,8 +59,14 @@ REPLACE.push("rust_eh_personality") if RUBY_PLATFORM.include?("darwin") print "Checking leaked global symbols..." STDOUT.flush -soext = /\.#{soext}(?:$|\.)/ if soext -so = soext =~ ARGV.first if ARGV.size == 1 +if soext + soext = /\.#{soext}(?:$|\.)/ + if EXTSTATIC + ARGV.delete_if {|n| soext =~ n} + elsif ARGV.size == 1 + so = soext =~ ARGV.first + end +end IO.foreach("|#{NM} #{ARGV.join(' ')}") do |line| line.chomp! next so = nil if line.empty? From 13879fea6957274f1752fb1df1cf1bd5b1626837 Mon Sep 17 00:00:00 2001 From: Adam Hess Date: Fri, 12 Jan 2024 10:22:03 -0800 Subject: [PATCH 199/640] [ruby/prism] Fix prism brace association for constant-like method/local calls https://github.com/ruby/prism/commit/8ca24f263e --- prism/prism.c | 6 +- test/prism/fixtures/method_calls.txt | 5 + test/prism/snapshots/method_calls.txt | 157 ++++++++++++++++++-------- 3 files changed, 118 insertions(+), 50 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index bbeb3cffe96934..15c793f08b9508 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -14315,7 +14315,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if ( match1(parser, PM_TOKEN_PARENTHESIS_LEFT) || (accepts_command_call && (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_UAMPERSAND, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR))) || - (pm_accepts_block_stack_p(parser) && match2(parser, PM_TOKEN_KEYWORD_DO, PM_TOKEN_BRACE_LEFT)) + (pm_accepts_block_stack_p(parser) && match1(parser, PM_TOKEN_KEYWORD_DO)) || + match1(parser, PM_TOKEN_BRACE_LEFT) ) { pm_arguments_t arguments = { 0 }; parse_arguments_list(parser, &arguments, true, accepts_command_call); @@ -14439,7 +14440,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // a block, so we need to check for that here. if ( (accepts_command_call && (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_UAMPERSAND, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR))) || - (pm_accepts_block_stack_p(parser) && match2(parser, PM_TOKEN_KEYWORD_DO, PM_TOKEN_BRACE_LEFT)) + (pm_accepts_block_stack_p(parser) && match1(parser, PM_TOKEN_KEYWORD_DO)) || + match1(parser, PM_TOKEN_BRACE_LEFT) ) { pm_arguments_t arguments = { 0 }; parse_arguments_list(parser, &arguments, true, accepts_command_call); diff --git a/test/prism/fixtures/method_calls.txt b/test/prism/fixtures/method_calls.txt index d8c32a148f6c2d..d30780771f7376 100644 --- a/test/prism/fixtures/method_calls.txt +++ b/test/prism/fixtures/method_calls.txt @@ -147,3 +147,8 @@ lst << A {} "#{(v)}" def f(*); p *; end + +foo 1, Bar { 1 } + +foo = 1 +foo {} diff --git a/test/prism/snapshots/method_calls.txt b/test/prism/snapshots/method_calls.txt index 0828a65a348977..ff6e0dd7df1381 100644 --- a/test/prism/snapshots/method_calls.txt +++ b/test/prism/snapshots/method_calls.txt @@ -1,8 +1,8 @@ -@ ProgramNode (location: (1,0)-(149,18)) -├── locals: [] +@ ProgramNode (location: (1,0)-(154,6)) +├── locals: [:foo] └── statements: - @ StatementsNode (location: (1,0)-(149,18)) - └── body: (length: 63) + @ StatementsNode (location: (1,0)-(154,6)) + └── body: (length: 66) ├── @ CallNode (location: (1,0)-(1,14)) │ ├── flags: ∅ │ ├── receiver: @@ -2304,48 +2304,109 @@ │ │ │ └── closing_loc: (147,5)-(147,6) = ")" │ │ └── closing_loc: (147,6)-(147,7) = "}" │ └── closing_loc: (147,7)-(147,8) = "\"" - └── @ DefNode (location: (149,0)-(149,18)) - ├── name: :f - ├── name_loc: (149,4)-(149,5) = "f" + ├── @ DefNode (location: (149,0)-(149,18)) + │ ├── name: :f + │ ├── name_loc: (149,4)-(149,5) = "f" + │ ├── receiver: ∅ + │ ├── parameters: + │ │ @ ParametersNode (location: (149,6)-(149,7)) + │ │ ├── requireds: (length: 0) + │ │ ├── optionals: (length: 0) + │ │ ├── rest: + │ │ │ @ RestParameterNode (location: (149,6)-(149,7)) + │ │ │ ├── flags: ∅ + │ │ │ ├── name: ∅ + │ │ │ ├── name_loc: ∅ + │ │ │ └── operator_loc: (149,6)-(149,7) = "*" + │ │ ├── posts: (length: 0) + │ │ ├── keywords: (length: 0) + │ │ ├── keyword_rest: ∅ + │ │ └── block: ∅ + │ ├── body: + │ │ @ StatementsNode (location: (149,10)-(149,13)) + │ │ └── body: (length: 1) + │ │ └── @ CallNode (location: (149,10)-(149,13)) + │ │ ├── flags: ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :p + │ │ ├── message_loc: (149,10)-(149,11) = "p" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: + │ │ │ @ ArgumentsNode (location: (149,12)-(149,13)) + │ │ │ ├── flags: ∅ + │ │ │ └── arguments: (length: 1) + │ │ │ └── @ SplatNode (location: (149,12)-(149,13)) + │ │ │ ├── operator_loc: (149,12)-(149,13) = "*" + │ │ │ └── expression: ∅ + │ │ ├── closing_loc: ∅ + │ │ └── block: ∅ + │ ├── locals: [:*] + │ ├── locals_body_index: 1 + │ ├── def_keyword_loc: (149,0)-(149,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: (149,5)-(149,6) = "(" + │ ├── rparen_loc: (149,7)-(149,8) = ")" + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (149,15)-(149,18) = "end" + ├── @ CallNode (location: (151,0)-(151,16)) + │ ├── flags: ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :foo + │ ├── message_loc: (151,0)-(151,3) = "foo" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (151,4)-(151,16)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 2) + │ │ ├── @ IntegerNode (location: (151,4)-(151,5)) + │ │ │ └── flags: decimal + │ │ └── @ CallNode (location: (151,7)-(151,16)) + │ │ ├── flags: ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :Bar + │ │ ├── message_loc: (151,7)-(151,10) = "Bar" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ └── block: + │ │ @ BlockNode (location: (151,11)-(151,16)) + │ │ ├── locals: [] + │ │ ├── locals_body_index: 0 + │ │ ├── parameters: ∅ + │ │ ├── body: + │ │ │ @ StatementsNode (location: (151,13)-(151,14)) + │ │ │ └── body: (length: 1) + │ │ │ └── @ IntegerNode (location: (151,13)-(151,14)) + │ │ │ └── flags: decimal + │ │ ├── opening_loc: (151,11)-(151,12) = "{" + │ │ └── closing_loc: (151,15)-(151,16) = "}" + │ ├── closing_loc: ∅ + │ └── block: ∅ + ├── @ LocalVariableWriteNode (location: (153,0)-(153,7)) + │ ├── name: :foo + │ ├── depth: 0 + │ ├── name_loc: (153,0)-(153,3) = "foo" + │ ├── value: + │ │ @ IntegerNode (location: (153,6)-(153,7)) + │ │ └── flags: decimal + │ └── operator_loc: (153,4)-(153,5) = "=" + └── @ CallNode (location: (154,0)-(154,6)) + ├── flags: ignore_visibility ├── receiver: ∅ - ├── parameters: - │ @ ParametersNode (location: (149,6)-(149,7)) - │ ├── requireds: (length: 0) - │ ├── optionals: (length: 0) - │ ├── rest: - │ │ @ RestParameterNode (location: (149,6)-(149,7)) - │ │ ├── flags: ∅ - │ │ ├── name: ∅ - │ │ ├── name_loc: ∅ - │ │ └── operator_loc: (149,6)-(149,7) = "*" - │ ├── posts: (length: 0) - │ ├── keywords: (length: 0) - │ ├── keyword_rest: ∅ - │ └── block: ∅ - ├── body: - │ @ StatementsNode (location: (149,10)-(149,13)) - │ └── body: (length: 1) - │ └── @ CallNode (location: (149,10)-(149,13)) - │ ├── flags: ignore_visibility - │ ├── receiver: ∅ - │ ├── call_operator_loc: ∅ - │ ├── name: :p - │ ├── message_loc: (149,10)-(149,11) = "p" - │ ├── opening_loc: ∅ - │ ├── arguments: - │ │ @ ArgumentsNode (location: (149,12)-(149,13)) - │ │ ├── flags: ∅ - │ │ └── arguments: (length: 1) - │ │ └── @ SplatNode (location: (149,12)-(149,13)) - │ │ ├── operator_loc: (149,12)-(149,13) = "*" - │ │ └── expression: ∅ - │ ├── closing_loc: ∅ - │ └── block: ∅ - ├── locals: [:*] - ├── locals_body_index: 1 - ├── def_keyword_loc: (149,0)-(149,3) = "def" - ├── operator_loc: ∅ - ├── lparen_loc: (149,5)-(149,6) = "(" - ├── rparen_loc: (149,7)-(149,8) = ")" - ├── equal_loc: ∅ - └── end_keyword_loc: (149,15)-(149,18) = "end" + ├── call_operator_loc: ∅ + ├── name: :foo + ├── message_loc: (154,0)-(154,3) = "foo" + ├── opening_loc: ∅ + ├── arguments: ∅ + ├── closing_loc: ∅ + └── block: + @ BlockNode (location: (154,4)-(154,6)) + ├── locals: [] + ├── locals_body_index: 0 + ├── parameters: ∅ + ├── body: ∅ + ├── opening_loc: (154,4)-(154,5) = "{" + └── closing_loc: (154,5)-(154,6) = "}" From 67a545b3d2c52fbbf4336e9c2bea662cdfb30bc7 Mon Sep 17 00:00:00 2001 From: git Date: Wed, 17 Jan 2024 13:26:15 +0000 Subject: [PATCH 200/640] * expand tabs. [ci skip] Please consider using misc/expand_tabs.rb as a pre-commit hook. --- prism/prism.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 15c793f08b9508..b2d7373e659b75 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -14316,7 +14316,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b match1(parser, PM_TOKEN_PARENTHESIS_LEFT) || (accepts_command_call && (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_UAMPERSAND, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR))) || (pm_accepts_block_stack_p(parser) && match1(parser, PM_TOKEN_KEYWORD_DO)) || - match1(parser, PM_TOKEN_BRACE_LEFT) + match1(parser, PM_TOKEN_BRACE_LEFT) ) { pm_arguments_t arguments = { 0 }; parse_arguments_list(parser, &arguments, true, accepts_command_call); @@ -14441,7 +14441,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if ( (accepts_command_call && (token_begins_expression_p(parser->current.type) || match3(parser, PM_TOKEN_UAMPERSAND, PM_TOKEN_USTAR, PM_TOKEN_USTAR_STAR))) || (pm_accepts_block_stack_p(parser) && match1(parser, PM_TOKEN_KEYWORD_DO)) || - match1(parser, PM_TOKEN_BRACE_LEFT) + match1(parser, PM_TOKEN_BRACE_LEFT) ) { pm_arguments_t arguments = { 0 }; parse_arguments_list(parser, &arguments, true, accepts_command_call); From e17c83e02c5019f7a8c31b31a567ab6de6d6c7f4 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 16 Jan 2024 09:32:21 -0500 Subject: [PATCH 201/640] Fix memory leak in String#tr and String#tr_s rb_enc_codepoint_len could raise, which would cause the memory in buf to leak. For example: str1 = "\xE0\xA0\xA1#{" " * 100}".force_encoding("EUC-JP") str2 = "" str3 = "a".force_encoding("Windows-31J") 10.times do 1_000_000.times do str1.tr_s(str2, str3) rescue end puts `ps -o rss= -p #{$$}` end Before: 17536 22752 28032 33312 38688 43968 49200 54432 59744 64992 After: 12176 12352 12352 12448 12448 12448 12448 12448 12448 12448 --- string.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/string.c b/string.c index 5eda835f4b36a3..4c0fe87635a5a9 100644 --- a/string.c +++ b/string.c @@ -7987,7 +7987,14 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag) while (s < send) { int may_modify = 0; - c0 = c = rb_enc_codepoint_len((char *)s, (char *)send, &clen, e1); + int r = rb_enc_precise_mbclen((char *)s, (char *)send, e1); + if (!MBCLEN_CHARFOUND_P(r)) { + xfree(buf); + rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(e1)); + } + clen = MBCLEN_CHARFOUND_LEN(r); + c0 = c = rb_enc_mbc_to_codepoint((char *)s, (char *)send, e1); + tlen = enc == e1 ? clen : rb_enc_codelen(c, enc); s += clen; @@ -8067,7 +8074,15 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag) while (s < send) { int may_modify = 0; - c0 = c = rb_enc_codepoint_len((char *)s, (char *)send, &clen, e1); + + int r = rb_enc_precise_mbclen((char *)s, (char *)send, e1); + if (!MBCLEN_CHARFOUND_P(r)) { + xfree(buf); + rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(e1)); + } + clen = MBCLEN_CHARFOUND_LEN(r); + c0 = c = rb_enc_mbc_to_codepoint((char *)s, (char *)send, e1); + tlen = enc == e1 ? clen : rb_enc_codelen(c, enc); if (c < 256) { From ef4a08eb65ab00eb0101b8b64212bef613e4f833 Mon Sep 17 00:00:00 2001 From: Matt Valentine-House Date: Wed, 17 Jan 2024 13:59:30 +0000 Subject: [PATCH 202/640] [PRISM] Fix stack inconsistency in MultiWriteNode --- prism_compile.c | 12 +++++++++--- test/ruby/test_compile_prism.rb | 4 ++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 722dabf8ab142b..55bc348492eae3 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -5216,6 +5216,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_multi_write_node_t *multi_write_node = (pm_multi_write_node_t *)node; pm_node_list_t *lefts = &multi_write_node->lefts; pm_node_list_t *rights = &multi_write_node->rights; + bool has_rest_expression = (multi_write_node->rest && + PM_NODE_TYPE_P(multi_write_node->rest, PM_SPLAT_NODE)); size_t argc = 1; // pre-process the left hand side of multi-assignments. @@ -5313,9 +5315,13 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, PM_COMPILE(rights->nodes[index]); } } - else if (rest_expression) { - ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(0), INT2FIX(1)); - PM_COMPILE(rest_expression); + else if (has_rest_expression) { + if (rest_expression) { + ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(0), INT2FIX(1)); + PM_COMPILE(rest_expression); + } else if (!lefts->size && !PM_NODE_TYPE_P(multi_write_node->value, PM_SPLAT_NODE)){ + ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(0), INT2FIX(0)); + } } return; diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index bc9f0b3aba7a87..9b4e998b271462 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -543,6 +543,10 @@ def test_MultiWriteNode assert_prism_eval("_, {}[:foo], _ = 1") assert_prism_eval("_, {}[:foo], _ = 1") assert_prism_eval("_,{}[:foo], _, {}[:bar] = 1") + assert_prism_eval("* = :foo") + assert_prism_eval("* = *[]") + assert_prism_eval("a, * = :foo") + assert_prism_eval(<<~CODE) class Foo From 3a7ad808b135bace484038e4ba0549796d98d872 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 16 Jan 2024 13:27:11 -0500 Subject: [PATCH 203/640] [PRISM] Fix test_compile_prism_with_file The test should be testing RubyVM::InstructionSequence.compile_prism with a file but it is instead passing the file path (which is a string) which raises a SyntaxError because it is not Ruby syntax. --- test/ruby/test_iseq.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/ruby/test_iseq.rb b/test/ruby/test_iseq.rb index f5c0b8205718dc..dd81610b5368fe 100644 --- a/test/ruby/test_iseq.rb +++ b/test/ruby/test_iseq.rb @@ -805,10 +805,7 @@ def test_compile_prism_with_file f.close assert_nothing_raised(TypeError) do - begin - RubyVM::InstructionSequence.compile_prism(f.path) - rescue SyntaxError - end + RubyVM::InstructionSequence.compile_prism(f) end end end From 0c814092ee1268562b4ba42973ea754e0dcf1bd0 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Tue, 16 Jan 2024 15:10:39 -0500 Subject: [PATCH 204/640] [Prism] Implement defined for PM_NEXT_NODE Ruby code: ```ruby defined?(next) ``` Instructions ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,15)> 0000 putobject "expression" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,15)> 0000 putobject "expression" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 2 ++ 2 files changed, 3 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 55bc348492eae3..80101e5b663fd6 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2471,6 +2471,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_KEYWORD_HASH_NODE: case PM_LAMBDA_NODE: case PM_MATCH_PREDICATE_NODE: + case PM_NEXT_NODE: case PM_OR_NODE: case PM_RANGE_NODE: case PM_REGULAR_EXPRESSION_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 9b4e998b271462..18ad6d1c08cbbb 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -218,6 +218,8 @@ def m1; end defined?(PrismDefinedNode.new.m1) RUBY + + assert_prism_eval("defined?(next)") end def test_GlobalVariableReadNode From 82ed90950e485ffd8b5d5536d105b3ebf953a1fa Mon Sep 17 00:00:00 2001 From: eileencodes Date: Tue, 16 Jan 2024 15:16:31 -0500 Subject: [PATCH 205/640] [Prism] Implement defined? for PM_BREAK_NODE Ruby code: ```ruby defined?(break) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,15)> 0000 putobject "expression" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,15)> 0000 putobject "expression" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 80101e5b663fd6..c603e2a2cd46a4 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2462,6 +2462,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co } } case PM_AND_NODE: + case PM_BREAK_NODE: case PM_FLOAT_NODE: case PM_HASH_NODE: case PM_IMAGINARY_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 18ad6d1c08cbbb..16392a15e28eba 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -220,6 +220,7 @@ def m1; end RUBY assert_prism_eval("defined?(next)") + assert_prism_eval("defined?(break)") end def test_GlobalVariableReadNode From 25f1a8e4479324ebcc3c9a46c67cdd23b028f435 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Tue, 16 Jan 2024 15:24:55 -0500 Subject: [PATCH 206/640] [Prism] Implement defined? for PM_DEFINED_NODE Ruby code: ```ruby defined?(defined?(a)) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,21)> 0000 putobject "expression" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,21)> 0000 putobject "expression" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index c603e2a2cd46a4..b80b95ac0aa976 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2463,6 +2463,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co } case PM_AND_NODE: case PM_BREAK_NODE: + case PM_DEFINED_NODE: case PM_FLOAT_NODE: case PM_HASH_NODE: case PM_IMAGINARY_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 16392a15e28eba..3865fb1b3f4490 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -221,6 +221,7 @@ def m1; end assert_prism_eval("defined?(next)") assert_prism_eval("defined?(break)") + assert_prism_eval("defined?(defined?(a))") end def test_GlobalVariableReadNode From e0c90199c996c53db41611bc7fcb9b68a1ae9c64 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Tue, 16 Jan 2024 15:31:24 -0500 Subject: [PATCH 207/640] [Prism] Implement defined? for PM_INTERPOLATED_SYMBOL_NODE Ruby code: ```ruby defined?(:"1 #{1 + 2} 1") ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,25)> 0000 putobject "expression" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,25)> 0000 putobject "expression" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index b80b95ac0aa976..90baba2c4d8481 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2470,6 +2470,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_INTEGER_NODE: case PM_INTERPOLATED_REGULAR_EXPRESSION_NODE: case PM_INTERPOLATED_STRING_NODE: + case PM_INTERPOLATED_SYMBOL_NODE: case PM_KEYWORD_HASH_NODE: case PM_LAMBDA_NODE: case PM_MATCH_PREDICATE_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 3865fb1b3f4490..abef12d90a7d4c 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -222,6 +222,7 @@ def m1; end assert_prism_eval("defined?(next)") assert_prism_eval("defined?(break)") assert_prism_eval("defined?(defined?(a))") + assert_prism_eval('defined?(:"#{1}")') end def test_GlobalVariableReadNode From 2697acf7ffe0d607f6bb0f95b1017f3bb0d6195f Mon Sep 17 00:00:00 2001 From: eileencodes Date: Tue, 16 Jan 2024 15:40:54 -0500 Subject: [PATCH 208/640] [Prism] Implement defined? for PM_INTERPOLATED_X_STRING_NODE Ruby code: ```ruby defined?(`echo #{1}`) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,21)> 0000 putobject "expression" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,21)> 0000 putobject "expression" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 90baba2c4d8481..3758d05d6c3e65 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2471,6 +2471,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_INTERPOLATED_REGULAR_EXPRESSION_NODE: case PM_INTERPOLATED_STRING_NODE: case PM_INTERPOLATED_SYMBOL_NODE: + case PM_INTERPOLATED_X_STRING_NODE: case PM_KEYWORD_HASH_NODE: case PM_LAMBDA_NODE: case PM_MATCH_PREDICATE_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index abef12d90a7d4c..5f13d8d0a1eee7 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -223,6 +223,7 @@ def m1; end assert_prism_eval("defined?(break)") assert_prism_eval("defined?(defined?(a))") assert_prism_eval('defined?(:"#{1}")') + assert_prism_eval("defined?(`echo #{1}`)") end def test_GlobalVariableReadNode From d0a7c33f05626bdec6f085ff4084aaaf25214ec3 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Tue, 16 Jan 2024 15:43:24 -0500 Subject: [PATCH 209/640] [Prism] Implement defined? for PM_REDO_NODE Ruby code: ```ruby defined?(redo) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,14)> 0000 putobject "expression" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,14)> 0000 putobject "expression" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 3758d05d6c3e65..14e7e612daef9c 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2478,6 +2478,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_NEXT_NODE: case PM_OR_NODE: case PM_RANGE_NODE: + case PM_REDO_NODE: case PM_REGULAR_EXPRESSION_NODE: case PM_SOURCE_ENCODING_NODE: case PM_SOURCE_FILE_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 5f13d8d0a1eee7..9625d3f8e097c6 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -221,6 +221,7 @@ def m1; end assert_prism_eval("defined?(next)") assert_prism_eval("defined?(break)") + assert_prism_eval("defined?(redo)") assert_prism_eval("defined?(defined?(a))") assert_prism_eval('defined?(:"#{1}")') assert_prism_eval("defined?(`echo #{1}`)") From 8774abad55c1b3d76af996f5ad8aae19704702c7 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Tue, 16 Jan 2024 15:44:58 -0500 Subject: [PATCH 210/640] [Prism] Implement defined? for PM_RETURN_NODE Ruby code: ```ruby defined?(return) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,16)> 0000 putobject "expression" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,16)> 0000 putobject "expression" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 14e7e612daef9c..2f09d851a1f0f4 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2480,6 +2480,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_RANGE_NODE: case PM_REDO_NODE: case PM_REGULAR_EXPRESSION_NODE: + case PM_RETURN_NODE: case PM_SOURCE_ENCODING_NODE: case PM_SOURCE_FILE_NODE: case PM_SOURCE_LINE_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 9625d3f8e097c6..dd2d38fe09182d 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -222,6 +222,7 @@ def m1; end assert_prism_eval("defined?(next)") assert_prism_eval("defined?(break)") assert_prism_eval("defined?(redo)") + assert_prism_eval("defined?(return)") assert_prism_eval("defined?(defined?(a))") assert_prism_eval('defined?(:"#{1}")') assert_prism_eval("defined?(`echo #{1}`)") From 338aa465c0a2922b0e7ff306d88bdfec0232f4fb Mon Sep 17 00:00:00 2001 From: eileencodes Date: Tue, 16 Jan 2024 15:47:10 -0500 Subject: [PATCH 211/640] [Prism] Implement defined? for PM_RETRY_NODE Ruby code: ```ruby defined?(retry) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,15)> 0000 putobject "expression" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,15)> 0000 putobject "expression" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 2 ++ 2 files changed, 3 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 2f09d851a1f0f4..f12a0c49448e81 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2480,6 +2480,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_RANGE_NODE: case PM_REDO_NODE: case PM_REGULAR_EXPRESSION_NODE: + case PM_RETRY_NODE: case PM_RETURN_NODE: case PM_SOURCE_ENCODING_NODE: case PM_SOURCE_FILE_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index dd2d38fe09182d..eb183cca58fd8e 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -223,6 +223,8 @@ def m1; end assert_prism_eval("defined?(break)") assert_prism_eval("defined?(redo)") assert_prism_eval("defined?(return)") + assert_prism_eval("defined?(retry)") + assert_prism_eval("defined?(defined?(a))") assert_prism_eval('defined?(:"#{1}")') assert_prism_eval("defined?(`echo #{1}`)") From dcf9d77b45bcca3193a310e1a0f496e2d74cfc81 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Tue, 16 Jan 2024 15:50:45 -0500 Subject: [PATCH 212/640] [Prism] Implement defined? for PM_BEGIN_NODE Ruby code: ```ruby defined?(begin; 1; end) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,23)> 0000 putobject "expression" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,23)> 0000 putobject "expression" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 2 ++ 2 files changed, 3 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index f12a0c49448e81..2a083220c3d81b 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2462,6 +2462,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co } } case PM_AND_NODE: + case PM_BEGIN_NODE: case PM_BREAK_NODE: case PM_DEFINED_NODE: case PM_FLOAT_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index eb183cca58fd8e..3f416c178193e4 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -225,6 +225,8 @@ def m1; end assert_prism_eval("defined?(return)") assert_prism_eval("defined?(retry)") + assert_prism_eval("defined?(begin; 1; end)") + assert_prism_eval("defined?(defined?(a))") assert_prism_eval('defined?(:"#{1}")') assert_prism_eval("defined?(`echo #{1}`)") From 63ff29cdb4ba27eb366d706d81a74b89a1d6b18a Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 09:23:42 -0500 Subject: [PATCH 213/640] [Prism] Fix return test This test didn't work as is because it causes a SyntaxError. Instead we need to put the `defined?(return)` into a method and call that. I double checked that on the `master` branch this returns an Unsupported node error. --- test/ruby/test_compile_prism.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 3f416c178193e4..76dd05255bfaa4 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -222,9 +222,16 @@ def m1; end assert_prism_eval("defined?(next)") assert_prism_eval("defined?(break)") assert_prism_eval("defined?(redo)") - assert_prism_eval("defined?(return)") assert_prism_eval("defined?(retry)") + assert_prism_eval(<<~RUBY) + class PrismDefinedReturnNode + def self.m1; defined?(return) end + end + + PrismDefinedReturnNode.m1 + RUBY + assert_prism_eval("defined?(begin; 1; end)") assert_prism_eval("defined?(defined?(a))") From afba09d30f4c2ce6d0d77e06d5250967411cd74a Mon Sep 17 00:00:00 2001 From: Maxime Chevalier-Boisvert Date: Wed, 17 Jan 2024 10:35:48 -0500 Subject: [PATCH 214/640] YJIT: specialized codegen for integer right shift (#9564) * YJIT: specialized codegen for integer right shift Used in optcarrot. May also be used to write pure-Ruby gems. No overflow check or fixnum untagging required. * Update yjit/src/codegen.rs Co-authored-by: Takashi Kokubun --------- Co-authored-by: Takashi Kokubun --- bootstraptest/test_yjit.rb | 5 ++++ yjit.rb | 1 + yjit/src/codegen.rs | 52 ++++++++++++++++++++++++++++++++++++++ yjit/src/stats.rs | 2 ++ 4 files changed, 60 insertions(+) diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index 70a5501be20fe4..5b53e8089bfbf4 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -4352,3 +4352,8 @@ def entry assert_equal '[2, 4611686018427387904]', %q{ [1.succ, 4611686018427387903.succ] } + +# Integer right shift +assert_equal '[0, 1, -4]', %q{ + [0 >> 1, 2 >> 1, -7 >> 1] +} diff --git a/yjit.rb b/yjit.rb index 84d4d99b1f480a..485b4062fa0a4d 100644 --- a/yjit.rb +++ b/yjit.rb @@ -290,6 +290,7 @@ def _print_stats_reasons(stats, out) # :nodoc: print_counters(stats, out: out, prefix: "#{insn}_", prompt: "#{insn} exit reasons:", optional: true) end print_counters(stats, out: out, prefix: 'lshift_', prompt: 'left shift (opt_ltlt) exit reasons: ') + print_counters(stats, out: out, prefix: 'rshift_', prompt: 'right shift (>>) exit reasons: ') print_counters(stats, out: out, prefix: 'invalidate_', prompt: 'invalidation reasons: ') end diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 1ccb55d3b4d35a..7d42030345a546 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -4737,6 +4737,57 @@ fn jit_rb_int_lshift( true } +fn jit_rb_int_rshift( + jit: &mut JITState, + asm: &mut Assembler, + ocb: &mut OutlinedCb, + _ci: *const rb_callinfo, + _cme: *const rb_callable_method_entry_t, + _block: Option, + _argc: i32, + _known_recv_class: *const VALUE, +) -> bool { + if asm.ctx.two_fixnums_on_stack(jit) != Some(true) { + return false; + } + guard_two_fixnums(jit, asm, ocb); + + let comptime_shift = jit.peek_at_stack(&asm.ctx, 0); + + // Untag the fixnum shift amount + let shift_amt = comptime_shift.as_isize() >> 1; + if shift_amt > 63 || shift_amt < 0 { + return false; + } + + // Fallback to a C call if the shift amount varies + if asm.ctx.get_chain_depth() > 2 { + return false; + } + + let rhs = asm.stack_pop(1); + let lhs = asm.stack_pop(1); + + // Guard on the shift amount we speculated on + asm.cmp(rhs, comptime_shift.into()); + jit_chain_guard( + JCC_JNE, + jit, + asm, + ocb, + 2, // defer_compilation increments chain_depth + Counter::rshift_amount_changed, + ); + + let shift_opnd = Opnd::UImm(shift_amt as u64); + let out_val = asm.rshift(lhs, shift_opnd); + let out_val = asm.or(out_val, 1.into()); + + let ret_opnd = asm.stack_push(Type::Fixnum); + asm.mov(ret_opnd, out_val); + true +} + fn jit_rb_int_aref( jit: &mut JITState, asm: &mut Assembler, @@ -8909,6 +8960,7 @@ pub fn yjit_reg_method_codegen_fns() { yjit_reg_method(rb_cInteger, "succ", jit_rb_int_succ); yjit_reg_method(rb_cInteger, "/", jit_rb_int_div); yjit_reg_method(rb_cInteger, "<<", jit_rb_int_lshift); + yjit_reg_method(rb_cInteger, ">>", jit_rb_int_rshift); yjit_reg_method(rb_cInteger, "[]", jit_rb_int_aref); yjit_reg_method(rb_cString, "empty?", jit_rb_str_empty_p); diff --git a/yjit/src/stats.rs b/yjit/src/stats.rs index 924628e13acedf..4b77dceaf18db6 100644 --- a/yjit/src/stats.rs +++ b/yjit/src/stats.rs @@ -458,6 +458,8 @@ make_counters! { lshift_amount_changed, lshift_overflow, + rshift_amount_changed, + opt_aref_argc_not_one, opt_aref_arg_not_fixnum, opt_aref_not_array, From 3f23cb1a43f02d6214f1c1bdb989ceb20ce0454f Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 17 Jan 2024 10:44:37 -0500 Subject: [PATCH 215/640] [ruby/prism] Remove flag gating for 3.3.0 bug fixes https://github.com/ruby/prism/commit/64baf94271 --- prism/options.h | 6 +++--- prism/prism.c | 10 ++-------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/prism/options.h b/prism/options.h index 130d635b98e5ae..c3ca47b594decd 100644 --- a/prism/options.h +++ b/prism/options.h @@ -25,9 +25,9 @@ typedef struct pm_options_scope { } pm_options_scope_t; /** - * The version of prism that we should be parsing with. This is used to allow - * consumers to specify which behavior they want in case they need to parse - * exactly as a specific version of CRuby. + * The version of Ruby syntax that we should be parsing with. This is used to + * allow consumers to specify which behavior they want in case they need to + * parse in the same way as a specific version of CRuby would have. */ typedef enum { /** The current version of prism. */ diff --git a/prism/prism.c b/prism/prism.c index b2d7373e659b75..83b641abc70c47 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -2203,14 +2203,10 @@ pm_index_target_node_create(pm_parser_t *parser, pm_call_node_t *target) { pm_index_target_node_t *node = PM_ALLOC_NODE(parser, pm_index_target_node_t); pm_node_flags_t flags = target->base.flags; - if (parser->version != PM_OPTIONS_VERSION_CRUBY_3_3_0) { - flags |= PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE; - } - *node = (pm_index_target_node_t) { { .type = PM_INDEX_TARGET_NODE, - .flags = flags, + .flags = flags | PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE, .location = target->base.location }, .receiver = target->receiver, @@ -12306,9 +12302,7 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept arguments->block = (pm_node_t *) block; } else { if (arguments->has_forwarding) { - if (parser->version != PM_OPTIONS_VERSION_CRUBY_3_3_0) { - pm_parser_err_node(parser, (pm_node_t *) block, PM_ERR_ARGUMENT_BLOCK_FORWARDING); - } + pm_parser_err_node(parser, (pm_node_t *) block, PM_ERR_ARGUMENT_BLOCK_FORWARDING); } else { pm_parser_err_node(parser, (pm_node_t *) block, PM_ERR_ARGUMENT_BLOCK_MULTI); } From 03645d1eefdf280c3c1ff20f9431fb8fe45799b4 Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Wed, 17 Jan 2024 10:52:15 -0500 Subject: [PATCH 216/640] YJIT: Support empty splat and some block_arg calls to ivar getters (#9567) These seem odd at first glance, but they're used with `...` calls with `Module#delegate` from Active Support. These account for ~3% of fallback reasons in the `lobsters` benchmark. --- test/ruby/test_yjit.rb | 34 +++++++++++++++++++++++++++- yjit/src/codegen.rs | 50 ++++++++++++++++++++++++++++-------------- yjit/src/stats.rs | 1 + 3 files changed, 68 insertions(+), 17 deletions(-) diff --git a/test/ruby/test_yjit.rb b/test/ruby/test_yjit.rb index 55b86bea78f11c..bd513c60e660cd 100644 --- a/test/ruby/test_yjit.rb +++ b/test/ruby/test_yjit.rb @@ -1514,6 +1514,24 @@ def test_disable_stats assert_in_out_err(%w[--yjit-stats --yjit-disable]) end + def test_odd_calls_to_attr_reader + # Use of delegate from ActiveSupport use these kind of calls to getter methods. + assert_compiles(<<~RUBY, result: [1, 1, 1], no_send_fallbacks: true) + class One + attr_reader :one + def initialize + @one = 1 + end + end + + def calls(obj, empty, &) + [obj.one(*empty), obj.one(&), obj.one(*empty, &)] + end + + calls(One.new, []) + RUBY + end + private def code_gc_helpers @@ -1537,7 +1555,17 @@ def assert_no_exits(script) end ANY = Object.new - def assert_compiles(test_script, insns: [], call_threshold: 1, stdout: nil, exits: {}, result: ANY, frozen_string_literal: nil, mem_size: nil, code_gc: false) + def assert_compiles( + test_script, insns: [], + call_threshold: 1, + stdout: nil, + exits: {}, + result: ANY, + frozen_string_literal: nil, + mem_size: nil, + code_gc: false, + no_send_fallbacks: false + ) reset_stats = <<~RUBY RubyVM::YJIT.runtime_stats RubyVM::YJIT.reset_stats! @@ -1610,6 +1638,10 @@ def collect_insns(iseq) end end + if no_send_fallbacks + assert_equal(0, runtime_stats[:num_send_dynamic], "Expected no use of fallback implementation") + end + # Only available when --enable-yjit=dev if runtime_stats[:all_stats] missed_insns = insns.dup diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 7d42030345a546..378b397fe493f9 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -7355,21 +7355,43 @@ fn gen_send_general( ); } VM_METHOD_TYPE_IVAR => { - if flags & VM_CALL_ARGS_SPLAT != 0 { - gen_counter_incr(asm, Counter::send_args_splat_ivar); + // This is a .send call not supported right now for getters + if flags & VM_CALL_OPT_SEND != 0 { + gen_counter_incr(asm, Counter::send_send_getter); return None; } - if argc != 0 { - // Argument count mismatch. Getters take no arguments. - gen_counter_incr(asm, Counter::send_getter_arity); - return None; + if flags & VM_CALL_ARGS_BLOCKARG != 0 { + match asm.ctx.get_opnd_type(StackOpnd(0)) { + Type::Nil | Type::BlockParamProxy => { + // Getters ignore the block arg, and these types of block args can be + // passed without side-effect (never any `to_proc` call). + asm.stack_pop(1); + } + _ => { + gen_counter_incr(asm, Counter::send_getter_block_arg); + return None; + } + } } - // This is a .send call not supported right now for getters - if flags & VM_CALL_OPT_SEND != 0 { - gen_counter_incr(asm, Counter::send_send_getter); - return None; + if argc != 0 { + // Guard for simple splat of empty array + if VM_CALL_ARGS_SPLAT == flags & (VM_CALL_ARGS_SPLAT | VM_CALL_KWARG | VM_CALL_KW_SPLAT) + && argc == 1 { + // Not using chain guards since on failure these likely end up just raising + // ArgumentError + let splat = asm.stack_opnd(0); + guard_object_is_array(asm, splat, splat.into(), Counter::guard_send_getter_splat_non_empty); + let splat_len = get_array_len(asm, splat); + asm.cmp(splat_len, 0.into()); + asm.jne(Target::side_exit(Counter::guard_send_getter_splat_non_empty)); + asm.stack_pop(1); + } else { + // Argument count mismatch. Getters take no arguments. + gen_counter_incr(asm, Counter::send_getter_arity); + return None; + } } if c_method_tracing_currently_enabled(jit) { @@ -7386,13 +7408,9 @@ fn gen_send_general( return None; } + let recv = asm.stack_opnd(0); // the receiver should now be the stack top let ivar_name = unsafe { get_cme_def_body_attr_id(cme) }; - if flags & VM_CALL_ARGS_BLOCKARG != 0 { - gen_counter_incr(asm, Counter::send_getter_block_arg); - return None; - } - return gen_get_ivar( jit, asm, @@ -7401,7 +7419,7 @@ fn gen_send_general( comptime_recv, ivar_name, recv, - recv_opnd, + recv.into(), ); } VM_METHOD_TYPE_ATTRSET => { diff --git a/yjit/src/stats.rs b/yjit/src/stats.rs index 4b77dceaf18db6..264843117a683b 100644 --- a/yjit/src/stats.rs +++ b/yjit/src/stats.rs @@ -400,6 +400,7 @@ make_counters! { // Method calls that exit to the interpreter guard_send_block_arg_type, + guard_send_getter_splat_non_empty, guard_send_klass_megamorphic, guard_send_se_cf_overflow, guard_send_se_protected_check_failed, From 78ad91f83f1c16318b2d3e5920c6ad98f88a4955 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 3 Jan 2024 14:23:44 -0500 Subject: [PATCH 217/640] [Prism] Fix more method call argumnents In #2087 it was noted that there was a bug in the number of arguments in `SplatNode` and `KeywordHashNode`. I looked into this with Aaron before the linked PR was merged and we found a bunch of cases that weren't working quite right. This PR aims to fix some of those cases, but there may be more. A splat argument followed by a positional argument will concat the array until the end or unless the argument is a kwarg or splat kwarg. For example ``` foo(a, *b, c, *d, e) ``` Will have an `argc` of 2, because `b`, `c`, `d`, and `e` will be concatenated together. ``` foo(a, *b, c, *d, **e) ``` Will have an `argc` of 3, because `b`, `c`, and `d` will be concatenated together and `e` is a separate argument. --- prism_compile.c | 109 +++++++++++++++++++++++++------- test/ruby/test_compile_prism.rb | 40 ++++++++++++ 2 files changed, 127 insertions(+), 22 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 2a083220c3d81b..994007752d4b6a 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -966,6 +966,9 @@ static int pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinfo_kwarg **kw_arg, rb_iseq_t *iseq, LINK_ANCHOR *const ret, const uint8_t *src, bool popped, pm_scope_node_t *scope_node, NODE dummy_line_node, pm_parser_t *parser) { int orig_argc = 0; + bool has_splat = false; + bool has_keyword_splat = false; + if (arguments_node == NULL) { if (*flags & VM_CALL_FCALL) { *flags |= VM_CALL_VCALL; @@ -974,8 +977,7 @@ pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinf else { pm_node_list_t arguments_node_list = arguments_node->arguments; - bool has_keyword_splat = (arguments_node->base.flags & PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT); - bool has_splat = false; + has_keyword_splat = (arguments_node->base.flags & PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT); // We count the number of elements post the splat node that are not keyword elements to // eventually pass as an argument to newarray @@ -990,7 +992,11 @@ pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinf pm_keyword_hash_node_t *keyword_arg = (pm_keyword_hash_node_t *)argument; size_t len = keyword_arg->elements.size; - if (has_keyword_splat) { + if (has_keyword_splat || has_splat) { + *flags |= VM_CALL_KW_SPLAT; + *flags |= VM_CALL_KW_SPLAT_MUT; + + has_keyword_splat = true; int cur_hash_size = 0; bool new_hash_emitted = false; @@ -1001,7 +1007,6 @@ pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinf switch (PM_NODE_TYPE(cur_node)) { case PM_ASSOC_NODE: { - orig_argc++; pm_assoc_node_t *assoc = (pm_assoc_node_t *)cur_node; PM_COMPILE_NOT_POPPED(assoc->key); @@ -1104,11 +1109,39 @@ pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinf *flags |= VM_CALL_ARGS_SPLAT; pm_splat_node_t *splat_node = (pm_splat_node_t *)argument; if (splat_node->expression) { - orig_argc++; PM_COMPILE_NOT_POPPED(splat_node->expression); } - ADD_INSN1(ret, &dummy_line_node, splatarray, Qfalse); + bool first_splat = !has_splat; + + if (first_splat) { + // If this is the first splat array seen and it's not the + // last parameter, we want splatarray to dup it. + // + // foo(a, *b, c) + // ^^ + if (index + 1 < arguments_node_list.size) { + ADD_INSN1(ret, &dummy_line_node, splatarray, Qtrue); + } + // If this is the first spalt array seen and it's the last + // parameter, we don't want splatarray to dup it. + // + // foo(a, *b) + // ^^ + else { + ADD_INSN1(ret, &dummy_line_node, splatarray, Qfalse); + } + } + else { + // If this is not the first splat array seen and it is also + // the last parameter, we don't want splayarray to dup it + // and we need to concat the array. + // + // foo(a, *b, *c) + // ^^ + ADD_INSN1(ret, &dummy_line_node, splatarray, Qfalse); + ADD_INSN(ret, &dummy_line_node, concatarray); + } has_splat = true; post_splat_counter = 0; @@ -1124,36 +1157,68 @@ pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinf break; } default: { - orig_argc++; post_splat_counter++; PM_COMPILE_NOT_POPPED(argument); + // If we have a splat and we've seen a splat, we need to process + // everything after the splat. if (has_splat) { - // If the next node starts the keyword section of parameters - if ((index < arguments_node_list.size - 1) && PM_NODE_TYPE_P(arguments_node_list.nodes[index + 1], PM_KEYWORD_HASH_NODE)) { - + // Stack items are turned into an array and concatenated in + // the following cases: + // + // If the next node is a splat: + // + // foo(*a, b, *c) + // + // If the next node is a kwarg or kwarg splat: + // + // foo(*a, b, c: :d) + // foo(*a, b, **c) + // + // If the next node is NULL (we have hit the end): + // + // foo(*a, b) + if (index == arguments_node_list.size - 1) { + RUBY_ASSERT(post_splat_counter > 0); ADD_INSN1(ret, &dummy_line_node, newarray, INT2FIX(post_splat_counter)); - ADD_INSN1(ret, &dummy_line_node, splatarray, Qfalse); ADD_INSN(ret, &dummy_line_node, concatarray); } - // If it's the final node - else if (index == arguments_node_list.size - 1) { - if (post_splat_counter > 1) { - ADD_INSN1(ret, &dummy_line_node, newarray, INT2FIX(post_splat_counter)); - ADD_INSN1(ret, &dummy_line_node, splatarray, Qfalse); - ADD_INSN(ret, &dummy_line_node, concatarray); - } - else { - ADD_INSN1(ret, &dummy_line_node, newarray, INT2FIX(post_splat_counter)); - ADD_INSN(ret, &dummy_line_node, concatarray); + else { + pm_node_t *next_arg = arguments_node_list.nodes[index + 1]; + + switch (PM_NODE_TYPE(next_arg)) { + // A keyword hash node contains all keyword arguments as AssocNodes and AssocSplatNodes + case PM_KEYWORD_HASH_NODE: { + ADD_INSN1(ret, &dummy_line_node, newarray, INT2FIX(post_splat_counter)); + ADD_INSN(ret, &dummy_line_node, concatarray); + break; + } + case PM_SPLAT_NODE: { + ADD_INSN1(ret, &dummy_line_node, newarray, INT2FIX(post_splat_counter)); + ADD_INSN(ret, &dummy_line_node, concatarray); + break; + } + default: + break; } - orig_argc = 1; } } + else { + orig_argc++; + } } } } } + + if (has_splat) { + orig_argc++; + } + + if (has_keyword_splat) { + orig_argc++; + } + return orig_argc; } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 76dd05255bfaa4..c0f85af8b4e470 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1388,6 +1388,46 @@ def self.prism_test_def_node(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, CODE end + def test_trailing_keyword_method_params + # foo(1, b: 2, c: 3) # argc -> 3 + assert_prism_eval("def self.foo(a, b:, c:); [a, b, c]; end; foo(1, b: 2, c: 3)") + end + + def test_keyword_method_params_only + # foo(a: 1, b: 2) # argc -> 2 + assert_prism_eval("def self.foo(a:, b:); [a, b]; end; foo(a: 1, b: 2)") + end + + def test_keyword_method_params_with_splat + # foo(a: 1, **b) # argc -> 1 + assert_prism_eval("def self.foo(a:, b:); [a, b]; end; b = { b: 2 }; foo(a: 1, **b)") + end + + def test_positional_and_splat_keyword_method_params + # foo(a, **b) # argc -> 2 + assert_prism_eval("def self.foo(a, b); [a, b]; end; b = { b: 2 }; foo(1, **b)") + end + + def test_positional_and_splat_method_params + # foo(a, *b, c, *d, e) # argc -> 2 + assert_prism_eval("def self.foo(a, b, c, d, e); [a, b, c, d, e]; end; b = [2]; d = [4]; foo(1, *b, 3, *d, 5)") + end + + def test_positional_with_splat_and_splat_keyword_method_params + # foo(a, *b, c, *d, **e) # argc -> 3 + assert_prism_eval("def self.foo(a, b, c, d, e); [a, b, c, d, e]; end; b = [2]; d = [4]; e = { e: 5 }; foo(1, *b, 3, *d, **e)") + end + + def test_positional_with_splat_and_keyword_method_params + # foo(a, *b, c, *d, e:) # argc -> 3 + assert_prism_eval("def self.foo(a, b, c, d, e:); [a, b, c, d, e]; end; b = [2]; d = [4]; foo(1, *b, 3, *d, e: 5)") + end + + def test_leading_splat_and_keyword_method_params + # foo(*a, b:) # argc -> 2 + assert_prism_eval("def self.foo(a, b:); [a, b]; end; a = [1]; foo(*a, b: 2)") + end + def test_repeated_method_params assert_prism_eval("def self.foo(_a, _a); _a; end; foo(1, 2)") end From 947194aacb3b82602eab63b92fbe5876f10c5640 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Wed, 17 Jan 2024 10:08:00 -0500 Subject: [PATCH 218/640] [PRISM] Fix memory leak of ST table This commit fixes a memory leak in rb_translate_prism because the ST table is never freed. There are still more memory leaks which still need to be fixed. For example: 10.times do 100_000.times do RubyVM::InstructionSequence.compile_prism("") end puts `ps -o rss= -p #{$$}` end Before: 34544 57120 79360 102176 123712 146320 168192 190592 212192 234896 After: 18336 24592 31488 37648 44592 50944 57280 63632 69904 76160 --- prism_compile.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 994007752d4b6a..472d25eb355db4 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -6936,6 +6936,8 @@ rb_translate_prism(pm_parser_t *parser, rb_iseq_t *iseq, pm_scope_node_t *scope_ pm_compile_node(iseq, (pm_node_t *)scope_node, ret, scope_node->base.location.start, false, (pm_scope_node_t *)scope_node); iseq_set_sequence(iseq, ret); + st_free_table(index_lookup_table); + return Qnil; } From 6213ab1a51387fd9cdcb5e87908722f3bbdf78cb Mon Sep 17 00:00:00 2001 From: Ewoud Kohl van Wijngaarden Date: Fri, 5 Jan 2024 15:58:59 +0100 Subject: [PATCH 219/640] [ruby/openssl] Only set min_version on OpenSSL < 1.1.0 Both Red Hat and Debian-like systems configure the minimum TLS version to be 1.2 by default, but allow users to change this via configs. On Red Hat and derivatives this happens via crypto-policies[1], which in writes settings in /etc/crypto-policies/back-ends/opensslcnf.config. Most notably, it sets TLS.MinProtocol there. For Debian there's MinProtocol in /etc/ssl/openssl.cnf. Both default to TLSv1.2, which is considered a secure default. In constrast, the SSLContext has a hard coded OpenSSL::SSL::TLS1_VERSION for min_version. TLS 1.0 and 1.1 are considered insecure. By always setting this in the default parameters, the system wide default can't be respected, even if a developer wants to. This takes the approach that's also done for ciphers: it's only set for OpenSSL < 1.1.0. [1]: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/security_hardening/using-the-system-wide-cryptographic-policies_security-hardening https://github.com/ruby/openssl/commit/ae215a47ae --- ext/openssl/lib/openssl/ssl.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb index ccc945f2f2d556..7e59400ccbca97 100644 --- a/ext/openssl/lib/openssl/ssl.rb +++ b/ext/openssl/lib/openssl/ssl.rb @@ -22,7 +22,6 @@ module OpenSSL module SSL class SSLContext DEFAULT_PARAMS = { # :nodoc: - :min_version => OpenSSL::SSL::TLS1_VERSION, :verify_mode => OpenSSL::SSL::VERIFY_PEER, :verify_hostname => true, :options => -> { @@ -55,6 +54,7 @@ class SSLContext if !(OpenSSL::OPENSSL_VERSION.start_with?("OpenSSL") && OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10100000) DEFAULT_PARAMS.merge!( + min_version: OpenSSL::SSL::TLS1_VERSION, ciphers: %w{ ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-RSA-AES128-GCM-SHA256 From 4f634d3c85ca45b5995c1f37619784c99f2be62c Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Thu, 18 Jan 2024 06:08:59 +1300 Subject: [PATCH 220/640] [ruby/openssl] Add support for IO#timeout. (https://github.com/ruby/openssl/pull/714) * Add support for IO#timeout. https://github.com/ruby/openssl/commit/3bbf5178a9 --- ext/openssl/extconf.rb | 1 + ext/openssl/lib/openssl/ssl.rb | 10 ++++++++++ ext/openssl/ossl_ssl.c | 15 +++++++++++++-- test/openssl/test_ssl.rb | 18 ++++++++++++++++++ 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index 56f4a1c3ab0ea6..4119c72c48767d 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -49,6 +49,7 @@ have_func("rb_io_descriptor") have_func("rb_io_maybe_wait(0, Qnil, Qnil, Qnil)", "ruby/io.h") # Ruby 3.1 +have_func("rb_io_timeout", "ruby/io.h") Logging::message "=== Checking for system dependent stuff... ===\n" have_library("nsl", "t_open") diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb index 7e59400ccbca97..75a74a3f5164a7 100644 --- a/ext/openssl/lib/openssl/ssl.rb +++ b/ext/openssl/lib/openssl/ssl.rb @@ -299,6 +299,16 @@ def wait_readable(*args) def wait_writable(*args) to_io.wait_writable(*args) end + + if IO.method_defined?(:timeout) + def timeout + to_io.timeout + end + + def timeout=(value) + to_io.timeout=(value) + end + end end def verify_certificate_identity(cert, hostname) diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index 236d455ff2a48e..9f374b65ffac0a 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -1725,11 +1725,20 @@ no_exception_p(VALUE opts) #define RUBY_IO_TIMEOUT_DEFAULT Qnil #endif +#ifdef HAVE_RB_IO_TIMEOUT +#define IO_TIMEOUT_ERROR rb_eIOTimeoutError +#else +#define IO_TIMEOUT_ERROR rb_eIOError +#endif + + static void io_wait_writable(VALUE io) { #ifdef HAVE_RB_IO_MAYBE_WAIT - rb_io_maybe_wait_writable(errno, io, RUBY_IO_TIMEOUT_DEFAULT); + if (!rb_io_maybe_wait_writable(errno, io, RUBY_IO_TIMEOUT_DEFAULT)) { + rb_raise(IO_TIMEOUT_ERROR, "Timed out while waiting to become writable!"); + } #else rb_io_t *fptr; GetOpenFile(io, fptr); @@ -1741,7 +1750,9 @@ static void io_wait_readable(VALUE io) { #ifdef HAVE_RB_IO_MAYBE_WAIT - rb_io_maybe_wait_readable(errno, io, RUBY_IO_TIMEOUT_DEFAULT); + if (!rb_io_maybe_wait_readable(errno, io, RUBY_IO_TIMEOUT_DEFAULT)) { + rb_raise(IO_TIMEOUT_ERROR, "Timed out while waiting to become readable!"); + } #else rb_io_t *fptr; GetOpenFile(io, fptr); diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb index 07dc9a343cef8e..dcb7757add02be 100644 --- a/test/openssl/test_ssl.rb +++ b/test/openssl/test_ssl.rb @@ -193,6 +193,24 @@ def test_sysread_and_syswrite } end + def test_read_with_timeout + omit "does not support timeout" unless IO.method_defined?(:timeout) + + start_server do |port| + server_connect(port) do |ssl| + str = +("x" * 100 + "\n") + ssl.syswrite(str) + assert_equal(str, ssl.sysread(str.bytesize)) + + ssl.timeout = 1 + assert_raise(IO::TimeoutError) {ssl.read(1)} + + ssl.syswrite(str) + assert_equal(str, ssl.sysread(str.bytesize)) + end + end + end + def test_getbyte start_server { |port| server_connect(port) { |ssl| From e1751b2ec8ddc3a423446b68109114da740f0439 Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Sat, 25 Nov 2023 21:30:09 +0900 Subject: [PATCH 221/640] [ruby/openssl] test/openssl/test_ocsp.rb: fix flaky test Fixes: https://github.com/ruby/openssl/issues/695 https://github.com/ruby/openssl/commit/95281fe4a9 --- test/openssl/test_ocsp.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/openssl/test_ocsp.rb b/test/openssl/test_ocsp.rb index 85f133752cb660..cf96fc22e515ba 100644 --- a/test/openssl/test_ocsp.rb +++ b/test/openssl/test_ocsp.rb @@ -228,7 +228,7 @@ def test_basic_response_response_operations assert_equal OpenSSL::OCSP::V_CERTSTATUS_REVOKED, single.cert_status assert_equal OpenSSL::OCSP::REVOKED_STATUS_UNSPECIFIED, single.revocation_reason assert_equal now - 400, single.revocation_time - assert_in_delta (now - 301), single.this_update, 1 + assert_in_delta (now - 300), single.this_update, 1 assert_equal nil, single.next_update assert_equal [], single.extensions From 5273c4c9199c154f1818e256127fc539ff8a8a55 Mon Sep 17 00:00:00 2001 From: nikhilbhatt Date: Sun, 14 Jan 2024 14:28:30 +0530 Subject: [PATCH 222/640] [ruby/prism] Document AndNode and OrNode https://github.com/ruby/prism/commit/a925856c2b --- prism/config.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/prism/config.yml b/prism/config.yml index 748729ec6b1eb3..cfc6f2f1e080b9 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -475,10 +475,25 @@ nodes: fields: - name: left type: node + comment: | + Represents left side of expression. + + left and right + ^^^^ - name: right type: node + comment: | + Represents right side of expression. + + left && right + ^^^^^ - name: operator_loc type: location + comment: | + The Location of `and` keyword or `&&` operator. + + left and right + ^^^ comment: | Represents the use of the `&&` operator or the `and` keyword. @@ -2273,10 +2288,25 @@ nodes: fields: - name: left type: node + comment: | + Represents left side of expression. + + left or right + ^^^^ - name: right type: node + comment: | + Represents right side of expression. + + left || right + ^^^^^ - name: operator_loc type: location + comment: | + The Location of `or` keyword or `||` operator. + + left or right + ^^ comment: | Represents the use of the `||` operator or the `or` keyword. From 32cbbfc97d56d9c01677b5411518b52c9404c484 Mon Sep 17 00:00:00 2001 From: nikhilbhatt Date: Wed, 17 Jan 2024 08:39:40 +0530 Subject: [PATCH 223/640] [ruby/prism] Added descriptive comments https://github.com/ruby/prism/commit/2695ae115d --- prism/config.yml | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/prism/config.yml b/prism/config.yml index cfc6f2f1e080b9..85d0f50103aeb5 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -476,21 +476,27 @@ nodes: - name: left type: node comment: | - Represents left side of expression. + Represents left side of expression. It includes any kind of node that returns a non-void value. left and right ^^^^ + 1 && 2 + ^ - name: right type: node comment: | - Represents right side of expression. + Represents right side of expression. It includes any kind of node that returns non-void value. + If nothing is given, it will be replaced by MissingNode. left && right ^^^^^ + 1 and 2 + ^ - name: operator_loc type: location comment: | The Location of `and` keyword or `&&` operator. + The only difference between the two is that `&&` has higher precedence than `and`. left and right ^^^ @@ -2289,21 +2295,27 @@ nodes: - name: left type: node comment: | - Represents left side of expression. + Represents left side of expression. It includes any kind of node that returns a non-void value. left or right ^^^^ + 1 || 2 + ^ - name: right type: node comment: | - Represents right side of expression. + Represents right side of expression. It includes any kind of node that returns a non-void value. + If nothing is given, it will be replaced by MissingNode. left || right ^^^^^ + 1 or 2 + ^ - name: operator_loc type: location comment: | The Location of `or` keyword or `||` operator. + The only difference between the two is that `||` has higher precedence than `or`. left or right ^^ From cd4290910c7f3f63118567101bf6cec4df90361a Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 17 Jan 2024 12:42:44 -0500 Subject: [PATCH 224/640] [ruby/prism] Wording in node field comments https://github.com/ruby/prism/commit/c9c913ee99 --- prism/config.yml | 93 +++++++++++++++++++++--------------------------- 1 file changed, 40 insertions(+), 53 deletions(-) diff --git a/prism/config.yml b/prism/config.yml index 85d0f50103aeb5..0bff427bbff05d 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -476,30 +476,32 @@ nodes: - name: left type: node comment: | - Represents left side of expression. It includes any kind of node that returns a non-void value. + Represents the left side of the expression. It can be any kind of node + that represents a non-void expression. - left and right - ^^^^ - 1 && 2 - ^ + left and right + ^^^^ + + 1 && 2 + ^ - name: right type: node comment: | - Represents right side of expression. It includes any kind of node that returns non-void value. - If nothing is given, it will be replaced by MissingNode. + Represents the right side of the expression. It can be any kind of + node that represents a non-void expression. - left && right - ^^^^^ - 1 and 2 - ^ + left && right + ^^^^^ + + 1 and 2 + ^ - name: operator_loc type: location comment: | - The Location of `and` keyword or `&&` operator. - The only difference between the two is that `&&` has higher precedence than `and`. + The location of the `and` keyword or the `&&` operator. - left and right - ^^^ + left and right + ^^^ comment: | Represents the use of the `&&` operator or the `and` keyword. @@ -570,7 +572,8 @@ nodes: - name: key type: node comment: | - The key of the association. This can be any node that represents a non-void expression. + The key of the association. This can be any node that represents a + non-void expression. { a: b } ^ @@ -701,8 +704,8 @@ nodes: comment: | Represents a block of ruby code. - [1, 2, 3].each { |i| puts x } - ^^^^^^^^^^^^^^ + [1, 2, 3].each { |i| puts x } + ^^^^^^^^^^^^^^ - name: BlockParameterNode fields: - name: flags @@ -1214,7 +1217,8 @@ nodes: - name: name type: constant comment: | - Represents writing to a constant in a context that doesn't have an explicit value. + Represents writing to a constant in a context that doesn't have an + explicit value. Foo, Bar = baz ^^^ ^^^ @@ -1845,19 +1849,6 @@ nodes: - name: flags type: flags kind: IntegerBaseFlags - comment: | - Represents flag indicating the base of the integer - - 10 base decimal, value 10 - 0d10 base decimal, value 10 - 0b10 base binary, value 2 - 0o10 base octal, value 8 - 010 base octal, value 8 - 0x10 base hexidecimal, value 16 - - A 0 prefix indicates the number has a different base. - The d, b, o, and x prefixes indicate the base. If one of those - four letters is omitted, the base is assumed to be octal. comment: | Represents an integer number literal. @@ -2295,30 +2286,32 @@ nodes: - name: left type: node comment: | - Represents left side of expression. It includes any kind of node that returns a non-void value. + Represents the left side of the expression. It can be any kind of node + that represents a non-void expression. - left or right - ^^^^ - 1 || 2 - ^ + left or right + ^^^^ + + 1 || 2 + ^ - name: right type: node comment: | - Represents right side of expression. It includes any kind of node that returns a non-void value. - If nothing is given, it will be replaced by MissingNode. + Represents the right side of the expression. It can be any kind of + node that represents a non-void expression. - left || right - ^^^^^ - 1 or 2 - ^ + left || right + ^^^^^ + + 1 or 2 + ^ - name: operator_loc type: location comment: | - The Location of `or` keyword or `||` operator. - The only difference between the two is that `||` has higher precedence than `or`. + The location of the `or` keyword or the `||` operator. - left or right - ^^ + left or right + ^^ comment: | Represents the use of the `||` operator or the `or` keyword. @@ -2434,12 +2427,6 @@ nodes: - name: flags type: flags kind: RangeFlags - comment: | - A flag indicating whether the range excludes the end value. - - 1..3 # includes 3 - - 1...3 # excludes 3 - name: left type: node? comment: | From 603f2ca730cc62818a7a9852291f5877cbadd55d Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Fri, 12 Jan 2024 09:12:43 -0800 Subject: [PATCH 225/640] [ruby/prism] Parse `it` default parameter https://github.com/ruby/prism/commit/a0c5361b9f --- prism/diagnostic.c | 1 + prism/diagnostic.h | 1 + prism/prism.c | 92 +++++++++++++++++++++++++++++++++++-- test/prism/errors_test.rb | 7 +++ test/prism/location_test.rb | 6 +++ 5 files changed, 103 insertions(+), 4 deletions(-) diff --git a/prism/diagnostic.c b/prism/diagnostic.c index c779955eb314e6..ed47a1cdade06d 100644 --- a/prism/diagnostic.c +++ b/prism/diagnostic.c @@ -175,6 +175,7 @@ static const char* const diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = { [PM_ERR_INVALID_PERCENT] = "invalid `%` token", // TODO WHAT? [PM_ERR_INVALID_TOKEN] = "invalid token", // TODO WHAT? [PM_ERR_INVALID_VARIABLE_GLOBAL] = "invalid global variable", + [PM_ERR_IT_NOT_ALLOWED] = "`it` is not allowed when an ordinary parameter is defined", [PM_ERR_LAMBDA_OPEN] = "expected a `do` keyword or a `{` to open the lambda block", [PM_ERR_LAMBDA_TERM_BRACE] = "expected a lambda block beginning with `{` to end with `}`", [PM_ERR_LAMBDA_TERM_END] = "expected a lambda block beginning with `do` to end with `end`", diff --git a/prism/diagnostic.h b/prism/diagnostic.h index da430b543851be..fb4110236151d2 100644 --- a/prism/diagnostic.h +++ b/prism/diagnostic.h @@ -167,6 +167,7 @@ typedef enum { PM_ERR_INVALID_PERCENT, PM_ERR_INVALID_TOKEN, PM_ERR_INVALID_VARIABLE_GLOBAL, + PM_ERR_IT_NOT_ALLOWED, PM_ERR_LAMBDA_OPEN, PM_ERR_LAMBDA_TERM_BRACE, PM_ERR_LAMBDA_TERM_END, diff --git a/prism/prism.c b/prism/prism.c index 83b641abc70c47..0778667f962f23 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -4196,12 +4196,10 @@ pm_local_variable_or_write_node_create(pm_parser_t *parser, pm_node_t *target, c } /** - * Allocate a new LocalVariableReadNode node. + * Allocate a new LocalVariableReadNode node with constant_id. */ static pm_local_variable_read_node_t * -pm_local_variable_read_node_create(pm_parser_t *parser, const pm_token_t *name, uint32_t depth) { - pm_constant_id_t name_id = pm_parser_constant_id_token(parser, name); - +pm_local_variable_read_node_create_constant_id(pm_parser_t *parser, const pm_token_t *name, pm_constant_id_t name_id, uint32_t depth) { if (parser->current_param_name == name_id) { pm_parser_err_token(parser, name, PM_ERR_PARAMETER_CIRCULAR); } @@ -4220,6 +4218,15 @@ pm_local_variable_read_node_create(pm_parser_t *parser, const pm_token_t *name, return node; } +/** + * Allocate a new LocalVariableReadNode node. + */ +static pm_local_variable_read_node_t * +pm_local_variable_read_node_create(pm_parser_t *parser, const pm_token_t *name, uint32_t depth) { + pm_constant_id_t name_id = pm_parser_constant_id_token(parser, name); + return pm_local_variable_read_node_create_constant_id(parser, name, name_id, depth); +} + /** * Allocate and initialize a new LocalVariableWriteNode node. */ @@ -4245,6 +4252,57 @@ pm_local_variable_write_node_create(pm_parser_t *parser, pm_constant_id_t name, return node; } +/** + * Returns true if the given bounds comprise `it`. + */ +static inline bool +pm_token_is_it(const uint8_t *start, const uint8_t *end) { + return (end - start == 2) && (start[0] == 'i') && (start[1] == 't'); +} + +/** + * Returns true if the given node is `it` default parameter. + */ +static inline bool +pm_node_is_it(pm_parser_t *parser, pm_node_t *node) { + // Check if it's a local variable reference + if (node->type != PM_CALL_NODE) { + return false; + } + + // Check if it's a variable call + pm_call_node_t *call_node = (pm_call_node_t *) node; + if (!pm_call_node_variable_call_p(call_node)) { + return false; + } + + // Check if it's called `it` + pm_constant_id_t id = ((pm_call_node_t *)node)->name; + pm_constant_t *constant = pm_constant_pool_id_to_constant(&parser->constant_pool, id); + return pm_token_is_it(constant->start, constant->start + constant->length); +} + +/** + * Convert a `it` variable call node to a node for `it` default parameter. + */ +static pm_node_t * +pm_node_check_it(pm_parser_t *parser, pm_node_t *node) { + if ( + (parser->version != PM_OPTIONS_VERSION_CRUBY_3_3_0) && + !parser->current_scope->closed && + pm_node_is_it(parser, node) + ) { + if (parser->current_scope->explicit_params) { + pm_parser_err_previous(parser, PM_ERR_IT_NOT_ALLOWED); + } else { + pm_node_destroy(parser, node); + pm_constant_id_t name_id = pm_parser_constant_id_constant(parser, "0it", 3); + node = (pm_node_t *) pm_local_variable_read_node_create_constant_id(parser, &parser->previous, name_id, 0); + } + } + return node; +} + /** * Returns true if the given bounds comprise a numbered parameter (i.e., they * are of the form /^_\d$/). @@ -14449,6 +14507,31 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if ((binding_power == PM_BINDING_POWER_STATEMENT) && match1(parser, PM_TOKEN_COMMA)) { node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX); } + else { + // Check if `it` is not going to be assigned. + switch (parser->current.type) { + case PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL: + case PM_TOKEN_AMPERSAND_EQUAL: + case PM_TOKEN_CARET_EQUAL: + case PM_TOKEN_EQUAL: + case PM_TOKEN_GREATER_GREATER_EQUAL: + case PM_TOKEN_LESS_LESS_EQUAL: + case PM_TOKEN_MINUS_EQUAL: + case PM_TOKEN_PARENTHESIS_RIGHT: + case PM_TOKEN_PERCENT_EQUAL: + case PM_TOKEN_PIPE_EQUAL: + case PM_TOKEN_PIPE_PIPE_EQUAL: + case PM_TOKEN_PLUS_EQUAL: + case PM_TOKEN_SLASH_EQUAL: + case PM_TOKEN_STAR_EQUAL: + case PM_TOKEN_STAR_STAR_EQUAL: + break; + default: + // Once we know it's neither a method call nor an assignment, + // we can finally create `it` default parameter. + node = pm_node_check_it(parser, node); + } + } return node; } @@ -15056,6 +15139,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (match2(parser, PM_TOKEN_DOT, PM_TOKEN_COLON_COLON)) { receiver = parse_variable_call(parser); + receiver = pm_node_check_it(parser, receiver); saved_param_name = pm_parser_current_param_name_unset(parser); pm_parser_scope_push(parser, true); diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index d1af9a5dae8385..60322585f05133 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -2069,6 +2069,13 @@ def test_forwarding_arg_and_block ], compare_ripper: false # Ripper does not check 'both block arg and actual block given'. end + def test_it_with_ordinary_parameter + source = "proc { || it }" + errors = [["`it` is not allowed when an ordinary parameter is defined", 10..12]] + + assert_errors expression(source), source, errors, compare_ripper: false + end + private def assert_errors(expected, source, errors, compare_ripper: RUBY_ENGINE == "ruby") diff --git a/test/prism/location_test.rb b/test/prism/location_test.rb index e5b75469255e45..a36f5fe011e270 100644 --- a/test/prism/location_test.rb +++ b/test/prism/location_test.rb @@ -570,6 +570,12 @@ def test_LocalVariableOrWriteNode def test_LocalVariableReadNode assert_location(LocalVariableReadNode, "foo = 1; foo", 9...12) + assert_location(LocalVariableReadNode, "-> { it }", 5...7) do |node| + node.body.body.first + end + assert_location(LocalVariableReadNode, "foo { it }", 6...8) do |node| + node.block.body.body.first + end end def test_LocalVariableTargetNode From bcc4b07cc318df3d5f53f14e36829eeab4066ecc Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Tue, 16 Jan 2024 21:47:14 -0800 Subject: [PATCH 226/640] [ruby/prism] Add a documentation about 0it https://github.com/ruby/prism/commit/313be8e3f7 --- prism/config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/prism/config.yml b/prism/config.yml index 0bff427bbff05d..ed331edbe26eca 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -2044,7 +2044,8 @@ nodes: comment: | Represents reading a local variable. Note that this requires that a local variable of the same name has already been written to in the same scope, - otherwise it is parsed as a method call. + otherwise it is parsed as a method call. Note that `it` default parameter + has `0it` as the name of this node. foo ^^^ From e0d60a833b8baa6305a2027253c1deafe5b5bcba Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Tue, 16 Jan 2024 22:06:39 -0800 Subject: [PATCH 227/640] [ruby/prism] Fix => ^it https://github.com/ruby/prism/commit/24a2872b4e --- prism/prism.c | 9 +++++++-- test/prism/location_test.rb | 3 +++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 0778667f962f23..3316c095177bf4 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -13602,8 +13602,13 @@ parse_pattern_primitive(pm_parser_t *parser, pm_diagnostic_id_t diag_id) { parser_lex(parser); pm_node_t *variable = (pm_node_t *) parse_variable(parser); if (variable == NULL) { - PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, PM_ERR_NO_LOCAL_VARIABLE, (int) (parser->previous.end - parser->previous.start), parser->previous.start); - variable = (pm_node_t *) pm_local_variable_read_node_create(parser, &parser->previous, 0); + if (pm_token_is_it(parser->previous.start, parser->previous.end)) { + pm_constant_id_t name_id = pm_parser_constant_id_constant(parser, "0it", 3); + variable = (pm_node_t *) pm_local_variable_read_node_create_constant_id(parser, &parser->previous, name_id, 0); + } else { + PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, PM_ERR_NO_LOCAL_VARIABLE, (int) (parser->previous.end - parser->previous.start), parser->previous.start); + variable = (pm_node_t *) pm_local_variable_read_node_create(parser, &parser->previous, 0); + } } return (pm_node_t *) pm_pinned_variable_node_create(parser, &operator, variable); diff --git a/test/prism/location_test.rb b/test/prism/location_test.rb index a36f5fe011e270..bcc357776a021b 100644 --- a/test/prism/location_test.rb +++ b/test/prism/location_test.rb @@ -680,6 +680,9 @@ def test_PinnedExpressionNode def test_PinnedVariableNode assert_location(PinnedVariableNode, "bar = 1; foo in ^bar", 16...20, &:pattern) + assert_location(PinnedVariableNode, "proc { 1 in ^it }.call(1)", 12...15) do |node| + node.receiver.block.body.body.first.pattern + end end def test_PostExecutionNode From 27d81b92828b7cb9d694724ebf12b614b0e6fb21 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Wed, 17 Jan 2024 09:08:25 -0800 Subject: [PATCH 228/640] [ruby/prism] Guard 3.3.0 for pinned it https://github.com/ruby/prism/commit/9778377b12 Co-authored-by: Kevin Newton --- prism/prism.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prism/prism.c b/prism/prism.c index 3316c095177bf4..22efbf33773d30 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -13602,7 +13602,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_diagnostic_id_t diag_id) { parser_lex(parser); pm_node_t *variable = (pm_node_t *) parse_variable(parser); if (variable == NULL) { - if (pm_token_is_it(parser->previous.start, parser->previous.end)) { + if (parser->version != PM_OPTIONS_VERSION_CRUBY_3_3_0 && pm_token_is_it(parser->previous.start, parser->previous.end)) { pm_constant_id_t name_id = pm_parser_constant_id_constant(parser, "0it", 3); variable = (pm_node_t *) pm_local_variable_read_node_create_constant_id(parser, &parser->previous, name_id, 0); } else { From de9411c0b91010e3a30b86904c7470b724564341 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Wed, 17 Jan 2024 09:24:11 -0800 Subject: [PATCH 229/640] [ruby/prism] Test version: 3.3.0 https://github.com/ruby/prism/commit/94ecb366c4 --- test/prism/location_test.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/prism/location_test.rb b/test/prism/location_test.rb index bcc357776a021b..9d583635e0290a 100644 --- a/test/prism/location_test.rb +++ b/test/prism/location_test.rb @@ -174,6 +174,10 @@ def test_CallNode assert_location(CallNode, "foo bar baz") assert_location(CallNode, "foo bar('baz')") + + assert_location(CallNode, "-> { it }", 5...7, version: "3.3.0") do |node| + node.body.body.first + end end def test_CallAndWriteNode @@ -900,8 +904,8 @@ def test_all_tested private - def assert_location(kind, source, expected = 0...source.length) - result = Prism.parse(source) + def assert_location(kind, source, expected = 0...source.length, **options) + result = Prism.parse(source, **options) assert_equal [], result.comments assert_equal [], result.errors From f43a919be494cf5b0f98f104da1024efda1abba5 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Wed, 17 Jan 2024 11:19:54 -0500 Subject: [PATCH 230/640] [PRISM] Fix fallthrough for PM_ENSURE_NODE This caused it to fall into PM_ELSE_NODE which caused ensure nodes to be compiled twice. Fixes ruby/prism#2176. --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 472d25eb355db4..368cba703980c3 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -4236,6 +4236,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, PM_COMPILE((pm_node_t *)ensure_node->statements); } ADD_LABEL(ret, end); + return; } case PM_ELSE_NODE: { pm_else_node_t *cast = (pm_else_node_t *)node; diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index c0f85af8b4e470..d547f82fe30e2e 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -931,6 +931,21 @@ def test_EnsureNode end a CODE + + # Test that ensure block only evaluated once + assert_prism_eval(<<~RUBY) + res = [] + begin + begin + raise + ensure + res << $!.to_s + end + rescue + res + end + RUBY + assert_prism_eval(<<-CODE) a = 1 begin From b2c12bfddbe7a0efdb7e7087dc7d05f8ce345b35 Mon Sep 17 00:00:00 2001 From: Andrew Konchin Date: Wed, 17 Jan 2024 20:11:09 +0200 Subject: [PATCH 231/640] [ruby/prism] Document order of scopes in parsing options https://github.com/ruby/prism/commit/908e92a695 --- prism/extension.c | 3 ++- prism/options.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/prism/extension.c b/prism/extension.c index 28bea39c7f03d7..b7c59e514ec86c 100644 --- a/prism/extension.c +++ b/prism/extension.c @@ -651,7 +651,8 @@ parse_input(pm_string_t *input, const pm_options_t *options) { * prism (which you can trigger with `nil` or `"latest"`). If you want to * parse exactly as CRuby 3.3.0 would, then you can pass `"3.3.0"`. * * `scopes` - the locals that are in scope surrounding the code that is being - * parsed. This should be an array of arrays of symbols or nil. + * parsed. This should be an array of arrays of symbols or nil. Scopes are + * ordered from the outermost scope to the innermost one. */ static VALUE parse(int argc, VALUE *argv, VALUE self) { diff --git a/prism/options.h b/prism/options.h index c3ca47b594decd..9ec3fba51e0d23 100644 --- a/prism/options.h +++ b/prism/options.h @@ -64,7 +64,8 @@ typedef struct { /** * The scopes surrounding the code that is being parsed. For most parses * this will be NULL, but for evals it will be the locals that are in scope - * surrounding the eval. + * surrounding the eval. Scopes are ordered from the outermost scope to the + * innermost one. */ pm_options_scope_t *scopes; From ebc470469687bc5d4788ff7c0c82454758f0080d Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Wed, 17 Jan 2024 14:45:05 -0500 Subject: [PATCH 232/640] [PRISM] Fix indentation in pm_setup_args [ci skip] --- prism_compile.c | 305 ++++++++++++++++++++++++------------------------ 1 file changed, 152 insertions(+), 153 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 368cba703980c3..7496105bc178d0 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -987,86 +987,85 @@ pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinf pm_node_t *argument = arguments_node_list.nodes[index]; switch (PM_NODE_TYPE(argument)) { - // A keyword hash node contains all keyword arguments as AssocNodes and AssocSplatNodes + // A keyword hash node contains all keyword arguments as AssocNodes and AssocSplatNodes case PM_KEYWORD_HASH_NODE: { - pm_keyword_hash_node_t *keyword_arg = (pm_keyword_hash_node_t *)argument; - size_t len = keyword_arg->elements.size; + pm_keyword_hash_node_t *keyword_arg = (pm_keyword_hash_node_t *)argument; + size_t len = keyword_arg->elements.size; - if (has_keyword_splat || has_splat) { - *flags |= VM_CALL_KW_SPLAT; - *flags |= VM_CALL_KW_SPLAT_MUT; + if (has_keyword_splat || has_splat) { + *flags |= VM_CALL_KW_SPLAT; + *flags |= VM_CALL_KW_SPLAT_MUT; - has_keyword_splat = true; - int cur_hash_size = 0; + has_keyword_splat = true; + int cur_hash_size = 0; - bool new_hash_emitted = false; - for (size_t i = 0; i < len; i++) { - pm_node_t *cur_node = keyword_arg->elements.nodes[i]; + bool new_hash_emitted = false; + for (size_t i = 0; i < len; i++) { + pm_node_t *cur_node = keyword_arg->elements.nodes[i]; - pm_node_type_t cur_type = PM_NODE_TYPE(cur_node); + pm_node_type_t cur_type = PM_NODE_TYPE(cur_node); - switch (PM_NODE_TYPE(cur_node)) { - case PM_ASSOC_NODE: { - pm_assoc_node_t *assoc = (pm_assoc_node_t *)cur_node; + switch (PM_NODE_TYPE(cur_node)) { + case PM_ASSOC_NODE: { + pm_assoc_node_t *assoc = (pm_assoc_node_t *)cur_node; - PM_COMPILE_NOT_POPPED(assoc->key); - PM_COMPILE_NOT_POPPED(assoc->value); - cur_hash_size++; + PM_COMPILE_NOT_POPPED(assoc->key); + PM_COMPILE_NOT_POPPED(assoc->value); + cur_hash_size++; - // If we're at the last keyword arg, or the last assoc node of this "set", - // then we want to either construct a newhash or merge onto previous hashes - if (i == (len - 1) || !PM_NODE_TYPE_P(keyword_arg->elements.nodes[i + 1], cur_type)) { - if (new_hash_emitted) { - ADD_SEND(ret, &dummy_line_node, id_core_hash_merge_ptr, INT2FIX(cur_hash_size * 2 + 1)); - } - else { - ADD_INSN1(ret, &dummy_line_node, newhash, INT2FIX(cur_hash_size * 2)); - cur_hash_size = 0; - new_hash_emitted = true; - } + // If we're at the last keyword arg, or the last assoc node of this "set", + // then we want to either construct a newhash or merge onto previous hashes + if (i == (len - 1) || !PM_NODE_TYPE_P(keyword_arg->elements.nodes[i + 1], cur_type)) { + if (new_hash_emitted) { + ADD_SEND(ret, &dummy_line_node, id_core_hash_merge_ptr, INT2FIX(cur_hash_size * 2 + 1)); + } + else { + ADD_INSN1(ret, &dummy_line_node, newhash, INT2FIX(cur_hash_size * 2)); + cur_hash_size = 0; + new_hash_emitted = true; } - - break; } - case PM_ASSOC_SPLAT_NODE: { - if (len > 1) { - ADD_INSN1(ret, &dummy_line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); - if (i == 0) { - ADD_INSN1(ret, &dummy_line_node, newhash, INT2FIX(0)); - new_hash_emitted = true; - } - else { - PM_SWAP; - } - *flags |= VM_CALL_KW_SPLAT_MUT; + break; + } + case PM_ASSOC_SPLAT_NODE: { + if (len > 1) { + ADD_INSN1(ret, &dummy_line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + if (i == 0) { + ADD_INSN1(ret, &dummy_line_node, newhash, INT2FIX(0)); + new_hash_emitted = true; + } + else { + PM_SWAP; } - pm_assoc_splat_node_t *assoc_splat = (pm_assoc_splat_node_t *)cur_node; - PM_COMPILE_NOT_POPPED(assoc_splat->value); - - *flags |= VM_CALL_KW_SPLAT; + *flags |= VM_CALL_KW_SPLAT_MUT; + } - if (len > 1) { - ADD_SEND(ret, &dummy_line_node, id_core_hash_merge_kwd, INT2FIX(2)); - } + pm_assoc_splat_node_t *assoc_splat = (pm_assoc_splat_node_t *)cur_node; + PM_COMPILE_NOT_POPPED(assoc_splat->value); - if ((i < len - 1) && !PM_NODE_TYPE_P(keyword_arg->elements.nodes[i + 1], cur_type)) { - ADD_INSN1(ret, &dummy_line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); - PM_SWAP; - } + *flags |= VM_CALL_KW_SPLAT; - cur_hash_size = 0; - break; + if (len > 1) { + ADD_SEND(ret, &dummy_line_node, id_core_hash_merge_kwd, INT2FIX(2)); } - default: { - rb_bug("Unknown type in keyword argument %s\n", pm_node_type_to_str(PM_NODE_TYPE(cur_node))); + + if ((i < len - 1) && !PM_NODE_TYPE_P(keyword_arg->elements.nodes[i + 1], cur_type)) { + ADD_INSN1(ret, &dummy_line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + PM_SWAP; } + + cur_hash_size = 0; + break; } - } - break; - } - else { + default: { + rb_bug("Unknown type in keyword argument %s\n", pm_node_type_to_str(PM_NODE_TYPE(cur_node))); + } + } + } + } + else { // We need to first figure out if all elements of the KeywordHashNode are AssocNodes // with symbol keys. if (PM_NODE_FLAG_P(keyword_arg, PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS)) { @@ -1102,110 +1101,110 @@ pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinf ADD_INSN1(ret, &dummy_line_node, newhash, INT2FIX(len * 2)); } - } - break; + } + break; } case PM_SPLAT_NODE: { - *flags |= VM_CALL_ARGS_SPLAT; - pm_splat_node_t *splat_node = (pm_splat_node_t *)argument; - if (splat_node->expression) { - PM_COMPILE_NOT_POPPED(splat_node->expression); - } + *flags |= VM_CALL_ARGS_SPLAT; + pm_splat_node_t *splat_node = (pm_splat_node_t *)argument; + if (splat_node->expression) { + PM_COMPILE_NOT_POPPED(splat_node->expression); + } - bool first_splat = !has_splat; + bool first_splat = !has_splat; - if (first_splat) { - // If this is the first splat array seen and it's not the - // last parameter, we want splatarray to dup it. - // - // foo(a, *b, c) - // ^^ - if (index + 1 < arguments_node_list.size) { - ADD_INSN1(ret, &dummy_line_node, splatarray, Qtrue); - } - // If this is the first spalt array seen and it's the last - // parameter, we don't want splatarray to dup it. - // - // foo(a, *b) - // ^^ - else { - ADD_INSN1(ret, &dummy_line_node, splatarray, Qfalse); - } - } - else { - // If this is not the first splat array seen and it is also - // the last parameter, we don't want splayarray to dup it - // and we need to concat the array. - // - // foo(a, *b, *c) - // ^^ - ADD_INSN1(ret, &dummy_line_node, splatarray, Qfalse); - ADD_INSN(ret, &dummy_line_node, concatarray); - } + if (first_splat) { + // If this is the first splat array seen and it's not the + // last parameter, we want splatarray to dup it. + // + // foo(a, *b, c) + // ^^ + if (index + 1 < arguments_node_list.size) { + ADD_INSN1(ret, &dummy_line_node, splatarray, Qtrue); + } + // If this is the first spalt array seen and it's the last + // parameter, we don't want splatarray to dup it. + // + // foo(a, *b) + // ^^ + else { + ADD_INSN1(ret, &dummy_line_node, splatarray, Qfalse); + } + } + else { + // If this is not the first splat array seen and it is also + // the last parameter, we don't want splayarray to dup it + // and we need to concat the array. + // + // foo(a, *b, *c) + // ^^ + ADD_INSN1(ret, &dummy_line_node, splatarray, Qfalse); + ADD_INSN(ret, &dummy_line_node, concatarray); + } - has_splat = true; - post_splat_counter = 0; + has_splat = true; + post_splat_counter = 0; - break; + break; } case PM_FORWARDING_ARGUMENTS_NODE: { - orig_argc++; - *flags |= VM_CALL_ARGS_BLOCKARG | VM_CALL_ARGS_SPLAT; - ADD_GETLOCAL(ret, &dummy_line_node, 3, 0); - ADD_INSN1(ret, &dummy_line_node, splatarray, RBOOL(arguments_node_list.size > 1)); - ADD_INSN2(ret, &dummy_line_node, getblockparamproxy, INT2FIX(4), INT2FIX(0)); - break; + orig_argc++; + *flags |= VM_CALL_ARGS_BLOCKARG | VM_CALL_ARGS_SPLAT; + ADD_GETLOCAL(ret, &dummy_line_node, 3, 0); + ADD_INSN1(ret, &dummy_line_node, splatarray, RBOOL(arguments_node_list.size > 1)); + ADD_INSN2(ret, &dummy_line_node, getblockparamproxy, INT2FIX(4), INT2FIX(0)); + break; } default: { - post_splat_counter++; - PM_COMPILE_NOT_POPPED(argument); - - // If we have a splat and we've seen a splat, we need to process - // everything after the splat. - if (has_splat) { - // Stack items are turned into an array and concatenated in - // the following cases: - // - // If the next node is a splat: - // - // foo(*a, b, *c) - // - // If the next node is a kwarg or kwarg splat: - // - // foo(*a, b, c: :d) - // foo(*a, b, **c) - // - // If the next node is NULL (we have hit the end): - // - // foo(*a, b) - if (index == arguments_node_list.size - 1) { - RUBY_ASSERT(post_splat_counter > 0); - ADD_INSN1(ret, &dummy_line_node, newarray, INT2FIX(post_splat_counter)); - ADD_INSN(ret, &dummy_line_node, concatarray); - } - else { - pm_node_t *next_arg = arguments_node_list.nodes[index + 1]; + post_splat_counter++; + PM_COMPILE_NOT_POPPED(argument); + + // If we have a splat and we've seen a splat, we need to process + // everything after the splat. + if (has_splat) { + // Stack items are turned into an array and concatenated in + // the following cases: + // + // If the next node is a splat: + // + // foo(*a, b, *c) + // + // If the next node is a kwarg or kwarg splat: + // + // foo(*a, b, c: :d) + // foo(*a, b, **c) + // + // If the next node is NULL (we have hit the end): + // + // foo(*a, b) + if (index == arguments_node_list.size - 1) { + RUBY_ASSERT(post_splat_counter > 0); + ADD_INSN1(ret, &dummy_line_node, newarray, INT2FIX(post_splat_counter)); + ADD_INSN(ret, &dummy_line_node, concatarray); + } + else { + pm_node_t *next_arg = arguments_node_list.nodes[index + 1]; - switch (PM_NODE_TYPE(next_arg)) { - // A keyword hash node contains all keyword arguments as AssocNodes and AssocSplatNodes - case PM_KEYWORD_HASH_NODE: { - ADD_INSN1(ret, &dummy_line_node, newarray, INT2FIX(post_splat_counter)); - ADD_INSN(ret, &dummy_line_node, concatarray); - break; - } - case PM_SPLAT_NODE: { - ADD_INSN1(ret, &dummy_line_node, newarray, INT2FIX(post_splat_counter)); - ADD_INSN(ret, &dummy_line_node, concatarray); - break; - } - default: - break; + switch (PM_NODE_TYPE(next_arg)) { + // A keyword hash node contains all keyword arguments as AssocNodes and AssocSplatNodes + case PM_KEYWORD_HASH_NODE: { + ADD_INSN1(ret, &dummy_line_node, newarray, INT2FIX(post_splat_counter)); + ADD_INSN(ret, &dummy_line_node, concatarray); + break; } - } - } - else { - orig_argc++; - } + case PM_SPLAT_NODE: { + ADD_INSN1(ret, &dummy_line_node, newarray, INT2FIX(post_splat_counter)); + ADD_INSN(ret, &dummy_line_node, concatarray); + break; + } + default: + break; + } + } + } + else { + orig_argc++; + } } } } From b0a32b724971c5113c02946b1b959c1d73a9e256 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 17 Jan 2024 14:35:51 -0500 Subject: [PATCH 233/640] [PRISM] Enable more btests --- tool/prism_btests | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tool/prism_btests b/tool/prism_btests index e14f0d3cf9524a..1c96438545df1c 100644 --- a/tool/prism_btests +++ b/tool/prism_btests @@ -1,5 +1,6 @@ ../src/bootstraptest/test_attr.rb ../src/bootstraptest/test_autoload.rb +../src/bootstraptest/test_block.rb ../src/bootstraptest/test_class.rb ../src/bootstraptest/test_constant_cache.rb ../src/bootstraptest/test_env.rb @@ -9,27 +10,26 @@ ../src/bootstraptest/test_flip.rb ../src/bootstraptest/test_fork.rb ../src/bootstraptest/test_gc.rb +../src/bootstraptest/test_io.rb ../src/bootstraptest/test_jump.rb -../src/bootstraptest/test_literal.rb ../src/bootstraptest/test_literal_suffix.rb +../src/bootstraptest/test_literal.rb ../src/bootstraptest/test_load.rb ../src/bootstraptest/test_marshal.rb +../src/bootstraptest/test_massign.rb ../src/bootstraptest/test_objectspace.rb ../src/bootstraptest/test_proc.rb ../src/bootstraptest/test_rjit.rb ../src/bootstraptest/test_string.rb ../src/bootstraptest/test_struct.rb ../src/bootstraptest/test_thread.rb -../src/bootstraptest/test_block.rb +../src/bootstraptest/test_yjit_30k_ifelse.rb +../src/bootstraptest/test_yjit_30k_methods.rb # ../src/bootstraptest/test_exception.rb # ../src/bootstraptest/test_flow.rb # ../src/bootstraptest/test_insns.rb -# ../src/bootstraptest/test_io.rb -# ../src/bootstraptest/test_massign.rb # ../src/bootstraptest/test_method.rb # ../src/bootstraptest/test_ractor.rb # ../src/bootstraptest/test_syntax.rb -# ../src/bootstraptest/test_yjit.rb -../src/bootstraptest/test_yjit_30k_ifelse.rb -../src/bootstraptest/test_yjit_30k_methods.rb # ../src/bootstraptest/test_yjit_rust_port.rb +# ../src/bootstraptest/test_yjit.rb From a6e924cf5f67368b49d5745f5cae22bc68ef21a1 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Wed, 17 Jan 2024 11:50:40 -0500 Subject: [PATCH 234/640] [PRISM] Fix crash in compile_prism If the argument is not a file or a string, it assumes it's a string which will crash because RSTRING_PTR and RSTRING_LEN assumes it's a string. --- iseq.c | 1 + test/ruby/test_iseq.rb | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/iseq.c b/iseq.c index 28c2d4f80b2068..4f1c39d2ae51b1 100644 --- a/iseq.c +++ b/iseq.c @@ -1485,6 +1485,7 @@ iseqw_s_compile_prism(int argc, VALUE *argv, VALUE self) pm_string_mapped_init(&input, RSTRING_PTR(file)); } else { + Check_Type(src, T_STRING); input.source = (const uint8_t *)RSTRING_PTR(src); input.length = RSTRING_LEN(src); input.type = PM_STRING_SHARED; diff --git a/test/ruby/test_iseq.rb b/test/ruby/test_iseq.rb index dd81610b5368fe..35bf36e4921cca 100644 --- a/test/ruby/test_iseq.rb +++ b/test/ruby/test_iseq.rb @@ -809,4 +809,10 @@ def test_compile_prism_with_file end end end + + def test_compile_prism_with_invalid_object_type + assert_raise(TypeError) do + RubyVM::InstructionSequence.compile_prism(Object.new) + end + end end From f657fd150f46ab4d93344d34bcb663630d7f064a Mon Sep 17 00:00:00 2001 From: eileencodes Date: Tue, 16 Jan 2024 16:11:24 -0500 Subject: [PATCH 235/640] [Prism] Implement defined? for PM_CALL_AND_WRITE_NODE Ruby code: ```ruby defined?(PrismTestSubclass.test_call_and_write_node &&= 1) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,58)> 0000 putobject "assignment" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,58)> 0000 putobject "assignment" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 2 ++ 2 files changed, 3 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 7496105bc178d0..98b7b3537e8352 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2686,6 +2686,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co ADD_INSN3(ret, &dummy_line_node, defined, INT2FIX(DEFINED_ZSUPER), 0, PUSH_VAL(DEFINED_ZSUPER)); return; + case PM_CALL_AND_WRITE_NODE: case PM_CONSTANT_WRITE_NODE: case PM_CONSTANT_OPERATOR_WRITE_NODE: case PM_CONSTANT_AND_WRITE_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index d547f82fe30e2e..38bce4f303b8b0 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -237,6 +237,8 @@ def self.m1; defined?(return) end assert_prism_eval("defined?(defined?(a))") assert_prism_eval('defined?(:"#{1}")') assert_prism_eval("defined?(`echo #{1}`)") + + assert_prism_eval("defined?(PrismTestSubclass.test_call_and_write_node &&= 1)") end def test_GlobalVariableReadNode From 9c5391d7dc99fcc06fae1541f1f6fc0c2913c932 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 10:01:38 -0500 Subject: [PATCH 236/640] [Prism] Implement defined? for PM_CALL_OPERATOR_WRITE_NODE Ruby code: ```ruby defined?(PrismTestSubclass.test_call_operator_write_node += 1) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,58)> 0000 putobject "assignment" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,58)> 0000 putobject "assignment" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 2 ++ test/ruby/test_compile_prism.rb | 1 + 2 files changed, 3 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 98b7b3537e8352..6880f46b693fd4 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2687,6 +2687,8 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co PUSH_VAL(DEFINED_ZSUPER)); return; case PM_CALL_AND_WRITE_NODE: + case PM_CALL_OPERATOR_WRITE_NODE: + case PM_CONSTANT_WRITE_NODE: case PM_CONSTANT_OPERATOR_WRITE_NODE: case PM_CONSTANT_AND_WRITE_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 38bce4f303b8b0..ba8178674f838f 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -239,6 +239,7 @@ def self.m1; defined?(return) end assert_prism_eval("defined?(`echo #{1}`)") assert_prism_eval("defined?(PrismTestSubclass.test_call_and_write_node &&= 1)") + assert_prism_eval("defined?(PrismTestSubclass.test_call_operator_write_node += 1)") end def test_GlobalVariableReadNode From 7522e867ee1b77a303d294ef9fba26889c1e59dd Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 10:03:36 -0500 Subject: [PATCH 237/640] [Prism] Implement defined? for PM_CALL_OR_WRITE_NODE Ruby code: ```ruby defined?(PrismTestSubclass.test_call_or_write_node ||= 1) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,58)> 0000 putobject "assignment" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,58)> 0000 putobject "assignment" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 6880f46b693fd4..eab1a2d7ea4170 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2688,6 +2688,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co return; case PM_CALL_AND_WRITE_NODE: case PM_CALL_OPERATOR_WRITE_NODE: + case PM_CALL_OR_WRITE_NODE: case PM_CONSTANT_WRITE_NODE: case PM_CONSTANT_OPERATOR_WRITE_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index ba8178674f838f..df6a27a666ea7e 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -240,6 +240,7 @@ def self.m1; defined?(return) end assert_prism_eval("defined?(PrismTestSubclass.test_call_and_write_node &&= 1)") assert_prism_eval("defined?(PrismTestSubclass.test_call_operator_write_node += 1)") + assert_prism_eval("defined?(PrismTestSubclass.test_call_or_write_node ||= 1)") end def test_GlobalVariableReadNode From 98d6f503129f436292073c22ac1051a31bfd5f00 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 10:05:58 -0500 Subject: [PATCH 238/640] [Prism] Implement defined? for PM_CONSTANT_PATH_AND_WRITE_NODE Ruby code: ```ruby defined?(Prism::CPAWN &&= 1) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,58)> 0000 putobject "assignment" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,58)> 0000 putobject "assignment" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 2 ++ test/ruby/test_compile_prism.rb | 1 + 2 files changed, 3 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index eab1a2d7ea4170..04e25a565a418e 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2695,6 +2695,8 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_CONSTANT_AND_WRITE_NODE: case PM_CONSTANT_OR_WRITE_NODE: + case PM_CONSTANT_PATH_AND_WRITE_NODE: + case PM_GLOBAL_VARIABLE_WRITE_NODE: case PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE: case PM_GLOBAL_VARIABLE_AND_WRITE_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index df6a27a666ea7e..6dbe716ff0850f 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -241,6 +241,7 @@ def self.m1; defined?(return) end assert_prism_eval("defined?(PrismTestSubclass.test_call_and_write_node &&= 1)") assert_prism_eval("defined?(PrismTestSubclass.test_call_operator_write_node += 1)") assert_prism_eval("defined?(PrismTestSubclass.test_call_or_write_node ||= 1)") + assert_prism_eval("defined?(Prism::CPAWN &&= 1)") end def test_GlobalVariableReadNode From 3c9dc2f806af09005d39b4d8ffbf260485b248e2 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 10:09:18 -0500 Subject: [PATCH 239/640] [Prism] Implement defined? for PM_CONSTANT_PATH_OPERATOR_WRITE_NODE Ruby code: ```ruby defined?(Prism::CPOWN += 1) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,58)> 0000 putobject "assignment" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,58)> 0000 putobject "assignment" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 04e25a565a418e..d4bd93cf5da6e3 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2696,6 +2696,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_CONSTANT_OR_WRITE_NODE: case PM_CONSTANT_PATH_AND_WRITE_NODE: + case PM_CONSTANT_PATH_OPERATOR_WRITE_NODE: case PM_GLOBAL_VARIABLE_WRITE_NODE: case PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 6dbe716ff0850f..fe463a02339bd9 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -242,6 +242,7 @@ def self.m1; defined?(return) end assert_prism_eval("defined?(PrismTestSubclass.test_call_operator_write_node += 1)") assert_prism_eval("defined?(PrismTestSubclass.test_call_or_write_node ||= 1)") assert_prism_eval("defined?(Prism::CPAWN &&= 1)") + assert_prism_eval("defined?(Prism::CPOWN += 1)") end def test_GlobalVariableReadNode From 54b8330e45b718fc33cd391d6f0ed6cb67ee73c3 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 10:12:49 -0500 Subject: [PATCH 240/640] [Prism] Implement defined? for PM_CONSTANT_PATH_OR_WRITE_NODE Ruby code: ```ruby defined?(Prism::CPOrWN ||= 1) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,58)> 0000 putobject "assignment" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,58)> 0000 putobject "assignment" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index d4bd93cf5da6e3..93eb2f1e050ee4 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2697,6 +2697,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_CONSTANT_PATH_AND_WRITE_NODE: case PM_CONSTANT_PATH_OPERATOR_WRITE_NODE: + case PM_CONSTANT_PATH_OR_WRITE_NODE: case PM_GLOBAL_VARIABLE_WRITE_NODE: case PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index fe463a02339bd9..57e5c85275dee0 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -243,6 +243,7 @@ def self.m1; defined?(return) end assert_prism_eval("defined?(PrismTestSubclass.test_call_or_write_node ||= 1)") assert_prism_eval("defined?(Prism::CPAWN &&= 1)") assert_prism_eval("defined?(Prism::CPOWN += 1)") + assert_prism_eval("defined?(Prism::CPOrWN ||= 1)") end def test_GlobalVariableReadNode From e217c5772bd1824606c029d093e39f43acb15179 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 10:18:02 -0500 Subject: [PATCH 241/640] [Prism] Implement defined? for PM_CONSTANT_PATH_WRITE_NODE Ruby code: ```ruby defined?(Prism::CPWN = 1) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,58)> 0000 putobject "assignment" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,58)> 0000 putobject "assignment" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 93eb2f1e050ee4..be9be37411e0bb 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2698,6 +2698,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_CONSTANT_PATH_AND_WRITE_NODE: case PM_CONSTANT_PATH_OPERATOR_WRITE_NODE: case PM_CONSTANT_PATH_OR_WRITE_NODE: + case PM_CONSTANT_PATH_WRITE_NODE: case PM_GLOBAL_VARIABLE_WRITE_NODE: case PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 57e5c85275dee0..5e6b43d25a03f7 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -244,6 +244,7 @@ def self.m1; defined?(return) end assert_prism_eval("defined?(Prism::CPAWN &&= 1)") assert_prism_eval("defined?(Prism::CPOWN += 1)") assert_prism_eval("defined?(Prism::CPOrWN ||= 1)") + assert_prism_eval("defined?(Prism::CPWN = 1)") end def test_GlobalVariableReadNode From f8ef77af3bbd2690c81cffccdf40afe953c7e6a7 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 10:22:01 -0500 Subject: [PATCH 242/640] [Prism] Implement defined? for PM_INDEX_AND_WRITE_NODE Ruby code: ```ruby defined?([0][0] &&= 1) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,58)> 0000 putobject "assignment" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,58)> 0000 putobject "assignment" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 2 ++ test/ruby/test_compile_prism.rb | 1 + 2 files changed, 3 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index be9be37411e0bb..4bcbeb1208d8b3 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2710,6 +2710,8 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_CLASS_VARIABLE_AND_WRITE_NODE: case PM_CLASS_VARIABLE_OR_WRITE_NODE: + case PM_INDEX_AND_WRITE_NODE: + case PM_INSTANCE_VARIABLE_WRITE_NODE: case PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE: case PM_INSTANCE_VARIABLE_AND_WRITE_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 5e6b43d25a03f7..d64cef57d80325 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -245,6 +245,7 @@ def self.m1; defined?(return) end assert_prism_eval("defined?(Prism::CPOWN += 1)") assert_prism_eval("defined?(Prism::CPOrWN ||= 1)") assert_prism_eval("defined?(Prism::CPWN = 1)") + assert_prism_eval("defined?([0][0] &&= 1)") end def test_GlobalVariableReadNode From ff54a8f4c7b46b60ef3849a66fd46d1a199c83f2 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 10:23:23 -0500 Subject: [PATCH 243/640] [Prism] Implement defined? for PM_INDEX_OPERATOR_WRITE_NODE Ruby code: ```ruby defined?([0][0] += 1) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,58)> 0000 putobject "assignment" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,58)> 0000 putobject "assignment" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 4bcbeb1208d8b3..dc2b3387fef9ef 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2711,6 +2711,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_CLASS_VARIABLE_OR_WRITE_NODE: case PM_INDEX_AND_WRITE_NODE: + case PM_INDEX_OPERATOR_WRITE_NODE: case PM_INSTANCE_VARIABLE_WRITE_NODE: case PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index d64cef57d80325..def4bd1e26ff78 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -246,6 +246,7 @@ def self.m1; defined?(return) end assert_prism_eval("defined?(Prism::CPOrWN ||= 1)") assert_prism_eval("defined?(Prism::CPWN = 1)") assert_prism_eval("defined?([0][0] &&= 1)") + assert_prism_eval("defined?([0][0] += 1)") end def test_GlobalVariableReadNode From e1bae2c6930cee58586e9c9d7999b0143af3ee23 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 10:24:34 -0500 Subject: [PATCH 244/640] [Prism] Implement defined? for PM_INDEX_OR_WRITE_NODE Ruby code: ```ruby defined?([0][0] ||= 1) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,58)> 0000 putobject "assignment" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,58)> 0000 putobject "assignment" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index dc2b3387fef9ef..95bdbece4243f5 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2712,6 +2712,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_INDEX_AND_WRITE_NODE: case PM_INDEX_OPERATOR_WRITE_NODE: + case PM_INDEX_OR_WRITE_NODE: case PM_INSTANCE_VARIABLE_WRITE_NODE: case PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index def4bd1e26ff78..f46c491598ee1f 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -247,6 +247,7 @@ def self.m1; defined?(return) end assert_prism_eval("defined?(Prism::CPWN = 1)") assert_prism_eval("defined?([0][0] &&= 1)") assert_prism_eval("defined?([0][0] += 1)") + assert_prism_eval("defined?([0][0] ||= 1)") end def test_GlobalVariableReadNode From c546ee3bb5a8d7469ea6db86f21963dc04913c30 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Wed, 17 Jan 2024 11:08:21 -0800 Subject: [PATCH 245/640] Remove SizedQueue#freeze Queue#freeze uses the same C function, so SizedQueue#freeze can use that via normal method lookup. --- thread_sync.c | 1 - 1 file changed, 1 deletion(-) diff --git a/thread_sync.c b/thread_sync.c index c0a0ca7103369e..0792da481d47b1 100644 --- a/thread_sync.c +++ b/thread_sync.c @@ -1652,7 +1652,6 @@ Init_thread_sync(void) rb_define_method(rb_cSizedQueue, "clear", rb_szqueue_clear, 0); rb_define_method(rb_cSizedQueue, "length", rb_szqueue_length, 0); rb_define_method(rb_cSizedQueue, "num_waiting", rb_szqueue_num_waiting, 0); - rb_define_method(rb_cSizedQueue, "freeze", rb_queue_freeze, 0); rb_define_alias(rb_cSizedQueue, "size", "length"); /* CVar */ From 00f9456f166e9d45c70e530992f5a90b37050553 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Wed, 17 Jan 2024 14:59:47 -0500 Subject: [PATCH 246/640] [PRISM] Remove unnecessary flag setting VM_CALL_KW_SPLAT and VM_CALL_KW_SPLAT_MUT are guaranteeed to be set in this code path, so we don't need to set it again. --- prism_compile.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 95bdbece4243f5..75d8de5b34b995 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -1038,15 +1038,11 @@ pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinf else { PM_SWAP; } - - *flags |= VM_CALL_KW_SPLAT_MUT; } pm_assoc_splat_node_t *assoc_splat = (pm_assoc_splat_node_t *)cur_node; PM_COMPILE_NOT_POPPED(assoc_splat->value); - *flags |= VM_CALL_KW_SPLAT; - if (len > 1) { ADD_SEND(ret, &dummy_line_node, id_core_hash_merge_kwd, INT2FIX(2)); } From 9f0d38960f8b3a5e8544105fdbeda79cbd7ecd4c Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Wed, 17 Jan 2024 15:29:37 -0500 Subject: [PATCH 247/640] [PRISM] Refactor keyword hash nodes Follow up to #9540. --- prism_compile.c | 208 ++++++++++++++++++------------------------------ 1 file changed, 76 insertions(+), 132 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 75d8de5b34b995..5c153b25e62b0e 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -962,6 +962,78 @@ pm_compile_index_write_nodes_add_send(bool popped, LINK_ANCHOR *const ret, rb_is return; } +static void +pm_arg_compile_keyword_hash_node(pm_keyword_hash_node_t *node, rb_iseq_t *iseq, LINK_ANCHOR *const ret, const uint8_t *src, bool popped, pm_scope_node_t *scope_node, NODE dummy_line_node) +{ + size_t len = node->elements.size; + int cur_hash_size = 0; + + bool new_hash_emitted = false; + for (size_t i = 0; i < len; i++) { + pm_node_t *cur_node = node->elements.nodes[i]; + pm_node_type_t cur_type = PM_NODE_TYPE(cur_node); + + switch (cur_type) { + case PM_ASSOC_NODE: { + pm_assoc_node_t *assoc = (pm_assoc_node_t *)cur_node; + + PM_COMPILE(assoc->key); + PM_COMPILE(assoc->value); + cur_hash_size++; + + // If we're at the last keyword arg, or the last assoc node of this "set", + // then we want to either construct a newhash or merge onto previous hashes + if (i == (len - 1) || !PM_NODE_TYPE_P(node->elements.nodes[i + 1], cur_type)) { + if (new_hash_emitted) { + ADD_SEND(ret, &dummy_line_node, id_core_hash_merge_ptr, INT2FIX(cur_hash_size * 2 + 1)); + } + else { + if (!popped) { + ADD_INSN1(ret, &dummy_line_node, newhash, INT2FIX(cur_hash_size * 2)); + cur_hash_size = 0; + new_hash_emitted = true; + } + } + } + + break; + } + case PM_ASSOC_SPLAT_NODE: { + if (len > 1) { + ADD_INSN1(ret, &dummy_line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + if (i == 0) { + if (!popped) { + ADD_INSN1(ret, &dummy_line_node, newhash, INT2FIX(0)); + new_hash_emitted = true; + } + } + else { + PM_SWAP; + } + } + + pm_assoc_splat_node_t *assoc_splat = (pm_assoc_splat_node_t *)cur_node; + PM_COMPILE(assoc_splat->value); + + if (len > 1) { + ADD_SEND(ret, &dummy_line_node, id_core_hash_merge_kwd, INT2FIX(2)); + } + + if ((i < len - 1) && !PM_NODE_TYPE_P(node->elements.nodes[i + 1], cur_type)) { + ADD_INSN1(ret, &dummy_line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + PM_SWAP; + } + + cur_hash_size = 0; + break; + } + default: { + rb_bug("Unknown type in keyword argument %s\n", pm_node_type_to_str(PM_NODE_TYPE(cur_node))); + } + } + } +} + static int pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinfo_kwarg **kw_arg, rb_iseq_t *iseq, LINK_ANCHOR *const ret, const uint8_t *src, bool popped, pm_scope_node_t *scope_node, NODE dummy_line_node, pm_parser_t *parser) { @@ -990,78 +1062,18 @@ pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinf // A keyword hash node contains all keyword arguments as AssocNodes and AssocSplatNodes case PM_KEYWORD_HASH_NODE: { pm_keyword_hash_node_t *keyword_arg = (pm_keyword_hash_node_t *)argument; - size_t len = keyword_arg->elements.size; if (has_keyword_splat || has_splat) { *flags |= VM_CALL_KW_SPLAT; *flags |= VM_CALL_KW_SPLAT_MUT; has_keyword_splat = true; - int cur_hash_size = 0; - - bool new_hash_emitted = false; - for (size_t i = 0; i < len; i++) { - pm_node_t *cur_node = keyword_arg->elements.nodes[i]; - - pm_node_type_t cur_type = PM_NODE_TYPE(cur_node); - - switch (PM_NODE_TYPE(cur_node)) { - case PM_ASSOC_NODE: { - pm_assoc_node_t *assoc = (pm_assoc_node_t *)cur_node; - - PM_COMPILE_NOT_POPPED(assoc->key); - PM_COMPILE_NOT_POPPED(assoc->value); - cur_hash_size++; - - // If we're at the last keyword arg, or the last assoc node of this "set", - // then we want to either construct a newhash or merge onto previous hashes - if (i == (len - 1) || !PM_NODE_TYPE_P(keyword_arg->elements.nodes[i + 1], cur_type)) { - if (new_hash_emitted) { - ADD_SEND(ret, &dummy_line_node, id_core_hash_merge_ptr, INT2FIX(cur_hash_size * 2 + 1)); - } - else { - ADD_INSN1(ret, &dummy_line_node, newhash, INT2FIX(cur_hash_size * 2)); - cur_hash_size = 0; - new_hash_emitted = true; - } - } - - break; - } - case PM_ASSOC_SPLAT_NODE: { - if (len > 1) { - ADD_INSN1(ret, &dummy_line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); - if (i == 0) { - ADD_INSN1(ret, &dummy_line_node, newhash, INT2FIX(0)); - new_hash_emitted = true; - } - else { - PM_SWAP; - } - } - - pm_assoc_splat_node_t *assoc_splat = (pm_assoc_splat_node_t *)cur_node; - PM_COMPILE_NOT_POPPED(assoc_splat->value); - if (len > 1) { - ADD_SEND(ret, &dummy_line_node, id_core_hash_merge_kwd, INT2FIX(2)); - } - - if ((i < len - 1) && !PM_NODE_TYPE_P(keyword_arg->elements.nodes[i + 1], cur_type)) { - ADD_INSN1(ret, &dummy_line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); - PM_SWAP; - } - - cur_hash_size = 0; - break; - } - default: { - rb_bug("Unknown type in keyword argument %s\n", pm_node_type_to_str(PM_NODE_TYPE(cur_node))); - } - } - } + pm_arg_compile_keyword_hash_node(keyword_arg, iseq, ret, src, false, scope_node, dummy_line_node); } else { + size_t len = keyword_arg->elements.size; + // We need to first figure out if all elements of the KeywordHashNode are AssocNodes // with symbol keys. if (PM_NODE_FLAG_P(keyword_arg, PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS)) { @@ -3158,76 +3170,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, switch (PM_NODE_TYPE(element_node)) { case PM_KEYWORD_HASH_NODE: { has_kw_splat = true; - pm_keyword_hash_node_t *keyword_arg = (pm_keyword_hash_node_t *)element_node; - size_t len = keyword_arg->elements.size; - - int cur_hash_size = 0; - - bool new_hash_emitted = false; - for (size_t i = 0; i < len; i++) { - pm_node_t *cur_node = keyword_arg->elements.nodes[i]; - - pm_node_type_t cur_type = PM_NODE_TYPE(cur_node); - - switch (PM_NODE_TYPE(cur_node)) { - case PM_ASSOC_NODE: { - pm_assoc_node_t *assoc = (pm_assoc_node_t *)cur_node; - - PM_COMPILE(assoc->key); - PM_COMPILE(assoc->value); - cur_hash_size++; - - // If we're at the last keyword arg, or the last assoc node of this "set", - // then we want to either construct a newhash or merge onto previous hashes - if (i == (len - 1) || !PM_NODE_TYPE_P(keyword_arg->elements.nodes[i + 1], cur_type)) { - if (new_hash_emitted) { - ADD_SEND(ret, &dummy_line_node, id_core_hash_merge_ptr, INT2FIX(cur_hash_size * 2 + 1)); - } - else { - if (!popped) { - ADD_INSN1(ret, &dummy_line_node, newhash, INT2FIX(cur_hash_size * 2)); - cur_hash_size = 0; - new_hash_emitted = true; - } - } - } - break; - } - case PM_ASSOC_SPLAT_NODE: { - if (len > 1) { - ADD_INSN1(ret, &dummy_line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); - if (i == 0) { - if (!popped) { - ADD_INSN1(ret, &dummy_line_node, newhash, INT2FIX(0)); - new_hash_emitted = true; - } - } - else { - PM_SWAP; - } - } - - pm_assoc_splat_node_t *assoc_splat = (pm_assoc_splat_node_t *)cur_node; - PM_COMPILE(assoc_splat->value); - - if (len > 1) { - ADD_SEND(ret, &dummy_line_node, id_core_hash_merge_kwd, INT2FIX(2)); - } - - if ((i < len - 1) && !PM_NODE_TYPE_P(keyword_arg->elements.nodes[i + 1], cur_type)) { - ADD_INSN1(ret, &dummy_line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); - PM_SWAP; - } - - cur_hash_size = 0; - break; - } - default: { - rb_bug("Unknown type in keyword argument %s\n", pm_node_type_to_str(PM_NODE_TYPE(cur_node))); - } - } - } + pm_arg_compile_keyword_hash_node((pm_keyword_hash_node_t *)element_node, iseq, ret, src, popped, scope_node, dummy_line_node); break; } From a25c6fd9a00b29fabca5f9013e47574eedc1e5b1 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 16:31:04 -0500 Subject: [PATCH 248/640] [PRISM] Fix test spelling `RescueModifer` -> `RescueModifier` `RescueModifier` was spelled wrong. Not a big deal, but it meant I didn't immediately find the test when I was searching for it while working on implementing `defined?` nodes. --- test/ruby/test_compile_prism.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index f46c491598ee1f..7326035c02451e 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1197,7 +1197,7 @@ def test_RescueNode CODE end - def test_RescueModiferNode + def test_RescueModifierNode assert_prism_eval("1.nil? rescue false") assert_prism_eval("1.nil? rescue 1") assert_prism_eval("raise 'bang' rescue nil") From 75bed8c61ac03368a4f3b6774a15e79af85d3f97 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 10:37:14 -0500 Subject: [PATCH 249/640] [Prism] Implement defined? for PM_CASE_NODE Ruby code: ```ruby defined?(case :a; when :a; 1; else; 2; end) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,43)> 0000 putobject "expression" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,43)> 0000 putobject "expression" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 2 ++ 2 files changed, 3 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 5c153b25e62b0e..2943bd0f01bac5 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2536,6 +2536,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_AND_NODE: case PM_BEGIN_NODE: case PM_BREAK_NODE: + case PM_CASE_NODE: case PM_DEFINED_NODE: case PM_FLOAT_NODE: case PM_HASH_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 7326035c02451e..00b443d7f3c463 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -248,6 +248,8 @@ def self.m1; defined?(return) end assert_prism_eval("defined?([0][0] &&= 1)") assert_prism_eval("defined?([0][0] += 1)") assert_prism_eval("defined?([0][0] ||= 1)") + + assert_prism_eval("defined?(case :a; when :a; 1; else; 2; end)") end def test_GlobalVariableReadNode From 9bcd42c378c0755c9aa606f84405e01c8ed5255f Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 10:38:33 -0500 Subject: [PATCH 250/640] [Prism] Implement defined? for PM_CASE_MATCH_NODE Ruby code: ```ruby defined?(case [1, 2, 3]; in [1, 2, 3]; 4; end) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,43)> 0000 putobject "expression" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,43)> 0000 putobject "expression" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 2943bd0f01bac5..d6be1facd2724f 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2537,6 +2537,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_BEGIN_NODE: case PM_BREAK_NODE: case PM_CASE_NODE: + case PM_CASE_MATCH_NODE: case PM_DEFINED_NODE: case PM_FLOAT_NODE: case PM_HASH_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 00b443d7f3c463..5bb47ce6167102 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -250,6 +250,7 @@ def self.m1; defined?(return) end assert_prism_eval("defined?([0][0] ||= 1)") assert_prism_eval("defined?(case :a; when :a; 1; else; 2; end)") + assert_prism_eval("defined?(case [1, 2, 3]; in [1, 2, 3]; 4; end)") end def test_GlobalVariableReadNode From 30e7dbb78de4d4690b29b996424c7e7f4400b853 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 10:40:57 -0500 Subject: [PATCH 251/640] [Prism] Implement defined? for PM_CLASS_NODE Ruby code: ```ruby defined?(class PrismClassA; end) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,43)> 0000 putobject "expression" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,43)> 0000 putobject "expression" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index d6be1facd2724f..0e65d16d2efaad 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2538,6 +2538,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_BREAK_NODE: case PM_CASE_NODE: case PM_CASE_MATCH_NODE: + case PM_CLASS_NODE: case PM_DEFINED_NODE: case PM_FLOAT_NODE: case PM_HASH_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 5bb47ce6167102..d3ee027ef4e57a 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -251,6 +251,7 @@ def self.m1; defined?(return) end assert_prism_eval("defined?(case :a; when :a; 1; else; 2; end)") assert_prism_eval("defined?(case [1, 2, 3]; in [1, 2, 3]; 4; end)") + assert_prism_eval("defined?(class PrismClassA; end)") end def test_GlobalVariableReadNode From 7460820fec8086d14c820d8e8f8042811105470f Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 10:42:22 -0500 Subject: [PATCH 252/640] [Prism] Implement defined? for PM_DEF_NODE Ruby code: ```ruby defined?(def prism_test_def_node; end) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,43)> 0000 putobject "expression" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,43)> 0000 putobject "expression" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 0e65d16d2efaad..e8eab6ed351963 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2539,6 +2539,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_CASE_NODE: case PM_CASE_MATCH_NODE: case PM_CLASS_NODE: + case PM_DEF_NODE: case PM_DEFINED_NODE: case PM_FLOAT_NODE: case PM_HASH_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index d3ee027ef4e57a..98083c4368529b 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -252,6 +252,7 @@ def self.m1; defined?(return) end assert_prism_eval("defined?(case :a; when :a; 1; else; 2; end)") assert_prism_eval("defined?(case [1, 2, 3]; in [1, 2, 3]; 4; end)") assert_prism_eval("defined?(class PrismClassA; end)") + assert_prism_eval("defined?(def prism_test_def_node; end)") end def test_GlobalVariableReadNode From fb1eed3f7034c9219f83d086011296f8955bcddc Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 10:44:01 -0500 Subject: [PATCH 253/640] [Prism] Implement defined? for PM_FOR_NODE Ruby code: ```ruby defined?(for i in [1,2] do; i; end) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,43)> 0000 putobject "expression" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,43)> 0000 putobject "expression" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index e8eab6ed351963..5fe98a3737cb20 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2542,6 +2542,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_DEF_NODE: case PM_DEFINED_NODE: case PM_FLOAT_NODE: + case PM_FOR_NODE: case PM_HASH_NODE: case PM_IMAGINARY_NODE: case PM_INTEGER_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 98083c4368529b..5b301b6f2668fe 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -253,6 +253,7 @@ def self.m1; defined?(return) end assert_prism_eval("defined?(case [1, 2, 3]; in [1, 2, 3]; 4; end)") assert_prism_eval("defined?(class PrismClassA; end)") assert_prism_eval("defined?(def prism_test_def_node; end)") + assert_prism_eval("defined?(for i in [1,2] do; i; end)") end def test_GlobalVariableReadNode From a2092ef2070091caa42dfaa304ecc5a16dc1694a Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 10:45:48 -0500 Subject: [PATCH 254/640] [Prism] Implement defined? for PM_IF_NODE Ruby code: ```ruby defined?(if true; 1; end) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,43)> 0000 putobject "expression" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,43)> 0000 putobject "expression" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 5fe98a3737cb20..b8e15a99fd2198 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2544,6 +2544,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_FLOAT_NODE: case PM_FOR_NODE: case PM_HASH_NODE: + case PM_IF_NODE: case PM_IMAGINARY_NODE: case PM_INTEGER_NODE: case PM_INTERPOLATED_REGULAR_EXPRESSION_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 5b301b6f2668fe..3f34fa98f812ab 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -254,6 +254,7 @@ def self.m1; defined?(return) end assert_prism_eval("defined?(class PrismClassA; end)") assert_prism_eval("defined?(def prism_test_def_node; end)") assert_prism_eval("defined?(for i in [1,2] do; i; end)") + assert_prism_eval("defined?(if true; 1; end)") end def test_GlobalVariableReadNode From b40fc4f0a7f9aafb1d9cf2079d89f0a00047c47b Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 10:47:50 -0500 Subject: [PATCH 255/640] [Prism] Implement defined? for PM_MATCH_WRITE_NODE Ruby code: ```ruby defined?(/(?bar)/ =~ 'barbar') ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,35)> local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) [ 1] foo@0 0000 putobject "expression" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,35)> local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) [ 1] foo@0 0000 putobject "expression" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index b8e15a99fd2198..0656fb0aa4306a 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2554,6 +2554,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_KEYWORD_HASH_NODE: case PM_LAMBDA_NODE: case PM_MATCH_PREDICATE_NODE: + case PM_MATCH_WRITE_NODE: case PM_NEXT_NODE: case PM_OR_NODE: case PM_RANGE_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 3f34fa98f812ab..aa06f9ac3f00dc 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -255,6 +255,7 @@ def self.m1; defined?(return) end assert_prism_eval("defined?(def prism_test_def_node; end)") assert_prism_eval("defined?(for i in [1,2] do; i; end)") assert_prism_eval("defined?(if true; 1; end)") + assert_prism_eval("defined?(/(?bar)/ =~ 'barbar')") end def test_GlobalVariableReadNode From a9a22b9f2d3200cb55938a0eaf8d2c42ea05c7c9 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 10:49:29 -0500 Subject: [PATCH 256/640] [Prism] Implement defined? for PM_MATCH_REQUIRED_NODE Ruby code: ```ruby defined?(1 => 1) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,16)> 0000 putobject "expression" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,16)> 0000 putobject "expression" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 0656fb0aa4306a..ec3ab32e10f01a 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2554,6 +2554,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_KEYWORD_HASH_NODE: case PM_LAMBDA_NODE: case PM_MATCH_PREDICATE_NODE: + case PM_MATCH_REQUIRED_NODE: case PM_MATCH_WRITE_NODE: case PM_NEXT_NODE: case PM_OR_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index aa06f9ac3f00dc..d90289b90434d6 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -256,6 +256,7 @@ def self.m1; defined?(return) end assert_prism_eval("defined?(for i in [1,2] do; i; end)") assert_prism_eval("defined?(if true; 1; end)") assert_prism_eval("defined?(/(?bar)/ =~ 'barbar')") + assert_prism_eval("defined?(1 => 1)") end def test_GlobalVariableReadNode From 913772a08acb9ebf4ea91762ebcf5ccdb1d9732c Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 10:50:58 -0500 Subject: [PATCH 257/640] [Prism] Implement defined? for PM_MODULE_NODE Ruby code: ```ruby defined?(module M; end) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,16)> 0000 putobject "expression" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,16)> 0000 putobject "expression" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index ec3ab32e10f01a..da093e18619562 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2556,6 +2556,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_MATCH_PREDICATE_NODE: case PM_MATCH_REQUIRED_NODE: case PM_MATCH_WRITE_NODE: + case PM_MODULE_NODE: case PM_NEXT_NODE: case PM_OR_NODE: case PM_RANGE_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index d90289b90434d6..a635683fc3f415 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -257,6 +257,7 @@ def self.m1; defined?(return) end assert_prism_eval("defined?(if true; 1; end)") assert_prism_eval("defined?(/(?bar)/ =~ 'barbar')") assert_prism_eval("defined?(1 => 1)") + assert_prism_eval("defined?(module M; end)") end def test_GlobalVariableReadNode From d2000e0e6c3b7538e7bec51af8d5a128e8acf7ab Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 11:00:08 -0500 Subject: [PATCH 258/640] [Prism] Implement defined? for PM_RATIONAL_NODE Ruby code: ```ruby defined?(1.2r) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,16)> 0000 putobject "expression" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,16)> 0000 putobject "expression" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index da093e18619562..4d1d0d851f857d 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2560,6 +2560,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_NEXT_NODE: case PM_OR_NODE: case PM_RANGE_NODE: + case PM_RATIONAL_NODE: case PM_REDO_NODE: case PM_REGULAR_EXPRESSION_NODE: case PM_RETRY_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index a635683fc3f415..63e1a311994285 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -258,6 +258,7 @@ def self.m1; defined?(return) end assert_prism_eval("defined?(/(?bar)/ =~ 'barbar')") assert_prism_eval("defined?(1 => 1)") assert_prism_eval("defined?(module M; end)") + assert_prism_eval("defined?(1.2r)") end def test_GlobalVariableReadNode From b5d3d61130437de1434cf1a98048bf9d40e7908b Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 11:03:28 -0500 Subject: [PATCH 259/640] [Prism] Implement defined? for PM_SINGLETON_CLASS_NODE Ruby code: ```ruby defined?(class << self; end) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,16)> 0000 putobject "expression" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,16)> 0000 putobject "expression" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 4d1d0d851f857d..70faae0e0fafe4 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2565,6 +2565,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_REGULAR_EXPRESSION_NODE: case PM_RETRY_NODE: case PM_RETURN_NODE: + case PM_SINGLETON_CLASS_NODE: case PM_SOURCE_ENCODING_NODE: case PM_SOURCE_FILE_NODE: case PM_SOURCE_LINE_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 63e1a311994285..69729385733f72 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -259,6 +259,7 @@ def self.m1; defined?(return) end assert_prism_eval("defined?(1 => 1)") assert_prism_eval("defined?(module M; end)") assert_prism_eval("defined?(1.2r)") + assert_prism_eval("defined?(class << self; end)") end def test_GlobalVariableReadNode From 24d02cd4859ea3cee3b9dfaca196c7b34c5686a4 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 11:36:45 -0500 Subject: [PATCH 260/640] [Prism] Implement defined? for PM_WHILE_NODE Ruby code: ```ruby defined?(while a != 1; end) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,16)> 0000 putobject "expression" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,16)> 0000 putobject "expression" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 70faae0e0fafe4..729e82a24a6e75 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2571,6 +2571,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_SOURCE_LINE_NODE: case PM_STRING_NODE: case PM_SYMBOL_NODE: + case PM_WHILE_NODE: case PM_X_STRING_NODE: dtype = DEFINED_EXPR; break; diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 69729385733f72..7bb94ecb8b4ca2 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -260,6 +260,7 @@ def self.m1; defined?(return) end assert_prism_eval("defined?(module M; end)") assert_prism_eval("defined?(1.2r)") assert_prism_eval("defined?(class << self; end)") + assert_prism_eval("defined?(while a != 1; end)") end def test_GlobalVariableReadNode From 555af5e599772033d3073afd6b91c28dc53b3f71 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 11:38:02 -0500 Subject: [PATCH 261/640] [Prism] Implement defined? for PM_UNTIL_NODE Ruby code: ```ruby defined?(until a == 1; end) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,16)> 0000 putobject "expression" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,16)> 0000 putobject "expression" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 729e82a24a6e75..ffabda71750118 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2571,6 +2571,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_SOURCE_LINE_NODE: case PM_STRING_NODE: case PM_SYMBOL_NODE: + case PM_UNTIL_NODE: case PM_WHILE_NODE: case PM_X_STRING_NODE: dtype = DEFINED_EXPR; diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 7bb94ecb8b4ca2..1f9ce84bfa1f74 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -261,6 +261,7 @@ def self.m1; defined?(return) end assert_prism_eval("defined?(1.2r)") assert_prism_eval("defined?(class << self; end)") assert_prism_eval("defined?(while a != 1; end)") + assert_prism_eval("defined?(until a == 1; end)") end def test_GlobalVariableReadNode From db9f5fc91620b799c8829d0ca69bf72564a16e14 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Wed, 17 Jan 2024 11:40:01 -0500 Subject: [PATCH 262/640] [Prism] Implement defined? for PM_UNLESS_NODE Ruby code: ```ruby defined?(unless true; 1; end) ``` Instructions: ``` "********* Ruby *************" == disasm: #@:1 (1,0)-(59,16)> 0000 putobject "expression" ( 59)[Li] 0002 leave "********* PRISM *************" == disasm: #@:58 (58,0)-(58,16)> 0000 putobject "expression" ( 58)[Li] 0002 leave ``` Related: ruby/prism#2188 --- prism_compile.c | 1 + test/ruby/test_compile_prism.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index ffabda71750118..876278166be5a4 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2571,6 +2571,7 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co case PM_SOURCE_LINE_NODE: case PM_STRING_NODE: case PM_SYMBOL_NODE: + case PM_UNLESS_NODE: case PM_UNTIL_NODE: case PM_WHILE_NODE: case PM_X_STRING_NODE: diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 1f9ce84bfa1f74..f1274fccf5d9d6 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -262,6 +262,7 @@ def self.m1; defined?(return) end assert_prism_eval("defined?(class << self; end)") assert_prism_eval("defined?(while a != 1; end)") assert_prism_eval("defined?(until a == 1; end)") + assert_prism_eval("defined?(unless true; 1; end)") end def test_GlobalVariableReadNode From 2b0766113b35baf188bcb40e7da36a27423a2149 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 17 Jan 2024 09:59:48 +0900 Subject: [PATCH 263/640] Extract bigdecimal as bundled gems --- ext/bigdecimal/bigdecimal.c | 7738 --------------------- ext/bigdecimal/bigdecimal.gemspec | 54 - ext/bigdecimal/bigdecimal.h | 313 - ext/bigdecimal/bits.h | 141 - ext/bigdecimal/depend | 327 - ext/bigdecimal/extconf.rb | 62 - ext/bigdecimal/feature.h | 68 - ext/bigdecimal/lib/bigdecimal.rb | 5 - ext/bigdecimal/lib/bigdecimal/jacobian.rb | 90 - ext/bigdecimal/lib/bigdecimal/ludcmp.rb | 89 - ext/bigdecimal/lib/bigdecimal/math.rb | 232 - ext/bigdecimal/lib/bigdecimal/newton.rb | 80 - ext/bigdecimal/lib/bigdecimal/util.rb | 185 - ext/bigdecimal/missing.c | 27 - ext/bigdecimal/missing.h | 196 - ext/bigdecimal/missing/dtoa.c | 3462 --------- ext/bigdecimal/sample/linear.rb | 74 - ext/bigdecimal/sample/nlsolve.rb | 40 - ext/bigdecimal/sample/pi.rb | 21 - ext/bigdecimal/static_assert.h | 54 - gems/bundled_gems | 1 + test/bigdecimal/helper.rb | 39 - test/bigdecimal/test_bigdecimal.rb | 2310 ------ test/bigdecimal/test_bigdecimal_util.rb | 141 - test/bigdecimal/test_bigmath.rb | 81 - test/bigdecimal/test_ractor.rb | 23 - 26 files changed, 1 insertion(+), 15852 deletions(-) delete mode 100644 ext/bigdecimal/bigdecimal.c delete mode 100644 ext/bigdecimal/bigdecimal.gemspec delete mode 100644 ext/bigdecimal/bigdecimal.h delete mode 100644 ext/bigdecimal/bits.h delete mode 100644 ext/bigdecimal/depend delete mode 100644 ext/bigdecimal/extconf.rb delete mode 100644 ext/bigdecimal/feature.h delete mode 100644 ext/bigdecimal/lib/bigdecimal.rb delete mode 100644 ext/bigdecimal/lib/bigdecimal/jacobian.rb delete mode 100644 ext/bigdecimal/lib/bigdecimal/ludcmp.rb delete mode 100644 ext/bigdecimal/lib/bigdecimal/math.rb delete mode 100644 ext/bigdecimal/lib/bigdecimal/newton.rb delete mode 100644 ext/bigdecimal/lib/bigdecimal/util.rb delete mode 100644 ext/bigdecimal/missing.c delete mode 100644 ext/bigdecimal/missing.h delete mode 100644 ext/bigdecimal/missing/dtoa.c delete mode 100644 ext/bigdecimal/sample/linear.rb delete mode 100644 ext/bigdecimal/sample/nlsolve.rb delete mode 100644 ext/bigdecimal/sample/pi.rb delete mode 100644 ext/bigdecimal/static_assert.h delete mode 100644 test/bigdecimal/helper.rb delete mode 100644 test/bigdecimal/test_bigdecimal.rb delete mode 100644 test/bigdecimal/test_bigdecimal_util.rb delete mode 100644 test/bigdecimal/test_bigmath.rb delete mode 100644 test/bigdecimal/test_ractor.rb diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c deleted file mode 100644 index cb8874d31a1a1f..00000000000000 --- a/ext/bigdecimal/bigdecimal.c +++ /dev/null @@ -1,7738 +0,0 @@ -/* - * - * Ruby BigDecimal(Variable decimal precision) extension library. - * - * Copyright(C) 2002 by Shigeo Kobayashi(shigeo@tinyforest.gr.jp) - * - */ - -/* #define BIGDECIMAL_DEBUG 1 */ - -#include "bigdecimal.h" -#include "ruby/util.h" - -#ifndef BIGDECIMAL_DEBUG -# undef NDEBUG -# define NDEBUG -#endif -#include - -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_IEEEFP_H -#include -#endif - -#include "bits.h" -#include "static_assert.h" - -#define BIGDECIMAL_VERSION "3.1.5" - -/* #define ENABLE_NUMERIC_STRING */ - -#define SIGNED_VALUE_MAX INTPTR_MAX -#define SIGNED_VALUE_MIN INTPTR_MIN -#define MUL_OVERFLOW_SIGNED_VALUE_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, SIGNED_VALUE_MIN, SIGNED_VALUE_MAX) - -VALUE rb_cBigDecimal; -VALUE rb_mBigMath; - -static ID id_BigDecimal_exception_mode; -static ID id_BigDecimal_rounding_mode; -static ID id_BigDecimal_precision_limit; - -static ID id_up; -static ID id_down; -static ID id_truncate; -static ID id_half_up; -static ID id_default; -static ID id_half_down; -static ID id_half_even; -static ID id_banker; -static ID id_ceiling; -static ID id_ceil; -static ID id_floor; -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 -#else -#define ENTER(n) volatile VALUE RB_UNUSED_VAR(vStack[n]);int iStack=0 -#endif -#define PUSH(x) (vStack[iStack++] = (VALUE)(x)) -#define SAVE(p) PUSH((p)->obj) -#define GUARD_OBJ(p,y) ((p)=(y), SAVE(p)) - -#define BASE_FIG BIGDECIMAL_COMPONENT_FIGURES -#define BASE BIGDECIMAL_BASE - -#define HALF_BASE (BASE/2) -#define BASE1 (BASE/10) - -#define LOG10_2 0.3010299956639812 - -#ifndef RRATIONAL_ZERO_P -# define RRATIONAL_ZERO_P(x) (FIXNUM_P(rb_rational_num(x)) && \ - FIX2LONG(rb_rational_num(x)) == 0) -#endif - -#ifndef RRATIONAL_NEGATIVE_P -# define RRATIONAL_NEGATIVE_P(x) RTEST(rb_funcall((x), '<', 1, INT2FIX(0))) -#endif - -#ifndef DECIMAL_SIZE_OF_BITS -#define DECIMAL_SIZE_OF_BITS(n) (((n) * 3010 + 9998) / 9999) -/* an approximation of ceil(n * log10(2)), upto 65536 at least */ -#endif - -#ifdef PRIsVALUE -# define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj) -# define RB_OBJ_STRING(obj) (obj) -#else -# define PRIsVALUE "s" -# define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj) -# define RB_OBJ_STRING(obj) StringValueCStr(obj) -#endif - -#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) - -/* - * VP routines used in BigDecimal part - */ -static unsigned short VpGetException(void); -static void VpSetException(unsigned short f); -static void VpCheckException(Real *p, bool always); -static VALUE VpCheckGetValue(Real *p); -static void VpInternalRound(Real *c, size_t ixDigit, DECDIG vPrev, DECDIG v); -static int VpLimitRound(Real *c, size_t ixDigit); -static Real *VpCopy(Real *pv, Real const* const x); -static int VPrint(FILE *fp,const char *cntl_chr,Real *a); - -/* - * **** BigDecimal part **** - */ - -static VALUE BigDecimal_nan(void); -static VALUE BigDecimal_positive_infinity(void); -static VALUE BigDecimal_negative_infinity(void); -static VALUE BigDecimal_positive_zero(void); -static VALUE BigDecimal_negative_zero(void); - -static void -BigDecimal_delete(void *pv) -{ - rbd_free_struct(pv); -} - -static size_t -BigDecimal_memsize(const void *ptr) -{ - const Real *pv = ptr; - return (sizeof(*pv) + pv->MaxPrec * sizeof(DECDIG)); -} - -#ifndef HAVE_RB_EXT_RACTOR_SAFE -# undef RUBY_TYPED_FROZEN_SHAREABLE -# define RUBY_TYPED_FROZEN_SHAREABLE 0 -#endif - -static const rb_data_type_t BigDecimal_data_type = { - "BigDecimal", - { 0, BigDecimal_delete, BigDecimal_memsize, }, -#ifdef RUBY_TYPED_FREE_IMMEDIATELY - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE | RUBY_TYPED_WB_PROTECTED -#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) -{ - return rb_typeddata_is_kind_of(v, &BigDecimal_data_type); -} - -NORETURN(static void cannot_be_coerced_into_BigDecimal(VALUE, VALUE)); - -static void -cannot_be_coerced_into_BigDecimal(VALUE exc_class, VALUE v) -{ - VALUE str; - - if (rb_special_const_p(v)) { - str = rb_inspect(v); - } - else { - str = rb_class_name(rb_obj_class(v)); - } - - str = rb_str_cat2(rb_str_dup(str), " can't be coerced into BigDecimal"); - rb_exc_raise(rb_exc_new3(exc_class, str)); -} - -static inline VALUE BigDecimal_div2(VALUE, VALUE, VALUE); -static VALUE rb_inum_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception); -static VALUE rb_float_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception); -static VALUE rb_rational_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception); -static VALUE rb_cstr_convert_to_BigDecimal(const char *c_str, size_t digs, int raise_exception); -static VALUE rb_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception); - -static Real* -GetVpValueWithPrec(VALUE v, long prec, int must) -{ - const size_t digs = prec < 0 ? SIZE_MAX : (size_t)prec; - - switch(TYPE(v)) { - case T_FLOAT: - v = rb_float_convert_to_BigDecimal(v, digs, must); - break; - - case T_RATIONAL: - v = rb_rational_convert_to_BigDecimal(v, digs, must); - break; - - case T_DATA: - if (!is_kind_of_BigDecimal(v)) { - goto SomeOneMayDoIt; - } - break; - - case T_FIXNUM: { - char szD[128]; - snprintf(szD, 128, "%ld", FIX2LONG(v)); - v = rb_cstr_convert_to_BigDecimal(szD, VpBaseFig() * 2 + 1, must); - break; - } - -#ifdef ENABLE_NUMERIC_STRING - case T_STRING: { - const char *c_str = StringValueCStr(v); - v = rb_cstr_convert_to_BigDecimal(c_str, RSTRING_LEN(v) + VpBaseFig() + 1, must); - break; - } -#endif /* ENABLE_NUMERIC_STRING */ - - case T_BIGNUM: { - VALUE bg = rb_big2str(v, 10); - v = rb_cstr_convert_to_BigDecimal(RSTRING_PTR(bg), RSTRING_LEN(bg) + VpBaseFig() + 1, must); - RB_GC_GUARD(bg); - break; - } - - default: - goto SomeOneMayDoIt; - } - - Real *vp; - TypedData_Get_Struct(v, Real, &BigDecimal_data_type, vp); - return vp; - -SomeOneMayDoIt: - if (must) { - cannot_be_coerced_into_BigDecimal(rb_eTypeError, v); - } - return NULL; /* NULL means to coerce */ -} - -static inline Real* -GetVpValue(VALUE v, int must) -{ - return GetVpValueWithPrec(v, -1, must); -} - -/* call-seq: - * BigDecimal.double_fig -> integer - * - * Returns the number of digits a Float object is allowed to have; - * the result is system-dependent: - * - * BigDecimal.double_fig # => 16 - * - */ -static inline VALUE -BigDecimal_double_fig(VALUE self) -{ - return INT2FIX(VpDblFig()); -} - -/* call-seq: - * precs -> array - * - * Returns an Array of two Integer values that represent platform-dependent - * internal storage properties. - * - * This method is deprecated and will be removed in the future. - * Instead, use BigDecimal#n_significant_digits for obtaining the number of - * significant digits in scientific notation, and BigDecimal#precision for - * obtaining the number of digits in decimal notation. - * - */ - -static VALUE -BigDecimal_prec(VALUE self) -{ - ENTER(1); - Real *p; - VALUE obj; - - rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, - "BigDecimal#precs is deprecated and will be removed in the future; " - "use BigDecimal#precision instead."); - - GUARD_OBJ(p, GetVpValue(self, 1)); - obj = rb_assoc_new(SIZET2NUM(p->Prec*VpBaseFig()), - SIZET2NUM(p->MaxPrec*VpBaseFig())); - return obj; -} - -static void -BigDecimal_count_precision_and_scale(VALUE self, ssize_t *out_precision, ssize_t *out_scale) -{ - ENTER(1); - - if (out_precision == NULL && out_scale == NULL) - return; - - Real *p; - GUARD_OBJ(p, GetVpValue(self, 1)); - if (VpIsZero(p) || !VpIsDef(p)) { - zero: - if (out_precision) *out_precision = 0; - if (out_scale) *out_scale = 0; - return; - } - - DECDIG x; - - ssize_t n = p->Prec; /* The length of frac without zeros. */ - while (n > 0 && p->frac[n-1] == 0) --n; - if (n == 0) goto zero; - - int nlz = BASE_FIG; - for (x = p->frac[0]; x > 0; x /= 10) --nlz; - - int ntz = 0; - for (x = p->frac[n-1]; x > 0 && x % 10 == 0; x /= 10) ++ntz; - - /* - * Calculate the precision and the scale - * ------------------------------------- - * - * The most significant digit is frac[0], and the least significant digit - * is frac[Prec-1]. When the exponent is zero, the decimal point is - * located just before frac[0]. - * - * When the exponent is negative, the decimal point moves to leftward. - * In this case, the precision can be calculated by - * - * precision = BASE_FIG * (-exponent + n) - ntz, - * - * and the scale is the same as precision. - * - * 0 . 0000 0000 | frac[0] ... frac[n-1] | - * |<----------| exponent == -2 | - * |---------------------------------->| precision - * |---------------------------------->| scale - * - * - * Conversely, when the exponent is positive, the decimal point moves to - * rightward. In this case, the scale equals to - * - * BASE_FIG * (n - exponent) - ntz. - * - * the precision equals to - * - * scale + BASE_FIG * exponent - nlz. - * - * | frac[0] frac[1] . frac[2] ... frac[n-1] | - * |---------------->| exponent == 2 | - * | |---------------------->| scale - * |---------------------------------------->| precision - */ - - ssize_t ex = p->exponent; - - /* Count the number of decimal digits before frac[1]. */ - ssize_t n_digits_head = BASE_FIG; - if (ex < 0) { - n_digits_head += (-ex) * BASE_FIG; /* The number of leading zeros before frac[0]. */ - ex = 0; - } - else if (ex > 0) { - /* Count the number of decimal digits without the leading zeros in - * the most significant digit in the integral part. - */ - n_digits_head -= nlz; /* Make the number of digits */ - } - - if (out_precision) { - ssize_t precision = n_digits_head; - - /* Count the number of decimal digits after frac[0]. */ - if (ex > (ssize_t)n) { - /* In this case the number is an integer with some trailing zeros. */ - precision += (ex - 1) * BASE_FIG; - } - else if (n > 0) { - precision += (n - 1) * BASE_FIG; - - if (ex < (ssize_t)n) { - precision -= ntz; - } - } - - *out_precision = precision; - } - - if (out_scale) { - ssize_t scale = 0; - - if (p->exponent < 0) { - scale = n_digits_head + (n - 1) * BASE_FIG - ntz; - } - else if (n > p->exponent) { - scale = (n - p->exponent) * BASE_FIG - ntz; - } - - *out_scale = scale; - } -} - -/* - * call-seq: - * precision -> integer - * - * Returns the number of decimal digits in +self+: - * - * BigDecimal("0").precision # => 0 - * BigDecimal("1").precision # => 1 - * BigDecimal("1.1").precision # => 2 - * BigDecimal("3.1415").precision # => 5 - * BigDecimal("-1e20").precision # => 21 - * BigDecimal("1e-20").precision # => 20 - * BigDecimal("Infinity").precision # => 0 - * BigDecimal("-Infinity").precision # => 0 - * BigDecimal("NaN").precision # => 0 - * - */ -static VALUE -BigDecimal_precision(VALUE self) -{ - ssize_t precision; - BigDecimal_count_precision_and_scale(self, &precision, NULL); - return SSIZET2NUM(precision); -} - -/* - * call-seq: - * scale -> integer - * - * Returns the number of decimal digits following the decimal digits in +self+. - * - * BigDecimal("0").scale # => 0 - * BigDecimal("1").scale # => 0 - * BigDecimal("1.1").scale # => 1 - * BigDecimal("3.1415").scale # => 4 - * BigDecimal("-1e20").precision # => 0 - * BigDecimal("1e-20").precision # => 20 - * BigDecimal("Infinity").scale # => 0 - * BigDecimal("-Infinity").scale # => 0 - * BigDecimal("NaN").scale # => 0 - */ -static VALUE -BigDecimal_scale(VALUE self) -{ - ssize_t scale; - BigDecimal_count_precision_and_scale(self, NULL, &scale); - return SSIZET2NUM(scale); -} - -/* - * call-seq: - * precision_scale -> [integer, integer] - * - * Returns a 2-length array; the first item is the result of - * BigDecimal#precision and the second one is of BigDecimal#scale. - * - * See BigDecimal#precision. - * See BigDecimal#scale. - */ -static VALUE -BigDecimal_precision_scale(VALUE self) -{ - ssize_t precision, scale; - BigDecimal_count_precision_and_scale(self, &precision, &scale); - return rb_assoc_new(SSIZET2NUM(precision), SSIZET2NUM(scale)); -} - -/* - * call-seq: - * n_significant_digits -> integer - * - * Returns the number of decimal significant digits in +self+. - * - * BigDecimal("0").n_significant_digits # => 0 - * BigDecimal("1").n_significant_digits # => 1 - * BigDecimal("1.1").n_significant_digits # => 2 - * BigDecimal("3.1415").n_significant_digits # => 5 - * BigDecimal("-1e20").n_significant_digits # => 1 - * BigDecimal("1e-20").n_significant_digits # => 1 - * BigDecimal("Infinity").n_significant_digits # => 0 - * BigDecimal("-Infinity").n_significant_digits # => 0 - * BigDecimal("NaN").n_significant_digits # => 0 - */ -static VALUE -BigDecimal_n_significant_digits(VALUE self) -{ - ENTER(1); - - Real *p; - GUARD_OBJ(p, GetVpValue(self, 1)); - if (VpIsZero(p) || !VpIsDef(p)) { - return INT2FIX(0); - } - - ssize_t n = p->Prec; /* The length of frac without trailing zeros. */ - for (n = p->Prec; n > 0 && p->frac[n-1] == 0; --n); - if (n == 0) return INT2FIX(0); - - DECDIG x; - int nlz = BASE_FIG; - for (x = p->frac[0]; x > 0; x /= 10) --nlz; - - int ntz = 0; - for (x = p->frac[n-1]; x > 0 && x % 10 == 0; x /= 10) ++ntz; - - ssize_t n_significant_digits = BASE_FIG*n - nlz - ntz; - return SSIZET2NUM(n_significant_digits); -} - -/* - * call-seq: - * hash -> integer - * - * Returns the integer hash value for +self+. - * - * Two instances of \BigDecimal have the same hash value if and only if - * they have equal: - * - * - Sign. - * - Fractional part. - * - Exponent. - * - */ -static VALUE -BigDecimal_hash(VALUE self) -{ - ENTER(1); - Real *p; - st_index_t hash; - - GUARD_OBJ(p, GetVpValue(self, 1)); - hash = (st_index_t)p->sign; - /* hash!=2: the case for 0(1),NaN(0) or +-Infinity(3) is sign itself */ - if(hash == 2 || hash == (st_index_t)-2) { - hash ^= rb_memhash(p->frac, sizeof(DECDIG)*p->Prec); - hash += p->exponent; - } - return ST2FIX(hash); -} - -/* - * call-seq: - * _dump -> string - * - * Returns a string representing the marshalling of +self+. - * See module Marshal. - * - * inf = BigDecimal('Infinity') # => Infinity - * dumped = inf._dump # => "9:Infinity" - * BigDecimal._load(dumped) # => Infinity - * - */ -static VALUE -BigDecimal_dump(int argc, VALUE *argv, VALUE self) -{ - ENTER(5); - Real *vp; - 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); - 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; -} - -/* - * Internal method used to provide marshalling support. See the Marshal module. - */ -static VALUE -BigDecimal_load(VALUE self, VALUE str) -{ - ENTER(2); - Real *pv; - unsigned char *pch; - unsigned char ch; - unsigned long m=0; - - pch = (unsigned char *)StringValueCStr(str); - /* First get max prec */ - while((*pch) != (unsigned char)'\0' && (ch = *pch++) != (unsigned char)':') { - if(!ISDIGIT(ch)) { - rb_raise(rb_eTypeError, "load failed: invalid character in the marshaled string"); - } - m = m*10 + (unsigned long)(ch-'0'); - } - if (m > VpBaseFig()) m -= VpBaseFig(); - GUARD_OBJ(pv, VpNewRbClass(m, (char *)pch, self, true, true)); - m /= VpBaseFig(); - if (m && pv->MaxPrec > m) { - pv->MaxPrec = m+1; - } - return VpCheckGetValue(pv); -} - -static unsigned short -check_rounding_mode_option(VALUE const opts) -{ - VALUE mode; - char const *s; - long l; - - assert(RB_TYPE_P(opts, T_HASH)); - - if (NIL_P(opts)) - goto no_opt; - - mode = rb_hash_lookup2(opts, ID2SYM(id_half), Qundef); - if (mode == Qundef || NIL_P(mode)) - 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; - } - s = RSTRING_PTR(mode); - l = RSTRING_LEN(mode); - switch (l) { - case 2: - if (strncasecmp(s, "up", 2) == 0) - return VP_ROUND_HALF_UP; - break; - case 4: - if (strncasecmp(s, "even", 4) == 0) - return VP_ROUND_HALF_EVEN; - else if (strncasecmp(s, "down", 4) == 0) - return VP_ROUND_HALF_DOWN; - break; - default: - break; - } - - invalid: - rb_raise(rb_eArgError, "invalid rounding mode (%"PRIsVALUE")", mode); - - no_opt: - return VpGetRoundMode(); -} - -static unsigned short -check_rounding_mode(VALUE const v) -{ - unsigned short sw; - ID id; - 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); - } - else { - sw = NUM2USHORT(v); - if (!VpIsRoundMode(sw)) { - rb_raise(rb_eArgError, "invalid rounding mode (%"PRIsVALUE")", v); - } - return sw; - } -} - -/* call-seq: - * BigDecimal.mode(mode, setting = nil) -> integer - * - * Returns an integer representing the mode settings - * for exception handling and rounding. - * - * These modes control exception handling: - * - * - \BigDecimal::EXCEPTION_NaN. - * - \BigDecimal::EXCEPTION_INFINITY. - * - \BigDecimal::EXCEPTION_UNDERFLOW. - * - \BigDecimal::EXCEPTION_OVERFLOW. - * - \BigDecimal::EXCEPTION_ZERODIVIDE. - * - \BigDecimal::EXCEPTION_ALL. - * - * Values for +setting+ for exception handling: - * - * - +true+: sets the given +mode+ to +true+. - * - +false+: sets the given +mode+ to +false+. - * - +nil+: does not modify the mode settings. - * - * You can use method BigDecimal.save_exception_mode - * to temporarily change, and then automatically restore, exception modes. - * - * For clarity, some examples below begin by setting all - * exception modes to +false+. - * - * This mode controls the way rounding is to be performed: - * - * - \BigDecimal::ROUND_MODE - * - * You can use method BigDecimal.save_rounding_mode - * to temporarily change, and then automatically restore, the rounding mode. - * - * NaNs - * - * Mode \BigDecimal::EXCEPTION_NaN controls behavior - * when a \BigDecimal NaN is created. - * - * Settings: - * - * - +false+ (default): Returns BigDecimal('NaN'). - * - +true+: Raises FloatDomainError. - * - * Examples: - * - * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0 - * BigDecimal('NaN') # => NaN - * BigDecimal.mode(BigDecimal::EXCEPTION_NaN, true) # => 2 - * BigDecimal('NaN') # Raises FloatDomainError - * - * Infinities - * - * Mode \BigDecimal::EXCEPTION_INFINITY controls behavior - * when a \BigDecimal Infinity or -Infinity is created. - * Settings: - * - * - +false+ (default): Returns BigDecimal('Infinity') - * or BigDecimal('-Infinity'). - * - +true+: Raises FloatDomainError. - * - * Examples: - * - * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0 - * BigDecimal('Infinity') # => Infinity - * BigDecimal('-Infinity') # => -Infinity - * BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, true) # => 1 - * BigDecimal('Infinity') # Raises FloatDomainError - * BigDecimal('-Infinity') # Raises FloatDomainError - * - * Underflow - * - * Mode \BigDecimal::EXCEPTION_UNDERFLOW controls behavior - * when a \BigDecimal underflow occurs. - * Settings: - * - * - +false+ (default): Returns BigDecimal('0') - * or BigDecimal('-Infinity'). - * - +true+: Raises FloatDomainError. - * - * Examples: - * - * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0 - * def flow_under - * x = BigDecimal('0.1') - * 100.times { x *= x } - * end - * flow_under # => 100 - * BigDecimal.mode(BigDecimal::EXCEPTION_UNDERFLOW, true) # => 4 - * flow_under # Raises FloatDomainError - * - * Overflow - * - * Mode \BigDecimal::EXCEPTION_OVERFLOW controls behavior - * when a \BigDecimal overflow occurs. - * Settings: - * - * - +false+ (default): Returns BigDecimal('Infinity') - * or BigDecimal('-Infinity'). - * - +true+: Raises FloatDomainError. - * - * Examples: - * - * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0 - * def flow_over - * x = BigDecimal('10') - * 100.times { x *= x } - * end - * flow_over # => 100 - * BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, true) # => 1 - * flow_over # Raises FloatDomainError - * - * Zero Division - * - * Mode \BigDecimal::EXCEPTION_ZERODIVIDE controls behavior - * when a zero-division occurs. - * Settings: - * - * - +false+ (default): Returns BigDecimal('Infinity') - * or BigDecimal('-Infinity'). - * - +true+: Raises FloatDomainError. - * - * Examples: - * - * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0 - * one = BigDecimal('1') - * zero = BigDecimal('0') - * one / zero # => Infinity - * BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, true) # => 16 - * one / zero # Raises FloatDomainError - * - * All Exceptions - * - * Mode \BigDecimal::EXCEPTION_ALL controls all of the above: - * - * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0 - * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, true) # => 23 - * - * Rounding - * - * Mode \BigDecimal::ROUND_MODE controls the way rounding is to be performed; - * its +setting+ values are: - * - * - +ROUND_UP+: Round away from zero. - * Aliased as +:up+. - * - +ROUND_DOWN+: Round toward zero. - * Aliased as +:down+ and +:truncate+. - * - +ROUND_HALF_UP+: Round toward the nearest neighbor; - * if the neighbors are equidistant, round away from zero. - * Aliased as +:half_up+ and +:default+. - * - +ROUND_HALF_DOWN+: Round toward the nearest neighbor; - * if the neighbors are equidistant, round toward zero. - * Aliased as +:half_down+. - * - +ROUND_HALF_EVEN+ (Banker's rounding): Round toward the nearest neighbor; - * if the neighbors are equidistant, round toward the even neighbor. - * Aliased as +:half_even+ and +:banker+. - * - +ROUND_CEILING+: Round toward positive infinity. - * Aliased as +:ceiling+ and +:ceil+. - * - +ROUND_FLOOR+: Round toward negative infinity. - * Aliased as +:floor:+. - * - */ -static VALUE -BigDecimal_mode(int argc, VALUE *argv, VALUE self) -{ - VALUE which; - VALUE val; - unsigned long f,fo; - - rb_scan_args(argc, argv, "11", &which, &val); - f = (unsigned long)NUM2INT(which); - - if (f & VP_EXCEPTION_ALL) { - /* Exception mode setting */ - fo = VpGetException(); - if (val == Qnil) return INT2FIX(fo); - if (val != Qfalse && val!=Qtrue) { - rb_raise(rb_eArgError, "second argument must be true or false"); - return Qnil; /* Not reached */ - } - if (f & VP_EXCEPTION_INFINITY) { - VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_INFINITY) : - (fo & (~VP_EXCEPTION_INFINITY)))); - } - fo = VpGetException(); - if (f & VP_EXCEPTION_NaN) { - VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_NaN) : - (fo & (~VP_EXCEPTION_NaN)))); - } - fo = VpGetException(); - if (f & VP_EXCEPTION_UNDERFLOW) { - VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_UNDERFLOW) : - (fo & (~VP_EXCEPTION_UNDERFLOW)))); - } - fo = VpGetException(); - if(f & VP_EXCEPTION_ZERODIVIDE) { - VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_ZERODIVIDE) : - (fo & (~VP_EXCEPTION_ZERODIVIDE)))); - } - fo = VpGetException(); - return INT2FIX(fo); - } - if (VP_ROUND_MODE == f) { - /* Rounding mode setting */ - unsigned short sw; - fo = VpGetRoundMode(); - if (NIL_P(val)) return INT2FIX(fo); - sw = check_rounding_mode(val); - fo = VpSetRoundMode(sw); - return INT2FIX(fo); - } - rb_raise(rb_eTypeError, "first argument for BigDecimal.mode invalid"); - return Qnil; -} - -static size_t -GetAddSubPrec(Real *a, Real *b) -{ - size_t mxs; - size_t mx = a->Prec; - SIGNED_VALUE d; - - if (!VpIsDef(a) || !VpIsDef(b)) return (size_t)-1L; - if (mx < b->Prec) mx = b->Prec; - if (a->exponent != b->exponent) { - mxs = mx; - d = a->exponent - b->exponent; - if (d < 0) d = -d; - mx = mx + (size_t)d; - if (mx < mxs) { - return VpException(VP_EXCEPTION_INFINITY, "Exponent overflow", 0); - } - } - return mx; -} - -static inline SIGNED_VALUE -check_int_precision(VALUE v) -{ - SIGNED_VALUE n; -#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"); - } - return n; -} - -static VALUE -BigDecimal_wrap_struct(VALUE obj, Real *vp) -{ - assert(is_kind_of_BigDecimal(obj)); - assert(vp != NULL); - - if (vp->obj == obj && RTYPEDDATA_DATA(obj) == vp) - return obj; - - assert(RTYPEDDATA_DATA(obj) == NULL); - assert(vp->obj == 0); - - RTYPEDDATA_DATA(obj) = vp; - vp->obj = obj; - RB_OBJ_FREEZE(obj); - return obj; -} - -VP_EXPORT Real * -VpNewRbClass(size_t mx, const char *str, VALUE klass, bool strict_p, bool raise_exception) -{ - VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0); - Real *pv = VpAlloc(mx, str, strict_p, raise_exception); - if (!pv) - return NULL; - BigDecimal_wrap_struct(obj, pv); - return pv; -} - -VP_EXPORT Real * -VpCreateRbObject(size_t mx, const char *str, bool raise_exception) -{ - return VpNewRbClass(mx, str, rb_cBigDecimal, true, raise_exception); -} - -static Real * -VpCopy(Real *pv, Real const* const x) -{ - assert(x != NULL); - - pv = rbd_reallocate_struct(pv, x->MaxPrec); - pv->MaxPrec = x->MaxPrec; - pv->Prec = x->Prec; - pv->exponent = x->exponent; - pv->sign = x->sign; - pv->flag = x->flag; - MEMCPY(pv->frac, x->frac, DECDIG, pv->MaxPrec); - - return pv; -} - -/* Returns True if the value is Not a Number. */ -static VALUE -BigDecimal_IsNaN(VALUE self) -{ - Real *p = GetVpValue(self, 1); - if (VpIsNaN(p)) return Qtrue; - return Qfalse; -} - -/* Returns nil, -1, or +1 depending on whether the value is finite, - * -Infinity, or +Infinity. - */ -static VALUE -BigDecimal_IsInfinite(VALUE self) -{ - Real *p = GetVpValue(self, 1); - if (VpIsPosInf(p)) return INT2FIX(1); - if (VpIsNegInf(p)) return INT2FIX(-1); - return Qnil; -} - -/* Returns True if the value is finite (not NaN or infinite). */ -static VALUE -BigDecimal_IsFinite(VALUE self) -{ - Real *p = GetVpValue(self, 1); - if (VpIsNaN(p)) return Qfalse; - if (VpIsInf(p)) return Qfalse; - return Qtrue; -} - -static void -BigDecimal_check_num(Real *p) -{ - VpCheckException(p, true); -} - -static VALUE BigDecimal_split(VALUE self); - -/* Returns the value as an Integer. - * - * If the BigDecimal is infinity or NaN, raises FloatDomainError. - */ -static VALUE -BigDecimal_to_i(VALUE self) -{ - ENTER(5); - ssize_t e, nf; - Real *p; - - GUARD_OBJ(p, GetVpValue(self, 1)); - BigDecimal_check_num(p); - - e = VpExponent10(p); - if (e <= 0) return INT2FIX(0); - nf = VpBaseFig(); - if (e <= nf) { - return LONG2NUM((long)(VpGetSign(p) * (DECDIG_DBL_SIGNED)p->frac[0])); - } - else { - VALUE a = BigDecimal_split(self); - VALUE digits = RARRAY_AREF(a, 1); - VALUE numerator = rb_funcall(digits, rb_intern("to_i"), 0); - VALUE ret; - ssize_t dpower = e - (ssize_t)RSTRING_LEN(digits); - - if (BIGDECIMAL_NEGATIVE_P(p)) { - numerator = rb_funcall(numerator, '*', 1, INT2FIX(-1)); - } - if (dpower < 0) { - ret = rb_funcall(numerator, rb_intern("div"), 1, - rb_funcall(INT2FIX(10), rb_intern("**"), 1, - INT2FIX(-dpower))); - } - else { - ret = rb_funcall(numerator, '*', 1, - rb_funcall(INT2FIX(10), rb_intern("**"), 1, - INT2FIX(dpower))); - } - if (RB_TYPE_P(ret, T_FLOAT)) { - rb_raise(rb_eFloatDomainError, "Infinity"); - } - return ret; - } -} - -/* Returns a new Float object having approximately the same value as the - * BigDecimal number. Normal accuracy limits and built-in errors of binary - * Float arithmetic apply. - */ -static VALUE -BigDecimal_to_f(VALUE self) -{ - ENTER(1); - Real *p; - double d; - SIGNED_VALUE e; - char *buf; - volatile VALUE str; - - GUARD_OBJ(p, GetVpValue(self, 1)); - if (VpVtoD(&d, &e, p) != 1) - return rb_float_new(d); - if (e > (SIGNED_VALUE)(DBL_MAX_10_EXP+BASE_FIG)) - goto overflow; - if (e < (SIGNED_VALUE)(DBL_MIN_10_EXP-BASE_FIG)) - goto underflow; - - str = rb_str_new(0, VpNumOfChars(p, "E")); - buf = RSTRING_PTR(str); - VpToString(p, buf, RSTRING_LEN(str), 0, 0); - errno = 0; - d = strtod(buf, 0); - if (errno == ERANGE) { - if (d == 0.0) goto underflow; - if (fabs(d) >= HUGE_VAL) goto overflow; - } - return rb_float_new(d); - -overflow: - VpException(VP_EXCEPTION_OVERFLOW, "BigDecimal to Float conversion", 0); - if (BIGDECIMAL_NEGATIVE_P(p)) - return rb_float_new(VpGetDoubleNegInf()); - else - return rb_float_new(VpGetDoublePosInf()); - -underflow: - VpException(VP_EXCEPTION_UNDERFLOW, "BigDecimal to Float conversion", 0); - if (BIGDECIMAL_NEGATIVE_P(p)) - return rb_float_new(-0.0); - else - return rb_float_new(0.0); -} - - -/* Converts a BigDecimal to a Rational. - */ -static VALUE -BigDecimal_to_r(VALUE self) -{ - Real *p; - ssize_t sign, power, denomi_power; - VALUE a, digits, numerator; - - p = GetVpValue(self, 1); - BigDecimal_check_num(p); - - sign = VpGetSign(p); - power = VpExponent10(p); - a = BigDecimal_split(self); - digits = RARRAY_AREF(a, 1); - denomi_power = power - RSTRING_LEN(digits); - numerator = rb_funcall(digits, rb_intern("to_i"), 0); - - if (sign < 0) { - numerator = rb_funcall(numerator, '*', 1, INT2FIX(-1)); - } - if (denomi_power < 0) { - return rb_Rational(numerator, - rb_funcall(INT2FIX(10), rb_intern("**"), 1, - INT2FIX(-denomi_power))); - } - else { - return rb_Rational1(rb_funcall(numerator, '*', 1, - rb_funcall(INT2FIX(10), rb_intern("**"), 1, - INT2FIX(denomi_power)))); - } -} - -/* The coerce method provides support for Ruby type coercion. It is not - * enabled by default. - * - * This means that binary operations like + * / or - can often be performed - * on a BigDecimal and an object of another type, if the other object can - * be coerced into a BigDecimal value. - * - * e.g. - * a = BigDecimal("1.0") - * b = a / 2.0 #=> 0.5 - * - * Note that coercing a String to a BigDecimal is not supported by default; - * it requires a special compile-time option when building Ruby. - */ -static VALUE -BigDecimal_coerce(VALUE self, VALUE other) -{ - ENTER(2); - VALUE obj; - Real *b; - - if (RB_TYPE_P(other, T_FLOAT)) { - GUARD_OBJ(b, GetVpValueWithPrec(other, 0, 1)); - obj = rb_assoc_new(VpCheckGetValue(b), self); - } - else { - if (RB_TYPE_P(other, T_RATIONAL)) { - Real* pv = DATA_PTR(self); - GUARD_OBJ(b, GetVpValueWithPrec(other, pv->Prec*VpBaseFig(), 1)); - } - else { - GUARD_OBJ(b, GetVpValue(other, 1)); - } - obj = rb_assoc_new(b->obj, self); - } - - return obj; -} - -/* - * call-seq: - * +big_decimal -> self - * - * Returns +self+: - * - * +BigDecimal(5) # => 0.5e1 - * +BigDecimal(-5) # => -0.5e1 - * - */ - -static VALUE -BigDecimal_uplus(VALUE self) -{ - return self; -} - - /* - * call-seq: - * self + value -> bigdecimal - * - * Returns the \BigDecimal sum of +self+ and +value+: - * - * b = BigDecimal('111111.111') # => 0.111111111e6 - * b + 2 # => 0.111113111e6 - * b + 2.0 # => 0.111113111e6 - * b + Rational(2, 1) # => 0.111113111e6 - * b + Complex(2, 0) # => (0.111113111e6+0i) - * - * See the {Note About Precision}[BigDecimal.html#class-BigDecimal-label-A+Note+About+Precision]. - * - */ - -static VALUE -BigDecimal_add(VALUE self, VALUE r) -{ - ENTER(5); - Real *c, *a, *b; - size_t mx; - - GUARD_OBJ(a, GetVpValue(self, 1)); - if (RB_TYPE_P(r, T_FLOAT)) { - b = GetVpValueWithPrec(r, 0, 1); - } - else if (RB_TYPE_P(r, T_RATIONAL)) { - b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1); - } - else { - b = GetVpValue(r, 0); - } - - if (!b) return DoSomeOne(self,r,'+'); - SAVE(b); - - if (VpIsNaN(b)) return b->obj; - if (VpIsNaN(a)) return a->obj; - - mx = GetAddSubPrec(a, b); - if (mx == (size_t)-1L) { - GUARD_OBJ(c, NewZeroWrapLimited(1, VpBaseFig() + 1)); - VpAddSub(c, a, b, 1); - } - else { - GUARD_OBJ(c, NewZeroWrapLimited(1, mx * (VpBaseFig() + 1))); - if (!mx) { - VpSetInf(c, VpGetSign(a)); - } - else { - VpAddSub(c, a, b, 1); - } - } - return VpCheckGetValue(c); -} - - /* call-seq: - * self - value -> bigdecimal - * - * Returns the \BigDecimal difference of +self+ and +value+: - * - * b = BigDecimal('333333.333') # => 0.333333333e6 - * b - 2 # => 0.333331333e6 - * b - 2.0 # => 0.333331333e6 - * b - Rational(2, 1) # => 0.333331333e6 - * b - Complex(2, 0) # => (0.333331333e6+0i) - * - * See the {Note About Precision}[BigDecimal.html#class-BigDecimal-label-A+Note+About+Precision]. - * - */ -static VALUE -BigDecimal_sub(VALUE self, VALUE r) -{ - ENTER(5); - Real *c, *a, *b; - size_t mx; - - GUARD_OBJ(a, GetVpValue(self,1)); - if (RB_TYPE_P(r, T_FLOAT)) { - b = GetVpValueWithPrec(r, 0, 1); - } - else if (RB_TYPE_P(r, T_RATIONAL)) { - b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1); - } - else { - b = GetVpValue(r,0); - } - - if (!b) return DoSomeOne(self,r,'-'); - SAVE(b); - - if (VpIsNaN(b)) return b->obj; - if (VpIsNaN(a)) return a->obj; - - mx = GetAddSubPrec(a,b); - if (mx == (size_t)-1L) { - GUARD_OBJ(c, NewZeroWrapLimited(1, VpBaseFig() + 1)); - VpAddSub(c, a, b, -1); - } - else { - GUARD_OBJ(c, NewZeroWrapLimited(1, mx *(VpBaseFig() + 1))); - if (!mx) { - VpSetInf(c,VpGetSign(a)); - } - else { - VpAddSub(c, a, b, -1); - } - } - return VpCheckGetValue(c); -} - -static VALUE -BigDecimalCmp(VALUE self, VALUE r,char op) -{ - ENTER(5); - SIGNED_VALUE e; - Real *a, *b=0; - GUARD_OBJ(a, GetVpValue(self, 1)); - switch (TYPE(r)) { - case T_DATA: - if (!is_kind_of_BigDecimal(r)) break; - /* fall through */ - case T_FIXNUM: - /* fall through */ - case T_BIGNUM: - GUARD_OBJ(b, GetVpValue(r, 0)); - break; - - case T_FLOAT: - GUARD_OBJ(b, GetVpValueWithPrec(r, 0, 0)); - break; - - case T_RATIONAL: - GUARD_OBJ(b, GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 0)); - break; - - default: - break; - } - if (b == NULL) { - ID f = 0; - - switch (op) { - case '*': - return rb_num_coerce_cmp(self, r, rb_intern("<=>")); - - case '=': - return RTEST(rb_num_coerce_cmp(self, r, rb_intern("=="))) ? Qtrue : Qfalse; - - case 'G': - f = rb_intern(">="); - break; - - case 'L': - f = rb_intern("<="); - break; - - case '>': - /* fall through */ - case '<': - f = (ID)op; - break; - - default: - break; - } - return rb_num_coerce_relop(self, r, f); - } - SAVE(b); - e = VpComp(a, b); - if (e == 999) - return (op == '*') ? Qnil : Qfalse; - switch (op) { - case '*': - return INT2FIX(e); /* any op */ - - case '=': - if (e == 0) return Qtrue; - return Qfalse; - - case 'G': - if (e >= 0) return Qtrue; - return Qfalse; - - case '>': - if (e > 0) return Qtrue; - return Qfalse; - - case 'L': - if (e <= 0) return Qtrue; - return Qfalse; - - case '<': - if (e < 0) return Qtrue; - return Qfalse; - - default: - break; - } - - rb_bug("Undefined operation in BigDecimalCmp()"); - - UNREACHABLE; -} - -/* Returns True if the value is zero. */ -static VALUE -BigDecimal_zero(VALUE self) -{ - Real *a = GetVpValue(self, 1); - return VpIsZero(a) ? Qtrue : Qfalse; -} - -/* Returns self if the value is non-zero, nil otherwise. */ -static VALUE -BigDecimal_nonzero(VALUE self) -{ - Real *a = GetVpValue(self, 1); - return VpIsZero(a) ? Qnil : self; -} - -/* The comparison operator. - * a <=> b is 0 if a == b, 1 if a > b, -1 if a < b. - */ -static VALUE -BigDecimal_comp(VALUE self, VALUE r) -{ - return BigDecimalCmp(self, r, '*'); -} - -/* - * Tests for value equality; returns true if the values are equal. - * - * The == and === operators and the eql? method have the same implementation - * for BigDecimal. - * - * Values may be coerced to perform the comparison: - * - * BigDecimal('1.0') == 1.0 #=> true - */ -static VALUE -BigDecimal_eq(VALUE self, VALUE r) -{ - return BigDecimalCmp(self, r, '='); -} - -/* call-seq: - * self < other -> true or false - * - * Returns +true+ if +self+ is less than +other+, +false+ otherwise: - * - * b = BigDecimal('1.5') # => 0.15e1 - * b < 2 # => true - * b < 2.0 # => true - * b < Rational(2, 1) # => true - * b < 1.5 # => false - * - * Raises an exception if the comparison cannot be made. - * - */ -static VALUE -BigDecimal_lt(VALUE self, VALUE r) -{ - return BigDecimalCmp(self, r, '<'); -} - -/* call-seq: - * self <= other -> true or false - * - * Returns +true+ if +self+ is less or equal to than +other+, +false+ otherwise: - * - * b = BigDecimal('1.5') # => 0.15e1 - * b <= 2 # => true - * b <= 2.0 # => true - * b <= Rational(2, 1) # => true - * b <= 1.5 # => true - * b < 1 # => false - * - * Raises an exception if the comparison cannot be made. - * - */ -static VALUE -BigDecimal_le(VALUE self, VALUE r) -{ - return BigDecimalCmp(self, r, 'L'); -} - -/* call-seq: - * self > other -> true or false - * - * Returns +true+ if +self+ is greater than +other+, +false+ otherwise: - * - * b = BigDecimal('1.5') - * b > 1 # => true - * b > 1.0 # => true - * b > Rational(1, 1) # => true - * b > 2 # => false - * - * Raises an exception if the comparison cannot be made. - * - */ -static VALUE -BigDecimal_gt(VALUE self, VALUE r) -{ - return BigDecimalCmp(self, r, '>'); -} - -/* call-seq: - * self >= other -> true or false - * - * Returns +true+ if +self+ is greater than or equal to +other+, +false+ otherwise: - * - * b = BigDecimal('1.5') - * b >= 1 # => true - * b >= 1.0 # => true - * b >= Rational(1, 1) # => true - * b >= 1.5 # => true - * b > 2 # => false - * - * Raises an exception if the comparison cannot be made. - * - */ -static VALUE -BigDecimal_ge(VALUE self, VALUE r) -{ - return BigDecimalCmp(self, r, 'G'); -} - -/* - * call-seq: - * -self -> bigdecimal - * - * Returns the \BigDecimal negation of self: - * - * b0 = BigDecimal('1.5') - * b1 = -b0 # => -0.15e1 - * b2 = -b1 # => 0.15e1 - * - */ - -static VALUE -BigDecimal_neg(VALUE self) -{ - ENTER(5); - Real *c, *a; - GUARD_OBJ(a, GetVpValue(self, 1)); - GUARD_OBJ(c, NewZeroWrapLimited(1, a->Prec *(VpBaseFig() + 1))); - VpAsgn(c, a, -1); - return VpCheckGetValue(c); -} - -static VALUE -BigDecimal_mult(VALUE self, VALUE r) -{ - ENTER(5); - Real *c, *a, *b; - size_t mx; - - GUARD_OBJ(a, GetVpValue(self, 1)); - if (RB_TYPE_P(r, T_FLOAT)) { - b = GetVpValueWithPrec(r, 0, 1); - } - else if (RB_TYPE_P(r, T_RATIONAL)) { - b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1); - } - else { - b = GetVpValue(r,0); - } - - if (!b) return DoSomeOne(self, r, '*'); - SAVE(b); - - mx = a->Prec + b->Prec; - GUARD_OBJ(c, NewZeroWrapLimited(1, mx * (VpBaseFig() + 1))); - VpMult(c, a, b); - return VpCheckGetValue(c); -} - -static VALUE -BigDecimal_divide(VALUE self, VALUE r, Real **c, Real **res, Real **div) -/* For c = self.div(r): with round operation */ -{ - ENTER(5); - Real *a, *b; - ssize_t a_prec, b_prec; - size_t mx; - - TypedData_Get_Struct(self, Real, &BigDecimal_data_type, a); - SAVE(a); - - VALUE rr = r; - if (is_kind_of_BigDecimal(rr)) { - /* do nothing */ - } - else if (RB_INTEGER_TYPE_P(r)) { - rr = rb_inum_convert_to_BigDecimal(r, 0, true); - } - else if (RB_TYPE_P(r, T_FLOAT)) { - rr = rb_float_convert_to_BigDecimal(r, 0, true); - } - else if (RB_TYPE_P(r, T_RATIONAL)) { - rr = rb_rational_convert_to_BigDecimal(r, a->Prec*BASE_FIG, true); - } - - if (!is_kind_of_BigDecimal(rr)) { - return DoSomeOne(self, r, '/'); - } - - TypedData_Get_Struct(rr, Real, &BigDecimal_data_type, b); - SAVE(b); - *div = b; - - BigDecimal_count_precision_and_scale(self, &a_prec, NULL); - BigDecimal_count_precision_and_scale(rr, &b_prec, NULL); - mx = (a_prec > b_prec) ? a_prec : b_prec; - mx *= 2; - - if (2*BIGDECIMAL_DOUBLE_FIGURES > mx) - mx = 2*BIGDECIMAL_DOUBLE_FIGURES; - - GUARD_OBJ((*c), NewZeroWrapNolimit(1, mx + 2*BASE_FIG)); - GUARD_OBJ((*res), NewZeroWrapNolimit(1, (mx + 1)*2 + 2*BASE_FIG)); - VpDivd(*c, *res, a, b); - - return Qnil; -} - -static VALUE BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod); - -/* call-seq: - * a / b -> bigdecimal - * - * Divide by the specified value. - * - * The result precision will be the precision of the larger operand, - * but its minimum is 2*Float::DIG. - * - * See BigDecimal#div. - * See BigDecimal#quo. - */ -static VALUE -BigDecimal_div(VALUE self, VALUE r) -/* For c = self/r: with round operation */ -{ - ENTER(5); - Real *c=NULL, *res=NULL, *div = NULL; - r = BigDecimal_divide(self, r, &c, &res, &div); - if (!NIL_P(r)) return r; /* coerced by other */ - SAVE(c); SAVE(res); SAVE(div); - /* a/b = c + r/b */ - /* c xxxxx - r 00000yyyyy ==> (y/b)*BASE >= HALF_BASE - */ - /* Round */ - if (VpHasVal(div)) { /* frac[0] must be zero for NaN,INF,Zero */ - VpInternalRound(c, 0, c->frac[c->Prec-1], (DECDIG)(VpBaseVal() * (DECDIG_DBL)res->frac[0] / div->frac[0])); - } - return VpCheckGetValue(c); -} - -static VALUE BigDecimal_round(int argc, VALUE *argv, VALUE self); - -/* call-seq: - * quo(value) -> bigdecimal - * quo(value, digits) -> bigdecimal - * - * Divide by the specified value. - * - * digits:: If specified and less than the number of significant digits of - * the result, the result is rounded to the given number of digits, - * according to the rounding mode indicated by BigDecimal.mode. - * - * If digits is 0 or omitted, the result is the same as for the - * / operator. - * - * See BigDecimal#/. - * See BigDecimal#div. - */ -static VALUE -BigDecimal_quo(int argc, VALUE *argv, VALUE self) -{ - VALUE value, digits, result; - SIGNED_VALUE n = -1; - - argc = rb_scan_args(argc, argv, "11", &value, &digits); - if (argc > 1) { - n = check_int_precision(digits); - } - - if (n > 0) { - result = BigDecimal_div2(self, value, digits); - } - else { - result = BigDecimal_div(self, value); - } - - return result; -} - -/* - * %: mod = a%b = a - (a.to_f/b).floor * b - * div = (a.to_f/b).floor - */ -static VALUE -BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod) -{ - ENTER(8); - Real *c=NULL, *d=NULL, *res=NULL; - Real *a, *b; - ssize_t a_prec, b_prec; - size_t mx; - - TypedData_Get_Struct(self, Real, &BigDecimal_data_type, a); - SAVE(a); - - VALUE rr = r; - if (is_kind_of_BigDecimal(rr)) { - /* do nothing */ - } - else if (RB_INTEGER_TYPE_P(r)) { - rr = rb_inum_convert_to_BigDecimal(r, 0, true); - } - else if (RB_TYPE_P(r, T_FLOAT)) { - rr = rb_float_convert_to_BigDecimal(r, 0, true); - } - else if (RB_TYPE_P(r, T_RATIONAL)) { - rr = rb_rational_convert_to_BigDecimal(r, a->Prec*BASE_FIG, true); - } - - if (!is_kind_of_BigDecimal(rr)) { - return Qfalse; - } - - TypedData_Get_Struct(rr, Real, &BigDecimal_data_type, b); - SAVE(b); - - if (VpIsNaN(a) || VpIsNaN(b)) goto NaN; - if (VpIsInf(a) && VpIsInf(b)) goto NaN; - if (VpIsZero(b)) { - rb_raise(rb_eZeroDivError, "divided by 0"); - } - if (VpIsInf(a)) { - if (VpGetSign(a) == VpGetSign(b)) { - VALUE inf = BigDecimal_positive_infinity(); - TypedData_Get_Struct(inf, Real, &BigDecimal_data_type, *div); - } - else { - VALUE inf = BigDecimal_negative_infinity(); - TypedData_Get_Struct(inf, Real, &BigDecimal_data_type, *div); - } - VALUE nan = BigDecimal_nan(); - TypedData_Get_Struct(nan, Real, &BigDecimal_data_type, *mod); - return Qtrue; - } - if (VpIsInf(b)) { - VALUE zero = BigDecimal_positive_zero(); - TypedData_Get_Struct(zero, Real, &BigDecimal_data_type, *div); - *mod = a; - return Qtrue; - } - if (VpIsZero(a)) { - VALUE zero = BigDecimal_positive_zero(); - TypedData_Get_Struct(zero, Real, &BigDecimal_data_type, *div); - TypedData_Get_Struct(zero, Real, &BigDecimal_data_type, *mod); - return Qtrue; - } - - BigDecimal_count_precision_and_scale(self, &a_prec, NULL); - BigDecimal_count_precision_and_scale(rr, &b_prec, NULL); - - mx = (a_prec > b_prec) ? a_prec : b_prec; - mx *= 2; - - if (2*BIGDECIMAL_DOUBLE_FIGURES > mx) - mx = 2*BIGDECIMAL_DOUBLE_FIGURES; - - GUARD_OBJ(c, NewZeroWrapLimited(1, mx + 2*BASE_FIG)); - GUARD_OBJ(res, NewZeroWrapNolimit(1, mx*2 + 2*BASE_FIG)); - VpDivd(c, res, a, b); - - mx = c->Prec * BASE_FIG; - GUARD_OBJ(d, NewZeroWrapLimited(1, mx)); - VpActiveRound(d, c, VP_ROUND_DOWN, 0); - - VpMult(res, d, b); - VpAddSub(c, a, res, -1); - - if (!VpIsZero(c) && (VpGetSign(a) * VpGetSign(b) < 0)) { - /* result adjustment for negative case */ - res = rbd_reallocate_struct(res, d->MaxPrec); - res->MaxPrec = d->MaxPrec; - VpAddSub(res, d, VpOne(), -1); - GUARD_OBJ(d, NewZeroWrapLimited(1, GetAddSubPrec(c, b) * 2*BASE_FIG)); - VpAddSub(d, c, b, 1); - *div = res; - *mod = d; - } - else { - *div = d; - *mod = c; - } - return Qtrue; - - NaN: - { - VALUE nan = BigDecimal_nan(); - TypedData_Get_Struct(nan, Real, &BigDecimal_data_type, *div); - TypedData_Get_Struct(nan, Real, &BigDecimal_data_type, *mod); - } - return Qtrue; -} - -/* call-seq: - * a % b - * a.modulo(b) - * - * Returns the modulus from dividing by b. - * - * See BigDecimal#divmod. - */ -static VALUE -BigDecimal_mod(VALUE self, VALUE r) /* %: a%b = a - (a.to_f/b).floor * b */ -{ - ENTER(3); - Real *div = NULL, *mod = NULL; - - if (BigDecimal_DoDivmod(self, r, &div, &mod)) { - SAVE(div); SAVE(mod); - return VpCheckGetValue(mod); - } - return DoSomeOne(self, r, '%'); -} - -static VALUE -BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv) -{ - ENTER(10); - size_t mx; - Real *a = NULL, *b = NULL, *c = NULL, *res = NULL, *d = NULL, *rr = NULL, *ff = NULL; - Real *f = NULL; - - GUARD_OBJ(a, GetVpValue(self, 1)); - if (RB_TYPE_P(r, T_FLOAT)) { - b = GetVpValueWithPrec(r, 0, 1); - } - else if (RB_TYPE_P(r, T_RATIONAL)) { - b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1); - } - else { - b = GetVpValue(r, 0); - } - - if (!b) return DoSomeOne(self, r, rb_intern("remainder")); - SAVE(b); - - if (VpIsPosInf(b) || VpIsNegInf(b)) { - GUARD_OBJ(*dv, NewZeroWrapLimited(1, 1)); - VpSetZero(*dv, 1); - *rv = a; - return Qnil; - } - - mx = (a->MaxPrec + b->MaxPrec) *VpBaseFig(); - 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, NewZeroWrapLimited(1, mx)); - GUARD_OBJ(f, NewZeroWrapLimited(1, mx)); - - VpActiveRound(d, c, VP_ROUND_DOWN, 0); /* 0: round off */ - - VpFrac(f, c); - VpMult(rr, f, b); - VpAddSub(ff, res, rr, 1); - - *dv = d; - *rv = ff; - return Qnil; -} - -/* call-seq: - * remainder(value) - * - * Returns the remainder from dividing by the value. - * - * x.remainder(y) means x-y*(x/y).truncate - */ -static VALUE -BigDecimal_remainder(VALUE self, VALUE r) /* remainder */ -{ - VALUE f; - Real *d, *rv = 0; - f = BigDecimal_divremain(self, r, &d, &rv); - if (!NIL_P(f)) return f; - return VpCheckGetValue(rv); -} - -/* call-seq: - * divmod(value) - * - * Divides by the specified value, and returns the quotient and modulus - * as BigDecimal numbers. The quotient is rounded towards negative infinity. - * - * For example: - * - * require 'bigdecimal' - * - * a = BigDecimal("42") - * b = BigDecimal("9") - * - * q, m = a.divmod(b) - * - * c = q * b + m - * - * a == c #=> true - * - * The quotient q is (a/b).floor, and the modulus is the amount that must be - * added to q * b to get a. - */ -static VALUE -BigDecimal_divmod(VALUE self, VALUE r) -{ - ENTER(5); - Real *div = NULL, *mod = NULL; - - if (BigDecimal_DoDivmod(self, r, &div, &mod)) { - SAVE(div); SAVE(mod); - return rb_assoc_new(VpCheckGetValue(div), VpCheckGetValue(mod)); - } - return DoSomeOne(self,r,rb_intern("divmod")); -} - -/* - * Do the same manner as Float#div when n is nil. - * Do the same manner as BigDecimal#quo when n is 0. - */ -static inline VALUE -BigDecimal_div2(VALUE self, VALUE b, VALUE n) -{ - ENTER(5); - SIGNED_VALUE ix; - - if (NIL_P(n)) { /* div in Float sense */ - Real *div = NULL; - Real *mod; - if (BigDecimal_DoDivmod(self, b, &div, &mod)) { - return BigDecimal_to_i(VpCheckGetValue(div)); - } - return DoSomeOne(self, b, rb_intern("div")); - } - - /* div in BigDecimal sense */ - ix = check_int_precision(n); - if (ix == 0) { - return BigDecimal_div(self, b); - } - else { - Real *res = NULL; - Real *av = NULL, *bv = NULL, *cv = NULL; - size_t mx = ix + VpBaseFig()*2; - size_t b_prec = ix; - size_t pl = VpSetPrecLimit(0); - - GUARD_OBJ(cv, 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 - * GetVpValueWithPrec. */ - if (RB_FLOAT_TYPE_P(b) && b_prec > BIGDECIMAL_DOUBLE_FIGURES) { - b_prec = BIGDECIMAL_DOUBLE_FIGURES; - } - GUARD_OBJ(bv, GetVpValueWithPrec(b, b_prec, 1)); - mx = av->Prec + bv->Prec + 2; - if (mx <= cv->MaxPrec) mx = cv->MaxPrec + 1; - GUARD_OBJ(res, NewZeroWrapNolimit(1, (mx * 2 + 2)*VpBaseFig())); - VpDivd(cv, res, av, bv); - VpSetPrecLimit(pl); - VpLeftRound(cv, VpGetRoundMode(), ix); - return VpCheckGetValue(cv); - } -} - - /* - * Document-method: BigDecimal#div - * - * call-seq: - * div(value) -> integer - * div(value, digits) -> bigdecimal or integer - * - * Divide by the specified value. - * - * digits:: If specified and less than the number of significant digits of the - * result, the result is rounded to that number of digits, according - * to BigDecimal.mode. - * - * If digits is 0, the result is the same as for the / operator - * or #quo. - * - * If digits is not specified, the result is an integer, - * by analogy with Float#div; see also BigDecimal#divmod. - * - * See BigDecimal#/. - * See BigDecimal#quo. - * - * Examples: - * - * a = BigDecimal("4") - * b = BigDecimal("3") - * - * a.div(b, 3) # => 0.133e1 - * - * a.div(b, 0) # => 0.1333333333333333333e1 - * a / b # => 0.1333333333333333333e1 - * a.quo(b) # => 0.1333333333333333333e1 - * - * a.div(b) # => 1 - */ -static VALUE -BigDecimal_div3(int argc, VALUE *argv, VALUE self) -{ - VALUE b,n; - - rb_scan_args(argc, argv, "11", &b, &n); - - return BigDecimal_div2(self, b, n); -} - - /* - * call-seq: - * add(value, ndigits) -> new_bigdecimal - * - * Returns the \BigDecimal sum of +self+ and +value+ - * with a precision of +ndigits+ decimal digits. - * - * When +ndigits+ is less than the number of significant digits - * in the sum, the sum is rounded to that number of digits, - * according to the current rounding mode; see BigDecimal.mode. - * - * Examples: - * - * # Set the rounding mode. - * BigDecimal.mode(BigDecimal::ROUND_MODE, :half_up) - * b = BigDecimal('111111.111') - * b.add(1, 0) # => 0.111112111e6 - * b.add(1, 3) # => 0.111e6 - * b.add(1, 6) # => 0.111112e6 - * b.add(1, 15) # => 0.111112111e6 - * b.add(1.0, 15) # => 0.111112111e6 - * b.add(Rational(1, 1), 15) # => 0.111112111e6 - * - */ - -static VALUE -BigDecimal_add2(VALUE self, VALUE b, VALUE n) -{ - ENTER(2); - Real *cv; - SIGNED_VALUE mx = check_int_precision(n); - if (mx == 0) return BigDecimal_add(self, b); - else { - size_t pl = VpSetPrecLimit(0); - VALUE c = BigDecimal_add(self, b); - VpSetPrecLimit(pl); - GUARD_OBJ(cv, GetVpValue(c, 1)); - VpLeftRound(cv, VpGetRoundMode(), mx); - return VpCheckGetValue(cv); - } -} - -/* call-seq: - * sub(value, digits) -> bigdecimal - * - * Subtract the specified value. - * - * e.g. - * c = a.sub(b,n) - * - * digits:: If specified and less than the number of significant digits of the - * result, the result is rounded to that number of digits, according - * to BigDecimal.mode. - * - */ -static VALUE -BigDecimal_sub2(VALUE self, VALUE b, VALUE n) -{ - ENTER(2); - Real *cv; - SIGNED_VALUE mx = check_int_precision(n); - if (mx == 0) return BigDecimal_sub(self, b); - else { - size_t pl = VpSetPrecLimit(0); - VALUE c = BigDecimal_sub(self, b); - VpSetPrecLimit(pl); - GUARD_OBJ(cv, GetVpValue(c, 1)); - VpLeftRound(cv, VpGetRoundMode(), mx); - return VpCheckGetValue(cv); - } -} - - /* - * call-seq: - * mult(other, ndigits) -> bigdecimal - * - * Returns the \BigDecimal product of +self+ and +value+ - * with a precision of +ndigits+ decimal digits. - * - * When +ndigits+ is less than the number of significant digits - * in the sum, the sum is rounded to that number of digits, - * according to the current rounding mode; see BigDecimal.mode. - * - * Examples: - * - * # Set the rounding mode. - * BigDecimal.mode(BigDecimal::ROUND_MODE, :half_up) - * b = BigDecimal('555555.555') - * b.mult(3, 0) # => 0.1666666665e7 - * b.mult(3, 3) # => 0.167e7 - * b.mult(3, 6) # => 0.166667e7 - * b.mult(3, 15) # => 0.1666666665e7 - * b.mult(3.0, 0) # => 0.1666666665e7 - * b.mult(Rational(3, 1), 0) # => 0.1666666665e7 - * b.mult(Complex(3, 0), 0) # => (0.1666666665e7+0.0i) - * - */ - -static VALUE -BigDecimal_mult2(VALUE self, VALUE b, VALUE n) -{ - ENTER(2); - Real *cv; - SIGNED_VALUE mx = check_int_precision(n); - if (mx == 0) return BigDecimal_mult(self, b); - else { - size_t pl = VpSetPrecLimit(0); - VALUE c = BigDecimal_mult(self, b); - VpSetPrecLimit(pl); - GUARD_OBJ(cv, GetVpValue(c, 1)); - VpLeftRound(cv, VpGetRoundMode(), mx); - return VpCheckGetValue(cv); - } -} - -/* - * call-seq: - * abs -> bigdecimal - * - * Returns the \BigDecimal absolute value of +self+: - * - * BigDecimal('5').abs # => 0.5e1 - * BigDecimal('-3').abs # => 0.3e1 - * - */ - -static VALUE -BigDecimal_abs(VALUE self) -{ - ENTER(5); - Real *c, *a; - size_t mx; - - GUARD_OBJ(a, GetVpValue(self, 1)); - mx = a->Prec *(VpBaseFig() + 1); - GUARD_OBJ(c, NewZeroWrapLimited(1, mx)); - VpAsgn(c, a, 1); - VpChangeSign(c, 1); - return VpCheckGetValue(c); -} - -/* call-seq: - * sqrt(n) - * - * Returns the square root of the value. - * - * Result has at least n significant digits. - */ -static VALUE -BigDecimal_sqrt(VALUE self, VALUE nFig) -{ - ENTER(5); - Real *c, *a; - size_t mx, n; - - GUARD_OBJ(a, GetVpValue(self, 1)); - mx = a->Prec * (VpBaseFig() + 1); - - n = check_int_precision(nFig); - n += VpDblFig() + VpBaseFig(); - if (mx <= n) mx = n; - GUARD_OBJ(c, NewZeroWrapLimited(1, mx)); - VpSqrt(c, a); - return VpCheckGetValue(c); -} - -/* Return the integer part of the number, as a BigDecimal. - */ -static VALUE -BigDecimal_fix(VALUE self) -{ - ENTER(5); - Real *c, *a; - size_t mx; - - GUARD_OBJ(a, GetVpValue(self, 1)); - mx = a->Prec *(VpBaseFig() + 1); - GUARD_OBJ(c, NewZeroWrapLimited(1, mx)); - VpActiveRound(c, a, VP_ROUND_DOWN, 0); /* 0: round off */ - return VpCheckGetValue(c); -} - -/* call-seq: - * round(n, mode) - * - * Round to the nearest integer (by default), returning the result as a - * BigDecimal if n is specified, or as an Integer if it isn't. - * - * BigDecimal('3.14159').round #=> 3 - * BigDecimal('8.7').round #=> 9 - * BigDecimal('-9.9').round #=> -10 - * - * BigDecimal('3.14159').round(2).class.name #=> "BigDecimal" - * BigDecimal('3.14159').round.class.name #=> "Integer" - * - * If n is specified and positive, the fractional part of the result has no - * more than that many digits. - * - * If n is specified and negative, at least that many digits to the left of the - * decimal point will be 0 in the result, and return value will be an Integer. - * - * BigDecimal('3.14159').round(3) #=> 3.142 - * BigDecimal('13345.234').round(-2) #=> 13300 - * - * The value of the optional mode argument can be used to determine how - * rounding is performed; see BigDecimal.mode. - */ -static VALUE -BigDecimal_round(int argc, VALUE *argv, VALUE self) -{ - ENTER(5); - Real *c, *a; - int iLoc = 0; - VALUE vLoc; - VALUE vRound; - int round_to_int = 0; - size_t mx, pl; - - unsigned short sw = VpGetRoundMode(); - - switch (rb_scan_args(argc, argv, "02", &vLoc, &vRound)) { - case 0: - iLoc = 0; - round_to_int = 1; - break; - case 1: - if (RB_TYPE_P(vLoc, T_HASH)) { - sw = check_rounding_mode_option(vLoc); - } - else { - iLoc = NUM2INT(vLoc); - if (iLoc < 1) round_to_int = 1; - } - break; - case 2: - iLoc = NUM2INT(vLoc); - if (RB_TYPE_P(vRound, T_HASH)) { - sw = check_rounding_mode_option(vRound); - } - else { - sw = check_rounding_mode(vRound); - } - break; - default: - break; - } - - pl = VpSetPrecLimit(0); - GUARD_OBJ(a, GetVpValue(self, 1)); - mx = a->Prec * (VpBaseFig() + 1); - GUARD_OBJ(c, NewZeroWrapLimited(1, mx)); - VpSetPrecLimit(pl); - VpActiveRound(c, a, sw, iLoc); - if (round_to_int) { - return BigDecimal_to_i(VpCheckGetValue(c)); - } - return VpCheckGetValue(c); -} - -/* call-seq: - * truncate(n) - * - * Truncate to the nearest integer (by default), returning the result as a - * BigDecimal. - * - * BigDecimal('3.14159').truncate #=> 3 - * BigDecimal('8.7').truncate #=> 8 - * BigDecimal('-9.9').truncate #=> -9 - * - * If n is specified and positive, the fractional part of the result has no - * more than that many digits. - * - * If n is specified and negative, at least that many digits to the left of the - * decimal point will be 0 in the result. - * - * BigDecimal('3.14159').truncate(3) #=> 3.141 - * BigDecimal('13345.234').truncate(-2) #=> 13300.0 - */ -static VALUE -BigDecimal_truncate(int argc, VALUE *argv, VALUE self) -{ - ENTER(5); - Real *c, *a; - int iLoc; - VALUE vLoc; - size_t mx, pl = VpSetPrecLimit(0); - - if (rb_scan_args(argc, argv, "01", &vLoc) == 0) { - iLoc = 0; - } - else { - iLoc = NUM2INT(vLoc); - } - - GUARD_OBJ(a, GetVpValue(self, 1)); - mx = a->Prec * (VpBaseFig() + 1); - GUARD_OBJ(c, NewZeroWrapLimited(1, mx)); - VpSetPrecLimit(pl); - VpActiveRound(c, a, VP_ROUND_DOWN, iLoc); /* 0: truncate */ - if (argc == 0) { - return BigDecimal_to_i(VpCheckGetValue(c)); - } - return VpCheckGetValue(c); -} - -/* Return the fractional part of the number, as a BigDecimal. - */ -static VALUE -BigDecimal_frac(VALUE self) -{ - ENTER(5); - Real *c, *a; - size_t mx; - - GUARD_OBJ(a, GetVpValue(self, 1)); - mx = a->Prec * (VpBaseFig() + 1); - GUARD_OBJ(c, NewZeroWrapLimited(1, mx)); - VpFrac(c, a); - return VpCheckGetValue(c); -} - -/* call-seq: - * floor(n) - * - * Return the largest integer less than or equal to the value, as a BigDecimal. - * - * BigDecimal('3.14159').floor #=> 3 - * BigDecimal('-9.1').floor #=> -10 - * - * If n is specified and positive, the fractional part of the result has no - * more than that many digits. - * - * If n is specified and negative, at least that - * many digits to the left of the decimal point will be 0 in the result. - * - * BigDecimal('3.14159').floor(3) #=> 3.141 - * BigDecimal('13345.234').floor(-2) #=> 13300.0 - */ -static VALUE -BigDecimal_floor(int argc, VALUE *argv, VALUE self) -{ - ENTER(5); - Real *c, *a; - int iLoc; - VALUE vLoc; - size_t mx, pl = VpSetPrecLimit(0); - - if (rb_scan_args(argc, argv, "01", &vLoc)==0) { - iLoc = 0; - } - else { - iLoc = NUM2INT(vLoc); - } - - GUARD_OBJ(a, GetVpValue(self, 1)); - mx = a->Prec * (VpBaseFig() + 1); - GUARD_OBJ(c, NewZeroWrapLimited(1, mx)); - VpSetPrecLimit(pl); - VpActiveRound(c, a, VP_ROUND_FLOOR, iLoc); -#ifdef BIGDECIMAL_DEBUG - VPrint(stderr, "floor: c=%\n", c); -#endif - if (argc == 0) { - return BigDecimal_to_i(VpCheckGetValue(c)); - } - return VpCheckGetValue(c); -} - -/* call-seq: - * ceil(n) - * - * Return the smallest integer greater than or equal to the value, as a BigDecimal. - * - * BigDecimal('3.14159').ceil #=> 4 - * BigDecimal('-9.1').ceil #=> -9 - * - * If n is specified and positive, the fractional part of the result has no - * more than that many digits. - * - * If n is specified and negative, at least that - * many digits to the left of the decimal point will be 0 in the result. - * - * BigDecimal('3.14159').ceil(3) #=> 3.142 - * BigDecimal('13345.234').ceil(-2) #=> 13400.0 - */ -static VALUE -BigDecimal_ceil(int argc, VALUE *argv, VALUE self) -{ - ENTER(5); - Real *c, *a; - int iLoc; - VALUE vLoc; - size_t mx, pl = VpSetPrecLimit(0); - - if (rb_scan_args(argc, argv, "01", &vLoc) == 0) { - iLoc = 0; - } else { - iLoc = NUM2INT(vLoc); - } - - GUARD_OBJ(a, GetVpValue(self, 1)); - mx = a->Prec * (VpBaseFig() + 1); - GUARD_OBJ(c, NewZeroWrapLimited(1, mx)); - VpSetPrecLimit(pl); - VpActiveRound(c, a, VP_ROUND_CEIL, iLoc); - if (argc == 0) { - return BigDecimal_to_i(VpCheckGetValue(c)); - } - return VpCheckGetValue(c); -} - -/* call-seq: - * to_s(s) - * - * Converts the value to a string. - * - * The default format looks like 0.xxxxEnn. - * - * The optional parameter s consists of either an integer; or an optional '+' - * or ' ', followed by an optional number, followed by an optional 'E' or 'F'. - * - * If there is a '+' at the start of s, positive values are returned with - * a leading '+'. - * - * A space at the start of s returns positive values with a leading space. - * - * If s contains a number, a space is inserted after each group of that many - * digits, starting from '.' and counting outwards. - * - * If s ends with an 'E', engineering notation (0.xxxxEnn) is used. - * - * If s ends with an 'F', conventional floating point notation is used. - * - * Examples: - * - * BigDecimal('-1234567890123.45678901234567890').to_s('5F') - * #=> '-123 45678 90123.45678 90123 45678 9' - * - * BigDecimal('1234567890123.45678901234567890').to_s('+8F') - * #=> '+12345 67890123.45678901 23456789' - * - * BigDecimal('1234567890123.45678901234567890').to_s(' F') - * #=> ' 1234567890123.4567890123456789' - */ -static VALUE -BigDecimal_to_s(int argc, VALUE *argv, VALUE self) -{ - ENTER(5); - int fmt = 0; /* 0: E format, 1: F format */ - int fPlus = 0; /* 0: default, 1: set ' ' before digits, 2: set '+' before digits. */ - Real *vp; - volatile VALUE str; - char *psz; - char ch; - size_t nc, mc = 0; - SIGNED_VALUE m; - VALUE f; - - GUARD_OBJ(vp, GetVpValue(self, 1)); - - if (rb_scan_args(argc, argv, "01", &f) == 1) { - if (RB_TYPE_P(f, T_STRING)) { - psz = StringValueCStr(f); - if (*psz == ' ') { - fPlus = 1; - psz++; - } - else if (*psz == '+') { - fPlus = 2; - psz++; - } - while ((ch = *psz++) != 0) { - if (ISSPACE(ch)) { - continue; - } - if (!ISDIGIT(ch)) { - if (ch == 'F' || ch == 'f') { - fmt = 1; /* F format */ - } - break; - } - mc = mc*10 + ch - '0'; - } - } - else { - m = NUM2INT(f); - if (m <= 0) { - rb_raise(rb_eArgError, "argument must be positive"); - } - mc = (size_t)m; - } - } - if (fmt) { - nc = VpNumOfChars(vp, "F"); - } - else { - nc = VpNumOfChars(vp, "E"); - } - if (mc > 0) { - nc += (nc + mc - 1) / mc + 1; - } - - str = rb_usascii_str_new(0, nc); - psz = RSTRING_PTR(str); - - if (fmt) { - VpToFString(vp, psz, RSTRING_LEN(str), mc, fPlus); - } - else { - VpToString (vp, psz, RSTRING_LEN(str), mc, fPlus); - } - rb_str_resize(str, strlen(psz)); - return str; -} - -/* Splits a BigDecimal number into four parts, returned as an array of values. - * - * The first value represents the sign of the BigDecimal, and is -1 or 1, or 0 - * if the BigDecimal is Not a Number. - * - * The second value is a string representing the significant digits of the - * BigDecimal, with no leading zeros. - * - * The third value is the base used for arithmetic (currently always 10) as an - * Integer. - * - * The fourth value is an Integer exponent. - * - * If the BigDecimal can be represented as 0.xxxxxx*10**n, then xxxxxx is the - * string of significant digits with no leading zeros, and n is the exponent. - * - * From these values, you can translate a BigDecimal to a float as follows: - * - * sign, significant_digits, base, exponent = a.split - * f = sign * "0.#{significant_digits}".to_f * (base ** exponent) - * - * (Note that the to_f method is provided as a more convenient way to translate - * a BigDecimal to a Float.) - */ -static VALUE -BigDecimal_split(VALUE self) -{ - ENTER(5); - Real *vp; - VALUE obj,str; - ssize_t e, s; - char *psz1; - - GUARD_OBJ(vp, GetVpValue(self, 1)); - str = rb_str_new(0, VpNumOfChars(vp, "E")); - psz1 = RSTRING_PTR(str); - VpSzMantissa(vp, psz1, RSTRING_LEN(str)); - s = 1; - if(psz1[0] == '-') { - size_t len = strlen(psz1 + 1); - - memmove(psz1, psz1 + 1, len); - psz1[len] = '\0'; - s = -1; - } - if (psz1[0] == 'N') s = 0; /* NaN */ - e = VpExponent10(vp); - obj = rb_ary_new2(4); - rb_ary_push(obj, INT2FIX(s)); - rb_ary_push(obj, str); - rb_str_resize(str, strlen(psz1)); - rb_ary_push(obj, INT2FIX(10)); - rb_ary_push(obj, SSIZET2NUM(e)); - return obj; -} - -/* Returns the exponent of the BigDecimal number, as an Integer. - * - * If the number can be represented as 0.xxxxxx*10**n where xxxxxx is a string - * of digits with no leading zeros, then n is the exponent. - */ -static VALUE -BigDecimal_exponent(VALUE self) -{ - ssize_t e = VpExponent10(GetVpValue(self, 1)); - return SSIZET2NUM(e); -} - -/* Returns a string representation of self. - * - * BigDecimal("1234.5678").inspect - * #=> "0.12345678e4" - */ -static VALUE -BigDecimal_inspect(VALUE self) -{ - ENTER(5); - Real *vp; - volatile VALUE str; - size_t nc; - - GUARD_OBJ(vp, GetVpValue(self, 1)); - nc = VpNumOfChars(vp, "E"); - - str = rb_str_new(0, nc); - VpToString(vp, RSTRING_PTR(str), RSTRING_LEN(str), 0, 0); - rb_str_resize(str, strlen(RSTRING_PTR(str))); - return str; -} - -static VALUE BigMath_s_exp(VALUE, VALUE, VALUE); -static VALUE BigMath_s_log(VALUE, VALUE, VALUE); - -#define BigMath_exp(x, n) BigMath_s_exp(rb_mBigMath, (x), (n)) -#define BigMath_log(x, n) BigMath_s_log(rb_mBigMath, (x), (n)) - -inline static int -is_integer(VALUE x) -{ - return (RB_TYPE_P(x, T_FIXNUM) || RB_TYPE_P(x, T_BIGNUM)); -} - -inline static int -is_negative(VALUE x) -{ - if (FIXNUM_P(x)) { - return FIX2LONG(x) < 0; - } - else if (RB_TYPE_P(x, T_BIGNUM)) { - return FIX2INT(rb_big_cmp(x, INT2FIX(0))) < 0; - } - else if (RB_TYPE_P(x, T_FLOAT)) { - return RFLOAT_VALUE(x) < 0.0; - } - return RTEST(rb_funcall(x, '<', 1, INT2FIX(0))); -} - -#define is_positive(x) (!is_negative(x)) - -inline static int -is_zero(VALUE x) -{ - VALUE num; - - switch (TYPE(x)) { - case T_FIXNUM: - return FIX2LONG(x) == 0; - - case T_BIGNUM: - return Qfalse; - - case T_RATIONAL: - num = rb_rational_num(x); - return FIXNUM_P(num) && FIX2LONG(num) == 0; - - default: - break; - } - - return RTEST(rb_funcall(x, id_eq, 1, INT2FIX(0))); -} - -inline static int -is_one(VALUE x) -{ - VALUE num, den; - - switch (TYPE(x)) { - case T_FIXNUM: - return FIX2LONG(x) == 1; - - case T_BIGNUM: - return Qfalse; - - case T_RATIONAL: - num = rb_rational_num(x); - den = rb_rational_den(x); - return FIXNUM_P(den) && FIX2LONG(den) == 1 && - FIXNUM_P(num) && FIX2LONG(num) == 1; - - default: - break; - } - - return RTEST(rb_funcall(x, id_eq, 1, INT2FIX(1))); -} - -inline static int -is_even(VALUE x) -{ - switch (TYPE(x)) { - case T_FIXNUM: - return (FIX2LONG(x) % 2) == 0; - - case T_BIGNUM: - { - unsigned long l; - rb_big_pack(x, &l, 1); - return l % 2 == 0; - } - - default: - break; - } - - return 0; -} - -static VALUE -bigdecimal_power_by_bigdecimal(Real const* x, Real const* exp, ssize_t const n) -{ - VALUE log_x, multiplied, y; - volatile VALUE obj = exp->obj; - - if (VpIsZero(exp)) { - return VpCheckGetValue(NewOneWrapLimited(1, n)); - } - - log_x = BigMath_log(x->obj, SSIZET2NUM(n+1)); - multiplied = BigDecimal_mult2(exp->obj, log_x, SSIZET2NUM(n+1)); - y = BigMath_exp(multiplied, SSIZET2NUM(n)); - RB_GC_GUARD(obj); - - return y; -} - -/* call-seq: - * power(n) - * power(n, prec) - * - * Returns the value raised to the power of n. - * - * Note that n must be an Integer. - * - * Also available as the operator **. - */ -static VALUE -BigDecimal_power(int argc, VALUE*argv, VALUE self) -{ - ENTER(5); - VALUE vexp, prec; - Real* exp = NULL; - Real *x, *y; - ssize_t mp, ma, n; - SIGNED_VALUE int_exp; - double d; - - rb_scan_args(argc, argv, "11", &vexp, &prec); - - GUARD_OBJ(x, GetVpValue(self, 1)); - n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec); - - if (VpIsNaN(x)) { - y = NewZeroWrapLimited(1, n); - VpSetNaN(y); - RB_GC_GUARD(y->obj); - return VpCheckGetValue(y); - } - - retry: - switch (TYPE(vexp)) { - case T_FIXNUM: - break; - - case T_BIGNUM: - break; - - case T_FLOAT: - d = RFLOAT_VALUE(vexp); - if (d == round(d)) { - if (FIXABLE(d)) { - vexp = LONG2FIX((long)d); - } - else { - vexp = rb_dbl2big(d); - } - goto retry; - } - if (NIL_P(prec)) { - n += BIGDECIMAL_DOUBLE_FIGURES; - } - exp = GetVpValueWithPrec(vexp, 0, 1); - break; - - case T_RATIONAL: - if (is_zero(rb_rational_num(vexp))) { - if (is_positive(vexp)) { - vexp = INT2FIX(0); - goto retry; - } - } - else if (is_one(rb_rational_den(vexp))) { - vexp = rb_rational_num(vexp); - goto retry; - } - exp = GetVpValueWithPrec(vexp, n, 1); - if (NIL_P(prec)) { - n += n; - } - break; - - case T_DATA: - if (is_kind_of_BigDecimal(vexp)) { - VALUE zero = INT2FIX(0); - VALUE rounded = BigDecimal_round(1, &zero, vexp); - if (RTEST(BigDecimal_eq(vexp, rounded))) { - vexp = BigDecimal_to_i(vexp); - goto retry; - } - if (NIL_P(prec)) { - GUARD_OBJ(y, GetVpValue(vexp, 1)); - n += y->Prec*VpBaseFig(); - } - exp = DATA_PTR(vexp); - break; - } - /* fall through */ - default: - rb_raise(rb_eTypeError, - "wrong argument type %"PRIsVALUE" (expected scalar Numeric)", - RB_OBJ_CLASSNAME(vexp)); - } - - if (VpIsZero(x)) { - 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(NewOneWrapLimited(1, n)); - } - else { - return VpCheckGetValue(NewZeroWrapLimited(1, n)); - } - } - - if (is_zero(vexp)) { - return VpCheckGetValue(NewOneWrapLimited(1, n)); - } - else if (is_one(vexp)) { - 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(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); - } - else if (RB_TYPE_P(vexp, T_BIGNUM)) { - 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(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(NewZeroWrapLimited(-1, n)); - } - else { - return VpCheckGetValue(NewZeroWrapLimited(1, n)); - } - } - } - - int_exp = FIX2LONG(vexp); - ma = int_exp; - if (ma < 0) ma = -ma; - if (ma == 0) ma = 1; - - if (VpIsDef(x)) { - mp = x->Prec * (VpBaseFig() + 1); - GUARD_OBJ(y, NewZeroWrapLimited(1, mp * (ma + 1))); - } - else { - GUARD_OBJ(y, NewZeroWrapLimited(1, 1)); - } - VpPowerByInt(y, x, int_exp); - if (!NIL_P(prec) && VpIsDef(y)) { - VpMidRound(y, VpGetRoundMode(), n); - } - return VpCheckGetValue(y); -} - -/* call-seq: - * self ** other -> bigdecimal - * - * Returns the \BigDecimal value of +self+ raised to power +other+: - * - * b = BigDecimal('3.14') - * b ** 2 # => 0.98596e1 - * b ** 2.0 # => 0.98596e1 - * b ** Rational(2, 1) # => 0.98596e1 - * - * Related: BigDecimal#power. - * - */ -static VALUE -BigDecimal_power_op(VALUE self, VALUE exp) -{ - return BigDecimal_power(1, &exp, self); -} - -/* :nodoc: - * - * private method for dup and clone the provided BigDecimal +other+ - */ -static VALUE -BigDecimal_initialize_copy(VALUE self, VALUE other) -{ - Real *pv = rb_check_typeddata(self, &BigDecimal_data_type); - Real *x = rb_check_typeddata(other, &BigDecimal_data_type); - - if (self != other) { - DATA_PTR(self) = VpCopy(pv, x); - } - return self; -} - -static VALUE -BigDecimal_clone(VALUE self) -{ - return self; -} - -#ifdef HAVE_RB_OPTS_EXCEPTION_P -int rb_opts_exception_p(VALUE opts, int default_value); -#define opts_exception_p(opts) rb_opts_exception_p((opts), 1) -#else -static int -opts_exception_p(VALUE opts) -{ - static ID kwds[1]; - VALUE exception; - if (!kwds[0]) { - kwds[0] = rb_intern_const("exception"); - } - if (!rb_get_kwargs(opts, kwds, 0, 1, &exception)) return 1; - switch (exception) { - case Qtrue: case Qfalse: - break; - default: - rb_raise(rb_eArgError, "true or false is expected as exception: %+"PRIsVALUE, - exception); - } - return exception != Qfalse; -} -#endif - -static VALUE -check_exception(VALUE bd) -{ - assert(is_kind_of_BigDecimal(bd)); - - Real *vp; - TypedData_Get_Struct(bd, Real, &BigDecimal_data_type, vp); - VpCheckGetValue(vp); /* VpCheckGetValue performs exception check */ - - return bd; -} - -static VALUE -rb_uint64_convert_to_BigDecimal(uint64_t uval, RB_UNUSED_VAR(size_t digs), int raise_exception) -{ - VALUE obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0); - - Real *vp; - if (uval == 0) { - vp = rbd_allocate_struct(1); - vp->MaxPrec = 1; - vp->Prec = 1; - vp->exponent = 1; - VpSetZero(vp, 1); - vp->frac[0] = 0; - } - else if (uval < BASE) { - vp = rbd_allocate_struct(1); - vp->MaxPrec = 1; - vp->Prec = 1; - vp->exponent = 1; - VpSetSign(vp, 1); - vp->frac[0] = (DECDIG)uval; - } - else { - DECDIG buf[BIGDECIMAL_INT64_MAX_LENGTH] = {0,}; - DECDIG r = uval % BASE; - size_t len = 0, ntz = 0; - if (r == 0) { - // Count and skip trailing zeros - for (; r == 0 && uval > 0; ++ntz) { - uval /= BASE; - r = uval % BASE; - } - } - for (; uval > 0; ++len) { - // Store digits - buf[BIGDECIMAL_INT64_MAX_LENGTH - len - 1] = r; - uval /= BASE; - r = uval % BASE; - } - - const size_t exp = len + ntz; - vp = rbd_allocate_struct(len); - vp->MaxPrec = len; - vp->Prec = len; - vp->exponent = exp; - VpSetSign(vp, 1); - MEMCPY(vp->frac, buf + BIGDECIMAL_INT64_MAX_LENGTH - len, DECDIG, len); - } - - return BigDecimal_wrap_struct(obj, vp); -} - -static VALUE -rb_int64_convert_to_BigDecimal(int64_t ival, size_t digs, int raise_exception) -{ - const uint64_t uval = (ival < 0) ? (((uint64_t)-(ival+1))+1) : (uint64_t)ival; - VALUE bd = rb_uint64_convert_to_BigDecimal(uval, digs, raise_exception); - if (ival < 0) { - Real *vp; - TypedData_Get_Struct(bd, Real, &BigDecimal_data_type, vp); - VpSetSign(vp, -1); - } - return bd; -} - -static VALUE -rb_big_convert_to_BigDecimal(VALUE val, RB_UNUSED_VAR(size_t digs), int raise_exception) -{ - assert(RB_TYPE_P(val, T_BIGNUM)); - - int leading_zeros; - size_t size = rb_absint_size(val, &leading_zeros); - int sign = FIX2INT(rb_big_cmp(val, INT2FIX(0))); - if (sign < 0 && leading_zeros == 0) { - size += 1; - } - if (size <= sizeof(long)) { - if (sign < 0) { - return rb_int64_convert_to_BigDecimal(NUM2LONG(val), digs, raise_exception); - } - else { - return rb_uint64_convert_to_BigDecimal(NUM2ULONG(val), digs, raise_exception); - } - } -#if defined(SIZEOF_LONG_LONG) && SIZEOF_LONG < SIZEOF_LONG_LONG - else if (size <= sizeof(LONG_LONG)) { - if (sign < 0) { - return rb_int64_convert_to_BigDecimal(NUM2LL(val), digs, raise_exception); - } - else { - return rb_uint64_convert_to_BigDecimal(NUM2ULL(val), digs, raise_exception); - } - } -#endif - else { - VALUE str = rb_big2str(val, 10); - Real *vp = VpCreateRbObject(RSTRING_LEN(str) + BASE_FIG + 1, - RSTRING_PTR(str), true); - RB_GC_GUARD(str); - return check_exception(vp->obj); - } -} - -static VALUE -rb_inum_convert_to_BigDecimal(VALUE val, RB_UNUSED_VAR(size_t digs), int raise_exception) -{ - assert(RB_INTEGER_TYPE_P(val)); - if (FIXNUM_P(val)) { - return rb_int64_convert_to_BigDecimal(FIX2LONG(val), digs, raise_exception); - } - else { - return rb_big_convert_to_BigDecimal(val, digs, raise_exception); - } -} - -static VALUE -rb_float_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception) -{ - assert(RB_FLOAT_TYPE_P(val)); - - double d = RFLOAT_VALUE(val); - - if (isnan(d)) { - VALUE obj = BigDecimal_nan(); - return check_exception(obj); - } - else if (isinf(d)) { - VALUE obj; - if (d > 0) { - obj = BigDecimal_positive_infinity(); - } - else { - obj = BigDecimal_negative_infinity(); - } - return check_exception(obj); - } - else if (d == 0.0) { - if (1/d < 0.0) { - return BigDecimal_negative_zero(); - } - else { - return BigDecimal_positive_zero(); - } - } - - if (digs == SIZE_MAX) { - if (!raise_exception) - return Qnil; - rb_raise(rb_eArgError, - "can't omit precision for a %"PRIsVALUE".", - CLASS_OF(val)); - } - else if (digs > BIGDECIMAL_DOUBLE_FIGURES) { - if (!raise_exception) - return Qnil; - rb_raise(rb_eArgError, "precision too large."); - } - - /* Use the same logic in flo_to_s to convert a float to a decimal string */ - char buf[BIGDECIMAL_DOUBLE_FIGURES + BASE_FIG + 2 + 1]; /* sizeof(buf) == 28 in the typical case */ - int decpt, negative_p; - char *e; - const int mode = digs == 0 ? 0 : 2; - char *p = BigDecimal_dtoa(d, mode, (int)digs, &decpt, &negative_p, &e); - int len10 = (int)(e - p); - if (len10 > BIGDECIMAL_DOUBLE_FIGURES) { - /* TODO: Presumably, rounding should be done here. */ - len10 = BIGDECIMAL_DOUBLE_FIGURES; - } - memcpy(buf, p, len10); - xfree(p); - - VALUE inum; - size_t RB_UNUSED_VAR(prec) = 0; - SIGNED_VALUE exp = 0; - if (decpt > 0) { - if (decpt < len10) { - /* - * len10 |---------------| - * : |-------| frac_len10 = len10 - decpt - * decpt |-------| |--| ntz10 = BASE_FIG - frac_len10 % BASE_FIG - * : : : - * 00 dd dddd.dddd dd 00 - * prec |-----.----.----.-----| prec = exp + roomof(frac_len, BASE_FIG) - * exp |-----.----| exp = roomof(decpt, BASE_FIG) - */ - const size_t frac_len10 = len10 - decpt; - const size_t ntz10 = BASE_FIG - frac_len10 % BASE_FIG; - memset(buf + len10, '0', ntz10); - buf[len10 + ntz10] = '\0'; - inum = rb_cstr_to_inum(buf, 10, false); - - exp = roomof(decpt, BASE_FIG); - prec = exp + roomof(frac_len10, BASE_FIG); - } - else { - /* - * decpt |-----------------------| - * len10 |----------| : - * : |------------| exp10 - * : : : - * 00 dd dddd dd 00 0000 0000.0 - * : : : : - * : |--| ntz10 = exp10 % BASE_FIG - * prec |-----.----.-----| : - * : |----.----| exp10 / BASE_FIG - * exp |-----.----.-----.----.----| - */ - const size_t exp10 = decpt - len10; - const size_t ntz10 = exp10 % BASE_FIG; - - memset(buf + len10, '0', ntz10); - buf[len10 + ntz10] = '\0'; - inum = rb_cstr_to_inum(buf, 10, false); - - prec = roomof(len10 + ntz10, BASE_FIG); - exp = prec + exp10 / BASE_FIG; - } - } - else if (decpt == 0) { - /* - * len10 |------------| - * : : - * 0.dddd dddd dd 00 - * : : : - * : |--| ntz10 = prec * BASE_FIG - len10 - * prec |----.----.-----| roomof(len10, BASE_FIG) - */ - prec = roomof(len10, BASE_FIG); - const size_t ntz10 = prec * BASE_FIG - len10; - - memset(buf + len10, '0', ntz10); - buf[len10 + ntz10] = '\0'; - inum = rb_cstr_to_inum(buf, 10, false); - } - else { - /* - * len10 |---------------| - * : : - * decpt |-------| |--| ntz10 = prec * BASE_FIG - nlz10 - len10 - * : : : - * 0.0000 00 dd dddd dddd dd 00 - * : : : - * nlz10 |--| : decpt % BASE_FIG - * prec |-----.----.----.-----| roomof(decpt + len10, BASE_FIG) - exp - * exp |----| decpt / BASE_FIG - */ - decpt = -decpt; - - const size_t nlz10 = decpt % BASE_FIG; - exp = decpt / BASE_FIG; - prec = roomof(decpt + len10, BASE_FIG) - exp; - const size_t ntz10 = prec * BASE_FIG - nlz10 - len10; - - if (nlz10 > 0) { - memmove(buf + nlz10, buf, len10); - memset(buf, '0', nlz10); - } - memset(buf + nlz10 + len10, '0', ntz10); - buf[nlz10 + len10 + ntz10] = '\0'; - inum = rb_cstr_to_inum(buf, 10, false); - - exp = -exp; - } - - VALUE bd = rb_inum_convert_to_BigDecimal(inum, SIZE_MAX, raise_exception); - Real *vp; - TypedData_Get_Struct(bd, Real, &BigDecimal_data_type, vp); - assert(vp->Prec == prec); - vp->exponent = exp; - - if (negative_p) VpSetSign(vp, -1); - return bd; -} - -static VALUE -rb_rational_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception) -{ - assert(RB_TYPE_P(val, T_RATIONAL)); - - if (digs == SIZE_MAX) { - if (!raise_exception) - return Qnil; - rb_raise(rb_eArgError, - "can't omit precision for a %"PRIsVALUE".", - CLASS_OF(val)); - } - - VALUE num = rb_inum_convert_to_BigDecimal(rb_rational_num(val), 0, raise_exception); - VALUE d = BigDecimal_div2(num, rb_rational_den(val), SIZET2NUM(digs)); - return d; -} - -static VALUE -rb_cstr_convert_to_BigDecimal(const char *c_str, size_t digs, int raise_exception) -{ - if (digs == SIZE_MAX) - digs = 0; - - Real *vp = VpCreateRbObject(digs, c_str, raise_exception); - if (!vp) - return Qnil; - return VpCheckGetValue(vp); -} - -static inline VALUE -rb_str_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception) -{ - const char *c_str = StringValueCStr(val); - return rb_cstr_convert_to_BigDecimal(c_str, digs, raise_exception); -} - -static VALUE -rb_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception) -{ - switch (val) { - case Qnil: - case Qtrue: - case Qfalse: - if (raise_exception) { - const char *cname = NIL_P(val) ? "nil" : - val == Qtrue ? "true" : - val == Qfalse ? "false" : - NULL; - rb_raise(rb_eTypeError, - "can't convert %s into BigDecimal", cname); - } - return Qnil; - - default: - break; - } - - if (is_kind_of_BigDecimal(val)) { - if (digs == SIZE_MAX) - return check_exception(val); - - Real *vp; - TypedData_Get_Struct(val, Real, &BigDecimal_data_type, vp); - - VALUE copy = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0); - vp = VpCopy(NULL, vp); - /* TODO: rounding */ - BigDecimal_wrap_struct(copy, vp); - return VpCheckGetValue(vp); - } - else if (RB_INTEGER_TYPE_P(val)) { - return rb_inum_convert_to_BigDecimal(val, digs, raise_exception); - } - else if (RB_FLOAT_TYPE_P(val)) { - return rb_float_convert_to_BigDecimal(val, digs, raise_exception); - } - else if (RB_TYPE_P(val, T_RATIONAL)) { - return rb_rational_convert_to_BigDecimal(val, digs, raise_exception); - } - else if (RB_TYPE_P(val, T_COMPLEX)) { - VALUE im = rb_complex_imag(val); - if (!is_zero(im)) { - /* TODO: handle raise_exception */ - rb_raise(rb_eArgError, - "Unable to make a BigDecimal from non-zero imaginary number"); - } - return rb_convert_to_BigDecimal(rb_complex_real(val), digs, raise_exception); - } - else if (RB_TYPE_P(val, T_STRING)) { - return rb_str_convert_to_BigDecimal(val, digs, raise_exception); - } - - /* TODO: chheck to_d */ - /* TODO: chheck to_int */ - - VALUE str = rb_check_convert_type(val, T_STRING, "String", "to_str"); - if (!RB_TYPE_P(str, T_STRING)) { - if (raise_exception) { - rb_raise(rb_eTypeError, - "can't convert %"PRIsVALUE" into BigDecimal", rb_obj_class(val)); - } - return Qnil; - } - return rb_str_convert_to_BigDecimal(str, digs, raise_exception); -} - -/* call-seq: - * BigDecimal(value, exception: true) -> bigdecimal - * BigDecimal(value, ndigits, exception: true) -> bigdecimal - * - * 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 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+: - * - * - Integer, Float, Rational, Complex, or BigDecimal: converted directly: - * - * # Integer, Complex, or BigDecimal value does not require ndigits; ignored if given. - * BigDecimal(2) # => 0.2e1 - * BigDecimal(Complex(2, 0)) # => 0.2e1 - * BigDecimal(BigDecimal(2)) # => 0.2e1 - * # Float or Rational value requires ndigits. - * BigDecimal(2.0, 0) # => 0.2e1 - * BigDecimal(Rational(2, 1), 0) # => 0.2e1 - * - * - String: converted by parsing if it contains an integer or floating-point literal; - * leading and trailing whitespace is ignored: - * - * # String does not require ndigits; ignored if given. - * BigDecimal('2') # => 0.2e1 - * BigDecimal('2.0') # => 0.2e1 - * BigDecimal('0.2e1') # => 0.2e1 - * BigDecimal(' 2.0 ') # => 0.2e1 - * - * - Other type that responds to method :to_str: - * first converted to a string, then converted to a \BigDecimal, as above. - * - * - Other type: - * - * - Raises an exception if keyword argument +exception+ is +true+. - * - Returns +nil+ if keyword argument +exception+ is +false+. - * - * Raises an exception if +value+ evaluates to a Float - * and +digits+ is larger than Float::DIG + 1. - * - */ -static VALUE -f_BigDecimal(int argc, VALUE *argv, VALUE self) -{ - VALUE val, digs_v, opts = Qnil; - argc = rb_scan_args(argc, argv, "11:", &val, &digs_v, &opts); - int exception = opts_exception_p(opts); - - size_t digs = SIZE_MAX; /* this means digs is omitted */ - if (argc > 1) { - digs_v = rb_to_int(digs_v); - if (FIXNUM_P(digs_v)) { - long n = FIX2LONG(digs_v); - if (n < 0) - goto negative_digs; - digs = (size_t)n; - } - else { - if (RBIGNUM_NEGATIVE_P(digs_v)) { - negative_digs: - if (!exception) - return Qnil; - rb_raise(rb_eArgError, "negative precision"); - } - digs = NUM2SIZET(digs_v); - } - } - - return rb_convert_to_BigDecimal(val, digs, exception); -} - -static VALUE -BigDecimal_s_interpret_loosely(VALUE klass, VALUE str) -{ - char const *c_str = StringValueCStr(str); - Real *vp = VpNewRbClass(0, c_str, klass, false, true); - if (!vp) - return Qnil; - else - return VpCheckGetValue(vp); -} - - /* call-seq: - * BigDecimal.limit(digits) - * - * Limit the number of significant digits in newly created BigDecimal - * numbers to the specified value. Rounding is performed as necessary, - * as specified by BigDecimal.mode. - * - * A limit of 0, the default, means no upper limit. - * - * The limit specified by this method takes less priority over any limit - * specified to instance methods such as ceil, floor, truncate, or round. - */ -static VALUE -BigDecimal_limit(int argc, VALUE *argv, VALUE self) -{ - VALUE nFig; - VALUE nCur = SIZET2NUM(VpGetPrecLimit()); - - if (rb_scan_args(argc, argv, "01", &nFig) == 1) { - int nf; - if (NIL_P(nFig)) return nCur; - nf = NUM2INT(nFig); - if (nf < 0) { - rb_raise(rb_eArgError, "argument must be positive"); - } - VpSetPrecLimit(nf); - } - return nCur; -} - -/* Returns the sign of the value. - * - * 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: - * - * BigDecimal::SIGN_NaN:: value is Not a Number - * BigDecimal::SIGN_POSITIVE_ZERO:: value is +0 - * BigDecimal::SIGN_NEGATIVE_ZERO:: value is -0 - * BigDecimal::SIGN_POSITIVE_INFINITE:: value is +Infinity - * BigDecimal::SIGN_NEGATIVE_INFINITE:: value is -Infinity - * BigDecimal::SIGN_POSITIVE_FINITE:: value is positive - * BigDecimal::SIGN_NEGATIVE_FINITE:: value is negative - */ -static VALUE -BigDecimal_sign(VALUE self) -{ /* sign */ - int s = GetVpValue(self, 1)->sign; - return INT2FIX(s); -} - -/* - * call-seq: BigDecimal.save_exception_mode { ... } - * - * Execute the provided block, but preserve the exception mode - * - * BigDecimal.save_exception_mode do - * BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - * BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - * - * BigDecimal(BigDecimal('Infinity')) - * BigDecimal(BigDecimal('-Infinity')) - * BigDecimal(BigDecimal('NaN')) - * end - * - * For use with the BigDecimal::EXCEPTION_* - * - * See BigDecimal.mode - */ -static VALUE -BigDecimal_save_exception_mode(VALUE self) -{ - unsigned short const exception_mode = VpGetException(); - int state; - VALUE ret = rb_protect(rb_yield, Qnil, &state); - VpSetException(exception_mode); - if (state) rb_jump_tag(state); - return ret; -} - -/* - * call-seq: BigDecimal.save_rounding_mode { ... } - * - * Execute the provided block, but preserve the rounding mode - * - * BigDecimal.save_rounding_mode do - * BigDecimal.mode(BigDecimal::ROUND_MODE, :up) - * puts BigDecimal.mode(BigDecimal::ROUND_MODE) - * end - * - * For use with the BigDecimal::ROUND_* - * - * See BigDecimal.mode - */ -static VALUE -BigDecimal_save_rounding_mode(VALUE self) -{ - unsigned short const round_mode = VpGetRoundMode(); - int state; - VALUE ret = rb_protect(rb_yield, Qnil, &state); - VpSetRoundMode(round_mode); - if (state) rb_jump_tag(state); - return ret; -} - -/* - * call-seq: BigDecimal.save_limit { ... } - * - * Execute the provided block, but preserve the precision limit - * - * BigDecimal.limit(100) - * puts BigDecimal.limit - * BigDecimal.save_limit do - * BigDecimal.limit(200) - * puts BigDecimal.limit - * end - * puts BigDecimal.limit - * - */ -static VALUE -BigDecimal_save_limit(VALUE self) -{ - size_t const limit = VpGetPrecLimit(); - int state; - VALUE ret = rb_protect(rb_yield, Qnil, &state); - VpSetPrecLimit(limit); - if (state) rb_jump_tag(state); - return ret; -} - -/* call-seq: - * BigMath.exp(decimal, numeric) -> BigDecimal - * - * Computes the value of e (the base of natural logarithms) raised to the - * power of +decimal+, to the specified number of digits of precision. - * - * If +decimal+ is infinity, returns Infinity. - * - * If +decimal+ is NaN, returns NaN. - */ -static VALUE -BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec) -{ - ssize_t prec, n, i; - Real* vx = NULL; - VALUE one, d, y; - int negative = 0; - int infinite = 0; - int nan = 0; - double flo; - - prec = NUM2SSIZET(vprec); - if (prec <= 0) { - rb_raise(rb_eArgError, "Zero or negative precision for exp"); - } - - /* TODO: the following switch statement is almost same as one in the - * BigDecimalCmp function. */ - switch (TYPE(x)) { - case T_DATA: - if (!is_kind_of_BigDecimal(x)) break; - vx = DATA_PTR(x); - negative = BIGDECIMAL_NEGATIVE_P(vx); - infinite = VpIsPosInf(vx) || VpIsNegInf(vx); - nan = VpIsNaN(vx); - break; - - case T_FIXNUM: - /* fall through */ - case T_BIGNUM: - vx = GetVpValue(x, 0); - break; - - case T_FLOAT: - flo = RFLOAT_VALUE(x); - negative = flo < 0; - infinite = isinf(flo); - nan = isnan(flo); - if (!infinite && !nan) { - vx = GetVpValueWithPrec(x, 0, 0); - } - break; - - case T_RATIONAL: - vx = GetVpValueWithPrec(x, prec, 0); - break; - - default: - break; - } - if (infinite) { - if (negative) { - return VpCheckGetValue(GetVpValueWithPrec(INT2FIX(0), prec, 1)); - } - else { - Real* vy = NewZeroWrapNolimit(1, prec); - VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE); - RB_GC_GUARD(vy->obj); - return VpCheckGetValue(vy); - } - } - else if (nan) { - Real* vy = NewZeroWrapNolimit(1, prec); - VpSetNaN(vy); - RB_GC_GUARD(vy->obj); - return VpCheckGetValue(vy); - } - else if (vx == NULL) { - cannot_be_coerced_into_BigDecimal(rb_eArgError, x); - } - x = vx->obj; - - n = prec + BIGDECIMAL_DOUBLE_FIGURES; - negative = BIGDECIMAL_NEGATIVE_P(vx); - if (negative) { - VALUE x_zero = INT2NUM(1); - VALUE x_copy = f_BigDecimal(1, &x_zero, klass); - x = BigDecimal_initialize_copy(x_copy, x); - vx = DATA_PTR(x); - VpSetSign(vx, 1); - } - - one = VpCheckGetValue(NewOneWrapLimited(1, 1)); - y = one; - d = y; - i = 1; - - while (!VpIsZero((Real*)DATA_PTR(d))) { - SIGNED_VALUE const ey = VpExponent10(DATA_PTR(y)); - SIGNED_VALUE const ed = VpExponent10(DATA_PTR(d)); - ssize_t m = n - vabs(ey - ed); - - rb_thread_check_ints(); - - if (m <= 0) { - break; - } - else if ((size_t)m < BIGDECIMAL_DOUBLE_FIGURES) { - m = BIGDECIMAL_DOUBLE_FIGURES; - } - - d = BigDecimal_mult(d, x); /* d <- d * x */ - d = BigDecimal_div2(d, SSIZET2NUM(i), SSIZET2NUM(m)); /* d <- d / i */ - y = BigDecimal_add(y, d); /* y <- y + d */ - ++i; /* i <- i + 1 */ - } - - if (negative) { - return BigDecimal_div2(one, y, vprec); - } - else { - vprec = SSIZET2NUM(prec - VpExponent10(DATA_PTR(y))); - return BigDecimal_round(1, &vprec, y); - } - - RB_GC_GUARD(one); - RB_GC_GUARD(x); - RB_GC_GUARD(y); - RB_GC_GUARD(d); -} - -/* call-seq: - * BigMath.log(decimal, numeric) -> BigDecimal - * - * Computes the natural logarithm of +decimal+ to the specified number of - * digits of precision, +numeric+. - * - * If +decimal+ is zero or negative, raises Math::DomainError. - * - * If +decimal+ is positive infinity, returns Infinity. - * - * If +decimal+ is NaN, returns NaN. - */ -static VALUE -BigMath_s_log(VALUE klass, VALUE x, VALUE vprec) -{ - ssize_t prec, n, i; - SIGNED_VALUE expo; - Real* vx = NULL; - VALUE vn, one, two, w, x2, y, d; - int zero = 0; - int negative = 0; - int infinite = 0; - int nan = 0; - double flo; - long fix; - - if (!is_integer(vprec)) { - rb_raise(rb_eArgError, "precision must be an Integer"); - } - - prec = NUM2SSIZET(vprec); - if (prec <= 0) { - rb_raise(rb_eArgError, "Zero or negative precision for exp"); - } - - /* TODO: the following switch statement is almost same as one in the - * BigDecimalCmp function. */ - switch (TYPE(x)) { - case T_DATA: - if (!is_kind_of_BigDecimal(x)) break; - vx = DATA_PTR(x); - zero = VpIsZero(vx); - negative = BIGDECIMAL_NEGATIVE_P(vx); - infinite = VpIsPosInf(vx) || VpIsNegInf(vx); - nan = VpIsNaN(vx); - break; - - case T_FIXNUM: - fix = FIX2LONG(x); - zero = fix == 0; - negative = fix < 0; - goto get_vp_value; - - case T_BIGNUM: - i = FIX2INT(rb_big_cmp(x, INT2FIX(0))); - zero = i == 0; - negative = i < 0; -get_vp_value: - if (zero || negative) break; - vx = GetVpValue(x, 0); - break; - - case T_FLOAT: - flo = RFLOAT_VALUE(x); - zero = flo == 0; - negative = flo < 0; - infinite = isinf(flo); - nan = isnan(flo); - if (!zero && !negative && !infinite && !nan) { - vx = GetVpValueWithPrec(x, 0, 1); - } - break; - - case T_RATIONAL: - zero = RRATIONAL_ZERO_P(x); - negative = RRATIONAL_NEGATIVE_P(x); - if (zero || negative) break; - vx = GetVpValueWithPrec(x, prec, 1); - break; - - case T_COMPLEX: - rb_raise(rb_eMathDomainError, - "Complex argument for BigMath.log"); - - default: - break; - } - if (infinite && !negative) { - Real *vy = NewZeroWrapNolimit(1, prec); - RB_GC_GUARD(vy->obj); - VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE); - return VpCheckGetValue(vy); - } - else if (nan) { - Real* vy = NewZeroWrapNolimit(1, prec); - RB_GC_GUARD(vy->obj); - VpSetNaN(vy); - return VpCheckGetValue(vy); - } - else if (zero || negative) { - rb_raise(rb_eMathDomainError, - "Zero or negative argument for log"); - } - else if (vx == NULL) { - cannot_be_coerced_into_BigDecimal(rb_eArgError, x); - } - x = VpCheckGetValue(vx); - - one = VpCheckGetValue(NewOneWrapLimited(1, 1)); - two = VpCheckGetValue(VpCreateRbObject(1, "2", true)); - - n = prec + BIGDECIMAL_DOUBLE_FIGURES; - vn = SSIZET2NUM(n); - expo = VpExponent10(vx); - if (expo < 0 || expo >= 3) { - char buf[DECIMAL_SIZE_OF_BITS(SIZEOF_VALUE * CHAR_BIT) + 4]; - snprintf(buf, sizeof(buf), "1E%"PRIdVALUE, -expo); - x = BigDecimal_mult2(x, VpCheckGetValue(VpCreateRbObject(1, buf, true)), vn); - } - else { - expo = 0; - } - w = BigDecimal_sub(x, one); - x = BigDecimal_div2(w, BigDecimal_add(x, one), vn); - x2 = BigDecimal_mult2(x, x, vn); - y = x; - d = y; - i = 1; - while (!VpIsZero((Real*)DATA_PTR(d))) { - SIGNED_VALUE const ey = VpExponent10(DATA_PTR(y)); - SIGNED_VALUE const ed = VpExponent10(DATA_PTR(d)); - ssize_t m = n - vabs(ey - ed); - if (m <= 0) { - break; - } - else if ((size_t)m < BIGDECIMAL_DOUBLE_FIGURES) { - m = BIGDECIMAL_DOUBLE_FIGURES; - } - - x = BigDecimal_mult2(x2, x, vn); - i += 2; - d = BigDecimal_div2(x, SSIZET2NUM(i), SSIZET2NUM(m)); - y = BigDecimal_add(y, d); - } - - y = BigDecimal_mult(y, two); - if (expo != 0) { - VALUE log10, vexpo, dy; - log10 = BigMath_s_log(klass, INT2FIX(10), vprec); - vexpo = VpCheckGetValue(GetVpValue(SSIZET2NUM(expo), 1)); - dy = BigDecimal_mult(log10, vexpo); - y = BigDecimal_add(y, dy); - } - - RB_GC_GUARD(one); - RB_GC_GUARD(two); - RB_GC_GUARD(vn); - RB_GC_GUARD(x2); - RB_GC_GUARD(y); - RB_GC_GUARD(d); - - return y; -} - -static VALUE BIGDECIMAL_NAN = Qnil; - -static VALUE -BigDecimal_nan(void) -{ - return BIGDECIMAL_NAN; -} - -static VALUE BIGDECIMAL_POSITIVE_INFINITY = Qnil; - -static VALUE -BigDecimal_positive_infinity(void) -{ - return BIGDECIMAL_POSITIVE_INFINITY; -} - -static VALUE BIGDECIMAL_NEGATIVE_INFINITY = Qnil; - -static VALUE -BigDecimal_negative_infinity(void) -{ - return BIGDECIMAL_NEGATIVE_INFINITY; -} - -static VALUE BIGDECIMAL_POSITIVE_ZERO = Qnil; - -static VALUE -BigDecimal_positive_zero(void) -{ - return BIGDECIMAL_POSITIVE_ZERO; -} - -static VALUE BIGDECIMAL_NEGATIVE_ZERO = Qnil; - -static VALUE -BigDecimal_negative_zero(void) -{ - return BIGDECIMAL_NEGATIVE_ZERO; -} - -/* Document-class: BigDecimal - * BigDecimal provides arbitrary-precision floating point decimal arithmetic. - * - * == Introduction - * - * Ruby provides built-in support for arbitrary precision integer arithmetic. - * - * For example: - * - * 42**13 #=> 1265437718438866624512 - * - * BigDecimal provides similar support for very large or very accurate floating - * point numbers. - * - * Decimal arithmetic is also useful for general calculation, because it - * provides the correct answers people expect--whereas normal binary floating - * point arithmetic often introduces subtle errors because of the conversion - * between base 10 and base 2. - * - * For example, try: - * - * sum = 0 - * 10_000.times do - * sum = sum + 0.0001 - * end - * print sum #=> 0.9999999999999062 - * - * and contrast with the output from: - * - * require 'bigdecimal' - * - * sum = BigDecimal("0") - * 10_000.times do - * sum = sum + BigDecimal("0.0001") - * end - * print sum #=> 0.1E1 - * - * Similarly: - * - * (BigDecimal("1.2") - BigDecimal("1.0")) == BigDecimal("0.2") #=> true - * - * (1.2 - 1.0) == 0.2 #=> false - * - * == A Note About Precision - * - * For a calculation using a \BigDecimal and another +value+, - * the precision of the result depends on the type of +value+: - * - * - If +value+ is a \Float, - * the precision is Float::DIG + 1. - * - If +value+ is a \Rational, the precision is larger than Float::DIG + 1. - * - If +value+ is a \BigDecimal, the precision is +value+'s precision in the - * internal representation, which is platform-dependent. - * - If +value+ is other object, the precision is determined by the result of +BigDecimal(value)+. - * - * == Special features of accurate decimal arithmetic - * - * Because BigDecimal is more accurate than normal binary floating point - * arithmetic, it requires some special values. - * - * === Infinity - * - * BigDecimal sometimes needs to return infinity, for example if you divide - * a value by zero. - * - * BigDecimal("1.0") / BigDecimal("0.0") #=> Infinity - * BigDecimal("-1.0") / BigDecimal("0.0") #=> -Infinity - * - * You can represent infinite numbers to BigDecimal using the strings - * 'Infinity', '+Infinity' and - * '-Infinity' (case-sensitive) - * - * === Not a Number - * - * When a computation results in an undefined value, the special value +NaN+ - * (for 'not a number') is returned. - * - * Example: - * - * BigDecimal("0.0") / BigDecimal("0.0") #=> NaN - * - * You can also create undefined values. - * - * NaN is never considered to be the same as any other value, even NaN itself: - * - * n = BigDecimal('NaN') - * n == 0.0 #=> false - * n == n #=> false - * - * === Positive and negative zero - * - * If a computation results in a value which is too small to be represented as - * a BigDecimal within the currently specified limits of precision, zero must - * be returned. - * - * If the value which is too small to be represented is negative, a BigDecimal - * value of negative zero is returned. - * - * BigDecimal("1.0") / BigDecimal("-Infinity") #=> -0.0 - * - * If the value is positive, a value of positive zero is returned. - * - * BigDecimal("1.0") / BigDecimal("Infinity") #=> 0.0 - * - * (See BigDecimal.mode for how to specify limits of precision.) - * - * Note that +-0.0+ and +0.0+ are considered to be the same for the purposes of - * comparison. - * - * Note also that in mathematics, there is no particular concept of negative - * or positive zero; true mathematical zero has no sign. - * - * == bigdecimal/util - * - * When you require +bigdecimal/util+, the #to_d method will be - * available on BigDecimal and the native Integer, Float, Rational, - * and String classes: - * - * require 'bigdecimal/util' - * - * 42.to_d # => 0.42e2 - * 0.5.to_d # => 0.5e0 - * (2/3r).to_d(3) # => 0.667e0 - * "0.5".to_d # => 0.5e0 - * - * == Methods for Working with \JSON - * - * - {::json_create}[rdoc-ref:BigDecimal.json_create]: - * Returns a new \BigDecimal object constructed from the given object. - * - {#as_json}[rdoc-ref:BigDecimal#as_json]: - * Returns a 2-element hash representing +self+. - * - {#to_json}[rdoc-ref:BigDecimal#to_json]: - * Returns a \JSON string representing +self+. - * - * These methods are provided by the {JSON gem}[https://github.com/flori/json]. To make these methods available: - * - * require 'json/add/bigdecimal' - * - * * == License - * - * Copyright (C) 2002 by Shigeo Kobayashi . - * - * BigDecimal is released under the Ruby and 2-clause BSD licenses. - * See LICENSE.txt for details. - * - * Maintained by mrkn and ruby-core members. - * - * Documented by zzak , mathew , and - * many other contributors. - */ -void -Init_bigdecimal(void) -{ -#ifdef HAVE_RB_EXT_RACTOR_SAFE - rb_ext_ractor_safe(true); -#endif - VALUE arg; - - id_BigDecimal_exception_mode = rb_intern_const("BigDecimal.exception_mode"); - id_BigDecimal_rounding_mode = rb_intern_const("BigDecimal.rounding_mode"); - id_BigDecimal_precision_limit = rb_intern_const("BigDecimal.precision_limit"); - - /* Initialize VP routines */ - VpInit(0UL); - - /* Class and method registration */ - rb_cBigDecimal = rb_define_class("BigDecimal", rb_cNumeric); - - /* Global function */ - rb_define_global_function("BigDecimal", f_BigDecimal, -1); - - /* Class methods */ - rb_undef_alloc_func(rb_cBigDecimal); - rb_undef_method(CLASS_OF(rb_cBigDecimal), "new"); - rb_define_singleton_method(rb_cBigDecimal, "interpret_loosely", BigDecimal_s_interpret_loosely, 1); - rb_define_singleton_method(rb_cBigDecimal, "mode", BigDecimal_mode, -1); - rb_define_singleton_method(rb_cBigDecimal, "limit", BigDecimal_limit, -1); - rb_define_singleton_method(rb_cBigDecimal, "double_fig", BigDecimal_double_fig, 0); - rb_define_singleton_method(rb_cBigDecimal, "_load", BigDecimal_load, 1); - - rb_define_singleton_method(rb_cBigDecimal, "save_exception_mode", BigDecimal_save_exception_mode, 0); - rb_define_singleton_method(rb_cBigDecimal, "save_rounding_mode", BigDecimal_save_rounding_mode, 0); - rb_define_singleton_method(rb_cBigDecimal, "save_limit", BigDecimal_save_limit, 0); - - /* Constants definition */ - - /* - * The version of bigdecimal library - */ - rb_define_const(rb_cBigDecimal, "VERSION", rb_str_new2(BIGDECIMAL_VERSION)); - - /* - * Base value used in internal calculations. On a 32 bit system, BASE - * is 10000, indicating that calculation is done in groups of 4 digits. - * (If it were larger, BASE**2 wouldn't fit in 32 bits, so you couldn't - * guarantee that two groups could always be multiplied together without - * overflow.) - */ - rb_define_const(rb_cBigDecimal, "BASE", INT2FIX((SIGNED_VALUE)VpBaseVal())); - - /* Exceptions */ - - /* - * 0xff: Determines whether overflow, underflow or zero divide result in - * an exception being thrown. See BigDecimal.mode. - */ - rb_define_const(rb_cBigDecimal, "EXCEPTION_ALL", INT2FIX(VP_EXCEPTION_ALL)); - - /* - * 0x02: Determines what happens when the result of a computation is not a - * number (NaN). See BigDecimal.mode. - */ - rb_define_const(rb_cBigDecimal, "EXCEPTION_NaN", INT2FIX(VP_EXCEPTION_NaN)); - - /* - * 0x01: Determines what happens when the result of a computation is - * infinity. See BigDecimal.mode. - */ - rb_define_const(rb_cBigDecimal, "EXCEPTION_INFINITY", INT2FIX(VP_EXCEPTION_INFINITY)); - - /* - * 0x04: Determines what happens when the result of a computation is an - * underflow (a result too small to be represented). See BigDecimal.mode. - */ - rb_define_const(rb_cBigDecimal, "EXCEPTION_UNDERFLOW", INT2FIX(VP_EXCEPTION_UNDERFLOW)); - - /* - * 0x01: Determines what happens when the result of a computation is an - * overflow (a result too large to be represented). See BigDecimal.mode. - */ - rb_define_const(rb_cBigDecimal, "EXCEPTION_OVERFLOW", INT2FIX(VP_EXCEPTION_OVERFLOW)); - - /* - * 0x10: Determines what happens when a division by zero is performed. - * See BigDecimal.mode. - */ - rb_define_const(rb_cBigDecimal, "EXCEPTION_ZERODIVIDE", INT2FIX(VP_EXCEPTION_ZERODIVIDE)); - - /* - * 0x100: Determines what happens when a result must be rounded in order to - * fit in the appropriate number of significant digits. See - * BigDecimal.mode. - */ - rb_define_const(rb_cBigDecimal, "ROUND_MODE", INT2FIX(VP_ROUND_MODE)); - - /* 1: Indicates that values should be rounded away from zero. See - * BigDecimal.mode. - */ - rb_define_const(rb_cBigDecimal, "ROUND_UP", INT2FIX(VP_ROUND_UP)); - - /* 2: Indicates that values should be rounded towards zero. See - * BigDecimal.mode. - */ - rb_define_const(rb_cBigDecimal, "ROUND_DOWN", INT2FIX(VP_ROUND_DOWN)); - - /* 3: Indicates that digits >= 5 should be rounded up, others rounded down. - * See BigDecimal.mode. */ - rb_define_const(rb_cBigDecimal, "ROUND_HALF_UP", INT2FIX(VP_ROUND_HALF_UP)); - - /* 4: Indicates that digits >= 6 should be rounded up, others rounded down. - * See BigDecimal.mode. - */ - rb_define_const(rb_cBigDecimal, "ROUND_HALF_DOWN", INT2FIX(VP_ROUND_HALF_DOWN)); - /* 5: Round towards +Infinity. See BigDecimal.mode. */ - rb_define_const(rb_cBigDecimal, "ROUND_CEILING", INT2FIX(VP_ROUND_CEIL)); - - /* 6: Round towards -Infinity. See BigDecimal.mode. */ - rb_define_const(rb_cBigDecimal, "ROUND_FLOOR", INT2FIX(VP_ROUND_FLOOR)); - - /* 7: Round towards the even neighbor. See BigDecimal.mode. */ - rb_define_const(rb_cBigDecimal, "ROUND_HALF_EVEN", INT2FIX(VP_ROUND_HALF_EVEN)); - - /* 0: Indicates that a value is not a number. See BigDecimal.sign. */ - rb_define_const(rb_cBigDecimal, "SIGN_NaN", INT2FIX(VP_SIGN_NaN)); - - /* 1: Indicates that a value is +0. See BigDecimal.sign. */ - rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_ZERO", INT2FIX(VP_SIGN_POSITIVE_ZERO)); - - /* -1: Indicates that a value is -0. See BigDecimal.sign. */ - rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_ZERO", INT2FIX(VP_SIGN_NEGATIVE_ZERO)); - - /* 2: Indicates that a value is positive and finite. See BigDecimal.sign. */ - rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_FINITE", INT2FIX(VP_SIGN_POSITIVE_FINITE)); - - /* -2: Indicates that a value is negative and finite. See BigDecimal.sign. */ - rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_FINITE", INT2FIX(VP_SIGN_NEGATIVE_FINITE)); - - /* 3: Indicates that a value is positive and infinite. See BigDecimal.sign. */ - rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_INFINITE", INT2FIX(VP_SIGN_POSITIVE_INFINITE)); - - /* -3: Indicates that a value is negative and infinite. See BigDecimal.sign. */ - rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_INFINITE", INT2FIX(VP_SIGN_NEGATIVE_INFINITE)); - - /* Positive zero value. */ - arg = rb_str_new2("+0"); - BIGDECIMAL_POSITIVE_ZERO = f_BigDecimal(1, &arg, rb_cBigDecimal); - rb_gc_register_mark_object(BIGDECIMAL_POSITIVE_ZERO); - - /* Negative zero value. */ - arg = rb_str_new2("-0"); - BIGDECIMAL_NEGATIVE_ZERO = f_BigDecimal(1, &arg, rb_cBigDecimal); - rb_gc_register_mark_object(BIGDECIMAL_NEGATIVE_ZERO); - - /* Positive infinity value. */ - arg = rb_str_new2("+Infinity"); - BIGDECIMAL_POSITIVE_INFINITY = f_BigDecimal(1, &arg, rb_cBigDecimal); - rb_gc_register_mark_object(BIGDECIMAL_POSITIVE_INFINITY); - - /* Negative infinity value. */ - arg = rb_str_new2("-Infinity"); - BIGDECIMAL_NEGATIVE_INFINITY = f_BigDecimal(1, &arg, rb_cBigDecimal); - rb_gc_register_mark_object(BIGDECIMAL_NEGATIVE_INFINITY); - - /* 'Not a Number' value. */ - arg = rb_str_new2("NaN"); - BIGDECIMAL_NAN = f_BigDecimal(1, &arg, rb_cBigDecimal); - rb_gc_register_mark_object(BIGDECIMAL_NAN); - - /* Special value constants */ - rb_define_const(rb_cBigDecimal, "INFINITY", BIGDECIMAL_POSITIVE_INFINITY); - rb_define_const(rb_cBigDecimal, "NAN", BIGDECIMAL_NAN); - - /* instance methods */ - rb_define_method(rb_cBigDecimal, "precs", BigDecimal_prec, 0); - rb_define_method(rb_cBigDecimal, "precision", BigDecimal_precision, 0); - rb_define_method(rb_cBigDecimal, "scale", BigDecimal_scale, 0); - rb_define_method(rb_cBigDecimal, "precision_scale", BigDecimal_precision_scale, 0); - rb_define_method(rb_cBigDecimal, "n_significant_digits", BigDecimal_n_significant_digits, 0); - - rb_define_method(rb_cBigDecimal, "add", BigDecimal_add2, 2); - rb_define_method(rb_cBigDecimal, "sub", BigDecimal_sub2, 2); - rb_define_method(rb_cBigDecimal, "mult", BigDecimal_mult2, 2); - rb_define_method(rb_cBigDecimal, "div", BigDecimal_div3, -1); - rb_define_method(rb_cBigDecimal, "hash", BigDecimal_hash, 0); - rb_define_method(rb_cBigDecimal, "to_s", BigDecimal_to_s, -1); - rb_define_method(rb_cBigDecimal, "to_i", BigDecimal_to_i, 0); - rb_define_method(rb_cBigDecimal, "to_int", BigDecimal_to_i, 0); - rb_define_method(rb_cBigDecimal, "to_r", BigDecimal_to_r, 0); - rb_define_method(rb_cBigDecimal, "split", BigDecimal_split, 0); - rb_define_method(rb_cBigDecimal, "+", BigDecimal_add, 1); - rb_define_method(rb_cBigDecimal, "-", BigDecimal_sub, 1); - rb_define_method(rb_cBigDecimal, "+@", BigDecimal_uplus, 0); - rb_define_method(rb_cBigDecimal, "-@", BigDecimal_neg, 0); - rb_define_method(rb_cBigDecimal, "*", BigDecimal_mult, 1); - rb_define_method(rb_cBigDecimal, "/", BigDecimal_div, 1); - rb_define_method(rb_cBigDecimal, "quo", BigDecimal_quo, -1); - rb_define_method(rb_cBigDecimal, "%", BigDecimal_mod, 1); - rb_define_method(rb_cBigDecimal, "modulo", BigDecimal_mod, 1); - rb_define_method(rb_cBigDecimal, "remainder", BigDecimal_remainder, 1); - rb_define_method(rb_cBigDecimal, "divmod", BigDecimal_divmod, 1); - rb_define_method(rb_cBigDecimal, "clone", BigDecimal_clone, 0); - rb_define_method(rb_cBigDecimal, "dup", BigDecimal_clone, 0); - rb_define_method(rb_cBigDecimal, "to_f", BigDecimal_to_f, 0); - rb_define_method(rb_cBigDecimal, "abs", BigDecimal_abs, 0); - rb_define_method(rb_cBigDecimal, "sqrt", BigDecimal_sqrt, 1); - rb_define_method(rb_cBigDecimal, "fix", BigDecimal_fix, 0); - rb_define_method(rb_cBigDecimal, "round", BigDecimal_round, -1); - rb_define_method(rb_cBigDecimal, "frac", BigDecimal_frac, 0); - rb_define_method(rb_cBigDecimal, "floor", BigDecimal_floor, -1); - rb_define_method(rb_cBigDecimal, "ceil", BigDecimal_ceil, -1); - rb_define_method(rb_cBigDecimal, "power", BigDecimal_power, -1); - rb_define_method(rb_cBigDecimal, "**", BigDecimal_power_op, 1); - rb_define_method(rb_cBigDecimal, "<=>", BigDecimal_comp, 1); - rb_define_method(rb_cBigDecimal, "==", BigDecimal_eq, 1); - rb_define_method(rb_cBigDecimal, "===", BigDecimal_eq, 1); - rb_define_method(rb_cBigDecimal, "eql?", BigDecimal_eq, 1); - rb_define_method(rb_cBigDecimal, "<", BigDecimal_lt, 1); - rb_define_method(rb_cBigDecimal, "<=", BigDecimal_le, 1); - rb_define_method(rb_cBigDecimal, ">", BigDecimal_gt, 1); - rb_define_method(rb_cBigDecimal, ">=", BigDecimal_ge, 1); - rb_define_method(rb_cBigDecimal, "zero?", BigDecimal_zero, 0); - rb_define_method(rb_cBigDecimal, "nonzero?", BigDecimal_nonzero, 0); - rb_define_method(rb_cBigDecimal, "coerce", BigDecimal_coerce, 1); - rb_define_method(rb_cBigDecimal, "inspect", BigDecimal_inspect, 0); - rb_define_method(rb_cBigDecimal, "exponent", BigDecimal_exponent, 0); - rb_define_method(rb_cBigDecimal, "sign", BigDecimal_sign, 0); - rb_define_method(rb_cBigDecimal, "nan?", BigDecimal_IsNaN, 0); - rb_define_method(rb_cBigDecimal, "infinite?", BigDecimal_IsInfinite, 0); - rb_define_method(rb_cBigDecimal, "finite?", BigDecimal_IsFinite, 0); - rb_define_method(rb_cBigDecimal, "truncate", BigDecimal_truncate, -1); - rb_define_method(rb_cBigDecimal, "_dump", BigDecimal_dump, -1); - - rb_mBigMath = rb_define_module("BigMath"); - rb_define_singleton_method(rb_mBigMath, "exp", BigMath_s_exp, 2); - rb_define_singleton_method(rb_mBigMath, "log", BigMath_s_log, 2); - -#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 */ -} - -/* - * - * ============================================================================ - * - * vp_ routines begin from here. - * - * ============================================================================ - * - */ -#ifdef BIGDECIMAL_DEBUG -static int gfDebug = 1; /* Debug switch */ -#if 0 -static int gfCheckVal = 1; /* Value checking flag in VpNmlz() */ -#endif -#endif /* BIGDECIMAL_DEBUG */ - -static Real *VpConstOne; /* constant 1.0 */ -static Real *VpConstPt5; /* constant 0.5 */ -#define maxnr 100UL /* Maximum iterations for calculating sqrt. */ - /* used in VpSqrt() */ - -/* ETC */ -#define MemCmp(x,y,z) memcmp(x,y,z) -#define StrCmp(x,y) strcmp(x,y) - -enum op_sw { - OP_SW_ADD = 1, /* + */ - OP_SW_SUB, /* - */ - OP_SW_MULT, /* * */ - OP_SW_DIV /* / */ -}; - -static int VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw); -static int AddExponent(Real *a, SIGNED_VALUE n); -static DECDIG VpAddAbs(Real *a,Real *b,Real *c); -static DECDIG VpSubAbs(Real *a,Real *b,Real *c); -static size_t VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos, DECDIG *av, DECDIG *bv); -static int VpNmlz(Real *a); -static void VpFormatSt(char *psz, size_t fFmt); -static int VpRdup(Real *m, size_t ind_m); - -#ifdef BIGDECIMAL_DEBUG -# ifdef HAVE_RB_EXT_RACTOR_SAFE -# error Need to make rewiting gnAlloc atomic -# endif -static int gnAlloc = 0; /* Memory allocation counter */ -#endif /* BIGDECIMAL_DEBUG */ - -/* - * EXCEPTION Handling. - */ - -#define bigdecimal_set_thread_local_exception_mode(mode) \ - rb_thread_local_aset( \ - rb_thread_current(), \ - id_BigDecimal_exception_mode, \ - INT2FIX((int)(mode)) \ - ) - -static unsigned short -VpGetException (void) -{ - VALUE const vmode = rb_thread_local_aref( - rb_thread_current(), - id_BigDecimal_exception_mode - ); - - if (NIL_P(vmode)) { - bigdecimal_set_thread_local_exception_mode(BIGDECIMAL_EXCEPTION_MODE_DEFAULT); - return BIGDECIMAL_EXCEPTION_MODE_DEFAULT; - } - - return NUM2USHORT(vmode); -} - -static void -VpSetException(unsigned short f) -{ - bigdecimal_set_thread_local_exception_mode(f); -} - -static void -VpCheckException(Real *p, bool always) -{ - if (VpIsNaN(p)) { - VpException(VP_EXCEPTION_NaN, "Computation results in 'NaN' (Not a Number)", always); - } - else if (VpIsPosInf(p)) { - VpException(VP_EXCEPTION_INFINITY, "Computation results in 'Infinity'", always); - } - else if (VpIsNegInf(p)) { - VpException(VP_EXCEPTION_INFINITY, "Computation results in '-Infinity'", always); - } -} - -static VALUE -VpCheckGetValue(Real *p) -{ - VpCheckException(p, false); - return p->obj; -} - -/* - * Precision limit. - */ - -#define bigdecimal_set_thread_local_precision_limit(limit) \ - rb_thread_local_aset( \ - rb_thread_current(), \ - id_BigDecimal_precision_limit, \ - SIZET2NUM(limit) \ - ) -#define BIGDECIMAL_PRECISION_LIMIT_DEFAULT ((size_t)0) - -/* These 2 functions added at v1.1.7 */ -VP_EXPORT size_t -VpGetPrecLimit(void) -{ - VALUE const vlimit = rb_thread_local_aref( - rb_thread_current(), - id_BigDecimal_precision_limit - ); - - if (NIL_P(vlimit)) { - bigdecimal_set_thread_local_precision_limit(BIGDECIMAL_PRECISION_LIMIT_DEFAULT); - return BIGDECIMAL_PRECISION_LIMIT_DEFAULT; - } - - return NUM2SIZET(vlimit); -} - -VP_EXPORT size_t -VpSetPrecLimit(size_t n) -{ - size_t const s = VpGetPrecLimit(); - bigdecimal_set_thread_local_precision_limit(n); - return s; -} - -/* - * Rounding mode. - */ - -#define bigdecimal_set_thread_local_rounding_mode(mode) \ - rb_thread_local_aset( \ - rb_thread_current(), \ - id_BigDecimal_rounding_mode, \ - INT2FIX((int)(mode)) \ - ) - -VP_EXPORT unsigned short -VpGetRoundMode(void) -{ - VALUE const vmode = rb_thread_local_aref( - rb_thread_current(), - id_BigDecimal_rounding_mode - ); - - if (NIL_P(vmode)) { - bigdecimal_set_thread_local_rounding_mode(BIGDECIMAL_ROUNDING_MODE_DEFAULT); - return BIGDECIMAL_ROUNDING_MODE_DEFAULT; - } - - return NUM2USHORT(vmode); -} - -VP_EXPORT int -VpIsRoundMode(unsigned short n) -{ - switch (n) { - case VP_ROUND_UP: - case VP_ROUND_DOWN: - case VP_ROUND_HALF_UP: - case VP_ROUND_HALF_DOWN: - case VP_ROUND_CEIL: - case VP_ROUND_FLOOR: - case VP_ROUND_HALF_EVEN: - return 1; - - default: - return 0; - } -} - -VP_EXPORT unsigned short -VpSetRoundMode(unsigned short n) -{ - if (VpIsRoundMode(n)) { - bigdecimal_set_thread_local_rounding_mode(n); - return n; - } - - return VpGetRoundMode(); -} - -/* - * 0.0 & 1.0 generator - * These gZero_..... and gOne_..... can be any name - * referenced from nowhere except Zero() and One(). - * gZero_..... and gOne_..... must have global scope - * (to let the compiler know they may be changed in outside - * (... but not actually..)). - */ -volatile const double gOne_ABCED9B4_CE73__00400511F31D = 1.0; - -static double -One(void) -{ - return gOne_ABCED9B4_CE73__00400511F31D; -} - -/* - ---------------------------------------------------------------- - Value of sign in Real structure is reserved for future use. - short sign; - ==0 : NaN - 1 : Positive zero - -1 : Negative zero - 2 : Positive number - -2 : Negative number - 3 : Positive infinite number - -3 : Negative infinite number - ---------------------------------------------------------------- -*/ - -VP_EXPORT double -VpGetDoubleNaN(void) /* Returns the value of NaN */ -{ - return nan(""); -} - -VP_EXPORT double -VpGetDoublePosInf(void) /* Returns the value of +Infinity */ -{ - return HUGE_VAL; -} - -VP_EXPORT double -VpGetDoubleNegInf(void) /* Returns the value of -Infinity */ -{ - return -HUGE_VAL; -} - -VP_EXPORT double -VpGetDoubleNegZero(void) /* Returns the value of -0 */ -{ - static double nzero = 1000.0; - if (nzero != 0.0) nzero = (One()/VpGetDoubleNegInf()); - return nzero; -} - -#if 0 /* unused */ -VP_EXPORT int -VpIsNegDoubleZero(double v) -{ - double z = VpGetDoubleNegZero(); - return MemCmp(&v,&z,sizeof(v))==0; -} -#endif - -VP_EXPORT int -VpException(unsigned short f, const char *str,int always) -{ - unsigned short const exception_mode = VpGetException(); - - if (f == VP_EXCEPTION_OP) always = 1; - - if (always || (exception_mode & f)) { - switch(f) { - /* case VP_EXCEPTION_OVERFLOW: */ - case VP_EXCEPTION_ZERODIVIDE: - case VP_EXCEPTION_INFINITY: - case VP_EXCEPTION_NaN: - case VP_EXCEPTION_UNDERFLOW: - case VP_EXCEPTION_OP: - rb_raise(rb_eFloatDomainError, "%s", str); - break; - default: - rb_fatal("%s", str); - } - } - return 0; /* 0 Means VpException() raised no exception */ -} - -/* Throw exception or returns 0,when resulting c is Inf or NaN */ -/* sw=1:+ 2:- 3:* 4:/ */ -static int -VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw) -{ - if (VpIsNaN(a) || VpIsNaN(b)) { - /* at least a or b is NaN */ - VpSetNaN(c); - goto NaN; - } - - if (VpIsInf(a)) { - if (VpIsInf(b)) { - switch(sw) { - case OP_SW_ADD: /* + */ - if (VpGetSign(a) == VpGetSign(b)) { - VpSetInf(c, VpGetSign(a)); - goto Inf; - } - else { - VpSetNaN(c); - goto NaN; - } - case OP_SW_SUB: /* - */ - if (VpGetSign(a) != VpGetSign(b)) { - VpSetInf(c, VpGetSign(a)); - goto Inf; - } - else { - VpSetNaN(c); - goto NaN; - } - case OP_SW_MULT: /* * */ - VpSetInf(c, VpGetSign(a)*VpGetSign(b)); - goto Inf; - case OP_SW_DIV: /* / */ - VpSetNaN(c); - goto NaN; - } - VpSetNaN(c); - goto NaN; - } - /* Inf op Finite */ - switch(sw) { - case OP_SW_ADD: /* + */ - case OP_SW_SUB: /* - */ - VpSetInf(c, VpGetSign(a)); - break; - case OP_SW_MULT: /* * */ - if (VpIsZero(b)) { - VpSetNaN(c); - goto NaN; - } - VpSetInf(c, VpGetSign(a)*VpGetSign(b)); - break; - case OP_SW_DIV: /* / */ - VpSetInf(c, VpGetSign(a)*VpGetSign(b)); - } - goto Inf; - } - - if (VpIsInf(b)) { - switch(sw) { - case OP_SW_ADD: /* + */ - VpSetInf(c, VpGetSign(b)); - break; - case OP_SW_SUB: /* - */ - VpSetInf(c, -VpGetSign(b)); - break; - case OP_SW_MULT: /* * */ - if (VpIsZero(a)) { - VpSetNaN(c); - goto NaN; - } - VpSetInf(c, VpGetSign(a)*VpGetSign(b)); - break; - case OP_SW_DIV: /* / */ - VpSetZero(c, VpGetSign(a)*VpGetSign(b)); - } - goto Inf; - } - return 1; /* Results OK */ - -Inf: - if (VpIsPosInf(c)) { - return VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0); - } - else { - return VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 0); - } - -NaN: - return VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'", 0); -} - -/* - ---------------------------------------------------------------- -*/ - -/* - * returns number of chars needed to represent vp in specified format. - */ -VP_EXPORT size_t -VpNumOfChars(Real *vp,const char *pszFmt) -{ - SIGNED_VALUE ex; - size_t nc; - - if (vp == NULL) return BASE_FIG*2+6; - if (!VpIsDef(vp)) return 32; /* not sure,may be OK */ - - switch(*pszFmt) { - case 'F': - nc = BASE_FIG*(vp->Prec + 1)+2; - ex = vp->exponent; - if (ex < 0) { - nc += BASE_FIG*(size_t)(-ex); - } - else { - if ((size_t)ex > vp->Prec) { - nc += BASE_FIG*((size_t)ex - vp->Prec); - } - } - break; - case 'E': - /* fall through */ - default: - nc = BASE_FIG*(vp->Prec + 2)+6; /* 3: sign + exponent chars */ - } - return nc; -} - -/* - * Initializer for Vp routines and constants used. - * [Input] - * BaseVal: Base value(assigned to BASE) for Vp calculation. - * It must be the form BaseVal=10**n.(n=1,2,3,...) - * If Base <= 0L,then the BASE will be calculated so - * that BASE is as large as possible satisfying the - * relation MaxVal <= BASE*(BASE+1). Where the value - * MaxVal is the largest value which can be represented - * by one DECDIG word in the computer used. - * - * [Returns] - * BIGDECIMAL_DOUBLE_FIGURES ... OK - */ -VP_EXPORT size_t -VpInit(DECDIG BaseVal) -{ - /* Setup +/- Inf NaN -0 */ - VpGetDoubleNegZero(); - - /* 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; -#endif /* BIGDECIMAL_DEBUG */ - -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - printf("VpInit: BaseVal = %"PRIuDECDIG"\n", BaseVal); - printf("\tBASE = %"PRIuDECDIG"\n", BASE); - printf("\tHALF_BASE = %"PRIuDECDIG"\n", HALF_BASE); - printf("\tBASE1 = %"PRIuDECDIG"\n", BASE1); - printf("\tBASE_FIG = %u\n", BASE_FIG); - printf("\tBIGDECIMAL_DOUBLE_FIGURES = %d\n", BIGDECIMAL_DOUBLE_FIGURES); - } -#endif /* BIGDECIMAL_DEBUG */ - - return BIGDECIMAL_DOUBLE_FIGURES; -} - -VP_EXPORT Real * -VpOne(void) -{ - return VpConstOne; -} - -/* If exponent overflows,then raise exception or returns 0 */ -static int -AddExponent(Real *a, SIGNED_VALUE n) -{ - SIGNED_VALUE e = a->exponent; - SIGNED_VALUE m = e+n; - SIGNED_VALUE eb, mb; - if (e > 0) { - if (n > 0) { - if (MUL_OVERFLOW_SIGNED_VALUE_P(m, (SIGNED_VALUE)BASE_FIG) || - MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG)) - goto overflow; - mb = m*(SIGNED_VALUE)BASE_FIG; - eb = e*(SIGNED_VALUE)BASE_FIG; - if (eb - mb > 0) goto overflow; - } - } - else if (n < 0) { - if (MUL_OVERFLOW_SIGNED_VALUE_P(m, (SIGNED_VALUE)BASE_FIG) || - MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG)) - goto underflow; - mb = m*(SIGNED_VALUE)BASE_FIG; - eb = e*(SIGNED_VALUE)BASE_FIG; - if (mb - eb > 0) goto underflow; - } - a->exponent = m; - return 1; - -/* Overflow/Underflow ==> Raise exception or returns 0 */ -underflow: - VpSetZero(a, VpGetSign(a)); - return VpException(VP_EXCEPTION_UNDERFLOW, "Exponent underflow", 0); - -overflow: - VpSetInf(a, VpGetSign(a)); - return VpException(VP_EXCEPTION_OVERFLOW, "Exponent overflow", 0); -} - -Real * -bigdecimal_parse_special_string(const char *str) -{ - static const struct { - const char *str; - size_t len; - int sign; - } table[] = { - { SZ_INF, sizeof(SZ_INF) - 1, VP_SIGN_POSITIVE_INFINITE }, - { SZ_PINF, sizeof(SZ_PINF) - 1, VP_SIGN_POSITIVE_INFINITE }, - { SZ_NINF, sizeof(SZ_NINF) - 1, VP_SIGN_NEGATIVE_INFINITE }, - { SZ_NaN, sizeof(SZ_NaN) - 1, VP_SIGN_NaN } - }; - static const size_t table_length = sizeof(table) / sizeof(table[0]); - size_t i; - - for (i = 0; i < table_length; ++i) { - const char *p; - if (strncmp(str, table[i].str, table[i].len) != 0) { - continue; - } - - p = str + table[i].len; - while (*p && ISSPACE(*p)) ++p; - if (*p == '\0') { - Real *vp = rbd_allocate_struct(1); - vp->MaxPrec = 1; - switch (table[i].sign) { - default: - UNREACHABLE; break; - case VP_SIGN_POSITIVE_INFINITE: - VpSetPosInf(vp); - return vp; - case VP_SIGN_NEGATIVE_INFINITE: - VpSetNegInf(vp); - return vp; - case VP_SIGN_NaN: - VpSetNaN(vp); - return vp; - } - } - } - - return NULL; -} - -/* - * Allocates variable. - * [Input] - * 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 - * NULL be returned if memory allocation is failed,or any error. - */ -VP_EXPORT Real * -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; - VALUE buf; - - if (szVal == NULL) { - return_zero: - /* necessary to be able to store */ - /* at least mx digits. */ - /* szVal==NULL ==> allocate zero value. */ - 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 */ - buf = rb_str_tmp_new(strlen(szVal) + 1); - psz = RSTRING_PTR(buf); - - /* cursor: i for psz, and j for szVal */ - i = j = 0; - - /* Scanning: sign part */ - v = psz[i] = szVal[j]; - if ((v == '-') || (v == '+')) { - sign = -(v == '-'); - ++i; - ++j; - } - - /* Scanning: integer part */ - ni = 0; /* number of digits in the integer part */ - while ((v = psz[i] = szVal[j]) != '\0') { - if (!strict_p && ISSPACE(v)) { - v = psz[i] = '\0'; - break; - } - if (v == '_') { - if (ni > 0) { - v = szVal[j+1]; - if (v == '\0' || ISSPACE(v) || ISDIGIT(v)) { - ++j; - continue; - } - if (!strict_p) { - v = psz[i] = '\0'; - break; - } - } - goto invalid_value; - } - if (!ISDIGIT(v)) { - break; - } - ++ni; - ++i; - ++j; - } - - /* Scanning: fractional part */ - nf = 0; /* number of digits in the fractional part */ - ne = 0; /* number of digits in the exponential part */ - ipf = 0; /* index of the beginning of the fractional part */ - ipe = 0; /* index of the beginning of the exponential part */ - dot_seen = 0; - exp_seen = 0; - - if (v != '\0') { - /* Scanning fractional part */ - if ((psz[i] = szVal[j]) == '.') { - dot_seen = 1; - ++i; - ++j; - ipf = i; - while ((v = psz[i] = szVal[j]) != '\0') { - if (!strict_p && ISSPACE(v)) { - v = psz[i] = '\0'; - break; - } - if (v == '_') { - if (nf > 0 && ISDIGIT(szVal[j+1])) { - ++j; - continue; - } - if (!strict_p) { - v = psz[i] = '\0'; - if (nf == 0) { - dot_seen = 0; - } - break; - } - goto invalid_value; - } - if (!ISDIGIT(v)) break; - ++i; - ++j; - ++nf; - } - } - - /* Scanning exponential part */ - if (v != '\0') { - switch ((psz[i] = szVal[j])) { - case '\0': - break; - case 'e': case 'E': - case 'd': case 'D': - exp_seen = 1; - ++i; - ++j; - ipe = i; - v = psz[i] = szVal[j]; - if ((v == '-') || (v == '+')) { - ++i; - ++j; - } - while ((v = psz[i] = szVal[j]) != '\0') { - if (!strict_p && ISSPACE(v)) { - v = psz[i] = '\0'; - break; - } - if (v == '_') { - if (ne > 0 && ISDIGIT(szVal[j+1])) { - ++j; - continue; - } - if (!strict_p) { - v = psz[i] = '\0'; - if (ne == 0) { - exp_seen = 0; - } - break; - } - goto invalid_value; - } - if (!ISDIGIT(v)) break; - ++i; - ++j; - ++ne; - } - break; - default: - break; - } - } - - if (v != '\0') { - /* Scanning trailing spaces */ - while (ISSPACE(szVal[j])) ++j; - - /* Invalid character */ - if (szVal[j] && strict_p) { - goto invalid_value; - } - } - } - - psz[i] = '\0'; - - if (strict_p && (((ni == 0 || dot_seen) && nf == 0) || (exp_seen && ne == 0))) { - VALUE str; - invalid_value: - if (!strict_p) { - goto return_zero; - } - if (!exc) { - return NULL; - } - str = rb_str_new2(orig_szVal); - rb_raise(rb_eArgError, "invalid value for BigDecimal(): \"%"PRIsVALUE"\"", str); - } - - nalloc = (ni + nf + BASE_FIG - 1) / BASE_FIG + 1; /* set effective allocation */ - /* units for szVal[] */ - 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); - return vp; -} - -/* - * Assignment(c=a). - * [Input] - * a ... RHSV - * isw ... switch for assignment. - * c = a when isw > 0 - * c = -a when isw < 0 - * if c->MaxPrec < a->Prec,then round operation - * will be performed. - * [Output] - * c ... LHSV - */ -VP_EXPORT size_t -VpAsgn(Real *c, Real *a, int isw) -{ - size_t n; - if (VpIsNaN(a)) { - VpSetNaN(c); - return 0; - } - if (VpIsInf(a)) { - VpSetInf(c, isw * VpGetSign(a)); - return 0; - } - - /* check if the RHS is zero */ - if (!VpIsZero(a)) { - c->exponent = a->exponent; /* store exponent */ - VpSetSign(c, isw * VpGetSign(a)); /* set sign */ - n = (a->Prec < c->MaxPrec) ? (a->Prec) : (c->MaxPrec); - c->Prec = n; - memcpy(c->frac, a->frac, n * sizeof(DECDIG)); - /* Needs round ? */ - if (isw != 10) { - /* Not in ActiveRound */ - if(c->Prec < a->Prec) { - VpInternalRound(c, n, (n>0) ? a->frac[n-1] : 0, a->frac[n]); - } - else { - VpLimitRound(c,0); - } - } - } - else { - /* The value of 'a' is zero. */ - VpSetZero(c, isw * VpGetSign(a)); - return 1; - } - return c->Prec * BASE_FIG; -} - -/* - * c = a + b when operation = 1 or 2 - * c = a - b when operation = -1 or -2. - * Returns number of significant digits of c - */ -VP_EXPORT size_t -VpAddSub(Real *c, Real *a, Real *b, int operation) -{ - short sw, isw; - Real *a_ptr, *b_ptr; - size_t n, na, nb, i; - DECDIG mrv; - -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, "VpAddSub(enter) a=% \n", a); - VPrint(stdout, " b=% \n", b); - printf(" operation=%d\n", operation); - } -#endif /* BIGDECIMAL_DEBUG */ - - if (!VpIsDefOP(c, a, b, (operation > 0) ? OP_SW_ADD : OP_SW_SUB)) return 0; /* No significant digits */ - - /* check if a or b is zero */ - if (VpIsZero(a)) { - /* a is zero,then assign b to c */ - if (!VpIsZero(b)) { - VpAsgn(c, b, operation); - } - else { - /* Both a and b are zero. */ - if (VpGetSign(a) < 0 && operation * VpGetSign(b) < 0) { - /* -0 -0 */ - VpSetZero(c, -1); - } - else { - VpSetZero(c, 1); - } - return 1; /* 0: 1 significant digits */ - } - return c->Prec * BASE_FIG; - } - if (VpIsZero(b)) { - /* b is zero,then assign a to c. */ - VpAsgn(c, a, 1); - return c->Prec*BASE_FIG; - } - - if (operation < 0) sw = -1; - else sw = 1; - - /* compare absolute value. As a result,|a_ptr|>=|b_ptr| */ - if (a->exponent > b->exponent) { - a_ptr = a; - b_ptr = b; - } /* |a|>|b| */ - else if (a->exponent < b->exponent) { - a_ptr = b; - b_ptr = a; - } /* |a|<|b| */ - else { - /* Exponent part of a and b is the same,then compare fraction */ - /* part */ - na = a->Prec; - nb = b->Prec; - n = Min(na, nb); - for (i=0; i < n; ++i) { - if (a->frac[i] > b->frac[i]) { - a_ptr = a; - b_ptr = b; - goto end_if; - } - else if (a->frac[i] < b->frac[i]) { - a_ptr = b; - b_ptr = a; - goto end_if; - } - } - if (na > nb) { - a_ptr = a; - b_ptr = b; - goto end_if; - } - else if (na < nb) { - a_ptr = b; - b_ptr = a; - goto end_if; - } - /* |a| == |b| */ - if (VpGetSign(a) + sw *VpGetSign(b) == 0) { - VpSetZero(c, 1); /* abs(a)=abs(b) and operation = '-' */ - return c->Prec * BASE_FIG; - } - a_ptr = a; - b_ptr = b; - } - -end_if: - isw = VpGetSign(a) + sw *VpGetSign(b); - /* - * isw = 0 ...( 1)+(-1),( 1)-( 1),(-1)+(1),(-1)-(-1) - * = 2 ...( 1)+( 1),( 1)-(-1) - * =-2 ...(-1)+(-1),(-1)-( 1) - * If isw==0, then c =(Sign a_ptr)(|a_ptr|-|b_ptr|) - * else c =(Sign ofisw)(|a_ptr|+|b_ptr|) - */ - if (isw) { /* addition */ - VpSetSign(c, 1); - mrv = VpAddAbs(a_ptr, b_ptr, c); - VpSetSign(c, isw / 2); - } - else { /* subtraction */ - VpSetSign(c, 1); - mrv = VpSubAbs(a_ptr, b_ptr, c); - if (a_ptr == a) { - VpSetSign(c,VpGetSign(a)); - } - else { - VpSetSign(c, VpGetSign(a_ptr) * sw); - } - } - VpInternalRound(c, 0, (c->Prec > 0) ? c->frac[c->Prec-1] : 0, mrv); - -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, "VpAddSub(result) c=% \n", c); - VPrint(stdout, " a=% \n", a); - VPrint(stdout, " b=% \n", b); - printf(" operation=%d\n", operation); - } -#endif /* BIGDECIMAL_DEBUG */ - return c->Prec * BASE_FIG; -} - -/* - * Addition of two values with variable precision - * a and b assuming abs(a)>abs(b). - * c = abs(a) + abs(b) ; where |a|>=|b| - */ -static DECDIG -VpAddAbs(Real *a, Real *b, Real *c) -{ - size_t word_shift; - size_t ap; - size_t bp; - size_t cp; - size_t a_pos; - size_t b_pos, b_pos_with_word_shift; - size_t c_pos; - DECDIG av, bv, carry, mrv; - -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, "VpAddAbs called: a = %\n", a); - VPrint(stdout, " b = %\n", b); - } -#endif /* BIGDECIMAL_DEBUG */ - - word_shift = VpSetPTR(a, b, c, &ap, &bp, &cp, &av, &bv); - a_pos = ap; - b_pos = bp; - c_pos = cp; - - if (word_shift == (size_t)-1L) return 0; /* Overflow */ - if (b_pos == (size_t)-1L) goto Assign_a; - - mrv = av + bv; /* Most right val. Used for round. */ - - /* Just assign the last few digits of b to c because a has no */ - /* corresponding digits to be added. */ - if (b_pos > 0) { - while (b_pos > 0 && b_pos + word_shift > a_pos) { - c->frac[--c_pos] = b->frac[--b_pos]; - } - } - if (b_pos == 0 && word_shift > a_pos) { - while (word_shift-- > a_pos) { - c->frac[--c_pos] = 0; - } - } - - /* Just assign the last few digits of a to c because b has no */ - /* corresponding digits to be added. */ - b_pos_with_word_shift = b_pos + word_shift; - while (a_pos > b_pos_with_word_shift) { - c->frac[--c_pos] = a->frac[--a_pos]; - } - carry = 0; /* set first carry be zero */ - - /* Now perform addition until every digits of b will be */ - /* exhausted. */ - while (b_pos > 0) { - c->frac[--c_pos] = a->frac[--a_pos] + b->frac[--b_pos] + carry; - if (c->frac[c_pos] >= BASE) { - c->frac[c_pos] -= BASE; - carry = 1; - } - else { - carry = 0; - } - } - - /* Just assign the first few digits of a with considering */ - /* the carry obtained so far because b has been exhausted. */ - while (a_pos > 0) { - c->frac[--c_pos] = a->frac[--a_pos] + carry; - if (c->frac[c_pos] >= BASE) { - c->frac[c_pos] -= BASE; - carry = 1; - } - else { - carry = 0; - } - } - if (c_pos) c->frac[c_pos - 1] += carry; - goto Exit; - -Assign_a: - VpAsgn(c, a, 1); - mrv = 0; - -Exit: - -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, "VpAddAbs exit: c=% \n", c); - } -#endif /* BIGDECIMAL_DEBUG */ - return mrv; -} - -/* - * c = abs(a) - abs(b) - */ -static DECDIG -VpSubAbs(Real *a, Real *b, Real *c) -{ - size_t word_shift; - size_t ap; - size_t bp; - size_t cp; - size_t a_pos; - size_t b_pos, b_pos_with_word_shift; - size_t c_pos; - DECDIG av, bv, borrow, mrv; - -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, "VpSubAbs called: a = %\n", a); - VPrint(stdout, " b = %\n", b); - } -#endif /* BIGDECIMAL_DEBUG */ - - word_shift = VpSetPTR(a, b, c, &ap, &bp, &cp, &av, &bv); - a_pos = ap; - b_pos = bp; - c_pos = cp; - if (word_shift == (size_t)-1L) return 0; /* Overflow */ - if (b_pos == (size_t)-1L) goto Assign_a; - - if (av >= bv) { - mrv = av - bv; - borrow = 0; - } - else { - mrv = 0; - borrow = 1; - } - - /* Just assign the values which are the BASE subtracted by */ - /* each of the last few digits of the b because the a has no */ - /* corresponding digits to be subtracted. */ - if (b_pos + word_shift > a_pos) { - while (b_pos > 0 && b_pos + word_shift > a_pos) { - c->frac[--c_pos] = BASE - b->frac[--b_pos] - borrow; - borrow = 1; - } - if (b_pos == 0) { - while (word_shift > a_pos) { - --word_shift; - c->frac[--c_pos] = BASE - borrow; - borrow = 1; - } - } - } - /* Just assign the last few digits of a to c because b has no */ - /* corresponding digits to subtract. */ - - b_pos_with_word_shift = b_pos + word_shift; - while (a_pos > b_pos_with_word_shift) { - c->frac[--c_pos] = a->frac[--a_pos]; - } - - /* Now perform subtraction until every digits of b will be */ - /* exhausted. */ - while (b_pos > 0) { - --c_pos; - if (a->frac[--a_pos] < b->frac[--b_pos] + borrow) { - c->frac[c_pos] = BASE + a->frac[a_pos] - b->frac[b_pos] - borrow; - borrow = 1; - } - else { - c->frac[c_pos] = a->frac[a_pos] - b->frac[b_pos] - borrow; - borrow = 0; - } - } - - /* Just assign the first few digits of a with considering */ - /* the borrow obtained so far because b has been exhausted. */ - while (a_pos > 0) { - --c_pos; - if (a->frac[--a_pos] < borrow) { - c->frac[c_pos] = BASE + a->frac[a_pos] - borrow; - borrow = 1; - } - else { - c->frac[c_pos] = a->frac[a_pos] - borrow; - borrow = 0; - } - } - if (c_pos) c->frac[c_pos - 1] -= borrow; - goto Exit; - -Assign_a: - VpAsgn(c, a, 1); - mrv = 0; - -Exit: -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, "VpSubAbs exit: c=% \n", c); - } -#endif /* BIGDECIMAL_DEBUG */ - return mrv; -} - -/* - * Note: If(av+bv)>= HALF_BASE,then 1 will be added to the least significant - * digit of c(In case of addition). - * ------------------------- figure of output ----------------------------------- - * a = xxxxxxxxxxx - * b = xxxxxxxxxx - * c =xxxxxxxxxxxxxxx - * word_shift = | | - * right_word = | | (Total digits in RHSV) - * left_word = | | (Total digits in LHSV) - * a_pos = | - * b_pos = | - * c_pos = | - */ -static size_t -VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos, DECDIG *av, DECDIG *bv) -{ - size_t left_word, right_word, word_shift; - - size_t const round_limit = (VpGetPrecLimit() + BASE_FIG - 1) / BASE_FIG; - - assert(a->exponent >= b->exponent); - - c->frac[0] = 0; - *av = *bv = 0; - - word_shift = (a->exponent - b->exponent); - left_word = b->Prec + word_shift; - right_word = Max(a->Prec, left_word); - left_word = c->MaxPrec - 1; /* -1 ... prepare for round up */ - - /* - * check if 'round' is needed. - */ - if (right_word > left_word) { /* round ? */ - /*--------------------------------- - * Actual size of a = xxxxxxAxx - * Actual size of b = xxxBxxxxx - * Max. size of c = xxxxxx - * Round off = |-----| - * c_pos = | - * right_word = | - * a_pos = | - */ - *c_pos = right_word = left_word + 1; /* Set resulting precision */ - /* be equal to that of c */ - if (a->Prec >= c->MaxPrec) { - /* - * a = xxxxxxAxxx - * c = xxxxxx - * a_pos = | - */ - *a_pos = left_word; - if (*a_pos <= round_limit) { - *av = a->frac[*a_pos]; /* av is 'A' shown in above. */ - } - } - else { - /* - * a = xxxxxxx - * c = xxxxxxxxxx - * a_pos = | - */ - *a_pos = a->Prec; - } - if (b->Prec + word_shift >= c->MaxPrec) { - /* - * a = xxxxxxxxx - * b = xxxxxxxBxxx - * c = xxxxxxxxxxx - * b_pos = | - */ - if (c->MaxPrec >= word_shift + 1) { - *b_pos = c->MaxPrec - word_shift - 1; - if (*b_pos + word_shift <= round_limit) { - *bv = b->frac[*b_pos]; - } - } - else { - *b_pos = -1L; - } - } - else { - /* - * a = xxxxxxxxxxxxxxxx - * b = xxxxxx - * c = xxxxxxxxxxxxx - * b_pos = | - */ - *b_pos = b->Prec; - } - } - else { /* The MaxPrec of c - 1 > The Prec of a + b */ - /* - * a = xxxxxxx - * b = xxxxxx - * c = xxxxxxxxxxx - * c_pos = | - */ - *b_pos = b->Prec; - *a_pos = a->Prec; - *c_pos = right_word + 1; - } - c->Prec = *c_pos; - c->exponent = a->exponent; - if (!AddExponent(c, 1)) return (size_t)-1L; - return word_shift; -} - -/* - * Return number of significant digits - * c = a * b , Where a = a0a1a2 ... an - * b = b0b1b2 ... bm - * c = c0c1c2 ... cl - * a0 a1 ... an * bm - * a0 a1 ... an * bm-1 - * . . . - * . . . - * a0 a1 .... an * b0 - * +_____________________________ - * c0 c1 c2 ...... cl - * nc <---| - * MaxAB |--------------------| - */ -VP_EXPORT size_t -VpMult(Real *c, Real *a, Real *b) -{ - size_t MxIndA, MxIndB, MxIndAB, MxIndC; - size_t ind_c, i, ii, nc; - size_t ind_as, ind_ae, ind_bs; - DECDIG carry; - DECDIG_DBL s; - Real *w; - -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, "VpMult(Enter): a=% \n", a); - VPrint(stdout, " b=% \n", b); - } -#endif /* BIGDECIMAL_DEBUG */ - - if (!VpIsDefOP(c, a, b, OP_SW_MULT)) return 0; /* No significant digit */ - - if (VpIsZero(a) || VpIsZero(b)) { - /* at least a or b is zero */ - VpSetZero(c, VpGetSign(a) * VpGetSign(b)); - return 1; /* 0: 1 significant digit */ - } - - if (VpIsOne(a)) { - VpAsgn(c, b, VpGetSign(a)); - goto Exit; - } - if (VpIsOne(b)) { - VpAsgn(c, a, VpGetSign(b)); - goto Exit; - } - if (b->Prec > a->Prec) { - /* Adjust so that digits(a)>digits(b) */ - w = a; - a = b; - b = w; - } - w = NULL; - MxIndA = a->Prec - 1; - MxIndB = b->Prec - 1; - MxIndC = c->MaxPrec - 1; - MxIndAB = a->Prec + b->Prec - 1; - - if (MxIndC < MxIndAB) { /* The Max. prec. of c < Prec(a)+Prec(b) */ - w = c; - c = NewZeroNolimit(1, (size_t)((MxIndAB + 1) * BASE_FIG)); - MxIndC = MxIndAB; - } - - /* set LHSV c info */ - - c->exponent = a->exponent; /* set exponent */ - if (!AddExponent(c, b->exponent)) { - if (w) rbd_free_struct(c); - return 0; - } - VpSetSign(c, VpGetSign(a) * VpGetSign(b)); /* set sign */ - carry = 0; - nc = ind_c = MxIndAB; - memset(c->frac, 0, (nc + 1) * sizeof(DECDIG)); /* Initialize c */ - c->Prec = nc + 1; /* set precision */ - for (nc = 0; nc < MxIndAB; ++nc, --ind_c) { - if (nc < MxIndB) { /* The left triangle of the Fig. */ - ind_as = MxIndA - nc; - ind_ae = MxIndA; - ind_bs = MxIndB; - } - else if (nc <= MxIndA) { /* The middle rectangular of the Fig. */ - ind_as = MxIndA - nc; - ind_ae = MxIndA - (nc - MxIndB); - ind_bs = MxIndB; - } - else /* if (nc > MxIndA) */ { /* The right triangle of the Fig. */ - ind_as = 0; - ind_ae = MxIndAB - nc - 1; - ind_bs = MxIndB - (nc - MxIndA); - } - - for (i = ind_as; i <= ind_ae; ++i) { - s = (DECDIG_DBL)a->frac[i] * b->frac[ind_bs--]; - carry = (DECDIG)(s / BASE); - s -= (DECDIG_DBL)carry * BASE; - c->frac[ind_c] += (DECDIG)s; - if (c->frac[ind_c] >= BASE) { - s = c->frac[ind_c] / BASE; - carry += (DECDIG)s; - c->frac[ind_c] -= (DECDIG)(s * BASE); - } - if (carry) { - ii = ind_c; - while (ii-- > 0) { - c->frac[ii] += carry; - if (c->frac[ii] >= BASE) { - carry = c->frac[ii] / BASE; - c->frac[ii] -= (carry * BASE); - } - else { - break; - } - } - } - } - } - if (w != NULL) { /* free work variable */ - VpNmlz(c); - VpAsgn(w, c, 1); - rbd_free_struct(c); - c = w; - } - else { - VpLimitRound(c,0); - } - -Exit: -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, "VpMult(c=a*b): c=% \n", c); - VPrint(stdout, " a=% \n", a); - VPrint(stdout, " b=% \n", b); - } -#endif /*BIGDECIMAL_DEBUG */ - return c->Prec*BASE_FIG; -} - -/* - * c = a / b, remainder = r - */ -VP_EXPORT size_t -VpDivd(Real *c, Real *r, Real *a, Real *b) -{ - size_t word_a, word_b, word_c, word_r; - size_t i, n, ind_a, ind_b, ind_c, ind_r; - size_t nLoop; - DECDIG_DBL q, b1, b1p1, b1b2, b1b2p1, r1r2; - DECDIG borrow, borrow1, borrow2; - DECDIG_DBL qb; - -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, " VpDivd(c=a/b) a=% \n", a); - VPrint(stdout, " b=% \n", b); - } -#endif /*BIGDECIMAL_DEBUG */ - - VpSetNaN(r); - if (!VpIsDefOP(c, a, b, OP_SW_DIV)) goto Exit; - if (VpIsZero(a) && VpIsZero(b)) { - VpSetNaN(c); - return VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'", 0); - } - if (VpIsZero(b)) { - VpSetInf(c, VpGetSign(a) * VpGetSign(b)); - return VpException(VP_EXCEPTION_ZERODIVIDE, "Divide by zero", 0); - } - if (VpIsZero(a)) { - /* numerator a is zero */ - VpSetZero(c, VpGetSign(a) * VpGetSign(b)); - VpSetZero(r, VpGetSign(a) * VpGetSign(b)); - goto Exit; - } - if (VpIsOne(b)) { - /* divide by one */ - VpAsgn(c, a, VpGetSign(b)); - VpSetZero(r, VpGetSign(a)); - goto Exit; - } - - word_a = a->Prec; - word_b = b->Prec; - word_c = c->MaxPrec; - word_r = r->MaxPrec; - - if (word_a >= word_r) goto space_error; - - ind_r = 1; - r->frac[0] = 0; - while (ind_r <= word_a) { - r->frac[ind_r] = a->frac[ind_r - 1]; - ++ind_r; - } - while (ind_r < word_r) r->frac[ind_r++] = 0; - - ind_c = 0; - while (ind_c < word_c) c->frac[ind_c++] = 0; - - /* initial procedure */ - b1 = b1p1 = b->frac[0]; - if (b->Prec <= 1) { - b1b2p1 = b1b2 = b1p1 * BASE; - } - else { - b1p1 = b1 + 1; - b1b2p1 = b1b2 = b1 * BASE + b->frac[1]; - if (b->Prec > 2) ++b1b2p1; - } - - /* */ - /* loop start */ - ind_c = word_r - 1; - nLoop = Min(word_c,ind_c); - ind_c = 1; - while (ind_c < nLoop) { - if (r->frac[ind_c] == 0) { - ++ind_c; - continue; - } - r1r2 = (DECDIG_DBL)r->frac[ind_c] * BASE + r->frac[ind_c + 1]; - if (r1r2 == b1b2) { - /* The first two word digits is the same */ - ind_b = 2; - ind_a = ind_c + 2; - while (ind_b < word_b) { - if (r->frac[ind_a] < b->frac[ind_b]) goto div_b1p1; - if (r->frac[ind_a] > b->frac[ind_b]) break; - ++ind_a; - ++ind_b; - } - /* The first few word digits of r and b is the same and */ - /* the first different word digit of w is greater than that */ - /* of b, so quotient is 1 and just subtract b from r. */ - borrow = 0; /* quotient=1, then just r-b */ - ind_b = b->Prec - 1; - ind_r = ind_c + ind_b; - if (ind_r >= word_r) goto space_error; - n = ind_b; - for (i = 0; i <= n; ++i) { - if (r->frac[ind_r] < b->frac[ind_b] + borrow) { - r->frac[ind_r] += (BASE - (b->frac[ind_b] + borrow)); - borrow = 1; - } - else { - r->frac[ind_r] = r->frac[ind_r] - b->frac[ind_b] - borrow; - borrow = 0; - } - --ind_r; - --ind_b; - } - ++c->frac[ind_c]; - goto carry; - } - /* The first two word digits is not the same, */ - /* then compare magnitude, and divide actually. */ - if (r1r2 >= b1b2p1) { - q = r1r2 / b1b2p1; /* q == (DECDIG)q */ - c->frac[ind_c] += (DECDIG)q; - ind_r = b->Prec + ind_c - 1; - goto sub_mult; - } - -div_b1p1: - if (ind_c + 1 >= word_c) goto out_side; - q = r1r2 / b1p1; /* q == (DECDIG)q */ - c->frac[ind_c + 1] += (DECDIG)q; - ind_r = b->Prec + ind_c; - -sub_mult: - borrow1 = borrow2 = 0; - ind_b = word_b - 1; - if (ind_r >= word_r) goto space_error; - n = ind_b; - for (i = 0; i <= n; ++i) { - /* now, perform r = r - q * b */ - qb = q * b->frac[ind_b]; - if (qb < BASE) borrow1 = 0; - else { - borrow1 = (DECDIG)(qb / BASE); - qb -= (DECDIG_DBL)borrow1 * BASE; /* get qb < BASE */ - } - if(r->frac[ind_r] < qb) { - r->frac[ind_r] += (DECDIG)(BASE - qb); - borrow2 = borrow2 + borrow1 + 1; - } - else { - r->frac[ind_r] -= (DECDIG)qb; - borrow2 += borrow1; - } - if (borrow2) { - if(r->frac[ind_r - 1] < borrow2) { - r->frac[ind_r - 1] += (BASE - borrow2); - borrow2 = 1; - } - else { - r->frac[ind_r - 1] -= borrow2; - borrow2 = 0; - } - } - --ind_r; - --ind_b; - } - - r->frac[ind_r] -= borrow2; -carry: - ind_r = ind_c; - while (c->frac[ind_r] >= BASE) { - c->frac[ind_r] -= BASE; - --ind_r; - ++c->frac[ind_r]; - } - } - /* End of operation, now final arrangement */ -out_side: - c->Prec = word_c; - c->exponent = a->exponent; - if (!AddExponent(c, 2)) return 0; - if (!AddExponent(c, -(b->exponent))) return 0; - - VpSetSign(c, VpGetSign(a) * VpGetSign(b)); - VpNmlz(c); /* normalize c */ - r->Prec = word_r; - r->exponent = a->exponent; - if (!AddExponent(r, 1)) return 0; - VpSetSign(r, VpGetSign(a)); - VpNmlz(r); /* normalize r(remainder) */ - goto Exit; - -space_error: -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - printf(" word_a=%"PRIuSIZE"\n", word_a); - printf(" word_b=%"PRIuSIZE"\n", word_b); - printf(" word_c=%"PRIuSIZE"\n", word_c); - printf(" word_r=%"PRIuSIZE"\n", word_r); - printf(" ind_r =%"PRIuSIZE"\n", ind_r); - } -#endif /* BIGDECIMAL_DEBUG */ - rb_bug("ERROR(VpDivd): space for remainder too small."); - -Exit: -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, " VpDivd(c=a/b), c=% \n", c); - VPrint(stdout, " r=% \n", r); - } -#endif /* BIGDECIMAL_DEBUG */ - return c->Prec * BASE_FIG; -} - -/* - * Input a = 00000xxxxxxxx En(5 preceding zeros) - * Output a = xxxxxxxx En-5 - */ -static int -VpNmlz(Real *a) -{ - size_t ind_a, i; - - if (!VpIsDef(a)) goto NoVal; - if (VpIsZero(a)) goto NoVal; - - ind_a = a->Prec; - while (ind_a--) { - if (a->frac[ind_a]) { - a->Prec = ind_a + 1; - i = 0; - while (a->frac[i] == 0) ++i; /* skip the first few zeros */ - if (i) { - a->Prec -= i; - if (!AddExponent(a, -(SIGNED_VALUE)i)) return 0; - memmove(&a->frac[0], &a->frac[i], a->Prec*sizeof(DECDIG)); - } - return 1; - } - } - /* a is zero(no non-zero digit) */ - VpSetZero(a, VpGetSign(a)); - return 0; - -NoVal: - a->frac[0] = 0; - a->Prec = 1; - return 0; -} - -/* - * VpComp = 0 ... if a=b, - * Pos ... a>b, - * Neg ... asign - b->sign; - else e = a->sign; - - if (e > 0) return 1; - else if (e < 0) return -1; - else return 0; - } - if (!VpIsDef(b)) { - e = -b->sign; - if (e > 0) return 1; - else return -1; - } - /* Zero check */ - if (VpIsZero(a)) { - if (VpIsZero(b)) return 0; /* both zero */ - val = -VpGetSign(b); - goto Exit; - } - if (VpIsZero(b)) { - val = VpGetSign(a); - goto Exit; - } - - /* compare sign */ - if (VpGetSign(a) > VpGetSign(b)) { - val = 1; /* a>b */ - goto Exit; - } - if (VpGetSign(a) < VpGetSign(b)) { - val = -1; /* aexponent > b->exponent) { - val = VpGetSign(a); - goto Exit; - } - if (a->exponent < b->exponent) { - val = -VpGetSign(b); - goto Exit; - } - - /* a and b have same exponent, then compare their significand. */ - mx = (a->Prec < b->Prec) ? a->Prec : b->Prec; - ind = 0; - while (ind < mx) { - if (a->frac[ind] > b->frac[ind]) { - val = VpGetSign(a); - goto Exit; - } - if (a->frac[ind] < b->frac[ind]) { - val = -VpGetSign(b); - goto Exit; - } - ++ind; - } - if (a->Prec > b->Prec) { - val = VpGetSign(a); - } - else if (a->Prec < b->Prec) { - val = -VpGetSign(b); - } - -Exit: - if (val > 1) val = 1; - else if (val < -1) val = -1; - -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, " VpComp a=%\n", a); - VPrint(stdout, " b=%\n", b); - printf(" ans=%d\n", val); - } -#endif /* BIGDECIMAL_DEBUG */ - return (int)val; -} - -/* - * cntl_chr ... ASCIIZ Character, print control characters - * Available control codes: - * % ... VP variable. To print '%', use '%%'. - * \n ... new line - * \b ... backspace - * \t ... tab - * Note: % must not appear more than once - * a ... VP variable to be printed - */ -static int -VPrint(FILE *fp, const char *cntl_chr, Real *a) -{ - size_t i, j, nc, nd, ZeroSup, sep = 10; - DECDIG m, e, nn; - - j = 0; - nd = nc = 0; /* nd : number of digits in fraction part(every 10 digits, */ - /* nd<=10). */ - /* 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; - - 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", %"PRIuSIZE", %"PRIuSIZE")", 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; -} - -static void -VpFormatSt(char *psz, size_t fFmt) -{ - size_t ie, i, nf = 0; - char ch; - - if (fFmt == 0) return; - - ie = strlen(psz); - for (i = 0; i < ie; ++i) { - ch = psz[i]; - if (!ch) break; - if (ISSPACE(ch) || ch=='-' || ch=='+') continue; - if (ch == '.') { nf = 0; continue; } - if (ch == 'E' || ch == 'e') break; - - if (++nf > fFmt) { - memmove(psz + i + 1, psz + i, ie - i + 1); - ++ie; - nf = 0; - psz[i] = ' '; - } - } -} - -VP_EXPORT ssize_t -VpExponent10(Real *a) -{ - ssize_t ex; - size_t n; - - if (!VpHasVal(a)) return 0; - - ex = a->exponent * (ssize_t)BASE_FIG; - n = BASE1; - while ((a->frac[0] / n) == 0) { - --ex; - n /= 10; - } - return ex; -} - -VP_EXPORT void -VpSzMantissa(Real *a, char *buf, size_t buflen) -{ - size_t i, n, ZeroSup; - DECDIG_DBL m, e, nn; - - if (VpIsNaN(a)) { - snprintf(buf, buflen, SZ_NaN); - return; - } - if (VpIsPosInf(a)) { - snprintf(buf, buflen, SZ_INF); - return; - } - if (VpIsNegInf(a)) { - 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)) *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)) snprintf(buf, buflen, "0"); - else snprintf(buf, buflen, "-0"); - } -} - -VP_EXPORT int -VpToSpecialString(Real *a, char *buf, size_t buflen, int fPlus) -/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */ -{ - if (VpIsNaN(a)) { - snprintf(buf, buflen, SZ_NaN); - return 1; - } - - if (VpIsPosInf(a)) { - if (fPlus == 1) { - *buf++ = ' '; - } - else if (fPlus == 2) { - *buf++ = '+'; - } - snprintf(buf, buflen, SZ_INF); - return 1; - } - if (VpIsNegInf(a)) { - snprintf(buf, buflen, SZ_NINF); - return 1; - } - if (VpIsZero(a)) { - 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 *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 *p = buf; - size_t plen = buflen; - ssize_t ex; - - if (VpToSpecialString(a, buf, buflen, fPlus)) return; - - ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */ - -#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); - - n = a->Prec; - for (i = 0; i < n; ++i) { - 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; - } - while (p - 1 > buf && p[-1] == '0') { - *(--p) = '\0'; - ++plen; - } - snprintf(p, plen, "e%"PRIdSIZE, ex); - if (fFmt) VpFormatSt(buf, fFmt); - - overflow: - return; -#undef ADVANCE -} - -VP_EXPORT void -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; - char *p = buf; - size_t plen = buflen, delim = fFmt; - ssize_t ex; - - if (VpToSpecialString(a, buf, buflen, fPlus)) return; - -#define APPEND(c, group) do { \ - if (plen < 1) goto overflow; \ - if (group && delim == 0) { \ - *p = ' '; \ - p += 1; \ - plen -= 1; \ - } \ - if (plen < 1) goto overflow; \ - *p = c; \ - p += 1; \ - plen -= 1; \ - if (group) delim = (delim + 1) % fFmt; \ -} while (0) - - - if (BIGDECIMAL_NEGATIVE_P(a)) { - APPEND('-', false); - } - else if (fPlus == 1) { - APPEND(' ', false); - } - else if (fPlus == 2) { - APPEND('+', false); - } - - n = a->Prec; - ex = a->exponent; - if (ex <= 0) { - APPEND('0', false); - APPEND('.', false); - } - while (ex < 0) { - for (i=0; i < BASE_FIG; ++i) { - APPEND('0', fFmt > 0); - } - ++ex; - } - - for (i = 0; i < n; ++i) { - m = BASE1; - e = a->frac[i]; - if (i == 0 && ex > 0) { - for (delim = 0; e / m == 0; delim++) { - m /= 10; - } - if (fFmt > 0) { - delim = 2*fFmt - (ex * BASE_FIG - delim) % fFmt; - } - } - while (m && (e || (i < n - 1) || ex > 0)) { - APPEND((char)(e / m + '0'), fFmt > 0); - e %= m; - m /= 10; - } - if (--ex == 0) { - APPEND('.', false); - delim = fFmt; - } - } - - while (ex > 0) { - for (i=0; i < BASE_FIG; ++i) { - APPEND('0', fFmt > 0); - } - if (--ex == 0) { - APPEND('.', false); - } - } - - *p = '\0'; - if (p - 1 > buf && p[-1] == '.') { - snprintf(p, plen, "0"); - } - - overflow: - return; -#undef APPEND -} - -/* - * [Output] - * a[] ... variable to be assigned the value. - * [Input] - * int_chr[] ... integer part(may include '+/-'). - * ni ... number of characters in int_chr[],not including '+/-'. - * frac[] ... fraction part. - * nf ... number of characters in frac[]. - * exp_chr[] ... exponent part(including '+/-'). - * ne ... number of characters in exp_chr[],not including '+/-'. - */ -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) -{ - size_t i, j, ind_a, ma, mi, me; - SIGNED_VALUE e, es, eb, ef; - int sign, signe, exponent_overflow; - - /* get exponent part */ - e = 0; - ma = a->MaxPrec; - mi = ni; - me = ne; - signe = 1; - exponent_overflow = 0; - memset(a->frac, 0, ma * sizeof(DECDIG)); - if (ne > 0) { - i = 0; - if (exp_chr[0] == '-') { - signe = -1; - ++i; - ++me; - } - else if (exp_chr[0] == '+') { - ++i; - ++me; - } - while (i < me) { - if (MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG)) { - es = e; - goto exp_overflow; - } - es = e * (SIGNED_VALUE)BASE_FIG; - if (MUL_OVERFLOW_SIGNED_VALUE_P(e, 10) || - SIGNED_VALUE_MAX - (exp_chr[i] - '0') < e * 10) - goto exp_overflow; - e = e * 10 + exp_chr[i] - '0'; - if (MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG)) - goto exp_overflow; - if (es > (SIGNED_VALUE)(e * BASE_FIG)) { - exp_overflow: - exponent_overflow = 1; - e = es; /* keep sign */ - break; - } - ++i; - } - } - - /* get integer part */ - i = 0; - sign = 1; - if (1 /*ni >= 0*/) { - if (int_chr[0] == '-') { - sign = -1; - ++i; - ++mi; - } - else if (int_chr[0] == '+') { - ++i; - ++mi; - } - } - - e = signe * e; /* e: The value of exponent part. */ - e = e + ni; /* set actual exponent size. */ - - if (e > 0) signe = 1; - else signe = -1; - - /* Adjust the exponent so that it is the multiple of BASE_FIG. */ - j = 0; - ef = 1; - while (ef) { - if (e >= 0) eb = e; - else eb = -e; - ef = eb / (SIGNED_VALUE)BASE_FIG; - ef = eb - ef * (SIGNED_VALUE)BASE_FIG; - if (ef) { - ++j; /* Means to add one more preceding zero */ - ++e; - } - } - - eb = e / (SIGNED_VALUE)BASE_FIG; - - if (exponent_overflow) { - int zero = 1; - for ( ; i < mi && zero; i++) zero = int_chr[i] == '0'; - for (i = 0; i < nf && zero; i++) zero = frac[i] == '0'; - if (!zero && signe > 0) { - VpSetInf(a, sign); - VpException(VP_EXCEPTION_INFINITY, "exponent overflow",0); - } - else VpSetZero(a, sign); - return 1; - } - - ind_a = 0; - while (i < mi) { - a->frac[ind_a] = 0; - while (j < BASE_FIG && i < mi) { - a->frac[ind_a] = a->frac[ind_a] * 10 + int_chr[i] - '0'; - ++j; - ++i; - } - if (i < mi) { - ++ind_a; - if (ind_a >= ma) goto over_flow; - j = 0; - } - } - - /* get fraction part */ - - i = 0; - while (i < nf) { - while (j < BASE_FIG && i < nf) { - a->frac[ind_a] = a->frac[ind_a] * 10 + frac[i] - '0'; - ++j; - ++i; - } - if (i < nf) { - ++ind_a; - if (ind_a >= ma) goto over_flow; - j = 0; - } - } - goto Final; - -over_flow: - rb_warn("Conversion from String to BigDecimal overflow (last few digits discarded)."); - -Final: - if (ind_a >= ma) ind_a = ma - 1; - while (j < BASE_FIG) { - a->frac[ind_a] = a->frac[ind_a] * 10; - ++j; - } - a->Prec = ind_a + 1; - a->exponent = eb; - VpSetSign(a, sign); - VpNmlz(a); - return 1; -} - -/* - * [Input] - * *m ... Real - * [Output] - * *d ... fraction part of m(d = 0.xxxxxxx). where # of 'x's is fig. - * *e ... exponent of m. - * BIGDECIMAL_DOUBLE_FIGURES ... Number of digits in a double variable. - * - * m -> d*10**e, 0Prec); - *d = 0.0; - div = 1.; - while (ind_m < mm) { - div /= (double)BASE; - *d = *d + (double)m->frac[ind_m++] * div; - } - *e = m->exponent * (SIGNED_VALUE)BASE_FIG; - *d *= VpGetSign(m); - -Exit: -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, " VpVtoD: m=%\n", m); - printf(" d=%e * 10 **%ld\n", *d, *e); - printf(" BIGDECIMAL_DOUBLE_FIGURES = %d\n", BIGDECIMAL_DOUBLE_FIGURES); - } -#endif /*BIGDECIMAL_DEBUG */ - return f; -} - -/* - * m <- d - */ -VP_EXPORT void -VpDtoV(Real *m, double d) -{ - size_t ind_m, mm; - SIGNED_VALUE ne; - DECDIG i; - double val, val2; - - if (isnan(d)) { - VpSetNaN(m); - goto Exit; - } - if (isinf(d)) { - if (d > 0.0) VpSetPosInf(m); - else VpSetNegInf(m); - goto Exit; - } - - if (d == 0.0) { - VpSetZero(m, 1); - goto Exit; - } - val = (d > 0.) ? d : -d; - ne = 0; - if (val >= 1.0) { - while (val >= 1.0) { - val /= (double)BASE; - ++ne; - } - } - else { - val2 = 1.0 / (double)BASE; - while (val < val2) { - val *= (double)BASE; - --ne; - } - } - /* Now val = 0.xxxxx*BASE**ne */ - - mm = m->MaxPrec; - memset(m->frac, 0, mm * sizeof(DECDIG)); - for (ind_m = 0; val > 0.0 && ind_m < mm; ind_m++) { - val *= (double)BASE; - i = (DECDIG)val; - val -= (double)i; - m->frac[ind_m] = i; - } - if (ind_m >= mm) ind_m = mm - 1; - VpSetSign(m, (d > 0.0) ? 1 : -1); - m->Prec = ind_m + 1; - m->exponent = ne; - - VpInternalRound(m, 0, (m->Prec > 0) ? m->frac[m->Prec-1] : 0, - (DECDIG)(val*(double)BASE)); - -Exit: -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - printf("VpDtoV d=%30.30e\n", d); - VPrint(stdout, " m=%\n", m); - } -#endif /* BIGDECIMAL_DEBUG */ - return; -} - -/* - * m <- ival - */ -#if 0 /* unused */ -VP_EXPORT void -VpItoV(Real *m, SIGNED_VALUE ival) -{ - size_t mm, ind_m; - size_t val, v1, v2, v; - int isign; - SIGNED_VALUE ne; - - if (ival == 0) { - VpSetZero(m, 1); - goto Exit; - } - isign = 1; - val = ival; - if (ival < 0) { - isign = -1; - val =(size_t)(-ival); - } - ne = 0; - ind_m = 0; - mm = m->MaxPrec; - while (ind_m < mm) { - m->frac[ind_m] = 0; - ++ind_m; - } - ind_m = 0; - while (val > 0) { - if (val) { - v1 = val; - v2 = 1; - while (v1 >= BASE) { - v1 /= BASE; - v2 *= BASE; - } - val = val - v2 * v1; - v = v1; - } - else { - v = 0; - } - m->frac[ind_m] = v; - ++ind_m; - ++ne; - } - m->Prec = ind_m - 1; - m->exponent = ne; - VpSetSign(m, isign); - VpNmlz(m); - -Exit: -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - printf(" VpItoV i=%d\n", ival); - VPrint(stdout, " m=%\n", m); - } -#endif /* BIGDECIMAL_DEBUG */ - return; -} -#endif - -/* - * y = SQRT(x), y*y - x =>0 - */ -VP_EXPORT int -VpSqrt(Real *y, Real *x) -{ - Real *f = NULL; - Real *r = NULL; - size_t y_prec; - SIGNED_VALUE n, e; - ssize_t nr; - double val; - - /* Zero or +Infinity ? */ - if (VpIsZero(x) || VpIsPosInf(x)) { - VpAsgn(y,x,1); - goto Exit; - } - - /* Negative ? */ - if (BIGDECIMAL_NEGATIVE_P(x)) { - VpSetNaN(y); - return VpException(VP_EXCEPTION_OP, "sqrt of negative value", 0); - } - - /* NaN ? */ - if (VpIsNaN(x)) { - VpSetNaN(y); - return VpException(VP_EXCEPTION_OP, "sqrt of 'NaN'(Not a Number)", 0); - } - - /* One ? */ - if (VpIsOne(x)) { - VpSetOne(y); - goto Exit; - } - - n = (SIGNED_VALUE)y->MaxPrec; - if (x->MaxPrec > (size_t)n) n = (ssize_t)x->MaxPrec; - - /* allocate temporally variables */ - /* 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; - - VpVtoD(&val, &e, x); /* val <- x */ - e /= (SIGNED_VALUE)BASE_FIG; - n = e / 2; - if (e - n * 2 != 0) { - val /= BASE; - n = (e + 1) / 2; - } - VpDtoV(y, sqrt(val)); /* y <- sqrt(val) */ - y->exponent += n; - n = (SIGNED_VALUE)roomof(BIGDECIMAL_DOUBLE_FIGURES, BASE_FIG); - y->MaxPrec = Min((size_t)n , y_prec); - f->MaxPrec = y->MaxPrec + 1; - n = (SIGNED_VALUE)(y_prec * BASE_FIG); - 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, 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 - if (gfDebug) { - printf("ERROR(VpSqrt): did not converge within %ld iterations.\n", nr); - } -#endif /* BIGDECIMAL_DEBUG */ - y->MaxPrec = y_prec; - -converge: - VpChangeSign(y, 1); -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VpMult(r, y, y); - VpAddSub(f, x, r, -1); - printf("VpSqrt: iterations = %"PRIdSIZE"\n", nr); - VPrint(stdout, " y =% \n", y); - VPrint(stdout, " x =% \n", x); - VPrint(stdout, " x-y*y = % \n", f); - } -#endif /* BIGDECIMAL_DEBUG */ - y->MaxPrec = y_prec; - -Exit: - rbd_free_struct(f); - rbd_free_struct(r); - return 1; -} - -/* - * Round relatively from the decimal point. - * f: rounding mode - * nf: digit location to round from the decimal point. - */ -VP_EXPORT int -VpMidRound(Real *y, unsigned short f, ssize_t nf) -{ - /* fracf: any positive digit under rounding position? */ - /* fracf_1further: any positive digits under one further than the rounding position? */ - /* exptoadd: number of digits needed to compensate negative nf */ - int fracf, fracf_1further; - ssize_t n,i,ix,ioffset, exptoadd; - DECDIG v, shifter; - DECDIG div; - - nf += y->exponent * (ssize_t)BASE_FIG; - exptoadd=0; - if (nf < 0) { - /* rounding position too left(large). */ - if (f != VP_ROUND_CEIL && f != VP_ROUND_FLOOR) { - VpSetZero(y, VpGetSign(y)); /* truncate everything */ - return 0; - } - exptoadd = -nf; - nf = 0; - } - - ix = nf / (ssize_t)BASE_FIG; - if ((size_t)ix >= y->Prec) return 0; /* rounding position too right(small). */ - v = y->frac[ix]; - - ioffset = nf - ix*(ssize_t)BASE_FIG; - n = (ssize_t)BASE_FIG - ioffset - 1; - for (shifter = 1, i = 0; i < n; ++i) shifter *= 10; - - /* so the representation used (in y->frac) is an array of DECDIG, where - each DECDIG contains a value between 0 and BASE-1, consisting of BASE_FIG - decimal places. - - (that numbers of decimal places are typed as ssize_t is somewhat confusing) - - nf is now position (in decimal places) of the digit from the start of - the array. - - ix is the position (in DECDIGs) of the DECDIG containing the decimal digit, - from the start of the array. - - v is the value of this DECDIG - - ioffset is the number of extra decimal places along of this decimal digit - within v. - - n is the number of decimal digits remaining within v after this decimal digit - shifter is 10**n, - - v % shifter are the remaining digits within v - v % (shifter * 10) are the digit together with the remaining digits within v - v / shifter are the digit's predecessors together with the digit - div = v / shifter / 10 is just the digit's precessors - (v / shifter) - div*10 is just the digit, which is what v ends up being reassigned to. - */ - - fracf = (v % (shifter * 10) > 0); - fracf_1further = ((v % shifter) > 0); - - v /= shifter; - div = v / 10; - v = v - div*10; - /* now v is just the digit required. - now fracf is whether the digit or any of the remaining digits within v are non-zero - now fracf_1further is whether any of the remaining digits within v are non-zero - */ - - /* now check all the remaining DECDIGs for zero-ness a whole DECDIG at a time. - if we spot any non-zeroness, that means that we found a positive digit under - rounding position, and we also found a positive digit under one further than - the rounding position, so both searches (to see if any such non-zero digit exists) - can stop */ - - for (i = ix + 1; (size_t)i < y->Prec; i++) { - if (y->frac[i] % BASE) { - fracf = fracf_1further = 1; - break; - } - } - - /* now fracf = does any positive digit exist under the rounding position? - now fracf_1further = does any positive digit exist under one further than the - rounding position? - now v = the first digit under the rounding position */ - - /* drop digits after pointed digit */ - memset(y->frac + ix + 1, 0, (y->Prec - (ix + 1)) * sizeof(DECDIG)); - - switch (f) { - case VP_ROUND_DOWN: /* Truncate */ - break; - case VP_ROUND_UP: /* Roundup */ - if (fracf) ++div; - break; - case VP_ROUND_HALF_UP: - if (v>=5) ++div; - break; - case VP_ROUND_HALF_DOWN: - if (v > 5 || (v == 5 && fracf_1further)) ++div; - break; - case VP_ROUND_CEIL: - if (fracf && BIGDECIMAL_POSITIVE_P(y)) ++div; - break; - case VP_ROUND_FLOOR: - if (fracf && BIGDECIMAL_NEGATIVE_P(y)) ++div; - break; - case VP_ROUND_HALF_EVEN: /* Banker's rounding */ - if (v > 5) ++div; - else if (v == 5) { - if (fracf_1further) { - ++div; - } - else { - if (ioffset == 0) { - /* v is the first decimal digit of its DECDIG; - need to grab the previous DECDIG if present - to check for evenness of the previous decimal - digit (which is same as that of the DECDIG since - base 10 has a factor of 2) */ - if (ix && (y->frac[ix-1] % 2)) ++div; - } - else { - if (div % 2) ++div; - } - } - } - break; - } - for (i = 0; i <= n; ++i) div *= 10; - if (div >= BASE) { - if (ix) { - y->frac[ix] = 0; - VpRdup(y, ix); - } - else { - short s = VpGetSign(y); - SIGNED_VALUE e = y->exponent; - VpSetOne(y); - VpSetSign(y, s); - y->exponent = e + 1; - } - } - else { - y->frac[ix] = div; - VpNmlz(y); - } - if (exptoadd > 0) { - y->exponent += (SIGNED_VALUE)(exptoadd / BASE_FIG); - exptoadd %= (ssize_t)BASE_FIG; - for (i = 0; i < exptoadd; i++) { - y->frac[0] *= 10; - if (y->frac[0] >= BASE) { - y->frac[0] /= BASE; - y->exponent++; - } - } - } - return 1; -} - -VP_EXPORT int -VpLeftRound(Real *y, unsigned short f, ssize_t nf) -/* - * Round from the left hand side of the digits. - */ -{ - DECDIG v; - if (!VpHasVal(y)) return 0; /* Unable to round */ - v = y->frac[0]; - nf -= VpExponent(y) * (ssize_t)BASE_FIG; - while ((v /= 10) != 0) nf--; - nf += (ssize_t)BASE_FIG-1; - return VpMidRound(y, f, nf); -} - -VP_EXPORT int -VpActiveRound(Real *y, Real *x, unsigned short f, ssize_t nf) -{ - /* First,assign whole value in truncation mode */ - if (VpAsgn(y, x, 10) <= 1) return 0; /* Zero,NaN,or Infinity */ - return VpMidRound(y, f, nf); -} - -static int -VpLimitRound(Real *c, size_t ixDigit) -{ - size_t ix = VpGetPrecLimit(); - if (!VpNmlz(c)) return -1; - if (!ix) return 0; - if (!ixDigit) ixDigit = c->Prec-1; - if ((ix + BASE_FIG - 1) / BASE_FIG > ixDigit + 1) return 0; - return VpLeftRound(c, VpGetRoundMode(), (ssize_t)ix); -} - -/* If I understand correctly, this is only ever used to round off the final decimal - digit of precision */ -static void -VpInternalRound(Real *c, size_t ixDigit, DECDIG vPrev, DECDIG v) -{ - int f = 0; - - unsigned short const rounding_mode = VpGetRoundMode(); - - if (VpLimitRound(c, ixDigit)) return; - if (!v) return; - - v /= BASE1; - switch (rounding_mode) { - case VP_ROUND_DOWN: - break; - case VP_ROUND_UP: - if (v) f = 1; - break; - case VP_ROUND_HALF_UP: - if (v >= 5) f = 1; - break; - case VP_ROUND_HALF_DOWN: - /* this is ok - because this is the last digit of precision, - the case where v == 5 and some further digits are nonzero - will never occur */ - if (v >= 6) f = 1; - break; - case VP_ROUND_CEIL: - if (v && BIGDECIMAL_POSITIVE_P(c)) f = 1; - break; - case VP_ROUND_FLOOR: - if (v && BIGDECIMAL_NEGATIVE_P(c)) f = 1; - break; - case VP_ROUND_HALF_EVEN: /* Banker's rounding */ - /* as per VP_ROUND_HALF_DOWN, because this is the last digit of precision, - there is no case to worry about where v == 5 and some further digits are nonzero */ - if (v > 5) f = 1; - else if (v == 5 && vPrev % 2) f = 1; - break; - } - if (f) { - VpRdup(c, ixDigit); - VpNmlz(c); - } -} - -/* - * Rounds up m(plus one to final digit of m). - */ -static int -VpRdup(Real *m, size_t ind_m) -{ - DECDIG carry; - - if (!ind_m) ind_m = m->Prec; - - carry = 1; - while (carry > 0 && ind_m--) { - m->frac[ind_m] += carry; - if (m->frac[ind_m] >= BASE) m->frac[ind_m] -= BASE; - else carry = 0; - } - if (carry > 0) { /* Overflow,count exponent and set fraction part be 1 */ - if (!AddExponent(m, 1)) return 0; - m->Prec = m->frac[0] = 1; - } - else { - VpNmlz(m); - } - return 1; -} - -/* - * y = x - fix(x) - */ -VP_EXPORT void -VpFrac(Real *y, Real *x) -{ - size_t my, ind_y, ind_x; - - if (!VpHasVal(x)) { - VpAsgn(y, x, 1); - goto Exit; - } - - if (x->exponent > 0 && (size_t)x->exponent >= x->Prec) { - VpSetZero(y, VpGetSign(x)); - goto Exit; - } - else if (x->exponent <= 0) { - VpAsgn(y, x, 1); - goto Exit; - } - - /* satisfy: x->exponent > 0 */ - - y->Prec = x->Prec - (size_t)x->exponent; - y->Prec = Min(y->Prec, y->MaxPrec); - y->exponent = 0; - VpSetSign(y, VpGetSign(x)); - ind_y = 0; - my = y->Prec; - ind_x = x->exponent; - while (ind_y < my) { - y->frac[ind_y] = x->frac[ind_x]; - ++ind_y; - ++ind_x; - } - VpNmlz(y); - -Exit: -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, "VpFrac y=%\n", y); - VPrint(stdout, " x=%\n", x); - } -#endif /* BIGDECIMAL_DEBUG */ - return; -} - -/* - * y = x ** n - */ -VP_EXPORT int -VpPowerByInt(Real *y, Real *x, SIGNED_VALUE n) -{ - size_t s, ss; - ssize_t sign; - Real *w1 = NULL; - Real *w2 = NULL; - - if (VpIsZero(x)) { - if (n == 0) { - VpSetOne(y); - goto Exit; - } - sign = VpGetSign(x); - if (n < 0) { - n = -n; - if (sign < 0) sign = (n % 2) ? -1 : 1; - VpSetInf(y, sign); - } - else { - if (sign < 0) sign = (n % 2) ? -1 : 1; - VpSetZero(y,sign); - } - goto Exit; - } - if (VpIsNaN(x)) { - VpSetNaN(y); - goto Exit; - } - if (VpIsInf(x)) { - if (n == 0) { - VpSetOne(y); - goto Exit; - } - if (n > 0) { - VpSetInf(y, (n % 2 == 0 || VpIsPosInf(x)) ? 1 : -1); - goto Exit; - } - VpSetZero(y, (n % 2 == 0 || VpIsPosInf(x)) ? 1 : -1); - goto Exit; - } - - if (x->exponent == 1 && x->Prec == 1 && x->frac[0] == 1) { - /* abs(x) = 1 */ - VpSetOne(y); - if (BIGDECIMAL_POSITIVE_P(x)) goto Exit; - if ((n % 2) == 0) goto Exit; - VpSetSign(y, -1); - goto Exit; - } - - if (n > 0) sign = 1; - else if (n < 0) { - sign = -1; - n = -n; - } - else { - VpSetOne(y); - goto Exit; - } - - /* 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); - - /* calculation start */ - - VpAsgn(y, x, 1); - --n; - while (n > 0) { - VpAsgn(w1, x, 1); - s = 1; - while (ss = s, (s += s) <= (size_t)n) { - VpMult(w2, w1, w1); - VpAsgn(w1, w2, 1); - } - n -= (SIGNED_VALUE)ss; - VpMult(w2, y, w1); - VpAsgn(y, w2, 1); - } - if (sign < 0) { - VpDivd(w1, w2, VpConstOne, y); - VpAsgn(y, w1, 1); - } - -Exit: -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, "VpPowerByInt y=%\n", y); - VPrint(stdout, "VpPowerByInt x=%\n", x); - printf(" n=%"PRIdVALUE"\n", n); - } -#endif /* BIGDECIMAL_DEBUG */ - rbd_free_struct(w2); - rbd_free_struct(w1); - return 1; -} - -#ifdef BIGDECIMAL_DEBUG -int -VpVarCheck(Real * v) -/* - * Checks the validity of the Real variable v. - * [Input] - * v ... Real *, variable to be checked. - * [Returns] - * 0 ... correct v. - * other ... error - */ -{ - size_t i; - - if (v->MaxPrec == 0) { - printf("ERROR(VpVarCheck): Illegal Max. Precision(=%"PRIuSIZE")\n", - v->MaxPrec); - return 1; - } - if (v->Prec == 0 || v->Prec > v->MaxPrec) { - printf("ERROR(VpVarCheck): Illegal Precision(=%"PRIuSIZE")\n", v->Prec); - printf(" Max. Prec.=%"PRIuSIZE"\n", v->MaxPrec); - return 2; - } - for (i = 0; i < v->Prec; ++i) { - if (v->frac[i] >= BASE) { - printf("ERROR(VpVarCheck): Illegal fraction\n"); - printf(" Frac[%"PRIuSIZE"]=%"PRIuDECDIG"\n", i, v->frac[i]); - printf(" Prec. =%"PRIuSIZE"\n", v->Prec); - printf(" Exp. =%"PRIdVALUE"\n", v->exponent); - printf(" BASE =%"PRIuDECDIG"\n", BASE); - return 3; - } - } - return 0; -} -#endif /* BIGDECIMAL_DEBUG */ diff --git a/ext/bigdecimal/bigdecimal.gemspec b/ext/bigdecimal/bigdecimal.gemspec deleted file mode 100644 index f9f3b456168531..00000000000000 --- a/ext/bigdecimal/bigdecimal.gemspec +++ /dev/null @@ -1,54 +0,0 @@ -# coding: utf-8 - -name = File.basename(__FILE__, '.*') -source_version = ["", "ext/#{name}/"].find do |dir| - begin - break File.foreach(File.join(__dir__, "#{dir}#{name}.c")) {|line| - break $1.sub("-", ".") if /^#define\s+#{name.upcase}_VERSION\s+"(.+)"/o =~ line - } - rescue Errno::ENOENT - end -end or raise "can't find #{name.upcase}_VERSION" - -Gem::Specification.new do |s| - s.name = name - s.version = source_version - 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.licenses = ["Ruby", "BSD-2-Clause"] - - s.require_paths = %w[lib] - s.files = %w[ - bigdecimal.gemspec - lib/bigdecimal.rb - lib/bigdecimal/jacobian.rb - lib/bigdecimal/ludcmp.rb - lib/bigdecimal/math.rb - lib/bigdecimal/newton.rb - lib/bigdecimal/util.rb - sample/linear.rb - sample/nlsolve.rb - sample/pi.rb - ] - if Gem::Platform === s.platform and s.platform =~ 'java' or RUBY_ENGINE == 'jruby' - s.platform = 'java' - else - s.extensions = %w[ext/bigdecimal/extconf.rb] - s.files += %w[ - ext/bigdecimal/bigdecimal.c - ext/bigdecimal/bigdecimal.h - ext/bigdecimal/bits.h - ext/bigdecimal/feature.h - ext/bigdecimal/missing.c - ext/bigdecimal/missing.h - ext/bigdecimal/missing/dtoa.c - ext/bigdecimal/static_assert.h - ] - end - - s.required_ruby_version = Gem::Requirement.new(">= 2.5.0") -end diff --git a/ext/bigdecimal/bigdecimal.h b/ext/bigdecimal/bigdecimal.h deleted file mode 100644 index 54fed811fb6abb..00000000000000 --- a/ext/bigdecimal/bigdecimal.h +++ /dev/null @@ -1,313 +0,0 @@ -/* - * - * Ruby BigDecimal(Variable decimal precision) extension library. - * - * Copyright(C) 2002 by Shigeo Kobayashi(shigeo@tinyforest.gr.jp) - * - */ - -#ifndef RUBY_BIG_DECIMAL_H -#define RUBY_BIG_DECIMAL_H 1 - -#define RUBY_NO_OLD_COMPATIBILITY -#include "ruby/ruby.h" -#include "missing.h" - -#ifdef HAVE_FLOAT_H -# include -#endif - -#ifdef HAVE_INT64_T -# define DECDIG uint32_t -# define DECDIG_DBL uint64_t -# define DECDIG_DBL_SIGNED int64_t -# define SIZEOF_DECDIG 4 -# define PRI_DECDIG_PREFIX "" -# ifdef PRI_LL_PREFIX -# define PRI_DECDIG_DBL_PREFIX PRI_LL_PREFIX -# else -# define PRI_DECDIG_DBL_PREFIX "l" -# endif -#else -# define DECDIG uint16_t -# define DECDIG_DBL uint32_t -# define DECDIG_DBL_SIGNED int32_t -# define SIZEOF_DECDIG 2 -# define PRI_DECDIG_PREFIX "h" -# define PRI_DECDIG_DBL_PREFIX "" -#endif - -#define PRIdDECDIG PRI_DECDIG_PREFIX"d" -#define PRIiDECDIG PRI_DECDIG_PREFIX"i" -#define PRIoDECDIG PRI_DECDIG_PREFIX"o" -#define PRIuDECDIG PRI_DECDIG_PREFIX"u" -#define PRIxDECDIG PRI_DECDIG_PREFIX"x" -#define PRIXDECDIG PRI_DECDIG_PREFIX"X" - -#define PRIdDECDIG_DBL PRI_DECDIG_DBL_PREFIX"d" -#define PRIiDECDIG_DBL PRI_DECDIG_DBL_PREFIX"i" -#define PRIoDECDIG_DBL PRI_DECDIG_DBL_PREFIX"o" -#define PRIuDECDIG_DBL PRI_DECDIG_DBL_PREFIX"u" -#define PRIxDECDIG_DBL PRI_DECDIG_DBL_PREFIX"x" -#define PRIXDECDIG_DBL PRI_DECDIG_DBL_PREFIX"X" - -#if SIZEOF_DECDIG == 4 -# define BIGDECIMAL_BASE ((DECDIG)1000000000U) -# define BIGDECIMAL_COMPONENT_FIGURES 9 -/* - * The number of components required for a 64-bit integer. - * - * INT64_MAX: 9_223372036_854775807 - * UINT64_MAX: 18_446744073_709551615 - */ -# define BIGDECIMAL_INT64_MAX_LENGTH 3 - -#elif SIZEOF_DECDIG == 2 -# define BIGDECIMAL_BASE ((DECDIG)10000U) -# define BIGDECIMAL_COMPONENT_FIGURES 4 -/* - * The number of components required for a 64-bit integer. - * - * INT64_MAX: 922_3372_0368_5477_5807 - * UINT64_MAX: 1844_6744_0737_0955_1615 - */ -# define BIGDECIMAL_INT64_MAX_LENGTH 5 - -#else -# error Unknown size of DECDIG -#endif - -#define BIGDECIMAL_DOUBLE_FIGURES (1+DBL_DIG) - -#if defined(__cplusplus) -extern "C" { -#if 0 -} /* satisfy cc-mode */ -#endif -#endif - -extern VALUE rb_cBigDecimal; - -/* - * NaN & Infinity - */ -#define SZ_NaN "NaN" -#define SZ_INF "Infinity" -#define SZ_PINF "+Infinity" -#define SZ_NINF "-Infinity" - -/* - * #define VP_EXPORT other than static to let VP_ routines - * be called from outside of this module. - */ -#define VP_EXPORT static - -/* Exception mode */ -#define VP_EXCEPTION_ALL ((unsigned short)0x00FF) -#define VP_EXCEPTION_INFINITY ((unsigned short)0x0001) -#define VP_EXCEPTION_NaN ((unsigned short)0x0002) -#define VP_EXCEPTION_UNDERFLOW ((unsigned short)0x0004) -#define VP_EXCEPTION_OVERFLOW ((unsigned short)0x0001) /* 0x0008) */ -#define VP_EXCEPTION_ZERODIVIDE ((unsigned short)0x0010) - -/* Following 2 exceptions can't controlled by user */ -#define VP_EXCEPTION_OP ((unsigned short)0x0020) - -#define BIGDECIMAL_EXCEPTION_MODE_DEFAULT 0U - -/* This is used in BigDecimal#mode */ -#define VP_ROUND_MODE ((unsigned short)0x0100) - -/* 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 */ -#define VP_SIGN_POSITIVE_FINITE 2 /* Positive finite number */ -#define VP_SIGN_NEGATIVE_FINITE -2 /* Negative finite number */ -#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__) -#define FLEXIBLE_ARRAY_SIZE 0 -#else -#define FLEXIBLE_ARRAY_SIZE 1 -#endif - -/* - * VP representation - * r = 0.xxxxxxxxx *BASE**exponent - */ -typedef struct { - VALUE obj; /* Back pointer(VALUE) for Ruby object. */ - size_t MaxPrec; /* Maximum precision size */ - /* This is the actual size of frac[] */ - /*(frac[0] to frac[MaxPrec] are available). */ - size_t Prec; /* Current precision size. */ - /* This indicates how much the */ - /* array frac[] is actually used. */ - SIGNED_VALUE exponent; /* Exponent part. */ - short sign; /* Attributes of the value. */ - /* - * ==0 : NaN - * 1 : Positive zero - * -1 : Negative zero - * 2 : Positive number - * -2 : Negative number - * 3 : Positive infinite number - * -3 : Negative infinite number - */ - short flag; /* Not used in vp_routines,space for user. */ - DECDIG frac[FLEXIBLE_ARRAY_SIZE]; /* Array of fraction part. */ -} Real; - -/* - * ------------------ - * EXPORTables. - * ------------------ - */ - -VP_EXPORT Real *VpNewRbClass(size_t mx, char const *str, VALUE klass, bool strict_p, bool raise_exception); - -VP_EXPORT Real *VpCreateRbObject(size_t mx, const char *str, bool raise_exception); - -#define VpBaseFig() BIGDECIMAL_COMPONENT_FIGURES -#define VpDblFig() BIGDECIMAL_DOUBLE_FIGURES -#define VpBaseVal() BIGDECIMAL_BASE - -/* Zero,Inf,NaN (isinf(),isnan() used to check) */ -VP_EXPORT double VpGetDoubleNaN(void); -VP_EXPORT double VpGetDoublePosInf(void); -VP_EXPORT double VpGetDoubleNegInf(void); -VP_EXPORT double VpGetDoubleNegZero(void); - -/* These 2 functions added at v1.1.7 */ -VP_EXPORT size_t VpGetPrecLimit(void); -VP_EXPORT size_t VpSetPrecLimit(size_t n); - -/* Round mode */ -VP_EXPORT int VpIsRoundMode(unsigned short n); -VP_EXPORT unsigned short VpGetRoundMode(void); -VP_EXPORT unsigned short VpSetRoundMode(unsigned short n); - -VP_EXPORT int VpException(unsigned short f,const char *str,int always); -#if 0 /* unused */ -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 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); -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 *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); -#if 0 /* unused */ -VP_EXPORT void VpItoV(Real *m,S_INT ival); -#endif -VP_EXPORT int VpSqrt(Real *y,Real *x); -VP_EXPORT int VpActiveRound(Real *y, Real *x, unsigned short f, ssize_t il); -VP_EXPORT int VpMidRound(Real *y, unsigned short f, ssize_t nf); -VP_EXPORT int VpLeftRound(Real *y, unsigned short f, ssize_t nf); -VP_EXPORT void VpFrac(Real *y, Real *x); -VP_EXPORT int VpPowerByInt(Real *y, Real *x, SIGNED_VALUE n); -#define VpPower VpPowerByInt - -/* VP constants */ -VP_EXPORT Real *VpOne(void); - -/* - * ------------------ - * MACRO definitions. - * ------------------ - */ -#define Abs(a) (((a)>= 0)?(a):(-(a))) -#define Max(a, b) (((a)>(b))?(a):(b)) -#define Min(a, b) (((a)>(b))?(b):(a)) - -#define VpMaxPrec(a) ((a)->MaxPrec) -#define VpPrec(a) ((a)->Prec) -#define VpGetFlag(a) ((a)->flag) - -/* Sign */ - -/* VpGetSign(a) returns 1,-1 if a>0,a<0 respectively */ -#define VpGetSign(a) (((a)->sign>0)?1:(-1)) -/* Change sign of a to a>0,a<0 if s = 1,-1 respectively */ -#define VpChangeSign(a,s) {if((s)>0) (a)->sign=(short)Abs((ssize_t)(a)->sign);else (a)->sign=-(short)Abs((ssize_t)(a)->sign);} -/* Sets sign of a to a>0,a<0 if s = 1,-1 respectively */ -#define VpSetSign(a,s) {if((s)>0) (a)->sign=(short)VP_SIGN_POSITIVE_FINITE;else (a)->sign=(short)VP_SIGN_NEGATIVE_FINITE;} - -/* 1 */ -#define VpSetOne(a) {(a)->Prec=(a)->exponent=(a)->frac[0]=1;(a)->sign=VP_SIGN_POSITIVE_FINITE;} - -/* ZEROs */ -#define VpIsPosZero(a) ((a)->sign==VP_SIGN_POSITIVE_ZERO) -#define VpIsNegZero(a) ((a)->sign==VP_SIGN_NEGATIVE_ZERO) -#define VpIsZero(a) (VpIsPosZero(a) || VpIsNegZero(a)) -#define VpSetPosZero(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_POSITIVE_ZERO) -#define VpSetNegZero(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_NEGATIVE_ZERO) -#define VpSetZero(a,s) (void)(((s)>0)?VpSetPosZero(a):VpSetNegZero(a)) - -/* NaN */ -#define VpIsNaN(a) ((a)->sign==VP_SIGN_NaN) -#define VpSetNaN(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_NaN) - -/* Infinity */ -#define VpIsPosInf(a) ((a)->sign==VP_SIGN_POSITIVE_INFINITE) -#define VpIsNegInf(a) ((a)->sign==VP_SIGN_NEGATIVE_INFINITE) -#define VpIsInf(a) (VpIsPosInf(a) || VpIsNegInf(a)) -#define VpIsDef(a) ( !(VpIsNaN(a)||VpIsInf(a)) ) -#define VpSetPosInf(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_POSITIVE_INFINITE) -#define VpSetNegInf(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_NEGATIVE_INFINITE) -#define VpSetInf(a,s) (void)(((s)>0)?VpSetPosInf(a):VpSetNegInf(a)) -#define VpHasVal(a) (a->frac[0]) -#define VpIsOne(a) ((a->Prec==1)&&(a->frac[0]==1)&&(a->exponent==1)) -#define VpExponent(a) (a->exponent) -#ifdef BIGDECIMAL_DEBUG -int VpVarCheck(Real * v); -#endif /* BIGDECIMAL_DEBUG */ - -#if defined(__cplusplus) -#if 0 -{ /* satisfy cc-mode */ -#endif -} /* extern "C" { */ -#endif -#endif /* RUBY_BIG_DECIMAL_H */ diff --git a/ext/bigdecimal/bits.h b/ext/bigdecimal/bits.h deleted file mode 100644 index 6e1e4776e39599..00000000000000 --- a/ext/bigdecimal/bits.h +++ /dev/null @@ -1,141 +0,0 @@ -#ifndef BIGDECIMAL_BITS_H -#define BIGDECIMAL_BITS_H - -#include "feature.h" -#include "static_assert.h" - -#if defined(__x86_64__) && defined(HAVE_X86INTRIN_H) -# include /* for _lzcnt_u64, etc. */ -#elif defined(_MSC_VER) && defined(HAVE_INTRIN_H) -# include /* for the following intrinsics */ -#endif - -#if defined(_MSC_VER) && defined(__AVX2__) -# pragma intrinsic(__lzcnt) -# pragma intrinsic(__lzcnt64) -#endif - -#define numberof(array) ((int)(sizeof(array) / sizeof((array)[0]))) -#define roomof(x, y) (((x) + (y) - 1) / (y)) -#define type_roomof(x, y) roomof(sizeof(x), sizeof(y)) - -#define MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \ - (a) == 0 ? 0 : \ - (a) == -1 ? (b) < -(max) : \ - (a) > 0 ? \ - ((b) > 0 ? (max) / (a) < (b) : (min) / (a) > (b)) : \ - ((b) > 0 ? (min) / (a) < (b) : (max) / (a) > (b))) - -#ifdef HAVE_UINT128_T -# define bit_length(x) \ - (unsigned int) \ - (sizeof(x) <= sizeof(int32_t) ? 32 - nlz_int32((uint32_t)(x)) : \ - sizeof(x) <= sizeof(int64_t) ? 64 - nlz_int64((uint64_t)(x)) : \ - 128 - nlz_int128((uint128_t)(x))) -#else -# define bit_length(x) \ - (unsigned int) \ - (sizeof(x) <= sizeof(int32_t) ? 32 - nlz_int32((uint32_t)(x)) : \ - 64 - nlz_int64((uint64_t)(x))) -#endif - -static inline unsigned nlz_int32(uint32_t x); -static inline unsigned nlz_int64(uint64_t x); -#ifdef HAVE_UINT128_T -static inline unsigned nlz_int128(uint128_t x); -#endif - -static inline unsigned int -nlz_int32(uint32_t x) -{ -#if defined(_MSC_VER) && defined(__AVX2__) && defined(HAVE___LZCNT) - /* Note: It seems there is no such thing like __LZCNT__ predefined in MSVC. - * AMD CPUs have had this instruction for decades (since K10) but for - * Intel, Haswell is the oldest one. We need to use __AVX2__ for maximum - * safety. */ - return (unsigned int)__lzcnt(x); - -#elif defined(__x86_64__) && defined(__LZCNT__) && defined(HAVE__LZCNT_U32) - return (unsigned int)_lzcnt_u32(x); - -#elif defined(_MSC_VER) && defined(HAVE__BITSCANREVERSE) - unsigned long r; - return _BitScanReverse(&r, x) ? (31 - (int)r) : 32; - -#elif __has_builtin(__builtin_clz) - STATIC_ASSERT(sizeof_int, sizeof(int) * CHAR_BIT == 32); - return x ? (unsigned int)__builtin_clz(x) : 32; - -#else - uint32_t y; - unsigned n = 32; - y = x >> 16; if (y) {n -= 16; x = y;} - y = x >> 8; if (y) {n -= 8; x = y;} - y = x >> 4; if (y) {n -= 4; x = y;} - y = x >> 2; if (y) {n -= 2; x = y;} - y = x >> 1; if (y) {return n - 2;} - return (unsigned int)(n - x); -#endif -} - -static inline unsigned int -nlz_int64(uint64_t x) -{ -#if defined(_MSC_VER) && defined(__AVX2__) && defined(HAVE___LZCNT64) - return (unsigned int)__lzcnt64(x); - -#elif defined(__x86_64__) && defined(__LZCNT__) && defined(HAVE__LZCNT_U64) - return (unsigned int)_lzcnt_u64(x); - -#elif defined(_WIN64) && defined(_MSC_VER) && defined(HAVE__BITSCANREVERSE64) - unsigned long r; - return _BitScanReverse64(&r, x) ? (63u - (unsigned int)r) : 64; - -#elif __has_builtin(__builtin_clzl) && __has_builtin(__builtin_clzll) && !(defined(__sun) && defined(__sparc)) - if (x == 0) { - return 64; - } - else if (sizeof(long) * CHAR_BIT == 64) { - return (unsigned int)__builtin_clzl((unsigned long)x); - } - else if (sizeof(long long) * CHAR_BIT == 64) { - return (unsigned int)__builtin_clzll((unsigned long long)x); - } - else { - /* :FIXME: Is there a way to make this branch a compile-time error? */ - __builtin_unreachable(); - } - -#else - uint64_t y; - unsigned int n = 64; - y = x >> 32; if (y) {n -= 32; x = y;} - y = x >> 16; if (y) {n -= 16; x = y;} - y = x >> 8; if (y) {n -= 8; x = y;} - y = x >> 4; if (y) {n -= 4; x = y;} - y = x >> 2; if (y) {n -= 2; x = y;} - y = x >> 1; if (y) {return n - 2;} - return (unsigned int)(n - x); - -#endif -} - -#ifdef HAVE_UINT128_T -static inline unsigned int -nlz_int128(uint128_t x) -{ - uint64_t y = (uint64_t)(x >> 64); - - if (x == 0) { - return 128; - } - else if (y == 0) { - return (unsigned int)nlz_int64(x) + 64; - } - else { - return (unsigned int)nlz_int64(y); - } -} -#endif - -#endif /* BIGDECIMAL_BITS_H */ diff --git a/ext/bigdecimal/depend b/ext/bigdecimal/depend deleted file mode 100644 index a2455ebbda6cba..00000000000000 --- a/ext/bigdecimal/depend +++ /dev/null @@ -1,327 +0,0 @@ -Makefile: $(BIGDECIMAL_RB) - -# AUTOGENERATED DEPENDENCIES START -bigdecimal.o: $(RUBY_EXTCONF_H) -bigdecimal.o: $(arch_hdrdir)/ruby/config.h -bigdecimal.o: $(hdrdir)/ruby/assert.h -bigdecimal.o: $(hdrdir)/ruby/backward/2/assume.h -bigdecimal.o: $(hdrdir)/ruby/backward/2/attributes.h -bigdecimal.o: $(hdrdir)/ruby/backward/2/bool.h -bigdecimal.o: $(hdrdir)/ruby/backward/2/inttypes.h -bigdecimal.o: $(hdrdir)/ruby/backward/2/limits.h -bigdecimal.o: $(hdrdir)/ruby/backward/2/long_long.h -bigdecimal.o: $(hdrdir)/ruby/backward/2/stdalign.h -bigdecimal.o: $(hdrdir)/ruby/backward/2/stdarg.h -bigdecimal.o: $(hdrdir)/ruby/defines.h -bigdecimal.o: $(hdrdir)/ruby/intern.h -bigdecimal.o: $(hdrdir)/ruby/internal/abi.h -bigdecimal.o: $(hdrdir)/ruby/internal/anyargs.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/char.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/double.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/int.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/long.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/short.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -bigdecimal.o: $(hdrdir)/ruby/internal/assume.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/artificial.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/cold.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/const.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/constexpr.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/deprecated.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/error.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/forceinline.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/format.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/noalias.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/noexcept.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/noinline.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/nonnull.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/noreturn.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/packed_struct.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/pure.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/restrict.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/warning.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/weakref.h -bigdecimal.o: $(hdrdir)/ruby/internal/cast.h -bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is.h -bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -bigdecimal.o: $(hdrdir)/ruby/internal/compiler_since.h -bigdecimal.o: $(hdrdir)/ruby/internal/config.h -bigdecimal.o: $(hdrdir)/ruby/internal/constant_p.h -bigdecimal.o: $(hdrdir)/ruby/internal/core.h -bigdecimal.o: $(hdrdir)/ruby/internal/core/rarray.h -bigdecimal.o: $(hdrdir)/ruby/internal/core/rbasic.h -bigdecimal.o: $(hdrdir)/ruby/internal/core/rbignum.h -bigdecimal.o: $(hdrdir)/ruby/internal/core/rclass.h -bigdecimal.o: $(hdrdir)/ruby/internal/core/rdata.h -bigdecimal.o: $(hdrdir)/ruby/internal/core/rfile.h -bigdecimal.o: $(hdrdir)/ruby/internal/core/rhash.h -bigdecimal.o: $(hdrdir)/ruby/internal/core/robject.h -bigdecimal.o: $(hdrdir)/ruby/internal/core/rregexp.h -bigdecimal.o: $(hdrdir)/ruby/internal/core/rstring.h -bigdecimal.o: $(hdrdir)/ruby/internal/core/rstruct.h -bigdecimal.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -bigdecimal.o: $(hdrdir)/ruby/internal/ctype.h -bigdecimal.o: $(hdrdir)/ruby/internal/dllexport.h -bigdecimal.o: $(hdrdir)/ruby/internal/dosish.h -bigdecimal.o: $(hdrdir)/ruby/internal/error.h -bigdecimal.o: $(hdrdir)/ruby/internal/eval.h -bigdecimal.o: $(hdrdir)/ruby/internal/event.h -bigdecimal.o: $(hdrdir)/ruby/internal/fl_type.h -bigdecimal.o: $(hdrdir)/ruby/internal/gc.h -bigdecimal.o: $(hdrdir)/ruby/internal/glob.h -bigdecimal.o: $(hdrdir)/ruby/internal/globals.h -bigdecimal.o: $(hdrdir)/ruby/internal/has/attribute.h -bigdecimal.o: $(hdrdir)/ruby/internal/has/builtin.h -bigdecimal.o: $(hdrdir)/ruby/internal/has/c_attribute.h -bigdecimal.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -bigdecimal.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -bigdecimal.o: $(hdrdir)/ruby/internal/has/extension.h -bigdecimal.o: $(hdrdir)/ruby/internal/has/feature.h -bigdecimal.o: $(hdrdir)/ruby/internal/has/warning.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/array.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/bignum.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/class.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/compar.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/complex.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/cont.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/dir.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/enum.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/enumerator.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/error.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/eval.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/file.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/hash.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/io.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/load.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/marshal.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/numeric.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/object.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/parse.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/proc.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/process.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/random.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/range.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/rational.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/re.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/ruby.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/select.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/signal.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/sprintf.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/string.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/struct.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/thread.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/time.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/variable.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/vm.h -bigdecimal.o: $(hdrdir)/ruby/internal/interpreter.h -bigdecimal.o: $(hdrdir)/ruby/internal/iterator.h -bigdecimal.o: $(hdrdir)/ruby/internal/memory.h -bigdecimal.o: $(hdrdir)/ruby/internal/method.h -bigdecimal.o: $(hdrdir)/ruby/internal/module.h -bigdecimal.o: $(hdrdir)/ruby/internal/newobj.h -bigdecimal.o: $(hdrdir)/ruby/internal/scan_args.h -bigdecimal.o: $(hdrdir)/ruby/internal/special_consts.h -bigdecimal.o: $(hdrdir)/ruby/internal/static_assert.h -bigdecimal.o: $(hdrdir)/ruby/internal/stdalign.h -bigdecimal.o: $(hdrdir)/ruby/internal/stdbool.h -bigdecimal.o: $(hdrdir)/ruby/internal/symbol.h -bigdecimal.o: $(hdrdir)/ruby/internal/value.h -bigdecimal.o: $(hdrdir)/ruby/internal/value_type.h -bigdecimal.o: $(hdrdir)/ruby/internal/variable.h -bigdecimal.o: $(hdrdir)/ruby/internal/warning_push.h -bigdecimal.o: $(hdrdir)/ruby/internal/xmalloc.h -bigdecimal.o: $(hdrdir)/ruby/missing.h -bigdecimal.o: $(hdrdir)/ruby/ruby.h -bigdecimal.o: $(hdrdir)/ruby/st.h -bigdecimal.o: $(hdrdir)/ruby/subst.h -bigdecimal.o: $(hdrdir)/ruby/util.h -bigdecimal.o: bigdecimal.c -bigdecimal.o: bigdecimal.h -bigdecimal.o: bits.h -bigdecimal.o: feature.h -bigdecimal.o: missing.h -bigdecimal.o: static_assert.h -missing.o: $(RUBY_EXTCONF_H) -missing.o: $(arch_hdrdir)/ruby/config.h -missing.o: $(hdrdir)/ruby/assert.h -missing.o: $(hdrdir)/ruby/atomic.h -missing.o: $(hdrdir)/ruby/backward.h -missing.o: $(hdrdir)/ruby/backward/2/assume.h -missing.o: $(hdrdir)/ruby/backward/2/attributes.h -missing.o: $(hdrdir)/ruby/backward/2/bool.h -missing.o: $(hdrdir)/ruby/backward/2/inttypes.h -missing.o: $(hdrdir)/ruby/backward/2/limits.h -missing.o: $(hdrdir)/ruby/backward/2/long_long.h -missing.o: $(hdrdir)/ruby/backward/2/stdalign.h -missing.o: $(hdrdir)/ruby/backward/2/stdarg.h -missing.o: $(hdrdir)/ruby/defines.h -missing.o: $(hdrdir)/ruby/intern.h -missing.o: $(hdrdir)/ruby/internal/abi.h -missing.o: $(hdrdir)/ruby/internal/anyargs.h -missing.o: $(hdrdir)/ruby/internal/arithmetic.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/char.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/double.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/int.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/long.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/short.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -missing.o: $(hdrdir)/ruby/internal/assume.h -missing.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -missing.o: $(hdrdir)/ruby/internal/attr/artificial.h -missing.o: $(hdrdir)/ruby/internal/attr/cold.h -missing.o: $(hdrdir)/ruby/internal/attr/const.h -missing.o: $(hdrdir)/ruby/internal/attr/constexpr.h -missing.o: $(hdrdir)/ruby/internal/attr/deprecated.h -missing.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -missing.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -missing.o: $(hdrdir)/ruby/internal/attr/error.h -missing.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -missing.o: $(hdrdir)/ruby/internal/attr/forceinline.h -missing.o: $(hdrdir)/ruby/internal/attr/format.h -missing.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -missing.o: $(hdrdir)/ruby/internal/attr/noalias.h -missing.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -missing.o: $(hdrdir)/ruby/internal/attr/noexcept.h -missing.o: $(hdrdir)/ruby/internal/attr/noinline.h -missing.o: $(hdrdir)/ruby/internal/attr/nonnull.h -missing.o: $(hdrdir)/ruby/internal/attr/noreturn.h -missing.o: $(hdrdir)/ruby/internal/attr/packed_struct.h -missing.o: $(hdrdir)/ruby/internal/attr/pure.h -missing.o: $(hdrdir)/ruby/internal/attr/restrict.h -missing.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h -missing.o: $(hdrdir)/ruby/internal/attr/warning.h -missing.o: $(hdrdir)/ruby/internal/attr/weakref.h -missing.o: $(hdrdir)/ruby/internal/cast.h -missing.o: $(hdrdir)/ruby/internal/compiler_is.h -missing.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -missing.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -missing.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -missing.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -missing.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -missing.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -missing.o: $(hdrdir)/ruby/internal/compiler_since.h -missing.o: $(hdrdir)/ruby/internal/config.h -missing.o: $(hdrdir)/ruby/internal/constant_p.h -missing.o: $(hdrdir)/ruby/internal/core.h -missing.o: $(hdrdir)/ruby/internal/core/rarray.h -missing.o: $(hdrdir)/ruby/internal/core/rbasic.h -missing.o: $(hdrdir)/ruby/internal/core/rbignum.h -missing.o: $(hdrdir)/ruby/internal/core/rclass.h -missing.o: $(hdrdir)/ruby/internal/core/rdata.h -missing.o: $(hdrdir)/ruby/internal/core/rfile.h -missing.o: $(hdrdir)/ruby/internal/core/rhash.h -missing.o: $(hdrdir)/ruby/internal/core/robject.h -missing.o: $(hdrdir)/ruby/internal/core/rregexp.h -missing.o: $(hdrdir)/ruby/internal/core/rstring.h -missing.o: $(hdrdir)/ruby/internal/core/rstruct.h -missing.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -missing.o: $(hdrdir)/ruby/internal/ctype.h -missing.o: $(hdrdir)/ruby/internal/dllexport.h -missing.o: $(hdrdir)/ruby/internal/dosish.h -missing.o: $(hdrdir)/ruby/internal/error.h -missing.o: $(hdrdir)/ruby/internal/eval.h -missing.o: $(hdrdir)/ruby/internal/event.h -missing.o: $(hdrdir)/ruby/internal/fl_type.h -missing.o: $(hdrdir)/ruby/internal/gc.h -missing.o: $(hdrdir)/ruby/internal/glob.h -missing.o: $(hdrdir)/ruby/internal/globals.h -missing.o: $(hdrdir)/ruby/internal/has/attribute.h -missing.o: $(hdrdir)/ruby/internal/has/builtin.h -missing.o: $(hdrdir)/ruby/internal/has/c_attribute.h -missing.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -missing.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -missing.o: $(hdrdir)/ruby/internal/has/extension.h -missing.o: $(hdrdir)/ruby/internal/has/feature.h -missing.o: $(hdrdir)/ruby/internal/has/warning.h -missing.o: $(hdrdir)/ruby/internal/intern/array.h -missing.o: $(hdrdir)/ruby/internal/intern/bignum.h -missing.o: $(hdrdir)/ruby/internal/intern/class.h -missing.o: $(hdrdir)/ruby/internal/intern/compar.h -missing.o: $(hdrdir)/ruby/internal/intern/complex.h -missing.o: $(hdrdir)/ruby/internal/intern/cont.h -missing.o: $(hdrdir)/ruby/internal/intern/dir.h -missing.o: $(hdrdir)/ruby/internal/intern/enum.h -missing.o: $(hdrdir)/ruby/internal/intern/enumerator.h -missing.o: $(hdrdir)/ruby/internal/intern/error.h -missing.o: $(hdrdir)/ruby/internal/intern/eval.h -missing.o: $(hdrdir)/ruby/internal/intern/file.h -missing.o: $(hdrdir)/ruby/internal/intern/hash.h -missing.o: $(hdrdir)/ruby/internal/intern/io.h -missing.o: $(hdrdir)/ruby/internal/intern/load.h -missing.o: $(hdrdir)/ruby/internal/intern/marshal.h -missing.o: $(hdrdir)/ruby/internal/intern/numeric.h -missing.o: $(hdrdir)/ruby/internal/intern/object.h -missing.o: $(hdrdir)/ruby/internal/intern/parse.h -missing.o: $(hdrdir)/ruby/internal/intern/proc.h -missing.o: $(hdrdir)/ruby/internal/intern/process.h -missing.o: $(hdrdir)/ruby/internal/intern/random.h -missing.o: $(hdrdir)/ruby/internal/intern/range.h -missing.o: $(hdrdir)/ruby/internal/intern/rational.h -missing.o: $(hdrdir)/ruby/internal/intern/re.h -missing.o: $(hdrdir)/ruby/internal/intern/ruby.h -missing.o: $(hdrdir)/ruby/internal/intern/select.h -missing.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -missing.o: $(hdrdir)/ruby/internal/intern/signal.h -missing.o: $(hdrdir)/ruby/internal/intern/sprintf.h -missing.o: $(hdrdir)/ruby/internal/intern/string.h -missing.o: $(hdrdir)/ruby/internal/intern/struct.h -missing.o: $(hdrdir)/ruby/internal/intern/thread.h -missing.o: $(hdrdir)/ruby/internal/intern/time.h -missing.o: $(hdrdir)/ruby/internal/intern/variable.h -missing.o: $(hdrdir)/ruby/internal/intern/vm.h -missing.o: $(hdrdir)/ruby/internal/interpreter.h -missing.o: $(hdrdir)/ruby/internal/iterator.h -missing.o: $(hdrdir)/ruby/internal/memory.h -missing.o: $(hdrdir)/ruby/internal/method.h -missing.o: $(hdrdir)/ruby/internal/module.h -missing.o: $(hdrdir)/ruby/internal/newobj.h -missing.o: $(hdrdir)/ruby/internal/scan_args.h -missing.o: $(hdrdir)/ruby/internal/special_consts.h -missing.o: $(hdrdir)/ruby/internal/static_assert.h -missing.o: $(hdrdir)/ruby/internal/stdalign.h -missing.o: $(hdrdir)/ruby/internal/stdbool.h -missing.o: $(hdrdir)/ruby/internal/symbol.h -missing.o: $(hdrdir)/ruby/internal/value.h -missing.o: $(hdrdir)/ruby/internal/value_type.h -missing.o: $(hdrdir)/ruby/internal/variable.h -missing.o: $(hdrdir)/ruby/internal/warning_push.h -missing.o: $(hdrdir)/ruby/internal/xmalloc.h -missing.o: $(hdrdir)/ruby/missing.h -missing.o: $(hdrdir)/ruby/ruby.h -missing.o: $(hdrdir)/ruby/st.h -missing.o: $(hdrdir)/ruby/subst.h -missing.o: missing.c -missing.o: missing/dtoa.c -# AUTOGENERATED DEPENDENCIES END diff --git a/ext/bigdecimal/extconf.rb b/ext/bigdecimal/extconf.rb deleted file mode 100644 index 23904ed60e3dd9..00000000000000 --- a/ext/bigdecimal/extconf.rb +++ /dev/null @@ -1,62 +0,0 @@ -# frozen_string_literal: false -require 'mkmf' - -def have_builtin_func(name, check_expr, opt = "", &b) - checking_for checking_message(name.funcall_style, nil, opt) do - if try_compile(< -#endif - -#ifdef RBIMPL_HAS_BUILTIN -# define BIGDECIMAL_HAS_BUILTIN(...) RBIMPL_HAS_BUILTIN(__VA_ARGS__) - -#else -# /* The following section is copied from CRuby's builtin.h */ -# -# ifdef __has_builtin -# if defined(__INTEL_COMPILER) -# /* :TODO: Intel C Compiler has __has_builtin (since 19.1 maybe?), and is -# * reportedly broken. We have to skip them. However the situation can -# * change. They might improve someday. We need to revisit here later. */ -# elif defined(__GNUC__) && ! __has_builtin(__builtin_alloca) -# /* FreeBSD's defines its own *broken* version of -# * __has_builtin. Cygwin copied that content to be a victim of the -# * broken-ness. We don't take them into account. */ -# else -# define HAVE___HAS_BUILTIN 1 -# endif -# endif -# -# if defined(HAVE___HAS_BUILTIN) -# define BIGDECIMAL_HAS_BUILTIN(_) __has_builtin(_) -# -# elif defined(__GNUC__) -# define BIGDECIMAL_HAS_BUILTIN(_) BIGDECIMAL_HAS_BUILTIN_ ## _ -# if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 6)) -# define BIGDECIMAL_HAS_BUILTIN___builtin_clz 1 -# define BIGDECIMAL_HAS_BUILTIN___builtin_clzl 1 -# else -# define BIGDECIMAL_HAS_BUILTIN___builtin_clz 0 -# define BIGDECIMAL_HAS_BUILTIN___builtin_clzl 0 -# endif -# elif defined(_MSC_VER) -# define BIGDECIMAL_HAS_BUILTIN(_) 0 -# -# else -# define BIGDECIMAL_HAS_BUILTIN(_) BIGDECIMAL_HAS_BUILTIN_ ## _ -# define BIGDECIMAL_HAS_BUILTIN___builtin_clz HAVE_BUILTIN___BUILTIN_CLZ -# define BIGDECIMAL_HAS_BUILTIN___builtin_clzl HAVE_BUILTIN___BUILTIN_CLZL -# endif -#endif /* RBIMPL_HAS_BUILTIN */ - -#ifndef __has_builtin -# define __has_builtin(...) BIGDECIMAL_HAS_BUILTIN(__VA_ARGS__) -#endif - -#endif /* BIGDECIMAL_HAS_FEATURE_H */ diff --git a/ext/bigdecimal/lib/bigdecimal.rb b/ext/bigdecimal/lib/bigdecimal.rb deleted file mode 100644 index 82b3e1b7b98808..00000000000000 --- a/ext/bigdecimal/lib/bigdecimal.rb +++ /dev/null @@ -1,5 +0,0 @@ -if RUBY_ENGINE == 'jruby' - JRuby::Util.load_ext("org.jruby.ext.bigdecimal.BigDecimalLibrary") -else - require 'bigdecimal.so' -end diff --git a/ext/bigdecimal/lib/bigdecimal/jacobian.rb b/ext/bigdecimal/lib/bigdecimal/jacobian.rb deleted file mode 100644 index 4448024c74285f..00000000000000 --- a/ext/bigdecimal/lib/bigdecimal/jacobian.rb +++ /dev/null @@ -1,90 +0,0 @@ -# frozen_string_literal: false - -require 'bigdecimal' - -# require 'bigdecimal/jacobian' -# -# Provides methods to compute the Jacobian matrix of a set of equations at a -# point x. In the methods below: -# -# f is an Object which is used to compute the Jacobian matrix of the equations. -# It must provide the following methods: -# -# f.values(x):: returns the values of all functions at x -# -# f.zero:: returns 0.0 -# f.one:: returns 1.0 -# f.two:: returns 2.0 -# f.ten:: returns 10.0 -# -# f.eps:: returns the convergence criterion (epsilon value) used to determine whether two values are considered equal. If |a-b| < epsilon, the two values are considered equal. -# -# x is the point at which to compute the Jacobian. -# -# fx is f.values(x). -# -module Jacobian - module_function - - # Determines the equality of two numbers by comparing to zero, or using the epsilon value - def isEqual(a,b,zero=0.0,e=1.0e-8) - aa = a.abs - bb = b.abs - if aa == zero && bb == zero then - true - else - if ((a-b)/(aa+bb)).abs < e then - true - else - false - end - end - end - - - # 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 - xSave = x[i] - ok = 0 - ratio = f.ten*f.ten*f.ten - dx = x[i].abs/ratio - dx = fx[i].abs/ratio if isEqual(dx,f.zero,f.zero,f.eps) - dx = f.one/f.ten if isEqual(dx,f.zero,f.zero,f.eps) - until ok>0 do - deriv = [] - nRetry += 1 - if nRetry > 100 - raise "Singular Jacobian matrix. No change at x[" + i.to_s + "]" - end - dx = dx*f.two - x[i] += dx - fxNew = f.values(x) - for j in 0...n do - if !isEqual(fxNew[j],fx[j],f.zero,f.eps) then - ok += 1 - deriv <<= (fxNew[j]-fx[j])/dx - else - deriv <<= f.zero - end - end - x[i] = xSave - end - deriv - end - - # 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) - for i in 0...n do - df = dfdxi(f,fx,x,i) - for j in 0...n do - dfdx[j*n+i] = df[j] - end - end - dfdx - end -end diff --git a/ext/bigdecimal/lib/bigdecimal/ludcmp.rb b/ext/bigdecimal/lib/bigdecimal/ludcmp.rb deleted file mode 100644 index dd265e482a3178..00000000000000 --- a/ext/bigdecimal/lib/bigdecimal/ludcmp.rb +++ /dev/null @@ -1,89 +0,0 @@ -# frozen_string_literal: false -require 'bigdecimal' - -# -# Solves a*x = b for x, using LU decomposition. -# -module LUSolve - module_function - - # Performs LU decomposition of the n by n matrix a. - def ludecomp(a,n,zero=0,one=1) - prec = BigDecimal.limit(nil) - ps = [] - scales = [] - for i in 0...n do # pick up largest(abs. val.) element in each row. - ps <<= i - nrmrow = zero - ixn = i*n - for j in 0...n do - biggst = a[ixn+j].abs - nrmrow = biggst if biggst>nrmrow - end - if nrmrow>zero then - scales <<= one.div(nrmrow,prec) - else - raise "Singular matrix" - end - end - n1 = n - 1 - for k in 0...n1 do # Gaussian elimination with partial pivoting. - biggst = zero; - for i in k...n do - size = a[ps[i]*n+k].abs*scales[ps[i]] - if size>biggst then - biggst = size - pividx = i - end - end - raise "Singular matrix" if biggst<=zero - if pividx!=k then - j = ps[k] - ps[k] = ps[pividx] - ps[pividx] = j - end - pivot = a[ps[k]*n+k] - for i in (k+1)...n do - psin = ps[i]*n - a[psin+k] = mult = a[psin+k].div(pivot,prec) - if mult!=zero then - pskn = ps[k]*n - for j in (k+1)...n do - a[psin+j] -= mult.mult(a[pskn+j],prec) - end - end - end - end - raise "Singular matrix" if a[ps[n1]*n+n1] == zero - ps - end - - # Solves a*x = b for x, using LU decomposition. - # - # a is a matrix, b is a constant vector, x is the solution vector. - # - # ps is the pivot, a vector which indicates the permutation of rows performed - # during LU decomposition. - def lusolve(a,b,ps,zero=0.0) - prec = BigDecimal.limit(nil) - n = ps.size - x = [] - for i in 0...n do - dot = zero - psin = ps[i]*n - for j in 0...i do - dot = a[psin+j].mult(x[j],prec) + dot - end - x <<= b[ps[i]] - dot - end - (n-1).downto(0) do |i| - dot = zero - psin = ps[i]*n - for j in (i+1)...n do - dot = a[psin+j].mult(x[j],prec) + dot - end - x[i] = (x[i]-dot).div(a[psin+i],prec) - end - x - end -end diff --git a/ext/bigdecimal/lib/bigdecimal/math.rb b/ext/bigdecimal/lib/bigdecimal/math.rb deleted file mode 100644 index 0b9d0648bb3e38..00000000000000 --- a/ext/bigdecimal/lib/bigdecimal/math.rb +++ /dev/null @@ -1,232 +0,0 @@ -# frozen_string_literal: false -require 'bigdecimal' - -# -#-- -# Contents: -# sqrt(x, prec) -# sin (x, prec) -# cos (x, prec) -# atan(x, prec) Note: |x|<1, x=0.9999 may not converge. -# PI (prec) -# E (prec) == exp(1.0,prec) -# -# where: -# x ... BigDecimal number to be computed. -# |x| must be small enough to get convergence. -# prec ... Number of digits to be obtained. -#++ -# -# Provides mathematical functions. -# -# Example: -# -# require "bigdecimal/math" -# -# include BigMath -# -# a = BigDecimal((PI(100)/2).to_s) -# puts sin(a,100) # => 0.99999999999999999999......e0 -# -module BigMath - module_function - - # call-seq: - # sqrt(decimal, numeric) -> BigDecimal - # - # Computes the square root of +decimal+ to the specified number of digits of - # precision, +numeric+. - # - # BigMath.sqrt(BigDecimal('2'), 16).to_s - # #=> "0.1414213562373095048801688724e1" - # - def sqrt(x, prec) - x.sqrt(prec) - end - - # call-seq: - # sin(decimal, numeric) -> BigDecimal - # - # Computes the sine of +decimal+ to the specified number of digits of - # precision, +numeric+. - # - # If +decimal+ is Infinity or NaN, returns NaN. - # - # BigMath.sin(BigMath.PI(5)/4, 5).to_s - # #=> "0.70710678118654752440082036563292800375e0" - # - def sin(x, prec) - raise ArgumentError, "Zero or negative precision for sin" if prec <= 0 - return BigDecimal("NaN") if x.infinite? || x.nan? - n = prec + BigDecimal.double_fig - one = BigDecimal("1") - two = BigDecimal("2") - x = -x if neg = x < 0 - if x > (twopi = two * BigMath.PI(prec)) - if x > 30 - x %= twopi - else - x -= twopi while x > twopi - end - end - x1 = x - x2 = x.mult(x,n) - sign = 1 - y = x - d = y - i = one - z = one - while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0) - m = BigDecimal.double_fig if m < BigDecimal.double_fig - sign = -sign - x1 = x2.mult(x1,n) - i += two - z *= (i-one) * i - d = sign * x1.div(z,m) - y += d - end - neg ? -y : y - end - - # call-seq: - # cos(decimal, numeric) -> BigDecimal - # - # Computes the cosine of +decimal+ to the specified number of digits of - # precision, +numeric+. - # - # If +decimal+ is Infinity or NaN, returns NaN. - # - # BigMath.cos(BigMath.PI(4), 16).to_s - # #=> "-0.999999999999999999999999999999856613163740061349e0" - # - def cos(x, prec) - raise ArgumentError, "Zero or negative precision for cos" if prec <= 0 - return BigDecimal("NaN") if x.infinite? || x.nan? - n = prec + BigDecimal.double_fig - one = BigDecimal("1") - two = BigDecimal("2") - x = -x if x < 0 - if x > (twopi = two * BigMath.PI(prec)) - if x > 30 - x %= twopi - else - x -= twopi while x > twopi - end - end - x1 = one - x2 = x.mult(x,n) - sign = 1 - y = one - d = y - i = BigDecimal("0") - z = one - while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0) - m = BigDecimal.double_fig if m < BigDecimal.double_fig - sign = -sign - x1 = x2.mult(x1,n) - i += two - z *= (i-one) * i - d = sign * x1.div(z,m) - y += d - end - y - end - - # call-seq: - # atan(decimal, numeric) -> BigDecimal - # - # Computes the arctangent of +decimal+ to the specified number of digits of - # precision, +numeric+. - # - # If +decimal+ is NaN, returns NaN. - # - # BigMath.atan(BigDecimal('-1'), 16).to_s - # #=> "-0.785398163397448309615660845819878471907514682065e0" - # - def atan(x, prec) - raise ArgumentError, "Zero or negative precision for atan" if prec <= 0 - return BigDecimal("NaN") if x.nan? - pi = PI(prec) - x = -x if neg = x < 0 - return pi.div(neg ? -2 : 2, prec) if x.infinite? - return pi / (neg ? -4 : 4) if x.round(prec) == 1 - x = BigDecimal("1").div(x, prec) if inv = x > 1 - x = (-1 + sqrt(1 + x**2, prec))/x if dbl = x > 0.5 - n = prec + BigDecimal.double_fig - y = x - d = y - t = x - r = BigDecimal("3") - x2 = x.mult(x,n) - while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0) - m = BigDecimal.double_fig if m < BigDecimal.double_fig - t = -t.mult(x2,n) - d = t.div(r,m) - y += d - r += 2 - end - y *= 2 if dbl - y = pi / 2 - y if inv - y = -y if neg - y - end - - # call-seq: - # PI(numeric) -> BigDecimal - # - # Computes the value of pi to the specified number of digits of precision, - # +numeric+. - # - # BigMath.PI(10).to_s - # #=> "0.3141592653589793238462643388813853786957412e1" - # - def PI(prec) - raise ArgumentError, "Zero or negative precision for PI" if prec <= 0 - n = prec + BigDecimal.double_fig - zero = BigDecimal("0") - one = BigDecimal("1") - two = BigDecimal("2") - - m25 = BigDecimal("-0.04") - m57121 = BigDecimal("-57121") - - pi = zero - - d = one - k = one - t = BigDecimal("-80") - while d.nonzero? && ((m = n - (pi.exponent - d.exponent).abs) > 0) - m = BigDecimal.double_fig if m < BigDecimal.double_fig - t = t*m25 - d = t.div(k,m) - k = k+two - pi = pi + d - end - - d = one - k = one - t = BigDecimal("956") - while d.nonzero? && ((m = n - (pi.exponent - d.exponent).abs) > 0) - m = BigDecimal.double_fig if m < BigDecimal.double_fig - t = t.div(m57121,n) - d = t.div(k,m) - pi = pi + d - k = k+two - end - pi - end - - # call-seq: - # E(numeric) -> BigDecimal - # - # Computes e (the base of natural logarithms) to the specified number of - # digits of precision, +numeric+. - # - # BigMath.E(10).to_s - # #=> "0.271828182845904523536028752390026306410273e1" - # - def E(prec) - raise ArgumentError, "Zero or negative precision for E" if prec <= 0 - BigMath.exp(1, prec) - end -end diff --git a/ext/bigdecimal/lib/bigdecimal/newton.rb b/ext/bigdecimal/lib/bigdecimal/newton.rb deleted file mode 100644 index 85bacb7f2efbf0..00000000000000 --- a/ext/bigdecimal/lib/bigdecimal/newton.rb +++ /dev/null @@ -1,80 +0,0 @@ -# frozen_string_literal: false -require "bigdecimal/ludcmp" -require "bigdecimal/jacobian" - -# -# newton.rb -# -# Solves the nonlinear algebraic equation system f = 0 by Newton's method. -# This program is not dependent on BigDecimal. -# -# To call: -# n = nlsolve(f,x) -# where n is the number of iterations required, -# x is the initial value vector -# f is an Object which is used to compute the values of the equations to be solved. -# It must provide the following methods: -# -# f.values(x):: returns the values of all functions at x -# -# f.zero:: returns 0.0 -# f.one:: returns 1.0 -# f.two:: returns 2.0 -# f.ten:: returns 10.0 -# -# f.eps:: returns the convergence criterion (epsilon value) used to determine whether two values are considered equal. If |a-b| < epsilon, the two values are considered equal. -# -# On exit, x is the solution vector. -# -module Newton - include LUSolve - include Jacobian - module_function - - def norm(fv,zero=0.0) # :nodoc: - s = zero - n = fv.size - for i in 0...n do - s += fv[i]*fv[i] - end - s - end - - # See also Newton - def nlsolve(f,x) - nRetry = 0 - n = x.size - - f0 = f.values(x) - zero = f.zero - one = f.one - two = f.two - p5 = one/two - d = norm(f0,zero) - minfact = f.ten*f.ten*f.ten - minfact = one/minfact - e = f.eps - while d >= e do - nRetry += 1 - # Not yet converged. => Compute Jacobian matrix - dfdx = jacobian(f,f0,x) - # Solve dfdx*dx = -f0 to estimate dx - dx = lusolve(dfdx,f0,ludecomp(dfdx,n,zero,one),zero) - fact = two - xs = x.dup - begin - fact *= p5 - if fact < minfact then - raise "Failed to reduce function values." - end - for i in 0...n do - x[i] = xs[i] - dx[i]*fact - end - f0 = f.values(x) - dn = norm(f0,zero) - end while(dn>=d) - d = dn - end - nRetry - end -end diff --git a/ext/bigdecimal/lib/bigdecimal/util.rb b/ext/bigdecimal/lib/bigdecimal/util.rb deleted file mode 100644 index 8bfc0ed8ed2a7d..00000000000000 --- a/ext/bigdecimal/lib/bigdecimal/util.rb +++ /dev/null @@ -1,185 +0,0 @@ -# frozen_string_literal: false -# -#-- -# bigdecimal/util extends various native classes to provide the #to_d method, -# and provides BigDecimal#to_d and BigDecimal#to_digits. -#++ - -require 'bigdecimal' - -class Integer < Numeric - # call-seq: - # int.to_d -> bigdecimal - # - # Returns the value of +int+ as a BigDecimal. - # - # require 'bigdecimal' - # require 'bigdecimal/util' - # - # 42.to_d # => 0.42e2 - # - # See also Kernel.BigDecimal. - # - def to_d - BigDecimal(self) - end -end - - -class Float < Numeric - # call-seq: - # float.to_d -> bigdecimal - # float.to_d(precision) -> bigdecimal - # - # Returns the value of +float+ as a BigDecimal. - # The +precision+ parameter is used to determine the number of - # 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 Kernel.BigDecimal. - # - def to_d(precision=0) - BigDecimal(self, precision) - end -end - - -class String - # call-seq: - # str.to_d -> bigdecimal - # - # Returns the result of interpreting leading characters in +str+ - # as a BigDecimal. - # - # require 'bigdecimal' - # require 'bigdecimal/util' - # - # "0.5".to_d # => 0.5e0 - # "123.45e1".to_d # => 0.12345e4 - # "45.67 degrees".to_d # => 0.4567e2 - # - # See also Kernel.BigDecimal. - # - def to_d - BigDecimal.interpret_loosely(self) - end -end - - -class BigDecimal < Numeric - # call-seq: - # a.to_digits -> string - # - # Converts a BigDecimal to a String of the form "nnnnnn.mmm". - # This method is deprecated; use BigDecimal#to_s("F") instead. - # - # require 'bigdecimal/util' - # - # d = BigDecimal("3.14") - # d.to_digits # => "3.14" - # - def to_digits - if self.nan? || self.infinite? || self.zero? - self.to_s - else - i = self.to_i.to_s - _,f,_,z = self.frac.split - i + "." + ("0"*(-z)) + f - end - end - - # call-seq: - # a.to_d -> bigdecimal - # - # Returns self. - # - # require 'bigdecimal/util' - # - # d = BigDecimal("3.14") - # d.to_d # => 0.314e1 - # - def to_d - self - end -end - - -class Rational < Numeric - # call-seq: - # rat.to_d(precision) -> bigdecimal - # - # Returns the value as a BigDecimal. - # - # The required +precision+ parameter is used to determine the number of - # significant digits for the result. - # - # require 'bigdecimal' - # require 'bigdecimal/util' - # - # Rational(22, 7).to_d(3) # => 0.314e1 - # - # See also Kernel.BigDecimal. - # - def to_d(precision) - BigDecimal(self, precision) - end -end - - -class Complex < Numeric - # call-seq: - # cmp.to_d -> bigdecimal - # cmp.to_d(precision) -> bigdecimal - # - # Returns the value as a BigDecimal. - # - # The +precision+ parameter is required for a rational complex number. - # This parameter is used to determine the number of significant digits - # for the result. - # - # require 'bigdecimal' - # require 'bigdecimal/util' - # - # Complex(0.1234567, 0).to_d(4) # => 0.1235e0 - # Complex(Rational(22, 7), 0).to_d(3) # => 0.314e1 - # - # See also Kernel.BigDecimal. - # - def to_d(*args) - BigDecimal(self) unless self.imag.zero? # to raise eerror - - if args.length == 0 - case self.real - when Rational - BigDecimal(self.real) # to raise error - end - end - self.real.to_d(*args) - end -end - - -class NilClass - # call-seq: - # nil.to_d -> bigdecimal - # - # Returns nil represented as a BigDecimal. - # - # require 'bigdecimal' - # require 'bigdecimal/util' - # - # nil.to_d # => 0.0 - # - def to_d - BigDecimal(0) - end -end diff --git a/ext/bigdecimal/missing.c b/ext/bigdecimal/missing.c deleted file mode 100644 index 703232d92f7716..00000000000000 --- a/ext/bigdecimal/missing.c +++ /dev/null @@ -1,27 +0,0 @@ -#include - -#ifdef HAVE_RUBY_ATOMIC_H -# include -#endif - -#ifdef RUBY_ATOMIC_PTR_CAS -# define ATOMIC_PTR_CAS(var, old, new) RUBY_ATOMIC_PTR_CAS(var, old, new) -#endif - -#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) -/* GCC warns about unknown sanitizer, which is annoying. */ -# undef NO_SANITIZE -# define NO_SANITIZE(x, y) \ - _Pragma("GCC diagnostic push") \ - _Pragma("GCC diagnostic ignored \"-Wattributes\"") \ - __attribute__((__no_sanitize__(x))) y; \ - _Pragma("GCC diagnostic pop") -#endif - -#undef strtod -#define strtod BigDecimal_strtod -#undef dtoa -#define dtoa BigDecimal_dtoa -#undef hdtoa -#define hdtoa BigDecimal_hdtoa -#include "missing/dtoa.c" diff --git a/ext/bigdecimal/missing.h b/ext/bigdecimal/missing.h deleted file mode 100644 index 325554b5f536d3..00000000000000 --- a/ext/bigdecimal/missing.h +++ /dev/null @@ -1,196 +0,0 @@ -#ifndef MISSING_H -#define MISSING_H 1 - -#if defined(__cplusplus) -extern "C" { -#if 0 -} /* satisfy cc-mode */ -#endif -#endif - -#ifdef HAVE_STDLIB_H -# include -#endif - -#ifdef HAVE_MATH_H -# include -#endif - -#ifndef RB_UNUSED_VAR -# if defined(_MSC_VER) && _MSC_VER >= 1911 -# define RB_UNUSED_VAR(x) x [[maybe_unused]] - -# elif defined(__has_cpp_attribute) && __has_cpp_attribute(maybe_unused) -# define RB_UNUSED_VAR(x) x [[maybe_unused]] - -# elif defined(__has_c_attribute) && __has_c_attribute(maybe_unused) -# define RB_UNUSED_VAR(x) x [[maybe_unused]] - -# elif defined(__GNUC__) -# define RB_UNUSED_VAR(x) x __attribute__ ((unused)) - -# else -# define RB_UNUSED_VAR(x) x -# endif -#endif /* RB_UNUSED_VAR */ - -#if defined(_MSC_VER) && _MSC_VER >= 1310 -# define HAVE___ASSUME 1 - -#elif defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1300 -# define HAVE___ASSUME 1 -#endif - -#ifndef UNREACHABLE -# if __has_builtin(__builtin_unreachable) -# define UNREACHABLE __builtin_unreachable() - -# elif defined(HAVE___ASSUME) -# define UNREACHABLE __assume(0) - -# else -# define UNREACHABLE /* unreachable */ -# endif -#endif /* UNREACHABLE */ - -/* bool */ - -#if defined(__bool_true_false_are_defined) -# /* Take that. */ - -#elif defined(HAVE_STDBOOL_H) -# include - -#else -typedef unsigned char _Bool; -# define bool _Bool -# define true ((_Bool)+1) -# define false ((_Bool)-1) -# define __bool_true_false_are_defined -#endif - -/* abs */ - -#ifndef HAVE_LABS -static inline long -labs(long const x) -{ - if (x < 0) return -x; - return x; -} -#endif - -#ifndef HAVE_LLABS -static inline LONG_LONG -llabs(LONG_LONG const x) -{ - if (x < 0) return -x; - return x; -} -#endif - -#ifdef vabs -# undef vabs -#endif -#if SIZEOF_VALUE <= SIZEOF_INT -# define vabs abs -#elif SIZEOF_VALUE <= SIZEOF_LONG -# define vabs labs -#elif SIZEOF_VALUE <= SIZEOF_LONG_LONG -# define vabs llabs -#endif - -/* finite */ - -#ifndef HAVE_FINITE -static int -finite(double) -{ - return !isnan(n) && !isinf(n); -} -#endif - -#ifndef isfinite -# ifndef HAVE_ISFINITE -# define HAVE_ISFINITE 1 -# define isfinite(x) finite(x) -# endif -#endif - -/* dtoa */ -char *BigDecimal_dtoa(double d_, int mode, int ndigits, int *decpt, int *sign, char **rve); - -/* rational */ - -#ifndef HAVE_RB_RATIONAL_NUM -static inline VALUE -rb_rational_num(VALUE rat) -{ -#ifdef RRATIONAL - return RRATIONAL(rat)->num; -#else - return rb_funcall(rat, rb_intern("numerator"), 0); -#endif -} -#endif - -#ifndef HAVE_RB_RATIONAL_DEN -static inline VALUE -rb_rational_den(VALUE rat) -{ -#ifdef RRATIONAL - return RRATIONAL(rat)->den; -#else - return rb_funcall(rat, rb_intern("denominator"), 0); -#endif -} -#endif - -/* complex */ - -#ifndef HAVE_RB_COMPLEX_REAL -static inline VALUE -rb_complex_real(VALUE cmp) -{ -#ifdef RCOMPLEX - return RCOMPLEX(cmp)->real; -#else - return rb_funcall(cmp, rb_intern("real"), 0); -#endif -} -#endif - -#ifndef HAVE_RB_COMPLEX_IMAG -static inline VALUE -rb_complex_imag(VALUE cmp) -{ -# ifdef RCOMPLEX - return RCOMPLEX(cmp)->imag; -# else - return rb_funcall(cmp, rb_intern("imag"), 0); -# endif -} -#endif - -/* st */ - -#ifndef ST2FIX -# undef RB_ST2FIX -# define RB_ST2FIX(h) LONG2FIX((long)(h)) -# define ST2FIX(h) RB_ST2FIX(h) -#endif - -/* warning */ - -#if !defined(HAVE_RB_CATEGORY_WARN) || !defined(HAVE_CONST_RB_WARN_CATEGORY_DEPRECATED) -# define rb_category_warn(category, ...) rb_warn(__VA_ARGS__) -#endif - -#if defined(__cplusplus) -#if 0 -{ /* satisfy cc-mode */ -#endif -} /* extern "C" { */ -#endif - -#endif /* MISSING_H */ diff --git a/ext/bigdecimal/missing/dtoa.c b/ext/bigdecimal/missing/dtoa.c deleted file mode 100644 index 41b0a221d14f4b..00000000000000 --- a/ext/bigdecimal/missing/dtoa.c +++ /dev/null @@ -1,3462 +0,0 @@ -/**************************************************************** - * - * The author of this software is David M. Gay. - * - * Copyright (c) 1991, 2000, 2001 by Lucent Technologies. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY - * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - * - ***************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -/* On a machine with IEEE extended-precision registers, it is - * necessary to specify double-precision (53-bit) rounding precision - * before invoking strtod or dtoa. If the machine uses (the equivalent - * of) Intel 80x87 arithmetic, the call - * _control87(PC_53, MCW_PC); - * does this with many compilers. Whether this or another call is - * appropriate depends on the compiler; for this to work, it may be - * necessary to #include "float.h" or another system-dependent header - * file. - */ - -/* strtod for IEEE-, VAX-, and IBM-arithmetic machines. - * - * This strtod returns a nearest machine number to the input decimal - * string (or sets errno to ERANGE). With IEEE arithmetic, ties are - * broken by the IEEE round-even rule. Otherwise ties are broken by - * biased rounding (add half and chop). - * - * Inspired loosely by William D. Clinger's paper "How to Read Floating - * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101]. - * - * Modifications: - * - * 1. We only require IEEE, IBM, or VAX double-precision - * arithmetic (not IEEE double-extended). - * 2. We get by with floating-point arithmetic in a case that - * Clinger missed -- when we're computing d * 10^n - * for a small integer d and the integer n is not too - * much larger than 22 (the maximum integer k for which - * we can represent 10^k exactly), we may be able to - * compute (d*10^k) * 10^(e-k) with just one roundoff. - * 3. Rather than a bit-at-a-time adjustment of the binary - * result in the hard case, we use floating-point - * arithmetic to determine the adjustment to within - * one bit; only in really hard cases do we need to - * compute a second residual. - * 4. Because of 3., we don't need a large table of powers of 10 - * for ten-to-e (just some small tables, e.g. of 10^k - * for 0 <= k <= 22). - */ - -/* - * #define IEEE_LITTLE_ENDIAN for IEEE-arithmetic machines where the least - * significant byte has the lowest address. - * #define IEEE_BIG_ENDIAN for IEEE-arithmetic machines where the most - * significant byte has the lowest address. - * #define Long int on machines with 32-bit ints and 64-bit longs. - * #define IBM for IBM mainframe-style floating-point arithmetic. - * #define VAX for VAX-style floating-point arithmetic (D_floating). - * #define No_leftright to omit left-right logic in fast floating-point - * computation of dtoa. - * #define Honor_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3 - * and strtod and dtoa should round accordingly. - * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3 - * and Honor_FLT_ROUNDS is not #defined. - * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines - * that use extended-precision instructions to compute rounded - * products and quotients) with IBM. - * #define ROUND_BIASED for IEEE-format with biased rounding. - * #define Inaccurate_Divide for IEEE-format with correctly rounded - * products but inaccurate quotients, e.g., for Intel i860. - * #define NO_LONG_LONG on machines that do not have a "long long" - * integer type (of >= 64 bits). On such machines, you can - * #define Just_16 to store 16 bits per 32-bit Long when doing - * high-precision integer arithmetic. Whether this speeds things - * up or slows things down depends on the machine and the number - * being converted. If long long is available and the name is - * something other than "long long", #define Llong to be the name, - * and if "unsigned Llong" does not work as an unsigned version of - * Llong, #define #ULLong to be the corresponding unsigned type. - * #define KR_headers for old-style C function headers. - * #define Bad_float_h if your system lacks a float.h or if it does not - * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP, - * FLT_RADIX, FLT_ROUNDS, and DBL_MAX. - * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n) - * if memory is available and otherwise does something you deem - * appropriate. If MALLOC is undefined, malloc will be invoked - * directly -- and assumed always to succeed. - * #define Omit_Private_Memory to omit logic (added Jan. 1998) for making - * memory allocations from a private pool of memory when possible. - * When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes, - * unless #defined to be a different length. This default length - * suffices to get rid of MALLOC calls except for unusual cases, - * such as decimal-to-binary conversion of a very long string of - * digits. The longest string dtoa can return is about 751 bytes - * long. For conversions by strtod of strings of 800 digits and - * all dtoa conversions in single-threaded executions with 8-byte - * pointers, PRIVATE_MEM >= 7400 appears to suffice; with 4-byte - * pointers, PRIVATE_MEM >= 7112 appears adequate. - * #define INFNAN_CHECK on IEEE systems to cause strtod to check for - * Infinity and NaN (case insensitively). On some systems (e.g., - * some HP systems), it may be necessary to #define NAN_WORD0 - * appropriately -- to the most significant word of a quiet NaN. - * (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.) - * When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined, - * strtod also accepts (case insensitively) strings of the form - * NaN(x), where x is a string of hexadecimal digits and spaces; - * if there is only one string of hexadecimal digits, it is taken - * for the 52 fraction bits of the resulting NaN; if there are two - * or more strings of hex digits, the first is for the high 20 bits, - * the second and subsequent for the low 32 bits, with intervening - * white space ignored; but if this results in none of the 52 - * fraction bits being on (an IEEE Infinity symbol), then NAN_WORD0 - * and NAN_WORD1 are used instead. - * #define MULTIPLE_THREADS if the system offers preemptively scheduled - * multiple threads. In this case, you must provide (or suitably - * #define) two locks, acquired by ACQUIRE_DTOA_LOCK(n) and freed - * by FREE_DTOA_LOCK(n) for n = 0 or 1. (The second lock, accessed - * in pow5mult, ensures lazy evaluation of only one copy of high - * powers of 5; omitting this lock would introduce a small - * probability of wasting memory, but would otherwise be harmless.) - * You must also invoke freedtoa(s) to free the value s returned by - * dtoa. You may do so whether or not MULTIPLE_THREADS is #defined. - * #define NO_IEEE_Scale to disable new (Feb. 1997) logic in strtod that - * avoids underflows on inputs whose result does not underflow. - * If you #define NO_IEEE_Scale on a machine that uses IEEE-format - * floating-point numbers and flushes underflows to zero rather - * than implementing gradual underflow, then you must also #define - * Sudden_Underflow. - * #define YES_ALIAS to permit aliasing certain double values with - * arrays of ULongs. This leads to slightly better code with - * some compilers and was always used prior to 19990916, but it - * is not strictly legal and can cause trouble with aggressively - * optimizing compilers (e.g., gcc 2.95.1 under -O2). - * #define USE_LOCALE to use the current locale's decimal_point value. - * #define SET_INEXACT if IEEE arithmetic is being used and extra - * computation should be done to set the inexact flag when the - * result is inexact and avoid setting inexact when the result - * is exact. In this case, dtoa.c must be compiled in - * an environment, perhaps provided by #include "dtoa.c" in a - * suitable wrapper, that defines two functions, - * int get_inexact(void); - * void clear_inexact(void); - * such that get_inexact() returns a nonzero value if the - * inexact bit is already set, and clear_inexact() sets the - * inexact bit to 0. When SET_INEXACT is #defined, strtod - * also does extra computations to set the underflow and overflow - * flags when appropriate (i.e., when the result is tiny and - * inexact or when it is a numeric value rounded to +-infinity). - * #define NO_ERRNO if strtod should not assign errno = ERANGE when - * the result overflows to +-Infinity or underflows to 0. - */ - -#ifdef WORDS_BIGENDIAN -#define IEEE_BIG_ENDIAN -#else -#define IEEE_LITTLE_ENDIAN -#endif - -#ifdef __vax__ -#define VAX -#undef IEEE_BIG_ENDIAN -#undef IEEE_LITTLE_ENDIAN -#endif - -#if defined(__arm__) && !defined(__VFP_FP__) -#define IEEE_BIG_ENDIAN -#undef IEEE_LITTLE_ENDIAN -#endif - -#undef Long -#undef ULong - -#include - -#if (INT_MAX >> 30) && !(INT_MAX >> 31) -#define Long int -#define ULong unsigned int -#elif (LONG_MAX >> 30) && !(LONG_MAX >> 31) -#define Long long int -#define ULong unsigned long int -#else -#error No 32bit integer -#endif - -#if HAVE_LONG_LONG -#define Llong LONG_LONG -#else -#define NO_LONG_LONG -#endif - -#ifdef DEBUG -#include -#define Bug(x) {fprintf(stderr, "%s\n", (x)); exit(EXIT_FAILURE);} -#endif - -#ifndef ISDIGIT -#include -#define ISDIGIT(c) isdigit(c) -#endif -#include -#include -#include - -#ifdef USE_LOCALE -#include -#endif - -#ifdef MALLOC -extern void *MALLOC(size_t); -#else -#define MALLOC xmalloc -#endif -#ifdef FREE -extern void FREE(void*); -#else -#define FREE xfree -#endif -#ifndef NO_SANITIZE -#define NO_SANITIZE(x, y) y -#endif - -#ifndef Omit_Private_Memory -#ifndef PRIVATE_MEM -#define PRIVATE_MEM 2304 -#endif -#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double)) -static double private_mem[PRIVATE_mem], *pmem_next = private_mem; -#endif - -#undef IEEE_Arith -#undef Avoid_Underflow -#ifdef IEEE_BIG_ENDIAN -#define IEEE_Arith -#endif -#ifdef IEEE_LITTLE_ENDIAN -#define IEEE_Arith -#endif - -#ifdef Bad_float_h - -#ifdef IEEE_Arith -#define DBL_DIG 15 -#define DBL_MAX_10_EXP 308 -#define DBL_MAX_EXP 1024 -#define FLT_RADIX 2 -#endif /*IEEE_Arith*/ - -#ifdef IBM -#define DBL_DIG 16 -#define DBL_MAX_10_EXP 75 -#define DBL_MAX_EXP 63 -#define FLT_RADIX 16 -#define DBL_MAX 7.2370055773322621e+75 -#endif - -#ifdef VAX -#define DBL_DIG 16 -#define DBL_MAX_10_EXP 38 -#define DBL_MAX_EXP 127 -#define FLT_RADIX 2 -#define DBL_MAX 1.7014118346046923e+38 -#endif - -#ifndef LONG_MAX -#define LONG_MAX 2147483647 -#endif - -#else /* ifndef Bad_float_h */ -#include -#endif /* Bad_float_h */ - -#include - -#ifdef __cplusplus -extern "C" { -#if 0 -} /* satisfy cc-mode */ -#endif -#endif - -#ifndef hexdigit -static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF"; -#endif - -#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN) + defined(VAX) + defined(IBM) != 1 -Exactly one of IEEE_LITTLE_ENDIAN, IEEE_BIG_ENDIAN, VAX, or IBM should be defined. -#endif - -typedef union { double d; ULong L[2]; } U; - -#ifdef YES_ALIAS -typedef double double_u; -# define dval(x) (x) -# ifdef IEEE_LITTLE_ENDIAN -# define word0(x) (((ULong *)&(x))[1]) -# define word1(x) (((ULong *)&(x))[0]) -# else -# define word0(x) (((ULong *)&(x))[0]) -# define word1(x) (((ULong *)&(x))[1]) -# endif -#else -typedef U double_u; -# ifdef IEEE_LITTLE_ENDIAN -# define word0(x) ((x).L[1]) -# define word1(x) ((x).L[0]) -# else -# define word0(x) ((x).L[0]) -# define word1(x) ((x).L[1]) -# endif -# define dval(x) ((x).d) -#endif - -/* The following definition of Storeinc is appropriate for MIPS processors. - * An alternative that might be better on some machines is - * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff) - */ -#if defined(IEEE_LITTLE_ENDIAN) + defined(VAX) + defined(__arm__) -#define Storeinc(a,b,c) (((unsigned short *)(a))[1] = (unsigned short)(b), \ -((unsigned short *)(a))[0] = (unsigned short)(c), (a)++) -#else -#define Storeinc(a,b,c) (((unsigned short *)(a))[0] = (unsigned short)(b), \ -((unsigned short *)(a))[1] = (unsigned short)(c), (a)++) -#endif - -/* #define P DBL_MANT_DIG */ -/* Ten_pmax = floor(P*log(2)/log(5)) */ -/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */ -/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */ -/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */ - -#ifdef IEEE_Arith -#define Exp_shift 20 -#define Exp_shift1 20 -#define Exp_msk1 0x100000 -#define Exp_msk11 0x100000 -#define Exp_mask 0x7ff00000 -#define P 53 -#define Bias 1023 -#define Emin (-1022) -#define Exp_1 0x3ff00000 -#define Exp_11 0x3ff00000 -#define Ebits 11 -#define Frac_mask 0xfffff -#define Frac_mask1 0xfffff -#define Ten_pmax 22 -#define Bletch 0x10 -#define Bndry_mask 0xfffff -#define Bndry_mask1 0xfffff -#define LSB 1 -#define Sign_bit 0x80000000 -#define Log2P 1 -#define Tiny0 0 -#define Tiny1 1 -#define Quick_max 14 -#define Int_max 14 -#ifndef NO_IEEE_Scale -#define Avoid_Underflow -#ifdef Flush_Denorm /* debugging option */ -#undef Sudden_Underflow -#endif -#endif - -#ifndef Flt_Rounds -#ifdef FLT_ROUNDS -#define Flt_Rounds FLT_ROUNDS -#else -#define Flt_Rounds 1 -#endif -#endif /*Flt_Rounds*/ - -#ifdef Honor_FLT_ROUNDS -#define Rounding rounding -#undef Check_FLT_ROUNDS -#define Check_FLT_ROUNDS -#else -#define Rounding Flt_Rounds -#endif - -#else /* ifndef IEEE_Arith */ -#undef Check_FLT_ROUNDS -#undef Honor_FLT_ROUNDS -#undef SET_INEXACT -#undef Sudden_Underflow -#define Sudden_Underflow -#ifdef IBM -#undef Flt_Rounds -#define Flt_Rounds 0 -#define Exp_shift 24 -#define Exp_shift1 24 -#define Exp_msk1 0x1000000 -#define Exp_msk11 0x1000000 -#define Exp_mask 0x7f000000 -#define P 14 -#define Bias 65 -#define Exp_1 0x41000000 -#define Exp_11 0x41000000 -#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */ -#define Frac_mask 0xffffff -#define Frac_mask1 0xffffff -#define Bletch 4 -#define Ten_pmax 22 -#define Bndry_mask 0xefffff -#define Bndry_mask1 0xffffff -#define LSB 1 -#define Sign_bit 0x80000000 -#define Log2P 4 -#define Tiny0 0x100000 -#define Tiny1 0 -#define Quick_max 14 -#define Int_max 15 -#else /* VAX */ -#undef Flt_Rounds -#define Flt_Rounds 1 -#define Exp_shift 23 -#define Exp_shift1 7 -#define Exp_msk1 0x80 -#define Exp_msk11 0x800000 -#define Exp_mask 0x7f80 -#define P 56 -#define Bias 129 -#define Exp_1 0x40800000 -#define Exp_11 0x4080 -#define Ebits 8 -#define Frac_mask 0x7fffff -#define Frac_mask1 0xffff007f -#define Ten_pmax 24 -#define Bletch 2 -#define Bndry_mask 0xffff007f -#define Bndry_mask1 0xffff007f -#define LSB 0x10000 -#define Sign_bit 0x8000 -#define Log2P 1 -#define Tiny0 0x80 -#define Tiny1 0 -#define Quick_max 15 -#define Int_max 15 -#endif /* IBM, VAX */ -#endif /* IEEE_Arith */ - -#ifndef IEEE_Arith -#define ROUND_BIASED -#endif - -#ifdef RND_PRODQUOT -#define rounded_product(a,b) ((a) = rnd_prod((a), (b))) -#define rounded_quotient(a,b) ((a) = rnd_quot((a), (b))) -extern double rnd_prod(double, double), rnd_quot(double, double); -#else -#define rounded_product(a,b) ((a) *= (b)) -#define rounded_quotient(a,b) ((a) /= (b)) -#endif - -#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1)) -#define Big1 0xffffffff - -#ifndef Pack_32 -#define Pack_32 -#endif - -#define FFFFFFFF 0xffffffffUL - -#ifdef NO_LONG_LONG -#undef ULLong -#ifdef Just_16 -#undef Pack_32 -/* When Pack_32 is not defined, we store 16 bits per 32-bit Long. - * This makes some inner loops simpler and sometimes saves work - * during multiplications, but it often seems to make things slightly - * slower. Hence the default is now to store 32 bits per Long. - */ -#endif -#else /* long long available */ -#ifndef Llong -#define Llong long long -#endif -#ifndef ULLong -#define ULLong unsigned Llong -#endif -#endif /* NO_LONG_LONG */ - -#define MULTIPLE_THREADS 1 - -#ifndef MULTIPLE_THREADS -#define ACQUIRE_DTOA_LOCK(n) /*nothing*/ -#define FREE_DTOA_LOCK(n) /*nothing*/ -#else -#define ACQUIRE_DTOA_LOCK(n) /*unused right now*/ -#define FREE_DTOA_LOCK(n) /*unused right now*/ -#endif - -#ifndef ATOMIC_PTR_CAS -#define ATOMIC_PTR_CAS(var, old, new) ((var) = (new), (old)) -#endif -#ifndef LIKELY -#define LIKELY(x) (x) -#endif -#ifndef UNLIKELY -#define UNLIKELY(x) (x) -#endif -#ifndef ASSUME -#define ASSUME(x) (void)(x) -#endif - -#define Kmax 15 - -struct Bigint { - struct Bigint *next; - int k, maxwds, sign, wds; - ULong x[1]; -}; - -typedef struct Bigint Bigint; - -static Bigint *freelist[Kmax+1]; - -static Bigint * -Balloc(int k) -{ - int x; - Bigint *rv; -#ifndef Omit_Private_Memory - size_t len; -#endif - - rv = 0; - ACQUIRE_DTOA_LOCK(0); - if (k <= Kmax) { - rv = freelist[k]; - while (rv) { - Bigint *rvn = rv; - rv = ATOMIC_PTR_CAS(freelist[k], rv, rv->next); - if (LIKELY(rvn == rv)) { - ASSUME(rv); - break; - } - } - } - if (!rv) { - x = 1 << k; -#ifdef Omit_Private_Memory - rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong)); -#else - len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1) - /sizeof(double); - if (k <= Kmax) { - double *pnext = pmem_next; - while (pnext - private_mem + len <= PRIVATE_mem) { - double *p = pnext; - pnext = ATOMIC_PTR_CAS(pmem_next, pnext, pnext + len); - if (LIKELY(p == pnext)) { - rv = (Bigint*)pnext; - ASSUME(rv); - break; - } - } - } - if (!rv) - rv = (Bigint*)MALLOC(len*sizeof(double)); -#endif - rv->k = k; - rv->maxwds = x; - } - FREE_DTOA_LOCK(0); - rv->sign = rv->wds = 0; - return rv; -} - -static void -Bfree(Bigint *v) -{ - Bigint *vn; - if (v) { - if (v->k > Kmax) { - FREE(v); - return; - } - ACQUIRE_DTOA_LOCK(0); - do { - vn = v->next = freelist[v->k]; - } while (UNLIKELY(ATOMIC_PTR_CAS(freelist[v->k], vn, v) != vn)); - FREE_DTOA_LOCK(0); - } -} - -#define Bcopy(x,y) memcpy((char *)&(x)->sign, (char *)&(y)->sign, \ -(y)->wds*sizeof(Long) + 2*sizeof(int)) - -static Bigint * -multadd(Bigint *b, int m, int a) /* multiply by m and add a */ -{ - int i, wds; - ULong *x; -#ifdef ULLong - ULLong carry, y; -#else - ULong carry, y; -#ifdef Pack_32 - ULong xi, z; -#endif -#endif - Bigint *b1; - - wds = b->wds; - x = b->x; - i = 0; - carry = a; - do { -#ifdef ULLong - y = *x * (ULLong)m + carry; - carry = y >> 32; - *x++ = (ULong)(y & FFFFFFFF); -#else -#ifdef Pack_32 - xi = *x; - y = (xi & 0xffff) * m + carry; - z = (xi >> 16) * m + (y >> 16); - carry = z >> 16; - *x++ = (z << 16) + (y & 0xffff); -#else - y = *x * m + carry; - carry = y >> 16; - *x++ = y & 0xffff; -#endif -#endif - } while (++i < wds); - if (carry) { - if (wds >= b->maxwds) { - b1 = Balloc(b->k+1); - Bcopy(b1, b); - Bfree(b); - b = b1; - } - b->x[wds++] = (ULong)carry; - b->wds = wds; - } - return b; -} - -static Bigint * -s2b(const char *s, int nd0, int nd, ULong y9) -{ - Bigint *b; - int i, k; - Long x, y; - - x = (nd + 8) / 9; - for (k = 0, y = 1; x > y; y <<= 1, k++) ; -#ifdef Pack_32 - b = Balloc(k); - b->x[0] = y9; - b->wds = 1; -#else - b = Balloc(k+1); - b->x[0] = y9 & 0xffff; - b->wds = (b->x[1] = y9 >> 16) ? 2 : 1; -#endif - - i = 9; - if (9 < nd0) { - s += 9; - do { - b = multadd(b, 10, *s++ - '0'); - } while (++i < nd0); - s++; - } - else - s += 10; - for (; i < nd; i++) - b = multadd(b, 10, *s++ - '0'); - return b; -} - -static int -hi0bits(register ULong x) -{ - register int k = 0; - - if (!(x & 0xffff0000)) { - k = 16; - x <<= 16; - } - if (!(x & 0xff000000)) { - k += 8; - x <<= 8; - } - if (!(x & 0xf0000000)) { - k += 4; - x <<= 4; - } - if (!(x & 0xc0000000)) { - k += 2; - x <<= 2; - } - if (!(x & 0x80000000)) { - k++; - if (!(x & 0x40000000)) - return 32; - } - return k; -} - -static int -lo0bits(ULong *y) -{ - register int k; - register ULong x = *y; - - if (x & 7) { - if (x & 1) - return 0; - if (x & 2) { - *y = x >> 1; - return 1; - } - *y = x >> 2; - return 2; - } - k = 0; - if (!(x & 0xffff)) { - k = 16; - x >>= 16; - } - if (!(x & 0xff)) { - k += 8; - x >>= 8; - } - if (!(x & 0xf)) { - k += 4; - x >>= 4; - } - if (!(x & 0x3)) { - k += 2; - x >>= 2; - } - if (!(x & 1)) { - k++; - x >>= 1; - if (!x) - return 32; - } - *y = x; - return k; -} - -static Bigint * -i2b(int i) -{ - Bigint *b; - - b = Balloc(1); - b->x[0] = i; - b->wds = 1; - return b; -} - -static Bigint * -mult(Bigint *a, Bigint *b) -{ - Bigint *c; - int k, wa, wb, wc; - ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0; - ULong y; -#ifdef ULLong - ULLong carry, z; -#else - ULong carry, z; -#ifdef Pack_32 - ULong z2; -#endif -#endif - - if (a->wds < b->wds) { - c = a; - a = b; - b = c; - } - k = a->k; - wa = a->wds; - wb = b->wds; - wc = wa + wb; - if (wc > a->maxwds) - k++; - c = Balloc(k); - for (x = c->x, xa = x + wc; x < xa; x++) - *x = 0; - xa = a->x; - xae = xa + wa; - xb = b->x; - xbe = xb + wb; - xc0 = c->x; -#ifdef ULLong - for (; xb < xbe; xc0++) { - if ((y = *xb++) != 0) { - x = xa; - xc = xc0; - carry = 0; - do { - z = *x++ * (ULLong)y + *xc + carry; - carry = z >> 32; - *xc++ = (ULong)(z & FFFFFFFF); - } while (x < xae); - *xc = (ULong)carry; - } - } -#else -#ifdef Pack_32 - for (; xb < xbe; xb++, xc0++) { - if ((y = *xb & 0xffff) != 0) { - x = xa; - xc = xc0; - carry = 0; - do { - z = (*x & 0xffff) * y + (*xc & 0xffff) + carry; - carry = z >> 16; - z2 = (*x++ >> 16) * y + (*xc >> 16) + carry; - carry = z2 >> 16; - Storeinc(xc, z2, z); - } while (x < xae); - *xc = (ULong)carry; - } - if ((y = *xb >> 16) != 0) { - x = xa; - xc = xc0; - carry = 0; - z2 = *xc; - do { - z = (*x & 0xffff) * y + (*xc >> 16) + carry; - carry = z >> 16; - Storeinc(xc, z, z2); - z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry; - carry = z2 >> 16; - } while (x < xae); - *xc = z2; - } - } -#else - for (; xb < xbe; xc0++) { - if (y = *xb++) { - x = xa; - xc = xc0; - carry = 0; - do { - z = *x++ * y + *xc + carry; - carry = z >> 16; - *xc++ = z & 0xffff; - } while (x < xae); - *xc = (ULong)carry; - } - } -#endif -#endif - for (xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ; - c->wds = wc; - return c; -} - -static Bigint *p5s; - -static Bigint * -pow5mult(Bigint *b, int k) -{ - Bigint *b1, *p5, *p51; - Bigint *p5tmp; - int i; - static const int p05[3] = { 5, 25, 125 }; - - if ((i = k & 3) != 0) - b = multadd(b, p05[i-1], 0); - - if (!(k >>= 2)) - return b; - if (!(p5 = p5s)) { - /* first time */ - ACQUIRE_DTOA_LOCK(1); - if (!(p5 = p5s)) { - p5 = i2b(625); - p5->next = 0; - p5tmp = ATOMIC_PTR_CAS(p5s, NULL, p5); - if (UNLIKELY(p5tmp)) { - Bfree(p5); - p5 = p5tmp; - } - } - FREE_DTOA_LOCK(1); - } - for (;;) { - if (k & 1) { - b1 = mult(b, p5); - Bfree(b); - b = b1; - } - if (!(k >>= 1)) - break; - if (!(p51 = p5->next)) { - ACQUIRE_DTOA_LOCK(1); - if (!(p51 = p5->next)) { - p51 = mult(p5,p5); - p51->next = 0; - p5tmp = ATOMIC_PTR_CAS(p5->next, NULL, p51); - if (UNLIKELY(p5tmp)) { - Bfree(p51); - p51 = p5tmp; - } - } - FREE_DTOA_LOCK(1); - } - p5 = p51; - } - return b; -} - -static Bigint * -lshift(Bigint *b, int k) -{ - int i, k1, n, n1; - Bigint *b1; - ULong *x, *x1, *xe, z; - -#ifdef Pack_32 - n = k >> 5; -#else - n = k >> 4; -#endif - k1 = b->k; - n1 = n + b->wds + 1; - for (i = b->maxwds; n1 > i; i <<= 1) - k1++; - b1 = Balloc(k1); - x1 = b1->x; - for (i = 0; i < n; i++) - *x1++ = 0; - x = b->x; - xe = x + b->wds; -#ifdef Pack_32 - if (k &= 0x1f) { - k1 = 32 - k; - z = 0; - do { - *x1++ = *x << k | z; - z = *x++ >> k1; - } while (x < xe); - if ((*x1 = z) != 0) - ++n1; - } -#else - if (k &= 0xf) { - k1 = 16 - k; - z = 0; - do { - *x1++ = *x << k & 0xffff | z; - z = *x++ >> k1; - } while (x < xe); - if (*x1 = z) - ++n1; - } -#endif - else - do { - *x1++ = *x++; - } while (x < xe); - b1->wds = n1 - 1; - Bfree(b); - return b1; -} - -static int -cmp(Bigint *a, Bigint *b) -{ - ULong *xa, *xa0, *xb, *xb0; - int i, j; - - i = a->wds; - j = b->wds; -#ifdef DEBUG - if (i > 1 && !a->x[i-1]) - Bug("cmp called with a->x[a->wds-1] == 0"); - if (j > 1 && !b->x[j-1]) - Bug("cmp called with b->x[b->wds-1] == 0"); -#endif - if (i -= j) - return i; - xa0 = a->x; - xa = xa0 + j; - xb0 = b->x; - xb = xb0 + j; - for (;;) { - if (*--xa != *--xb) - return *xa < *xb ? -1 : 1; - if (xa <= xa0) - break; - } - return 0; -} - -NO_SANITIZE("unsigned-integer-overflow", static Bigint * diff(Bigint *a, Bigint *b)); -static Bigint * -diff(Bigint *a, Bigint *b) -{ - Bigint *c; - int i, wa, wb; - ULong *xa, *xae, *xb, *xbe, *xc; -#ifdef ULLong - ULLong borrow, y; -#else - ULong borrow, y; -#ifdef Pack_32 - ULong z; -#endif -#endif - - i = cmp(a,b); - if (!i) { - c = Balloc(0); - c->wds = 1; - c->x[0] = 0; - return c; - } - if (i < 0) { - c = a; - a = b; - b = c; - i = 1; - } - else - i = 0; - c = Balloc(a->k); - c->sign = i; - wa = a->wds; - xa = a->x; - xae = xa + wa; - wb = b->wds; - xb = b->x; - xbe = xb + wb; - xc = c->x; - borrow = 0; -#ifdef ULLong - do { - y = (ULLong)*xa++ - *xb++ - borrow; - borrow = y >> 32 & (ULong)1; - *xc++ = (ULong)(y & FFFFFFFF); - } while (xb < xbe); - while (xa < xae) { - y = *xa++ - borrow; - borrow = y >> 32 & (ULong)1; - *xc++ = (ULong)(y & FFFFFFFF); - } -#else -#ifdef Pack_32 - do { - y = (*xa & 0xffff) - (*xb & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - z = (*xa++ >> 16) - (*xb++ >> 16) - borrow; - borrow = (z & 0x10000) >> 16; - Storeinc(xc, z, y); - } while (xb < xbe); - while (xa < xae) { - y = (*xa & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - z = (*xa++ >> 16) - borrow; - borrow = (z & 0x10000) >> 16; - Storeinc(xc, z, y); - } -#else - do { - y = *xa++ - *xb++ - borrow; - borrow = (y & 0x10000) >> 16; - *xc++ = y & 0xffff; - } while (xb < xbe); - while (xa < xae) { - y = *xa++ - borrow; - borrow = (y & 0x10000) >> 16; - *xc++ = y & 0xffff; - } -#endif -#endif - while (!*--xc) - wa--; - c->wds = wa; - return c; -} - -static double -ulp(double x_) -{ - register Long L; - double_u x, a; - dval(x) = x_; - - L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1; -#ifndef Avoid_Underflow -#ifndef Sudden_Underflow - if (L > 0) { -#endif -#endif -#ifdef IBM - L |= Exp_msk1 >> 4; -#endif - word0(a) = L; - word1(a) = 0; -#ifndef Avoid_Underflow -#ifndef Sudden_Underflow - } - else { - L = -L >> Exp_shift; - if (L < Exp_shift) { - word0(a) = 0x80000 >> L; - word1(a) = 0; - } - else { - word0(a) = 0; - L -= Exp_shift; - word1(a) = L >= 31 ? 1 : 1 << 31 - L; - } - } -#endif -#endif - return dval(a); -} - -static double -b2d(Bigint *a, int *e) -{ - ULong *xa, *xa0, w, y, z; - int k; - double_u d; -#ifdef VAX - ULong d0, d1; -#else -#define d0 word0(d) -#define d1 word1(d) -#endif - - xa0 = a->x; - xa = xa0 + a->wds; - y = *--xa; -#ifdef DEBUG - if (!y) Bug("zero y in b2d"); -#endif - k = hi0bits(y); - *e = 32 - k; -#ifdef Pack_32 - if (k < Ebits) { - d0 = Exp_1 | y >> (Ebits - k); - w = xa > xa0 ? *--xa : 0; - d1 = y << ((32-Ebits) + k) | w >> (Ebits - k); - goto ret_d; - } - z = xa > xa0 ? *--xa : 0; - if (k -= Ebits) { - d0 = Exp_1 | y << k | z >> (32 - k); - y = xa > xa0 ? *--xa : 0; - d1 = z << k | y >> (32 - k); - } - else { - d0 = Exp_1 | y; - d1 = z; - } -#else - if (k < Ebits + 16) { - z = xa > xa0 ? *--xa : 0; - d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k; - w = xa > xa0 ? *--xa : 0; - y = xa > xa0 ? *--xa : 0; - d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k; - goto ret_d; - } - z = xa > xa0 ? *--xa : 0; - w = xa > xa0 ? *--xa : 0; - k -= Ebits + 16; - d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k; - y = xa > xa0 ? *--xa : 0; - d1 = w << k + 16 | y << k; -#endif -ret_d: -#ifdef VAX - word0(d) = d0 >> 16 | d0 << 16; - word1(d) = d1 >> 16 | d1 << 16; -#else -#undef d0 -#undef d1 -#endif - return dval(d); -} - -static Bigint * -d2b(double d_, int *e, int *bits) -{ - double_u d; - Bigint *b; - int de, k; - ULong *x, y, z; -#ifndef Sudden_Underflow - int i; -#endif -#ifdef VAX - ULong d0, d1; -#endif - dval(d) = d_; -#ifdef VAX - d0 = word0(d) >> 16 | word0(d) << 16; - d1 = word1(d) >> 16 | word1(d) << 16; -#else -#define d0 word0(d) -#define d1 word1(d) -#endif - -#ifdef Pack_32 - b = Balloc(1); -#else - b = Balloc(2); -#endif - x = b->x; - - z = d0 & Frac_mask; - d0 &= 0x7fffffff; /* clear sign bit, which we ignore */ -#ifdef Sudden_Underflow - de = (int)(d0 >> Exp_shift); -#ifndef IBM - z |= Exp_msk11; -#endif -#else - if ((de = (int)(d0 >> Exp_shift)) != 0) - z |= Exp_msk1; -#endif -#ifdef Pack_32 - if ((y = d1) != 0) { - if ((k = lo0bits(&y)) != 0) { - x[0] = y | z << (32 - k); - z >>= k; - } - else - x[0] = y; -#ifndef Sudden_Underflow - i = -#endif - b->wds = (x[1] = z) ? 2 : 1; - } - else { -#ifdef DEBUG - if (!z) - Bug("Zero passed to d2b"); -#endif - k = lo0bits(&z); - x[0] = z; -#ifndef Sudden_Underflow - i = -#endif - b->wds = 1; - k += 32; - } -#else - if (y = d1) { - if (k = lo0bits(&y)) - if (k >= 16) { - x[0] = y | z << 32 - k & 0xffff; - x[1] = z >> k - 16 & 0xffff; - x[2] = z >> k; - i = 2; - } - else { - x[0] = y & 0xffff; - x[1] = y >> 16 | z << 16 - k & 0xffff; - x[2] = z >> k & 0xffff; - x[3] = z >> k+16; - i = 3; - } - else { - x[0] = y & 0xffff; - x[1] = y >> 16; - x[2] = z & 0xffff; - x[3] = z >> 16; - i = 3; - } - } - else { -#ifdef DEBUG - if (!z) - Bug("Zero passed to d2b"); -#endif - k = lo0bits(&z); - if (k >= 16) { - x[0] = z; - i = 0; - } - else { - x[0] = z & 0xffff; - x[1] = z >> 16; - i = 1; - } - k += 32; - } - while (!x[i]) - --i; - b->wds = i + 1; -#endif -#ifndef Sudden_Underflow - if (de) { -#endif -#ifdef IBM - *e = (de - Bias - (P-1) << 2) + k; - *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask); -#else - *e = de - Bias - (P-1) + k; - *bits = P - k; -#endif -#ifndef Sudden_Underflow - } - else { - *e = de - Bias - (P-1) + 1 + k; -#ifdef Pack_32 - *bits = 32*i - hi0bits(x[i-1]); -#else - *bits = (i+2)*16 - hi0bits(x[i]); -#endif - } -#endif - return b; -} -#undef d0 -#undef d1 - -static double -ratio(Bigint *a, Bigint *b) -{ - double_u da, db; - int k, ka, kb; - - dval(da) = b2d(a, &ka); - dval(db) = b2d(b, &kb); -#ifdef Pack_32 - k = ka - kb + 32*(a->wds - b->wds); -#else - k = ka - kb + 16*(a->wds - b->wds); -#endif -#ifdef IBM - if (k > 0) { - word0(da) += (k >> 2)*Exp_msk1; - if (k &= 3) - dval(da) *= 1 << k; - } - else { - k = -k; - word0(db) += (k >> 2)*Exp_msk1; - if (k &= 3) - dval(db) *= 1 << k; - } -#else - if (k > 0) - word0(da) += k*Exp_msk1; - else { - k = -k; - word0(db) += k*Exp_msk1; - } -#endif - return dval(da) / dval(db); -} - -static const double -tens[] = { - 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, - 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, - 1e20, 1e21, 1e22 -#ifdef VAX - , 1e23, 1e24 -#endif -}; - -static const double -#ifdef IEEE_Arith -bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 }; -static const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, -#ifdef Avoid_Underflow - 9007199254740992.*9007199254740992.e-256 - /* = 2^106 * 1e-53 */ -#else - 1e-256 -#endif -}; -/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */ -/* flag unnecessarily. It leads to a song and dance at the end of strtod. */ -#define Scale_Bit 0x10 -#define n_bigtens 5 -#else -#ifdef IBM -bigtens[] = { 1e16, 1e32, 1e64 }; -static const double tinytens[] = { 1e-16, 1e-32, 1e-64 }; -#define n_bigtens 3 -#else -bigtens[] = { 1e16, 1e32 }; -static const double tinytens[] = { 1e-16, 1e-32 }; -#define n_bigtens 2 -#endif -#endif - -#ifndef IEEE_Arith -#undef INFNAN_CHECK -#endif - -#ifdef INFNAN_CHECK - -#ifndef NAN_WORD0 -#define NAN_WORD0 0x7ff80000 -#endif - -#ifndef NAN_WORD1 -#define NAN_WORD1 0 -#endif - -static int -match(const char **sp, char *t) -{ - int c, d; - const char *s = *sp; - - while (d = *t++) { - if ((c = *++s) >= 'A' && c <= 'Z') - c += 'a' - 'A'; - if (c != d) - return 0; - } - *sp = s + 1; - return 1; -} - -#ifndef No_Hex_NaN -static void -hexnan(double *rvp, const char **sp) -{ - ULong c, x[2]; - const char *s; - int havedig, udx0, xshift; - - x[0] = x[1] = 0; - havedig = xshift = 0; - udx0 = 1; - s = *sp; - while (c = *(const unsigned char*)++s) { - if (c >= '0' && c <= '9') - c -= '0'; - else if (c >= 'a' && c <= 'f') - c += 10 - 'a'; - else if (c >= 'A' && c <= 'F') - c += 10 - 'A'; - else if (c <= ' ') { - if (udx0 && havedig) { - udx0 = 0; - xshift = 1; - } - continue; - } - else if (/*(*/ c == ')' && havedig) { - *sp = s + 1; - break; - } - else - return; /* invalid form: don't change *sp */ - havedig = 1; - if (xshift) { - xshift = 0; - x[0] = x[1]; - x[1] = 0; - } - if (udx0) - x[0] = (x[0] << 4) | (x[1] >> 28); - x[1] = (x[1] << 4) | c; - } - if ((x[0] &= 0xfffff) || x[1]) { - word0(*rvp) = Exp_mask | x[0]; - word1(*rvp) = x[1]; - } -} -#endif /*No_Hex_NaN*/ -#endif /* INFNAN_CHECK */ - -NO_SANITIZE("unsigned-integer-overflow", double strtod(const char *s00, char **se)); -double -strtod(const char *s00, char **se) -{ -#ifdef Avoid_Underflow - int scale; -#endif - int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, - e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign; - const char *s, *s0, *s1; - double aadj, adj; - double_u aadj1, rv, rv0; - Long L; - ULong y, z; - Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; -#ifdef SET_INEXACT - int inexact, oldinexact; -#endif -#ifdef Honor_FLT_ROUNDS - int rounding; -#endif -#ifdef USE_LOCALE - const char *s2; -#endif - - errno = 0; - sign = nz0 = nz = 0; - dval(rv) = 0.; - for (s = s00;;s++) - switch (*s) { - case '-': - sign = 1; - /* no break */ - case '+': - if (*++s) - goto break2; - /* no break */ - case 0: - goto ret0; - case '\t': - case '\n': - case '\v': - case '\f': - case '\r': - case ' ': - continue; - default: - goto break2; - } -break2: - if (*s == '0') { - if (s[1] == 'x' || s[1] == 'X') { - s0 = ++s; - adj = 0; - aadj = 1.0; - nd0 = -4; - - if (!*++s || !(s1 = strchr(hexdigit, *s))) goto ret0; - if (*s == '0') { - while (*++s == '0'); - s1 = strchr(hexdigit, *s); - } - if (s1 != NULL) { - do { - adj += aadj * ((s1 - hexdigit) & 15); - nd0 += 4; - aadj /= 16; - } while (*++s && (s1 = strchr(hexdigit, *s))); - } - - if (*s == '.') { - dsign = 1; - if (!*++s || !(s1 = strchr(hexdigit, *s))) goto ret0; - if (nd0 < 0) { - while (*s == '0') { - s++; - nd0 -= 4; - } - } - for (; *s && (s1 = strchr(hexdigit, *s)); ++s) { - adj += aadj * ((s1 - hexdigit) & 15); - if ((aadj /= 16) == 0.0) { - while (strchr(hexdigit, *++s)); - break; - } - } - } - else { - dsign = 0; - } - - if (*s == 'P' || *s == 'p') { - dsign = 0x2C - *++s; /* +: 2B, -: 2D */ - if (abs(dsign) == 1) s++; - else dsign = 1; - - nd = 0; - c = *s; - if (c < '0' || '9' < c) goto ret0; - do { - nd *= 10; - nd += c; - nd -= '0'; - c = *++s; - /* Float("0x0."+("0"*267)+"1fp2095") */ - if (nd + dsign * nd0 > 2095) { - while ('0' <= c && c <= '9') c = *++s; - break; - } - } while ('0' <= c && c <= '9'); - nd0 += nd * dsign; - } - else { - if (dsign) goto ret0; - } - dval(rv) = ldexp(adj, nd0); - goto ret; - } - nz0 = 1; - while (*++s == '0') ; - if (!*s) - goto ret; - } - s0 = s; - y = z = 0; - for (nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) - if (nd < 9) - y = 10*y + c - '0'; - else if (nd < DBL_DIG + 2) - z = 10*z + c - '0'; - nd0 = nd; -#ifdef USE_LOCALE - s1 = localeconv()->decimal_point; - if (c == *s1) { - c = '.'; - if (*++s1) { - s2 = s; - for (;;) { - if (*++s2 != *s1) { - c = 0; - break; - } - if (!*++s1) { - s = s2; - break; - } - } - } - } -#endif - if (c == '.') { - if (!ISDIGIT(s[1])) - goto dig_done; - c = *++s; - if (!nd) { - for (; c == '0'; c = *++s) - nz++; - if (c > '0' && c <= '9') { - s0 = s; - nf += nz; - nz = 0; - goto have_dig; - } - goto dig_done; - } - for (; c >= '0' && c <= '9'; c = *++s) { -have_dig: - nz++; - if (nd > DBL_DIG * 4) { - continue; - } - if (c -= '0') { - nf += nz; - for (i = 1; i < nz; i++) - if (nd++ < 9) - y *= 10; - else if (nd <= DBL_DIG + 2) - z *= 10; - if (nd++ < 9) - y = 10*y + c; - else if (nd <= DBL_DIG + 2) - z = 10*z + c; - nz = 0; - } - } - } -dig_done: - e = 0; - if (c == 'e' || c == 'E') { - if (!nd && !nz && !nz0) { - goto ret0; - } - s00 = s; - esign = 0; - switch (c = *++s) { - case '-': - esign = 1; - case '+': - c = *++s; - } - if (c >= '0' && c <= '9') { - while (c == '0') - c = *++s; - if (c > '0' && c <= '9') { - L = c - '0'; - s1 = s; - while ((c = *++s) >= '0' && c <= '9') - L = 10*L + c - '0'; - if (s - s1 > 8 || L > 19999) - /* Avoid confusion from exponents - * so large that e might overflow. - */ - e = 19999; /* safe for 16 bit ints */ - else - e = (int)L; - if (esign) - e = -e; - } - else - e = 0; - } - else - s = s00; - } - if (!nd) { - if (!nz && !nz0) { -#ifdef INFNAN_CHECK - /* Check for Nan and Infinity */ - switch (c) { - case 'i': - case 'I': - if (match(&s,"nf")) { - --s; - if (!match(&s,"inity")) - ++s; - word0(rv) = 0x7ff00000; - word1(rv) = 0; - goto ret; - } - break; - case 'n': - case 'N': - if (match(&s, "an")) { - word0(rv) = NAN_WORD0; - word1(rv) = NAN_WORD1; -#ifndef No_Hex_NaN - if (*s == '(') /*)*/ - hexnan(&rv, &s); -#endif - goto ret; - } - } -#endif /* INFNAN_CHECK */ -ret0: - s = s00; - sign = 0; - } - goto ret; - } - e1 = e -= nf; - - /* Now we have nd0 digits, starting at s0, followed by a - * decimal point, followed by nd-nd0 digits. The number we're - * after is the integer represented by those digits times - * 10**e */ - - if (!nd0) - nd0 = nd; - k = nd < DBL_DIG + 2 ? nd : DBL_DIG + 2; - dval(rv) = y; - if (k > 9) { -#ifdef SET_INEXACT - if (k > DBL_DIG) - oldinexact = get_inexact(); -#endif - dval(rv) = tens[k - 9] * dval(rv) + z; - } - bd0 = bb = bd = bs = delta = 0; - if (nd <= DBL_DIG -#ifndef RND_PRODQUOT -#ifndef Honor_FLT_ROUNDS - && Flt_Rounds == 1 -#endif -#endif - ) { - if (!e) - goto ret; - if (e > 0) { - if (e <= Ten_pmax) { -#ifdef VAX - goto vax_ovfl_check; -#else -#ifdef Honor_FLT_ROUNDS - /* round correctly FLT_ROUNDS = 2 or 3 */ - if (sign) { - dval(rv) = -dval(rv); - sign = 0; - } -#endif - /* rv = */ rounded_product(dval(rv), tens[e]); - goto ret; -#endif - } - i = DBL_DIG - nd; - if (e <= Ten_pmax + i) { - /* A fancier test would sometimes let us do - * this for larger i values. - */ -#ifdef Honor_FLT_ROUNDS - /* round correctly FLT_ROUNDS = 2 or 3 */ - if (sign) { - dval(rv) = -dval(rv); - sign = 0; - } -#endif - e -= i; - dval(rv) *= tens[i]; -#ifdef VAX - /* VAX exponent range is so narrow we must - * worry about overflow here... - */ -vax_ovfl_check: - word0(rv) -= P*Exp_msk1; - /* rv = */ rounded_product(dval(rv), tens[e]); - if ((word0(rv) & Exp_mask) - > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) - goto ovfl; - word0(rv) += P*Exp_msk1; -#else - /* rv = */ rounded_product(dval(rv), tens[e]); -#endif - goto ret; - } - } -#ifndef Inaccurate_Divide - else if (e >= -Ten_pmax) { -#ifdef Honor_FLT_ROUNDS - /* round correctly FLT_ROUNDS = 2 or 3 */ - if (sign) { - dval(rv) = -dval(rv); - sign = 0; - } -#endif - /* rv = */ rounded_quotient(dval(rv), tens[-e]); - goto ret; - } -#endif - } - e1 += nd - k; - -#ifdef IEEE_Arith -#ifdef SET_INEXACT - inexact = 1; - if (k <= DBL_DIG) - oldinexact = get_inexact(); -#endif -#ifdef Avoid_Underflow - scale = 0; -#endif -#ifdef Honor_FLT_ROUNDS - if ((rounding = Flt_Rounds) >= 2) { - if (sign) - rounding = rounding == 2 ? 0 : 2; - else - if (rounding != 2) - rounding = 0; - } -#endif -#endif /*IEEE_Arith*/ - - /* Get starting approximation = rv * 10**e1 */ - - if (e1 > 0) { - if ((i = e1 & 15) != 0) - dval(rv) *= tens[i]; - if (e1 &= ~15) { - if (e1 > DBL_MAX_10_EXP) { -ovfl: -#ifndef NO_ERRNO - errno = ERANGE; -#endif - /* Can't trust HUGE_VAL */ -#ifdef IEEE_Arith -#ifdef Honor_FLT_ROUNDS - switch (rounding) { - case 0: /* toward 0 */ - case 3: /* toward -infinity */ - word0(rv) = Big0; - word1(rv) = Big1; - break; - default: - word0(rv) = Exp_mask; - word1(rv) = 0; - } -#else /*Honor_FLT_ROUNDS*/ - word0(rv) = Exp_mask; - word1(rv) = 0; -#endif /*Honor_FLT_ROUNDS*/ -#ifdef SET_INEXACT - /* set overflow bit */ - dval(rv0) = 1e300; - dval(rv0) *= dval(rv0); -#endif -#else /*IEEE_Arith*/ - word0(rv) = Big0; - word1(rv) = Big1; -#endif /*IEEE_Arith*/ - if (bd0) - goto retfree; - goto ret; - } - e1 >>= 4; - for (j = 0; e1 > 1; j++, e1 >>= 1) - if (e1 & 1) - dval(rv) *= bigtens[j]; - /* The last multiplication could overflow. */ - word0(rv) -= P*Exp_msk1; - dval(rv) *= bigtens[j]; - if ((z = word0(rv) & Exp_mask) - > Exp_msk1*(DBL_MAX_EXP+Bias-P)) - goto ovfl; - if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) { - /* set to largest number */ - /* (Can't trust DBL_MAX) */ - word0(rv) = Big0; - word1(rv) = Big1; - } - else - word0(rv) += P*Exp_msk1; - } - } - else if (e1 < 0) { - e1 = -e1; - if ((i = e1 & 15) != 0) - dval(rv) /= tens[i]; - if (e1 >>= 4) { - if (e1 >= 1 << n_bigtens) - goto undfl; -#ifdef Avoid_Underflow - if (e1 & Scale_Bit) - scale = 2*P; - for (j = 0; e1 > 0; j++, e1 >>= 1) - if (e1 & 1) - dval(rv) *= tinytens[j]; - if (scale && (j = 2*P + 1 - ((word0(rv) & Exp_mask) - >> Exp_shift)) > 0) { - /* scaled rv is denormal; zap j low bits */ - if (j >= 32) { - word1(rv) = 0; - if (j >= 53) - word0(rv) = (P+2)*Exp_msk1; - else - word0(rv) &= 0xffffffff << (j-32); - } - else - word1(rv) &= 0xffffffff << j; - } -#else - for (j = 0; e1 > 1; j++, e1 >>= 1) - if (e1 & 1) - dval(rv) *= tinytens[j]; - /* The last multiplication could underflow. */ - dval(rv0) = dval(rv); - dval(rv) *= tinytens[j]; - if (!dval(rv)) { - dval(rv) = 2.*dval(rv0); - dval(rv) *= tinytens[j]; -#endif - if (!dval(rv)) { -undfl: - dval(rv) = 0.; -#ifndef NO_ERRNO - errno = ERANGE; -#endif - if (bd0) - goto retfree; - goto ret; - } -#ifndef Avoid_Underflow - word0(rv) = Tiny0; - word1(rv) = Tiny1; - /* The refinement below will clean - * this approximation up. - */ - } -#endif - } - } - - /* Now the hard part -- adjusting rv to the correct value.*/ - - /* Put digits into bd: true value = bd * 10^e */ - - bd0 = s2b(s0, nd0, nd, y); - - for (;;) { - bd = Balloc(bd0->k); - Bcopy(bd, bd0); - bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */ - bs = i2b(1); - - if (e >= 0) { - bb2 = bb5 = 0; - bd2 = bd5 = e; - } - else { - bb2 = bb5 = -e; - bd2 = bd5 = 0; - } - if (bbe >= 0) - bb2 += bbe; - else - bd2 -= bbe; - bs2 = bb2; -#ifdef Honor_FLT_ROUNDS - if (rounding != 1) - bs2++; -#endif -#ifdef Avoid_Underflow - j = bbe - scale; - i = j + bbbits - 1; /* logb(rv) */ - if (i < Emin) /* denormal */ - j += P - Emin; - else - j = P + 1 - bbbits; -#else /*Avoid_Underflow*/ -#ifdef Sudden_Underflow -#ifdef IBM - j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3); -#else - j = P + 1 - bbbits; -#endif -#else /*Sudden_Underflow*/ - j = bbe; - i = j + bbbits - 1; /* logb(rv) */ - if (i < Emin) /* denormal */ - j += P - Emin; - else - j = P + 1 - bbbits; -#endif /*Sudden_Underflow*/ -#endif /*Avoid_Underflow*/ - bb2 += j; - bd2 += j; -#ifdef Avoid_Underflow - bd2 += scale; -#endif - i = bb2 < bd2 ? bb2 : bd2; - if (i > bs2) - i = bs2; - if (i > 0) { - bb2 -= i; - bd2 -= i; - bs2 -= i; - } - if (bb5 > 0) { - bs = pow5mult(bs, bb5); - bb1 = mult(bs, bb); - Bfree(bb); - bb = bb1; - } - if (bb2 > 0) - bb = lshift(bb, bb2); - if (bd5 > 0) - bd = pow5mult(bd, bd5); - if (bd2 > 0) - bd = lshift(bd, bd2); - if (bs2 > 0) - bs = lshift(bs, bs2); - delta = diff(bb, bd); - dsign = delta->sign; - delta->sign = 0; - i = cmp(delta, bs); -#ifdef Honor_FLT_ROUNDS - if (rounding != 1) { - if (i < 0) { - /* Error is less than an ulp */ - if (!delta->x[0] && delta->wds <= 1) { - /* exact */ -#ifdef SET_INEXACT - inexact = 0; -#endif - break; - } - if (rounding) { - if (dsign) { - adj = 1.; - goto apply_adj; - } - } - else if (!dsign) { - adj = -1.; - if (!word1(rv) - && !(word0(rv) & Frac_mask)) { - y = word0(rv) & Exp_mask; -#ifdef Avoid_Underflow - if (!scale || y > 2*P*Exp_msk1) -#else - if (y) -#endif - { - delta = lshift(delta,Log2P); - if (cmp(delta, bs) <= 0) - adj = -0.5; - } - } -apply_adj: -#ifdef Avoid_Underflow - if (scale && (y = word0(rv) & Exp_mask) - <= 2*P*Exp_msk1) - word0(adj) += (2*P+1)*Exp_msk1 - y; -#else -#ifdef Sudden_Underflow - if ((word0(rv) & Exp_mask) <= - P*Exp_msk1) { - word0(rv) += P*Exp_msk1; - dval(rv) += adj*ulp(dval(rv)); - word0(rv) -= P*Exp_msk1; - } - else -#endif /*Sudden_Underflow*/ -#endif /*Avoid_Underflow*/ - dval(rv) += adj*ulp(dval(rv)); - } - break; - } - adj = ratio(delta, bs); - if (adj < 1.) - adj = 1.; - if (adj <= 0x7ffffffe) { - /* adj = rounding ? ceil(adj) : floor(adj); */ - y = adj; - if (y != adj) { - if (!((rounding>>1) ^ dsign)) - y++; - adj = y; - } - } -#ifdef Avoid_Underflow - if (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1) - word0(adj) += (2*P+1)*Exp_msk1 - y; -#else -#ifdef Sudden_Underflow - if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { - word0(rv) += P*Exp_msk1; - adj *= ulp(dval(rv)); - if (dsign) - dval(rv) += adj; - else - dval(rv) -= adj; - word0(rv) -= P*Exp_msk1; - goto cont; - } -#endif /*Sudden_Underflow*/ -#endif /*Avoid_Underflow*/ - adj *= ulp(dval(rv)); - if (dsign) - dval(rv) += adj; - else - dval(rv) -= adj; - goto cont; - } -#endif /*Honor_FLT_ROUNDS*/ - - if (i < 0) { - /* Error is less than half an ulp -- check for - * special case of mantissa a power of two. - */ - if (dsign || word1(rv) || word0(rv) & Bndry_mask -#ifdef IEEE_Arith -#ifdef Avoid_Underflow - || (word0(rv) & Exp_mask) <= (2*P+1)*Exp_msk1 -#else - || (word0(rv) & Exp_mask) <= Exp_msk1 -#endif -#endif - ) { -#ifdef SET_INEXACT - if (!delta->x[0] && delta->wds <= 1) - inexact = 0; -#endif - break; - } - if (!delta->x[0] && delta->wds <= 1) { - /* exact result */ -#ifdef SET_INEXACT - inexact = 0; -#endif - break; - } - delta = lshift(delta,Log2P); - if (cmp(delta, bs) > 0) - goto drop_down; - break; - } - if (i == 0) { - /* exactly half-way between */ - if (dsign) { - if ((word0(rv) & Bndry_mask1) == Bndry_mask1 - && word1(rv) == ( -#ifdef Avoid_Underflow - (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1) - ? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) : -#endif - 0xffffffff)) { - /*boundary case -- increment exponent*/ - word0(rv) = (word0(rv) & Exp_mask) - + Exp_msk1 -#ifdef IBM - | Exp_msk1 >> 4 -#endif - ; - word1(rv) = 0; -#ifdef Avoid_Underflow - dsign = 0; -#endif - break; - } - } - else if (!(word0(rv) & Bndry_mask) && !word1(rv)) { -drop_down: - /* boundary case -- decrement exponent */ -#ifdef Sudden_Underflow /*{{*/ - L = word0(rv) & Exp_mask; -#ifdef IBM - if (L < Exp_msk1) -#else -#ifdef Avoid_Underflow - if (L <= (scale ? (2*P+1)*Exp_msk1 : Exp_msk1)) -#else - if (L <= Exp_msk1) -#endif /*Avoid_Underflow*/ -#endif /*IBM*/ - goto undfl; - L -= Exp_msk1; -#else /*Sudden_Underflow}{*/ -#ifdef Avoid_Underflow - if (scale) { - L = word0(rv) & Exp_mask; - if (L <= (2*P+1)*Exp_msk1) { - if (L > (P+2)*Exp_msk1) - /* round even ==> */ - /* accept rv */ - break; - /* rv = smallest denormal */ - goto undfl; - } - } -#endif /*Avoid_Underflow*/ - L = (word0(rv) & Exp_mask) - Exp_msk1; -#endif /*Sudden_Underflow}}*/ - word0(rv) = L | Bndry_mask1; - word1(rv) = 0xffffffff; -#ifdef IBM - goto cont; -#else - break; -#endif - } -#ifndef ROUND_BIASED - if (!(word1(rv) & LSB)) - break; -#endif - if (dsign) - dval(rv) += ulp(dval(rv)); -#ifndef ROUND_BIASED - else { - dval(rv) -= ulp(dval(rv)); -#ifndef Sudden_Underflow - if (!dval(rv)) - goto undfl; -#endif - } -#ifdef Avoid_Underflow - dsign = 1 - dsign; -#endif -#endif - break; - } - if ((aadj = ratio(delta, bs)) <= 2.) { - if (dsign) - aadj = dval(aadj1) = 1.; - else if (word1(rv) || word0(rv) & Bndry_mask) { -#ifndef Sudden_Underflow - if (word1(rv) == Tiny1 && !word0(rv)) - goto undfl; -#endif - aadj = 1.; - dval(aadj1) = -1.; - } - else { - /* special case -- power of FLT_RADIX to be */ - /* rounded down... */ - - if (aadj < 2./FLT_RADIX) - aadj = 1./FLT_RADIX; - else - aadj *= 0.5; - dval(aadj1) = -aadj; - } - } - else { - aadj *= 0.5; - dval(aadj1) = dsign ? aadj : -aadj; -#ifdef Check_FLT_ROUNDS - switch (Rounding) { - case 2: /* towards +infinity */ - dval(aadj1) -= 0.5; - break; - case 0: /* towards 0 */ - case 3: /* towards -infinity */ - dval(aadj1) += 0.5; - } -#else - if (Flt_Rounds == 0) - dval(aadj1) += 0.5; -#endif /*Check_FLT_ROUNDS*/ - } - y = word0(rv) & Exp_mask; - - /* Check for overflow */ - - if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { - dval(rv0) = dval(rv); - word0(rv) -= P*Exp_msk1; - adj = dval(aadj1) * ulp(dval(rv)); - dval(rv) += adj; - if ((word0(rv) & Exp_mask) >= - Exp_msk1*(DBL_MAX_EXP+Bias-P)) { - if (word0(rv0) == Big0 && word1(rv0) == Big1) - goto ovfl; - word0(rv) = Big0; - word1(rv) = Big1; - goto cont; - } - else - word0(rv) += P*Exp_msk1; - } - else { -#ifdef Avoid_Underflow - if (scale && y <= 2*P*Exp_msk1) { - if (aadj <= 0x7fffffff) { - if ((z = (int)aadj) <= 0) - z = 1; - aadj = z; - dval(aadj1) = dsign ? aadj : -aadj; - } - word0(aadj1) += (2*P+1)*Exp_msk1 - y; - } - adj = dval(aadj1) * ulp(dval(rv)); - dval(rv) += adj; -#else -#ifdef Sudden_Underflow - if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { - dval(rv0) = dval(rv); - word0(rv) += P*Exp_msk1; - adj = dval(aadj1) * ulp(dval(rv)); - dval(rv) += adj; -#ifdef IBM - if ((word0(rv) & Exp_mask) < P*Exp_msk1) -#else - if ((word0(rv) & Exp_mask) <= P*Exp_msk1) -#endif - { - if (word0(rv0) == Tiny0 && word1(rv0) == Tiny1) - goto undfl; - word0(rv) = Tiny0; - word1(rv) = Tiny1; - goto cont; - } - else - word0(rv) -= P*Exp_msk1; - } - else { - adj = dval(aadj1) * ulp(dval(rv)); - dval(rv) += adj; - } -#else /*Sudden_Underflow*/ - /* Compute adj so that the IEEE rounding rules will - * correctly round rv + adj in some half-way cases. - * If rv * ulp(rv) is denormalized (i.e., - * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid - * trouble from bits lost to denormalization; - * example: 1.2e-307 . - */ - if (y <= (P-1)*Exp_msk1 && aadj > 1.) { - dval(aadj1) = (double)(int)(aadj + 0.5); - if (!dsign) - dval(aadj1) = -dval(aadj1); - } - adj = dval(aadj1) * ulp(dval(rv)); - dval(rv) += adj; -#endif /*Sudden_Underflow*/ -#endif /*Avoid_Underflow*/ - } - z = word0(rv) & Exp_mask; -#ifndef SET_INEXACT -#ifdef Avoid_Underflow - if (!scale) -#endif - if (y == z) { - /* Can we stop now? */ - L = (Long)aadj; - aadj -= L; - /* The tolerances below are conservative. */ - if (dsign || word1(rv) || word0(rv) & Bndry_mask) { - if (aadj < .4999999 || aadj > .5000001) - break; - } - else if (aadj < .4999999/FLT_RADIX) - break; - } -#endif -cont: - Bfree(bb); - Bfree(bd); - Bfree(bs); - Bfree(delta); - } -#ifdef SET_INEXACT - if (inexact) { - if (!oldinexact) { - word0(rv0) = Exp_1 + (70 << Exp_shift); - word1(rv0) = 0; - dval(rv0) += 1.; - } - } - else if (!oldinexact) - clear_inexact(); -#endif -#ifdef Avoid_Underflow - if (scale) { - word0(rv0) = Exp_1 - 2*P*Exp_msk1; - word1(rv0) = 0; - dval(rv) *= dval(rv0); -#ifndef NO_ERRNO - /* try to avoid the bug of testing an 8087 register value */ - if (word0(rv) == 0 && word1(rv) == 0) - errno = ERANGE; -#endif - } -#endif /* Avoid_Underflow */ -#ifdef SET_INEXACT - if (inexact && !(word0(rv) & Exp_mask)) { - /* set underflow bit */ - dval(rv0) = 1e-300; - dval(rv0) *= dval(rv0); - } -#endif -retfree: - Bfree(bb); - Bfree(bd); - Bfree(bs); - Bfree(bd0); - Bfree(delta); -ret: - if (se) - *se = (char *)s; - return sign ? -dval(rv) : dval(rv); -} - -NO_SANITIZE("unsigned-integer-overflow", static int quorem(Bigint *b, Bigint *S)); -static int -quorem(Bigint *b, Bigint *S) -{ - int n; - ULong *bx, *bxe, q, *sx, *sxe; -#ifdef ULLong - ULLong borrow, carry, y, ys; -#else - ULong borrow, carry, y, ys; -#ifdef Pack_32 - ULong si, z, zs; -#endif -#endif - - n = S->wds; -#ifdef DEBUG - /*debug*/ if (b->wds > n) - /*debug*/ Bug("oversize b in quorem"); -#endif - if (b->wds < n) - return 0; - sx = S->x; - sxe = sx + --n; - bx = b->x; - bxe = bx + n; - q = *bxe / (*sxe + 1); /* ensure q <= true quotient */ -#ifdef DEBUG - /*debug*/ if (q > 9) - /*debug*/ Bug("oversized quotient in quorem"); -#endif - if (q) { - borrow = 0; - carry = 0; - do { -#ifdef ULLong - ys = *sx++ * (ULLong)q + carry; - carry = ys >> 32; - y = *bx - (ys & FFFFFFFF) - borrow; - borrow = y >> 32 & (ULong)1; - *bx++ = (ULong)(y & FFFFFFFF); -#else -#ifdef Pack_32 - si = *sx++; - ys = (si & 0xffff) * q + carry; - zs = (si >> 16) * q + (ys >> 16); - carry = zs >> 16; - y = (*bx & 0xffff) - (ys & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - z = (*bx >> 16) - (zs & 0xffff) - borrow; - borrow = (z & 0x10000) >> 16; - Storeinc(bx, z, y); -#else - ys = *sx++ * q + carry; - carry = ys >> 16; - y = *bx - (ys & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - *bx++ = y & 0xffff; -#endif -#endif - } while (sx <= sxe); - if (!*bxe) { - bx = b->x; - while (--bxe > bx && !*bxe) - --n; - b->wds = n; - } - } - if (cmp(b, S) >= 0) { - q++; - borrow = 0; - carry = 0; - bx = b->x; - sx = S->x; - do { -#ifdef ULLong - ys = *sx++ + carry; - carry = ys >> 32; - y = *bx - (ys & FFFFFFFF) - borrow; - borrow = y >> 32 & (ULong)1; - *bx++ = (ULong)(y & FFFFFFFF); -#else -#ifdef Pack_32 - si = *sx++; - ys = (si & 0xffff) + carry; - zs = (si >> 16) + (ys >> 16); - carry = zs >> 16; - y = (*bx & 0xffff) - (ys & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - z = (*bx >> 16) - (zs & 0xffff) - borrow; - borrow = (z & 0x10000) >> 16; - Storeinc(bx, z, y); -#else - ys = *sx++ + carry; - carry = ys >> 16; - y = *bx - (ys & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - *bx++ = y & 0xffff; -#endif -#endif - } while (sx <= sxe); - bx = b->x; - bxe = bx + n; - if (!*bxe) { - while (--bxe > bx && !*bxe) - --n; - b->wds = n; - } - } - return q; -} - -#ifndef MULTIPLE_THREADS -static char *dtoa_result; -#endif - -#ifndef MULTIPLE_THREADS -static char * -rv_alloc(int i) -{ - return dtoa_result = MALLOC(i); -} -#else -#define rv_alloc(i) MALLOC(i) -#endif - -static char * -nrv_alloc(const char *s, char **rve, size_t n) -{ - char *rv, *t; - - t = rv = rv_alloc(n); - while ((*t = *s++) != 0) t++; - if (rve) - *rve = t; - return rv; -} - -#define rv_strdup(s, rve) nrv_alloc((s), (rve), strlen(s)+1) - -#ifndef MULTIPLE_THREADS -/* freedtoa(s) must be used to free values s returned by dtoa - * when MULTIPLE_THREADS is #defined. It should be used in all cases, - * but for consistency with earlier versions of dtoa, it is optional - * when MULTIPLE_THREADS is not defined. - */ - -static void -freedtoa(char *s) -{ - FREE(s); -} -#endif - -static const char INFSTR[] = "Infinity"; -static const char NANSTR[] = "NaN"; -static const char ZEROSTR[] = "0"; - -/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. - * - * Inspired by "How to Print Floating-Point Numbers Accurately" by - * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126]. - * - * Modifications: - * 1. Rather than iterating, we use a simple numeric overestimate - * to determine k = floor(log10(d)). We scale relevant - * quantities using O(log2(k)) rather than O(k) multiplications. - * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't - * try to generate digits strictly left to right. Instead, we - * compute with fewer bits and propagate the carry if necessary - * when rounding the final digit up. This is often faster. - * 3. Under the assumption that input will be rounded nearest, - * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22. - * That is, we allow equality in stopping tests when the - * round-nearest rule will give the same floating-point value - * as would satisfaction of the stopping test with strict - * inequality. - * 4. We remove common factors of powers of 2 from relevant - * quantities. - * 5. When converting floating-point integers less than 1e16, - * we use floating-point arithmetic rather than resorting - * to multiple-precision integers. - * 6. When asked to produce fewer than 15 digits, we first try - * to get by with floating-point arithmetic; we resort to - * multiple-precision integer arithmetic only if we cannot - * guarantee that the floating-point calculation has given - * the correctly rounded result. For k requested digits and - * "uniformly" distributed input, the probability is - * something like 10^(k-15) that we must resort to the Long - * calculation. - */ - -char * -dtoa(double d_, int mode, int ndigits, int *decpt, int *sign, char **rve) -{ - /* Arguments ndigits, decpt, sign are similar to those - of ecvt and fcvt; trailing zeros are suppressed from - the returned string. If not null, *rve is set to point - to the end of the return value. If d is +-Infinity or NaN, - then *decpt is set to 9999. - - mode: - 0 ==> shortest string that yields d when read in - and rounded to nearest. - 1 ==> like 0, but with Steele & White stopping rule; - e.g. with IEEE P754 arithmetic , mode 0 gives - 1e23 whereas mode 1 gives 9.999999999999999e22. - 2 ==> max(1,ndigits) significant digits. This gives a - return value similar to that of ecvt, except - that trailing zeros are suppressed. - 3 ==> through ndigits past the decimal point. This - gives a return value similar to that from fcvt, - except that trailing zeros are suppressed, and - ndigits can be negative. - 4,5 ==> similar to 2 and 3, respectively, but (in - round-nearest mode) with the tests of mode 0 to - possibly return a shorter string that rounds to d. - With IEEE arithmetic and compilation with - -DHonor_FLT_ROUNDS, modes 4 and 5 behave the same - as modes 2 and 3 when FLT_ROUNDS != 1. - 6-9 ==> Debugging modes similar to mode - 4: don't try - fast floating-point estimate (if applicable). - - Values of mode other than 0-9 are treated as mode 0. - - Sufficient space is allocated to the return value - to hold the suppressed trailing zeros. - */ - - int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1, - j, j1, k, k0, k_check, leftright, m2, m5, s2, s5, - spec_case, try_quick, half = 0; - Long L; -#ifndef Sudden_Underflow - int denorm; - ULong x; -#endif - Bigint *b, *b1, *delta, *mlo = 0, *mhi = 0, *S; - double ds; - double_u d, d2, eps; - char *s, *s0; -#ifdef Honor_FLT_ROUNDS - int rounding; -#endif -#ifdef SET_INEXACT - int inexact, oldinexact; -#endif - - dval(d) = d_; - -#ifndef MULTIPLE_THREADS - if (dtoa_result) { - freedtoa(dtoa_result); - dtoa_result = 0; - } -#endif - - if (word0(d) & Sign_bit) { - /* set sign for everything, including 0's and NaNs */ - *sign = 1; - word0(d) &= ~Sign_bit; /* clear sign bit */ - } - else - *sign = 0; - -#if defined(IEEE_Arith) + defined(VAX) -#ifdef IEEE_Arith - if ((word0(d) & Exp_mask) == Exp_mask) -#else - if (word0(d) == 0x8000) -#endif - { - /* Infinity or NaN */ - *decpt = 9999; -#ifdef IEEE_Arith - if (!word1(d) && !(word0(d) & 0xfffff)) - return rv_strdup(INFSTR, rve); -#endif - return rv_strdup(NANSTR, rve); - } -#endif -#ifdef IBM - dval(d) += 0; /* normalize */ -#endif - if (!dval(d)) { - *decpt = 1; - return rv_strdup(ZEROSTR, rve); - } - -#ifdef SET_INEXACT - try_quick = oldinexact = get_inexact(); - inexact = 1; -#endif -#ifdef Honor_FLT_ROUNDS - if ((rounding = Flt_Rounds) >= 2) { - if (*sign) - rounding = rounding == 2 ? 0 : 2; - else - if (rounding != 2) - rounding = 0; - } -#endif - - b = d2b(dval(d), &be, &bbits); -#ifdef Sudden_Underflow - i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); -#else - if ((i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) != 0) { -#endif - dval(d2) = dval(d); - word0(d2) &= Frac_mask1; - word0(d2) |= Exp_11; -#ifdef IBM - if (j = 11 - hi0bits(word0(d2) & Frac_mask)) - dval(d2) /= 1 << j; -#endif - - /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 - * log10(x) = log(x) / log(10) - * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) - * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2) - * - * This suggests computing an approximation k to log10(d) by - * - * k = (i - Bias)*0.301029995663981 - * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); - * - * We want k to be too large rather than too small. - * The error in the first-order Taylor series approximation - * is in our favor, so we just round up the constant enough - * to compensate for any error in the multiplication of - * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077, - * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14, - * adding 1e-13 to the constant term more than suffices. - * Hence we adjust the constant term to 0.1760912590558. - * (We could get a more accurate k by invoking log10, - * but this is probably not worthwhile.) - */ - - i -= Bias; -#ifdef IBM - i <<= 2; - i += j; -#endif -#ifndef Sudden_Underflow - denorm = 0; - } - else { - /* d is denormalized */ - - i = bbits + be + (Bias + (P-1) - 1); - x = i > 32 ? word0(d) << (64 - i) | word1(d) >> (i - 32) - : word1(d) << (32 - i); - dval(d2) = x; - word0(d2) -= 31*Exp_msk1; /* adjust exponent */ - i -= (Bias + (P-1) - 1) + 1; - denorm = 1; - } -#endif - ds = (dval(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; - k = (int)ds; - if (ds < 0. && ds != k) - k--; /* want k = floor(ds) */ - k_check = 1; - if (k >= 0 && k <= Ten_pmax) { - if (dval(d) < tens[k]) - k--; - k_check = 0; - } - j = bbits - i - 1; - if (j >= 0) { - b2 = 0; - s2 = j; - } - else { - b2 = -j; - s2 = 0; - } - if (k >= 0) { - b5 = 0; - s5 = k; - s2 += k; - } - else { - b2 -= k; - b5 = -k; - s5 = 0; - } - if (mode < 0 || mode > 9) - mode = 0; - -#ifndef SET_INEXACT -#ifdef Check_FLT_ROUNDS - try_quick = Rounding == 1; -#else - try_quick = 1; -#endif -#endif /*SET_INEXACT*/ - - if (mode > 5) { - mode -= 4; - try_quick = 0; - } - leftright = 1; - ilim = ilim1 = -1; - switch (mode) { - case 0: - case 1: - i = 18; - ndigits = 0; - break; - case 2: - leftright = 0; - /* no break */ - case 4: - if (ndigits <= 0) - ndigits = 1; - ilim = ilim1 = i = ndigits; - break; - case 3: - leftright = 0; - /* no break */ - case 5: - i = ndigits + k + 1; - ilim = i; - ilim1 = i - 1; - if (i <= 0) - i = 1; - } - s = s0 = rv_alloc(i+1); - -#ifdef Honor_FLT_ROUNDS - if (mode > 1 && rounding != 1) - leftright = 0; -#endif - - if (ilim >= 0 && ilim <= Quick_max && try_quick) { - - /* Try to get by with floating-point arithmetic. */ - - i = 0; - dval(d2) = dval(d); - k0 = k; - ilim0 = ilim; - ieps = 2; /* conservative */ - if (k > 0) { - ds = tens[k&0xf]; - j = k >> 4; - if (j & Bletch) { - /* prevent overflows */ - j &= Bletch - 1; - dval(d) /= bigtens[n_bigtens-1]; - ieps++; - } - for (; j; j >>= 1, i++) - if (j & 1) { - ieps++; - ds *= bigtens[i]; - } - dval(d) /= ds; - } - else if ((j1 = -k) != 0) { - dval(d) *= tens[j1 & 0xf]; - for (j = j1 >> 4; j; j >>= 1, i++) - if (j & 1) { - ieps++; - dval(d) *= bigtens[i]; - } - } - if (k_check && dval(d) < 1. && ilim > 0) { - if (ilim1 <= 0) - goto fast_failed; - ilim = ilim1; - k--; - dval(d) *= 10.; - ieps++; - } - dval(eps) = ieps*dval(d) + 7.; - word0(eps) -= (P-1)*Exp_msk1; - if (ilim == 0) { - S = mhi = 0; - dval(d) -= 5.; - if (dval(d) > dval(eps)) - goto one_digit; - if (dval(d) < -dval(eps)) - goto no_digits; - goto fast_failed; - } -#ifndef No_leftright - if (leftright) { - /* Use Steele & White method of only - * generating digits needed. - */ - dval(eps) = 0.5/tens[ilim-1] - dval(eps); - for (i = 0;;) { - L = (int)dval(d); - dval(d) -= L; - *s++ = '0' + (int)L; - if (dval(d) < dval(eps)) - goto ret1; - if (1. - dval(d) < dval(eps)) - goto bump_up; - if (++i >= ilim) - break; - dval(eps) *= 10.; - dval(d) *= 10.; - } - } - else { -#endif - /* Generate ilim digits, then fix them up. */ - dval(eps) *= tens[ilim-1]; - for (i = 1;; i++, dval(d) *= 10.) { - L = (Long)(dval(d)); - if (!(dval(d) -= L)) - ilim = i; - *s++ = '0' + (int)L; - if (i == ilim) { - if (dval(d) > 0.5 + dval(eps)) - goto bump_up; - else if (dval(d) < 0.5 - dval(eps)) { - while (*--s == '0') ; - s++; - goto ret1; - } - half = 1; - if ((*(s-1) - '0') & 1) { - goto bump_up; - } - break; - } - } -#ifndef No_leftright - } -#endif -fast_failed: - s = s0; - dval(d) = dval(d2); - k = k0; - ilim = ilim0; - } - - /* Do we have a "small" integer? */ - - if (be >= 0 && k <= Int_max) { - /* Yes. */ - ds = tens[k]; - if (ndigits < 0 && ilim <= 0) { - S = mhi = 0; - if (ilim < 0 || dval(d) <= 5*ds) - goto no_digits; - goto one_digit; - } - for (i = 1;; i++, dval(d) *= 10.) { - L = (Long)(dval(d) / ds); - dval(d) -= L*ds; -#ifdef Check_FLT_ROUNDS - /* If FLT_ROUNDS == 2, L will usually be high by 1 */ - if (dval(d) < 0) { - L--; - dval(d) += ds; - } -#endif - *s++ = '0' + (int)L; - if (!dval(d)) { -#ifdef SET_INEXACT - inexact = 0; -#endif - break; - } - if (i == ilim) { -#ifdef Honor_FLT_ROUNDS - if (mode > 1) - switch (rounding) { - case 0: goto ret1; - case 2: goto bump_up; - } -#endif - dval(d) += dval(d); - if (dval(d) > ds || (dval(d) == ds && (L & 1))) { -bump_up: - while (*--s == '9') - if (s == s0) { - k++; - *s = '0'; - break; - } - ++*s++; - } - break; - } - } - goto ret1; - } - - m2 = b2; - m5 = b5; - if (leftright) { - i = -#ifndef Sudden_Underflow - denorm ? be + (Bias + (P-1) - 1 + 1) : -#endif -#ifdef IBM - 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3); -#else - 1 + P - bbits; -#endif - b2 += i; - s2 += i; - mhi = i2b(1); - } - if (m2 > 0 && s2 > 0) { - i = m2 < s2 ? m2 : s2; - b2 -= i; - m2 -= i; - s2 -= i; - } - if (b5 > 0) { - if (leftright) { - if (m5 > 0) { - mhi = pow5mult(mhi, m5); - b1 = mult(mhi, b); - Bfree(b); - b = b1; - } - if ((j = b5 - m5) != 0) - b = pow5mult(b, j); - } - else - b = pow5mult(b, b5); - } - S = i2b(1); - if (s5 > 0) - S = pow5mult(S, s5); - - /* Check for special case that d is a normalized power of 2. */ - - spec_case = 0; - if ((mode < 2 || leftright) -#ifdef Honor_FLT_ROUNDS - && rounding == 1 -#endif - ) { - if (!word1(d) && !(word0(d) & Bndry_mask) -#ifndef Sudden_Underflow - && word0(d) & (Exp_mask & ~Exp_msk1) -#endif - ) { - /* The special case */ - b2 += Log2P; - s2 += Log2P; - spec_case = 1; - } - } - - /* Arrange for convenient computation of quotients: - * shift left if necessary so divisor has 4 leading 0 bits. - * - * Perhaps we should just compute leading 28 bits of S once - * and for all and pass them and a shift to quorem, so it - * can do shifts and ors to compute the numerator for q. - */ -#ifdef Pack_32 - if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f) != 0) - i = 32 - i; -#else - if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf) != 0) - i = 16 - i; -#endif - if (i > 4) { - i -= 4; - b2 += i; - m2 += i; - s2 += i; - } - else if (i < 4) { - i += 28; - b2 += i; - m2 += i; - s2 += i; - } - if (b2 > 0) - b = lshift(b, b2); - if (s2 > 0) - S = lshift(S, s2); - if (k_check) { - if (cmp(b,S) < 0) { - k--; - b = multadd(b, 10, 0); /* we botched the k estimate */ - if (leftright) - mhi = multadd(mhi, 10, 0); - ilim = ilim1; - } - } - if (ilim <= 0 && (mode == 3 || mode == 5)) { - if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) { - /* no digits, fcvt style */ -no_digits: - k = -1 - ndigits; - goto ret; - } -one_digit: - *s++ = '1'; - k++; - goto ret; - } - if (leftright) { - if (m2 > 0) - mhi = lshift(mhi, m2); - - /* Compute mlo -- check for special case - * that d is a normalized power of 2. - */ - - mlo = mhi; - if (spec_case) { - mhi = Balloc(mhi->k); - Bcopy(mhi, mlo); - mhi = lshift(mhi, Log2P); - } - - for (i = 1;;i++) { - dig = quorem(b,S) + '0'; - /* Do we yet have the shortest decimal string - * that will round to d? - */ - j = cmp(b, mlo); - delta = diff(S, mhi); - j1 = delta->sign ? 1 : cmp(b, delta); - Bfree(delta); -#ifndef ROUND_BIASED - if (j1 == 0 && mode != 1 && !(word1(d) & 1) -#ifdef Honor_FLT_ROUNDS - && rounding >= 1 -#endif - ) { - if (dig == '9') - goto round_9_up; - if (j > 0) - dig++; -#ifdef SET_INEXACT - else if (!b->x[0] && b->wds <= 1) - inexact = 0; -#endif - *s++ = dig; - goto ret; - } -#endif - if (j < 0 || (j == 0 && mode != 1 -#ifndef ROUND_BIASED - && !(word1(d) & 1) -#endif - )) { - if (!b->x[0] && b->wds <= 1) { -#ifdef SET_INEXACT - inexact = 0; -#endif - goto accept_dig; - } -#ifdef Honor_FLT_ROUNDS - if (mode > 1) - switch (rounding) { - case 0: goto accept_dig; - case 2: goto keep_dig; - } -#endif /*Honor_FLT_ROUNDS*/ - if (j1 > 0) { - b = lshift(b, 1); - j1 = cmp(b, S); - if ((j1 > 0 || (j1 == 0 && (dig & 1))) && dig++ == '9') - goto round_9_up; - } -accept_dig: - *s++ = dig; - goto ret; - } - if (j1 > 0) { -#ifdef Honor_FLT_ROUNDS - if (!rounding) - goto accept_dig; -#endif - if (dig == '9') { /* possible if i == 1 */ -round_9_up: - *s++ = '9'; - goto roundoff; - } - *s++ = dig + 1; - goto ret; - } -#ifdef Honor_FLT_ROUNDS -keep_dig: -#endif - *s++ = dig; - if (i == ilim) - break; - b = multadd(b, 10, 0); - if (mlo == mhi) - mlo = mhi = multadd(mhi, 10, 0); - else { - mlo = multadd(mlo, 10, 0); - mhi = multadd(mhi, 10, 0); - } - } - } - else - for (i = 1;; i++) { - *s++ = dig = quorem(b,S) + '0'; - if (!b->x[0] && b->wds <= 1) { -#ifdef SET_INEXACT - inexact = 0; -#endif - goto ret; - } - if (i >= ilim) - break; - b = multadd(b, 10, 0); - } - - /* Round off last digit */ - -#ifdef Honor_FLT_ROUNDS - switch (rounding) { - case 0: goto trimzeros; - case 2: goto roundoff; - } -#endif - b = lshift(b, 1); - j = cmp(b, S); - if (j > 0 || (j == 0 && (dig & 1))) { - roundoff: - while (*--s == '9') - if (s == s0) { - k++; - *s++ = '1'; - goto ret; - } - if (!half || (*s - '0') & 1) - ++*s; - } - else { - while (*--s == '0') ; - } - s++; -ret: - Bfree(S); - if (mhi) { - if (mlo && mlo != mhi) - Bfree(mlo); - Bfree(mhi); - } -ret1: -#ifdef SET_INEXACT - if (inexact) { - if (!oldinexact) { - word0(d) = Exp_1 + (70 << Exp_shift); - word1(d) = 0; - dval(d) += 1.; - } - } - else if (!oldinexact) - clear_inexact(); -#endif - Bfree(b); - *s = 0; - *decpt = k + 1; - if (rve) - *rve = s; - return s0; -} - -/*- - * Copyright (c) 2004-2008 David Schultz - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#define DBL_MANH_SIZE 20 -#define DBL_MANL_SIZE 32 -#define DBL_ADJ (DBL_MAX_EXP - 2) -#define SIGFIGS ((DBL_MANT_DIG + 3) / 4 + 1) -#define dexp_get(u) ((int)(word0(u) >> Exp_shift) & ~Exp_msk1) -#define dexp_set(u,v) (word0(u) = (((int)(word0(u)) & ~Exp_mask) | ((v) << Exp_shift))) -#define dmanh_get(u) ((uint32_t)(word0(u) & Frac_mask)) -#define dmanl_get(u) ((uint32_t)word1(u)) - - -/* - * This procedure converts a double-precision number in IEEE format - * into a string of hexadecimal digits and an exponent of 2. Its - * behavior is bug-for-bug compatible with dtoa() in mode 2, with the - * following exceptions: - * - * - An ndigits < 0 causes it to use as many digits as necessary to - * represent the number exactly. - * - The additional xdigs argument should point to either the string - * "0123456789ABCDEF" or the string "0123456789abcdef", depending on - * which case is desired. - * - This routine does not repeat dtoa's mistake of setting decpt - * to 9999 in the case of an infinity or NaN. INT_MAX is used - * for this purpose instead. - * - * Note that the C99 standard does not specify what the leading digit - * should be for non-zero numbers. For instance, 0x1.3p3 is the same - * as 0x2.6p2 is the same as 0x4.cp3. This implementation always makes - * the leading digit a 1. This ensures that the exponent printed is the - * actual base-2 exponent, i.e., ilogb(d). - * - * Inputs: d, xdigs, ndigits - * Outputs: decpt, sign, rve - */ -char * -hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign, char **rve) -{ - U u; - char *s, *s0; - int bufsize; - uint32_t manh, manl; - - u.d = d; - if (word0(u) & Sign_bit) { - /* set sign for everything, including 0's and NaNs */ - *sign = 1; - word0(u) &= ~Sign_bit; /* clear sign bit */ - } - else - *sign = 0; - - if (isinf(d)) { /* FP_INFINITE */ - *decpt = INT_MAX; - return rv_strdup(INFSTR, rve); - } - else if (isnan(d)) { /* FP_NAN */ - *decpt = INT_MAX; - return rv_strdup(NANSTR, rve); - } - else if (d == 0.0) { /* FP_ZERO */ - *decpt = 1; - return rv_strdup(ZEROSTR, rve); - } - else if (dexp_get(u)) { /* FP_NORMAL */ - *decpt = dexp_get(u) - DBL_ADJ; - } - else { /* FP_SUBNORMAL */ - u.d *= 5.363123171977039e+154 /* 0x1p514 */; - *decpt = dexp_get(u) - (514 + DBL_ADJ); - } - - if (ndigits == 0) /* dtoa() compatibility */ - ndigits = 1; - - /* - * If ndigits < 0, we are expected to auto-size, so we allocate - * enough space for all the digits. - */ - bufsize = (ndigits > 0) ? ndigits : SIGFIGS; - s0 = rv_alloc(bufsize+1); - - /* Round to the desired number of digits. */ - if (SIGFIGS > ndigits && ndigits > 0) { - float redux = 1.0f; - int offset = 4 * ndigits + DBL_MAX_EXP - 4 - DBL_MANT_DIG; - dexp_set(u, offset); - u.d += redux; - u.d -= redux; - *decpt += dexp_get(u) - offset; - } - - manh = dmanh_get(u); - manl = dmanl_get(u); - *s0 = '1'; - for (s = s0 + 1; s < s0 + bufsize; s++) { - *s = xdigs[(manh >> (DBL_MANH_SIZE - 4)) & 0xf]; - manh = (manh << 4) | (manl >> (DBL_MANL_SIZE - 4)); - manl <<= 4; - } - - /* If ndigits < 0, we are expected to auto-size the precision. */ - if (ndigits < 0) { - for (ndigits = SIGFIGS; s0[ndigits - 1] == '0'; ndigits--) - ; - } - - s = s0 + ndigits; - *s = '\0'; - if (rve != NULL) - *rve = s; - return (s0); -} - -#ifdef __cplusplus -#if 0 -{ /* satisfy cc-mode */ -#endif -} -#endif diff --git a/ext/bigdecimal/sample/linear.rb b/ext/bigdecimal/sample/linear.rb deleted file mode 100644 index 516c2473be8fce..00000000000000 --- a/ext/bigdecimal/sample/linear.rb +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/local/bin/ruby -# frozen_string_literal: false - -# -# linear.rb -# -# Solves linear equation system(A*x = b) by LU decomposition method. -# where A is a coefficient matrix,x is an answer vector,b is a constant vector. -# -# USAGE: -# ruby linear.rb [input file solved] -# - -# :stopdoc: -require "bigdecimal" -require "bigdecimal/ludcmp" - -# -# NOTE: -# Change following BigDecimal.limit() if needed. -BigDecimal.limit(100) -# - -include LUSolve -def rd_order(na) - printf("Number of equations ?") if(na <= 0) - n = ARGF.gets().to_i -end - -na = ARGV.size -zero = BigDecimal("0.0") -one = BigDecimal("1.0") - -while (n=rd_order(na))>0 - a = [] - as= [] - b = [] - if na <= 0 - # Read data from console. - printf("\nEnter coefficient matrix element A[i,j]\n") - for i in 0...n do - for j in 0...n do - printf("A[%d,%d]? ",i,j); s = ARGF.gets - a << BigDecimal(s) - as << BigDecimal(s) - end - printf("Contatant vector element b[%d] ? ",i) - b << BigDecimal(ARGF.gets) - end - else - # Read data from specified file. - printf("Coefficient matrix and constant vector.\n") - for i in 0...n do - s = ARGF.gets - printf("%d) %s",i,s) - s = s.split - for j in 0...n do - a << BigDecimal(s[j]) - as << BigDecimal(s[j]) - end - b << BigDecimal(s[n]) - end - end - x = lusolve(a,b,ludecomp(a,n,zero,one),zero) - printf("Answer(x[i] & (A*x-b)[i]) follows\n") - for i in 0...n do - printf("x[%d]=%s ",i,x[i].to_s) - s = zero - for j in 0...n do - s = s + as[i*n+j]*x[j] - end - printf(" & %s\n",(s-b[i]).to_s) - end -end diff --git a/ext/bigdecimal/sample/nlsolve.rb b/ext/bigdecimal/sample/nlsolve.rb deleted file mode 100644 index c2227dac739ba7..00000000000000 --- a/ext/bigdecimal/sample/nlsolve.rb +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/local/bin/ruby -# frozen_string_literal: false - -# -# nlsolve.rb -# An example for solving nonlinear algebraic equation system. -# - -require "bigdecimal" -require "bigdecimal/newton" -include Newton - -class Function # :nodoc: all - def initialize() - @zero = BigDecimal("0.0") - @one = BigDecimal("1.0") - @two = BigDecimal("2.0") - @ten = BigDecimal("10.0") - @eps = BigDecimal("1.0e-16") - end - def zero;@zero;end - def one ;@one ;end - def two ;@two ;end - def ten ;@ten ;end - def eps ;@eps ;end - def values(x) # <= defines functions solved - f = [] - f1 = x[0]*x[0] + x[1]*x[1] - @two # f1 = x**2 + y**2 - 2 => 0 - f2 = x[0] - x[1] # f2 = x - y => 0 - f <<= f1 - f <<= f2 - f - end -end - -f = BigDecimal.limit(100) -f = Function.new -x = [f.zero,f.zero] # Initial values -n = nlsolve(f,x) -p x diff --git a/ext/bigdecimal/sample/pi.rb b/ext/bigdecimal/sample/pi.rb deleted file mode 100644 index ea9663896c2a21..00000000000000 --- a/ext/bigdecimal/sample/pi.rb +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/local/bin/ruby -# frozen_string_literal: false - -# -# pi.rb -# -# Calculates 3.1415.... (the number of times that a circle's diameter -# will fit around the circle) using J. Machin's formula. -# - -require "bigdecimal" -require "bigdecimal/math.rb" - -include BigMath - -if ARGV.size == 1 - print "PI("+ARGV[0]+"):\n" - p PI(ARGV[0].to_i) -else - print "TRY: ruby pi.rb 1000 \n" -end diff --git a/ext/bigdecimal/static_assert.h b/ext/bigdecimal/static_assert.h deleted file mode 100644 index 9295729bf6a61c..00000000000000 --- a/ext/bigdecimal/static_assert.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef BIGDECIMAL_STATIC_ASSERT_H -#define BIGDECIMAL_STATIC_ASSERT_H - -#include "feature.h" - -#ifdef HAVE_RUBY_INTERNAL_STATIC_ASSERT_H -# include -#endif - -#ifdef RBIMPL_STATIC_ASSERT -# define STATIC_ASSERT RBIMPL_STATIC_ASSERT -#endif - -#ifndef STATIC_ASSERT -# /* The following section is copied from CRuby's static_assert.h */ - -# if defined(__cplusplus) && defined(__cpp_static_assert) -# /* https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations */ -# define BIGDECIMAL_STATIC_ASSERT0 static_assert - -# elif defined(__cplusplus) && defined(_MSC_VER) && _MSC_VER >= 1600 -# define BIGDECIMAL_STATIC_ASSERT0 static_assert - -# elif defined(__INTEL_CXX11_MODE__) -# define BIGDECIMAL_STATIC_ASSERT0 static_assert - -# elif defined(__cplusplus) && __cplusplus >= 201103L -# define BIGDECIMAL_STATIC_ASSERT0 static_assert - -# elif defined(__cplusplus) && __has_extension(cxx_static_assert) -# define BIGDECIMAL_STATIC_ASSERT0 __extension__ static_assert - -# elif defined(__STDC_VERSION__) && __has_extension(c_static_assert) -# define BIGDECIMAL_STATIC_ASSERT0 __extension__ _Static_assert - -# elif defined(__STDC_VERSION__) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) -# define BIGDECIMAL_STATIC_ASSERT0 __extension__ _Static_assert -#endif - -# if defined(__DOXYGEN__) -# define STATIC_ASSERT static_assert - -# elif defined(BIGDECIMAL_STATIC_ASSERT0) -# define STATIC_ASSERT(name, expr) \ - BIGDECIMAL_STATIC_ASSERT0(expr, #name ": " #expr) - -# else -# define STATIC_ASSERT(name, expr) \ - typedef int static_assert_ ## name ## _check[1 - 2 * !(expr)] -# endif -#endif /* STATIC_ASSERT */ - - -#endif /* BIGDECIMAL_STATIC_ASSERT_H */ diff --git a/gems/bundled_gems b/gems/bundled_gems index 6c3ece4d2b63a1..042ca947e77d3b 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -24,3 +24,4 @@ racc 1.7.3 https://github.com/ruby/racc mutex_m 0.2.0 https://github.com/ruby/mutex_m getoptlong 0.2.1 https://github.com/ruby/getoptlong base64 0.2.0 https://github.com/ruby/base64 +bigdecimal 3.1.5 https://github.com/ruby/bigdecimal diff --git a/test/bigdecimal/helper.rb b/test/bigdecimal/helper.rb deleted file mode 100644 index 46721fb9a817e7..00000000000000 --- a/test/bigdecimal/helper.rb +++ /dev/null @@ -1,39 +0,0 @@ -# frozen_string_literal: false -require "test/unit" -require "bigdecimal" -require 'rbconfig/sizeof' - -module TestBigDecimalBase - if RbConfig::SIZEOF.key?("int64_t") - SIZEOF_DECDIG = RbConfig::SIZEOF["int32_t"] - BASE = 1_000_000_000 - BASE_FIG = 9 - else - SIZEOF_DECDIG = RbConfig::SIZEOF["int16_t"] - BASE = 1000 - BASE_FIG = 4 - end - - def setup - @mode = BigDecimal.mode(BigDecimal::EXCEPTION_ALL) - BigDecimal.mode(BigDecimal::EXCEPTION_ALL, true) - BigDecimal.mode(BigDecimal::EXCEPTION_UNDERFLOW, true) - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, true) - BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_UP) - BigDecimal.limit(0) - end - - def teardown - [BigDecimal::EXCEPTION_INFINITY, BigDecimal::EXCEPTION_NaN, - BigDecimal::EXCEPTION_UNDERFLOW, BigDecimal::EXCEPTION_OVERFLOW].each do |mode| - BigDecimal.mode(mode, !(@mode & mode).zero?) - end - end - - def under_gc_stress - stress, GC.stress = GC.stress, true - yield - ensure - GC.stress = stress - end -end diff --git a/test/bigdecimal/test_bigdecimal.rb b/test/bigdecimal/test_bigdecimal.rb deleted file mode 100644 index b28242b747be26..00000000000000 --- a/test/bigdecimal/test_bigdecimal.rb +++ /dev/null @@ -1,2310 +0,0 @@ -# frozen_string_literal: false -require_relative "helper" -require 'bigdecimal/math' - -class TestBigDecimal < Test::Unit::TestCase - include TestBigDecimalBase - - if defined? RbConfig::LIMITS - LIMITS = RbConfig::LIMITS - else - require 'fiddle' - LONG_MAX = (1 << (Fiddle::SIZEOF_LONG*8 - 1)) - 1 - LONG_MIN = [LONG_MAX + 1].pack("L!").unpack("l!")[0] - LLONG_MAX = (1 << (Fiddle::SIZEOF_LONG_LONG*8 - 1)) - 1 - LLONG_MIN = [LLONG_MAX + 1].pack("Q!").unpack("q!")[0] - ULLONG_MAX = (1 << Fiddle::SIZEOF_LONG_LONG*8) - 1 - LIMITS = { - "LLONG_MIN" => LLONG_MIN, - "ULLONG_MAX" => ULLONG_MAX, - "FIXNUM_MIN" => LONG_MIN / 2, - "FIXNUM_MAX" => LONG_MAX / 2, - "INT64_MIN" => -9223372036854775808, - "INT64_MAX" => 9223372036854775807, - "UINT64_MAX" => 18446744073709551615, - }.freeze - end - - ROUNDING_MODE_MAP = [ - [ BigDecimal::ROUND_UP, :up], - [ BigDecimal::ROUND_DOWN, :down], - [ BigDecimal::ROUND_DOWN, :truncate], - [ BigDecimal::ROUND_HALF_UP, :half_up], - [ BigDecimal::ROUND_HALF_UP, :default], - [ BigDecimal::ROUND_HALF_DOWN, :half_down], - [ BigDecimal::ROUND_HALF_EVEN, :half_even], - [ BigDecimal::ROUND_HALF_EVEN, :banker], - [ BigDecimal::ROUND_CEILING, :ceiling], - [ BigDecimal::ROUND_CEILING, :ceil], - [ BigDecimal::ROUND_FLOOR, :floor], - ] - - def assert_nan(x) - assert(x.nan?, "Expected #{x.inspect} to be NaN") - end - - def assert_positive_infinite(x) - assert(x.infinite?, "Expected #{x.inspect} to be positive infinite") - assert_operator(x, :>, 0) - end - - def assert_negative_infinite(x) - assert(x.infinite?, "Expected #{x.inspect} to be negative infinite") - assert_operator(x, :<, 0) - end - - def assert_positive_zero(x) - assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, x.sign, - "Expected #{x.inspect} to be positive zero") - end - - def assert_negative_zero(x) - assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, x.sign, - "Expected #{x.inspect} to be negative zero") - end - - def test_not_equal - assert_not_equal BigDecimal("1"), BigDecimal("2") - end - - def test_BigDecimal - assert_equal(1, BigDecimal("1")) - assert_equal(1, BigDecimal("1", 1)) - assert_equal(1, BigDecimal(" 1 ")) - assert_equal(111, BigDecimal("1_1_1_")) - assert_equal(10**(-1), BigDecimal("1E-1"), '#4825') - assert_equal(1234, BigDecimal(" \t\n\r \r1234 \t\n\r \r")) - - assert_raise(ArgumentError) { BigDecimal("1", -1) } - assert_raise_with_message(ArgumentError, /"1__1_1"/) { BigDecimal("1__1_1") } - assert_raise_with_message(ArgumentError, /"_1_1_1"/) { BigDecimal("_1_1_1") } - - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - assert_positive_infinite(BigDecimal("Infinity")) - assert_positive_infinite(BigDecimal("1E1111111111111111111")) - assert_positive_infinite(BigDecimal(" \t\n\r \rInfinity \t\n\r \r")) - assert_negative_infinite(BigDecimal("-Infinity")) - assert_negative_infinite(BigDecimal(" \t\n\r \r-Infinity \t\n\r \r")) - assert_nan(BigDecimal("NaN")) - assert_nan(BigDecimal(" \t\n\r \rNaN \t\n\r \r")) - end - end - - def test_BigDecimal_bug7522 - bd = BigDecimal("1.12", 1) - assert_same(bd, BigDecimal(bd)) - assert_same(bd, BigDecimal(bd, exception: false)) - assert_not_same(bd, BigDecimal(bd, 1)) - assert_not_same(bd, BigDecimal(bd, 1, exception: false)) - end - - def test_BigDecimal_issue_192 - # https://github.com/ruby/bigdecimal/issues/192 - # https://github.com/rails/rails/pull/42125 - if BASE_FIG == 9 - int = 1_000_000_000_12345_0000 - big = BigDecimal("0.100000000012345e19") - else # BASE_FIG == 4 - int = 1_0000_12_00 - big = BigDecimal("0.1000012e9") - end - assert_equal(BigDecimal(int), big, "[ruby/bigdecimal#192]") - end - - def test_BigDecimal_with_invalid_string - [ - '', '.', 'e1', 'd1', '.e', '.d', '1.e', '1.d', '.1e', '.1d', - '2,30', '19,000.0', '-2,30', '-19,000.0', '+2,30', '+19,000.0', - '2.3,0', '19.000,0', '-2.3,0', '-19.000,0', '+2.3,0', '+19.000,0', - '2.3.0', '19.000.0', '-2.3.0', '-19.000.0', '+2.3.0', '+19.000.0', - 'invlaid value', '123 xyz' - ].each do |invalid_string| - assert_raise_with_message(ArgumentError, %Q[invalid value for BigDecimal(): "#{invalid_string}"]) do - BigDecimal(invalid_string) - end - end - - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - assert_raise_with_message(ArgumentError, /"Infinity_"/) { BigDecimal("Infinity_") } - assert_raise_with_message(ArgumentError, /"\+Infinity_"/) { BigDecimal("+Infinity_") } - assert_raise_with_message(ArgumentError, /"-Infinity_"/) { BigDecimal("-Infinity_") } - assert_raise_with_message(ArgumentError, /"NaN_"/) { BigDecimal("NaN_") } - end - end - - def test_BigDecimal_with_integer - assert_equal(BigDecimal("0"), BigDecimal(0)) - assert_equal(BigDecimal("1"), BigDecimal(1)) - assert_equal(BigDecimal("-1"), BigDecimal(-1)) - assert_equal(BigDecimal((2**100).to_s), BigDecimal(2**100)) - assert_equal(BigDecimal((-2**100).to_s), BigDecimal(-2**100)) - - assert_equal(BigDecimal(LIMITS["FIXNUM_MIN"].to_s), BigDecimal(LIMITS["FIXNUM_MIN"])) - - assert_equal(BigDecimal(LIMITS["FIXNUM_MAX"].to_s), BigDecimal(LIMITS["FIXNUM_MAX"])) - - assert_equal(BigDecimal(LIMITS["INT64_MIN"].to_s), BigDecimal(LIMITS["INT64_MIN"])) - - assert_equal(BigDecimal(LIMITS["INT64_MAX"].to_s), BigDecimal(LIMITS["INT64_MAX"])) - - assert_equal(BigDecimal(LIMITS["UINT64_MAX"].to_s), BigDecimal(LIMITS["UINT64_MAX"])) - end - - def test_BigDecimal_with_rational - assert_equal(BigDecimal("0.333333333333333333333"), BigDecimal(1.quo(3), 21)) - assert_equal(BigDecimal("-0.333333333333333333333"), BigDecimal(-1.quo(3), 21)) - assert_raise_with_message(ArgumentError, "can't omit precision for a Rational.") { BigDecimal(42.quo(7)) } - end - - def test_BigDecimal_with_float - assert_equal(BigDecimal("0.1235"), BigDecimal(0.1234567, 4)) - assert_equal(BigDecimal("-0.1235"), BigDecimal(-0.1234567, 4)) - assert_equal(BigDecimal("0.01"), BigDecimal(0.01, Float::DIG + 1)) - assert_raise_with_message(ArgumentError, "can't omit precision for a Float.") { BigDecimal(4.2) } - assert_raise(ArgumentError) { BigDecimal(0.1, Float::DIG + 2) } - assert_nothing_raised { BigDecimal(0.1, Float::DIG + 1) } - - assert_same(BigDecimal(0.0), BigDecimal(0.0)) - assert_same(BigDecimal(-0.0), BigDecimal(-0.0)) - - bug9214 = '[ruby-core:58858]' - assert_equal(BigDecimal(-0.0).sign, -1, bug9214) - - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - assert_nan(BigDecimal(Float::NAN)) - assert_same(BigDecimal(Float::NAN), BigDecimal(Float::NAN)) - end - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false) - assert_positive_infinite(BigDecimal(Float::INFINITY)) - assert_same(BigDecimal(Float::INFINITY), BigDecimal(Float::INFINITY)) - assert_negative_infinite(BigDecimal(-Float::INFINITY)) - assert_same(BigDecimal(-Float::INFINITY), BigDecimal(-Float::INFINITY)) - end - end - - def test_BigDecimal_with_complex - assert_equal(BigDecimal("1"), BigDecimal(Complex(1, 0))) - assert_equal(BigDecimal("0.333333333333333333333"), BigDecimal(Complex(1.quo(3), 0), 21)) - assert_equal(BigDecimal("0.1235"), BigDecimal(Complex(0.1234567, 0), 4)) - - assert_raise_with_message(ArgumentError, "Unable to make a BigDecimal from non-zero imaginary number") { BigDecimal(Complex(1, 1)) } - end - - def test_BigDecimal_with_big_decimal - assert_equal(BigDecimal(1), BigDecimal(BigDecimal(1))) - assert_equal(BigDecimal('+0'), BigDecimal(BigDecimal('+0'))) - assert_equal(BigDecimal('-0'), BigDecimal(BigDecimal('-0'))) - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - assert_positive_infinite(BigDecimal(BigDecimal('Infinity'))) - assert_negative_infinite(BigDecimal(BigDecimal('-Infinity'))) - assert_nan(BigDecimal(BigDecimal('NaN'))) - end - end - - if RUBY_VERSION < '2.7' - def test_BigDecimal_with_tainted_string - Thread.new { - $SAFE = 1 - BigDecimal('1'.taint) - }.join - ensure - $SAFE = 0 - end - end - - def test_BigDecimal_with_exception_keyword - assert_raise(ArgumentError) { - BigDecimal('.', exception: true) - } - assert_nothing_raised(ArgumentError) { - assert_equal(nil, BigDecimal(".", exception: false)) - } - assert_raise(ArgumentError) { - BigDecimal("1", -1, exception: true) - } - assert_nothing_raised(ArgumentError) { - assert_equal(nil, BigDecimal("1", -1, exception: false)) - } - assert_raise(ArgumentError) { - BigDecimal(42.quo(7), exception: true) - } - assert_nothing_raised(ArgumentError) { - assert_equal(nil, BigDecimal(42.quo(7), exception: false)) - } - assert_raise(ArgumentError) { - BigDecimal(4.2, exception: true) - } - assert_nothing_raised(ArgumentError) { - assert_equal(nil, BigDecimal(4.2, exception: false)) - } - # TODO: support conversion from complex - # assert_raise(RangeError) { - # BigDecimal(1i, exception: true) - # } - # assert_nothing_raised(RangeError) { - # assert_equal(nil, BigDecimal(1i, exception: false)) - # } - assert_raise_with_message(TypeError, "can't convert nil into BigDecimal") { - BigDecimal(nil, exception: true) - } - assert_raise_with_message(TypeError, "can't convert true into BigDecimal") { - BigDecimal(true, exception: true) - } - assert_raise_with_message(TypeError, "can't convert false into BigDecimal") { - BigDecimal(false, exception: true) - } - assert_raise_with_message(TypeError, "can't convert Object into BigDecimal") { - BigDecimal(Object.new, exception: true) - } - assert_nothing_raised(TypeError) { - assert_equal(nil, BigDecimal(nil, exception: false)) - } - assert_nothing_raised(TypeError) { - assert_equal(nil, BigDecimal(:test, exception: false)) - } - assert_nothing_raised(TypeError) { - assert_equal(nil, BigDecimal(Object.new, exception: false)) - } - assert_nothing_raised(TypeError) { - assert_equal(nil, BigDecimal(Object.new, exception: false)) - } - # TODO: support to_d - # assert_nothing_raised(TypeError) { - # o = Object.new - # def o.to_d; 3.14; end - # assert_equal(3.14, BigDecimal(o, exception: false)) - # } - # assert_nothing_raised(RuntimeError) { - # o = Object.new - # def o.to_d; raise; end - # assert_equal(nil, BigDecimal(o, exception: false)) - # } - end - - def test_s_ver - assert_raise_with_message(NoMethodError, /undefined method `ver'/) { BigDecimal.ver } - end - - def test_s_allocate - if RUBY_ENGINE == "truffleruby" - assert_raise_with_message(NoMethodError, /undefined.+allocate.+for BigDecimal/) { BigDecimal.allocate } - else - assert_raise_with_message(TypeError, /allocator undefined for BigDecimal/) { BigDecimal.allocate } - end - end - - def test_s_new - assert_raise_with_message(NoMethodError, /undefined method `new'/) { BigDecimal.new("1") } - end - - def test_s_interpret_loosely - assert_equal(BigDecimal('1'), BigDecimal.interpret_loosely("1__1_1")) - assert_equal(BigDecimal('2.5'), BigDecimal.interpret_loosely("2.5")) - assert_equal(BigDecimal('2.5'), BigDecimal.interpret_loosely("2.5 degrees")) - assert_equal(BigDecimal('2.5e1'), BigDecimal.interpret_loosely("2.5e1 degrees")) - assert_equal(BigDecimal('0'), BigDecimal.interpret_loosely("degrees 100.0")) - assert_equal(BigDecimal('0.125'), BigDecimal.interpret_loosely("0.1_2_5")) - assert_equal(BigDecimal('0.125'), BigDecimal.interpret_loosely("0.1_2_5__")) - assert_equal(BigDecimal('1'), BigDecimal.interpret_loosely("1_.125")) - assert_equal(BigDecimal('1'), BigDecimal.interpret_loosely("1._125")) - assert_equal(BigDecimal('0.1'), BigDecimal.interpret_loosely("0.1__2_5")) - assert_equal(BigDecimal('0.1'), BigDecimal.interpret_loosely("0.1_e10")) - assert_equal(BigDecimal('0.1'), BigDecimal.interpret_loosely("0.1e_10")) - assert_equal(BigDecimal('1'), BigDecimal.interpret_loosely("0.1e1__0")) - assert_equal(BigDecimal('1.2'), BigDecimal.interpret_loosely("1.2.3")) - assert_equal(BigDecimal('1'), BigDecimal.interpret_loosely("1.")) - assert_equal(BigDecimal('1'), BigDecimal.interpret_loosely("1e")) - - assert_equal(BigDecimal('0.0'), BigDecimal.interpret_loosely("invalid")) - - assert(BigDecimal.interpret_loosely("2.5").frozen?) - end - - def _test_mode(type) - BigDecimal.mode(type, true) - assert_raise(FloatDomainError) { yield } - - BigDecimal.mode(type, false) - assert_nothing_raised { yield } - end - - def test_mode - assert_raise(ArgumentError) { BigDecimal.mode(BigDecimal::EXCEPTION_ALL, 1) } - assert_raise(ArgumentError) { BigDecimal.mode(BigDecimal::ROUND_MODE, 256) } - assert_raise(ArgumentError) { BigDecimal.mode(BigDecimal::ROUND_MODE, :xyzzy) } - assert_raise(TypeError) { BigDecimal.mode(0xf000, true) } - - begin - saved_mode = BigDecimal.mode(BigDecimal::ROUND_MODE) - - [ BigDecimal::ROUND_UP, - BigDecimal::ROUND_DOWN, - BigDecimal::ROUND_HALF_UP, - BigDecimal::ROUND_HALF_DOWN, - BigDecimal::ROUND_CEILING, - BigDecimal::ROUND_FLOOR, - BigDecimal::ROUND_HALF_EVEN, - ].each do |mode| - BigDecimal.mode(BigDecimal::ROUND_MODE, mode) - assert_equal(mode, BigDecimal.mode(BigDecimal::ROUND_MODE)) - end - ensure - BigDecimal.mode(BigDecimal::ROUND_MODE, saved_mode) - end - - BigDecimal.save_rounding_mode do - ROUNDING_MODE_MAP.each do |const, sym| - BigDecimal.mode(BigDecimal::ROUND_MODE, sym) - assert_equal(const, BigDecimal.mode(BigDecimal::ROUND_MODE)) - end - end - end - - def test_thread_local_mode - begin - saved_mode = BigDecimal.mode(BigDecimal::ROUND_MODE) - - BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_UP) - Thread.start { - BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_EVEN) - assert_equal(BigDecimal::ROUND_HALF_EVEN, BigDecimal.mode(BigDecimal::ROUND_MODE)) - }.join - assert_equal(BigDecimal::ROUND_UP, BigDecimal.mode(BigDecimal::ROUND_MODE)) - ensure - BigDecimal.mode(BigDecimal::ROUND_MODE, saved_mode) - end - end - - def test_save_exception_mode - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - mode = BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW) - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, true) - end - assert_equal(mode, BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW)) - - BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_FLOOR) - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_EVEN) - end - assert_equal(BigDecimal::ROUND_HALF_EVEN, BigDecimal.mode(BigDecimal::ROUND_MODE)) - - assert_equal(42, BigDecimal.save_exception_mode { 42 }) - end - - def test_save_rounding_mode - saved_mode = BigDecimal.mode(BigDecimal::ROUND_MODE) - - BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_FLOOR) - BigDecimal.save_rounding_mode do - BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_EVEN) - end - assert_equal(BigDecimal::ROUND_FLOOR, BigDecimal.mode(BigDecimal::ROUND_MODE)) - - assert_equal(42, BigDecimal.save_rounding_mode { 42 }) - ensure - BigDecimal.mode(BigDecimal::ROUND_MODE, saved_mode) - end - - def test_save_limit - begin - old = BigDecimal.limit - BigDecimal.limit(100) - BigDecimal.save_limit do - BigDecimal.limit(200) - end - assert_equal(100, BigDecimal.limit); - ensure - BigDecimal.limit(old) - end - - assert_equal(42, BigDecimal.save_limit { 42 }) - end - - def test_exception_nan - _test_mode(BigDecimal::EXCEPTION_NaN) { BigDecimal("NaN") } - end - - def test_exception_infinity - _test_mode(BigDecimal::EXCEPTION_INFINITY) { BigDecimal("Infinity") } - end - - def test_exception_underflow - _test_mode(BigDecimal::EXCEPTION_UNDERFLOW) do - x = BigDecimal("0.1") - 100.times do - x *= x - end - end - end - - def test_exception_overflow - _test_mode(BigDecimal::EXCEPTION_OVERFLOW) do - x = BigDecimal("10") - 100.times do - x *= x - end - end - end - - def test_exception_zerodivide - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - _test_mode(BigDecimal::EXCEPTION_ZERODIVIDE) { 1 / BigDecimal("0") } - _test_mode(BigDecimal::EXCEPTION_ZERODIVIDE) { -1 / BigDecimal("0") } - end - - def test_round_up - n4 = BigDecimal("4") # n4 / 9 = 0.44444... - n5 = BigDecimal("5") # n5 / 9 = 0.55555... - n6 = BigDecimal("6") # n6 / 9 = 0.66666... - m4, m5, m6 = -n4, -n5, -n6 - n2h = BigDecimal("2.5") - n3h = BigDecimal("3.5") - m2h, m3h = -n2h, -n3h - - BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_UP) - assert_operator(n4, :<, n4 / 9 * 9) - assert_operator(n5, :<, n5 / 9 * 9) - assert_operator(n6, :<, n6 / 9 * 9) - assert_operator(m4, :>, m4 / 9 * 9) - assert_operator(m5, :>, m5 / 9 * 9) - assert_operator(m6, :>, m6 / 9 * 9) - assert_equal(3, n2h.round) - assert_equal(4, n3h.round) - assert_equal(-3, m2h.round) - assert_equal(-4, m3h.round) - - BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_DOWN) - assert_operator(n4, :>, n4 / 9 * 9) - assert_operator(n5, :>, n5 / 9 * 9) - assert_operator(n6, :>, n6 / 9 * 9) - assert_operator(m4, :<, m4 / 9 * 9) - assert_operator(m5, :<, m5 / 9 * 9) - assert_operator(m6, :<, m6 / 9 * 9) - assert_equal(2, n2h.round) - assert_equal(3, n3h.round) - assert_equal(-2, m2h.round) - assert_equal(-3, m3h.round) - - BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_UP) - assert_operator(n4, :>, n4 / 9 * 9) - assert_operator(n5, :<, n5 / 9 * 9) - assert_operator(n6, :<, n6 / 9 * 9) - assert_operator(m4, :<, m4 / 9 * 9) - assert_operator(m5, :>, m5 / 9 * 9) - assert_operator(m6, :>, m6 / 9 * 9) - assert_equal(3, n2h.round) - assert_equal(4, n3h.round) - assert_equal(-3, m2h.round) - assert_equal(-4, m3h.round) - - BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_DOWN) - assert_operator(n4, :>, n4 / 9 * 9) - assert_operator(n5, :>, n5 / 9 * 9) - assert_operator(n6, :<, n6 / 9 * 9) - assert_operator(m4, :<, m4 / 9 * 9) - assert_operator(m5, :<, m5 / 9 * 9) - assert_operator(m6, :>, m6 / 9 * 9) - assert_equal(2, n2h.round) - assert_equal(3, n3h.round) - assert_equal(-2, m2h.round) - assert_equal(-3, m3h.round) - - BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_EVEN) - assert_operator(n4, :>, n4 / 9 * 9) - assert_operator(n5, :<, n5 / 9 * 9) - assert_operator(n6, :<, n6 / 9 * 9) - assert_operator(m4, :<, m4 / 9 * 9) - assert_operator(m5, :>, m5 / 9 * 9) - assert_operator(m6, :>, m6 / 9 * 9) - assert_equal(2, n2h.round) - assert_equal(4, n3h.round) - assert_equal(-2, m2h.round) - assert_equal(-4, m3h.round) - - BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_CEILING) - assert_operator(n4, :<, n4 / 9 * 9) - assert_operator(n5, :<, n5 / 9 * 9) - assert_operator(n6, :<, n6 / 9 * 9) - assert_operator(m4, :<, m4 / 9 * 9) - assert_operator(m5, :<, m5 / 9 * 9) - assert_operator(m6, :<, m6 / 9 * 9) - assert_equal(3, n2h.round) - assert_equal(4, n3h.round) - assert_equal(-2, m2h.round) - assert_equal(-3, m3h.round) - - BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_FLOOR) - assert_operator(n4, :>, n4 / 9 * 9) - assert_operator(n5, :>, n5 / 9 * 9) - assert_operator(n6, :>, n6 / 9 * 9) - assert_operator(m4, :>, m4 / 9 * 9) - assert_operator(m5, :>, m5 / 9 * 9) - assert_operator(m6, :>, m6 / 9 * 9) - assert_equal(2, n2h.round) - assert_equal(3, n3h.round) - assert_equal(-3, m2h.round) - assert_equal(-4, m3h.round) - end - - def test_zero_p - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false) - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - - assert_equal(true, BigDecimal("0").zero?) - assert_equal(true, BigDecimal("-0").zero?) - assert_equal(false, BigDecimal("1").zero?) - assert_equal(true, BigDecimal("0E200000000000000").zero?) - assert_equal(false, BigDecimal("Infinity").zero?) - assert_equal(false, BigDecimal("-Infinity").zero?) - assert_equal(false, BigDecimal("NaN").zero?) - end - - def test_nonzero_p - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false) - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - - assert_equal(nil, BigDecimal("0").nonzero?) - assert_equal(nil, BigDecimal("-0").nonzero?) - assert_equal(BigDecimal("1"), BigDecimal("1").nonzero?) - assert_positive_infinite(BigDecimal("Infinity").nonzero?) - assert_negative_infinite(BigDecimal("-Infinity").nonzero?) - assert_nan(BigDecimal("NaN").nonzero?) - end - - def test_double_fig - assert_kind_of(Integer, BigDecimal.double_fig) - end - - def test_cmp - n1 = BigDecimal("1") - n2 = BigDecimal("2") - assert_equal( 0, n1 <=> n1) - assert_equal( 1, n2 <=> n1) - assert_equal(-1, n1 <=> n2) - assert_operator(n1, :==, n1) - assert_operator(n1, :!=, n2) - assert_operator(n1, :<, n2) - assert_operator(n1, :<=, n1) - assert_operator(n1, :<=, n2) - assert_operator(n2, :>, n1) - assert_operator(n2, :>=, n1) - assert_operator(n1, :>=, n1) - - assert_operator(BigDecimal("-0"), :==, BigDecimal("0")) - assert_operator(BigDecimal("0"), :<, BigDecimal("1")) - assert_operator(BigDecimal("1"), :>, BigDecimal("0")) - assert_operator(BigDecimal("1"), :>, BigDecimal("-1")) - assert_operator(BigDecimal("-1"), :<, BigDecimal("1")) - assert_operator(BigDecimal((2**100).to_s), :>, BigDecimal("1")) - assert_operator(BigDecimal("1"), :<, BigDecimal((2**100).to_s)) - - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - inf = BigDecimal("Infinity") - assert_operator(inf, :>, 1) - assert_operator(1, :<, inf) - - assert_operator(BigDecimal("1E-1"), :==, 10**(-1), '#4825') - assert_equal(0, BigDecimal("1E-1") <=> 10**(-1), '#4825') - end - - def test_cmp_issue9192 - bug9192 = '[ruby-core:58756] [#9192]' - operators = { :== => :==, :< => :>, :> => :<, :<= => :>=, :>= => :<= } - 5.upto(8) do |i| - s = "706.0#{i}" - d = BigDecimal(s) - f = s.to_f - operators.each do |op, inv| - assert_equal(d.send(op, f), f.send(inv, d), - "(BigDecimal(#{s.inspect}) #{op} #{s}) and (#{s} #{inv} BigDecimal(#{s.inspect})) is different #{bug9192}") - end - end - end - - def test_cmp_nan - n1 = BigDecimal("1") - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - assert_equal(nil, BigDecimal("NaN") <=> n1) - assert_equal(false, BigDecimal("NaN") > n1) - assert_equal(nil, BigDecimal("NaN") <=> BigDecimal("NaN")) - assert_equal(false, BigDecimal("NaN") == BigDecimal("NaN")) - end - - def test_cmp_failing_coercion - n1 = BigDecimal("1") - assert_equal(nil, n1 <=> nil) - assert_raise(ArgumentError){n1 > nil} - end - - def test_cmp_coerce - n1 = BigDecimal("1") - n2 = BigDecimal("2") - o1 = Object.new; def o1.coerce(x); [x, BigDecimal("1")]; end - o2 = Object.new; def o2.coerce(x); [x, BigDecimal("2")]; end - assert_equal( 0, n1 <=> o1) - assert_equal( 1, n2 <=> o1) - assert_equal(-1, n1 <=> o2) - assert_operator(n1, :==, o1) - assert_operator(n1, :!=, o2) - assert_operator(n1, :<, o2) - assert_operator(n1, :<=, o1) - assert_operator(n1, :<=, o2) - assert_operator(n2, :>, o1) - assert_operator(n2, :>=, o1) - assert_operator(n1, :>=, 1) - - bug10109 = '[ruby-core:64190]' - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false) - assert_operator(BigDecimal(0), :<, Float::INFINITY, bug10109) - assert_operator(Float::INFINITY, :>, BigDecimal(0), bug10109) - end - - def test_cmp_bignum - assert_operator(BigDecimal((2**100).to_s), :==, 2**100) - end - - def test_cmp_data - d = Time.now; def d.coerce(x); [x, x]; end - assert_operator(BigDecimal((2**100).to_s), :==, d) - end - - def test_precs_deprecated - assert_warn(/BigDecimal#precs is deprecated and will be removed in the future/) do - Warning[:deprecated] = true if defined?(Warning.[]) - BigDecimal("1").precs - end - end - - def test_precs - assert_separately(["-rbigdecimal"], "#{<<~"begin;"}\n#{<<~'end;'}") - begin; - $VERBOSE = nil - a = BigDecimal("1").precs - assert_instance_of(Array, a) - assert_equal(2, a.size) - assert_kind_of(Integer, a[0]) - assert_kind_of(Integer, a[1]) - end; - end - - def test_hash - a = [] - b = BigDecimal("1") - 10.times { a << b *= 10 } - h = {} - a.each_with_index {|x, i| h[x] = i } - a.each_with_index do |x, i| - assert_equal(i, h[x]) - end - end - - def test_marshal - s = Marshal.dump(BigDecimal("1", 1)) - assert_equal(BigDecimal("1", 1), Marshal.load(s)) - - # corrupt data - s = s.gsub(/BigDecimal.*\z/m) {|x| x.gsub(/\d/m, "-") } - assert_raise(TypeError) { Marshal.load(s) } - end - - def test_finite_infinite_nan - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, false) - - x = BigDecimal("0") - assert_equal(true, x.finite?) - assert_equal(nil, x.infinite?) - assert_equal(false, x.nan?) - y = 1 / x - assert_equal(false, y.finite?) - assert_equal(1, y.infinite?) - assert_equal(false, y.nan?) - y = -1 / x - assert_equal(false, y.finite?) - assert_equal(-1, y.infinite?) - assert_equal(false, y.nan?) - - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - y = 0 / x - assert_equal(false, y.finite?) - assert_equal(nil, y.infinite?) - assert_equal(true, y.nan?) - end - - def test_to_i - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - - x = BigDecimal("0") - assert_kind_of(Integer, x.to_i) - assert_equal(0, x.to_i) - assert_raise(FloatDomainError){( 1 / x).to_i} - assert_raise(FloatDomainError){(-1 / x).to_i} - assert_raise(FloatDomainError) {( 0 / x).to_i} - x = BigDecimal("1") - assert_equal(1, x.to_i) - x = BigDecimal((2**100).to_s) - assert_equal(2**100, x.to_i) - end - - def test_to_f - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, false) - - x = BigDecimal("0") - assert_instance_of(Float, x.to_f) - assert_equal(0.0, x.to_f) - assert_equal( 1.0 / 0.0, ( 1 / x).to_f) - assert_equal(-1.0 / 0.0, (-1 / x).to_f) - assert_nan(( 0 / x).to_f) - x = BigDecimal("1") - assert_equal(1.0, x.to_f) - x = BigDecimal((2**100).to_s) - assert_equal((2**100).to_f, x.to_f) - x = BigDecimal("1" + "0" * 10000) - assert_equal(0, BigDecimal("-0").to_f) - - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, true) - assert_raise(FloatDomainError) { x.to_f } - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - assert_kind_of(Float, x .to_f) - assert_kind_of(Float, (-x).to_f) - - bug6944 = '[ruby-core:47342]' - - BigDecimal.mode(BigDecimal::EXCEPTION_UNDERFLOW, true) - x = "1e#{Float::MIN_10_EXP - 2*Float::DIG}" - assert_raise(FloatDomainError, x) {BigDecimal(x).to_f} - x = "-#{x}" - assert_raise(FloatDomainError, x) {BigDecimal(x).to_f} - x = "1e#{Float::MIN_10_EXP - Float::DIG}" - assert_nothing_raised(FloatDomainError, x) { - assert_in_delta(0.0, BigDecimal(x).to_f, 10**Float::MIN_10_EXP, bug6944) - } - x = "-#{x}" - assert_nothing_raised(FloatDomainError, x) { - assert_in_delta(0.0, BigDecimal(x).to_f, 10**Float::MIN_10_EXP, bug6944) - } - - BigDecimal.mode(BigDecimal::EXCEPTION_UNDERFLOW, false) - x = "1e#{Float::MIN_10_EXP - 2*Float::DIG}" - assert_equal( 0.0, BigDecimal(x).to_f, x) - x = "-#{x}" - assert_equal(-0.0, BigDecimal(x).to_f, x) - x = "1e#{Float::MIN_10_EXP - Float::DIG}" - assert_nothing_raised(FloatDomainError, x) { - assert_in_delta(0.0, BigDecimal(x).to_f, 10**Float::MIN_10_EXP, bug6944) - } - x = "-#{x}" - assert_nothing_raised(FloatDomainError, x) { - assert_in_delta(0.0, BigDecimal(x).to_f, 10**Float::MIN_10_EXP, bug6944) - } - - assert_equal( 0.0, BigDecimal( '9e-325').to_f) - assert_equal( 0.0, BigDecimal( '10e-325').to_f) - assert_equal(-0.0, BigDecimal( '-9e-325').to_f) - assert_equal(-0.0, BigDecimal('-10e-325').to_f) - end - - def test_to_r - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - - x = BigDecimal("0") - assert_kind_of(Rational, x.to_r) - assert_equal(0, x.to_r) - assert_raise(FloatDomainError) {( 1 / x).to_r} - assert_raise(FloatDomainError) {(-1 / x).to_r} - assert_raise(FloatDomainError) {( 0 / x).to_r} - - assert_equal(1, BigDecimal("1").to_r) - assert_equal(Rational(3, 2), BigDecimal("1.5").to_r) - assert_equal((2**100).to_r, BigDecimal((2**100).to_s).to_r) - end - - def test_coerce - a, b = BigDecimal("1").coerce(1.0) - assert_instance_of(BigDecimal, a) - assert_instance_of(BigDecimal, b) - assert_equal(2, 1 + BigDecimal("1"), '[ruby-core:25697]') - - a, b = BigDecimal("1").coerce(1.quo(10)) - assert_equal(BigDecimal("0.1"), a, '[ruby-core:34318]') - - a, b = BigDecimal("0.11111").coerce(1.quo(3)) - assert_equal(BigDecimal("0." + "3"*a.precision), a) - - assert_nothing_raised(TypeError, '#7176') do - BigDecimal('1') + Rational(1) - end - end - - def test_uplus - x = BigDecimal("1") - assert_equal(x, x.send(:+@)) - end - - def test_neg - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false) - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - - assert_equal(BigDecimal("-1"), BigDecimal("1").send(:-@)) - assert_equal(BigDecimal("-0"), BigDecimal("0").send(:-@)) - assert_equal(BigDecimal("0"), BigDecimal("-0").send(:-@)) - assert_equal(BigDecimal("-Infinity"), BigDecimal("Infinity").send(:-@)) - assert_equal(BigDecimal("Infinity"), BigDecimal("-Infinity").send(:-@)) - assert_equal(true, BigDecimal("NaN").send(:-@).nan?) - end - - def test_add - x = BigDecimal("1") - assert_equal(BigDecimal("2"), x + x) - assert_equal(1, BigDecimal("0") + 1) - assert_equal(1, x + 0) - - assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal("0") + 0).sign) - assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal("-0") + 0).sign) - assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, (BigDecimal("-0") + BigDecimal("-0")).sign) - - x = BigDecimal((2**100).to_s) - assert_equal(BigDecimal((2**100+1).to_s), x + 1) - - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false) - inf = BigDecimal("Infinity") - neginf = BigDecimal("-Infinity") - - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, true) - assert_raise_with_message(FloatDomainError, "Computation results to 'Infinity'") { inf + inf } - assert_raise_with_message(FloatDomainError, "Computation results to '-Infinity'") { neginf + neginf } - end - - def test_sub - x = BigDecimal("1") - assert_equal(BigDecimal("0"), x - x) - assert_equal(-1, BigDecimal("0") - 1) - assert_equal(1, x - 0) - - assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal("0") - 0).sign) - assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, (BigDecimal("-0") - 0).sign) - assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal("-0") - BigDecimal("-0")).sign) - - x = BigDecimal((2**100).to_s) - assert_equal(BigDecimal((2**100-1).to_s), x - 1) - - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false) - inf = BigDecimal("Infinity") - neginf = BigDecimal("-Infinity") - - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, true) - assert_raise_with_message(FloatDomainError, "Computation results to 'Infinity'") { inf - neginf } - assert_raise_with_message(FloatDomainError, "Computation results to '-Infinity'") { neginf - inf } - end - - def test_sub_with_float - assert_kind_of(BigDecimal, BigDecimal("3") - 1.0) - end - - def test_sub_with_rational - assert_kind_of(BigDecimal, BigDecimal("3") - 1.quo(3)) - end - - def test_mult - x = BigDecimal((2**100).to_s) - assert_equal(BigDecimal((2**100 * 3).to_s), (x * 3).to_i) - assert_equal(x, (x * 1).to_i) - assert_equal(x, (BigDecimal("1") * x).to_i) - assert_equal(BigDecimal((2**200).to_s), (x * x).to_i) - - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false) - inf = BigDecimal("Infinity") - neginf = BigDecimal("-Infinity") - - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, true) - assert_raise_with_message(FloatDomainError, "Computation results to 'Infinity'") { inf * inf } - assert_raise_with_message(FloatDomainError, "Computation results to '-Infinity'") { neginf * inf } - end - - def test_mult_with_float - assert_kind_of(BigDecimal, BigDecimal("3") * 1.5) - assert_equal(BigDecimal("64.4"), BigDecimal(1) * 64.4) - end - - def test_mult_with_rational - assert_kind_of(BigDecimal, BigDecimal("3") * 1.quo(3)) - end - - def test_mult_with_nil - assert_raise(TypeError) { - BigDecimal('1.1') * nil - } - end - - def test_div - x = BigDecimal((2**100).to_s) - assert_equal(BigDecimal((2**100 / 3).to_s), (x / 3).to_i) - assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal("0") / 1).sign) - assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, (BigDecimal("-0") / 1).sign) - assert_equal(2, BigDecimal("2") / 1) - assert_equal(-2, BigDecimal("2") / -1) - - assert_equal(BigDecimal('1486.868686869'), - (BigDecimal('1472.0') / BigDecimal('0.99')).round(9), - '[ruby-core:59365] [#9316]') - - assert_in_delta(4.124045235, - (BigDecimal('0.9932') / (700 * BigDecimal('0.344045') / BigDecimal('1000.0'))).round(9, half: :up), - 10**Float::MIN_10_EXP, '[#9305]') - - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false) - assert_positive_zero(BigDecimal("1.0") / BigDecimal("Infinity")) - assert_negative_zero(BigDecimal("-1.0") / BigDecimal("Infinity")) - assert_negative_zero(BigDecimal("1.0") / BigDecimal("-Infinity")) - assert_positive_zero(BigDecimal("-1.0") / BigDecimal("-Infinity")) - - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, true) - BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, false) - assert_raise_with_message(FloatDomainError, "Computation results in 'Infinity'") { BigDecimal("1") / 0 } - assert_raise_with_message(FloatDomainError, "Computation results in '-Infinity'") { BigDecimal("-1") / 0 } - end - - def test_div_gh220 - x = BigDecimal("1.0") - y = BigDecimal("3672577333.6608990499165058135986328125") - c = BigDecimal("0.272288343892592687909520102748926752911779209181321744700032723729015151607289998e-9") - assert_equal(c, x / y, "[GH-220]") - end - - def test_div_precision - bug13754 = '[ruby-core:82107] [Bug #13754]' - a = BigDecimal('101') - b = BigDecimal('0.9163472602589686') - c = a/b - assert(c.precision > b.precision, - "(101/0.9163472602589686).precision >= (0.9163472602589686).precision #{bug13754}") - end - - def test_div_with_float - assert_kind_of(BigDecimal, BigDecimal("3") / 1.5) - assert_equal(BigDecimal("0.5"), BigDecimal(1) / 2.0) - end - - def test_div_with_rational - assert_kind_of(BigDecimal, BigDecimal("3") / 1.quo(3)) - end - - def test_div_with_complex - q = BigDecimal("3") / 1i - assert_kind_of(Complex, q) - end - - def test_div_error - assert_raise(TypeError) { BigDecimal(20) / '2' } - end - - def test_mod - x = BigDecimal((2**100).to_s) - assert_equal(1, x % 3) - assert_equal(2, (-x) % 3) - assert_equal(-2, x % -3) - assert_equal(-1, (-x) % -3) - end - - def test_mod_with_float - assert_kind_of(BigDecimal, BigDecimal("3") % 1.5) - end - - def test_mod_with_rational - assert_kind_of(BigDecimal, BigDecimal("3") % 1.quo(3)) - end - - def test_remainder - x = BigDecimal((2**100).to_s) - assert_equal(1, x.remainder(3)) - assert_equal(-1, (-x).remainder(3)) - assert_equal(1, x.remainder(-3)) - assert_equal(-1, (-x).remainder(-3)) - end - - def test_remainder_with_float - assert_kind_of(BigDecimal, BigDecimal("3").remainder(1.5)) - end - - def test_remainder_with_rational - assert_kind_of(BigDecimal, BigDecimal("3").remainder(1.quo(3))) - end - - def test_divmod - x = BigDecimal((2**100).to_s) - assert_equal([(x / 3).floor, 1], x.divmod(3)) - assert_equal([(-x / 3).floor, 2], (-x).divmod(3)) - - assert_equal([0, 0], BigDecimal("0").divmod(2)) - - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - assert_raise(ZeroDivisionError){BigDecimal("0").divmod(0)} - end - - def test_divmod_precision - a = BigDecimal('2e55') - b = BigDecimal('1.23456789e10') - q, r = a.divmod(b) - assert_equal((a/b).round(0, :down), q) - assert_equal((a - q*b), r) - - b = BigDecimal('-1.23456789e10') - q, r = a.divmod(b) - assert_equal((a/b).round(0, :down) - 1, q) - assert_equal((a - q*b), r) - end - - def test_divmod_error - assert_raise(TypeError) { BigDecimal(20).divmod('2') } - end - - def test_add_bigdecimal - x = BigDecimal((2**100).to_s) - assert_equal(3000000000000000000000000000000, x.add(x, 1)) - assert_equal(2500000000000000000000000000000, x.add(x, 2)) - assert_equal(2540000000000000000000000000000, x.add(x, 3)) - end - - def test_sub_bigdecimal - x = BigDecimal((2**100).to_s) - assert_equal(1000000000000000000000000000000, x.sub(1, 1)) - assert_equal(1300000000000000000000000000000, x.sub(1, 2)) - assert_equal(1270000000000000000000000000000, x.sub(1, 3)) - end - - def test_mult_bigdecimal - x = BigDecimal((2**100).to_s) - assert_equal(4000000000000000000000000000000, x.mult(3, 1)) - assert_equal(3800000000000000000000000000000, x.mult(3, 2)) - assert_equal(3800000000000000000000000000000, x.mult(3, 3)) - end - - def test_div_bigdecimal - x = BigDecimal((2**100).to_s) - assert_equal(422550200076076467165567735125, x.div(3)) - assert_equal(400000000000000000000000000000, x.div(3, 1)) - assert_equal(420000000000000000000000000000, x.div(3, 2)) - assert_equal(423000000000000000000000000000, x.div(3, 3)) - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false) - assert_equal(0, BigDecimal("0").div(BigDecimal("Infinity"))) - end - end - - def test_div_bigdecimal_with_float_and_precision - x = BigDecimal(5) - y = 5.1 - assert_equal(x.div(BigDecimal(y, 0), 8), - x.div(y, 8)) - - assert_equal(x.div(BigDecimal(y, 0), 100), - x.div(y, 100)) - end - - def test_quo_without_prec - x = BigDecimal(5) - y = BigDecimal(229) - assert_equal(BigDecimal("0.021834061135371179039301310043668122"), x.quo(y)) - end - - def test_quo_with_prec - begin - saved_mode = BigDecimal.mode(BigDecimal::ROUND_MODE) - BigDecimal.mode(BigDecimal::ROUND_MODE, :half_up) - - x = BigDecimal(5) - y = BigDecimal(229) - assert_equal(BigDecimal("0.021834061135371179039301310043668122"), x.quo(y, 0)) - assert_equal(BigDecimal("0.022"), x.quo(y, 2)) - assert_equal(BigDecimal("0.0218"), x.quo(y, 3)) - assert_equal(BigDecimal("0.0218341"), x.quo(y, 6)) - assert_equal(BigDecimal("0.02183406114"), x.quo(y, 10)) - assert_equal(BigDecimal("0.021834061135371179039301310043668122270742358078603"), x.quo(y, 50)) - ensure - BigDecimal.mode(BigDecimal::ROUND_MODE, saved_mode) - end - end - - def test_abs_bigdecimal - x = BigDecimal((2**100).to_s) - assert_equal(1267650600228229401496703205376, x.abs) - x = BigDecimal("-" + (2**100).to_s) - assert_equal(1267650600228229401496703205376, x.abs) - x = BigDecimal("0") - assert_equal(0, x.abs) - x = BigDecimal("-0") - assert_equal(0, x.abs) - - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false) - x = BigDecimal("Infinity") - assert_equal(BigDecimal("Infinity"), x.abs) - x = BigDecimal("-Infinity") - assert_equal(BigDecimal("Infinity"), x.abs) - - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - x = BigDecimal("NaN") - assert_nan(x.abs) - end - - def test_sqrt_bigdecimal - x = BigDecimal("0.09") - assert_in_delta(0.3, x.sqrt(1), 0.001) - x = BigDecimal((2**100).to_s) - y = BigDecimal("1125899906842624") - e = y.exponent - assert_equal(true, (x.sqrt(100) - y).abs < BigDecimal("1E#{e-100}")) - assert_equal(true, (x.sqrt(200) - y).abs < BigDecimal("1E#{e-200}")) - assert_equal(true, (x.sqrt(300) - y).abs < BigDecimal("1E#{e-300}")) - x = BigDecimal("-" + (2**100).to_s) - assert_raise_with_message(FloatDomainError, "sqrt of negative value") { x.sqrt(1) } - x = BigDecimal((2**200).to_s) - assert_equal(2**100, x.sqrt(1)) - - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - assert_raise_with_message(FloatDomainError, "sqrt of 'NaN'(Not a Number)") { BigDecimal("NaN").sqrt(1) } - assert_raise_with_message(FloatDomainError, "sqrt of negative value") { BigDecimal("-Infinity").sqrt(1) } - - assert_equal(0, BigDecimal("0").sqrt(1)) - assert_equal(0, BigDecimal("-0").sqrt(1)) - assert_equal(1, BigDecimal("1").sqrt(1)) - assert_positive_infinite(BigDecimal("Infinity").sqrt(1)) - end - - def test_sqrt_5266 - x = BigDecimal('2' + '0'*100) - assert_equal('0.14142135623730950488016887242096980785696718753769480731', - x.sqrt(56).to_s(56).split(' ')[0]) - assert_equal('0.1414213562373095048801688724209698078569671875376948073', - x.sqrt(55).to_s(55).split(' ')[0]) - - x = BigDecimal('2' + '0'*200) - assert_equal('0.14142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727350138462', - x.sqrt(110).to_s(110).split(' ')[0]) - assert_equal('0.1414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641572735013846', - x.sqrt(109).to_s(109).split(' ')[0]) - end - - def test_fix - x = BigDecimal("1.1") - assert_equal(1, x.fix) - assert_kind_of(BigDecimal, x.fix) - end - - def test_frac - x = BigDecimal("1.1") - assert_equal(0.1, x.frac) - assert_equal(0.1, BigDecimal("0.1").frac) - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - assert_nan(BigDecimal("NaN").frac) - end - - def test_round - assert_equal(3, BigDecimal("3.14159").round) - assert_equal(9, BigDecimal("8.7").round) - assert_equal(3.142, BigDecimal("3.14159").round(3)) - assert_equal(13300.0, BigDecimal("13345.234").round(-2)) - - x = BigDecimal("111.111") - assert_equal(111 , x.round) - assert_equal(111.1 , x.round(1)) - assert_equal(111.11 , x.round(2)) - assert_equal(111.111, x.round(3)) - assert_equal(111.111, x.round(4)) - assert_equal(110 , x.round(-1)) - assert_equal(100 , x.round(-2)) - assert_equal( 0 , x.round(-3)) - assert_equal( 0 , x.round(-4)) - - x = BigDecimal("2.5") - assert_equal(3, x.round(0, BigDecimal::ROUND_UP)) - assert_equal(2, x.round(0, BigDecimal::ROUND_DOWN)) - assert_equal(3, x.round(0, BigDecimal::ROUND_HALF_UP)) - assert_equal(2, x.round(0, BigDecimal::ROUND_HALF_DOWN)) - assert_equal(2, x.round(0, BigDecimal::ROUND_HALF_EVEN)) - assert_equal(3, x.round(0, BigDecimal::ROUND_CEILING)) - assert_equal(2, x.round(0, BigDecimal::ROUND_FLOOR)) - assert_raise(ArgumentError) { x.round(0, 256) } - - x = BigDecimal("-2.5") - assert_equal(-3, x.round(0, BigDecimal::ROUND_UP)) - assert_equal(-2, x.round(0, BigDecimal::ROUND_DOWN)) - assert_equal(-3, x.round(0, BigDecimal::ROUND_HALF_UP)) - assert_equal(-2, x.round(0, BigDecimal::ROUND_HALF_DOWN)) - assert_equal(-2, x.round(0, BigDecimal::ROUND_HALF_EVEN)) - assert_equal(-2, x.round(0, BigDecimal::ROUND_CEILING)) - assert_equal(-3, x.round(0, BigDecimal::ROUND_FLOOR)) - - ROUNDING_MODE_MAP.each do |const, sym| - assert_equal(x.round(0, const), x.round(0, sym)) - end - - bug3803 = '[ruby-core:32136]' - 15.times do |n| - x = BigDecimal("5#{'0'*n}1") - assert_equal(10**(n+2), x.round(-(n+2), BigDecimal::ROUND_HALF_DOWN), bug3803) - assert_equal(10**(n+2), x.round(-(n+2), BigDecimal::ROUND_HALF_EVEN), bug3803) - x = BigDecimal("0.5#{'0'*n}1") - assert_equal(1, x.round(0, BigDecimal::ROUND_HALF_DOWN), bug3803) - assert_equal(1, x.round(0, BigDecimal::ROUND_HALF_EVEN), bug3803) - x = BigDecimal("-0.5#{'0'*n}1") - assert_equal(-1, x.round(0, BigDecimal::ROUND_HALF_DOWN), bug3803) - assert_equal(-1, x.round(0, BigDecimal::ROUND_HALF_EVEN), bug3803) - end - - assert_instance_of(Integer, x.round) - assert_instance_of(Integer, x.round(0)) - assert_instance_of(Integer, x.round(-1)) - assert_instance_of(BigDecimal, x.round(1)) - end - - def test_round_half_even - assert_equal(BigDecimal('12.0'), BigDecimal('12.5').round(half: :even)) - assert_equal(BigDecimal('14.0'), BigDecimal('13.5').round(half: :even)) - - assert_equal(BigDecimal('2.2'), BigDecimal('2.15').round(1, half: :even)) - assert_equal(BigDecimal('2.2'), BigDecimal('2.25').round(1, half: :even)) - assert_equal(BigDecimal('2.4'), BigDecimal('2.35').round(1, half: :even)) - - assert_equal(BigDecimal('-2.2'), BigDecimal('-2.15').round(1, half: :even)) - assert_equal(BigDecimal('-2.2'), BigDecimal('-2.25').round(1, half: :even)) - assert_equal(BigDecimal('-2.4'), BigDecimal('-2.35').round(1, half: :even)) - - assert_equal(BigDecimal('7.1364'), BigDecimal('7.13645').round(4, half: :even)) - assert_equal(BigDecimal('7.1365'), BigDecimal('7.1364501').round(4, half: :even)) - assert_equal(BigDecimal('7.1364'), BigDecimal('7.1364499').round(4, half: :even)) - - assert_equal(BigDecimal('-7.1364'), BigDecimal('-7.13645').round(4, half: :even)) - assert_equal(BigDecimal('-7.1365'), BigDecimal('-7.1364501').round(4, half: :even)) - assert_equal(BigDecimal('-7.1364'), BigDecimal('-7.1364499').round(4, half: :even)) - end - - def test_round_half_up - assert_equal(BigDecimal('13.0'), BigDecimal('12.5').round(half: :up)) - assert_equal(BigDecimal('14.0'), BigDecimal('13.5').round(half: :up)) - - assert_equal(BigDecimal('2.2'), BigDecimal('2.15').round(1, half: :up)) - assert_equal(BigDecimal('2.3'), BigDecimal('2.25').round(1, half: :up)) - assert_equal(BigDecimal('2.4'), BigDecimal('2.35').round(1, half: :up)) - - assert_equal(BigDecimal('-2.2'), BigDecimal('-2.15').round(1, half: :up)) - assert_equal(BigDecimal('-2.3'), BigDecimal('-2.25').round(1, half: :up)) - assert_equal(BigDecimal('-2.4'), BigDecimal('-2.35').round(1, half: :up)) - - assert_equal(BigDecimal('7.1365'), BigDecimal('7.13645').round(4, half: :up)) - assert_equal(BigDecimal('7.1365'), BigDecimal('7.1364501').round(4, half: :up)) - assert_equal(BigDecimal('7.1364'), BigDecimal('7.1364499').round(4, half: :up)) - - assert_equal(BigDecimal('-7.1365'), BigDecimal('-7.13645').round(4, half: :up)) - assert_equal(BigDecimal('-7.1365'), BigDecimal('-7.1364501').round(4, half: :up)) - assert_equal(BigDecimal('-7.1364'), BigDecimal('-7.1364499').round(4, half: :up)) - end - - def test_round_half_down - assert_equal(BigDecimal('12.0'), BigDecimal('12.5').round(half: :down)) - assert_equal(BigDecimal('13.0'), BigDecimal('13.5').round(half: :down)) - - assert_equal(BigDecimal('2.1'), BigDecimal('2.15').round(1, half: :down)) - assert_equal(BigDecimal('2.2'), BigDecimal('2.25').round(1, half: :down)) - assert_equal(BigDecimal('2.3'), BigDecimal('2.35').round(1, half: :down)) - - assert_equal(BigDecimal('-2.1'), BigDecimal('-2.15').round(1, half: :down)) - assert_equal(BigDecimal('-2.2'), BigDecimal('-2.25').round(1, half: :down)) - assert_equal(BigDecimal('-2.3'), BigDecimal('-2.35').round(1, half: :down)) - - assert_equal(BigDecimal('7.1364'), BigDecimal('7.13645').round(4, half: :down)) - assert_equal(BigDecimal('7.1365'), BigDecimal('7.1364501').round(4, half: :down)) - assert_equal(BigDecimal('7.1364'), BigDecimal('7.1364499').round(4, half: :down)) - - assert_equal(BigDecimal('-7.1364'), BigDecimal('-7.13645').round(4, half: :down)) - assert_equal(BigDecimal('-7.1365'), BigDecimal('-7.1364501').round(4, half: :down)) - assert_equal(BigDecimal('-7.1364'), BigDecimal('-7.1364499').round(4, half: :down)) - end - - def test_round_half_nil - x = BigDecimal("2.5") - - BigDecimal.save_rounding_mode do - BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_UP) - assert_equal(3, x.round(0, half: nil)) - end - - BigDecimal.save_rounding_mode do - BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_DOWN) - assert_equal(2, x.round(0, half: nil)) - end - - BigDecimal.save_rounding_mode do - BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_UP) - assert_equal(3, x.round(0, half: nil)) - end - - BigDecimal.save_rounding_mode do - BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_DOWN) - assert_equal(2, x.round(0, half: nil)) - end - - BigDecimal.save_rounding_mode do - BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_EVEN) - assert_equal(2, x.round(0, half: nil)) - end - - BigDecimal.save_rounding_mode do - BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_CEILING) - assert_equal(3, x.round(0, half: nil)) - end - - BigDecimal.save_rounding_mode do - BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_FLOOR) - assert_equal(2, x.round(0, half: nil)) - end - end - - def test_round_half_invalid_option - assert_raise_with_message(ArgumentError, "invalid rounding mode (upp)") do - BigDecimal('12.5').round(half: :upp) - end - assert_raise_with_message(ArgumentError, "invalid rounding mode (evenn)") do - BigDecimal('2.15').round(1, half: :evenn) - end - assert_raise_with_message(ArgumentError, "invalid rounding mode (downn)") do - BigDecimal('2.15').round(1, half: :downn) - end - assert_raise_with_message(ArgumentError, "invalid rounding mode (42)") do - BigDecimal('2.15').round(1, half: 42) - end - end - - def test_truncate - assert_equal(3, BigDecimal("3.14159").truncate) - assert_equal(8, BigDecimal("8.7").truncate) - assert_equal(3.141, BigDecimal("3.14159").truncate(3)) - assert_equal(13300.0, BigDecimal("13345.234").truncate(-2)) - - assert_equal(-3, BigDecimal("-3.14159").truncate) - assert_equal(-8, BigDecimal("-8.7").truncate) - assert_equal(-3.141, BigDecimal("-3.14159").truncate(3)) - assert_equal(-13300.0, BigDecimal("-13345.234").truncate(-2)) - end - - def test_floor - assert_equal(3, BigDecimal("3.14159").floor) - assert_equal(-10, BigDecimal("-9.1").floor) - assert_equal(3.141, BigDecimal("3.14159").floor(3)) - assert_equal(13300.0, BigDecimal("13345.234").floor(-2)) - end - - def test_ceil - assert_equal(4, BigDecimal("3.14159").ceil) - assert_equal(-9, BigDecimal("-9.1").ceil) - assert_equal(3.142, BigDecimal("3.14159").ceil(3)) - assert_equal(13400.0, BigDecimal("13345.234").ceil(-2)) - end - - def test_to_s - assert_equal('0.0', BigDecimal('0').to_s) - assert_equal('-123 45678 90123.45678 90123 45678 9', BigDecimal('-1234567890123.45678901234567890').to_s('5F')) - assert_equal('+12345 67890123.45678901 23456789', BigDecimal('1234567890123.45678901234567890').to_s('+8F')) - assert_equal(' 1234567890123.4567890123456789', BigDecimal('1234567890123.45678901234567890').to_s(' F')) - assert_equal('100 000 000 000.000 000 000 01', BigDecimal('100000000000.00000000001').to_s('3F')) - assert_equal('0.0 0 0 0 0 0 0 0 0 0 0 0 1', BigDecimal('0.0000000000001').to_s('1F')) - assert_equal('+1000000 0000000.0', BigDecimal('10000000000000').to_s('+7F')) - assert_equal('0.1234567890123456789e3', BigDecimal('123.45678901234567890').to_s) - assert_equal('0.12345 67890 12345 6789e3', BigDecimal('123.45678901234567890').to_s(5)) - end - - def test_split - x = BigDecimal('-123.45678901234567890') - assert_equal([-1, "1234567890123456789", 10, 3], x.split) - assert_equal([1, "0", 10, 0], BigDecimal("0").split) - assert_equal([-1, "0", 10, 0], BigDecimal("-0").split) - - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - assert_equal([0, "NaN", 10, 0], BigDecimal("NaN").split) - assert_equal([1, "Infinity", 10, 0], BigDecimal("Infinity").split) - assert_equal([-1, "Infinity", 10, 0], BigDecimal("-Infinity").split) - end - - def test_exponent - x = BigDecimal('-123.45678901234567890') - assert_equal(3, x.exponent) - end - - def test_inspect - assert_equal("0.123456789012e0", BigDecimal("0.123456789012").inspect) - assert_equal("0.123456789012e4", BigDecimal("1234.56789012").inspect) - assert_equal("0.123456789012e-4", BigDecimal("0.0000123456789012").inspect) - end - - def test_power - assert_nothing_raised(TypeError, '[ruby-core:47632]') do - 1000.times { BigDecimal('1001.10')**0.75 } - end - end - - def test_power_with_nil - assert_raise(TypeError) do - BigDecimal(3) ** nil - end - end - - def test_power_of_nan - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - assert_nan(BigDecimal::NAN ** 0) - assert_nan(BigDecimal::NAN ** 1) - assert_nan(BigDecimal::NAN ** 42) - assert_nan(BigDecimal::NAN ** -42) - assert_nan(BigDecimal::NAN ** 42.0) - assert_nan(BigDecimal::NAN ** -42.0) - assert_nan(BigDecimal::NAN ** BigDecimal(42)) - assert_nan(BigDecimal::NAN ** BigDecimal(-42)) - assert_nan(BigDecimal::NAN ** BigDecimal::INFINITY) - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false) - assert_nan(BigDecimal::NAN ** (-BigDecimal::INFINITY)) - end - end - end - - def test_power_with_Bignum - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false) - assert_equal(0, BigDecimal(0) ** (2**100)) - - assert_positive_infinite(BigDecimal(0) ** -(2**100)) - assert_positive_infinite((-BigDecimal(0)) ** -(2**100)) - assert_negative_infinite((-BigDecimal(0)) ** -(2**100 + 1)) - - assert_equal(1, BigDecimal(1) ** (2**100)) - - assert_positive_infinite(BigDecimal(3) ** (2**100)) - assert_positive_zero(BigDecimal(3) ** (-2**100)) - - assert_negative_infinite(BigDecimal(-3) ** (2**100)) - assert_positive_infinite(BigDecimal(-3) ** (2**100 + 1)) - assert_negative_zero(BigDecimal(-3) ** (-2**100)) - assert_positive_zero(BigDecimal(-3) ** (-2**100 - 1)) - - assert_positive_zero(BigDecimal(0.5, Float::DIG) ** (2**100)) - assert_positive_infinite(BigDecimal(0.5, Float::DIG) ** (-2**100)) - - assert_negative_zero(BigDecimal(-0.5, Float::DIG) ** (2**100)) - assert_positive_zero(BigDecimal(-0.5, Float::DIG) ** (2**100 - 1)) - assert_negative_infinite(BigDecimal(-0.5, Float::DIG) ** (-2**100)) - assert_positive_infinite(BigDecimal(-0.5, Float::DIG) ** (-2**100 - 1)) - end - end - - def test_power_with_BigDecimal - assert_nothing_raised do - assert_in_delta(3 ** 3, BigDecimal(3) ** BigDecimal(3)) - end - end - - def test_power_of_finite_with_zero - x = BigDecimal(1) - assert_equal(1, x ** 0) - assert_equal(1, x ** 0.quo(1)) - assert_equal(1, x ** 0.0) - assert_equal(1, x ** BigDecimal(0)) - - x = BigDecimal(42) - assert_equal(1, x ** 0) - assert_equal(1, x ** 0.quo(1)) - assert_equal(1, x ** 0.0) - assert_equal(1, x ** BigDecimal(0)) - - x = BigDecimal(-42) - assert_equal(1, x ** 0) - assert_equal(1, x ** 0.quo(1)) - assert_equal(1, x ** 0.0) - assert_equal(1, x ** BigDecimal(0)) - end - - def test_power_of_three - x = BigDecimal(3) - assert_equal(81, x ** 4) - assert_equal(1.quo(81), x ** -4) - assert_in_delta(1.0/81, x ** -4) - end - - def test_power_of_zero - zero = BigDecimal(0) - assert_equal(0, zero ** 4) - assert_equal(0, zero ** 4.quo(1)) - assert_equal(0, zero ** 4.0) - assert_equal(0, zero ** BigDecimal(4)) - assert_equal(1, zero ** 0) - assert_equal(1, zero ** 0.quo(1)) - assert_equal(1, zero ** 0.0) - assert_equal(1, zero ** BigDecimal(0)) - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false) - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - assert_positive_infinite(zero ** -1) - assert_positive_infinite(zero ** -1.quo(1)) - assert_positive_infinite(zero ** -1.0) - assert_positive_infinite(zero ** BigDecimal(-1)) - - m_zero = BigDecimal("-0") - assert_negative_infinite(m_zero ** -1) - assert_negative_infinite(m_zero ** -1.quo(1)) - assert_negative_infinite(m_zero ** -1.0) - assert_negative_infinite(m_zero ** BigDecimal(-1)) - assert_positive_infinite(m_zero ** -2) - assert_positive_infinite(m_zero ** -2.quo(1)) - assert_positive_infinite(m_zero ** -2.0) - assert_positive_infinite(m_zero ** BigDecimal(-2)) - end - end - - def test_power_of_positive_infinity - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - assert_positive_infinite(BigDecimal::INFINITY ** 3) - assert_positive_infinite(BigDecimal::INFINITY ** 3.quo(1)) - assert_positive_infinite(BigDecimal::INFINITY ** 3.0) - assert_positive_infinite(BigDecimal::INFINITY ** BigDecimal(3)) - assert_positive_infinite(BigDecimal::INFINITY ** 2) - assert_positive_infinite(BigDecimal::INFINITY ** 2.quo(1)) - assert_positive_infinite(BigDecimal::INFINITY ** 2.0) - assert_positive_infinite(BigDecimal::INFINITY ** BigDecimal(2)) - assert_positive_infinite(BigDecimal::INFINITY ** 1) - assert_positive_infinite(BigDecimal::INFINITY ** 1.quo(1)) - assert_positive_infinite(BigDecimal::INFINITY ** 1.0) - assert_positive_infinite(BigDecimal::INFINITY ** BigDecimal(1)) - assert_equal(1, BigDecimal::INFINITY ** 0) - assert_equal(1, BigDecimal::INFINITY ** 0.quo(1)) - assert_equal(1, BigDecimal::INFINITY ** 0.0) - assert_equal(1, BigDecimal::INFINITY ** BigDecimal(0)) - assert_positive_zero(BigDecimal::INFINITY ** -1) - assert_positive_zero(BigDecimal::INFINITY ** -1.quo(1)) - assert_positive_zero(BigDecimal::INFINITY ** -1.0) - assert_positive_zero(BigDecimal::INFINITY ** BigDecimal(-1)) - assert_positive_zero(BigDecimal::INFINITY ** -2) - assert_positive_zero(BigDecimal::INFINITY ** -2.0) - assert_positive_zero(BigDecimal::INFINITY ** BigDecimal(-2)) - end - end - - def test_power_of_negative_infinity - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - assert_negative_infinite((-BigDecimal::INFINITY) ** 3) - assert_negative_infinite((-BigDecimal::INFINITY) ** 3.quo(1)) - assert_negative_infinite((-BigDecimal::INFINITY) ** 3.0) - assert_negative_infinite((-BigDecimal::INFINITY) ** BigDecimal(3)) - assert_positive_infinite((-BigDecimal::INFINITY) ** 2) - assert_positive_infinite((-BigDecimal::INFINITY) ** 2.quo(1)) - assert_positive_infinite((-BigDecimal::INFINITY) ** 2.0) - assert_positive_infinite((-BigDecimal::INFINITY) ** BigDecimal(2)) - assert_negative_infinite((-BigDecimal::INFINITY) ** 1) - assert_negative_infinite((-BigDecimal::INFINITY) ** 1.quo(1)) - assert_negative_infinite((-BigDecimal::INFINITY) ** 1.0) - assert_negative_infinite((-BigDecimal::INFINITY) ** BigDecimal(1)) - assert_equal(1, (-BigDecimal::INFINITY) ** 0) - assert_equal(1, (-BigDecimal::INFINITY) ** 0.quo(1)) - assert_equal(1, (-BigDecimal::INFINITY) ** 0.0) - assert_equal(1, (-BigDecimal::INFINITY) ** BigDecimal(0)) - assert_negative_zero((-BigDecimal::INFINITY) ** -1) - assert_negative_zero((-BigDecimal::INFINITY) ** -1.quo(1)) - assert_negative_zero((-BigDecimal::INFINITY) ** -1.0) - assert_negative_zero((-BigDecimal::INFINITY) ** BigDecimal(-1)) - assert_positive_zero((-BigDecimal::INFINITY) ** -2) - assert_positive_zero((-BigDecimal::INFINITY) ** -2.quo(1)) - assert_positive_zero((-BigDecimal::INFINITY) ** -2.0) - assert_positive_zero((-BigDecimal::INFINITY) ** BigDecimal(-2)) - end - end - - def test_power_without_prec - pi = BigDecimal("3.14159265358979323846264338327950288419716939937511") - e = BigDecimal("2.71828182845904523536028747135266249775724709369996") - pow = BigDecimal("0.2245915771836104547342715220454373502758931513399678438732330680117143493477164265678321738086407229773690574073268002736527e2") - assert_equal(pow, pi.power(e)) - - n = BigDecimal("2222") - assert_equal(BigDecimal("0.5171353084572525892492416e12"), (n ** 3.5)) - assert_equal(BigDecimal("0.517135308457252592e12"), (n ** 3.5r)) - assert_equal(BigDecimal("0.517135308457252589249241582e12"), (n ** BigDecimal("3.5",15))) - end - - def test_power_with_prec - pi = BigDecimal("3.14159265358979323846264338327950288419716939937511") - e = BigDecimal("2.71828182845904523536028747135266249775724709369996") - pow = BigDecimal("22.459157718361045473") - assert_equal(pow, pi.power(e, 20)) - - b = BigDecimal('1.034482758620689655172413793103448275862068965517241379310344827586206896551724') - assert_equal(BigDecimal('0.114523E1'), b.power(4, 5), '[Bug #8818] [ruby-core:56802]') - end - - def test_limit - BigDecimal.save_limit do - BigDecimal.limit(1) - x = BigDecimal("3") - assert_equal(90, x ** 4) # OK? must it be 80? - # 3 * 3 * 3 * 3 = 10 * 3 * 3 = 30 * 3 = 90 ??? - assert_raise(ArgumentError) { BigDecimal.limit(-1) } - - bug7458 = '[ruby-core:50269] [#7458]' - one = BigDecimal('1') - epsilon = BigDecimal('0.7E-18') - - BigDecimal.limit(0) - assert_equal(BigDecimal("1.0000000000000000007"), one + epsilon, "limit(0) #{bug7458}") - - 1.upto(18) do |lim| - BigDecimal.limit(lim) - assert_equal(BigDecimal("1.0"), one + epsilon, "limit(#{lim}) #{bug7458}") - end - - BigDecimal.limit(19) - assert_equal(BigDecimal("1.000000000000000001"), one + epsilon, "limit(19) #{bug7458}") - - BigDecimal.limit(20) - assert_equal(BigDecimal("1.0000000000000000007"), one + epsilon, "limit(20) #{bug7458}") - end - end - - def test_sign - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, false) - - assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, BigDecimal("0").sign) - assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, BigDecimal("-0").sign) - assert_equal(BigDecimal::SIGN_POSITIVE_FINITE, BigDecimal("1").sign) - assert_equal(BigDecimal::SIGN_NEGATIVE_FINITE, BigDecimal("-1").sign) - assert_equal(BigDecimal::SIGN_POSITIVE_INFINITE, (BigDecimal("1") / 0).sign) - assert_equal(BigDecimal::SIGN_NEGATIVE_INFINITE, (BigDecimal("-1") / 0).sign) - assert_equal(BigDecimal::SIGN_NaN, (BigDecimal("0") / 0).sign) - end - - def test_inf - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - inf = BigDecimal("Infinity") - - assert_equal(inf, inf + inf) - assert_nan((inf + (-inf))) - assert_nan((inf - inf)) - assert_equal(inf, inf - (-inf)) - assert_equal(inf, inf * inf) - assert_nan((inf / inf)) - - assert_equal(inf, inf + 1) - assert_equal(inf, inf - 1) - assert_equal(inf, inf * 1) - assert_nan((inf * 0)) - assert_equal(inf, inf / 1) - - assert_equal(inf, 1 + inf) - assert_equal(-inf, 1 - inf) - assert_equal(inf, 1 * inf) - assert_equal(-inf, -1 * inf) - assert_nan((0 * inf)) - assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (1 / inf).sign) - assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, (-1 / inf).sign) - end - - def assert_equal_us_ascii_string(a, b) - assert_equal(a, b) - assert_equal(Encoding::US_ASCII, b.encoding) - end - - def test_to_special_string - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - nan = BigDecimal("NaN") - assert_equal_us_ascii_string("NaN", nan.to_s) - inf = BigDecimal("Infinity") - assert_equal_us_ascii_string("Infinity", inf.to_s) - assert_equal_us_ascii_string(" Infinity", inf.to_s(" ")) - assert_equal_us_ascii_string("+Infinity", inf.to_s("+")) - assert_equal_us_ascii_string("-Infinity", (-inf).to_s) - pzero = BigDecimal("0") - assert_equal_us_ascii_string("0.0", pzero.to_s) - assert_equal_us_ascii_string(" 0.0", pzero.to_s(" ")) - assert_equal_us_ascii_string("+0.0", pzero.to_s("+")) - assert_equal_us_ascii_string("-0.0", (-pzero).to_s) - end - - def test_to_string - assert_equal_us_ascii_string("0.01", BigDecimal("0.01").to_s("F")) - s = "0." + "0" * 100 + "1" - assert_equal_us_ascii_string(s, BigDecimal(s).to_s("F")) - s = "1" + "0" * 100 + ".0" - assert_equal_us_ascii_string(s, BigDecimal(s).to_s("F")) - end - - def test_ctov - assert_equal(0.1, BigDecimal("1E-1")) - assert_equal(10, BigDecimal("1E+1")) - assert_equal(1, BigDecimal("+1")) - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - - assert_equal(BigDecimal::SIGN_POSITIVE_INFINITE, BigDecimal("1E1" + "0" * 10000).sign) - assert_equal(BigDecimal::SIGN_NEGATIVE_INFINITE, BigDecimal("-1E1" + "0" * 10000).sign) - assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, BigDecimal("1E-1" + "0" * 10000).sign) - assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, BigDecimal("-1E-1" + "0" * 10000).sign) - end - - def test_split_under_gc_stress - bug3258 = '[ruby-dev:41213]' - expect = 10.upto(20).map{|i|[1, "1", 10, i+1].inspect} - assert_in_out_err(%w[-rbigdecimal --disable-gems], <<-EOS, expect, [], bug3258) - GC.stress = true - 10.upto(20) do |i| - p BigDecimal("1"+"0"*i).split - end - EOS - end - - def test_coerce_under_gc_stress - assert_in_out_err(%w[-rbigdecimal --disable-gems], <<-EOS, [], []) - expect = ":too_long_to_embed_as_string can't be coerced into BigDecimal" - b = BigDecimal("1") - GC.stress = true - 10.times do - begin - b.coerce(:too_long_to_embed_as_string) - rescue => e - raise unless e.is_a?(TypeError) - raise "'\#{expect}' is expected, but '\#{e.message}'" unless e.message == expect - end - end - EOS - end - - def test_INFINITY - assert_positive_infinite(BigDecimal::INFINITY) - end - - def test_NAN - assert_nan(BigDecimal::NAN) - end - - def test_exp_with_zero_precision - assert_raise(ArgumentError) do - BigMath.exp(1, 0) - end - end - - def test_exp_with_negative_precision - assert_raise(ArgumentError) do - BigMath.exp(1, -42) - end - end - - def test_exp_with_complex - assert_raise(ArgumentError) do - BigMath.exp(Complex(1, 2), 20) - end - end - - def test_exp_with_negative - x = BigDecimal(-1) - y = BigMath.exp(x, 20) - assert_equal(y, BigMath.exp(-1, 20)) - assert_equal(BigDecimal(-1), x) - end - - def test_exp_with_negative_infinite - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false) - assert_equal(0, BigMath.exp(-BigDecimal::INFINITY, 20)) - end - end - - def test_exp_with_positive_infinite - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false) - assert(BigMath.exp(BigDecimal::INFINITY, 20) > 0) - assert_positive_infinite(BigMath.exp(BigDecimal::INFINITY, 20)) - end - end - - def test_exp_with_nan - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - assert_nan(BigMath.exp(BigDecimal::NAN, 20)) - end - end - - def test_exp_with_1 - assert_in_epsilon(Math::E, BigMath.exp(1, 20)) - end - - def test_BigMath_exp - prec = 20 - assert_in_epsilon(Math.exp(20), BigMath.exp(BigDecimal("20"), prec)) - assert_in_epsilon(Math.exp(40), BigMath.exp(BigDecimal("40"), prec)) - assert_in_epsilon(Math.exp(-20), BigMath.exp(BigDecimal("-20"), prec)) - assert_in_epsilon(Math.exp(-40), BigMath.exp(BigDecimal("-40"), prec)) - end - - def test_BigMath_exp_with_float - prec = 20 - assert_in_epsilon(Math.exp(20), BigMath.exp(20.0, prec)) - assert_in_epsilon(Math.exp(40), BigMath.exp(40.0, prec)) - assert_in_epsilon(Math.exp(-20), BigMath.exp(-20.0, prec)) - assert_in_epsilon(Math.exp(-40), BigMath.exp(-40.0, prec)) - end - - def test_BigMath_exp_with_fixnum - prec = 20 - assert_in_epsilon(Math.exp(20), BigMath.exp(20, prec)) - assert_in_epsilon(Math.exp(40), BigMath.exp(40, prec)) - assert_in_epsilon(Math.exp(-20), BigMath.exp(-20, prec)) - assert_in_epsilon(Math.exp(-40), BigMath.exp(-40, prec)) - end - - def test_BigMath_exp_with_rational - prec = 20 - assert_in_epsilon(Math.exp(20), BigMath.exp(Rational(40,2), prec)) - assert_in_epsilon(Math.exp(40), BigMath.exp(Rational(80,2), prec)) - assert_in_epsilon(Math.exp(-20), BigMath.exp(Rational(-40,2), prec)) - assert_in_epsilon(Math.exp(-40), BigMath.exp(Rational(-80,2), prec)) - end - - def test_BigMath_exp_under_gc_stress - assert_in_out_err(%w[-rbigdecimal --disable-gems], <<-EOS, [], []) - expect = ":too_long_to_embed_as_string can't be coerced into BigDecimal" - 10.times do - begin - BigMath.exp(:too_long_to_embed_as_string, 6) - rescue => e - raise unless e.is_a?(ArgumentError) - raise "'\#{expect}' is expected, but '\#{e.message}'" unless e.message == expect - end - end - EOS - end - - def test_BigMath_log_with_string - assert_raise(ArgumentError) do - BigMath.log("foo", 20) - end - end - - def test_BigMath_log_with_nil - assert_raise(ArgumentError) do - BigMath.log(nil, 20) - end - end - - def test_BigMath_log_with_non_integer_precision - assert_raise(ArgumentError) do - BigMath.log(1, 0.5) - end - end - - def test_BigMath_log_with_nil_precision - assert_raise(ArgumentError) do - BigMath.log(1, nil) - end - end - - def test_BigMath_log_with_complex - assert_raise(Math::DomainError) do - BigMath.log(Complex(1, 2), 20) - end - end - - def test_BigMath_log_with_zero_arg - assert_raise(Math::DomainError) do - BigMath.log(0, 20) - end - end - - def test_BigMath_log_with_negative_arg - assert_raise(Math::DomainError) do - BigMath.log(-1, 20) - end - end - - def test_BigMath_log_with_zero_precision - assert_raise(ArgumentError) do - BigMath.log(1, 0) - end - end - - def test_BigMath_log_with_negative_precision - assert_raise(ArgumentError) do - BigMath.log(1, -42) - end - end - - def test_BigMath_log_with_negative_infinite - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false) - assert_raise(Math::DomainError) do - BigMath.log(-BigDecimal::INFINITY, 20) - end - end - end - - def test_BigMath_log_with_positive_infinite - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false) - assert(BigMath.log(BigDecimal::INFINITY, 20) > 0) - assert_positive_infinite(BigMath.log(BigDecimal::INFINITY, 20)) - end - end - - def test_BigMath_log_with_nan - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - assert_nan(BigMath.log(BigDecimal::NAN, 20)) - end - end - - def test_BigMath_log_with_float_nan - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - assert_nan(BigMath.log(Float::NAN, 20)) - end - end - - def test_BigMath_log_with_1 - assert_in_delta(0.0, BigMath.log(1, 20)) - assert_in_delta(0.0, BigMath.log(1.0, 20)) - assert_in_delta(0.0, BigMath.log(BigDecimal(1), 20)) - end - - def test_BigMath_log_with_exp_1 - assert_in_delta(1.0, BigMath.log(BigMath.E(10), 10)) - end - - def test_BigMath_log_with_2 - assert_in_delta(Math.log(2), BigMath.log(2, 20)) - assert_in_delta(Math.log(2), BigMath.log(2.0, 20)) - assert_in_delta(Math.log(2), BigMath.log(BigDecimal(2), 20)) - end - - def test_BigMath_log_with_square_of_E - assert_in_delta(2, BigMath.log(BigMath.E(20)**2, 20)) - end - - def test_BigMath_log_with_high_precision_case - e = BigDecimal('2.71828182845904523536028747135266249775724709369996') - e_3 = e.mult(e, 50).mult(e, 50) - log_3 = BigMath.log(e_3, 50) - assert_in_delta(3, log_3, 0.0000000000_0000000000_0000000000_0000000000_0000000001) - end - - def test_BigMath_log_with_42 - assert_in_delta(Math.log(42), BigMath.log(42, 20)) - assert_in_delta(Math.log(42), BigMath.log(42.0, 20)) - assert_in_delta(Math.log(42), BigMath.log(BigDecimal(42), 20)) - end - - def test_BigMath_log_with_101 - # this is mainly a performance test (should be very fast, not the 0.3 s) - assert_in_delta(Math.log(101), BigMath.log(101, 20), 1E-15) - end - - def test_BigMath_log_with_reciprocal_of_42 - assert_in_delta(Math.log(1e-42), BigMath.log(1e-42, 20)) - assert_in_delta(Math.log(1e-42), BigMath.log(BigDecimal("1e-42"), 20)) - end - - def test_BigMath_log_under_gc_stress - assert_in_out_err(%w[-rbigdecimal --disable-gems], <<-EOS, [], []) - expect = ":too_long_to_embed_as_string can't be coerced into BigDecimal" - 10.times do - begin - BigMath.log(:too_long_to_embed_as_string, 6) - rescue => e - raise unless e.is_a?(ArgumentError) - raise "'\#{expect}' is expected, but '\#{e.message}'" unless e.message == expect - end - end - EOS - end - - def test_frozen_p - x = BigDecimal(1) - assert(x.frozen?) - assert((x + x).frozen?) - end - - def test_clone - assert_warning(/^$/) do - x = BigDecimal(0) - assert_same(x, x.clone) - end - end - - def test_dup - assert_warning(/^$/) do - [1, -1, 2**100, -2**100].each do |i| - x = BigDecimal(i) - assert_same(x, x.dup) - end - end - end - - def test_new_subclass - c = Class.new(BigDecimal) - assert_raise_with_message(NoMethodError, /undefined method `new'/) { c.new(1) } - end - - def test_to_d - bug6093 = '[ruby-core:42969]' - code = "exit(BigDecimal('10.0') == 10.0.to_d)" - assert_ruby_status(%w[-rbigdecimal -rbigdecimal/util -rmathn -], code, bug6093) - end if RUBY_VERSION < '2.5' # mathn was removed from Ruby 2.5 - - def test_bug6406 - assert_in_out_err(%w[-rbigdecimal --disable-gems], <<-EOS, [], []) - Thread.current.keys.to_s - EOS - end - - def test_precision_only_integer - assert_equal(0, BigDecimal(0).precision) - assert_equal(1, BigDecimal(1).precision) - assert_equal(1, BigDecimal(-1).precision) - assert_equal(2, BigDecimal(10).precision) - assert_equal(2, BigDecimal(-10).precision) - assert_equal(9, BigDecimal(100_000_000).precision) - assert_equal(9, BigDecimal(-100_000_000).precision) - assert_equal(12, BigDecimal(100_000_000_000).precision) - assert_equal(12, BigDecimal(-100_000_000_000).precision) - assert_equal(21, BigDecimal(100_000_000_000_000_000_000).precision) - assert_equal(21, BigDecimal(-100_000_000_000_000_000_000).precision) - assert_equal(103, BigDecimal("111e100").precision) - assert_equal(103, BigDecimal("-111e100").precision) - end - - def test_precision_only_fraction - assert_equal(1, BigDecimal("0.1").precision) - assert_equal(1, BigDecimal("-0.1").precision) - assert_equal(2, BigDecimal("0.01").precision) - assert_equal(2, BigDecimal("-0.01").precision) - assert_equal(2, BigDecimal("0.11").precision) - assert_equal(2, BigDecimal("-0.11").precision) - assert_equal(9, BigDecimal("0.000_000_001").precision) - assert_equal(9, BigDecimal("-0.000_000_001").precision) - assert_equal(10, BigDecimal("0.000_000_000_1").precision) - assert_equal(10, BigDecimal("-0.000_000_000_1").precision) - assert_equal(21, BigDecimal("0.000_000_000_000_000_000_001").precision) - assert_equal(21, BigDecimal("-0.000_000_000_000_000_000_001").precision) - assert_equal(100, BigDecimal("111e-100").precision) - assert_equal(100, BigDecimal("-111e-100").precision) - end - - def test_precision_full - assert_equal(5, BigDecimal("11111e-2").precision) - assert_equal(5, BigDecimal("-11111e-2").precision) - assert_equal(5, BigDecimal("11111e-2").precision) - assert_equal(5, BigDecimal("-11111e-2").precision) - assert_equal(21, BigDecimal("100.000_000_000_000_000_001").precision) - assert_equal(21, BigDecimal("-100.000_000_000_000_000_001").precision) - end - - def test_precision_special - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - - assert_equal(0, BigDecimal("Infinity").precision) - assert_equal(0, BigDecimal("-Infinity").precision) - assert_equal(0, BigDecimal("NaN").precision) - end - end - - def test_scale_only_integer - assert_equal(0, BigDecimal(0).scale) - assert_equal(0, BigDecimal(1).scale) - assert_equal(0, BigDecimal(-1).scale) - assert_equal(0, BigDecimal(10).scale) - assert_equal(0, BigDecimal(-10).scale) - assert_equal(0, BigDecimal(100_000_000).scale) - assert_equal(0, BigDecimal(-100_000_000).scale) - assert_equal(0, BigDecimal(100_000_000_000).scale) - assert_equal(0, BigDecimal(-100_000_000_000).scale) - assert_equal(0, BigDecimal(100_000_000_000_000_000_000).scale) - assert_equal(0, BigDecimal(-100_000_000_000_000_000_000).scale) - assert_equal(0, BigDecimal("111e100").scale) - assert_equal(0, BigDecimal("-111e100").scale) - end - - def test_scale_only_fraction - assert_equal(1, BigDecimal("0.1").scale) - assert_equal(1, BigDecimal("-0.1").scale) - assert_equal(2, BigDecimal("0.01").scale) - assert_equal(2, BigDecimal("-0.01").scale) - assert_equal(2, BigDecimal("0.11").scale) - assert_equal(2, BigDecimal("-0.11").scale) - assert_equal(21, BigDecimal("0.000_000_000_000_000_000_001").scale) - assert_equal(21, BigDecimal("-0.000_000_000_000_000_000_001").scale) - assert_equal(100, BigDecimal("111e-100").scale) - assert_equal(100, BigDecimal("-111e-100").scale) - end - - def test_scale_full - assert_equal(1, BigDecimal("0.1").scale) - assert_equal(1, BigDecimal("-0.1").scale) - assert_equal(2, BigDecimal("0.01").scale) - assert_equal(2, BigDecimal("-0.01").scale) - assert_equal(2, BigDecimal("0.11").scale) - assert_equal(2, BigDecimal("-0.11").scale) - assert_equal(2, BigDecimal("11111e-2").scale) - assert_equal(2, BigDecimal("-11111e-2").scale) - assert_equal(18, BigDecimal("100.000_000_000_000_000_001").scale) - assert_equal(18, BigDecimal("-100.000_000_000_000_000_001").scale) - end - - def test_scale_special - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - - assert_equal(0, BigDecimal("Infinity").scale) - assert_equal(0, BigDecimal("-Infinity").scale) - assert_equal(0, BigDecimal("NaN").scale) - end - end - - def test_precision_scale - assert_equal([2, 0], BigDecimal("11.0").precision_scale) - assert_equal([2, 1], BigDecimal("1.1").precision_scale) - assert_equal([2, 2], BigDecimal("0.11").precision_scale) - - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - assert_equal([0, 0], BigDecimal("Infinity").precision_scale) - end - end - - def test_n_significant_digits_only_integer - assert_equal(0, BigDecimal(0).n_significant_digits) - assert_equal(1, BigDecimal(1).n_significant_digits) - assert_equal(1, BigDecimal(-1).n_significant_digits) - assert_equal(1, BigDecimal(10).n_significant_digits) - assert_equal(1, BigDecimal(-10).n_significant_digits) - assert_equal(3, BigDecimal(101).n_significant_digits) - assert_equal(3, BigDecimal(-101).n_significant_digits) - assert_equal(1, BigDecimal(100_000_000_000_000_000_000).n_significant_digits) - assert_equal(1, BigDecimal(-100_000_000_000_000_000_000).n_significant_digits) - assert_equal(21, BigDecimal(100_000_000_000_000_000_001).n_significant_digits) - assert_equal(21, BigDecimal(-100_000_000_000_000_000_001).n_significant_digits) - assert_equal(3, BigDecimal("111e100").n_significant_digits) - assert_equal(3, BigDecimal("-111e100").n_significant_digits) - end - - def test_n_significant_digits_only_fraction - assert_equal(1, BigDecimal("0.1").n_significant_digits) - assert_equal(1, BigDecimal("-0.1").n_significant_digits) - assert_equal(1, BigDecimal("0.01").n_significant_digits) - assert_equal(1, BigDecimal("-0.01").n_significant_digits) - assert_equal(2, BigDecimal("0.11").n_significant_digits) - assert_equal(2, BigDecimal("-0.11").n_significant_digits) - assert_equal(1, BigDecimal("0.000_000_000_000_000_000_001").n_significant_digits) - assert_equal(1, BigDecimal("-0.000_000_000_000_000_000_001").n_significant_digits) - assert_equal(3, BigDecimal("111e-100").n_significant_digits) - assert_equal(3, BigDecimal("-111e-100").n_significant_digits) - end - - def test_n_significant_digits_full - assert_equal(2, BigDecimal("1.1").n_significant_digits) - assert_equal(2, BigDecimal("-1.1").n_significant_digits) - assert_equal(3, BigDecimal("1.01").n_significant_digits) - assert_equal(3, BigDecimal("-1.01").n_significant_digits) - assert_equal(5, BigDecimal("11111e-2").n_significant_digits) - assert_equal(5, BigDecimal("-11111e-2").n_significant_digits) - assert_equal(21, BigDecimal("100.000_000_000_000_000_001").n_significant_digits) - assert_equal(21, BigDecimal("-100.000_000_000_000_000_001").n_significant_digits) - end - - def test_n_significant_digits_special - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - - assert_equal(0, BigDecimal("Infinity").n_significant_digits) - assert_equal(0, BigDecimal("-Infinity").n_significant_digits) - assert_equal(0, BigDecimal("NaN").n_significant_digits) - end - end - - def test_initialize_copy_dup_clone_frozen_error - bd = BigDecimal(1) - bd2 = BigDecimal(2) - err = RUBY_VERSION >= '2.5' ? FrozenError : TypeError - assert_raise(err) { bd.send(:initialize_copy, bd2) } - assert_raise(err) { bd.send(:initialize_clone, bd2) } - assert_raise(err) { bd.send(:initialize_dup, bd2) } - end - - def test_llong_min_gh_200 - # https://github.com/ruby/bigdecimal/issues/199 - # Between LLONG_MIN and -ULLONG_MAX - assert_equal(BigDecimal(LIMITS["LLONG_MIN"].to_s), BigDecimal(LIMITS["LLONG_MIN"]), "[GH-200]") - - minus_ullong_max = -LIMITS["ULLONG_MAX"] - assert_equal(BigDecimal(minus_ullong_max.to_s), BigDecimal(minus_ullong_max), "[GH-200]") - end - - def test_reminder_infinity_gh_187 - # https://github.com/ruby/bigdecimal/issues/187 - BigDecimal.save_exception_mode do - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false) - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - bd = BigDecimal("4.2") - assert_equal(bd.remainder(BigDecimal("+Infinity")), bd) - assert_equal(bd.remainder(BigDecimal("-Infinity")), bd) - end - end - - def test_bsearch_for_bigdecimal - assert_raise(TypeError) { - (BigDecimal('0.5')..BigDecimal('2.25')).bsearch - } - end - - def assert_no_memory_leak(code, *rest, **opt) - code = "8.times {20_000.times {begin #{code}; rescue NoMemoryError; end}; GC.start}" - super(["-rbigdecimal"], - "b = BigDecimal('10'); b.nil?; " \ - "GC.add_stress_to_class(BigDecimal); "\ - "#{code}", code, *rest, rss: true, limit: 1.1, **opt) - end - - if EnvUtil.gc_stress_to_class? - def test_no_memory_leak_allocate - assert_no_memory_leak("BigDecimal.allocate") - end - - def test_no_memory_leak_initialize - assert_no_memory_leak("BigDecimal()") - end - - def test_no_memory_leak_BigDecimal - assert_no_memory_leak("BigDecimal('10')") - assert_no_memory_leak("BigDecimal(b)") - end - - def test_no_memory_leak_create - assert_no_memory_leak("b + 10") - end - end -end diff --git a/test/bigdecimal/test_bigdecimal_util.rb b/test/bigdecimal/test_bigdecimal_util.rb deleted file mode 100644 index 2f27163ebfa702..00000000000000 --- a/test/bigdecimal/test_bigdecimal_util.rb +++ /dev/null @@ -1,141 +0,0 @@ -# frozen_string_literal: false -require_relative "helper" -require 'bigdecimal/util' - -class TestBigDecimalUtil < Test::Unit::TestCase - include TestBigDecimalBase - - def test_BigDecimal_to_d - x = BigDecimal(1) - assert_same(x, x.to_d) - end - - def test_Integer_to_d - assert_equal(BigDecimal(1), 1.to_d) - assert_equal(BigDecimal(2<<100), (2<<100).to_d) - - assert(1.to_d.frozen?) - end - - def test_Float_to_d_without_precision - delta = 1.0/10**(Float::DIG+1) - assert_in_delta(BigDecimal(0.5, 0), 0.5.to_d, delta) - assert_in_delta(BigDecimal(355.0/113.0, 0), (355.0/113.0).to_d, delta) - - assert_equal(9.05, 9.05.to_d.to_f) - assert_equal("9.05", 9.05.to_d.to_s('F')) - - assert_equal("65.6", 65.6.to_d.to_s("F")) - - assert_equal(Math::PI, Math::PI.to_d.to_f) - - bug9214 = '[ruby-core:58858]' - assert_equal((-0.0).to_d.sign, -1, bug9214) - - assert_raise(TypeError) { 0.3.to_d(nil) } - assert_raise(TypeError) { 0.3.to_d(false) } - - assert(1.1.to_d.frozen?) - - assert_equal(BigDecimal("999_999.9999"), 999_999.9999.to_d) - end - - def test_Float_to_d_with_precision - digits = 5 - delta = 1.0/10**(digits) - assert_in_delta(BigDecimal(0.5, 5), 0.5.to_d(digits), delta) - assert_in_delta(BigDecimal(355.0/113.0, 5), (355.0/113.0).to_d(digits), delta) - - bug9214 = '[ruby-core:58858]' - assert_equal((-0.0).to_d(digits).sign, -1, bug9214) - - assert(1.1.to_d(digits).frozen?) - end - - def test_Float_to_d_bug13331 - assert_equal(64.4.to_d, - 1.to_d * 64.4, - "[ruby-core:80234] [Bug #13331]") - - assert_equal((2*Math::PI).to_d, - 2.to_d * Math::PI, - "[ruby-core:80234] [Bug #13331]") - end - - def test_Float_to_d_issue_192 - # https://github.com/ruby/bigdecimal/issues/192 - # https://github.com/rails/rails/pull/42125 - if BASE_FIG == 9 - flo = 1_000_000_000.12345 - big = BigDecimal("0.100000000012345e10") - else # BASE_FIG == 4 - flo = 1_0000.12 - big = BigDecimal("0.1000012e5") - end - assert_equal(flo.to_d, big, "[ruby/bigdecimal#192]") - end - - def test_Rational_to_d - digits = 100 - delta = 1.0/10**(digits) - assert_in_delta(BigDecimal(1.quo(2), digits), 1.quo(2).to_d(digits), delta) - assert_in_delta(BigDecimal(355.quo(113), digits), 355.quo(113).to_d(digits), delta) - - assert(355.quo(113).to_d(digits).frozen?) - end - - def test_Rational_to_d_with_zero_precision - assert_equal(BigDecimal(355.quo(113), 0), 355.quo(113).to_d(0)) - end - - def test_Rational_to_d_with_negative_precision - assert_raise(ArgumentError) { 355.quo(113).to_d(-42) } - end - - def test_Complex_to_d - BigDecimal.save_rounding_mode do - BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_EVEN) - - assert_equal(BigDecimal("1"), Complex(1, 0).to_d) - assert_equal(BigDecimal("0.333333333333333333333"), - Complex(1.quo(3), 0).to_d(21)) - assert_equal(BigDecimal("0.1234567"), Complex(0.1234567, 0).to_d) - assert_equal(BigDecimal("0.1235"), Complex(0.1234567, 0).to_d(4)) - - assert_raise_with_message(ArgumentError, "can't omit precision for a Rational.") { Complex(1.quo(3), 0).to_d } - - assert_raise_with_message(ArgumentError, "Unable to make a BigDecimal from non-zero imaginary number") { Complex(1, 1).to_d } - end - end - - def test_String_to_d - assert_equal(BigDecimal('1'), "1__1_1".to_d) - assert_equal(BigDecimal('2.5'), "2.5".to_d) - assert_equal(BigDecimal('2.5'), "2.5 degrees".to_d) - assert_equal(BigDecimal('2.5e1'), "2.5e1 degrees".to_d) - assert_equal(BigDecimal('0'), "degrees 100.0".to_d) - assert_equal(BigDecimal('0.125'), "0.1_2_5".to_d) - assert_equal(BigDecimal('0.125'), "0.1_2_5__".to_d) - assert_equal(BigDecimal('1'), "1_.125".to_d) - assert_equal(BigDecimal('1'), "1._125".to_d) - assert_equal(BigDecimal('0.1'), "0.1__2_5".to_d) - assert_equal(BigDecimal('0.1'), "0.1_e10".to_d) - assert_equal(BigDecimal('0.1'), "0.1e_10".to_d) - assert_equal(BigDecimal('1'), "0.1e1__0".to_d) - assert_equal(BigDecimal('1.2'), "1.2.3".to_d) - assert_equal(BigDecimal('1'), "1.".to_d) - assert_equal(BigDecimal('1'), "1e".to_d) - - assert("2.5".to_d.frozen?) - end - - def test_invalid_String_to_d - assert_equal("invalid".to_d, BigDecimal('0.0')) - end - - def test_Nil_to_d - assert_equal(nil.to_d, BigDecimal('0.0')) - - assert(nil.to_d) - end -end diff --git a/test/bigdecimal/test_bigmath.rb b/test/bigdecimal/test_bigmath.rb deleted file mode 100644 index 5bf1fbf318a795..00000000000000 --- a/test/bigdecimal/test_bigmath.rb +++ /dev/null @@ -1,81 +0,0 @@ -# frozen_string_literal: false -require_relative "helper" -require "bigdecimal/math" - -class TestBigMath < Test::Unit::TestCase - include TestBigDecimalBase - include BigMath - N = 20 - PINF = BigDecimal("+Infinity") - MINF = BigDecimal("-Infinity") - NAN = BigDecimal("NaN") - - def test_const - assert_in_delta(Math::PI, PI(N)) - assert_in_delta(Math::E, E(N)) - end - - def test_sqrt - assert_in_delta(2**0.5, sqrt(BigDecimal("2"), N)) - assert_equal(10, sqrt(BigDecimal("100"), N)) - assert_equal(0.0, sqrt(BigDecimal("0"), N)) - assert_equal(0.0, sqrt(BigDecimal("-0"), N)) - assert_raise(FloatDomainError) {sqrt(BigDecimal("-1.0"), N)} - assert_raise(FloatDomainError) {sqrt(NAN, N)} - assert_raise(FloatDomainError) {sqrt(PINF, N)} - end - - def test_sin - assert_in_delta(0.0, sin(BigDecimal("0.0"), N)) - assert_in_delta(Math.sqrt(2.0) / 2, sin(PI(N) / 4, N)) - assert_in_delta(1.0, sin(PI(N) / 2, N)) - assert_in_delta(0.0, sin(PI(N) * 2, N)) - assert_in_delta(0.0, sin(PI(N), N)) - assert_in_delta(-1.0, sin(PI(N) / -2, N)) - assert_in_delta(0.0, sin(PI(N) * -2, N)) - assert_in_delta(0.0, sin(-PI(N), N)) - assert_in_delta(0.0, sin(PI(N) * 21, N)) - assert_in_delta(0.0, sin(PI(N) * 30, N)) - assert_in_delta(-1.0, sin(PI(N) * BigDecimal("301.5"), N)) - end - - def test_cos - assert_in_delta(1.0, cos(BigDecimal("0.0"), N)) - assert_in_delta(Math.sqrt(2.0) / 2, cos(PI(N) / 4, N)) - assert_in_delta(0.0, cos(PI(N) / 2, N)) - assert_in_delta(1.0, cos(PI(N) * 2, N)) - assert_in_delta(-1.0, cos(PI(N), N)) - assert_in_delta(0.0, cos(PI(N) / -2, N)) - assert_in_delta(1.0, cos(PI(N) * -2, N)) - assert_in_delta(-1.0, cos(-PI(N), N)) - assert_in_delta(-1.0, cos(PI(N) * 21, N)) - assert_in_delta(1.0, cos(PI(N) * 30, N)) - assert_in_delta(0.0, cos(PI(N) * BigDecimal("301.5"), N)) - end - - def test_atan - assert_equal(0.0, atan(BigDecimal("0.0"), N)) - assert_in_delta(Math::PI/4, atan(BigDecimal("1.0"), N)) - assert_in_delta(Math::PI/6, atan(sqrt(BigDecimal("3.0"), N) / 3, N)) - assert_in_delta(Math::PI/2, atan(PINF, N)) - assert_equal(BigDecimal("0.823840753418636291769355073102514088959345624027952954058347023122539489"), - atan(BigDecimal("1.08"), 72).round(72), '[ruby-dev:41257]') - end - - def test_log - assert_equal(0, BigMath.log(BigDecimal("1.0"), 10)) - assert_in_epsilon(Math.log(10)*1000, BigMath.log(BigDecimal("1e1000"), 10)) - assert_raise(Math::DomainError) {BigMath.log(BigDecimal("0"), 10)} - assert_raise(Math::DomainError) {BigMath.log(BigDecimal("-1"), 10)} - assert_separately(%w[-rbigdecimal], <<-SRC) - begin - x = BigMath.log(BigDecimal("1E19999999999999"), 10) - rescue FloatDomainError - else - unless x.infinite? - assert_in_epsilon(Math.log(10)*19999999999999, x) - end - end - SRC - end -end diff --git a/test/bigdecimal/test_ractor.rb b/test/bigdecimal/test_ractor.rb deleted file mode 100644 index 798cc494e18a9d..00000000000000 --- a/test/bigdecimal/test_ractor.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true -require_relative "helper" - -class TestBigDecimalRactor < Test::Unit::TestCase - include TestBigDecimalBase - - def setup - super - omit unless defined? Ractor - end - - def test_ractor_shareable - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") - begin; - $VERBOSE = nil - require "bigdecimal" - r = Ractor.new BigDecimal(Math::PI, Float::DIG+1) do |pi| - BigDecimal('2.0')*pi - end - assert_equal(2*Math::PI, r.take) - end; - end -end From 272b1c92cceb7b1e2780856058183aa79f3ff213 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 17 Jan 2024 10:00:27 +0900 Subject: [PATCH 264/640] Document about bigdecimal at Ruby 3.4 --- doc/maintainers.md | 6 +++--- doc/standard_library.rdoc | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/maintainers.md b/doc/maintainers.md index 32aa64dce150fb..57a4d93bdcd80c 100644 --- a/doc/maintainers.md +++ b/doc/maintainers.md @@ -327,9 +327,6 @@ have commit right, others don't. * https://rubygems.org/gems/weakref ### Extensions -#### ext/bigdecimal -* Kenta Murata (mrkn) https://github.com/ruby/bigdecimal -* https://rubygems.org/gems/bigdecimal #### ext/cgi * Nobuyoshi Nakada (nobu) @@ -481,6 +478,9 @@ have commit right, others don't. #### lib/base64.rb * https://github.com/ruby/base64 +#### ext/bigdecimal +* https://rubygems.org/gems/bigdecimal + ## Platform Maintainers ### mswin64 (Microsoft Windows) * NAKAMURA Usaku (usa) diff --git a/doc/standard_library.rdoc b/doc/standard_library.rdoc index 68fc34de01eb65..0d7bf45bf3f4b7 100644 --- a/doc/standard_library.rdoc +++ b/doc/standard_library.rdoc @@ -82,7 +82,6 @@ WeakRef:: Allows a referenced object to be garbage-collected == Extensions -BigDecimal:: Provides arbitrary-precision floating point decimal arithmetic Date:: A subclass of Object includes Comparable module for handling dates DateTime:: Subclass of Date to handling dates, hours, minutes, seconds, offsets Digest:: Provides a framework for message digest libraries @@ -130,3 +129,4 @@ Racc:: A LALR(1) parser generator written in Ruby. Mutex_m:: Mixin to extend objects to be handled like a Mutex GetoptLong:: Parse command line options similar to the GNU C getopt_long() Base64:: Support for encoding and decoding binary data using a Base64 representation +BigDecimal:: Provides arbitrary-precision floating point decimal arithmetic From 4dde4d1437ad5c39e4fdd78fdb6bdc3b230f9f7b Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 17 Jan 2024 10:01:25 +0900 Subject: [PATCH 265/640] Stop sync commits from bigdecimal repo --- tool/sync_default_gems.rb | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb index d403a01667d6f7..e9ce28a87e0e94 100755 --- a/tool/sync_default_gems.rb +++ b/tool/sync_default_gems.rb @@ -21,7 +21,6 @@ module SyncDefaultGems English: "ruby/English", abbrev: "ruby/abbrev", benchmark: "ruby/benchmark", - bigdecimal: "ruby/bigdecimal", cgi: "ruby/cgi", csv: 'ruby/csv', date: 'ruby/date', @@ -339,14 +338,6 @@ def sync_default_gems(gem) cp_r("#{upstream}/test/test_syslog.rb", "test") cp_r("#{upstream}/syslog.gemspec", "ext/syslog") `git checkout ext/syslog/depend` - when "bigdecimal" - rm_rf(%w[ext/bigdecimal test/bigdecimal]) - cp_r("#{upstream}/ext/bigdecimal", "ext") - cp_r("#{upstream}/sample", "ext/bigdecimal") - cp_r("#{upstream}/lib", "ext/bigdecimal") - cp_r("#{upstream}/test/bigdecimal", "test") - cp_r("#{upstream}/bigdecimal.gemspec", "ext/bigdecimal") - `git checkout ext/bigdecimal/depend` when "pathname" rm_rf(%w[ext/pathname test/pathname]) cp_r("#{upstream}/ext/pathname", "ext") From 0bdab1a784fb295df627f4650e14966fe11ec3e0 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 17 Jan 2024 12:31:35 +0900 Subject: [PATCH 266/640] Load Rake::TaskLib when missing it --- gems/lib/rake/extensiontask.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gems/lib/rake/extensiontask.rb b/gems/lib/rake/extensiontask.rb index aa668935fc154c..fdbe8d8874cd03 100644 --- a/gems/lib/rake/extensiontask.rb +++ b/gems/lib/rake/extensiontask.rb @@ -1,3 +1,5 @@ +require "rake/tasklib" unless defined?(Rake::TaskLib) + module Rake class ExtensionTask < TaskLib def initialize(...) From 9f729cf36a14ac47a08399aa0426343353f20b6c Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 17 Jan 2024 12:51:37 +0900 Subject: [PATCH 267/640] Skip bigdecimal extension on TestExtLibs --- test/test_extlibs.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/test/test_extlibs.rb b/test/test_extlibs.rb index 38070f227a478b..3e0276d8524ffa 100644 --- a/test/test_extlibs.rb +++ b/test/test_extlibs.rb @@ -41,7 +41,6 @@ def windows? end @excluded = excluded - check_existence "bigdecimal" check_existence "continuation" check_existence "coverage" check_existence "date" From 4328f190eaae5fc7e15e9889a0d9e7b2b8fa56ab Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 17 Jan 2024 13:15:37 +0900 Subject: [PATCH 268/640] spec/mspec/tool/wrap_with_guard.rb 'ruby_version_is ""..."3.4"' spec/ruby/library/bigdecimal/**/*_spec.rb --- .../library/bigdecimal/BigDecimal_spec.rb | 415 ++++++++--------- spec/ruby/library/bigdecimal/abs_spec.rb | 89 ++-- spec/ruby/library/bigdecimal/add_spec.rb | 339 +++++++------- .../library/bigdecimal/case_compare_spec.rb | 9 +- spec/ruby/library/bigdecimal/ceil_spec.rb | 187 ++++---- spec/ruby/library/bigdecimal/clone_spec.rb | 9 +- spec/ruby/library/bigdecimal/coerce_spec.rb | 43 +- .../library/bigdecimal/comparison_spec.rb | 137 +++--- .../ruby/library/bigdecimal/constants_spec.rb | 111 ++--- spec/ruby/library/bigdecimal/div_spec.rb | 185 ++++---- spec/ruby/library/bigdecimal/divide_spec.rb | 23 +- spec/ruby/library/bigdecimal/divmod_spec.rb | 293 ++++++------ .../library/bigdecimal/double_fig_spec.rb | 13 +- spec/ruby/library/bigdecimal/dup_spec.rb | 9 +- spec/ruby/library/bigdecimal/eql_spec.rb | 9 +- .../library/bigdecimal/equal_value_spec.rb | 9 +- spec/ruby/library/bigdecimal/exponent_spec.rb | 41 +- spec/ruby/library/bigdecimal/finite_spec.rb | 57 +-- spec/ruby/library/bigdecimal/fix_spec.rb | 99 ++-- spec/ruby/library/bigdecimal/floor_spec.rb | 169 +++---- spec/ruby/library/bigdecimal/frac_spec.rb | 89 ++-- spec/ruby/library/bigdecimal/gt_spec.rb | 161 +++---- spec/ruby/library/bigdecimal/gte_spec.rb | 169 +++---- spec/ruby/library/bigdecimal/hash_spec.rb | 43 +- spec/ruby/library/bigdecimal/infinite_spec.rb | 51 ++- spec/ruby/library/bigdecimal/inspect_spec.rb | 45 +- spec/ruby/library/bigdecimal/limit_spec.rb | 89 ++-- spec/ruby/library/bigdecimal/lt_spec.rb | 161 +++---- spec/ruby/library/bigdecimal/lte_spec.rb | 169 +++---- spec/ruby/library/bigdecimal/minus_spec.rb | 109 ++--- spec/ruby/library/bigdecimal/mode_spec.rb | 61 +-- spec/ruby/library/bigdecimal/modulo_spec.rb | 19 +- spec/ruby/library/bigdecimal/mult_spec.rb | 49 +- spec/ruby/library/bigdecimal/multiply_spec.rb | 63 +-- spec/ruby/library/bigdecimal/nan_spec.rb | 37 +- spec/ruby/library/bigdecimal/nonzero_spec.rb | 49 +- spec/ruby/library/bigdecimal/plus_spec.rb | 93 ++-- spec/ruby/library/bigdecimal/power_spec.rb | 9 +- spec/ruby/library/bigdecimal/precs_spec.rb | 79 ++-- spec/ruby/library/bigdecimal/quo_spec.rb | 17 +- .../ruby/library/bigdecimal/remainder_spec.rb | 161 +++---- spec/ruby/library/bigdecimal/round_spec.rb | 423 +++++++++--------- spec/ruby/library/bigdecimal/sign_spec.rb | 85 ++-- spec/ruby/library/bigdecimal/split_spec.rb | 149 +++--- spec/ruby/library/bigdecimal/sqrt_spec.rb | 217 ++++----- spec/ruby/library/bigdecimal/sub_spec.rb | 115 ++--- spec/ruby/library/bigdecimal/to_d_spec.rb | 15 +- spec/ruby/library/bigdecimal/to_f_spec.rb | 103 ++--- spec/ruby/library/bigdecimal/to_i_spec.rb | 11 +- spec/ruby/library/bigdecimal/to_int_spec.rb | 11 +- spec/ruby/library/bigdecimal/to_r_spec.rb | 43 +- spec/ruby/library/bigdecimal/to_s_spec.rb | 159 +++---- spec/ruby/library/bigdecimal/truncate_spec.rb | 135 +++--- spec/ruby/library/bigdecimal/uminus_spec.rb | 101 +++-- spec/ruby/library/bigdecimal/uplus_spec.rb | 29 +- spec/ruby/library/bigdecimal/util_spec.rb | 59 +-- spec/ruby/library/bigdecimal/zero_spec.rb | 45 +- 57 files changed, 2920 insertions(+), 2749 deletions(-) diff --git a/spec/ruby/library/bigdecimal/BigDecimal_spec.rb b/spec/ruby/library/bigdecimal/BigDecimal_spec.rb index 43a779b420ea35..d6e119b36ea137 100644 --- a/spec/ruby/library/bigdecimal/BigDecimal_spec.rb +++ b/spec/ruby/library/bigdecimal/BigDecimal_spec.rb @@ -1,269 +1,272 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal" do - it "is not defined unless it is required" do - ruby_exe('puts Object.const_defined?(:BigDecimal)').should == "false\n" - end -end +ruby_version_is ""..."3.4" do + require 'bigdecimal' -describe "Kernel#BigDecimal" do - - it "creates a new object of class BigDecimal" do - BigDecimal("3.14159").should be_kind_of(BigDecimal) - (0..9).each {|i| - BigDecimal("1#{i}").should == 10 + i - BigDecimal("-1#{i}").should == -10 - i - BigDecimal("1E#{i}").should == 10**i - BigDecimal("1000000E-#{i}").should == 10**(6-i).to_f - # ^ to_f to avoid Rational type - } - (1..9).each {|i| - BigDecimal("100.#{i}").to_s.should =~ /\A0\.100#{i}E3\z/i - BigDecimal("-100.#{i}").to_s.should =~ /\A-0\.100#{i}E3\z/i - } - end - - it "BigDecimal(Rational) with bigger-than-double numerator" do - rational = 99999999999999999999/100r - rational.numerator.should > 2**64 - BigDecimal(rational, 100).to_s.should == "0.99999999999999999999e18" - end - - it "accepts significant digits >= given precision" do - suppress_warning do - BigDecimal("3.1415923", 10).precs[1].should >= 10 + describe "BigDecimal" do + it "is not defined unless it is required" do + ruby_exe('puts Object.const_defined?(:BigDecimal)').should == "false\n" end end - it "determines precision from initial value" do - pi_string = "3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593014782083152134043" - suppress_warning { - BigDecimal(pi_string).precs[1] - }.should >= pi_string.size-1 - end - - it "ignores leading and trailing whitespace" do - BigDecimal(" \t\n \r1234\t\r\n ").should == BigDecimal("1234") - BigDecimal(" \t\n \rNaN \n").should.nan? - BigDecimal(" \t\n \rInfinity \n").infinite?.should == 1 - BigDecimal(" \t\n \r-Infinity \n").infinite?.should == -1 - end - - it "coerces the value argument with #to_str" do - initial = mock("value") - initial.should_receive(:to_str).and_return("123") - BigDecimal(initial).should == BigDecimal("123") - end - - it "does not ignores trailing garbage" do - -> { BigDecimal("123E45ruby") }.should raise_error(ArgumentError) - -> { BigDecimal("123x45") }.should raise_error(ArgumentError) - -> { BigDecimal("123.4%E5") }.should raise_error(ArgumentError) - -> { BigDecimal("1E2E3E4E5E") }.should raise_error(ArgumentError) - end - - it "raises ArgumentError for invalid strings" do - -> { BigDecimal("ruby") }.should raise_error(ArgumentError) - -> { BigDecimal(" \t\n \r-\t\t\tInfinity \n") }.should raise_error(ArgumentError) - end + describe "Kernel#BigDecimal" do + + it "creates a new object of class BigDecimal" do + BigDecimal("3.14159").should be_kind_of(BigDecimal) + (0..9).each {|i| + BigDecimal("1#{i}").should == 10 + i + BigDecimal("-1#{i}").should == -10 - i + BigDecimal("1E#{i}").should == 10**i + BigDecimal("1000000E-#{i}").should == 10**(6-i).to_f + # ^ to_f to avoid Rational type + } + (1..9).each {|i| + BigDecimal("100.#{i}").to_s.should =~ /\A0\.100#{i}E3\z/i + BigDecimal("-100.#{i}").to_s.should =~ /\A-0\.100#{i}E3\z/i + } + end - it "allows omitting the integer part" do - BigDecimal(".123").should == BigDecimal("0.123") - end + it "BigDecimal(Rational) with bigger-than-double numerator" do + rational = 99999999999999999999/100r + rational.numerator.should > 2**64 + BigDecimal(rational, 100).to_s.should == "0.99999999999999999999e18" + end - it "process underscores as Float()" do - reference = BigDecimal("12345.67E89") + it "accepts significant digits >= given precision" do + suppress_warning do + BigDecimal("3.1415923", 10).precs[1].should >= 10 + end + end - BigDecimal("12_345.67E89").should == reference - -> { BigDecimal("1_2_3_4_5_._6____7_E89") }.should raise_error(ArgumentError) - -> { BigDecimal("12345_.67E_8__9_") }.should raise_error(ArgumentError) - end + it "determines precision from initial value" do + pi_string = "3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593014782083152134043" + suppress_warning { + BigDecimal(pi_string).precs[1] + }.should >= pi_string.size-1 + end - it "accepts NaN and [+-]Infinity" do - BigDecimal("NaN").should.nan? + it "ignores leading and trailing whitespace" do + BigDecimal(" \t\n \r1234\t\r\n ").should == BigDecimal("1234") + BigDecimal(" \t\n \rNaN \n").should.nan? + BigDecimal(" \t\n \rInfinity \n").infinite?.should == 1 + BigDecimal(" \t\n \r-Infinity \n").infinite?.should == -1 + end - pos_inf = BigDecimal("Infinity") - pos_inf.should_not.finite? - pos_inf.should > 0 - pos_inf.should == BigDecimal("+Infinity") + it "coerces the value argument with #to_str" do + initial = mock("value") + initial.should_receive(:to_str).and_return("123") + BigDecimal(initial).should == BigDecimal("123") + end - neg_inf = BigDecimal("-Infinity") - neg_inf.should_not.finite? - neg_inf.should < 0 - end + it "does not ignores trailing garbage" do + -> { BigDecimal("123E45ruby") }.should raise_error(ArgumentError) + -> { BigDecimal("123x45") }.should raise_error(ArgumentError) + -> { BigDecimal("123.4%E5") }.should raise_error(ArgumentError) + -> { BigDecimal("1E2E3E4E5E") }.should raise_error(ArgumentError) + end - describe "with exception: false" do - it "returns nil for invalid strings" do - BigDecimal("invalid", exception: false).should be_nil - BigDecimal("0invalid", exception: false).should be_nil - BigDecimal("invalid0", exception: false).should be_nil - BigDecimal("0.", exception: false).should be_nil + it "raises ArgumentError for invalid strings" do + -> { BigDecimal("ruby") }.should raise_error(ArgumentError) + -> { BigDecimal(" \t\n \r-\t\t\tInfinity \n") }.should raise_error(ArgumentError) end - end - describe "accepts NaN and [+-]Infinity as Float values" do - it "works without an explicit precision" do - BigDecimal(Float::NAN).should.nan? + it "allows omitting the integer part" do + BigDecimal(".123").should == BigDecimal("0.123") + end - pos_inf = BigDecimal(Float::INFINITY) - pos_inf.should_not.finite? - pos_inf.should > 0 - pos_inf.should == BigDecimal("+Infinity") + it "process underscores as Float()" do + reference = BigDecimal("12345.67E89") - neg_inf = BigDecimal(-Float::INFINITY) - neg_inf.should_not.finite? - neg_inf.should < 0 + BigDecimal("12_345.67E89").should == reference + -> { BigDecimal("1_2_3_4_5_._6____7_E89") }.should raise_error(ArgumentError) + -> { BigDecimal("12345_.67E_8__9_") }.should raise_error(ArgumentError) end - it "works with an explicit precision" do - BigDecimal(Float::NAN, Float::DIG).should.nan? + it "accepts NaN and [+-]Infinity" do + BigDecimal("NaN").should.nan? - pos_inf = BigDecimal(Float::INFINITY, Float::DIG) + pos_inf = BigDecimal("Infinity") pos_inf.should_not.finite? pos_inf.should > 0 pos_inf.should == BigDecimal("+Infinity") - neg_inf = BigDecimal(-Float::INFINITY, Float::DIG) + neg_inf = BigDecimal("-Infinity") neg_inf.should_not.finite? neg_inf.should < 0 end - end - it "allows for [eEdD] as exponent separator" do - reference = BigDecimal("12345.67E89") - - BigDecimal("12345.67e89").should == reference - BigDecimal("12345.67E89").should == reference - BigDecimal("12345.67d89").should == reference - BigDecimal("12345.67D89").should == reference - end + describe "with exception: false" do + it "returns nil for invalid strings" do + BigDecimal("invalid", exception: false).should be_nil + BigDecimal("0invalid", exception: false).should be_nil + BigDecimal("invalid0", exception: false).should be_nil + BigDecimal("0.", exception: false).should be_nil + end + end - it "allows for varying signs" do - reference = BigDecimal("123.456E1") - - BigDecimal("+123.456E1").should == reference - BigDecimal("-123.456E1").should == -reference - BigDecimal("123.456E+1").should == reference - BigDecimal("12345.6E-1").should == reference - BigDecimal("+123.456E+1").should == reference - BigDecimal("+12345.6E-1").should == reference - BigDecimal("-123.456E+1").should == -reference - BigDecimal("-12345.6E-1").should == -reference - end + describe "accepts NaN and [+-]Infinity as Float values" do + it "works without an explicit precision" do + BigDecimal(Float::NAN).should.nan? - it "raises ArgumentError when Float is used without precision" do - -> { BigDecimal(1.0) }.should raise_error(ArgumentError) - end + pos_inf = BigDecimal(Float::INFINITY) + pos_inf.should_not.finite? + pos_inf.should > 0 + pos_inf.should == BigDecimal("+Infinity") - it "returns appropriate BigDecimal zero for signed zero" do - BigDecimal(-0.0, Float::DIG).sign.should == -1 - BigDecimal(0.0, Float::DIG).sign.should == 1 - end + neg_inf = BigDecimal(-Float::INFINITY) + neg_inf.should_not.finite? + neg_inf.should < 0 + end - it "pre-coerces long integers" do - BigDecimal(3).add(1 << 50, 3).should == BigDecimal('0.113e16') - end + it "works with an explicit precision" do + BigDecimal(Float::NAN, Float::DIG).should.nan? - it "does not call to_s when calling inspect" do - value = BigDecimal('44.44') - value.to_s.should == '0.4444e2' - value.inspect.should == '0.4444e2' + pos_inf = BigDecimal(Float::INFINITY, Float::DIG) + pos_inf.should_not.finite? + pos_inf.should > 0 + pos_inf.should == BigDecimal("+Infinity") - ruby_exe( <<-'EOF').should == "cheese 0.4444e2" - require 'bigdecimal' - module BigDecimalOverride - def to_s; "cheese"; end + neg_inf = BigDecimal(-Float::INFINITY, Float::DIG) + neg_inf.should_not.finite? + neg_inf.should < 0 end - BigDecimal.prepend BigDecimalOverride - value = BigDecimal('44.44') - print "#{value.to_s} #{value.inspect}" - EOF - end - - describe "when interacting with Rational" do - before :each do - @a = BigDecimal('166.666666666') - @b = Rational(500, 3) - @c = @a - @b end - # Check the input is as we understand it + it "allows for [eEdD] as exponent separator" do + reference = BigDecimal("12345.67E89") - it "has the LHS print as expected" do - @a.to_s.should == "0.166666666666e3" - @a.to_f.to_s.should == "166.666666666" - Float(@a).to_s.should == "166.666666666" + BigDecimal("12345.67e89").should == reference + BigDecimal("12345.67E89").should == reference + BigDecimal("12345.67d89").should == reference + BigDecimal("12345.67D89").should == reference end - it "has the RHS print as expected" do - @b.to_s.should == "500/3" - @b.to_f.to_s.should == "166.66666666666666" - Float(@b).to_s.should == "166.66666666666666" + it "allows for varying signs" do + reference = BigDecimal("123.456E1") + + BigDecimal("+123.456E1").should == reference + BigDecimal("-123.456E1").should == -reference + BigDecimal("123.456E+1").should == reference + BigDecimal("12345.6E-1").should == reference + BigDecimal("+123.456E+1").should == reference + BigDecimal("+12345.6E-1").should == reference + BigDecimal("-123.456E+1").should == -reference + BigDecimal("-12345.6E-1").should == -reference end - it "has the expected precision on the LHS" do - suppress_warning { @a.precs[0] }.should == 18 + it "raises ArgumentError when Float is used without precision" do + -> { BigDecimal(1.0) }.should raise_error(ArgumentError) end - it "has the expected maximum precision on the LHS" do - suppress_warning { @a.precs[1] }.should == 27 + it "returns appropriate BigDecimal zero for signed zero" do + BigDecimal(-0.0, Float::DIG).sign.should == -1 + BigDecimal(0.0, Float::DIG).sign.should == 1 end - it "produces the expected result when done via Float" do - (Float(@a) - Float(@b)).to_s.should == "-6.666596163995564e-10" + it "pre-coerces long integers" do + BigDecimal(3).add(1 << 50, 3).should == BigDecimal('0.113e16') end - it "produces the expected result when done via to_f" do - (@a.to_f - @b.to_f).to_s.should == "-6.666596163995564e-10" + it "does not call to_s when calling inspect" do + value = BigDecimal('44.44') + value.to_s.should == '0.4444e2' + value.inspect.should == '0.4444e2' + + ruby_exe( <<-'EOF').should == "cheese 0.4444e2" + require 'bigdecimal' + module BigDecimalOverride + def to_s; "cheese"; end + end + BigDecimal.prepend BigDecimalOverride + value = BigDecimal('44.44') + print "#{value.to_s} #{value.inspect}" + EOF end - # Check underlying methods work as we understand + describe "when interacting with Rational" do + before :each do + @a = BigDecimal('166.666666666') + @b = Rational(500, 3) + @c = @a - @b + end - it "BigDecimal precision is the number of digits rounded up to a multiple of nine" do - 1.upto(100) do |n| - b = BigDecimal('4' * n) - precs, _ = suppress_warning { b.precs } - (precs >= 9).should be_true - (precs >= n).should be_true - (precs % 9).should == 0 + # Check the input is as we understand it + + it "has the LHS print as expected" do + @a.to_s.should == "0.166666666666e3" + @a.to_f.to_s.should == "166.666666666" + Float(@a).to_s.should == "166.666666666" end - suppress_warning { BigDecimal('NaN').precs[0] }.should == 9 - end - it "BigDecimal maximum precision is nine more than precision except for abnormals" do - 1.upto(100) do |n| - b = BigDecimal('4' * n) - precs, max = suppress_warning { b.precs } - max.should == precs + 9 + it "has the RHS print as expected" do + @b.to_s.should == "500/3" + @b.to_f.to_s.should == "166.66666666666666" + Float(@b).to_s.should == "166.66666666666666" end - suppress_warning { BigDecimal('NaN').precs[1] }.should == 9 - end - it "BigDecimal(Rational, 18) produces the result we expect" do - BigDecimal(@b, 18).to_s.should == "0.166666666666666667e3" - end + it "has the expected precision on the LHS" do + suppress_warning { @a.precs[0] }.should == 18 + end - it "BigDecimal(Rational, BigDecimal.precs[0]) produces the result we expect" do - BigDecimal(@b, suppress_warning { @a.precs[0] }).to_s.should == "0.166666666666666667e3" - end + it "has the expected maximum precision on the LHS" do + suppress_warning { @a.precs[1] }.should == 27 + end - # Check the top-level expression works as we expect + it "produces the expected result when done via Float" do + (Float(@a) - Float(@b)).to_s.should == "-6.666596163995564e-10" + end - it "produces a BigDecimal" do - @c.class.should == BigDecimal - end + it "produces the expected result when done via to_f" do + (@a.to_f - @b.to_f).to_s.should == "-6.666596163995564e-10" + end - it "produces the expected result" do - @c.should == BigDecimal("-0.666667e-9") - @c.to_s.should == "-0.666667e-9" - end + # Check underlying methods work as we understand + + it "BigDecimal precision is the number of digits rounded up to a multiple of nine" do + 1.upto(100) do |n| + b = BigDecimal('4' * n) + precs, _ = suppress_warning { b.precs } + (precs >= 9).should be_true + (precs >= n).should be_true + (precs % 9).should == 0 + end + suppress_warning { BigDecimal('NaN').precs[0] }.should == 9 + end + + it "BigDecimal maximum precision is nine more than precision except for abnormals" do + 1.upto(100) do |n| + b = BigDecimal('4' * n) + precs, max = suppress_warning { b.precs } + max.should == precs + 9 + end + suppress_warning { BigDecimal('NaN').precs[1] }.should == 9 + end + + it "BigDecimal(Rational, 18) produces the result we expect" do + BigDecimal(@b, 18).to_s.should == "0.166666666666666667e3" + end + + it "BigDecimal(Rational, BigDecimal.precs[0]) produces the result we expect" do + BigDecimal(@b, suppress_warning { @a.precs[0] }).to_s.should == "0.166666666666666667e3" + end - it "produces the correct class for other arithmetic operators" do - (@a + @b).class.should == BigDecimal - (@a * @b).class.should == BigDecimal - (@a / @b).class.should == BigDecimal - (@a % @b).class.should == BigDecimal + # Check the top-level expression works as we expect + + it "produces a BigDecimal" do + @c.class.should == BigDecimal + end + + it "produces the expected result" do + @c.should == BigDecimal("-0.666667e-9") + @c.to_s.should == "-0.666667e-9" + end + + it "produces the correct class for other arithmetic operators" do + (@a + @b).class.should == BigDecimal + (@a * @b).class.should == BigDecimal + (@a / @b).class.should == BigDecimal + (@a % @b).class.should == BigDecimal + end end end end diff --git a/spec/ruby/library/bigdecimal/abs_spec.rb b/spec/ruby/library/bigdecimal/abs_spec.rb index 95dc45a90589e0..44ac0db77b956f 100644 --- a/spec/ruby/library/bigdecimal/abs_spec.rb +++ b/spec/ruby/library/bigdecimal/abs_spec.rb @@ -1,50 +1,53 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal#abs" do - before :each do - @one = BigDecimal("1") - @zero = BigDecimal("0") - @zero_pos = BigDecimal("+0") - @zero_neg = BigDecimal("-0") - @two = BigDecimal("2") - @three = BigDecimal("3") - @mixed = BigDecimal("1.23456789") - @nan = BigDecimal("NaN") - @infinity = BigDecimal("Infinity") - @infinity_minus = BigDecimal("-Infinity") - @one_minus = BigDecimal("-1") - @frac_1 = BigDecimal("1E-99999") - @frac_2 = BigDecimal("0.9E-99999") - end +ruby_version_is ""..."3.4" do + require 'bigdecimal' - it "returns the absolute value" do - pos_int = BigDecimal("2E5555") - neg_int = BigDecimal("-2E5555") - pos_frac = BigDecimal("2E-9999") - neg_frac = BigDecimal("-2E-9999") + describe "BigDecimal#abs" do + before :each do + @one = BigDecimal("1") + @zero = BigDecimal("0") + @zero_pos = BigDecimal("+0") + @zero_neg = BigDecimal("-0") + @two = BigDecimal("2") + @three = BigDecimal("3") + @mixed = BigDecimal("1.23456789") + @nan = BigDecimal("NaN") + @infinity = BigDecimal("Infinity") + @infinity_minus = BigDecimal("-Infinity") + @one_minus = BigDecimal("-1") + @frac_1 = BigDecimal("1E-99999") + @frac_2 = BigDecimal("0.9E-99999") + end - pos_int.abs.should == pos_int - neg_int.abs.should == pos_int - pos_frac.abs.should == pos_frac - neg_frac.abs.should == pos_frac - @one.abs.should == 1 - @two.abs.should == 2 - @three.abs.should == 3 - @mixed.abs.should == @mixed - @one_minus.abs.should == @one - end + it "returns the absolute value" do + pos_int = BigDecimal("2E5555") + neg_int = BigDecimal("-2E5555") + pos_frac = BigDecimal("2E-9999") + neg_frac = BigDecimal("-2E-9999") - it "properly handles special values" do - @infinity.abs.should == @infinity - @infinity_minus.abs.should == @infinity - @nan.abs.should.nan? # have to do it this way, since == doesn't work on NaN - @zero.abs.should == 0 - @zero.abs.sign.should == BigDecimal::SIGN_POSITIVE_ZERO - @zero_pos.abs.should == 0 - @zero_pos.abs.sign.should == BigDecimal::SIGN_POSITIVE_ZERO - @zero_neg.abs.should == 0 - @zero_neg.abs.sign.should == BigDecimal::SIGN_POSITIVE_ZERO - end + pos_int.abs.should == pos_int + neg_int.abs.should == pos_int + pos_frac.abs.should == pos_frac + neg_frac.abs.should == pos_frac + @one.abs.should == 1 + @two.abs.should == 2 + @three.abs.should == 3 + @mixed.abs.should == @mixed + @one_minus.abs.should == @one + end + it "properly handles special values" do + @infinity.abs.should == @infinity + @infinity_minus.abs.should == @infinity + @nan.abs.should.nan? # have to do it this way, since == doesn't work on NaN + @zero.abs.should == 0 + @zero.abs.sign.should == BigDecimal::SIGN_POSITIVE_ZERO + @zero_pos.abs.should == 0 + @zero_pos.abs.sign.should == BigDecimal::SIGN_POSITIVE_ZERO + @zero_neg.abs.should == 0 + @zero_neg.abs.sign.should == BigDecimal::SIGN_POSITIVE_ZERO + end + + end end diff --git a/spec/ruby/library/bigdecimal/add_spec.rb b/spec/ruby/library/bigdecimal/add_spec.rb index 542713011d6a93..9fea1a021246a8 100644 --- a/spec/ruby/library/bigdecimal/add_spec.rb +++ b/spec/ruby/library/bigdecimal/add_spec.rb @@ -1,193 +1,196 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' - -require 'bigdecimal' - -describe "BigDecimal#add" do - - before :each do - @one = BigDecimal("1") - @zero = BigDecimal("0") - @two = BigDecimal("2") - @three = BigDecimal("3") - @ten = BigDecimal("10") - @eleven = BigDecimal("11") - @nan = BigDecimal("NaN") - @infinity = BigDecimal("Infinity") - @infinity_minus = BigDecimal("-Infinity") - @one_minus = BigDecimal("-1") - @frac_1 = BigDecimal("1E-99999") - @frac_2 = BigDecimal("0.9E-99999") - @frac_3 = BigDecimal("12345E10") - @frac_4 = BigDecimal("98765E10") - @dot_ones = BigDecimal("0.1111111111") - end - - it "returns a + b with given precision" do - # documentation states that precision is optional, but it ain't, - @two.add(@one, 1).should == @three - @one .add(@two, 1).should == @three - @one.add(@one_minus, 1).should == @zero - @ten.add(@one, 2).should == @eleven - @zero.add(@one, 1).should == @one - @frac_2.add(@frac_1, 10000).should == BigDecimal("1.9E-99999") - @frac_1.add(@frac_1, 10000).should == BigDecimal("2E-99999") - @frac_3.add(@frac_4, 0).should == BigDecimal("0.11111E16") - @frac_3.add(@frac_4, 1).should == BigDecimal("0.1E16") - @frac_3.add(@frac_4, 2).should == BigDecimal("0.11E16") - @frac_3.add(@frac_4, 3).should == BigDecimal("0.111E16") - @frac_3.add(@frac_4, 4).should == BigDecimal("0.1111E16") - @frac_3.add(@frac_4, 5).should == BigDecimal("0.11111E16") - @frac_3.add(@frac_4, 6).should == BigDecimal("0.11111E16") - end - - it "returns a + [Fixnum value] with given precision" do - (1..10).each {|precision| - @dot_ones.add(0, precision).should == BigDecimal("0." + "1" * precision) - } - BigDecimal("0.88").add(0, 1).should == BigDecimal("0.9") - end - it "returns a + [Bignum value] with given precision" do - bignum = 10000000000000000000 - (1..20).each {|precision| - @dot_ones.add(bignum, precision).should == BigDecimal("0.1E20") - } - (21..30).each {|precision| - @dot_ones.add(bignum, precision).should == BigDecimal( - "0.10000000000000000000" + "1" * (precision - 20) + "E20") - } - end - -# TODO: -# https://blade.ruby-lang.org/ruby-core/17374 -# -# This doesn't work on MRI and looks like a bug to me: -# one can use BigDecimal + Float, but not Bigdecimal.add(Float) -# -# it "returns a + [Float value] with given precision" do -# (1..10).each {|precision| -# @dot_ones.add(0.0, precision).should == BigDecimal("0." + "1" * precision) -# } -# -# BigDecimal("0.88").add(0.0, 1).should == BigDecimal("0.9") -# end - - describe "with Object" do - it "tries to coerce the other operand to self" do - object = mock("Object") - object.should_receive(:coerce).with(@frac_3).and_return([@frac_3, @frac_4]) - @frac_3.add(object, 1).should == BigDecimal("0.1E16") +ruby_version_is ""..."3.4" do + require_relative 'fixtures/classes' + + require 'bigdecimal' + + describe "BigDecimal#add" do + + before :each do + @one = BigDecimal("1") + @zero = BigDecimal("0") + @two = BigDecimal("2") + @three = BigDecimal("3") + @ten = BigDecimal("10") + @eleven = BigDecimal("11") + @nan = BigDecimal("NaN") + @infinity = BigDecimal("Infinity") + @infinity_minus = BigDecimal("-Infinity") + @one_minus = BigDecimal("-1") + @frac_1 = BigDecimal("1E-99999") + @frac_2 = BigDecimal("0.9E-99999") + @frac_3 = BigDecimal("12345E10") + @frac_4 = BigDecimal("98765E10") + @dot_ones = BigDecimal("0.1111111111") end - end - describe "with Rational" do - it "produces a BigDecimal" do - (@three + Rational(500, 2)).should == BigDecimal("0.253e3") + it "returns a + b with given precision" do + # documentation states that precision is optional, but it ain't, + @two.add(@one, 1).should == @three + @one .add(@two, 1).should == @three + @one.add(@one_minus, 1).should == @zero + @ten.add(@one, 2).should == @eleven + @zero.add(@one, 1).should == @one + @frac_2.add(@frac_1, 10000).should == BigDecimal("1.9E-99999") + @frac_1.add(@frac_1, 10000).should == BigDecimal("2E-99999") + @frac_3.add(@frac_4, 0).should == BigDecimal("0.11111E16") + @frac_3.add(@frac_4, 1).should == BigDecimal("0.1E16") + @frac_3.add(@frac_4, 2).should == BigDecimal("0.11E16") + @frac_3.add(@frac_4, 3).should == BigDecimal("0.111E16") + @frac_3.add(@frac_4, 4).should == BigDecimal("0.1111E16") + @frac_3.add(@frac_4, 5).should == BigDecimal("0.11111E16") + @frac_3.add(@frac_4, 6).should == BigDecimal("0.11111E16") end - end - it "favors the precision specified in the second argument over the global limit" do - BigDecimalSpecs.with_limit(1) do - BigDecimal('0.888').add(@zero, 3).should == BigDecimal('0.888') + it "returns a + [Fixnum value] with given precision" do + (1..10).each {|precision| + @dot_ones.add(0, precision).should == BigDecimal("0." + "1" * precision) + } + BigDecimal("0.88").add(0, 1).should == BigDecimal("0.9") end - BigDecimalSpecs.with_limit(2) do - BigDecimal('0.888').add(@zero, 1).should == BigDecimal('0.9') + it "returns a + [Bignum value] with given precision" do + bignum = 10000000000000000000 + (1..20).each {|precision| + @dot_ones.add(bignum, precision).should == BigDecimal("0.1E20") + } + (21..30).each {|precision| + @dot_ones.add(bignum, precision).should == BigDecimal( + "0.10000000000000000000" + "1" * (precision - 20) + "E20") + } end - end - it "uses the current rounding mode if rounding is needed" do - BigDecimalSpecs.with_rounding(BigDecimal::ROUND_UP) do - BigDecimal('0.111').add(@zero, 1).should == BigDecimal('0.2') - BigDecimal('-0.111').add(@zero, 1).should == BigDecimal('-0.2') - end - BigDecimalSpecs.with_rounding(BigDecimal::ROUND_DOWN) do - BigDecimal('0.999').add(@zero, 1).should == BigDecimal('0.9') - BigDecimal('-0.999').add(@zero, 1).should == BigDecimal('-0.9') + # TODO: + # https://blade.ruby-lang.org/ruby-core/17374 + # + # This doesn't work on MRI and looks like a bug to me: + # one can use BigDecimal + Float, but not Bigdecimal.add(Float) + # + # it "returns a + [Float value] with given precision" do + # (1..10).each {|precision| + # @dot_ones.add(0.0, precision).should == BigDecimal("0." + "1" * precision) + # } + # + # BigDecimal("0.88").add(0.0, 1).should == BigDecimal("0.9") + # end + + describe "with Object" do + it "tries to coerce the other operand to self" do + object = mock("Object") + object.should_receive(:coerce).with(@frac_3).and_return([@frac_3, @frac_4]) + @frac_3.add(object, 1).should == BigDecimal("0.1E16") + end end - BigDecimalSpecs.with_rounding(BigDecimal::ROUND_HALF_UP) do - BigDecimal('0.85').add(@zero, 1).should == BigDecimal('0.9') - BigDecimal('-0.85').add(@zero, 1).should == BigDecimal('-0.9') + + describe "with Rational" do + it "produces a BigDecimal" do + (@three + Rational(500, 2)).should == BigDecimal("0.253e3") + end end - BigDecimalSpecs.with_rounding(BigDecimal::ROUND_HALF_DOWN) do - BigDecimal('0.85').add(@zero, 1).should == BigDecimal('0.8') - BigDecimal('-0.85').add(@zero, 1).should == BigDecimal('-0.8') + + it "favors the precision specified in the second argument over the global limit" do + BigDecimalSpecs.with_limit(1) do + BigDecimal('0.888').add(@zero, 3).should == BigDecimal('0.888') + end + + BigDecimalSpecs.with_limit(2) do + BigDecimal('0.888').add(@zero, 1).should == BigDecimal('0.9') + end end - BigDecimalSpecs.with_rounding(BigDecimal::ROUND_HALF_EVEN) do - BigDecimal('0.75').add(@zero, 1).should == BigDecimal('0.8') - BigDecimal('0.85').add(@zero, 1).should == BigDecimal('0.8') - BigDecimal('-0.75').add(@zero, 1).should == BigDecimal('-0.8') - BigDecimal('-0.85').add(@zero, 1).should == BigDecimal('-0.8') + + it "uses the current rounding mode if rounding is needed" do + BigDecimalSpecs.with_rounding(BigDecimal::ROUND_UP) do + BigDecimal('0.111').add(@zero, 1).should == BigDecimal('0.2') + BigDecimal('-0.111').add(@zero, 1).should == BigDecimal('-0.2') + end + BigDecimalSpecs.with_rounding(BigDecimal::ROUND_DOWN) do + BigDecimal('0.999').add(@zero, 1).should == BigDecimal('0.9') + BigDecimal('-0.999').add(@zero, 1).should == BigDecimal('-0.9') + end + BigDecimalSpecs.with_rounding(BigDecimal::ROUND_HALF_UP) do + BigDecimal('0.85').add(@zero, 1).should == BigDecimal('0.9') + BigDecimal('-0.85').add(@zero, 1).should == BigDecimal('-0.9') + end + BigDecimalSpecs.with_rounding(BigDecimal::ROUND_HALF_DOWN) do + BigDecimal('0.85').add(@zero, 1).should == BigDecimal('0.8') + BigDecimal('-0.85').add(@zero, 1).should == BigDecimal('-0.8') + end + BigDecimalSpecs.with_rounding(BigDecimal::ROUND_HALF_EVEN) do + BigDecimal('0.75').add(@zero, 1).should == BigDecimal('0.8') + BigDecimal('0.85').add(@zero, 1).should == BigDecimal('0.8') + BigDecimal('-0.75').add(@zero, 1).should == BigDecimal('-0.8') + BigDecimal('-0.85').add(@zero, 1).should == BigDecimal('-0.8') + end + BigDecimalSpecs.with_rounding(BigDecimal::ROUND_CEILING) do + BigDecimal('0.85').add(@zero, 1).should == BigDecimal('0.9') + BigDecimal('-0.85').add(@zero, 1).should == BigDecimal('-0.8') + end + BigDecimalSpecs.with_rounding(BigDecimal::ROUND_FLOOR) do + BigDecimal('0.85').add(@zero, 1).should == BigDecimal('0.8') + BigDecimal('-0.85').add(@zero, 1).should == BigDecimal('-0.9') + end end - BigDecimalSpecs.with_rounding(BigDecimal::ROUND_CEILING) do + + it "uses the default ROUND_HALF_UP rounding if it wasn't explicitly changed" do BigDecimal('0.85').add(@zero, 1).should == BigDecimal('0.9') - BigDecimal('-0.85').add(@zero, 1).should == BigDecimal('-0.8') - end - BigDecimalSpecs.with_rounding(BigDecimal::ROUND_FLOOR) do - BigDecimal('0.85').add(@zero, 1).should == BigDecimal('0.8') BigDecimal('-0.85').add(@zero, 1).should == BigDecimal('-0.9') end - end - - it "uses the default ROUND_HALF_UP rounding if it wasn't explicitly changed" do - BigDecimal('0.85').add(@zero, 1).should == BigDecimal('0.9') - BigDecimal('-0.85').add(@zero, 1).should == BigDecimal('-0.9') - end - it "returns NaN if NaN is involved" do - @one.add(@nan, 10000).should.nan? - @nan.add(@one, 1).should.nan? - end + it "returns NaN if NaN is involved" do + @one.add(@nan, 10000).should.nan? + @nan.add(@one, 1).should.nan? + end - it "returns Infinity or -Infinity if these are involved" do - @zero.add(@infinity, 1).should == @infinity - @frac_2.add(@infinity, 1).should == @infinity - @one_minus.add(@infinity, 1).should == @infinity - @two.add(@infinity, 1).should == @infinity - - @zero.add(@infinity_minus, 1).should == @infinity_minus - @frac_2.add(@infinity_minus, 1).should == @infinity_minus - @one_minus.add(@infinity_minus, 1).should == @infinity_minus - @two.add(@infinity_minus, 1).should == @infinity_minus - - @infinity.add(@zero, 1).should == @infinity - @infinity.add(@frac_2, 1).should == @infinity - @infinity.add(@one_minus, 1).should == @infinity - @infinity.add(@two, 1).should == @infinity - - @infinity_minus.add(@zero, 1).should == @infinity_minus - @infinity_minus.add(@frac_2, 1).should == @infinity_minus - @infinity_minus.add(@one_minus, 1).should == @infinity_minus - @infinity_minus.add(@two, 1).should == @infinity_minus - - @infinity.add(@infinity, 10000).should == @infinity - @infinity_minus.add(@infinity_minus, 10000).should == @infinity_minus - end + it "returns Infinity or -Infinity if these are involved" do + @zero.add(@infinity, 1).should == @infinity + @frac_2.add(@infinity, 1).should == @infinity + @one_minus.add(@infinity, 1).should == @infinity + @two.add(@infinity, 1).should == @infinity + + @zero.add(@infinity_minus, 1).should == @infinity_minus + @frac_2.add(@infinity_minus, 1).should == @infinity_minus + @one_minus.add(@infinity_minus, 1).should == @infinity_minus + @two.add(@infinity_minus, 1).should == @infinity_minus + + @infinity.add(@zero, 1).should == @infinity + @infinity.add(@frac_2, 1).should == @infinity + @infinity.add(@one_minus, 1).should == @infinity + @infinity.add(@two, 1).should == @infinity + + @infinity_minus.add(@zero, 1).should == @infinity_minus + @infinity_minus.add(@frac_2, 1).should == @infinity_minus + @infinity_minus.add(@one_minus, 1).should == @infinity_minus + @infinity_minus.add(@two, 1).should == @infinity_minus + + @infinity.add(@infinity, 10000).should == @infinity + @infinity_minus.add(@infinity_minus, 10000).should == @infinity_minus + end - it "returns NaN if Infinity + (- Infinity)" do - @infinity.add(@infinity_minus, 10000).should.nan? - @infinity_minus.add(@infinity, 10000).should.nan? - end + it "returns NaN if Infinity + (- Infinity)" do + @infinity.add(@infinity_minus, 10000).should.nan? + @infinity_minus.add(@infinity, 10000).should.nan? + end - it "raises TypeError when adds nil" do - -> { - @one.add(nil, 10) - }.should raise_error(TypeError) - -> { - @one.add(nil, 0) - }.should raise_error(TypeError) - end + it "raises TypeError when adds nil" do + -> { + @one.add(nil, 10) + }.should raise_error(TypeError) + -> { + @one.add(nil, 0) + }.should raise_error(TypeError) + end - it "raises TypeError when precision parameter is nil" do - -> { - @one.add(@one, nil) - }.should raise_error(TypeError) - end + it "raises TypeError when precision parameter is nil" do + -> { + @one.add(@one, nil) + }.should raise_error(TypeError) + end - it "raises ArgumentError when precision parameter is negative" do - -> { - @one.add(@one, -10) - }.should raise_error(ArgumentError) + it "raises ArgumentError when precision parameter is negative" do + -> { + @one.add(@one, -10) + }.should raise_error(ArgumentError) + end end end diff --git a/spec/ruby/library/bigdecimal/case_compare_spec.rb b/spec/ruby/library/bigdecimal/case_compare_spec.rb index fac67143561980..7803346c791185 100644 --- a/spec/ruby/library/bigdecimal/case_compare_spec.rb +++ b/spec/ruby/library/bigdecimal/case_compare_spec.rb @@ -1,7 +1,10 @@ require_relative '../../spec_helper' -require_relative 'shared/eql' +ruby_version_is ""..."3.4" do + require_relative 'shared/eql' -describe "BigDecimal#===" do - it_behaves_like :bigdecimal_eql, :=== + + describe "BigDecimal#===" do + it_behaves_like :bigdecimal_eql, :=== + end end diff --git a/spec/ruby/library/bigdecimal/ceil_spec.rb b/spec/ruby/library/bigdecimal/ceil_spec.rb index 60e71b12fb1528..a3b6806be50ad6 100644 --- a/spec/ruby/library/bigdecimal/ceil_spec.rb +++ b/spec/ruby/library/bigdecimal/ceil_spec.rb @@ -1,104 +1,107 @@ require_relative '../../spec_helper' -require 'bigdecimal' - -describe "BigDecimal#ceil" do - before :each do - @zero = BigDecimal("0") - @one = BigDecimal("1") - @three = BigDecimal("3") - @four = BigDecimal("4") - @mixed = BigDecimal("1.23456789") - @mixed_big = BigDecimal("1.23456789E100") - @pos_int = BigDecimal("2E5555") - @neg_int = BigDecimal("-2E5555") - @pos_frac = BigDecimal("2E-9999") - @neg_frac = BigDecimal("-2E-9999") - - @infinity = BigDecimal("Infinity") - @infinity_neg = BigDecimal("-Infinity") - @nan = BigDecimal("NaN") - @zero_pos = BigDecimal("+0") - @zero_neg = BigDecimal("-0") - end - - it "returns an Integer, if n is unspecified" do - @mixed.ceil.kind_of?(Integer).should == true - end - - it "returns a BigDecimal, if n is specified" do - @pos_int.ceil(2).kind_of?(BigDecimal).should == true - end - - it "returns the smallest integer greater or equal to self, if n is unspecified" do - @pos_int.ceil.should == @pos_int - @neg_int.ceil.should == @neg_int - @pos_frac.ceil.should == BigDecimal("1") - @neg_frac.ceil.should == @zero - @zero.ceil.should == 0 - @zero_pos.ceil.should == @zero_pos - @zero_neg.ceil.should == @zero_neg - - - BigDecimal('2.3').ceil.should == 3 - BigDecimal('2.5').ceil.should == 3 - BigDecimal('2.9999').ceil.should == 3 - BigDecimal('-2.3').ceil.should == -2 - BigDecimal('-2.5').ceil.should == -2 - BigDecimal('-2.9999').ceil.should == -2 - end - - it "raise exception, if self is special value" do - -> { @infinity.ceil }.should raise_error(FloatDomainError) - -> { @infinity_neg.ceil }.should raise_error(FloatDomainError) - -> { @nan.ceil }.should raise_error(FloatDomainError) - end - - it "returns n digits right of the decimal point if given n > 0" do - @mixed.ceil(1).should == BigDecimal("1.3") - @mixed.ceil(5).should == BigDecimal("1.23457") - BigDecimal("-0.03").ceil(1).should == BigDecimal("0") - BigDecimal("0.03").ceil(1).should == BigDecimal("0.1") - - BigDecimal("23.45").ceil(0).should == BigDecimal('24') - BigDecimal("23.45").ceil(1).should == BigDecimal('23.5') - BigDecimal("23.45").ceil(2).should == BigDecimal('23.45') +ruby_version_is ""..."3.4" do + require 'bigdecimal' + + describe "BigDecimal#ceil" do + before :each do + @zero = BigDecimal("0") + @one = BigDecimal("1") + @three = BigDecimal("3") + @four = BigDecimal("4") + @mixed = BigDecimal("1.23456789") + @mixed_big = BigDecimal("1.23456789E100") + @pos_int = BigDecimal("2E5555") + @neg_int = BigDecimal("-2E5555") + @pos_frac = BigDecimal("2E-9999") + @neg_frac = BigDecimal("-2E-9999") + + @infinity = BigDecimal("Infinity") + @infinity_neg = BigDecimal("-Infinity") + @nan = BigDecimal("NaN") + @zero_pos = BigDecimal("+0") + @zero_neg = BigDecimal("-0") + end - BigDecimal("-23.45").ceil(0).should == BigDecimal('-23') - BigDecimal("-23.45").ceil(1).should == BigDecimal('-23.4') - BigDecimal("-23.45").ceil(2).should == BigDecimal('-23.45') + it "returns an Integer, if n is unspecified" do + @mixed.ceil.kind_of?(Integer).should == true + end - BigDecimal("2E-10").ceil(0).should == @one - BigDecimal("2E-10").ceil(9).should == BigDecimal('1E-9') - BigDecimal("2E-10").ceil(10).should == BigDecimal('2E-10') - BigDecimal("2E-10").ceil(11).should == BigDecimal('2E-10') + it "returns a BigDecimal, if n is specified" do + @pos_int.ceil(2).kind_of?(BigDecimal).should == true + end - (1..10).each do |n| - # 0.4, 0.34, 0.334, etc. - (@one.div(@three,20)).ceil(n).should == BigDecimal("0.#{'3'*(n-1)}4") - # 1.4, 1.34, 1.334, etc. - (@four.div(@three,20)).ceil(n).should == BigDecimal("1.#{'3'*(n-1)}4") - (BigDecimal('31').div(@three,20)).ceil(n).should == BigDecimal("10.#{'3'*(n-1)}4") + it "returns the smallest integer greater or equal to self, if n is unspecified" do + @pos_int.ceil.should == @pos_int + @neg_int.ceil.should == @neg_int + @pos_frac.ceil.should == BigDecimal("1") + @neg_frac.ceil.should == @zero + @zero.ceil.should == 0 + @zero_pos.ceil.should == @zero_pos + @zero_neg.ceil.should == @zero_neg + + + BigDecimal('2.3').ceil.should == 3 + BigDecimal('2.5').ceil.should == 3 + BigDecimal('2.9999').ceil.should == 3 + BigDecimal('-2.3').ceil.should == -2 + BigDecimal('-2.5').ceil.should == -2 + BigDecimal('-2.9999').ceil.should == -2 end - (1..10).each do |n| - # -0.4, -0.34, -0.334, etc. - (-@one.div(@three,20)).ceil(n).should == BigDecimal("-0.#{'3'* n}") + + it "raise exception, if self is special value" do + -> { @infinity.ceil }.should raise_error(FloatDomainError) + -> { @infinity_neg.ceil }.should raise_error(FloatDomainError) + -> { @nan.ceil }.should raise_error(FloatDomainError) end - (1..10).each do |n| - (@three.div(@one,20)).ceil(n).should == @three + + it "returns n digits right of the decimal point if given n > 0" do + @mixed.ceil(1).should == BigDecimal("1.3") + @mixed.ceil(5).should == BigDecimal("1.23457") + + BigDecimal("-0.03").ceil(1).should == BigDecimal("0") + BigDecimal("0.03").ceil(1).should == BigDecimal("0.1") + + BigDecimal("23.45").ceil(0).should == BigDecimal('24') + BigDecimal("23.45").ceil(1).should == BigDecimal('23.5') + BigDecimal("23.45").ceil(2).should == BigDecimal('23.45') + + BigDecimal("-23.45").ceil(0).should == BigDecimal('-23') + BigDecimal("-23.45").ceil(1).should == BigDecimal('-23.4') + BigDecimal("-23.45").ceil(2).should == BigDecimal('-23.45') + + BigDecimal("2E-10").ceil(0).should == @one + BigDecimal("2E-10").ceil(9).should == BigDecimal('1E-9') + BigDecimal("2E-10").ceil(10).should == BigDecimal('2E-10') + BigDecimal("2E-10").ceil(11).should == BigDecimal('2E-10') + + (1..10).each do |n| + # 0.4, 0.34, 0.334, etc. + (@one.div(@three,20)).ceil(n).should == BigDecimal("0.#{'3'*(n-1)}4") + # 1.4, 1.34, 1.334, etc. + (@four.div(@three,20)).ceil(n).should == BigDecimal("1.#{'3'*(n-1)}4") + (BigDecimal('31').div(@three,20)).ceil(n).should == BigDecimal("10.#{'3'*(n-1)}4") + end + (1..10).each do |n| + # -0.4, -0.34, -0.334, etc. + (-@one.div(@three,20)).ceil(n).should == BigDecimal("-0.#{'3'* n}") + end + (1..10).each do |n| + (@three.div(@one,20)).ceil(n).should == @three + end + (1..10).each do |n| + (-@three.div(@one,20)).ceil(n).should == -@three + end end - (1..10).each do |n| - (-@three.div(@one,20)).ceil(n).should == -@three + + it "sets n digits left of the decimal point to 0, if given n < 0" do + BigDecimal("13345.234").ceil(-2).should == BigDecimal("13400.0") + @mixed_big.ceil(-99).should == BigDecimal("0.13E101") + @mixed_big.ceil(-100).should == BigDecimal("0.2E101") + @mixed_big.ceil(-95).should == BigDecimal("0.123457E101") + BigDecimal("1E10").ceil(-30).should == BigDecimal('1E30') + BigDecimal("-1E10").ceil(-30).should == @zero end - end - it "sets n digits left of the decimal point to 0, if given n < 0" do - BigDecimal("13345.234").ceil(-2).should == BigDecimal("13400.0") - @mixed_big.ceil(-99).should == BigDecimal("0.13E101") - @mixed_big.ceil(-100).should == BigDecimal("0.2E101") - @mixed_big.ceil(-95).should == BigDecimal("0.123457E101") - BigDecimal("1E10").ceil(-30).should == BigDecimal('1E30') - BigDecimal("-1E10").ceil(-30).should == @zero end - end diff --git a/spec/ruby/library/bigdecimal/clone_spec.rb b/spec/ruby/library/bigdecimal/clone_spec.rb index b3a1c61d6a6a01..8bb073b7b2c42a 100644 --- a/spec/ruby/library/bigdecimal/clone_spec.rb +++ b/spec/ruby/library/bigdecimal/clone_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require_relative 'shared/clone' -describe "BigDecimal#dup" do - it_behaves_like :bigdecimal_clone, :clone +ruby_version_is ""..."3.4" do + require_relative 'shared/clone' + + describe "BigDecimal#dup" do + it_behaves_like :bigdecimal_clone, :clone + end end diff --git a/spec/ruby/library/bigdecimal/coerce_spec.rb b/spec/ruby/library/bigdecimal/coerce_spec.rb index 1e5c73f9690b20..a12997ffcd9e40 100644 --- a/spec/ruby/library/bigdecimal/coerce_spec.rb +++ b/spec/ruby/library/bigdecimal/coerce_spec.rb @@ -1,26 +1,29 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal#coerce" do +ruby_version_is ""..."3.4" do + require 'bigdecimal' - it "returns [other, self] both as BigDecimal" do - one = BigDecimal("1.0") - five_point_28 = BigDecimal("5.28") - zero_minus = BigDecimal("-0.0") - some_value = 32434234234234234234 + describe "BigDecimal#coerce" do - BigDecimal("1.2").coerce(1).should == [one, BigDecimal("1.2")] - five_point_28.coerce(1.0).should == [one, BigDecimal("5.28")] - one.coerce(one).should == [one, one] - one.coerce(2.5).should == [2.5, one] - BigDecimal("1").coerce(3.14).should == [3.14, one] - a, b = zero_minus.coerce(some_value) - a.should == BigDecimal(some_value.to_s) - b.should == zero_minus - a, b = one.coerce(some_value) - a.should == BigDecimal(some_value.to_s) - b.to_f.should be_close(1.0, TOLERANCE) # can we take out the to_f once BigDecimal#- is implemented? - b.should == one - end + it "returns [other, self] both as BigDecimal" do + one = BigDecimal("1.0") + five_point_28 = BigDecimal("5.28") + zero_minus = BigDecimal("-0.0") + some_value = 32434234234234234234 + + BigDecimal("1.2").coerce(1).should == [one, BigDecimal("1.2")] + five_point_28.coerce(1.0).should == [one, BigDecimal("5.28")] + one.coerce(one).should == [one, one] + one.coerce(2.5).should == [2.5, one] + BigDecimal("1").coerce(3.14).should == [3.14, one] + a, b = zero_minus.coerce(some_value) + a.should == BigDecimal(some_value.to_s) + b.should == zero_minus + a, b = one.coerce(some_value) + a.should == BigDecimal(some_value.to_s) + b.to_f.should be_close(1.0, TOLERANCE) # can we take out the to_f once BigDecimal#- is implemented? + b.should == one + end + end end diff --git a/spec/ruby/library/bigdecimal/comparison_spec.rb b/spec/ruby/library/bigdecimal/comparison_spec.rb index c53187b727d830..ae6f00dd9a7c56 100644 --- a/spec/ruby/library/bigdecimal/comparison_spec.rb +++ b/spec/ruby/library/bigdecimal/comparison_spec.rb @@ -1,81 +1,84 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal#<=>" do - before :each do - @zero = BigDecimal("0") - @zero_pos = BigDecimal("+0") - @zero_neg = BigDecimal("-0") - @mixed = BigDecimal("1.23456789") - @mixed_big = BigDecimal("1.23456789E100") - @pos_int = BigDecimal("2E5555") - @neg_int = BigDecimal("-2E5555") - @pos_frac = BigDecimal("2E-9999") - @neg_frac = BigDecimal("-2E-9999") +ruby_version_is ""..."3.4" do + require 'bigdecimal' - @int_mock = mock('123') - class << @int_mock - def coerce(other) - return [other, BigDecimal('123')] - end - def >=(other) - BigDecimal('123') >= other + describe "BigDecimal#<=>" do + before :each do + @zero = BigDecimal("0") + @zero_pos = BigDecimal("+0") + @zero_neg = BigDecimal("-0") + @mixed = BigDecimal("1.23456789") + @mixed_big = BigDecimal("1.23456789E100") + @pos_int = BigDecimal("2E5555") + @neg_int = BigDecimal("-2E5555") + @pos_frac = BigDecimal("2E-9999") + @neg_frac = BigDecimal("-2E-9999") + + @int_mock = mock('123') + class << @int_mock + def coerce(other) + return [other, BigDecimal('123')] + end + def >=(other) + BigDecimal('123') >= other + end end - end - @values = [@mixed, @pos_int, @neg_int, @pos_frac, @neg_frac, - -2**32, -2**31, -2**30, -2**16, -2**8, -100, -10, -1, - @zero , 1, 2, 10, 2**8, 2**16, 2**32, @int_mock, @zero_pos, @zero_neg] + @values = [@mixed, @pos_int, @neg_int, @pos_frac, @neg_frac, + -2**32, -2**31, -2**30, -2**16, -2**8, -100, -10, -1, + @zero , 1, 2, 10, 2**8, 2**16, 2**32, @int_mock, @zero_pos, @zero_neg] - @infinity = BigDecimal("Infinity") - @infinity_neg = BigDecimal("-Infinity") - @nan = BigDecimal("NaN") - end + @infinity = BigDecimal("Infinity") + @infinity_neg = BigDecimal("-Infinity") + @nan = BigDecimal("NaN") + end - it "returns 0 if a == b" do - (@pos_int <=> @pos_int).should == 0 - (@neg_int <=> @neg_int).should == 0 - (@pos_frac <=> @pos_frac).should == 0 - (@neg_frac <=> @neg_frac).should == 0 - (@zero <=> @zero).should == 0 - (@infinity <=> @infinity).should == 0 - (@infinity_neg <=> @infinity_neg).should == 0 - end + it "returns 0 if a == b" do + (@pos_int <=> @pos_int).should == 0 + (@neg_int <=> @neg_int).should == 0 + (@pos_frac <=> @pos_frac).should == 0 + (@neg_frac <=> @neg_frac).should == 0 + (@zero <=> @zero).should == 0 + (@infinity <=> @infinity).should == 0 + (@infinity_neg <=> @infinity_neg).should == 0 + end - it "returns 1 if a > b" do - (@pos_int <=> @neg_int).should == 1 - (@pos_frac <=> @neg_frac).should == 1 - (@pos_frac <=> @zero).should == 1 - @values.each { |val| - (@infinity <=> val).should == 1 - } - end + it "returns 1 if a > b" do + (@pos_int <=> @neg_int).should == 1 + (@pos_frac <=> @neg_frac).should == 1 + (@pos_frac <=> @zero).should == 1 + @values.each { |val| + (@infinity <=> val).should == 1 + } + end - it "returns -1 if a < b" do - (@zero <=> @pos_frac).should == -1 - (@neg_int <=> @pos_frac).should == -1 - (@pos_frac <=> @pos_int).should == -1 - @values.each { |val| - (@infinity_neg <=> val).should == -1 - } - end + it "returns -1 if a < b" do + (@zero <=> @pos_frac).should == -1 + (@neg_int <=> @pos_frac).should == -1 + (@pos_frac <=> @pos_int).should == -1 + @values.each { |val| + (@infinity_neg <=> val).should == -1 + } + end - it "returns nil if NaN is involved" do - @values += [@infinity, @infinity_neg, @nan] - @values << nil - @values << Object.new - @values.each { |val| - (@nan <=> val).should == nil - } - end + it "returns nil if NaN is involved" do + @values += [@infinity, @infinity_neg, @nan] + @values << nil + @values << Object.new + @values.each { |val| + (@nan <=> val).should == nil + } + end - it "returns nil if the argument is nil" do - (@zero <=> nil).should == nil - (@infinity <=> nil).should == nil - (@infinity_neg <=> nil).should == nil - (@mixed <=> nil).should == nil - (@pos_int <=> nil).should == nil - (@neg_frac <=> nil).should == nil + it "returns nil if the argument is nil" do + (@zero <=> nil).should == nil + (@infinity <=> nil).should == nil + (@infinity_neg <=> nil).should == nil + (@mixed <=> nil).should == nil + (@pos_int <=> nil).should == nil + (@neg_frac <=> nil).should == nil + end end end diff --git a/spec/ruby/library/bigdecimal/constants_spec.rb b/spec/ruby/library/bigdecimal/constants_spec.rb index 8d879c036acc00..6779a727c366ee 100644 --- a/spec/ruby/library/bigdecimal/constants_spec.rb +++ b/spec/ruby/library/bigdecimal/constants_spec.rb @@ -1,69 +1,72 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal constants" do - it "defines a VERSION value" do - BigDecimal.const_defined?(:VERSION).should be_true - end +ruby_version_is ""..."3.4" do + require 'bigdecimal' - it "has a BASE value" do - # The actual one is decided based on HAVE_INT64_T in MRI, - # which is hard to check here. - [10000, 1000000000].should include(BigDecimal::BASE) - end + describe "BigDecimal constants" do + it "defines a VERSION value" do + BigDecimal.const_defined?(:VERSION).should be_true + end - it "has a NaN value" do - BigDecimal::NAN.nan?.should be_true - end + it "has a BASE value" do + # The actual one is decided based on HAVE_INT64_T in MRI, + # which is hard to check here. + [10000, 1000000000].should include(BigDecimal::BASE) + end - it "has an INFINITY value" do - BigDecimal::INFINITY.infinite?.should == 1 - end + it "has a NaN value" do + BigDecimal::NAN.nan?.should be_true + end + + it "has an INFINITY value" do + BigDecimal::INFINITY.infinite?.should == 1 + end - describe "exception-related constants" do - [ - [:EXCEPTION_ALL, 0xff], - [:EXCEPTION_INFINITY, 0x01], - [:EXCEPTION_NaN, 0x02], - [:EXCEPTION_UNDERFLOW, 0x04], - [:EXCEPTION_OVERFLOW, 0x01], - [:EXCEPTION_ZERODIVIDE, 0x10] - ].each do |const, value| - it "has a #{const} value" do - BigDecimal.const_get(const).should == value + describe "exception-related constants" do + [ + [:EXCEPTION_ALL, 0xff], + [:EXCEPTION_INFINITY, 0x01], + [:EXCEPTION_NaN, 0x02], + [:EXCEPTION_UNDERFLOW, 0x04], + [:EXCEPTION_OVERFLOW, 0x01], + [:EXCEPTION_ZERODIVIDE, 0x10] + ].each do |const, value| + it "has a #{const} value" do + BigDecimal.const_get(const).should == value + end end end - end - describe "rounding-related constants" do - [ - [:ROUND_MODE, 0x100], - [:ROUND_UP, 1], - [:ROUND_DOWN, 2], - [:ROUND_HALF_UP, 3], - [:ROUND_HALF_DOWN, 4], - [:ROUND_CEILING, 5], - [:ROUND_FLOOR, 6], - [:ROUND_HALF_EVEN, 7] - ].each do |const, value| - it "has a #{const} value" do - BigDecimal.const_get(const).should == value + describe "rounding-related constants" do + [ + [:ROUND_MODE, 0x100], + [:ROUND_UP, 1], + [:ROUND_DOWN, 2], + [:ROUND_HALF_UP, 3], + [:ROUND_HALF_DOWN, 4], + [:ROUND_CEILING, 5], + [:ROUND_FLOOR, 6], + [:ROUND_HALF_EVEN, 7] + ].each do |const, value| + it "has a #{const} value" do + BigDecimal.const_get(const).should == value + end end end - end - describe "sign-related constants" do - [ - [:SIGN_NaN, 0], - [:SIGN_POSITIVE_ZERO, 1], - [:SIGN_NEGATIVE_ZERO, -1], - [:SIGN_POSITIVE_FINITE, 2], - [:SIGN_NEGATIVE_FINITE, -2], - [:SIGN_POSITIVE_INFINITE, 3], - [:SIGN_NEGATIVE_INFINITE, -3] - ].each do |const, value| - it "has a #{const} value" do - BigDecimal.const_get(const).should == value + describe "sign-related constants" do + [ + [:SIGN_NaN, 0], + [:SIGN_POSITIVE_ZERO, 1], + [:SIGN_NEGATIVE_ZERO, -1], + [:SIGN_POSITIVE_FINITE, 2], + [:SIGN_NEGATIVE_FINITE, -2], + [:SIGN_POSITIVE_INFINITE, 3], + [:SIGN_NEGATIVE_INFINITE, -3] + ].each do |const, value| + it "has a #{const} value" do + BigDecimal.const_get(const).should == value + end end end end diff --git a/spec/ruby/library/bigdecimal/div_spec.rb b/spec/ruby/library/bigdecimal/div_spec.rb index 53ad6d04184d87..7e0b8fada75537 100644 --- a/spec/ruby/library/bigdecimal/div_spec.rb +++ b/spec/ruby/library/bigdecimal/div_spec.rb @@ -1,110 +1,113 @@ require_relative '../../spec_helper' -require_relative 'shared/quo' -require 'bigdecimal' - -describe "BigDecimal#div with precision set to 0" do - # TODO: figure out if there is a better way to do these - # shared specs rather than sending [0]. See other specs - # that share :bigdecimal_quo. - it_behaves_like :bigdecimal_quo, :div, [0] -end -describe "BigDecimal#div" do - - before :each do - @one = BigDecimal("1") - @zero = BigDecimal("0") - @zero_plus = BigDecimal("+0") - @zero_minus = BigDecimal("-0") - @two = BigDecimal("2") - @three = BigDecimal("3") - @nan = BigDecimal("NaN") - @infinity = BigDecimal("Infinity") - @infinity_minus = BigDecimal("-Infinity") - @one_minus = BigDecimal("-1") - @frac_1 = BigDecimal("1E-99999") - @frac_2 = BigDecimal("0.9E-99999") - end +ruby_version_is ""..."3.4" do + require_relative 'shared/quo' + require 'bigdecimal' - it "returns a / b with optional precision" do - @two.div(@one).should == @two - @one.div(@two).should == @zero - # ^^ is this really intended for a class with arbitrary precision? - @one.div(@two, 1).should == BigDecimal("0.5") - @one.div(@one_minus).should == @one_minus - @one_minus.div(@one_minus).should == @one - @frac_2.div(@frac_1, 1).should == BigDecimal("0.9") - @frac_1.div(@frac_1).should == @one - - res = "0." + "3" * 1000 - (1..100).each { |idx| - @one.div(@three, idx).to_s("F").should == "0." + res[2, idx] - } + describe "BigDecimal#div with precision set to 0" do + # TODO: figure out if there is a better way to do these + # shared specs rather than sending [0]. See other specs + # that share :bigdecimal_quo. + it_behaves_like :bigdecimal_quo, :div, [0] end - describe "with Object" do - it "tries to coerce the other operand to self" do - object = mock("Object") - object.should_receive(:coerce).with(@one).and_return([@one, @two]) - @one.div(object).should == @zero + describe "BigDecimal#div" do + + before :each do + @one = BigDecimal("1") + @zero = BigDecimal("0") + @zero_plus = BigDecimal("+0") + @zero_minus = BigDecimal("-0") + @two = BigDecimal("2") + @three = BigDecimal("3") + @nan = BigDecimal("NaN") + @infinity = BigDecimal("Infinity") + @infinity_minus = BigDecimal("-Infinity") + @one_minus = BigDecimal("-1") + @frac_1 = BigDecimal("1E-99999") + @frac_2 = BigDecimal("0.9E-99999") end - end - it "raises FloatDomainError if NaN is involved" do - -> { @one.div(@nan) }.should raise_error(FloatDomainError) - -> { @nan.div(@one) }.should raise_error(FloatDomainError) - -> { @nan.div(@nan) }.should raise_error(FloatDomainError) - end + it "returns a / b with optional precision" do + @two.div(@one).should == @two + @one.div(@two).should == @zero + # ^^ is this really intended for a class with arbitrary precision? + @one.div(@two, 1).should == BigDecimal("0.5") + @one.div(@one_minus).should == @one_minus + @one_minus.div(@one_minus).should == @one + @frac_2.div(@frac_1, 1).should == BigDecimal("0.9") + @frac_1.div(@frac_1).should == @one + + res = "0." + "3" * 1000 + (1..100).each { |idx| + @one.div(@three, idx).to_s("F").should == "0." + res[2, idx] + } + end - it "returns 0 if divided by Infinity and no precision given" do - @zero.div(@infinity).should == 0 - @frac_2.div(@infinity).should == 0 - end + describe "with Object" do + it "tries to coerce the other operand to self" do + object = mock("Object") + object.should_receive(:coerce).with(@one).and_return([@one, @two]) + @one.div(object).should == @zero + end + end - it "returns 0 if divided by Infinity with given precision" do - @zero.div(@infinity, 0).should == 0 - @frac_2.div(@infinity, 1).should == 0 - @zero.div(@infinity, 100000).should == 0 - @frac_2.div(@infinity, 100000).should == 0 - end + it "raises FloatDomainError if NaN is involved" do + -> { @one.div(@nan) }.should raise_error(FloatDomainError) + -> { @nan.div(@one) }.should raise_error(FloatDomainError) + -> { @nan.div(@nan) }.should raise_error(FloatDomainError) + end - it "raises ZeroDivisionError if divided by zero and no precision given" do - -> { @one.div(@zero) }.should raise_error(ZeroDivisionError) - -> { @one.div(@zero_plus) }.should raise_error(ZeroDivisionError) - -> { @one.div(@zero_minus) }.should raise_error(ZeroDivisionError) + it "returns 0 if divided by Infinity and no precision given" do + @zero.div(@infinity).should == 0 + @frac_2.div(@infinity).should == 0 + end - -> { @zero.div(@zero) }.should raise_error(ZeroDivisionError) - -> { @zero_minus.div(@zero_plus) }.should raise_error(ZeroDivisionError) - -> { @zero_minus.div(@zero_minus) }.should raise_error(ZeroDivisionError) - -> { @zero_plus.div(@zero_minus) }.should raise_error(ZeroDivisionError) - end + it "returns 0 if divided by Infinity with given precision" do + @zero.div(@infinity, 0).should == 0 + @frac_2.div(@infinity, 1).should == 0 + @zero.div(@infinity, 100000).should == 0 + @frac_2.div(@infinity, 100000).should == 0 + end - it "returns NaN if zero is divided by zero" do - @zero.div(@zero, 0).should.nan? - @zero_minus.div(@zero_plus, 0).should.nan? - @zero_plus.div(@zero_minus, 0).should.nan? + it "raises ZeroDivisionError if divided by zero and no precision given" do + -> { @one.div(@zero) }.should raise_error(ZeroDivisionError) + -> { @one.div(@zero_plus) }.should raise_error(ZeroDivisionError) + -> { @one.div(@zero_minus) }.should raise_error(ZeroDivisionError) - @zero.div(@zero, 10).should.nan? - @zero_minus.div(@zero_plus, 10).should.nan? - @zero_plus.div(@zero_minus, 10).should.nan? - end + -> { @zero.div(@zero) }.should raise_error(ZeroDivisionError) + -> { @zero_minus.div(@zero_plus) }.should raise_error(ZeroDivisionError) + -> { @zero_minus.div(@zero_minus) }.should raise_error(ZeroDivisionError) + -> { @zero_plus.div(@zero_minus) }.should raise_error(ZeroDivisionError) + end - it "raises FloatDomainError if (+|-) Infinity divided by 1 and no precision given" do - -> { @infinity_minus.div(@one) }.should raise_error(FloatDomainError) - -> { @infinity.div(@one) }.should raise_error(FloatDomainError) - -> { @infinity_minus.div(@one_minus) }.should raise_error(FloatDomainError) - end + it "returns NaN if zero is divided by zero" do + @zero.div(@zero, 0).should.nan? + @zero_minus.div(@zero_plus, 0).should.nan? + @zero_plus.div(@zero_minus, 0).should.nan? - it "returns (+|-)Infinity if (+|-)Infinity by 1 and precision given" do - @infinity_minus.div(@one, 0).should == @infinity_minus - @infinity.div(@one, 0).should == @infinity - @infinity_minus.div(@one_minus, 0).should == @infinity - end + @zero.div(@zero, 10).should.nan? + @zero_minus.div(@zero_plus, 10).should.nan? + @zero_plus.div(@zero_minus, 10).should.nan? + end - it "returns NaN if Infinity / ((+|-) Infinity)" do - @infinity.div(@infinity_minus, 100000).should.nan? - @infinity_minus.div(@infinity, 1).should.nan? - end + it "raises FloatDomainError if (+|-) Infinity divided by 1 and no precision given" do + -> { @infinity_minus.div(@one) }.should raise_error(FloatDomainError) + -> { @infinity.div(@one) }.should raise_error(FloatDomainError) + -> { @infinity_minus.div(@one_minus) }.should raise_error(FloatDomainError) + end + + it "returns (+|-)Infinity if (+|-)Infinity by 1 and precision given" do + @infinity_minus.div(@one, 0).should == @infinity_minus + @infinity.div(@one, 0).should == @infinity + @infinity_minus.div(@one_minus, 0).should == @infinity + end + + it "returns NaN if Infinity / ((+|-) Infinity)" do + @infinity.div(@infinity_minus, 100000).should.nan? + @infinity_minus.div(@infinity, 1).should.nan? + end + end end diff --git a/spec/ruby/library/bigdecimal/divide_spec.rb b/spec/ruby/library/bigdecimal/divide_spec.rb index c62b23557dec7a..77ca878402ea96 100644 --- a/spec/ruby/library/bigdecimal/divide_spec.rb +++ b/spec/ruby/library/bigdecimal/divide_spec.rb @@ -1,17 +1,20 @@ require_relative '../../spec_helper' -require_relative 'shared/quo' -require 'bigdecimal' -describe "BigDecimal#/" do - it_behaves_like :bigdecimal_quo, :/, [] +ruby_version_is ""..."3.4" do + require_relative 'shared/quo' + require 'bigdecimal' - before :each do - @three = BigDecimal("3") - end + describe "BigDecimal#/" do + it_behaves_like :bigdecimal_quo, :/, [] + + before :each do + @three = BigDecimal("3") + end - describe "with Rational" do - it "produces a BigDecimal" do - (@three / Rational(500, 2)).should == BigDecimal("0.12e-1") + describe "with Rational" do + it "produces a BigDecimal" do + (@three / Rational(500, 2)).should == BigDecimal("0.12e-1") + end end end end diff --git a/spec/ruby/library/bigdecimal/divmod_spec.rb b/spec/ruby/library/bigdecimal/divmod_spec.rb index 294f01cba01484..8b42f2329e4271 100644 --- a/spec/ruby/library/bigdecimal/divmod_spec.rb +++ b/spec/ruby/library/bigdecimal/divmod_spec.rb @@ -1,180 +1,183 @@ require_relative '../../spec_helper' -require_relative 'shared/modulo' -require 'bigdecimal' - -module DivmodSpecs - def self.check_both_nan(array) - array.length.should == 2 - array[0].should.nan? - array[1].should.nan? - end - def self.check_both_bigdecimal(array) - array.length.should == 2 - array[0].kind_of?(BigDecimal).should == true - array[1].kind_of?(BigDecimal).should == true + +ruby_version_is ""..."3.4" do + require_relative 'shared/modulo' + require 'bigdecimal' + + module DivmodSpecs + def self.check_both_nan(array) + array.length.should == 2 + array[0].should.nan? + array[1].should.nan? + end + def self.check_both_bigdecimal(array) + array.length.should == 2 + array[0].kind_of?(BigDecimal).should == true + array[1].kind_of?(BigDecimal).should == true + end end -end -# TODO: figure out a way to do the shared specs with helpers instead -# of spec'ing a method that does not really exist -describe "BigDecimal#mod_part_of_divmod" do - # BigDecimal#divmod[1] behaves exactly like #modulo - before :all do - class BigDecimal - def mod_part_of_divmod(arg) - divmod(arg)[1] + # TODO: figure out a way to do the shared specs with helpers instead + # of spec'ing a method that does not really exist + describe "BigDecimal#mod_part_of_divmod" do + # BigDecimal#divmod[1] behaves exactly like #modulo + before :all do + class BigDecimal + def mod_part_of_divmod(arg) + divmod(arg)[1] + end end end - end - after :all do - class BigDecimal - undef mod_part_of_divmod + after :all do + class BigDecimal + undef mod_part_of_divmod + end end - end - it_behaves_like :bigdecimal_modulo, :mod_part_of_divmod + it_behaves_like :bigdecimal_modulo, :mod_part_of_divmod - it "raises ZeroDivisionError if other is zero" do - bd5667 = BigDecimal("5667.19") + it "raises ZeroDivisionError if other is zero" do + bd5667 = BigDecimal("5667.19") - -> { bd5667.mod_part_of_divmod(0) }.should raise_error(ZeroDivisionError) - -> { bd5667.mod_part_of_divmod(BigDecimal("0")) }.should raise_error(ZeroDivisionError) - -> { @zero.mod_part_of_divmod(@zero) }.should raise_error(ZeroDivisionError) + -> { bd5667.mod_part_of_divmod(0) }.should raise_error(ZeroDivisionError) + -> { bd5667.mod_part_of_divmod(BigDecimal("0")) }.should raise_error(ZeroDivisionError) + -> { @zero.mod_part_of_divmod(@zero) }.should raise_error(ZeroDivisionError) + end end -end -describe "BigDecimal#divmod" do - - before :each do - @a = BigDecimal("42.00000000000000000001") - - @zero = BigDecimal("0") - @zero_pos = BigDecimal("+0") - @zero_neg = BigDecimal("-0") - - @one = BigDecimal("1") - @mixed = BigDecimal("1.23456789") - @pos_int = BigDecimal("2E5555") - @neg_int = BigDecimal("-2E5555") - @pos_frac = BigDecimal("2E-9999") - @neg_frac = BigDecimal("-2E-9999") - @nan = BigDecimal("NaN") - @infinity = BigDecimal("Infinity") - @infinity_minus = BigDecimal("-Infinity") - @one_minus = BigDecimal("-1") - @frac_1 = BigDecimal("1E-99999") - @frac_2 = BigDecimal("0.9E-99999") - - @special_vals = [@infinity, @infinity_minus, @nan] - @regular_vals = [ - @one, @mixed, @pos_int, @neg_int, @pos_frac, - @neg_frac, @one_minus, @frac_1, @frac_2] - @zeroes = [@zero, @zero_pos, @zero_neg] - end + describe "BigDecimal#divmod" do + + before :each do + @a = BigDecimal("42.00000000000000000001") + + @zero = BigDecimal("0") + @zero_pos = BigDecimal("+0") + @zero_neg = BigDecimal("-0") + + @one = BigDecimal("1") + @mixed = BigDecimal("1.23456789") + @pos_int = BigDecimal("2E5555") + @neg_int = BigDecimal("-2E5555") + @pos_frac = BigDecimal("2E-9999") + @neg_frac = BigDecimal("-2E-9999") + @nan = BigDecimal("NaN") + @infinity = BigDecimal("Infinity") + @infinity_minus = BigDecimal("-Infinity") + @one_minus = BigDecimal("-1") + @frac_1 = BigDecimal("1E-99999") + @frac_2 = BigDecimal("0.9E-99999") + + @special_vals = [@infinity, @infinity_minus, @nan] + @regular_vals = [ + @one, @mixed, @pos_int, @neg_int, @pos_frac, + @neg_frac, @one_minus, @frac_1, @frac_2] + @zeroes = [@zero, @zero_pos, @zero_neg] + end - it "divides value, returns an array" do - res = @a.divmod(5) - res.kind_of?(Array).should == true - end + it "divides value, returns an array" do + res = @a.divmod(5) + res.kind_of?(Array).should == true + end - it "array contains quotient and modulus as BigDecimal" do - res = @a.divmod(5) - DivmodSpecs.check_both_bigdecimal(res) - res[0].should == BigDecimal('0.8E1') - res[1].should == BigDecimal('2.00000000000000000001') + it "array contains quotient and modulus as BigDecimal" do + res = @a.divmod(5) + DivmodSpecs.check_both_bigdecimal(res) + res[0].should == BigDecimal('0.8E1') + res[1].should == BigDecimal('2.00000000000000000001') - BigDecimal('1').divmod(BigDecimal('2')).should == [0, 1] - BigDecimal('2').divmod(BigDecimal('1')).should == [2, 0] + BigDecimal('1').divmod(BigDecimal('2')).should == [0, 1] + BigDecimal('2').divmod(BigDecimal('1')).should == [2, 0] - BigDecimal('1').divmod(BigDecimal('-2')).should == [-1, -1] - BigDecimal('2').divmod(BigDecimal('-1')).should == [-2, 0] + BigDecimal('1').divmod(BigDecimal('-2')).should == [-1, -1] + BigDecimal('2').divmod(BigDecimal('-1')).should == [-2, 0] - BigDecimal('-1').divmod(BigDecimal('2')).should == [-1, 1] - BigDecimal('-2').divmod(BigDecimal('1')).should == [-2, 0] - end + BigDecimal('-1').divmod(BigDecimal('2')).should == [-1, 1] + BigDecimal('-2').divmod(BigDecimal('1')).should == [-2, 0] + end - it "can be reversed with * and +" do - # Example taken from BigDecimal documentation - a = BigDecimal("42") - b = BigDecimal("9") - q, m = a.divmod(b) - c = q * b + m - a.should == c - - values = [@one, @one_minus, BigDecimal('2'), BigDecimal('-2'), - BigDecimal('5'), BigDecimal('-5'), BigDecimal('10'), BigDecimal('-10'), - BigDecimal('20'), BigDecimal('-20'), BigDecimal('100'), BigDecimal('-100'), - BigDecimal('1.23456789E10'), BigDecimal('-1.23456789E10') - ] - - # TODO: file MRI bug: - # BigDecimal('1').divmod(BigDecimal('3E-9'))[0] #=> 0.3E9, - # but really should be 0.333333333E9 - values << BigDecimal('1E-10') - values << BigDecimal('-1E-10') - values << BigDecimal('2E55') - values << BigDecimal('-2E55') - values << BigDecimal('2E-5555') - values << BigDecimal('-2E-5555') - - - values_and_zeroes = values + @zeroes - values_and_zeroes.each do |val1| - values.each do |val2| - res = val1.divmod(val2) - DivmodSpecs.check_both_bigdecimal(res) - res[0].should == ((val1/val2).floor) - res[1].should == (val1 - res[0] * val2) + it "can be reversed with * and +" do + # Example taken from BigDecimal documentation + a = BigDecimal("42") + b = BigDecimal("9") + q, m = a.divmod(b) + c = q * b + m + a.should == c + + values = [@one, @one_minus, BigDecimal('2'), BigDecimal('-2'), + BigDecimal('5'), BigDecimal('-5'), BigDecimal('10'), BigDecimal('-10'), + BigDecimal('20'), BigDecimal('-20'), BigDecimal('100'), BigDecimal('-100'), + BigDecimal('1.23456789E10'), BigDecimal('-1.23456789E10') + ] + + # TODO: file MRI bug: + # BigDecimal('1').divmod(BigDecimal('3E-9'))[0] #=> 0.3E9, + # but really should be 0.333333333E9 + values << BigDecimal('1E-10') + values << BigDecimal('-1E-10') + values << BigDecimal('2E55') + values << BigDecimal('-2E55') + values << BigDecimal('2E-5555') + values << BigDecimal('-2E-5555') + + + values_and_zeroes = values + @zeroes + values_and_zeroes.each do |val1| + values.each do |val2| + res = val1.divmod(val2) + DivmodSpecs.check_both_bigdecimal(res) + res[0].should == ((val1/val2).floor) + res[1].should == (val1 - res[0] * val2) + end end end - end - it "returns an array of two NaNs if NaN is involved" do - (@special_vals + @regular_vals + @zeroes).each do |val| - DivmodSpecs.check_both_nan(val.divmod(@nan)) - DivmodSpecs.check_both_nan(@nan.divmod(val)) + it "returns an array of two NaNs if NaN is involved" do + (@special_vals + @regular_vals + @zeroes).each do |val| + DivmodSpecs.check_both_nan(val.divmod(@nan)) + DivmodSpecs.check_both_nan(@nan.divmod(val)) + end end - end - it "raises ZeroDivisionError if the divisor is zero" do - (@special_vals + @regular_vals + @zeroes - [@nan]).each do |val| - @zeroes.each do |zero| - -> { val.divmod(zero) }.should raise_error(ZeroDivisionError) + it "raises ZeroDivisionError if the divisor is zero" do + (@special_vals + @regular_vals + @zeroes - [@nan]).each do |val| + @zeroes.each do |zero| + -> { val.divmod(zero) }.should raise_error(ZeroDivisionError) + end end end - end - it "returns an array of Infinity and NaN if the dividend is Infinity" do - @regular_vals.each do |val| - array = @infinity.divmod(val) - array.length.should == 2 - array[0].infinite?.should == (val > 0 ? 1 : -1) - array[1].should.nan? + it "returns an array of Infinity and NaN if the dividend is Infinity" do + @regular_vals.each do |val| + array = @infinity.divmod(val) + array.length.should == 2 + array[0].infinite?.should == (val > 0 ? 1 : -1) + array[1].should.nan? + end end - end - it "returns an array of zero and the dividend if the divisor is Infinity" do - @regular_vals.each do |val| - array = val.divmod(@infinity) - array.length.should == 2 - array[0].should == @zero - array[1].should == val + it "returns an array of zero and the dividend if the divisor is Infinity" do + @regular_vals.each do |val| + array = val.divmod(@infinity) + array.length.should == 2 + array[0].should == @zero + array[1].should == val + end end - end - it "returns an array of two zero if the dividend is zero" do - @zeroes.each do |zero| - @regular_vals.each do |val| - zero.divmod(val).should == [@zero, @zero] + it "returns an array of two zero if the dividend is zero" do + @zeroes.each do |zero| + @regular_vals.each do |val| + zero.divmod(val).should == [@zero, @zero] + end end end - end - it "raises TypeError if the argument cannot be coerced to BigDecimal" do - -> { - @one.divmod('1') - }.should raise_error(TypeError) - end + it "raises TypeError if the argument cannot be coerced to BigDecimal" do + -> { + @one.divmod('1') + }.should raise_error(TypeError) + end + end end diff --git a/spec/ruby/library/bigdecimal/double_fig_spec.rb b/spec/ruby/library/bigdecimal/double_fig_spec.rb index f742d68f876f0a..d008dbcefb1bf7 100644 --- a/spec/ruby/library/bigdecimal/double_fig_spec.rb +++ b/spec/ruby/library/bigdecimal/double_fig_spec.rb @@ -1,9 +1,12 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal.double_fig" do - # The result depends on the CPU and OS - it "returns the number of digits a Float number is allowed to have" do - BigDecimal.double_fig.should_not == nil +ruby_version_is ""..."3.4" do + require 'bigdecimal' + + describe "BigDecimal.double_fig" do + # The result depends on the CPU and OS + it "returns the number of digits a Float number is allowed to have" do + BigDecimal.double_fig.should_not == nil + end end end diff --git a/spec/ruby/library/bigdecimal/dup_spec.rb b/spec/ruby/library/bigdecimal/dup_spec.rb index bfabaf6e8b7c29..3fe07c3738ff32 100644 --- a/spec/ruby/library/bigdecimal/dup_spec.rb +++ b/spec/ruby/library/bigdecimal/dup_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require_relative 'shared/clone' -describe "BigDecimal#dup" do - it_behaves_like :bigdecimal_clone, :dup +ruby_version_is ""..."3.4" do + require_relative 'shared/clone' + + describe "BigDecimal#dup" do + it_behaves_like :bigdecimal_clone, :dup + end end diff --git a/spec/ruby/library/bigdecimal/eql_spec.rb b/spec/ruby/library/bigdecimal/eql_spec.rb index 1be58627519f17..4a2c0e0b11926d 100644 --- a/spec/ruby/library/bigdecimal/eql_spec.rb +++ b/spec/ruby/library/bigdecimal/eql_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require_relative 'shared/eql' -describe "BigDecimal#eql?" do - it_behaves_like :bigdecimal_eql, :eql? +ruby_version_is ""..."3.4" do + require_relative 'shared/eql' + + describe "BigDecimal#eql?" do + it_behaves_like :bigdecimal_eql, :eql? + end end diff --git a/spec/ruby/library/bigdecimal/equal_value_spec.rb b/spec/ruby/library/bigdecimal/equal_value_spec.rb index 933060eada8ce8..7c2230cbc41795 100644 --- a/spec/ruby/library/bigdecimal/equal_value_spec.rb +++ b/spec/ruby/library/bigdecimal/equal_value_spec.rb @@ -1,7 +1,10 @@ require_relative '../../spec_helper' -require_relative 'shared/eql' +ruby_version_is ""..."3.4" do + require_relative 'shared/eql' -describe "BigDecimal#==" do - it_behaves_like :bigdecimal_eql, :== + + describe "BigDecimal#==" do + it_behaves_like :bigdecimal_eql, :== + end end diff --git a/spec/ruby/library/bigdecimal/exponent_spec.rb b/spec/ruby/library/bigdecimal/exponent_spec.rb index 887714795514d1..7574e8c560c6cc 100644 --- a/spec/ruby/library/bigdecimal/exponent_spec.rb +++ b/spec/ruby/library/bigdecimal/exponent_spec.rb @@ -1,27 +1,30 @@ require_relative '../../spec_helper' -require_relative 'shared/power' -require 'bigdecimal' -describe "BigDecimal#**" do - it_behaves_like :bigdecimal_power, :** -end - -describe "BigDecimal#exponent" do +ruby_version_is ""..."3.4" do + require_relative 'shared/power' + require 'bigdecimal' - it "returns an Integer" do - BigDecimal("2E100000000").exponent.kind_of?(Integer).should == true - BigDecimal("2E-999").exponent.kind_of?(Integer).should == true + describe "BigDecimal#**" do + it_behaves_like :bigdecimal_power, :** end - it "is n if number can be represented as 0.xxx*10**n" do - BigDecimal("2E1000").exponent.should == 1001 - BigDecimal("1234567E10").exponent.should == 17 - end + describe "BigDecimal#exponent" do - it "returns 0 if self is 0" do - BigDecimal("0").exponent.should == 0 - BigDecimal("+0").exponent.should == 0 - BigDecimal("-0").exponent.should == 0 - end + it "returns an Integer" do + BigDecimal("2E100000000").exponent.kind_of?(Integer).should == true + BigDecimal("2E-999").exponent.kind_of?(Integer).should == true + end + it "is n if number can be represented as 0.xxx*10**n" do + BigDecimal("2E1000").exponent.should == 1001 + BigDecimal("1234567E10").exponent.should == 17 + end + + it "returns 0 if self is 0" do + BigDecimal("0").exponent.should == 0 + BigDecimal("+0").exponent.should == 0 + BigDecimal("-0").exponent.should == 0 + end + + end end diff --git a/spec/ruby/library/bigdecimal/finite_spec.rb b/spec/ruby/library/bigdecimal/finite_spec.rb index 8fc06029bb3d76..af693ac496337e 100644 --- a/spec/ruby/library/bigdecimal/finite_spec.rb +++ b/spec/ruby/library/bigdecimal/finite_spec.rb @@ -1,34 +1,37 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal#finite?" do - before :each do - @one = BigDecimal("1") - @zero = BigDecimal("0") - @zero_pos = BigDecimal("+0") - @zero_neg = BigDecimal("-0") - @two = BigDecimal("2") - @three = BigDecimal("3") - @nan = BigDecimal("NaN") - @infinity = BigDecimal("Infinity") - @infinity_minus = BigDecimal("-Infinity") - @one_minus = BigDecimal("-1") - @frac_1 = BigDecimal("1E-99999") - @frac_2 = BigDecimal("0.9E-99999") - @big = BigDecimal("2E40001") - @finite_vals = [@one, @zero, @zero_pos, @zero_neg, @two, - @three, @frac_1, @frac_2, @big, @one_minus] - end +ruby_version_is ""..."3.4" do + require 'bigdecimal' - it "is false if Infinity or NaN" do - @infinity.should_not.finite? - @infinity_minus.should_not.finite? - @nan.should_not.finite? - end + describe "BigDecimal#finite?" do + before :each do + @one = BigDecimal("1") + @zero = BigDecimal("0") + @zero_pos = BigDecimal("+0") + @zero_neg = BigDecimal("-0") + @two = BigDecimal("2") + @three = BigDecimal("3") + @nan = BigDecimal("NaN") + @infinity = BigDecimal("Infinity") + @infinity_minus = BigDecimal("-Infinity") + @one_minus = BigDecimal("-1") + @frac_1 = BigDecimal("1E-99999") + @frac_2 = BigDecimal("0.9E-99999") + @big = BigDecimal("2E40001") + @finite_vals = [@one, @zero, @zero_pos, @zero_neg, @two, + @three, @frac_1, @frac_2, @big, @one_minus] + end + + it "is false if Infinity or NaN" do + @infinity.should_not.finite? + @infinity_minus.should_not.finite? + @nan.should_not.finite? + end - it "returns true for finite values" do - @finite_vals.each do |val| - val.should.finite? + it "returns true for finite values" do + @finite_vals.each do |val| + val.should.finite? + end end end end diff --git a/spec/ruby/library/bigdecimal/fix_spec.rb b/spec/ruby/library/bigdecimal/fix_spec.rb index 231c9a587e3cae..49a898b9c5e716 100644 --- a/spec/ruby/library/bigdecimal/fix_spec.rb +++ b/spec/ruby/library/bigdecimal/fix_spec.rb @@ -1,57 +1,60 @@ require_relative '../../spec_helper' -require 'bigdecimal' - -describe "BigDecimal#fix" do - before :each do - @zero = BigDecimal("0") - @mixed = BigDecimal("1.23456789") - @pos_int = BigDecimal("2E5555") - @neg_int = BigDecimal("-2E5555") - @pos_frac = BigDecimal("2E-9999") - @neg_frac = BigDecimal("-2E-9999") - - @infinity = BigDecimal("Infinity") - @infinity_neg = BigDecimal("-Infinity") - @nan = BigDecimal("NaN") - @zero_pos = BigDecimal("+0") - @zero_neg = BigDecimal("-0") + +ruby_version_is ""..."3.4" do + require 'bigdecimal' + + describe "BigDecimal#fix" do + before :each do + @zero = BigDecimal("0") + @mixed = BigDecimal("1.23456789") + @pos_int = BigDecimal("2E5555") + @neg_int = BigDecimal("-2E5555") + @pos_frac = BigDecimal("2E-9999") + @neg_frac = BigDecimal("-2E-9999") + + @infinity = BigDecimal("Infinity") + @infinity_neg = BigDecimal("-Infinity") + @nan = BigDecimal("NaN") + @zero_pos = BigDecimal("+0") + @zero_neg = BigDecimal("-0") + end + + it "returns a BigDecimal" do + BigDecimal("2E100000000").fix.kind_of?(BigDecimal).should == true + BigDecimal("2E-999").kind_of?(BigDecimal).should == true end - it "returns a BigDecimal" do - BigDecimal("2E100000000").fix.kind_of?(BigDecimal).should == true - BigDecimal("2E-999").kind_of?(BigDecimal).should == true - end + it "returns the integer part of the absolute value" do + a = BigDecimal("2E1000") + a.fix.should == a + b = BigDecimal("-2E1000") + b.fix.should == b + BigDecimal("0.123456789E5").fix.should == BigDecimal("0.12345E5") + BigDecimal("-0.123456789E5").fix.should == BigDecimal("-0.12345E5") + end - it "returns the integer part of the absolute value" do - a = BigDecimal("2E1000") - a.fix.should == a - b = BigDecimal("-2E1000") - b.fix.should == b - BigDecimal("0.123456789E5").fix.should == BigDecimal("0.12345E5") - BigDecimal("-0.123456789E5").fix.should == BigDecimal("-0.12345E5") - end + it "correctly handles special values" do + @infinity.fix.should == @infinity + @infinity_neg.fix.should == @infinity_neg + @nan.fix.should.nan? + end - it "correctly handles special values" do - @infinity.fix.should == @infinity - @infinity_neg.fix.should == @infinity_neg - @nan.fix.should.nan? - end + it "returns 0 if the absolute value is < 1" do + BigDecimal("0.99999").fix.should == 0 + BigDecimal("-0.99999").fix.should == 0 + BigDecimal("0.000000001").fix.should == 0 + BigDecimal("-0.00000001").fix.should == 0 + BigDecimal("-1000000").fix.should_not == 0 + @zero.fix.should == 0 + @zero_pos.fix.should == @zero_pos + @zero_neg.fix.should == @zero_neg + end - it "returns 0 if the absolute value is < 1" do - BigDecimal("0.99999").fix.should == 0 - BigDecimal("-0.99999").fix.should == 0 - BigDecimal("0.000000001").fix.should == 0 - BigDecimal("-0.00000001").fix.should == 0 - BigDecimal("-1000000").fix.should_not == 0 - @zero.fix.should == 0 - @zero_pos.fix.should == @zero_pos - @zero_neg.fix.should == @zero_neg - end + it "does not allow any arguments" do + -> { + @mixed.fix(10) + }.should raise_error(ArgumentError) + end - it "does not allow any arguments" do - -> { - @mixed.fix(10) - }.should raise_error(ArgumentError) end - end diff --git a/spec/ruby/library/bigdecimal/floor_spec.rb b/spec/ruby/library/bigdecimal/floor_spec.rb index a7dfec2c9a1fcb..e36843c1167c5c 100644 --- a/spec/ruby/library/bigdecimal/floor_spec.rb +++ b/spec/ruby/library/bigdecimal/floor_spec.rb @@ -1,100 +1,103 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal#floor" do - before :each do - @one = BigDecimal("1") - @three = BigDecimal("3") - @four = BigDecimal("4") - @zero = BigDecimal("0") - @mixed = BigDecimal("1.23456789") - @mixed_big = BigDecimal("1.23456789E100") - @pos_int = BigDecimal("2E5555") - @neg_int = BigDecimal("-2E5555") - @pos_frac = BigDecimal("2E-9999") - @neg_frac = BigDecimal("-2E-9999") +ruby_version_is ""..."3.4" do + require 'bigdecimal' - @infinity = BigDecimal("Infinity") - @infinity_neg = BigDecimal("-Infinity") - @nan = BigDecimal("NaN") - @zero_pos = BigDecimal("+0") - @zero_neg = BigDecimal("-0") - end + describe "BigDecimal#floor" do + before :each do + @one = BigDecimal("1") + @three = BigDecimal("3") + @four = BigDecimal("4") + @zero = BigDecimal("0") + @mixed = BigDecimal("1.23456789") + @mixed_big = BigDecimal("1.23456789E100") + @pos_int = BigDecimal("2E5555") + @neg_int = BigDecimal("-2E5555") + @pos_frac = BigDecimal("2E-9999") + @neg_frac = BigDecimal("-2E-9999") - it "returns the greatest integer smaller or equal to self" do - @pos_int.floor.should == @pos_int - @neg_int.floor.should == @neg_int - @pos_frac.floor.should == @zero - @neg_frac.floor.should == BigDecimal("-1") - @zero.floor.should == 0 - @zero_pos.floor.should == @zero_pos - @zero_neg.floor.should == @zero_neg + @infinity = BigDecimal("Infinity") + @infinity_neg = BigDecimal("-Infinity") + @nan = BigDecimal("NaN") + @zero_pos = BigDecimal("+0") + @zero_neg = BigDecimal("-0") + end - BigDecimal('2.3').floor.should == 2 - BigDecimal('2.5').floor.should == 2 - BigDecimal('2.9999').floor.should == 2 - BigDecimal('-2.3').floor.should == -3 - BigDecimal('-2.5').floor.should == -3 - BigDecimal('-2.9999').floor.should == -3 - BigDecimal('0.8').floor.should == 0 - BigDecimal('-0.8').floor.should == -1 - end + it "returns the greatest integer smaller or equal to self" do + @pos_int.floor.should == @pos_int + @neg_int.floor.should == @neg_int + @pos_frac.floor.should == @zero + @neg_frac.floor.should == BigDecimal("-1") + @zero.floor.should == 0 + @zero_pos.floor.should == @zero_pos + @zero_neg.floor.should == @zero_neg - it "raise exception, if self is special value" do - -> { @infinity.floor }.should raise_error(FloatDomainError) - -> { @infinity_neg.floor }.should raise_error(FloatDomainError) - -> { @nan.floor }.should raise_error(FloatDomainError) - end + BigDecimal('2.3').floor.should == 2 + BigDecimal('2.5').floor.should == 2 + BigDecimal('2.9999').floor.should == 2 + BigDecimal('-2.3').floor.should == -3 + BigDecimal('-2.5').floor.should == -3 + BigDecimal('-2.9999').floor.should == -3 + BigDecimal('0.8').floor.should == 0 + BigDecimal('-0.8').floor.should == -1 + end - it "returns n digits right of the decimal point if given n > 0" do - @mixed.floor(1).should == BigDecimal("1.2") - @mixed.floor(5).should == BigDecimal("1.23456") + it "raise exception, if self is special value" do + -> { @infinity.floor }.should raise_error(FloatDomainError) + -> { @infinity_neg.floor }.should raise_error(FloatDomainError) + -> { @nan.floor }.should raise_error(FloatDomainError) + end - BigDecimal("-0.03").floor(1).should == BigDecimal("-0.1") - BigDecimal("0.03").floor(1).should == BigDecimal("0") + it "returns n digits right of the decimal point if given n > 0" do + @mixed.floor(1).should == BigDecimal("1.2") + @mixed.floor(5).should == BigDecimal("1.23456") - BigDecimal("23.45").floor(0).should == BigDecimal('23') - BigDecimal("23.45").floor(1).should == BigDecimal('23.4') - BigDecimal("23.45").floor(2).should == BigDecimal('23.45') + BigDecimal("-0.03").floor(1).should == BigDecimal("-0.1") + BigDecimal("0.03").floor(1).should == BigDecimal("0") - BigDecimal("-23.45").floor(0).should == BigDecimal('-24') - BigDecimal("-23.45").floor(1).should == BigDecimal('-23.5') - BigDecimal("-23.45").floor(2).should == BigDecimal('-23.45') + BigDecimal("23.45").floor(0).should == BigDecimal('23') + BigDecimal("23.45").floor(1).should == BigDecimal('23.4') + BigDecimal("23.45").floor(2).should == BigDecimal('23.45') - BigDecimal("2E-10").floor(0).should == @zero - BigDecimal("2E-10").floor(9).should == @zero - BigDecimal("2E-10").floor(10).should == BigDecimal('2E-10') - BigDecimal("2E-10").floor(11).should == BigDecimal('2E-10') + BigDecimal("-23.45").floor(0).should == BigDecimal('-24') + BigDecimal("-23.45").floor(1).should == BigDecimal('-23.5') + BigDecimal("-23.45").floor(2).should == BigDecimal('-23.45') - (1..10).each do |n| - # 0.3, 0.33, 0.333, etc. - (@one.div(@three,20)).floor(n).should == BigDecimal("0.#{'3'*n}") - # 1.3, 1.33, 1.333, etc. - (@four.div(@three,20)).floor(n).should == BigDecimal("1.#{'3'*n}") - (BigDecimal('31').div(@three,20)).floor(n).should == BigDecimal("10.#{'3'*n}") - end - (1..10).each do |n| - # -0.4, -0.34, -0.334, etc. - (-@one.div(@three,20)).floor(n).should == BigDecimal("-0.#{'3'*(n-1)}4") - end - (1..10).each do |n| - (@three.div(@one,20)).floor(n).should == @three - end - (1..10).each do |n| - (-@three.div(@one,20)).floor(n).should == -@three + BigDecimal("2E-10").floor(0).should == @zero + BigDecimal("2E-10").floor(9).should == @zero + BigDecimal("2E-10").floor(10).should == BigDecimal('2E-10') + BigDecimal("2E-10").floor(11).should == BigDecimal('2E-10') + + (1..10).each do |n| + # 0.3, 0.33, 0.333, etc. + (@one.div(@three,20)).floor(n).should == BigDecimal("0.#{'3'*n}") + # 1.3, 1.33, 1.333, etc. + (@four.div(@three,20)).floor(n).should == BigDecimal("1.#{'3'*n}") + (BigDecimal('31').div(@three,20)).floor(n).should == BigDecimal("10.#{'3'*n}") + end + (1..10).each do |n| + # -0.4, -0.34, -0.334, etc. + (-@one.div(@three,20)).floor(n).should == BigDecimal("-0.#{'3'*(n-1)}4") + end + (1..10).each do |n| + (@three.div(@one,20)).floor(n).should == @three + end + (1..10).each do |n| + (-@three.div(@one,20)).floor(n).should == -@three + end end - end - it "sets n digits left of the decimal point to 0, if given n < 0" do - BigDecimal("13345.234").floor(-2).should == BigDecimal("13300.0") - @mixed_big.floor(-99).should == BigDecimal("0.12E101") - @mixed_big.floor(-100).should == BigDecimal("0.1E101") - @mixed_big.floor(-95).should == BigDecimal("0.123456E101") - (1..10).each do |n| - BigDecimal('1.8').floor(-n).should == @zero + it "sets n digits left of the decimal point to 0, if given n < 0" do + BigDecimal("13345.234").floor(-2).should == BigDecimal("13300.0") + @mixed_big.floor(-99).should == BigDecimal("0.12E101") + @mixed_big.floor(-100).should == BigDecimal("0.1E101") + @mixed_big.floor(-95).should == BigDecimal("0.123456E101") + (1..10).each do |n| + BigDecimal('1.8').floor(-n).should == @zero + end + BigDecimal("1E10").floor(-30).should == @zero + BigDecimal("-1E10").floor(-30).should == BigDecimal('-1E30') end - BigDecimal("1E10").floor(-30).should == @zero - BigDecimal("-1E10").floor(-30).should == BigDecimal('-1E30') - end + end end diff --git a/spec/ruby/library/bigdecimal/frac_spec.rb b/spec/ruby/library/bigdecimal/frac_spec.rb index 11ccf03c2f0606..9cf72d313ec78f 100644 --- a/spec/ruby/library/bigdecimal/frac_spec.rb +++ b/spec/ruby/library/bigdecimal/frac_spec.rb @@ -1,48 +1,51 @@ require_relative '../../spec_helper' -require 'bigdecimal' - -describe "BigDecimal#frac" do - before :each do - @zero = BigDecimal("0") - @mixed = BigDecimal("1.23456789") - @pos_int = BigDecimal("2E5555") - @neg_int = BigDecimal("-2E5555") - @pos_frac = BigDecimal("2E-9999") - @neg_frac = BigDecimal("-2E-9999") - - @infinity = BigDecimal("Infinity") - @infinity_neg = BigDecimal("-Infinity") - @nan = BigDecimal("NaN") - @zero_pos = BigDecimal("+0") - @zero_neg = BigDecimal("-0") - end - it "returns a BigDecimal" do - @pos_int.frac.kind_of?(BigDecimal).should == true - @neg_int.frac.kind_of?(BigDecimal).should == true - @pos_frac.kind_of?(BigDecimal).should == true - @neg_frac.kind_of?(BigDecimal).should == true - end +ruby_version_is ""..."3.4" do + require 'bigdecimal' + + describe "BigDecimal#frac" do + before :each do + @zero = BigDecimal("0") + @mixed = BigDecimal("1.23456789") + @pos_int = BigDecimal("2E5555") + @neg_int = BigDecimal("-2E5555") + @pos_frac = BigDecimal("2E-9999") + @neg_frac = BigDecimal("-2E-9999") + + @infinity = BigDecimal("Infinity") + @infinity_neg = BigDecimal("-Infinity") + @nan = BigDecimal("NaN") + @zero_pos = BigDecimal("+0") + @zero_neg = BigDecimal("-0") + end + + it "returns a BigDecimal" do + @pos_int.frac.kind_of?(BigDecimal).should == true + @neg_int.frac.kind_of?(BigDecimal).should == true + @pos_frac.kind_of?(BigDecimal).should == true + @neg_frac.kind_of?(BigDecimal).should == true + end + + it "returns the fractional part of the absolute value" do + @mixed.frac.should == BigDecimal("0.23456789") + @pos_frac.frac.should == @pos_frac + @neg_frac.frac.should == @neg_frac + end + + it "returns 0 if the value is 0" do + @zero.frac.should == @zero + end + + it "returns 0 if the value is an integer" do + @pos_int.frac.should == @zero + @neg_int.frac.should == @zero + end + + it "correctly handles special values" do + @infinity.frac.should == @infinity + @infinity_neg.frac.should == @infinity_neg + @nan.frac.should.nan? + end - it "returns the fractional part of the absolute value" do - @mixed.frac.should == BigDecimal("0.23456789") - @pos_frac.frac.should == @pos_frac - @neg_frac.frac.should == @neg_frac end - - it "returns 0 if the value is 0" do - @zero.frac.should == @zero - end - - it "returns 0 if the value is an integer" do - @pos_int.frac.should == @zero - @neg_int.frac.should == @zero - end - - it "correctly handles special values" do - @infinity.frac.should == @infinity - @infinity_neg.frac.should == @infinity_neg - @nan.frac.should.nan? - end - end diff --git a/spec/ruby/library/bigdecimal/gt_spec.rb b/spec/ruby/library/bigdecimal/gt_spec.rb index 78547fb85f152f..2af84673d382f7 100644 --- a/spec/ruby/library/bigdecimal/gt_spec.rb +++ b/spec/ruby/library/bigdecimal/gt_spec.rb @@ -1,96 +1,99 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal#>" do - before :each do - @zero = BigDecimal("0") - @zero_pos = BigDecimal("+0") - @zero_neg = BigDecimal("-0") - @mixed = BigDecimal("1.23456789") - @pos_int = BigDecimal("2E5555") - @neg_int = BigDecimal("-2E5555") - @pos_frac = BigDecimal("2E-9999") - @neg_frac = BigDecimal("-2E-9999") +ruby_version_is ""..."3.4" do + require 'bigdecimal' - @int_mock = mock('123') - class << @int_mock - def coerce(other) - return [other, BigDecimal('123')] - end - def >(other) - BigDecimal('123') > other + describe "BigDecimal#>" do + before :each do + @zero = BigDecimal("0") + @zero_pos = BigDecimal("+0") + @zero_neg = BigDecimal("-0") + @mixed = BigDecimal("1.23456789") + @pos_int = BigDecimal("2E5555") + @neg_int = BigDecimal("-2E5555") + @pos_frac = BigDecimal("2E-9999") + @neg_frac = BigDecimal("-2E-9999") + + @int_mock = mock('123') + class << @int_mock + def coerce(other) + return [other, BigDecimal('123')] + end + def >(other) + BigDecimal('123') > other + end end - end - @values = [@mixed, @pos_int, @neg_int, @pos_frac, @neg_frac, - -2**32, -2**31, -2**30, -2**16, -2**8, -100, -10, -1, - @zero , 1, 2, 10, 10.5, 2**8, 2**16, 2**32, @int_mock, @zero_pos, @zero_neg] + @values = [@mixed, @pos_int, @neg_int, @pos_frac, @neg_frac, + -2**32, -2**31, -2**30, -2**16, -2**8, -100, -10, -1, + @zero , 1, 2, 10, 10.5, 2**8, 2**16, 2**32, @int_mock, @zero_pos, @zero_neg] - @infinity = BigDecimal("Infinity") - @infinity_neg = BigDecimal("-Infinity") + @infinity = BigDecimal("Infinity") + @infinity_neg = BigDecimal("-Infinity") - @float_infinity = Float::INFINITY - @float_infinity_neg = -Float::INFINITY + @float_infinity = Float::INFINITY + @float_infinity_neg = -Float::INFINITY - @nan = BigDecimal("NaN") - end + @nan = BigDecimal("NaN") + end - it "returns true if a > b" do - one = BigDecimal("1") - two = BigDecimal("2") + it "returns true if a > b" do + one = BigDecimal("1") + two = BigDecimal("2") - frac_1 = BigDecimal("1E-99999") - frac_2 = BigDecimal("0.9E-99999") - (@zero > one).should == false - (two > @zero).should == true - (frac_2 > frac_1).should == false + frac_1 = BigDecimal("1E-99999") + frac_2 = BigDecimal("0.9E-99999") + (@zero > one).should == false + (two > @zero).should == true + (frac_2 > frac_1).should == false - (@neg_int > @pos_int).should == false - (@pos_int > @neg_int).should == true - (@neg_int > @pos_frac).should == false - (@pos_frac > @neg_int).should == true - (@zero > @zero_pos).should == false - (@zero > @zero_neg).should == false - (@zero_neg > @zero_pos).should == false - (@zero_pos > @zero_neg).should == false - end + (@neg_int > @pos_int).should == false + (@pos_int > @neg_int).should == true + (@neg_int > @pos_frac).should == false + (@pos_frac > @neg_int).should == true + (@zero > @zero_pos).should == false + (@zero > @zero_neg).should == false + (@zero_neg > @zero_pos).should == false + (@zero_pos > @zero_neg).should == false + end - it "properly handles infinity values" do - @values.each { |val| - (val > @infinity).should == false - (@infinity > val).should == true - (val > @infinity_neg).should == true - (@infinity_neg > val).should == false - } - (@infinity > @infinity).should == false - (@infinity_neg > @infinity_neg).should == false - (@infinity > @infinity_neg).should == true - (@infinity_neg > @infinity).should == false - end + it "properly handles infinity values" do + @values.each { |val| + (val > @infinity).should == false + (@infinity > val).should == true + (val > @infinity_neg).should == true + (@infinity_neg > val).should == false + } + (@infinity > @infinity).should == false + (@infinity_neg > @infinity_neg).should == false + (@infinity > @infinity_neg).should == true + (@infinity_neg > @infinity).should == false + end - it "properly handles Float infinity values" do - @values.each { |val| - (val > @float_infinity).should == false - (@float_infinity > val).should == true - (val > @float_infinity_neg).should == true - (@float_infinity_neg > val).should == false - } - end + it "properly handles Float infinity values" do + @values.each { |val| + (val > @float_infinity).should == false + (@float_infinity > val).should == true + (val > @float_infinity_neg).should == true + (@float_infinity_neg > val).should == false + } + end - it "properly handles NaN values" do - @values += [@infinity, @infinity_neg, @nan] - @values.each { |val| - (@nan > val).should == false - (val > @nan).should == false - } - end + it "properly handles NaN values" do + @values += [@infinity, @infinity_neg, @nan] + @values.each { |val| + (@nan > val).should == false + (val > @nan).should == false + } + end - it "raises an ArgumentError if the argument can't be coerced into a BigDecimal" do - -> {@zero > nil }.should raise_error(ArgumentError) - -> {@infinity > nil }.should raise_error(ArgumentError) - -> {@infinity_neg > nil }.should raise_error(ArgumentError) - -> {@mixed > nil }.should raise_error(ArgumentError) - -> {@pos_int > nil }.should raise_error(ArgumentError) - -> {@neg_frac > nil }.should raise_error(ArgumentError) + it "raises an ArgumentError if the argument can't be coerced into a BigDecimal" do + -> {@zero > nil }.should raise_error(ArgumentError) + -> {@infinity > nil }.should raise_error(ArgumentError) + -> {@infinity_neg > nil }.should raise_error(ArgumentError) + -> {@mixed > nil }.should raise_error(ArgumentError) + -> {@pos_int > nil }.should raise_error(ArgumentError) + -> {@neg_frac > nil }.should raise_error(ArgumentError) + end end end diff --git a/spec/ruby/library/bigdecimal/gte_spec.rb b/spec/ruby/library/bigdecimal/gte_spec.rb index 2a5cc025ba3821..1f9838bf25b434 100644 --- a/spec/ruby/library/bigdecimal/gte_spec.rb +++ b/spec/ruby/library/bigdecimal/gte_spec.rb @@ -1,100 +1,103 @@ require_relative '../../spec_helper' -require 'bigdecimal' - -describe "BigDecimal#>=" do - before :each do - @zero = BigDecimal("0") - @zero_pos = BigDecimal("+0") - @zero_neg = BigDecimal("-0") - @mixed = BigDecimal("1.23456789") - @pos_int = BigDecimal("2E5555") - @neg_int = BigDecimal("-2E5555") - @pos_frac = BigDecimal("2E-9999") - @neg_frac = BigDecimal("-2E-9999") - - @int_mock = mock('123') - class << @int_mock - def coerce(other) - return [other, BigDecimal('123')] - end - def >=(other) - BigDecimal('123') >= other + +ruby_version_is ""..."3.4" do + require 'bigdecimal' + + describe "BigDecimal#>=" do + before :each do + @zero = BigDecimal("0") + @zero_pos = BigDecimal("+0") + @zero_neg = BigDecimal("-0") + @mixed = BigDecimal("1.23456789") + @pos_int = BigDecimal("2E5555") + @neg_int = BigDecimal("-2E5555") + @pos_frac = BigDecimal("2E-9999") + @neg_frac = BigDecimal("-2E-9999") + + @int_mock = mock('123') + class << @int_mock + def coerce(other) + return [other, BigDecimal('123')] + end + def >=(other) + BigDecimal('123') >= other + end end - end - @values = [@mixed, @pos_int, @neg_int, @pos_frac, @neg_frac, - -2**32, -2**31, -2**30, -2**16, -2**8, -100, -10, -1, - @zero , 1, 2, 10, 10.5, 2**8, 2**16, 2**32, @int_mock, @zero_pos, @zero_neg] + @values = [@mixed, @pos_int, @neg_int, @pos_frac, @neg_frac, + -2**32, -2**31, -2**30, -2**16, -2**8, -100, -10, -1, + @zero , 1, 2, 10, 10.5, 2**8, 2**16, 2**32, @int_mock, @zero_pos, @zero_neg] - @infinity = BigDecimal("Infinity") - @infinity_neg = BigDecimal("-Infinity") + @infinity = BigDecimal("Infinity") + @infinity_neg = BigDecimal("-Infinity") - @float_infinity = Float::INFINITY - @float_infinity_neg = -Float::INFINITY + @float_infinity = Float::INFINITY + @float_infinity_neg = -Float::INFINITY - @nan = BigDecimal("NaN") - end + @nan = BigDecimal("NaN") + end - it "returns true if a >= b" do - one = BigDecimal("1") - two = BigDecimal("2") + it "returns true if a >= b" do + one = BigDecimal("1") + two = BigDecimal("2") - frac_1 = BigDecimal("1E-99999") - frac_2 = BigDecimal("0.9E-99999") + frac_1 = BigDecimal("1E-99999") + frac_2 = BigDecimal("0.9E-99999") - (@zero >= one).should == false - (two >= @zero).should == true + (@zero >= one).should == false + (two >= @zero).should == true - (frac_2 >= frac_1).should == false - (two >= two).should == true - (frac_1 >= frac_1).should == true + (frac_2 >= frac_1).should == false + (two >= two).should == true + (frac_1 >= frac_1).should == true - (@neg_int >= @pos_int).should == false - (@pos_int >= @neg_int).should == true - (@neg_int >= @pos_frac).should == false - (@pos_frac >= @neg_int).should == true - (@zero >= @zero_pos).should == true - (@zero >= @zero_neg).should == true - (@zero_neg >= @zero_pos).should == true - (@zero_pos >= @zero_neg).should == true - end + (@neg_int >= @pos_int).should == false + (@pos_int >= @neg_int).should == true + (@neg_int >= @pos_frac).should == false + (@pos_frac >= @neg_int).should == true + (@zero >= @zero_pos).should == true + (@zero >= @zero_neg).should == true + (@zero_neg >= @zero_pos).should == true + (@zero_pos >= @zero_neg).should == true + end - it "properly handles infinity values" do - @values.each { |val| - (val >= @infinity).should == false - (@infinity >= val).should == true - (val >= @infinity_neg).should == true - (@infinity_neg >= val).should == false - } - (@infinity >= @infinity).should == true - (@infinity_neg >= @infinity_neg).should == true - (@infinity >= @infinity_neg).should == true - (@infinity_neg >= @infinity).should == false - end + it "properly handles infinity values" do + @values.each { |val| + (val >= @infinity).should == false + (@infinity >= val).should == true + (val >= @infinity_neg).should == true + (@infinity_neg >= val).should == false + } + (@infinity >= @infinity).should == true + (@infinity_neg >= @infinity_neg).should == true + (@infinity >= @infinity_neg).should == true + (@infinity_neg >= @infinity).should == false + end - it "properly handles Float infinity values" do - @values.each { |val| - (val >= @float_infinity).should == false - (@float_infinity >= val).should == true - (val >= @float_infinity_neg).should == true - (@float_infinity_neg >= val).should == false - } - end + it "properly handles Float infinity values" do + @values.each { |val| + (val >= @float_infinity).should == false + (@float_infinity >= val).should == true + (val >= @float_infinity_neg).should == true + (@float_infinity_neg >= val).should == false + } + end - it "properly handles NaN values" do - @values += [@infinity, @infinity_neg, @nan] - @values.each { |val| - (@nan >= val).should == false - (val >= @nan).should == false - } - end + it "properly handles NaN values" do + @values += [@infinity, @infinity_neg, @nan] + @values.each { |val| + (@nan >= val).should == false + (val >= @nan).should == false + } + end - it "returns nil if the argument is nil" do - -> {@zero >= nil }.should raise_error(ArgumentError) - -> {@infinity >= nil }.should raise_error(ArgumentError) - -> {@infinity_neg >= nil }.should raise_error(ArgumentError) - -> {@mixed >= nil }.should raise_error(ArgumentError) - -> {@pos_int >= nil }.should raise_error(ArgumentError) - -> {@neg_frac >= nil }.should raise_error(ArgumentError) + it "returns nil if the argument is nil" do + -> {@zero >= nil }.should raise_error(ArgumentError) + -> {@infinity >= nil }.should raise_error(ArgumentError) + -> {@infinity_neg >= nil }.should raise_error(ArgumentError) + -> {@mixed >= nil }.should raise_error(ArgumentError) + -> {@pos_int >= nil }.should raise_error(ArgumentError) + -> {@neg_frac >= nil }.should raise_error(ArgumentError) + end end end diff --git a/spec/ruby/library/bigdecimal/hash_spec.rb b/spec/ruby/library/bigdecimal/hash_spec.rb index 7581c90f681bee..7eea0f6464d72f 100644 --- a/spec/ruby/library/bigdecimal/hash_spec.rb +++ b/spec/ruby/library/bigdecimal/hash_spec.rb @@ -1,30 +1,33 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BidDecimal#hash" do - describe "two BigDecimal objects with the same value" do - it "should have the same hash for ordinary values" do - BigDecimal('1.2920').hash.should == BigDecimal('1.2920').hash - end +ruby_version_is ""..."3.4" do + require 'bigdecimal' - it "should have the same hash for infinite values" do - BigDecimal("+Infinity").hash.should == BigDecimal("+Infinity").hash - BigDecimal("-Infinity").hash.should == BigDecimal("-Infinity").hash - end + describe "BidDecimal#hash" do + describe "two BigDecimal objects with the same value" do + it "should have the same hash for ordinary values" do + BigDecimal('1.2920').hash.should == BigDecimal('1.2920').hash + end - it "should have the same hash for NaNs" do - BigDecimal("NaN").hash.should == BigDecimal("NaN").hash - end + it "should have the same hash for infinite values" do + BigDecimal("+Infinity").hash.should == BigDecimal("+Infinity").hash + BigDecimal("-Infinity").hash.should == BigDecimal("-Infinity").hash + end - it "should have the same hash for zero values" do - BigDecimal("+0").hash.should == BigDecimal("+0").hash - BigDecimal("-0").hash.should == BigDecimal("-0").hash + it "should have the same hash for NaNs" do + BigDecimal("NaN").hash.should == BigDecimal("NaN").hash + end + + it "should have the same hash for zero values" do + BigDecimal("+0").hash.should == BigDecimal("+0").hash + BigDecimal("-0").hash.should == BigDecimal("-0").hash + end end - end - describe "two BigDecimal objects with numerically equal values" do - it "should have the same hash value" do - BigDecimal("1.2920").hash.should == BigDecimal("1.2920000").hash + describe "two BigDecimal objects with numerically equal values" do + it "should have the same hash value" do + BigDecimal("1.2920").hash.should == BigDecimal("1.2920000").hash + end end end end diff --git a/spec/ruby/library/bigdecimal/infinite_spec.rb b/spec/ruby/library/bigdecimal/infinite_spec.rb index 025386107f668c..79a451d85771b0 100644 --- a/spec/ruby/library/bigdecimal/infinite_spec.rb +++ b/spec/ruby/library/bigdecimal/infinite_spec.rb @@ -1,32 +1,35 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal#infinite?" do +ruby_version_is ""..."3.4" do + require 'bigdecimal' - it "returns 1 if self is Infinity" do - BigDecimal("Infinity").infinite?.should == 1 - end + describe "BigDecimal#infinite?" do - it "returns -1 if self is -Infinity" do - BigDecimal("-Infinity").infinite?.should == -1 - end + it "returns 1 if self is Infinity" do + BigDecimal("Infinity").infinite?.should == 1 + end - it "returns not true otherwise" do - e2_plus = BigDecimal("2E40001") - e3_minus = BigDecimal("3E-20001") - really_small_zero = BigDecimal("0E-200000000") - really_big_zero = BigDecimal("0E200000000000") - e3_minus.infinite?.should == nil - e2_plus.infinite?.should == nil - really_small_zero.infinite?.should == nil - really_big_zero.infinite?.should == nil - BigDecimal("0.000000000000000000000000").infinite?.should == nil - end + it "returns -1 if self is -Infinity" do + BigDecimal("-Infinity").infinite?.should == -1 + end - it "returns not true if self is NaN" do - # NaN is a special value which is neither finite nor infinite. - nan = BigDecimal("NaN") - nan.infinite?.should == nil - end + it "returns not true otherwise" do + e2_plus = BigDecimal("2E40001") + e3_minus = BigDecimal("3E-20001") + really_small_zero = BigDecimal("0E-200000000") + really_big_zero = BigDecimal("0E200000000000") + e3_minus.infinite?.should == nil + e2_plus.infinite?.should == nil + really_small_zero.infinite?.should == nil + really_big_zero.infinite?.should == nil + BigDecimal("0.000000000000000000000000").infinite?.should == nil + end + + it "returns not true if self is NaN" do + # NaN is a special value which is neither finite nor infinite. + nan = BigDecimal("NaN") + nan.infinite?.should == nil + end + end end diff --git a/spec/ruby/library/bigdecimal/inspect_spec.rb b/spec/ruby/library/bigdecimal/inspect_spec.rb index 7ce47142b2b603..a6f72f759f301a 100644 --- a/spec/ruby/library/bigdecimal/inspect_spec.rb +++ b/spec/ruby/library/bigdecimal/inspect_spec.rb @@ -1,30 +1,33 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal#inspect" do +ruby_version_is ""..."3.4" do + require 'bigdecimal' - before :each do - @bigdec = BigDecimal("1234.5678") - end + describe "BigDecimal#inspect" do - it "returns String" do - @bigdec.inspect.kind_of?(String).should == true - end + before :each do + @bigdec = BigDecimal("1234.5678") + end - it "looks like this" do - @bigdec.inspect.should == "0.12345678e4" - end + it "returns String" do + @bigdec.inspect.kind_of?(String).should == true + end - it "does not add an exponent for zero values" do - BigDecimal("0").inspect.should == "0.0" - BigDecimal("+0").inspect.should == "0.0" - BigDecimal("-0").inspect.should == "-0.0" - end + it "looks like this" do + @bigdec.inspect.should == "0.12345678e4" + end + + it "does not add an exponent for zero values" do + BigDecimal("0").inspect.should == "0.0" + BigDecimal("+0").inspect.should == "0.0" + BigDecimal("-0").inspect.should == "-0.0" + end - it "properly cases non-finite values" do - BigDecimal("NaN").inspect.should == "NaN" - BigDecimal("Infinity").inspect.should == "Infinity" - BigDecimal("+Infinity").inspect.should == "Infinity" - BigDecimal("-Infinity").inspect.should == "-Infinity" + it "properly cases non-finite values" do + BigDecimal("NaN").inspect.should == "NaN" + BigDecimal("Infinity").inspect.should == "Infinity" + BigDecimal("+Infinity").inspect.should == "Infinity" + BigDecimal("-Infinity").inspect.should == "-Infinity" + end end end diff --git a/spec/ruby/library/bigdecimal/limit_spec.rb b/spec/ruby/library/bigdecimal/limit_spec.rb index 75cbc8b55c9f0c..c1d130d4ec525c 100644 --- a/spec/ruby/library/bigdecimal/limit_spec.rb +++ b/spec/ruby/library/bigdecimal/limit_spec.rb @@ -1,55 +1,58 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require 'bigdecimal' - -describe "BigDecimal.limit" do - it "returns the value before set if the passed argument is nil or is not specified" do - old = BigDecimal.limit - BigDecimal.limit.should == 0 - BigDecimal.limit(10).should == 0 - BigDecimal.limit.should == 10 - BigDecimal.limit(old) - end - it "uses the global limit if no precision is specified" do - BigDecimalSpecs.with_limit(0) do - (BigDecimal('0.888') + BigDecimal('0')).should == BigDecimal('0.888') - (BigDecimal('0.888') - BigDecimal('0')).should == BigDecimal('0.888') - (BigDecimal('0.888') * BigDecimal('3')).should == BigDecimal('2.664') - (BigDecimal('0.888') / BigDecimal('3')).should == BigDecimal('0.296') - end +ruby_version_is ""..."3.4" do + require_relative 'fixtures/classes' + require 'bigdecimal' - BigDecimalSpecs.with_limit(1) do - (BigDecimal('0.888') + BigDecimal('0')).should == BigDecimal('0.9') - (BigDecimal('0.888') - BigDecimal('0')).should == BigDecimal('0.9') - (BigDecimal('0.888') * BigDecimal('3')).should == BigDecimal('3') - (BigDecimal('0.888') / BigDecimal('3')).should == BigDecimal('0.3') + describe "BigDecimal.limit" do + it "returns the value before set if the passed argument is nil or is not specified" do + old = BigDecimal.limit + BigDecimal.limit.should == 0 + BigDecimal.limit(10).should == 0 + BigDecimal.limit.should == 10 + BigDecimal.limit(old) end - BigDecimalSpecs.with_limit(2) do - (BigDecimal('0.888') + BigDecimal('0')).should == BigDecimal('0.89') - (BigDecimal('0.888') - BigDecimal('0')).should == BigDecimal('0.89') - (BigDecimal('0.888') * BigDecimal('3')).should == BigDecimal('2.7') - (BigDecimal('0.888') / BigDecimal('3')).should == BigDecimal('0.30') + it "uses the global limit if no precision is specified" do + BigDecimalSpecs.with_limit(0) do + (BigDecimal('0.888') + BigDecimal('0')).should == BigDecimal('0.888') + (BigDecimal('0.888') - BigDecimal('0')).should == BigDecimal('0.888') + (BigDecimal('0.888') * BigDecimal('3')).should == BigDecimal('2.664') + (BigDecimal('0.888') / BigDecimal('3')).should == BigDecimal('0.296') + end + + BigDecimalSpecs.with_limit(1) do + (BigDecimal('0.888') + BigDecimal('0')).should == BigDecimal('0.9') + (BigDecimal('0.888') - BigDecimal('0')).should == BigDecimal('0.9') + (BigDecimal('0.888') * BigDecimal('3')).should == BigDecimal('3') + (BigDecimal('0.888') / BigDecimal('3')).should == BigDecimal('0.3') + end + + BigDecimalSpecs.with_limit(2) do + (BigDecimal('0.888') + BigDecimal('0')).should == BigDecimal('0.89') + (BigDecimal('0.888') - BigDecimal('0')).should == BigDecimal('0.89') + (BigDecimal('0.888') * BigDecimal('3')).should == BigDecimal('2.7') + (BigDecimal('0.888') / BigDecimal('3')).should == BigDecimal('0.30') + end end - end - it "picks the specified precision over global limit" do - BigDecimalSpecs.with_limit(3) do - BigDecimal('0.888').add(BigDecimal('0'), 2).should == BigDecimal('0.89') - BigDecimal('0.888').sub(BigDecimal('0'), 2).should == BigDecimal('0.89') - BigDecimal('0.888').mult(BigDecimal('3'), 2).should == BigDecimal('2.7') - BigDecimal('0.888').div(BigDecimal('3'), 2).should == BigDecimal('0.30') + it "picks the specified precision over global limit" do + BigDecimalSpecs.with_limit(3) do + BigDecimal('0.888').add(BigDecimal('0'), 2).should == BigDecimal('0.89') + BigDecimal('0.888').sub(BigDecimal('0'), 2).should == BigDecimal('0.89') + BigDecimal('0.888').mult(BigDecimal('3'), 2).should == BigDecimal('2.7') + BigDecimal('0.888').div(BigDecimal('3'), 2).should == BigDecimal('0.30') + end end - end - it "picks the global precision when limit 0 specified" do - BigDecimalSpecs.with_limit(3) do - BigDecimal('0.8888').add(BigDecimal('0'), 0).should == BigDecimal('0.889') - BigDecimal('0.8888').sub(BigDecimal('0'), 0).should == BigDecimal('0.889') - BigDecimal('0.888').mult(BigDecimal('3'), 0).should == BigDecimal('2.66') - BigDecimal('0.8888').div(BigDecimal('3'), 0).should == BigDecimal('0.296') + it "picks the global precision when limit 0 specified" do + BigDecimalSpecs.with_limit(3) do + BigDecimal('0.8888').add(BigDecimal('0'), 0).should == BigDecimal('0.889') + BigDecimal('0.8888').sub(BigDecimal('0'), 0).should == BigDecimal('0.889') + BigDecimal('0.888').mult(BigDecimal('3'), 0).should == BigDecimal('2.66') + BigDecimal('0.8888').div(BigDecimal('3'), 0).should == BigDecimal('0.296') + end end - end + end end diff --git a/spec/ruby/library/bigdecimal/lt_spec.rb b/spec/ruby/library/bigdecimal/lt_spec.rb index 02390e76e33b61..7cffb12f7b9085 100644 --- a/spec/ruby/library/bigdecimal/lt_spec.rb +++ b/spec/ruby/library/bigdecimal/lt_spec.rb @@ -1,94 +1,97 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal#<" do - before :each do - @zero = BigDecimal("0") - @zero_pos = BigDecimal("+0") - @zero_neg = BigDecimal("-0") - @mixed = BigDecimal("1.23456789") - @pos_int = BigDecimal("2E5555") - @neg_int = BigDecimal("-2E5555") - @pos_frac = BigDecimal("2E-9999") - @neg_frac = BigDecimal("-2E-9999") +ruby_version_is ""..."3.4" do + require 'bigdecimal' - @int_mock = mock('123') - class << @int_mock - def coerce(other) - return [other, BigDecimal('123')] - end - def <(other) - BigDecimal('123') < other + describe "BigDecimal#<" do + before :each do + @zero = BigDecimal("0") + @zero_pos = BigDecimal("+0") + @zero_neg = BigDecimal("-0") + @mixed = BigDecimal("1.23456789") + @pos_int = BigDecimal("2E5555") + @neg_int = BigDecimal("-2E5555") + @pos_frac = BigDecimal("2E-9999") + @neg_frac = BigDecimal("-2E-9999") + + @int_mock = mock('123') + class << @int_mock + def coerce(other) + return [other, BigDecimal('123')] + end + def <(other) + BigDecimal('123') < other + end end - end - @values = [@mixed, @pos_int, @neg_int, @pos_frac, @neg_frac, - -2**32, -2**31, -2**30, -2**16, -2**8, -100, -10, -1, - @zero , 1, 2, 10, 10.5, 2**8, 2**16, 2**32, @int_mock, @zero_pos, @zero_neg] + @values = [@mixed, @pos_int, @neg_int, @pos_frac, @neg_frac, + -2**32, -2**31, -2**30, -2**16, -2**8, -100, -10, -1, + @zero , 1, 2, 10, 10.5, 2**8, 2**16, 2**32, @int_mock, @zero_pos, @zero_neg] - @infinity = BigDecimal("Infinity") - @infinity_neg = BigDecimal("-Infinity") + @infinity = BigDecimal("Infinity") + @infinity_neg = BigDecimal("-Infinity") - @float_infinity = Float::INFINITY - @float_infinity_neg = -Float::INFINITY + @float_infinity = Float::INFINITY + @float_infinity_neg = -Float::INFINITY - @nan = BigDecimal("NaN") - end + @nan = BigDecimal("NaN") + end - it "returns true if a < b" do - one = BigDecimal("1") - two = BigDecimal("2") - frac_1 = BigDecimal("1E-99999") - frac_2 = BigDecimal("0.9E-99999") - (@zero < one).should == true - (two < @zero).should == false - (frac_2 < frac_1).should == true - (@neg_int < @pos_int).should == true - (@pos_int < @neg_int).should == false - (@neg_int < @pos_frac).should == true - (@pos_frac < @neg_int).should == false - (@zero < @zero_pos).should == false - (@zero < @zero_neg).should == false - (@zero_neg < @zero_pos).should == false - (@zero_pos < @zero_neg).should == false - end + it "returns true if a < b" do + one = BigDecimal("1") + two = BigDecimal("2") + frac_1 = BigDecimal("1E-99999") + frac_2 = BigDecimal("0.9E-99999") + (@zero < one).should == true + (two < @zero).should == false + (frac_2 < frac_1).should == true + (@neg_int < @pos_int).should == true + (@pos_int < @neg_int).should == false + (@neg_int < @pos_frac).should == true + (@pos_frac < @neg_int).should == false + (@zero < @zero_pos).should == false + (@zero < @zero_neg).should == false + (@zero_neg < @zero_pos).should == false + (@zero_pos < @zero_neg).should == false + end - it "properly handles infinity values" do - @values.each { |val| - (val < @infinity).should == true - (@infinity < val).should == false - (val < @infinity_neg).should == false - (@infinity_neg < val).should == true - } - (@infinity < @infinity).should == false - (@infinity_neg < @infinity_neg).should == false - (@infinity < @infinity_neg).should == false - (@infinity_neg < @infinity).should == true - end + it "properly handles infinity values" do + @values.each { |val| + (val < @infinity).should == true + (@infinity < val).should == false + (val < @infinity_neg).should == false + (@infinity_neg < val).should == true + } + (@infinity < @infinity).should == false + (@infinity_neg < @infinity_neg).should == false + (@infinity < @infinity_neg).should == false + (@infinity_neg < @infinity).should == true + end - it "properly handles Float infinity values" do - @values.each { |val| - (val < @float_infinity).should == true - (@float_infinity < val).should == false - (val < @float_infinity_neg).should == false - (@float_infinity_neg < val).should == true - } - end + it "properly handles Float infinity values" do + @values.each { |val| + (val < @float_infinity).should == true + (@float_infinity < val).should == false + (val < @float_infinity_neg).should == false + (@float_infinity_neg < val).should == true + } + end - it "properly handles NaN values" do - @values += [@infinity, @infinity_neg, @nan] - @values.each { |val| - (@nan < val).should == false - (val < @nan).should == false - } - end + it "properly handles NaN values" do + @values += [@infinity, @infinity_neg, @nan] + @values.each { |val| + (@nan < val).should == false + (val < @nan).should == false + } + end - it "raises an ArgumentError if the argument can't be coerced into a BigDecimal" do - -> {@zero < nil }.should raise_error(ArgumentError) - -> {@infinity < nil }.should raise_error(ArgumentError) - -> {@infinity_neg < nil }.should raise_error(ArgumentError) - -> {@mixed < nil }.should raise_error(ArgumentError) - -> {@pos_int < nil }.should raise_error(ArgumentError) - -> {@neg_frac < nil }.should raise_error(ArgumentError) + it "raises an ArgumentError if the argument can't be coerced into a BigDecimal" do + -> {@zero < nil }.should raise_error(ArgumentError) + -> {@infinity < nil }.should raise_error(ArgumentError) + -> {@infinity_neg < nil }.should raise_error(ArgumentError) + -> {@mixed < nil }.should raise_error(ArgumentError) + -> {@pos_int < nil }.should raise_error(ArgumentError) + -> {@neg_frac < nil }.should raise_error(ArgumentError) + end end end diff --git a/spec/ruby/library/bigdecimal/lte_spec.rb b/spec/ruby/library/bigdecimal/lte_spec.rb index b92be04123f106..2dc6bdc9437363 100644 --- a/spec/ruby/library/bigdecimal/lte_spec.rb +++ b/spec/ruby/library/bigdecimal/lte_spec.rb @@ -1,100 +1,103 @@ require_relative '../../spec_helper' -require 'bigdecimal' - -describe "BigDecimal#<=" do - before :each do - @zero = BigDecimal("0") - @zero_pos = BigDecimal("+0") - @zero_neg = BigDecimal("-0") - @mixed = BigDecimal("1.23456789") - @pos_int = BigDecimal("2E5555") - @neg_int = BigDecimal("-2E5555") - @pos_frac = BigDecimal("2E-9999") - @neg_frac = BigDecimal("-2E-9999") - - @int_mock = mock('123') - class << @int_mock - def coerce(other) - return [other, BigDecimal('123')] - end - def <=(other) - BigDecimal('123') <= other + +ruby_version_is ""..."3.4" do + require 'bigdecimal' + + describe "BigDecimal#<=" do + before :each do + @zero = BigDecimal("0") + @zero_pos = BigDecimal("+0") + @zero_neg = BigDecimal("-0") + @mixed = BigDecimal("1.23456789") + @pos_int = BigDecimal("2E5555") + @neg_int = BigDecimal("-2E5555") + @pos_frac = BigDecimal("2E-9999") + @neg_frac = BigDecimal("-2E-9999") + + @int_mock = mock('123') + class << @int_mock + def coerce(other) + return [other, BigDecimal('123')] + end + def <=(other) + BigDecimal('123') <= other + end end - end - @values = [@mixed, @pos_int, @neg_int, @pos_frac, @neg_frac, - -2**32, -2**31, -2**30, -2**16, -2**8, -100, -10, -1, - @zero , 1, 2, 10, 10.5, 2**8, 2**16, 2**32, @int_mock, @zero_pos, @zero_neg] + @values = [@mixed, @pos_int, @neg_int, @pos_frac, @neg_frac, + -2**32, -2**31, -2**30, -2**16, -2**8, -100, -10, -1, + @zero , 1, 2, 10, 10.5, 2**8, 2**16, 2**32, @int_mock, @zero_pos, @zero_neg] - @infinity = BigDecimal("Infinity") - @infinity_neg = BigDecimal("-Infinity") + @infinity = BigDecimal("Infinity") + @infinity_neg = BigDecimal("-Infinity") - @float_infinity = Float::INFINITY - @float_infinity_neg = -Float::INFINITY + @float_infinity = Float::INFINITY + @float_infinity_neg = -Float::INFINITY - @nan = BigDecimal("NaN") - end + @nan = BigDecimal("NaN") + end - it "returns true if a <= b" do - one = BigDecimal("1") - two = BigDecimal("2") + it "returns true if a <= b" do + one = BigDecimal("1") + two = BigDecimal("2") - frac_1 = BigDecimal("1E-99999") - frac_2 = BigDecimal("0.9E-99999") + frac_1 = BigDecimal("1E-99999") + frac_2 = BigDecimal("0.9E-99999") - (@zero <= one).should == true - (two <= @zero).should == false + (@zero <= one).should == true + (two <= @zero).should == false - (frac_2 <= frac_1).should == true - (two <= two).should == true - (frac_1 <= frac_1).should == true + (frac_2 <= frac_1).should == true + (two <= two).should == true + (frac_1 <= frac_1).should == true - (@neg_int <= @pos_int).should == true - (@pos_int <= @neg_int).should == false - (@neg_int <= @pos_frac).should == true - (@pos_frac <= @neg_int).should == false - (@zero <= @zero_pos).should == true - (@zero <= @zero_neg).should == true - (@zero_neg <= @zero_pos).should == true - (@zero_pos <= @zero_neg).should == true - end + (@neg_int <= @pos_int).should == true + (@pos_int <= @neg_int).should == false + (@neg_int <= @pos_frac).should == true + (@pos_frac <= @neg_int).should == false + (@zero <= @zero_pos).should == true + (@zero <= @zero_neg).should == true + (@zero_neg <= @zero_pos).should == true + (@zero_pos <= @zero_neg).should == true + end - it "properly handles infinity values" do - @values.each { |val| - (val <= @infinity).should == true - (@infinity <= val).should == false - (val <= @infinity_neg).should == false - (@infinity_neg <= val).should == true - } - (@infinity <= @infinity).should == true - (@infinity_neg <= @infinity_neg).should == true - (@infinity <= @infinity_neg).should == false - (@infinity_neg <= @infinity).should == true - end + it "properly handles infinity values" do + @values.each { |val| + (val <= @infinity).should == true + (@infinity <= val).should == false + (val <= @infinity_neg).should == false + (@infinity_neg <= val).should == true + } + (@infinity <= @infinity).should == true + (@infinity_neg <= @infinity_neg).should == true + (@infinity <= @infinity_neg).should == false + (@infinity_neg <= @infinity).should == true + end - it "properly handles Float infinity values" do - @values.each { |val| - (val <= @float_infinity).should == true - (@float_infinity <= val).should == false - (val <= @float_infinity_neg).should == false - (@float_infinity_neg <= val).should == true - } - end + it "properly handles Float infinity values" do + @values.each { |val| + (val <= @float_infinity).should == true + (@float_infinity <= val).should == false + (val <= @float_infinity_neg).should == false + (@float_infinity_neg <= val).should == true + } + end - it "properly handles NaN values" do - @values += [@infinity, @infinity_neg, @nan] - @values.each { |val| - (@nan <= val).should == false - (val <= @nan).should == false - } - end + it "properly handles NaN values" do + @values += [@infinity, @infinity_neg, @nan] + @values.each { |val| + (@nan <= val).should == false + (val <= @nan).should == false + } + end - it "raises an ArgumentError if the argument can't be coerced into a BigDecimal" do - -> {@zero <= nil }.should raise_error(ArgumentError) - -> {@infinity <= nil }.should raise_error(ArgumentError) - -> {@infinity_neg <= nil }.should raise_error(ArgumentError) - -> {@mixed <= nil }.should raise_error(ArgumentError) - -> {@pos_int <= nil }.should raise_error(ArgumentError) - -> {@neg_frac <= nil }.should raise_error(ArgumentError) + it "raises an ArgumentError if the argument can't be coerced into a BigDecimal" do + -> {@zero <= nil }.should raise_error(ArgumentError) + -> {@infinity <= nil }.should raise_error(ArgumentError) + -> {@infinity_neg <= nil }.should raise_error(ArgumentError) + -> {@mixed <= nil }.should raise_error(ArgumentError) + -> {@pos_int <= nil }.should raise_error(ArgumentError) + -> {@neg_frac <= nil }.should raise_error(ArgumentError) + end end end diff --git a/spec/ruby/library/bigdecimal/minus_spec.rb b/spec/ruby/library/bigdecimal/minus_spec.rb index bd3c19584b84b8..e65b9bcffc9cb9 100644 --- a/spec/ruby/library/bigdecimal/minus_spec.rb +++ b/spec/ruby/library/bigdecimal/minus_spec.rb @@ -1,66 +1,69 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal#-" do +ruby_version_is ""..."3.4" do + require 'bigdecimal' - before :each do - @one = BigDecimal("1") - @zero = BigDecimal("0") - @two = BigDecimal("2") - @nan = BigDecimal("NaN") - @infinity = BigDecimal("Infinity") - @infinity_minus = BigDecimal("-Infinity") - @one_minus = BigDecimal("-1") - @frac_1 = BigDecimal("1E-99999") - @frac_2 = BigDecimal("0.9E-99999") - end + describe "BigDecimal#-" do - it "returns a - b" do - (@two - @one).should == @one - (@one - @two).should == @one_minus - (@one - @one_minus).should == @two - (@frac_2 - @frac_1).should == BigDecimal("-0.1E-99999") - (@two - @two).should == @zero - (@frac_1 - @frac_1).should == @zero - (BigDecimal('1.23456789') - BigDecimal('1.2')).should == BigDecimal("0.03456789") - end + before :each do + @one = BigDecimal("1") + @zero = BigDecimal("0") + @two = BigDecimal("2") + @nan = BigDecimal("NaN") + @infinity = BigDecimal("Infinity") + @infinity_minus = BigDecimal("-Infinity") + @one_minus = BigDecimal("-1") + @frac_1 = BigDecimal("1E-99999") + @frac_2 = BigDecimal("0.9E-99999") + end - it "returns NaN if NaN is involved" do - (@one - @nan).should.nan? - (@nan - @one).should.nan? - (@nan - @nan).should.nan? - (@nan - @infinity).should.nan? - (@nan - @infinity_minus).should.nan? - (@infinity - @nan).should.nan? - (@infinity_minus - @nan).should.nan? - end + it "returns a - b" do + (@two - @one).should == @one + (@one - @two).should == @one_minus + (@one - @one_minus).should == @two + (@frac_2 - @frac_1).should == BigDecimal("-0.1E-99999") + (@two - @two).should == @zero + (@frac_1 - @frac_1).should == @zero + (BigDecimal('1.23456789') - BigDecimal('1.2')).should == BigDecimal("0.03456789") + end - it "returns NaN both operands are infinite with the same sign" do - (@infinity - @infinity).should.nan? - (@infinity_minus - @infinity_minus).should.nan? - end + it "returns NaN if NaN is involved" do + (@one - @nan).should.nan? + (@nan - @one).should.nan? + (@nan - @nan).should.nan? + (@nan - @infinity).should.nan? + (@nan - @infinity_minus).should.nan? + (@infinity - @nan).should.nan? + (@infinity_minus - @nan).should.nan? + end - it "returns Infinity or -Infinity if these are involved" do - (@infinity - @infinity_minus).should == @infinity - (@infinity_minus - @infinity).should == @infinity_minus + it "returns NaN both operands are infinite with the same sign" do + (@infinity - @infinity).should.nan? + (@infinity_minus - @infinity_minus).should.nan? + end - (@infinity - @zero).should == @infinity - (@infinity - @frac_2).should == @infinity - (@infinity - @two).should == @infinity - (@infinity - @one_minus).should == @infinity + it "returns Infinity or -Infinity if these are involved" do + (@infinity - @infinity_minus).should == @infinity + (@infinity_minus - @infinity).should == @infinity_minus - (@zero - @infinity).should == @infinity_minus - (@frac_2 - @infinity).should == @infinity_minus - (@two - @infinity).should == @infinity_minus - (@one_minus - @infinity).should == @infinity_minus - end + (@infinity - @zero).should == @infinity + (@infinity - @frac_2).should == @infinity + (@infinity - @two).should == @infinity + (@infinity - @one_minus).should == @infinity - describe "with Object" do - it "tries to coerce the other operand to self" do - object = mock("Object") - object.should_receive(:coerce).with(@one).and_return([@one, BigDecimal("42")]) - (@one - object).should == BigDecimal("-41") + (@zero - @infinity).should == @infinity_minus + (@frac_2 - @infinity).should == @infinity_minus + (@two - @infinity).should == @infinity_minus + (@one_minus - @infinity).should == @infinity_minus end - end + describe "with Object" do + it "tries to coerce the other operand to self" do + object = mock("Object") + object.should_receive(:coerce).with(@one).and_return([@one, BigDecimal("42")]) + (@one - object).should == BigDecimal("-41") + end + end + + end end diff --git a/spec/ruby/library/bigdecimal/mode_spec.rb b/spec/ruby/library/bigdecimal/mode_spec.rb index 73fa1a118eaf41..62aeb773573a8f 100644 --- a/spec/ruby/library/bigdecimal/mode_spec.rb +++ b/spec/ruby/library/bigdecimal/mode_spec.rb @@ -1,36 +1,39 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal.mode" do - #the default value of BigDecimal exception constants is false - after :each do - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false) - BigDecimal.mode(BigDecimal::EXCEPTION_UNDERFLOW, false) - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, false) - end +ruby_version_is ""..."3.4" do + require 'bigdecimal' - it "returns the appropriate value and continue the computation if the flag is false" do - BigDecimal("NaN").add(BigDecimal("1"),0).should.nan? - BigDecimal("0").add(BigDecimal("Infinity"),0).should == BigDecimal("Infinity") - BigDecimal("1").quo(BigDecimal("0")).should == BigDecimal("Infinity") - end + describe "BigDecimal.mode" do + #the default value of BigDecimal exception constants is false + after :each do + BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) + BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false) + BigDecimal.mode(BigDecimal::EXCEPTION_UNDERFLOW, false) + BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) + BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, false) + end - it "returns Infinity when too big" do - BigDecimal("1E11111111111111111111").should == BigDecimal("Infinity") - (BigDecimal("1E1000000000000000000")**10).should == BigDecimal("Infinity") - end + it "returns the appropriate value and continue the computation if the flag is false" do + BigDecimal("NaN").add(BigDecimal("1"),0).should.nan? + BigDecimal("0").add(BigDecimal("Infinity"),0).should == BigDecimal("Infinity") + BigDecimal("1").quo(BigDecimal("0")).should == BigDecimal("Infinity") + end + + it "returns Infinity when too big" do + BigDecimal("1E11111111111111111111").should == BigDecimal("Infinity") + (BigDecimal("1E1000000000000000000")**10).should == BigDecimal("Infinity") + end - it "raise an exception if the flag is true" do - BigDecimal.mode(BigDecimal::EXCEPTION_NaN, true) - -> { BigDecimal("NaN").add(BigDecimal("1"),0) }.should raise_error(FloatDomainError) - BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, true) - -> { BigDecimal("0").add(BigDecimal("Infinity"),0) }.should raise_error(FloatDomainError) - BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, true) - -> { BigDecimal("1").quo(BigDecimal("0")) }.should raise_error(FloatDomainError) - BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, true) - -> { BigDecimal("1E11111111111111111111") }.should raise_error(FloatDomainError) - -> { (BigDecimal("1E1000000000000000000")**10) }.should raise_error(FloatDomainError) + it "raise an exception if the flag is true" do + BigDecimal.mode(BigDecimal::EXCEPTION_NaN, true) + -> { BigDecimal("NaN").add(BigDecimal("1"),0) }.should raise_error(FloatDomainError) + BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, true) + -> { BigDecimal("0").add(BigDecimal("Infinity"),0) }.should raise_error(FloatDomainError) + BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, true) + -> { BigDecimal("1").quo(BigDecimal("0")) }.should raise_error(FloatDomainError) + BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, true) + -> { BigDecimal("1E11111111111111111111") }.should raise_error(FloatDomainError) + -> { (BigDecimal("1E1000000000000000000")**10) }.should raise_error(FloatDomainError) + end end end diff --git a/spec/ruby/library/bigdecimal/modulo_spec.rb b/spec/ruby/library/bigdecimal/modulo_spec.rb index 035d31bd9828e3..682b9ec334f6b4 100644 --- a/spec/ruby/library/bigdecimal/modulo_spec.rb +++ b/spec/ruby/library/bigdecimal/modulo_spec.rb @@ -1,12 +1,15 @@ require_relative '../../spec_helper' -require_relative 'shared/modulo' -describe "BigDecimal#%" do - it_behaves_like :bigdecimal_modulo, :% - it_behaves_like :bigdecimal_modulo_zerodivisionerror, :% -end +ruby_version_is ""..."3.4" do + require_relative 'shared/modulo' + + describe "BigDecimal#%" do + it_behaves_like :bigdecimal_modulo, :% + it_behaves_like :bigdecimal_modulo_zerodivisionerror, :% + end -describe "BigDecimal#modulo" do - it_behaves_like :bigdecimal_modulo, :modulo - it_behaves_like :bigdecimal_modulo_zerodivisionerror, :modulo + describe "BigDecimal#modulo" do + it_behaves_like :bigdecimal_modulo, :modulo + it_behaves_like :bigdecimal_modulo_zerodivisionerror, :modulo + end end diff --git a/spec/ruby/library/bigdecimal/mult_spec.rb b/spec/ruby/library/bigdecimal/mult_spec.rb index b7f8044b0b2202..29cb0c226d917b 100644 --- a/spec/ruby/library/bigdecimal/mult_spec.rb +++ b/spec/ruby/library/bigdecimal/mult_spec.rb @@ -1,32 +1,35 @@ require_relative '../../spec_helper' -require_relative 'shared/mult' -require 'bigdecimal' -describe "BigDecimal#mult" do - it_behaves_like :bigdecimal_mult, :mult, [10] -end - -describe "BigDecimal#mult" do - before :each do - @one = BigDecimal "1" - @e3_minus = BigDecimal("3E-20001") - @e3_plus = BigDecimal("3E20001") - @e = BigDecimal "1.00000000000000000000123456789" - @tolerance = @e.sub @one, 1000 - @tolerance2 = BigDecimal "30001E-20005" +ruby_version_is ""..."3.4" do + require_relative 'shared/mult' + require 'bigdecimal' + describe "BigDecimal#mult" do + it_behaves_like :bigdecimal_mult, :mult, [10] end - it "multiply self with other with (optional) precision" do - @e.mult(@one, 1).should be_close(@one, @tolerance) - @e3_minus.mult(@one, 1).should be_close(0, @tolerance2) - end + describe "BigDecimal#mult" do + before :each do + @one = BigDecimal "1" + @e3_minus = BigDecimal("3E-20001") + @e3_plus = BigDecimal("3E20001") + @e = BigDecimal "1.00000000000000000000123456789" + @tolerance = @e.sub @one, 1000 + @tolerance2 = BigDecimal "30001E-20005" + + end + + it "multiply self with other with (optional) precision" do + @e.mult(@one, 1).should be_close(@one, @tolerance) + @e3_minus.mult(@one, 1).should be_close(0, @tolerance2) + end - describe "with Object" do - it "tries to coerce the other operand to self" do - object = mock("Object") - object.should_receive(:coerce).with(@e3_minus).and_return([@e3_minus, @e3_plus]) - @e3_minus.mult(object, 1).should == BigDecimal("9") + describe "with Object" do + it "tries to coerce the other operand to self" do + object = mock("Object") + object.should_receive(:coerce).with(@e3_minus).and_return([@e3_minus, @e3_plus]) + @e3_minus.mult(object, 1).should == BigDecimal("9") + end end end end diff --git a/spec/ruby/library/bigdecimal/multiply_spec.rb b/spec/ruby/library/bigdecimal/multiply_spec.rb index a8ce1da32edc60..2887bcc5a928e0 100644 --- a/spec/ruby/library/bigdecimal/multiply_spec.rb +++ b/spec/ruby/library/bigdecimal/multiply_spec.rb @@ -1,41 +1,44 @@ require_relative '../../spec_helper' -require_relative 'shared/mult' -require 'bigdecimal' -describe "BigDecimal#*" do - it_behaves_like :bigdecimal_mult, :*, [] -end +ruby_version_is ""..."3.4" do + require_relative 'shared/mult' + require 'bigdecimal' -describe "BigDecimal#*" do - before :each do - @three = BigDecimal("3") - @e3_minus = BigDecimal("3E-20001") - @e3_plus = BigDecimal("3E20001") - @e = BigDecimal("1.00000000000000000000123456789") - @one = BigDecimal("1") + describe "BigDecimal#*" do + it_behaves_like :bigdecimal_mult, :*, [] end - it "multiply self with other" do - (@one * @one).should == @one - (@e3_minus * @e3_plus).should == BigDecimal("9") - # Can't do this till we implement ** - # (@e3_minus * @e3_minus).should == @e3_minus ** 2 - # So let's rewrite it as: - (@e3_minus * @e3_minus).should == BigDecimal("9E-40002") - (@e * @one).should == @e - end + describe "BigDecimal#*" do + before :each do + @three = BigDecimal("3") + @e3_minus = BigDecimal("3E-20001") + @e3_plus = BigDecimal("3E20001") + @e = BigDecimal("1.00000000000000000000123456789") + @one = BigDecimal("1") + end - describe "with Object" do - it "tries to coerce the other operand to self" do - object = mock("Object") - object.should_receive(:coerce).with(@e3_minus).and_return([@e3_minus, @e3_plus]) - (@e3_minus * object).should == BigDecimal("9") + it "multiply self with other" do + (@one * @one).should == @one + (@e3_minus * @e3_plus).should == BigDecimal("9") + # Can't do this till we implement ** + # (@e3_minus * @e3_minus).should == @e3_minus ** 2 + # So let's rewrite it as: + (@e3_minus * @e3_minus).should == BigDecimal("9E-40002") + (@e * @one).should == @e + end + + describe "with Object" do + it "tries to coerce the other operand to self" do + object = mock("Object") + object.should_receive(:coerce).with(@e3_minus).and_return([@e3_minus, @e3_plus]) + (@e3_minus * object).should == BigDecimal("9") + end end - end - describe "with Rational" do - it "produces a BigDecimal" do - (@three * Rational(500, 2)).should == BigDecimal("0.75e3") + describe "with Rational" do + it "produces a BigDecimal" do + (@three * Rational(500, 2)).should == BigDecimal("0.75e3") + end end end end diff --git a/spec/ruby/library/bigdecimal/nan_spec.rb b/spec/ruby/library/bigdecimal/nan_spec.rb index 9eaf69b6106c00..0839ed675df97b 100644 --- a/spec/ruby/library/bigdecimal/nan_spec.rb +++ b/spec/ruby/library/bigdecimal/nan_spec.rb @@ -1,23 +1,26 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal#nan?" do +ruby_version_is ""..."3.4" do + require 'bigdecimal' - it "returns true if self is not a number" do - BigDecimal("NaN").should.nan? - end + describe "BigDecimal#nan?" do - it "returns false if self is not a NaN" do - BigDecimal("Infinity").should_not.nan? - BigDecimal("-Infinity").should_not.nan? - BigDecimal("0").should_not.nan? - BigDecimal("+0").should_not.nan? - BigDecimal("-0").should_not.nan? - BigDecimal("2E40001").should_not.nan? - BigDecimal("3E-20001").should_not.nan? - BigDecimal("0E-200000000").should_not.nan? - BigDecimal("0E200000000000").should_not.nan? - BigDecimal("0.000000000000000000000000").should_not.nan? - end + it "returns true if self is not a number" do + BigDecimal("NaN").should.nan? + end + it "returns false if self is not a NaN" do + BigDecimal("Infinity").should_not.nan? + BigDecimal("-Infinity").should_not.nan? + BigDecimal("0").should_not.nan? + BigDecimal("+0").should_not.nan? + BigDecimal("-0").should_not.nan? + BigDecimal("2E40001").should_not.nan? + BigDecimal("3E-20001").should_not.nan? + BigDecimal("0E-200000000").should_not.nan? + BigDecimal("0E200000000000").should_not.nan? + BigDecimal("0.000000000000000000000000").should_not.nan? + end + + end end diff --git a/spec/ruby/library/bigdecimal/nonzero_spec.rb b/spec/ruby/library/bigdecimal/nonzero_spec.rb index f43c4393cd3045..895e8cc429f294 100644 --- a/spec/ruby/library/bigdecimal/nonzero_spec.rb +++ b/spec/ruby/library/bigdecimal/nonzero_spec.rb @@ -1,29 +1,32 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal#nonzero?" do +ruby_version_is ""..."3.4" do + require 'bigdecimal' - it "returns self if self doesn't equal zero" do - # documentation says, it returns true. (04/10/08) - e2_plus = BigDecimal("2E40001") - e3_minus = BigDecimal("3E-20001") - infinity = BigDecimal("Infinity") - infinity_minus = BigDecimal("-Infinity") - nan = BigDecimal("NaN") - infinity.nonzero?.should equal(infinity) - infinity_minus.nonzero?.should equal(infinity_minus) - nan.nonzero?.should equal(nan) - e3_minus.nonzero?.should equal(e3_minus) - e2_plus.nonzero?.should equal(e2_plus) - end + describe "BigDecimal#nonzero?" do - it "returns nil otherwise" do - # documentation states, it should return false. (04/10/08) - really_small_zero = BigDecimal("0E-200000000") - really_big_zero = BigDecimal("0E200000000000") - really_small_zero.nonzero?.should == nil - really_big_zero.nonzero?.should == nil - BigDecimal("0.000000000000000000000000").nonzero?.should == nil - end + it "returns self if self doesn't equal zero" do + # documentation says, it returns true. (04/10/08) + e2_plus = BigDecimal("2E40001") + e3_minus = BigDecimal("3E-20001") + infinity = BigDecimal("Infinity") + infinity_minus = BigDecimal("-Infinity") + nan = BigDecimal("NaN") + infinity.nonzero?.should equal(infinity) + infinity_minus.nonzero?.should equal(infinity_minus) + nan.nonzero?.should equal(nan) + e3_minus.nonzero?.should equal(e3_minus) + e2_plus.nonzero?.should equal(e2_plus) + end + it "returns nil otherwise" do + # documentation states, it should return false. (04/10/08) + really_small_zero = BigDecimal("0E-200000000") + really_big_zero = BigDecimal("0E200000000000") + really_small_zero.nonzero?.should == nil + really_big_zero.nonzero?.should == nil + BigDecimal("0.000000000000000000000000").nonzero?.should == nil + end + + end end diff --git a/spec/ruby/library/bigdecimal/plus_spec.rb b/spec/ruby/library/bigdecimal/plus_spec.rb index d1934841c8ded7..e1ae0e316382b8 100644 --- a/spec/ruby/library/bigdecimal/plus_spec.rb +++ b/spec/ruby/library/bigdecimal/plus_spec.rb @@ -1,54 +1,57 @@ require_relative '../../spec_helper' -require 'bigdecimal' - -describe "BigDecimal#+" do - - before :each do - @one = BigDecimal("1") - @zero = BigDecimal("0") - @two = BigDecimal("2") - @three = BigDecimal("3") - @ten = BigDecimal("10") - @eleven = BigDecimal("11") - @nan = BigDecimal("NaN") - @infinity = BigDecimal("Infinity") - @infinity_minus = BigDecimal("-Infinity") - @one_minus = BigDecimal("-1") - @frac_1 = BigDecimal("1E-99999") - @frac_2 = BigDecimal("0.9E-99999") - end - it "returns a + b" do - (@two + @one).should == @three - (@one + @two).should == @three - (@one + @one_minus).should == @zero - (@zero + @one).should == @one - (@ten + @one).should == @eleven - (@frac_1 + @frac_2).should == BigDecimal("1.9E-99999") - (@frac_2 + @frac_1).should == BigDecimal("1.9E-99999") - (@frac_1 + @frac_1).should == BigDecimal("2E-99999") - end +ruby_version_is ""..."3.4" do + require 'bigdecimal' - it "returns NaN if NaN is involved" do - (@one + @nan).should.nan? - (@nan + @one).should.nan? - end + describe "BigDecimal#+" do - it "returns Infinity or -Infinity if these are involved" do - (@zero + @infinity).should == @infinity - (@frac_2 + @infinity).should == @infinity - (@two + @infinity_minus).should == @infinity_minus - end + before :each do + @one = BigDecimal("1") + @zero = BigDecimal("0") + @two = BigDecimal("2") + @three = BigDecimal("3") + @ten = BigDecimal("10") + @eleven = BigDecimal("11") + @nan = BigDecimal("NaN") + @infinity = BigDecimal("Infinity") + @infinity_minus = BigDecimal("-Infinity") + @one_minus = BigDecimal("-1") + @frac_1 = BigDecimal("1E-99999") + @frac_2 = BigDecimal("0.9E-99999") + end - it "returns NaN if Infinity + (- Infinity)" do - (@infinity + @infinity_minus).should.nan? - end + it "returns a + b" do + (@two + @one).should == @three + (@one + @two).should == @three + (@one + @one_minus).should == @zero + (@zero + @one).should == @one + (@ten + @one).should == @eleven + (@frac_1 + @frac_2).should == BigDecimal("1.9E-99999") + (@frac_2 + @frac_1).should == BigDecimal("1.9E-99999") + (@frac_1 + @frac_1).should == BigDecimal("2E-99999") + end + + it "returns NaN if NaN is involved" do + (@one + @nan).should.nan? + (@nan + @one).should.nan? + end + + it "returns Infinity or -Infinity if these are involved" do + (@zero + @infinity).should == @infinity + (@frac_2 + @infinity).should == @infinity + (@two + @infinity_minus).should == @infinity_minus + end + + it "returns NaN if Infinity + (- Infinity)" do + (@infinity + @infinity_minus).should.nan? + end - describe "with Object" do - it "tries to coerce the other operand to self" do - object = mock("Object") - object.should_receive(:coerce).with(@one).and_return([@one, BigDecimal("42")]) - (@one + object).should == BigDecimal("43") + describe "with Object" do + it "tries to coerce the other operand to self" do + object = mock("Object") + object.should_receive(:coerce).with(@one).and_return([@one, BigDecimal("42")]) + (@one + object).should == BigDecimal("43") + end end end end diff --git a/spec/ruby/library/bigdecimal/power_spec.rb b/spec/ruby/library/bigdecimal/power_spec.rb index 63a45a18872470..6ab0b9f2ca15f1 100644 --- a/spec/ruby/library/bigdecimal/power_spec.rb +++ b/spec/ruby/library/bigdecimal/power_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require_relative 'shared/power' -describe "BigDecimal#power" do - it_behaves_like :bigdecimal_power, :power +ruby_version_is ""..."3.4" do + require_relative 'shared/power' + + describe "BigDecimal#power" do + it_behaves_like :bigdecimal_power, :power + end end diff --git a/spec/ruby/library/bigdecimal/precs_spec.rb b/spec/ruby/library/bigdecimal/precs_spec.rb index 5fda8d30879a56..d32778b5417af7 100644 --- a/spec/ruby/library/bigdecimal/precs_spec.rb +++ b/spec/ruby/library/bigdecimal/precs_spec.rb @@ -1,54 +1,57 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal#precs" do - before :each do - @infinity = BigDecimal("Infinity") - @infinity_neg = BigDecimal("-Infinity") - @nan = BigDecimal("NaN") - @zero = BigDecimal("0") - @zero_neg = BigDecimal("-0") +ruby_version_is ""..."3.4" do + require 'bigdecimal' - @arr = [BigDecimal("2E40001"), BigDecimal("3E-20001"),\ - @infinity, @infinity_neg, @nan, @zero, @zero_neg] - @precision = BigDecimal::BASE.to_s.length - 1 - end + describe "BigDecimal#precs" do + before :each do + @infinity = BigDecimal("Infinity") + @infinity_neg = BigDecimal("-Infinity") + @nan = BigDecimal("NaN") + @zero = BigDecimal("0") + @zero_neg = BigDecimal("-0") + + @arr = [BigDecimal("2E40001"), BigDecimal("3E-20001"),\ + @infinity, @infinity_neg, @nan, @zero, @zero_neg] + @precision = BigDecimal::BASE.to_s.length - 1 + end - it "returns array of two values" do - suppress_warning do - @arr.each do |x| - x.precs.kind_of?(Array).should == true - x.precs.size.should == 2 + it "returns array of two values" do + suppress_warning do + @arr.each do |x| + x.precs.kind_of?(Array).should == true + x.precs.size.should == 2 + end end end - end - it "returns Integers as array values" do - suppress_warning do - @arr.each do |x| - x.precs[0].kind_of?(Integer).should == true - x.precs[1].kind_of?(Integer).should == true + it "returns Integers as array values" do + suppress_warning do + @arr.each do |x| + x.precs[0].kind_of?(Integer).should == true + x.precs[1].kind_of?(Integer).should == true + end end end - end - it "returns the current value of significant digits as the first value" do - suppress_warning do - BigDecimal("3.14159").precs[0].should >= 6 - BigDecimal('1').precs[0].should == BigDecimal('1' + '0' * 100).precs[0] - [@infinity, @infinity_neg, @nan, @zero, @zero_neg].each do |value| - value.precs[0].should <= @precision + it "returns the current value of significant digits as the first value" do + suppress_warning do + BigDecimal("3.14159").precs[0].should >= 6 + BigDecimal('1').precs[0].should == BigDecimal('1' + '0' * 100).precs[0] + [@infinity, @infinity_neg, @nan, @zero, @zero_neg].each do |value| + value.precs[0].should <= @precision + end end end - end - it "returns the maximum number of significant digits as the second value" do - suppress_warning do - BigDecimal("3.14159").precs[1].should >= 6 - BigDecimal('1').precs[1].should >= 1 - BigDecimal('1' + '0' * 100).precs[1].should >= 101 - [@infinity, @infinity_neg, @nan, @zero, @zero_neg].each do |value| - value.precs[1].should >= 1 + it "returns the maximum number of significant digits as the second value" do + suppress_warning do + BigDecimal("3.14159").precs[1].should >= 6 + BigDecimal('1').precs[1].should >= 1 + BigDecimal('1' + '0' * 100).precs[1].should >= 101 + [@infinity, @infinity_neg, @nan, @zero, @zero_neg].each do |value| + value.precs[1].should >= 1 + end end end end diff --git a/spec/ruby/library/bigdecimal/quo_spec.rb b/spec/ruby/library/bigdecimal/quo_spec.rb index 65a4330303d5ef..b839c380b480eb 100644 --- a/spec/ruby/library/bigdecimal/quo_spec.rb +++ b/spec/ruby/library/bigdecimal/quo_spec.rb @@ -1,12 +1,15 @@ require_relative '../../spec_helper' -require_relative 'shared/quo' -require 'bigdecimal' -describe "BigDecimal#quo" do - it_behaves_like :bigdecimal_quo, :quo, [] +ruby_version_is ""..."3.4" do + require_relative 'shared/quo' + require 'bigdecimal' - it "returns NaN if NaN is involved" do - BigDecimal("1").quo(BigDecimal("NaN")).should.nan? - BigDecimal("NaN").quo(BigDecimal("1")).should.nan? + describe "BigDecimal#quo" do + it_behaves_like :bigdecimal_quo, :quo, [] + + it "returns NaN if NaN is involved" do + BigDecimal("1").quo(BigDecimal("NaN")).should.nan? + BigDecimal("NaN").quo(BigDecimal("1")).should.nan? + end end end diff --git a/spec/ruby/library/bigdecimal/remainder_spec.rb b/spec/ruby/library/bigdecimal/remainder_spec.rb index bac5f37ba968c1..dde0a5bc2dda6f 100644 --- a/spec/ruby/library/bigdecimal/remainder_spec.rb +++ b/spec/ruby/library/bigdecimal/remainder_spec.rb @@ -1,94 +1,97 @@ require_relative '../../spec_helper' -require 'bigdecimal' - -describe "BigDecimal#remainder" do - - before :each do - @zero = BigDecimal("0") - @one = BigDecimal("1") - @three = BigDecimal("3") - @mixed = BigDecimal("1.23456789") - @pos_int = BigDecimal("2E5555") - @neg_int = BigDecimal("-2E5555") - @pos_frac = BigDecimal("2E-9999") - @neg_frac = BigDecimal("-2E-9999") - @nan = BigDecimal("NaN") - @infinity = BigDecimal("Infinity") - @infinity_minus = BigDecimal("-Infinity") - @one_minus = BigDecimal("-1") - @frac_1 = BigDecimal("1E-99999") - @frac_2 = BigDecimal("0.9E-99999") - end - it "it equals modulo, if both values are of same sign" do - BigDecimal('1234567890123456789012345679').remainder(BigDecimal('1')).should == @zero - BigDecimal('123456789').remainder(BigDecimal('333333333333333333333333333E-50')).should == BigDecimal('0.12233333333333333333345679E-24') +ruby_version_is ""..."3.4" do + require 'bigdecimal' - @mixed.remainder(@pos_frac).should == @mixed % @pos_frac - @pos_int.remainder(@pos_frac).should == @pos_int % @pos_frac - @neg_frac.remainder(@neg_int).should == @neg_frac % @neg_int - @neg_int.remainder(@neg_frac).should == @neg_int % @neg_frac - end + describe "BigDecimal#remainder" do - it "means self-arg*(self/arg).truncate" do - @mixed.remainder(@neg_frac).should == @mixed - @neg_frac * (@mixed / @neg_frac).truncate - @pos_int.remainder(@neg_frac).should == @pos_int - @neg_frac * (@pos_int / @neg_frac).truncate - @neg_frac.remainder(@pos_int).should == @neg_frac - @pos_int * (@neg_frac / @pos_int).truncate - @neg_int.remainder(@pos_frac).should == @neg_int - @pos_frac * (@neg_int / @pos_frac).truncate - end + before :each do + @zero = BigDecimal("0") + @one = BigDecimal("1") + @three = BigDecimal("3") + @mixed = BigDecimal("1.23456789") + @pos_int = BigDecimal("2E5555") + @neg_int = BigDecimal("-2E5555") + @pos_frac = BigDecimal("2E-9999") + @neg_frac = BigDecimal("-2E-9999") + @nan = BigDecimal("NaN") + @infinity = BigDecimal("Infinity") + @infinity_minus = BigDecimal("-Infinity") + @one_minus = BigDecimal("-1") + @frac_1 = BigDecimal("1E-99999") + @frac_2 = BigDecimal("0.9E-99999") + end - it "returns NaN used with zero" do - @mixed.remainder(@zero).should.nan? - @zero.remainder(@zero).should.nan? - end + it "it equals modulo, if both values are of same sign" do + BigDecimal('1234567890123456789012345679').remainder(BigDecimal('1')).should == @zero + BigDecimal('123456789').remainder(BigDecimal('333333333333333333333333333E-50')).should == BigDecimal('0.12233333333333333333345679E-24') - it "returns zero if used on zero" do - @zero.remainder(@mixed).should == @zero - end + @mixed.remainder(@pos_frac).should == @mixed % @pos_frac + @pos_int.remainder(@pos_frac).should == @pos_int % @pos_frac + @neg_frac.remainder(@neg_int).should == @neg_frac % @neg_int + @neg_int.remainder(@neg_frac).should == @neg_int % @neg_frac + end - it "returns NaN if NaN is involved" do - @nan.remainder(@nan).should.nan? - @nan.remainder(@one).should.nan? - @one.remainder(@nan).should.nan? - @infinity.remainder(@nan).should.nan? - @nan.remainder(@infinity).should.nan? - end + it "means self-arg*(self/arg).truncate" do + @mixed.remainder(@neg_frac).should == @mixed - @neg_frac * (@mixed / @neg_frac).truncate + @pos_int.remainder(@neg_frac).should == @pos_int - @neg_frac * (@pos_int / @neg_frac).truncate + @neg_frac.remainder(@pos_int).should == @neg_frac - @pos_int * (@neg_frac / @pos_int).truncate + @neg_int.remainder(@pos_frac).should == @neg_int - @pos_frac * (@neg_int / @pos_frac).truncate + end - version_is BigDecimal::VERSION, ""..."3.1.4" do #ruby_version_is ""..."3.3" do - it "returns NaN if Infinity is involved" do - @infinity.remainder(@infinity).should.nan? - @infinity.remainder(@one).should.nan? - @infinity.remainder(@mixed).should.nan? - @infinity.remainder(@one_minus).should.nan? - @infinity.remainder(@frac_1).should.nan? - @one.remainder(@infinity).should.nan? - - @infinity_minus.remainder(@infinity_minus).should.nan? - @infinity_minus.remainder(@one).should.nan? - @one.remainder(@infinity_minus).should.nan? - @frac_2.remainder(@infinity_minus).should.nan? - - @infinity.remainder(@infinity_minus).should.nan? - @infinity_minus.remainder(@infinity).should.nan? + it "returns NaN used with zero" do + @mixed.remainder(@zero).should.nan? + @zero.remainder(@zero).should.nan? end - end - it "coerces arguments to BigDecimal if possible" do - @three.remainder(2).should == @one - end + it "returns zero if used on zero" do + @zero.remainder(@mixed).should == @zero + end - describe "with Object" do - it "tries to coerce the other operand to self" do - object = mock("Object") - object.should_receive(:coerce).with(@three).and_return([@three, 2]) - @three.remainder(object).should == @one + it "returns NaN if NaN is involved" do + @nan.remainder(@nan).should.nan? + @nan.remainder(@one).should.nan? + @one.remainder(@nan).should.nan? + @infinity.remainder(@nan).should.nan? + @nan.remainder(@infinity).should.nan? end - end - it "raises TypeError if the argument cannot be coerced to BigDecimal" do - -> { - @one.remainder('2') - }.should raise_error(TypeError) - end + version_is BigDecimal::VERSION, ""..."3.1.4" do #ruby_version_is ""..."3.3" do + it "returns NaN if Infinity is involved" do + @infinity.remainder(@infinity).should.nan? + @infinity.remainder(@one).should.nan? + @infinity.remainder(@mixed).should.nan? + @infinity.remainder(@one_minus).should.nan? + @infinity.remainder(@frac_1).should.nan? + @one.remainder(@infinity).should.nan? + + @infinity_minus.remainder(@infinity_minus).should.nan? + @infinity_minus.remainder(@one).should.nan? + @one.remainder(@infinity_minus).should.nan? + @frac_2.remainder(@infinity_minus).should.nan? + + @infinity.remainder(@infinity_minus).should.nan? + @infinity_minus.remainder(@infinity).should.nan? + end + end + + it "coerces arguments to BigDecimal if possible" do + @three.remainder(2).should == @one + end + + describe "with Object" do + it "tries to coerce the other operand to self" do + object = mock("Object") + object.should_receive(:coerce).with(@three).and_return([@three, 2]) + @three.remainder(object).should == @one + end + end + it "raises TypeError if the argument cannot be coerced to BigDecimal" do + -> { + @one.remainder('2') + }.should raise_error(TypeError) + end + + end end diff --git a/spec/ruby/library/bigdecimal/round_spec.rb b/spec/ruby/library/bigdecimal/round_spec.rb index fba52df65d3b51..2c966ab44457fb 100644 --- a/spec/ruby/library/bigdecimal/round_spec.rb +++ b/spec/ruby/library/bigdecimal/round_spec.rb @@ -1,242 +1,245 @@ require_relative '../../spec_helper' -require 'bigdecimal' - -describe "BigDecimal#round" do - before :each do - @one = BigDecimal("1") - @two = BigDecimal("2") - @three = BigDecimal("3") - - @neg_one = BigDecimal("-1") - @neg_two = BigDecimal("-2") - @neg_three = BigDecimal("-3") - - @p1_50 = BigDecimal("1.50") - @p1_51 = BigDecimal("1.51") - @p1_49 = BigDecimal("1.49") - @n1_50 = BigDecimal("-1.50") - @n1_51 = BigDecimal("-1.51") - @n1_49 = BigDecimal("-1.49") - - @p2_50 = BigDecimal("2.50") - @p2_51 = BigDecimal("2.51") - @p2_49 = BigDecimal("2.49") - @n2_50 = BigDecimal("-2.50") - @n2_51 = BigDecimal("-2.51") - @n2_49 = BigDecimal("-2.49") - end - after :each do - BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_UP) - end +ruby_version_is ""..."3.4" do + require 'bigdecimal' + + describe "BigDecimal#round" do + before :each do + @one = BigDecimal("1") + @two = BigDecimal("2") + @three = BigDecimal("3") + + @neg_one = BigDecimal("-1") + @neg_two = BigDecimal("-2") + @neg_three = BigDecimal("-3") + + @p1_50 = BigDecimal("1.50") + @p1_51 = BigDecimal("1.51") + @p1_49 = BigDecimal("1.49") + @n1_50 = BigDecimal("-1.50") + @n1_51 = BigDecimal("-1.51") + @n1_49 = BigDecimal("-1.49") + + @p2_50 = BigDecimal("2.50") + @p2_51 = BigDecimal("2.51") + @p2_49 = BigDecimal("2.49") + @n2_50 = BigDecimal("-2.50") + @n2_51 = BigDecimal("-2.51") + @n2_49 = BigDecimal("-2.49") + end - it "uses default rounding method unless given" do - @p1_50.round(0).should == @two - @p1_51.round(0).should == @two - @p1_49.round(0).should == @one - @n1_50.round(0).should == @neg_two - @n1_51.round(0).should == @neg_two - @n1_49.round(0).should == @neg_one - - @p2_50.round(0).should == @three - @p2_51.round(0).should == @three - @p2_49.round(0).should == @two - @n2_50.round(0).should == @neg_three - @n2_51.round(0).should == @neg_three - @n2_49.round(0).should == @neg_two - - BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_DOWN) - - @p1_50.round(0).should == @one - @p1_51.round(0).should == @one - @p1_49.round(0).should == @one - @n1_50.round(0).should == @neg_one - @n1_51.round(0).should == @neg_one - @n1_49.round(0).should == @neg_one - - @p2_50.round(0).should == @two - @p2_51.round(0).should == @two - @p2_49.round(0).should == @two - @n2_50.round(0).should == @neg_two - @n2_51.round(0).should == @neg_two - @n2_49.round(0).should == @neg_two - end + after :each do + BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_UP) + end - ["BigDecimal::ROUND_UP", ":up"].each do |way| - describe way do - it "rounds values away from zero" do - mode = eval(way) - - @p1_50.round(0, mode).should == @two - @p1_51.round(0, mode).should == @two - @p1_49.round(0, mode).should == @two - @n1_50.round(0, mode).should == @neg_two - @n1_51.round(0, mode).should == @neg_two - @n1_49.round(0, mode).should == @neg_two - - @p2_50.round(0, mode).should == @three - @p2_51.round(0, mode).should == @three - @p2_49.round(0, mode).should == @three - @n2_50.round(0, mode).should == @neg_three - @n2_51.round(0, mode).should == @neg_three - @n2_49.round(0, mode).should == @neg_three + it "uses default rounding method unless given" do + @p1_50.round(0).should == @two + @p1_51.round(0).should == @two + @p1_49.round(0).should == @one + @n1_50.round(0).should == @neg_two + @n1_51.round(0).should == @neg_two + @n1_49.round(0).should == @neg_one + + @p2_50.round(0).should == @three + @p2_51.round(0).should == @three + @p2_49.round(0).should == @two + @n2_50.round(0).should == @neg_three + @n2_51.round(0).should == @neg_three + @n2_49.round(0).should == @neg_two + + BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_DOWN) + + @p1_50.round(0).should == @one + @p1_51.round(0).should == @one + @p1_49.round(0).should == @one + @n1_50.round(0).should == @neg_one + @n1_51.round(0).should == @neg_one + @n1_49.round(0).should == @neg_one + + @p2_50.round(0).should == @two + @p2_51.round(0).should == @two + @p2_49.round(0).should == @two + @n2_50.round(0).should == @neg_two + @n2_51.round(0).should == @neg_two + @n2_49.round(0).should == @neg_two + end + + ["BigDecimal::ROUND_UP", ":up"].each do |way| + describe way do + it "rounds values away from zero" do + mode = eval(way) + + @p1_50.round(0, mode).should == @two + @p1_51.round(0, mode).should == @two + @p1_49.round(0, mode).should == @two + @n1_50.round(0, mode).should == @neg_two + @n1_51.round(0, mode).should == @neg_two + @n1_49.round(0, mode).should == @neg_two + + @p2_50.round(0, mode).should == @three + @p2_51.round(0, mode).should == @three + @p2_49.round(0, mode).should == @three + @n2_50.round(0, mode).should == @neg_three + @n2_51.round(0, mode).should == @neg_three + @n2_49.round(0, mode).should == @neg_three + end end end - end - ["BigDecimal::ROUND_DOWN", ":down", ":truncate"].each do |way| - describe way do - it "rounds values towards zero" do - mode = eval(way) - - @p1_50.round(0, mode).should == @one - @p1_51.round(0, mode).should == @one - @p1_49.round(0, mode).should == @one - @n1_50.round(0, mode).should == @neg_one - @n1_51.round(0, mode).should == @neg_one - @n1_49.round(0, mode).should == @neg_one - - @p2_50.round(0, mode).should == @two - @p2_51.round(0, mode).should == @two - @p2_49.round(0, mode).should == @two - @n2_50.round(0, mode).should == @neg_two - @n2_51.round(0, mode).should == @neg_two - @n2_49.round(0, mode).should == @neg_two + ["BigDecimal::ROUND_DOWN", ":down", ":truncate"].each do |way| + describe way do + it "rounds values towards zero" do + mode = eval(way) + + @p1_50.round(0, mode).should == @one + @p1_51.round(0, mode).should == @one + @p1_49.round(0, mode).should == @one + @n1_50.round(0, mode).should == @neg_one + @n1_51.round(0, mode).should == @neg_one + @n1_49.round(0, mode).should == @neg_one + + @p2_50.round(0, mode).should == @two + @p2_51.round(0, mode).should == @two + @p2_49.round(0, mode).should == @two + @n2_50.round(0, mode).should == @neg_two + @n2_51.round(0, mode).should == @neg_two + @n2_49.round(0, mode).should == @neg_two + end end end - end - ["BigDecimal::ROUND_HALF_UP", ":half_up", ":default"].each do |way| - describe way do - it "rounds values >= 5 up, otherwise down" do - mode = eval(way) - - @p1_50.round(0, mode).should == @two - @p1_51.round(0, mode).should == @two - @p1_49.round(0, mode).should == @one - @n1_50.round(0, mode).should == @neg_two - @n1_51.round(0, mode).should == @neg_two - @n1_49.round(0, mode).should == @neg_one - - @p2_50.round(0, mode).should == @three - @p2_51.round(0, mode).should == @three - @p2_49.round(0, mode).should == @two - @n2_50.round(0, mode).should == @neg_three - @n2_51.round(0, mode).should == @neg_three - @n2_49.round(0, mode).should == @neg_two + ["BigDecimal::ROUND_HALF_UP", ":half_up", ":default"].each do |way| + describe way do + it "rounds values >= 5 up, otherwise down" do + mode = eval(way) + + @p1_50.round(0, mode).should == @two + @p1_51.round(0, mode).should == @two + @p1_49.round(0, mode).should == @one + @n1_50.round(0, mode).should == @neg_two + @n1_51.round(0, mode).should == @neg_two + @n1_49.round(0, mode).should == @neg_one + + @p2_50.round(0, mode).should == @three + @p2_51.round(0, mode).should == @three + @p2_49.round(0, mode).should == @two + @n2_50.round(0, mode).should == @neg_three + @n2_51.round(0, mode).should == @neg_three + @n2_49.round(0, mode).should == @neg_two + end end end - end - ["BigDecimal::ROUND_HALF_DOWN", ":half_down"].each do |way| - describe way do - it "rounds values > 5 up, otherwise down" do - mode = eval(way) - - @p1_50.round(0, mode).should == @one - @p1_51.round(0, mode).should == @two - @p1_49.round(0, mode).should == @one - @n1_50.round(0, mode).should == @neg_one - @n1_51.round(0, mode).should == @neg_two - @n1_49.round(0, mode).should == @neg_one - - @p2_50.round(0, mode).should == @two - @p2_51.round(0, mode).should == @three - @p2_49.round(0, mode).should == @two - @n2_50.round(0, mode).should == @neg_two - @n2_51.round(0, mode).should == @neg_three - @n2_49.round(0, mode).should == @neg_two + ["BigDecimal::ROUND_HALF_DOWN", ":half_down"].each do |way| + describe way do + it "rounds values > 5 up, otherwise down" do + mode = eval(way) + + @p1_50.round(0, mode).should == @one + @p1_51.round(0, mode).should == @two + @p1_49.round(0, mode).should == @one + @n1_50.round(0, mode).should == @neg_one + @n1_51.round(0, mode).should == @neg_two + @n1_49.round(0, mode).should == @neg_one + + @p2_50.round(0, mode).should == @two + @p2_51.round(0, mode).should == @three + @p2_49.round(0, mode).should == @two + @n2_50.round(0, mode).should == @neg_two + @n2_51.round(0, mode).should == @neg_three + @n2_49.round(0, mode).should == @neg_two + end end end - end - ["BigDecimal::ROUND_CEILING", ":ceiling", ":ceil"].each do |way| - describe way do - it "rounds values towards +infinity" do - mode = eval(way) - - @p1_50.round(0, mode).should == @two - @p1_51.round(0, mode).should == @two - @p1_49.round(0, mode).should == @two - @n1_50.round(0, mode).should == @neg_one - @n1_51.round(0, mode).should == @neg_one - @n1_49.round(0, mode).should == @neg_one - - @p2_50.round(0, mode).should == @three - @p2_51.round(0, mode).should == @three - @p2_49.round(0, mode).should == @three - @n2_50.round(0, mode).should == @neg_two - @n2_51.round(0, mode).should == @neg_two - @n2_49.round(0, mode).should == @neg_two + ["BigDecimal::ROUND_CEILING", ":ceiling", ":ceil"].each do |way| + describe way do + it "rounds values towards +infinity" do + mode = eval(way) + + @p1_50.round(0, mode).should == @two + @p1_51.round(0, mode).should == @two + @p1_49.round(0, mode).should == @two + @n1_50.round(0, mode).should == @neg_one + @n1_51.round(0, mode).should == @neg_one + @n1_49.round(0, mode).should == @neg_one + + @p2_50.round(0, mode).should == @three + @p2_51.round(0, mode).should == @three + @p2_49.round(0, mode).should == @three + @n2_50.round(0, mode).should == @neg_two + @n2_51.round(0, mode).should == @neg_two + @n2_49.round(0, mode).should == @neg_two + end end end - end - ["BigDecimal::ROUND_FLOOR", ":floor"].each do |way| - describe way do - it "rounds values towards -infinity" do - mode = eval(way) - - @p1_50.round(0, mode).should == @one - @p1_51.round(0, mode).should == @one - @p1_49.round(0, mode).should == @one - @n1_50.round(0, mode).should == @neg_two - @n1_51.round(0, mode).should == @neg_two - @n1_49.round(0, mode).should == @neg_two - - @p2_50.round(0, mode).should == @two - @p2_51.round(0, mode).should == @two - @p2_49.round(0, mode).should == @two - @n2_50.round(0, mode).should == @neg_three - @n2_51.round(0, mode).should == @neg_three - @n2_49.round(0, mode).should == @neg_three + ["BigDecimal::ROUND_FLOOR", ":floor"].each do |way| + describe way do + it "rounds values towards -infinity" do + mode = eval(way) + + @p1_50.round(0, mode).should == @one + @p1_51.round(0, mode).should == @one + @p1_49.round(0, mode).should == @one + @n1_50.round(0, mode).should == @neg_two + @n1_51.round(0, mode).should == @neg_two + @n1_49.round(0, mode).should == @neg_two + + @p2_50.round(0, mode).should == @two + @p2_51.round(0, mode).should == @two + @p2_49.round(0, mode).should == @two + @n2_50.round(0, mode).should == @neg_three + @n2_51.round(0, mode).should == @neg_three + @n2_49.round(0, mode).should == @neg_three + end end end - end - ["BigDecimal::ROUND_HALF_EVEN", ":half_even", ":banker"].each do |way| - describe way do - it "rounds values > 5 up, < 5 down and == 5 towards even neighbor" do - mode = eval(way) - - @p1_50.round(0, mode).should == @two - @p1_51.round(0, mode).should == @two - @p1_49.round(0, mode).should == @one - @n1_50.round(0, mode).should == @neg_two - @n1_51.round(0, mode).should == @neg_two - @n1_49.round(0, mode).should == @neg_one - - @p2_50.round(0, mode).should == @two - @p2_51.round(0, mode).should == @three - @p2_49.round(0, mode).should == @two - @n2_50.round(0, mode).should == @neg_two - @n2_51.round(0, mode).should == @neg_three - @n2_49.round(0, mode).should == @neg_two + ["BigDecimal::ROUND_HALF_EVEN", ":half_even", ":banker"].each do |way| + describe way do + it "rounds values > 5 up, < 5 down and == 5 towards even neighbor" do + mode = eval(way) + + @p1_50.round(0, mode).should == @two + @p1_51.round(0, mode).should == @two + @p1_49.round(0, mode).should == @one + @n1_50.round(0, mode).should == @neg_two + @n1_51.round(0, mode).should == @neg_two + @n1_49.round(0, mode).should == @neg_one + + @p2_50.round(0, mode).should == @two + @p2_51.round(0, mode).should == @three + @p2_49.round(0, mode).should == @two + @n2_50.round(0, mode).should == @neg_two + @n2_51.round(0, mode).should == @neg_three + @n2_49.round(0, mode).should == @neg_two + end end end - end - it 'raise exception, if self is special value' do - -> { BigDecimal('NaN').round }.should raise_error(FloatDomainError) - -> { BigDecimal('Infinity').round }.should raise_error(FloatDomainError) - -> { BigDecimal('-Infinity').round }.should raise_error(FloatDomainError) - end + it 'raise exception, if self is special value' do + -> { BigDecimal('NaN').round }.should raise_error(FloatDomainError) + -> { BigDecimal('Infinity').round }.should raise_error(FloatDomainError) + -> { BigDecimal('-Infinity').round }.should raise_error(FloatDomainError) + end - it 'do not raise exception, if self is special value and precision is given' do - -> { BigDecimal('NaN').round(2) }.should_not raise_error(FloatDomainError) - -> { BigDecimal('Infinity').round(2) }.should_not raise_error(FloatDomainError) - -> { BigDecimal('-Infinity').round(2) }.should_not raise_error(FloatDomainError) - end + it 'do not raise exception, if self is special value and precision is given' do + -> { BigDecimal('NaN').round(2) }.should_not raise_error(FloatDomainError) + -> { BigDecimal('Infinity').round(2) }.should_not raise_error(FloatDomainError) + -> { BigDecimal('-Infinity').round(2) }.should_not raise_error(FloatDomainError) + end - version_is BigDecimal::VERSION, ''...'3.1.3' do #ruby_version_is ''...'3.2' do - it 'raise for a non-existent round mode' do - -> { @p1_50.round(0, :nonsense) }.should raise_error(ArgumentError, "invalid rounding mode") + version_is BigDecimal::VERSION, ''...'3.1.3' do #ruby_version_is ''...'3.2' do + it 'raise for a non-existent round mode' do + -> { @p1_50.round(0, :nonsense) }.should raise_error(ArgumentError, "invalid rounding mode") + end end - end - version_is BigDecimal::VERSION, '3.1.3' do #ruby_version_is '3.2' do - it 'raise for a non-existent round mode' do - -> { @p1_50.round(0, :nonsense) }.should raise_error(ArgumentError, "invalid rounding mode (nonsense)") + version_is BigDecimal::VERSION, '3.1.3' do #ruby_version_is '3.2' do + it 'raise for a non-existent round mode' do + -> { @p1_50.round(0, :nonsense) }.should raise_error(ArgumentError, "invalid rounding mode (nonsense)") + end end end end diff --git a/spec/ruby/library/bigdecimal/sign_spec.rb b/spec/ruby/library/bigdecimal/sign_spec.rb index ae2c28e9fd2e14..c43ac05393e85a 100644 --- a/spec/ruby/library/bigdecimal/sign_spec.rb +++ b/spec/ruby/library/bigdecimal/sign_spec.rb @@ -1,46 +1,49 @@ require_relative '../../spec_helper' -require 'bigdecimal' - -describe "BigDecimal#sign" do - - it "defines several constants for signs" do - # are these really correct? - BigDecimal::SIGN_POSITIVE_INFINITE.should == 3 - BigDecimal::SIGN_NEGATIVE_INFINITE.should == -3 - BigDecimal::SIGN_POSITIVE_ZERO.should == 1 - BigDecimal::SIGN_NEGATIVE_ZERO.should == -1 - BigDecimal::SIGN_POSITIVE_FINITE.should == 2 - BigDecimal::SIGN_NEGATIVE_FINITE.should == -2 - end - it "returns positive value if BigDecimal greater than 0" do - BigDecimal("1").sign.should == BigDecimal::SIGN_POSITIVE_FINITE - BigDecimal("1E-20000000").sign.should == BigDecimal::SIGN_POSITIVE_FINITE - BigDecimal("1E200000000").sign.should == BigDecimal::SIGN_POSITIVE_FINITE - BigDecimal("Infinity").sign.should == BigDecimal::SIGN_POSITIVE_INFINITE - end +ruby_version_is ""..."3.4" do + require 'bigdecimal' + + describe "BigDecimal#sign" do + + it "defines several constants for signs" do + # are these really correct? + BigDecimal::SIGN_POSITIVE_INFINITE.should == 3 + BigDecimal::SIGN_NEGATIVE_INFINITE.should == -3 + BigDecimal::SIGN_POSITIVE_ZERO.should == 1 + BigDecimal::SIGN_NEGATIVE_ZERO.should == -1 + BigDecimal::SIGN_POSITIVE_FINITE.should == 2 + BigDecimal::SIGN_NEGATIVE_FINITE.should == -2 + end + + it "returns positive value if BigDecimal greater than 0" do + BigDecimal("1").sign.should == BigDecimal::SIGN_POSITIVE_FINITE + BigDecimal("1E-20000000").sign.should == BigDecimal::SIGN_POSITIVE_FINITE + BigDecimal("1E200000000").sign.should == BigDecimal::SIGN_POSITIVE_FINITE + BigDecimal("Infinity").sign.should == BigDecimal::SIGN_POSITIVE_INFINITE + end + + it "returns negative value if BigDecimal less than 0" do + BigDecimal("-1").sign.should == BigDecimal::SIGN_NEGATIVE_FINITE + BigDecimal("-1E-9990000").sign.should == BigDecimal::SIGN_NEGATIVE_FINITE + BigDecimal("-1E20000000").sign.should == BigDecimal::SIGN_NEGATIVE_FINITE + BigDecimal("-Infinity").sign.should == BigDecimal::SIGN_NEGATIVE_INFINITE + end + + it "returns positive zero if BigDecimal equals positive zero" do + BigDecimal("0").sign.should == BigDecimal::SIGN_POSITIVE_ZERO + BigDecimal("0E-200000000").sign.should == BigDecimal::SIGN_POSITIVE_ZERO + BigDecimal("0E200000000").sign.should == BigDecimal::SIGN_POSITIVE_ZERO + end + + it "returns negative zero if BigDecimal equals negative zero" do + BigDecimal("-0").sign.should == BigDecimal::SIGN_NEGATIVE_ZERO + BigDecimal("-0E-200000000").sign.should == BigDecimal::SIGN_NEGATIVE_ZERO + BigDecimal("-0E200000000").sign.should == BigDecimal::SIGN_NEGATIVE_ZERO + end + + it "returns BigDecimal::SIGN_NaN if BigDecimal is NaN" do + BigDecimal("NaN").sign.should == BigDecimal::SIGN_NaN + end - it "returns negative value if BigDecimal less than 0" do - BigDecimal("-1").sign.should == BigDecimal::SIGN_NEGATIVE_FINITE - BigDecimal("-1E-9990000").sign.should == BigDecimal::SIGN_NEGATIVE_FINITE - BigDecimal("-1E20000000").sign.should == BigDecimal::SIGN_NEGATIVE_FINITE - BigDecimal("-Infinity").sign.should == BigDecimal::SIGN_NEGATIVE_INFINITE end - - it "returns positive zero if BigDecimal equals positive zero" do - BigDecimal("0").sign.should == BigDecimal::SIGN_POSITIVE_ZERO - BigDecimal("0E-200000000").sign.should == BigDecimal::SIGN_POSITIVE_ZERO - BigDecimal("0E200000000").sign.should == BigDecimal::SIGN_POSITIVE_ZERO - end - - it "returns negative zero if BigDecimal equals negative zero" do - BigDecimal("-0").sign.should == BigDecimal::SIGN_NEGATIVE_ZERO - BigDecimal("-0E-200000000").sign.should == BigDecimal::SIGN_NEGATIVE_ZERO - BigDecimal("-0E200000000").sign.should == BigDecimal::SIGN_NEGATIVE_ZERO - end - - it "returns BigDecimal::SIGN_NaN if BigDecimal is NaN" do - BigDecimal("NaN").sign.should == BigDecimal::SIGN_NaN - end - end diff --git a/spec/ruby/library/bigdecimal/split_spec.rb b/spec/ruby/library/bigdecimal/split_spec.rb index f9b4bab5f7455b..a8752e3239124a 100644 --- a/spec/ruby/library/bigdecimal/split_spec.rb +++ b/spec/ruby/library/bigdecimal/split_spec.rb @@ -1,86 +1,89 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal#split" do +ruby_version_is ""..."3.4" do + require 'bigdecimal' - before :each do - @arr = BigDecimal("0.314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593014782083152134043E1").split - @arr_neg = BigDecimal("-0.314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593014782083152134043E1").split - @digits = "922337203685477580810101333333333333333333333333333" - @arr_big = BigDecimal("00#{@digits}000").split - @arr_big_neg = BigDecimal("-00#{@digits}000").split - @huge = BigDecimal('100000000000000000000000000000000000000000001E90000000').split + describe "BigDecimal#split" do - @infinity = BigDecimal("Infinity") - @infinity_neg = BigDecimal("-Infinity") - @nan = BigDecimal("NaN") - @zero = BigDecimal("0") - @zero_neg = BigDecimal("-0") - end + before :each do + @arr = BigDecimal("0.314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593014782083152134043E1").split + @arr_neg = BigDecimal("-0.314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593014782083152134043E1").split + @digits = "922337203685477580810101333333333333333333333333333" + @arr_big = BigDecimal("00#{@digits}000").split + @arr_big_neg = BigDecimal("-00#{@digits}000").split + @huge = BigDecimal('100000000000000000000000000000000000000000001E90000000').split - it "splits BigDecimal in an array with four values" do - @arr.size.should == 4 - end + @infinity = BigDecimal("Infinity") + @infinity_neg = BigDecimal("-Infinity") + @nan = BigDecimal("NaN") + @zero = BigDecimal("0") + @zero_neg = BigDecimal("-0") + end - it "first value: 1 for numbers > 0" do - @arr[0].should == 1 - @arr_big[0].should == 1 - @zero.split[0].should == 1 - @huge[0].should == 1 - BigDecimal("+0").split[0].should == 1 - BigDecimal("1E400").split[0].should == 1 - @infinity.split[0].should == 1 - end + it "splits BigDecimal in an array with four values" do + @arr.size.should == 4 + end - it "first value: -1 for numbers < 0" do - @arr_neg[0].should == -1 - @arr_big_neg[0].should == -1 - @zero_neg.split[0].should == -1 - BigDecimal("-1E400").split[0].should == -1 - @infinity_neg.split[0].should == -1 - end + it "first value: 1 for numbers > 0" do + @arr[0].should == 1 + @arr_big[0].should == 1 + @zero.split[0].should == 1 + @huge[0].should == 1 + BigDecimal("+0").split[0].should == 1 + BigDecimal("1E400").split[0].should == 1 + @infinity.split[0].should == 1 + end - it "first value: 0 if BigDecimal is NaN" do - BigDecimal("NaN").split[0].should == 0 - end + it "first value: -1 for numbers < 0" do + @arr_neg[0].should == -1 + @arr_big_neg[0].should == -1 + @zero_neg.split[0].should == -1 + BigDecimal("-1E400").split[0].should == -1 + @infinity_neg.split[0].should == -1 + end - it "second value: a string with the significant digits" do - string = "314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593014782083152134043" - @arr[1].should == string - @arr_big[1].should == @digits - @arr_big_neg[1].should == @digits - @huge[1].should == "100000000000000000000000000000000000000000001" - @infinity.split[1].should == @infinity.to_s - @nan.split[1].should == @nan.to_s - @infinity_neg.split[1].should == @infinity.to_s - @zero.split[1].should == "0" - BigDecimal("-0").split[1].should == "0" - end + it "first value: 0 if BigDecimal is NaN" do + BigDecimal("NaN").split[0].should == 0 + end - it "third value: the base (currently always ten)" do - @arr[2].should == 10 - @arr_neg[2].should == 10 - @arr_big[2].should == 10 - @arr_big_neg[2].should == 10 - @huge[2].should == 10 - @infinity.split[2].should == 10 - @nan.split[2].should == 10 - @infinity_neg.split[2].should == 10 - @zero.split[2].should == 10 - @zero_neg.split[2].should == 10 - end + it "second value: a string with the significant digits" do + string = "314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593014782083152134043" + @arr[1].should == string + @arr_big[1].should == @digits + @arr_big_neg[1].should == @digits + @huge[1].should == "100000000000000000000000000000000000000000001" + @infinity.split[1].should == @infinity.to_s + @nan.split[1].should == @nan.to_s + @infinity_neg.split[1].should == @infinity.to_s + @zero.split[1].should == "0" + BigDecimal("-0").split[1].should == "0" + end - it "fourth value: the exponent" do - @arr[3].should == 1 - @arr_neg[3].should == 1 - @arr_big[3].should == 54 - @arr_big_neg[3].should == 54 - @huge[3].should == 90000045 - @infinity.split[3].should == 0 - @nan.split[3].should == 0 - @infinity_neg.split[3].should == 0 - @zero.split[3].should == 0 - @zero_neg.split[3].should == 0 - end + it "third value: the base (currently always ten)" do + @arr[2].should == 10 + @arr_neg[2].should == 10 + @arr_big[2].should == 10 + @arr_big_neg[2].should == 10 + @huge[2].should == 10 + @infinity.split[2].should == 10 + @nan.split[2].should == 10 + @infinity_neg.split[2].should == 10 + @zero.split[2].should == 10 + @zero_neg.split[2].should == 10 + end + it "fourth value: the exponent" do + @arr[3].should == 1 + @arr_neg[3].should == 1 + @arr_big[3].should == 54 + @arr_big_neg[3].should == 54 + @huge[3].should == 90000045 + @infinity.split[3].should == 0 + @nan.split[3].should == 0 + @infinity_neg.split[3].should == 0 + @zero.split[3].should == 0 + @zero_neg.split[3].should == 0 + end + + end end diff --git a/spec/ruby/library/bigdecimal/sqrt_spec.rb b/spec/ruby/library/bigdecimal/sqrt_spec.rb index d149003b9f5a96..daf95dbfe94c9f 100644 --- a/spec/ruby/library/bigdecimal/sqrt_spec.rb +++ b/spec/ruby/library/bigdecimal/sqrt_spec.rb @@ -1,112 +1,115 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -require 'bigdecimal' - -describe "BigDecimal#sqrt" do - before :each do - @one = BigDecimal("1") - @zero = BigDecimal("0") - @zero_pos = BigDecimal("+0") - @zero_neg = BigDecimal("-0") - @two = BigDecimal("2.0") - @three = BigDecimal("3.0") - @nan = BigDecimal("NaN") - @infinity = BigDecimal("Infinity") - @infinity_minus = BigDecimal("-Infinity") - @one_minus = BigDecimal("-1") - @frac_1 = BigDecimal("1E-99999") - @frac_2 = BigDecimal("0.9E-99999") - end - - it "returns square root of 2 with desired precision" do - string = "1.41421356237309504880168872420969807856967187537694807317667973799073247846210703885038753432764157" - (1..99).each { |idx| - @two.sqrt(idx).should be_close(BigDecimal(string), BigDecimal("1E-#{idx-1}")) - } - end - - it "returns square root of 3 with desired precision" do - sqrt_3 = "1.732050807568877293527446341505872366942805253810380628055806979451933016908800037081146186757248575" - (1..99).each { |idx| - @three.sqrt(idx).should be_close(BigDecimal(sqrt_3), BigDecimal("1E-#{idx-1}")) - } - end - - it "returns square root of 121 with desired precision" do - BigDecimal('121').sqrt(5).should be_close(11, 0.00001) - end - - it "returns square root of 0.9E-99999 with desired precision" do - @frac_2.sqrt(1).to_s.should =~ /\A0\.3E-49999\z/i - end - - it "raises ArgumentError when no argument is given" do - -> { - @one.sqrt - }.should raise_error(ArgumentError) - end - - it "raises ArgumentError if a negative number is given" do - -> { - @one.sqrt(-1) - }.should raise_error(ArgumentError) - end - - it "raises ArgumentError if 2 arguments are given" do - -> { - @one.sqrt(1, 1) - }.should raise_error(ArgumentError) - end - it "raises TypeError if nil is given" do - -> { - @one.sqrt(nil) - }.should raise_error(TypeError) - end +ruby_version_is ""..."3.4" do + require_relative 'fixtures/classes' + require 'bigdecimal' + + describe "BigDecimal#sqrt" do + before :each do + @one = BigDecimal("1") + @zero = BigDecimal("0") + @zero_pos = BigDecimal("+0") + @zero_neg = BigDecimal("-0") + @two = BigDecimal("2.0") + @three = BigDecimal("3.0") + @nan = BigDecimal("NaN") + @infinity = BigDecimal("Infinity") + @infinity_minus = BigDecimal("-Infinity") + @one_minus = BigDecimal("-1") + @frac_1 = BigDecimal("1E-99999") + @frac_2 = BigDecimal("0.9E-99999") + end + + it "returns square root of 2 with desired precision" do + string = "1.41421356237309504880168872420969807856967187537694807317667973799073247846210703885038753432764157" + (1..99).each { |idx| + @two.sqrt(idx).should be_close(BigDecimal(string), BigDecimal("1E-#{idx-1}")) + } + end + + it "returns square root of 3 with desired precision" do + sqrt_3 = "1.732050807568877293527446341505872366942805253810380628055806979451933016908800037081146186757248575" + (1..99).each { |idx| + @three.sqrt(idx).should be_close(BigDecimal(sqrt_3), BigDecimal("1E-#{idx-1}")) + } + end + + it "returns square root of 121 with desired precision" do + BigDecimal('121').sqrt(5).should be_close(11, 0.00001) + end + + it "returns square root of 0.9E-99999 with desired precision" do + @frac_2.sqrt(1).to_s.should =~ /\A0\.3E-49999\z/i + end + + it "raises ArgumentError when no argument is given" do + -> { + @one.sqrt + }.should raise_error(ArgumentError) + end + + it "raises ArgumentError if a negative number is given" do + -> { + @one.sqrt(-1) + }.should raise_error(ArgumentError) + end + + it "raises ArgumentError if 2 arguments are given" do + -> { + @one.sqrt(1, 1) + }.should raise_error(ArgumentError) + end + + it "raises TypeError if nil is given" do + -> { + @one.sqrt(nil) + }.should raise_error(TypeError) + end + + it "raises TypeError if a string is given" do + -> { + @one.sqrt("stuff") + }.should raise_error(TypeError) + end + + it "raises TypeError if a plain Object is given" do + -> { + @one.sqrt(Object.new) + }.should raise_error(TypeError) + end + + it "returns 1 if precision is 0 or 1" do + @one.sqrt(1).should == 1 + @one.sqrt(0).should == 1 + end + + it "raises FloatDomainError on negative values" do + -> { + BigDecimal('-1').sqrt(10) + }.should raise_error(FloatDomainError) + end + + it "returns positive infinity for infinity" do + @infinity.sqrt(1).should == @infinity + end + + it "raises FloatDomainError for negative infinity" do + -> { + @infinity_minus.sqrt(1) + }.should raise_error(FloatDomainError) + end + + it "raises FloatDomainError for NaN" do + -> { + @nan.sqrt(1) + }.should raise_error(FloatDomainError) + end + + it "returns 0 for 0, +0.0 and -0.0" do + @zero.sqrt(1).should == 0 + @zero_pos.sqrt(1).should == 0 + @zero_neg.sqrt(1).should == 0 + end - it "raises TypeError if a string is given" do - -> { - @one.sqrt("stuff") - }.should raise_error(TypeError) end - - it "raises TypeError if a plain Object is given" do - -> { - @one.sqrt(Object.new) - }.should raise_error(TypeError) - end - - it "returns 1 if precision is 0 or 1" do - @one.sqrt(1).should == 1 - @one.sqrt(0).should == 1 - end - - it "raises FloatDomainError on negative values" do - -> { - BigDecimal('-1').sqrt(10) - }.should raise_error(FloatDomainError) - end - - it "returns positive infinity for infinity" do - @infinity.sqrt(1).should == @infinity - end - - it "raises FloatDomainError for negative infinity" do - -> { - @infinity_minus.sqrt(1) - }.should raise_error(FloatDomainError) - end - - it "raises FloatDomainError for NaN" do - -> { - @nan.sqrt(1) - }.should raise_error(FloatDomainError) - end - - it "returns 0 for 0, +0.0 and -0.0" do - @zero.sqrt(1).should == 0 - @zero_pos.sqrt(1).should == 0 - @zero_neg.sqrt(1).should == 0 - end - end diff --git a/spec/ruby/library/bigdecimal/sub_spec.rb b/spec/ruby/library/bigdecimal/sub_spec.rb index bddfec2186d6a4..aa4e2a86689115 100644 --- a/spec/ruby/library/bigdecimal/sub_spec.rb +++ b/spec/ruby/library/bigdecimal/sub_spec.rb @@ -1,70 +1,73 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal#sub" do +ruby_version_is ""..."3.4" do + require 'bigdecimal' - before :each do - @one = BigDecimal("1") - @zero = BigDecimal("0") - @two = BigDecimal("2") - @three = BigDecimal("3") - @nan = BigDecimal("NaN") - @infinity = BigDecimal("Infinity") - @infinity_minus = BigDecimal("-Infinity") - @one_minus = BigDecimal("-1") - @frac_1 = BigDecimal("1E-99999") - @frac_2 = BigDecimal("0.9E-99999") - @frac_3 = BigDecimal("12345E10") - @frac_4 = BigDecimal("98765E10") - end + describe "BigDecimal#sub" do - it "returns a - b with given precision" do - # documentation states, that precision is optional - # but implementation raises ArgumentError if not given. + before :each do + @one = BigDecimal("1") + @zero = BigDecimal("0") + @two = BigDecimal("2") + @three = BigDecimal("3") + @nan = BigDecimal("NaN") + @infinity = BigDecimal("Infinity") + @infinity_minus = BigDecimal("-Infinity") + @one_minus = BigDecimal("-1") + @frac_1 = BigDecimal("1E-99999") + @frac_2 = BigDecimal("0.9E-99999") + @frac_3 = BigDecimal("12345E10") + @frac_4 = BigDecimal("98765E10") + end - @two.sub(@one, 1).should == @one - @one.sub(@two, 1).should == @one_minus - @one.sub(@one_minus, 1).should == @two - @frac_2.sub(@frac_1, 1000000).should == BigDecimal("-0.1E-99999") - @frac_2.sub(@frac_1, 1).should == BigDecimal("-0.1E-99999") - # the above two examples puzzle me. - in_arow_one = BigDecimal("1.23456789") - in_arow_two = BigDecimal("1.2345678") - in_arow_one.sub(in_arow_two, 10).should == BigDecimal("0.9E-7") - @two.sub(@two,1).should == @zero - @frac_1.sub(@frac_1, 1000000).should == @zero - end + it "returns a - b with given precision" do + # documentation states, that precision is optional + # but implementation raises ArgumentError if not given. - describe "with Object" do - it "tries to coerce the other operand to self" do - object = mock("Object") - object.should_receive(:coerce).with(@frac_3).and_return([@frac_3, @frac_4]) - @frac_3.sub(object, 1).should == BigDecimal("-0.9E15") + @two.sub(@one, 1).should == @one + @one.sub(@two, 1).should == @one_minus + @one.sub(@one_minus, 1).should == @two + @frac_2.sub(@frac_1, 1000000).should == BigDecimal("-0.1E-99999") + @frac_2.sub(@frac_1, 1).should == BigDecimal("-0.1E-99999") + # the above two examples puzzle me. + in_arow_one = BigDecimal("1.23456789") + in_arow_two = BigDecimal("1.2345678") + in_arow_one.sub(in_arow_two, 10).should == BigDecimal("0.9E-7") + @two.sub(@two,1).should == @zero + @frac_1.sub(@frac_1, 1000000).should == @zero end - end - describe "with Rational" do - it "produces a BigDecimal" do - (@three - Rational(500, 2)).should == BigDecimal('-0.247e3') + describe "with Object" do + it "tries to coerce the other operand to self" do + object = mock("Object") + object.should_receive(:coerce).with(@frac_3).and_return([@frac_3, @frac_4]) + @frac_3.sub(object, 1).should == BigDecimal("-0.9E15") + end end - end - it "returns NaN if NaN is involved" do - @one.sub(@nan, 1).should.nan? - @nan.sub(@one, 1).should.nan? - end + describe "with Rational" do + it "produces a BigDecimal" do + (@three - Rational(500, 2)).should == BigDecimal('-0.247e3') + end + end - it "returns NaN if both values are infinite with the same signs" do - @infinity.sub(@infinity, 1).should.nan? - @infinity_minus.sub(@infinity_minus, 1).should.nan? - end + it "returns NaN if NaN is involved" do + @one.sub(@nan, 1).should.nan? + @nan.sub(@one, 1).should.nan? + end - it "returns Infinity or -Infinity if these are involved" do - @infinity.sub(@infinity_minus, 1).should == @infinity - @infinity_minus.sub(@infinity, 1).should == @infinity_minus - @zero.sub(@infinity, 1).should == @infinity_minus - @frac_2.sub( @infinity, 1).should == @infinity_minus - @two.sub(@infinity, 1).should == @infinity_minus - end + it "returns NaN if both values are infinite with the same signs" do + @infinity.sub(@infinity, 1).should.nan? + @infinity_minus.sub(@infinity_minus, 1).should.nan? + end + it "returns Infinity or -Infinity if these are involved" do + @infinity.sub(@infinity_minus, 1).should == @infinity + @infinity_minus.sub(@infinity, 1).should == @infinity_minus + @zero.sub(@infinity, 1).should == @infinity_minus + @frac_2.sub( @infinity, 1).should == @infinity_minus + @two.sub(@infinity, 1).should == @infinity_minus + end + + end end diff --git a/spec/ruby/library/bigdecimal/to_d_spec.rb b/spec/ruby/library/bigdecimal/to_d_spec.rb index 50aea99bf7ecbe..ae2f11fe6df7e0 100644 --- a/spec/ruby/library/bigdecimal/to_d_spec.rb +++ b/spec/ruby/library/bigdecimal/to_d_spec.rb @@ -1,10 +1,13 @@ require_relative '../../spec_helper' -require 'bigdecimal' -require 'bigdecimal/util' -describe "Float#to_d" do - it "returns appropriate BigDecimal zero for signed zero" do - -0.0.to_d.sign.should == -1 - 0.0.to_d.sign.should == 1 +ruby_version_is ""..."3.4" do + require 'bigdecimal' + require 'bigdecimal/util' + + describe "Float#to_d" do + it "returns appropriate BigDecimal zero for signed zero" do + -0.0.to_d.sign.should == -1 + 0.0.to_d.sign.should == 1 + end end end diff --git a/spec/ruby/library/bigdecimal/to_f_spec.rb b/spec/ruby/library/bigdecimal/to_f_spec.rb index 84d4d49de23c15..c91e123dbfac18 100644 --- a/spec/ruby/library/bigdecimal/to_f_spec.rb +++ b/spec/ruby/library/bigdecimal/to_f_spec.rb @@ -1,54 +1,57 @@ require_relative '../../spec_helper' -require 'bigdecimal' - -describe "BigDecimal#to_f" do - before :each do - @one = BigDecimal("1") - @zero = BigDecimal("0") - @zero_pos = BigDecimal("+0") - @zero_neg = BigDecimal("-0") - @two = BigDecimal("2") - @three = BigDecimal("3") - @nan = BigDecimal("NaN") - @infinity = BigDecimal("Infinity") - @infinity_minus = BigDecimal("-Infinity") - @one_minus = BigDecimal("-1") - @frac_1 = BigDecimal("1E-99999") - @frac_2 = BigDecimal("0.9E-99999") - @vals = [@one, @zero, @two, @three, @frac_1, @frac_2] - @spec_vals = [@zero_pos, @zero_neg, @nan, @infinity, @infinity_minus] - end - - it "returns number of type float" do - BigDecimal("3.14159").to_f.should be_kind_of(Float) - @vals.each { |val| val.to_f.should be_kind_of(Float) } - @spec_vals.each { |val| val.to_f.should be_kind_of(Float) } - end - - it "rounds correctly to Float precision" do - bigdec = BigDecimal("3.141592653589793238462643383279502884197169399375") - bigdec.to_f.should be_close(3.14159265358979, TOLERANCE) - @one.to_f.should == 1.0 - @two.to_f.should == 2.0 - @three.to_f.should be_close(3.0, TOLERANCE) - @one_minus.to_f.should == -1.0 - - # regression test for [ruby-talk:338957] - BigDecimal("10.03").to_f.should == 10.03 - end - - it "properly handles special values" do - @zero.to_f.should == 0 - @zero.to_f.to_s.should == "0.0" - - @nan.to_f.should.nan? - - @infinity.to_f.infinite?.should == 1 - @infinity_minus.to_f.infinite?.should == -1 - end - it "remembers negative zero when converted to float" do - @zero_neg.to_f.should == 0 - @zero_neg.to_f.to_s.should == "-0.0" +ruby_version_is ""..."3.4" do + require 'bigdecimal' + + describe "BigDecimal#to_f" do + before :each do + @one = BigDecimal("1") + @zero = BigDecimal("0") + @zero_pos = BigDecimal("+0") + @zero_neg = BigDecimal("-0") + @two = BigDecimal("2") + @three = BigDecimal("3") + @nan = BigDecimal("NaN") + @infinity = BigDecimal("Infinity") + @infinity_minus = BigDecimal("-Infinity") + @one_minus = BigDecimal("-1") + @frac_1 = BigDecimal("1E-99999") + @frac_2 = BigDecimal("0.9E-99999") + @vals = [@one, @zero, @two, @three, @frac_1, @frac_2] + @spec_vals = [@zero_pos, @zero_neg, @nan, @infinity, @infinity_minus] + end + + it "returns number of type float" do + BigDecimal("3.14159").to_f.should be_kind_of(Float) + @vals.each { |val| val.to_f.should be_kind_of(Float) } + @spec_vals.each { |val| val.to_f.should be_kind_of(Float) } + end + + it "rounds correctly to Float precision" do + bigdec = BigDecimal("3.141592653589793238462643383279502884197169399375") + bigdec.to_f.should be_close(3.14159265358979, TOLERANCE) + @one.to_f.should == 1.0 + @two.to_f.should == 2.0 + @three.to_f.should be_close(3.0, TOLERANCE) + @one_minus.to_f.should == -1.0 + + # regression test for [ruby-talk:338957] + BigDecimal("10.03").to_f.should == 10.03 + end + + it "properly handles special values" do + @zero.to_f.should == 0 + @zero.to_f.to_s.should == "0.0" + + @nan.to_f.should.nan? + + @infinity.to_f.infinite?.should == 1 + @infinity_minus.to_f.infinite?.should == -1 + end + + it "remembers negative zero when converted to float" do + @zero_neg.to_f.should == 0 + @zero_neg.to_f.to_s.should == "-0.0" + end end end diff --git a/spec/ruby/library/bigdecimal/to_i_spec.rb b/spec/ruby/library/bigdecimal/to_i_spec.rb index 09481fce154915..08367374e2db8f 100644 --- a/spec/ruby/library/bigdecimal/to_i_spec.rb +++ b/spec/ruby/library/bigdecimal/to_i_spec.rb @@ -1,7 +1,10 @@ require_relative '../../spec_helper' -require_relative 'shared/to_int' -require 'bigdecimal' -describe "BigDecimal#to_i" do - it_behaves_like :bigdecimal_to_int, :to_i +ruby_version_is ""..."3.4" do + require_relative 'shared/to_int' + require 'bigdecimal' + + describe "BigDecimal#to_i" do + it_behaves_like :bigdecimal_to_int, :to_i + end end diff --git a/spec/ruby/library/bigdecimal/to_int_spec.rb b/spec/ruby/library/bigdecimal/to_int_spec.rb index 4df674984525ff..8ded7bcaf970bd 100644 --- a/spec/ruby/library/bigdecimal/to_int_spec.rb +++ b/spec/ruby/library/bigdecimal/to_int_spec.rb @@ -1,8 +1,11 @@ require_relative '../../spec_helper' -require_relative 'shared/to_int' -require 'bigdecimal' +ruby_version_is ""..."3.4" do + require_relative 'shared/to_int' + require 'bigdecimal' -describe "BigDecimal#to_int" do - it_behaves_like :bigdecimal_to_int, :to_int + + describe "BigDecimal#to_int" do + it_behaves_like :bigdecimal_to_int, :to_int + end end diff --git a/spec/ruby/library/bigdecimal/to_r_spec.rb b/spec/ruby/library/bigdecimal/to_r_spec.rb index c350beff08c765..0d787a2effdf8f 100644 --- a/spec/ruby/library/bigdecimal/to_r_spec.rb +++ b/spec/ruby/library/bigdecimal/to_r_spec.rb @@ -1,28 +1,31 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal#to_r" do +ruby_version_is ""..."3.4" do + require 'bigdecimal' - it "returns a Rational" do - BigDecimal("3.14159").to_r.should be_kind_of(Rational) - end + describe "BigDecimal#to_r" do - it "returns a Rational with bignum values" do - r = BigDecimal("3.141592653589793238462643").to_r - r.numerator.should eql(3141592653589793238462643) - r.denominator.should eql(1000000000000000000000000) - end + it "returns a Rational" do + BigDecimal("3.14159").to_r.should be_kind_of(Rational) + end - it "returns a Rational from a BigDecimal with an exponent" do - r = BigDecimal("1E2").to_r - r.numerator.should eql(100) - r.denominator.should eql(1) - end + it "returns a Rational with bignum values" do + r = BigDecimal("3.141592653589793238462643").to_r + r.numerator.should eql(3141592653589793238462643) + r.denominator.should eql(1000000000000000000000000) + end - it "returns a Rational from a negative BigDecimal with an exponent" do - r = BigDecimal("-1E2").to_r - r.numerator.should eql(-100) - r.denominator.should eql(1) - end + it "returns a Rational from a BigDecimal with an exponent" do + r = BigDecimal("1E2").to_r + r.numerator.should eql(100) + r.denominator.should eql(1) + end + + it "returns a Rational from a negative BigDecimal with an exponent" do + r = BigDecimal("-1E2").to_r + r.numerator.should eql(-100) + r.denominator.should eql(1) + end + end end diff --git a/spec/ruby/library/bigdecimal/to_s_spec.rb b/spec/ruby/library/bigdecimal/to_s_spec.rb index ba9f960eb32450..02f1ce0d3e1d67 100644 --- a/spec/ruby/library/bigdecimal/to_s_spec.rb +++ b/spec/ruby/library/bigdecimal/to_s_spec.rb @@ -1,100 +1,103 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal#to_s" do +ruby_version_is ""..."3.4" do + require 'bigdecimal' - before :each do - @bigdec_str = "3.14159265358979323846264338327950288419716939937" - @bigneg_str = "-3.1415926535897932384626433832795028841971693993" - @bigdec = BigDecimal(@bigdec_str) - @bigneg = BigDecimal(@bigneg_str) - @internal = Encoding.default_internal - end + describe "BigDecimal#to_s" do - after :each do - Encoding.default_internal = @internal - end + before :each do + @bigdec_str = "3.14159265358979323846264338327950288419716939937" + @bigneg_str = "-3.1415926535897932384626433832795028841971693993" + @bigdec = BigDecimal(@bigdec_str) + @bigneg = BigDecimal(@bigneg_str) + @internal = Encoding.default_internal + end - it "return type is of class String" do - @bigdec.to_s.kind_of?(String).should == true - @bigneg.to_s.kind_of?(String).should == true - end + after :each do + Encoding.default_internal = @internal + end - it "the default format looks like 0.xxxxenn" do - @bigdec.to_s.should =~ /^0\.[0-9]*e[0-9]*$/ - end + it "return type is of class String" do + @bigdec.to_s.kind_of?(String).should == true + @bigneg.to_s.kind_of?(String).should == true + end - it "does not add an exponent for zero values" do - BigDecimal("0").to_s.should == "0.0" - BigDecimal("+0").to_s.should == "0.0" - BigDecimal("-0").to_s.should == "-0.0" - end + it "the default format looks like 0.xxxxenn" do + @bigdec.to_s.should =~ /^0\.[0-9]*e[0-9]*$/ + end - it "takes an optional argument" do - -> {@bigdec.to_s("F")}.should_not raise_error() - end + it "does not add an exponent for zero values" do + BigDecimal("0").to_s.should == "0.0" + BigDecimal("+0").to_s.should == "0.0" + BigDecimal("-0").to_s.should == "-0.0" + end - it "starts with + if + is supplied and value is positive" do - @bigdec.to_s("+").should =~ /^\+.*/ - @bigneg.to_s("+").should_not =~ /^\+.*/ - end + it "takes an optional argument" do + -> {@bigdec.to_s("F")}.should_not raise_error() + end - it "inserts a space every n chars to fraction part, if integer n is supplied" do - re =\ - /\A0\.314 159 265 358 979 323 846 264 338 327 950 288 419 716 939 937E1\z/i - @bigdec.to_s(3).should =~ re - - str1 = '-123.45678 90123 45678 9' - BigDecimal("-123.45678901234567890").to_s('5F').should == str1 - # trailing zeroes removed - BigDecimal("1.00000000000").to_s('1F').should == "1.0" - # 0 is treated as no spaces - BigDecimal("1.2345").to_s('0F').should == "1.2345" - end + it "starts with + if + is supplied and value is positive" do + @bigdec.to_s("+").should =~ /^\+.*/ + @bigneg.to_s("+").should_not =~ /^\+.*/ + end - version_is BigDecimal::VERSION, "3.1.5" do #ruby_version_is '3.3' do - it "inserts a space every n chars to integer part, if integer n is supplied" do - BigDecimal('1000010').to_s('5F').should == "10 00010.0" + it "inserts a space every n chars to fraction part, if integer n is supplied" do + re =\ + /\A0\.314 159 265 358 979 323 846 264 338 327 950 288 419 716 939 937E1\z/i + @bigdec.to_s(3).should =~ re + + str1 = '-123.45678 90123 45678 9' + BigDecimal("-123.45678901234567890").to_s('5F').should == str1 + # trailing zeroes removed + BigDecimal("1.00000000000").to_s('1F').should == "1.0" + # 0 is treated as no spaces + BigDecimal("1.2345").to_s('0F').should == "1.2345" end - end - it "can return a leading space for values > 0" do - @bigdec.to_s(" F").should =~ /\ .*/ - @bigneg.to_s(" F").should_not =~ /\ .*/ - end + version_is BigDecimal::VERSION, "3.1.5" do #ruby_version_is '3.3' do + it "inserts a space every n chars to integer part, if integer n is supplied" do + BigDecimal('1000010').to_s('5F').should == "10 00010.0" + end + end - it "removes trailing spaces in floating point notation" do - BigDecimal('-123.45678901234567890').to_s('F').should == "-123.4567890123456789" - BigDecimal('1.2500').to_s('F').should == "1.25" - BigDecimal('0000.00000').to_s('F').should == "0.0" - BigDecimal('-00.000010000').to_s('F').should == "-0.00001" - BigDecimal("5.00000E-2").to_s("F").should == "0.05" + it "can return a leading space for values > 0" do + @bigdec.to_s(" F").should =~ /\ .*/ + @bigneg.to_s(" F").should_not =~ /\ .*/ + end - BigDecimal("500000").to_s("F").should == "500000.0" - BigDecimal("5E2").to_s("F").should == "500.0" - BigDecimal("-5E100").to_s("F").should == "-5" + "0" * 100 + ".0" - end + it "removes trailing spaces in floating point notation" do + BigDecimal('-123.45678901234567890').to_s('F').should == "-123.4567890123456789" + BigDecimal('1.2500').to_s('F').should == "1.25" + BigDecimal('0000.00000').to_s('F').should == "0.0" + BigDecimal('-00.000010000').to_s('F').should == "-0.00001" + BigDecimal("5.00000E-2").to_s("F").should == "0.05" - it "can use engineering notation" do - @bigdec.to_s("E").should =~ /^0\.[0-9]*E[0-9]*$/i - end + BigDecimal("500000").to_s("F").should == "500000.0" + BigDecimal("5E2").to_s("F").should == "500.0" + BigDecimal("-5E100").to_s("F").should == "-5" + "0" * 100 + ".0" + end - it "can use conventional floating point notation" do - %w[f F].each do |format_char| - @bigdec.to_s(format_char).should == @bigdec_str - @bigneg.to_s(format_char).should == @bigneg_str - str2 = "+123.45678901 23456789" - BigDecimal('123.45678901234567890').to_s("+8#{format_char}").should == str2 + it "can use engineering notation" do + @bigdec.to_s("E").should =~ /^0\.[0-9]*E[0-9]*$/i end - end - it "returns a String in US-ASCII encoding when Encoding.default_internal is nil" do - Encoding.default_internal = nil - BigDecimal('1.23').to_s.encoding.should equal(Encoding::US_ASCII) - end + it "can use conventional floating point notation" do + %w[f F].each do |format_char| + @bigdec.to_s(format_char).should == @bigdec_str + @bigneg.to_s(format_char).should == @bigneg_str + str2 = "+123.45678901 23456789" + BigDecimal('123.45678901234567890').to_s("+8#{format_char}").should == str2 + end + end - it "returns a String in US-ASCII encoding when Encoding.default_internal is not nil" do - Encoding.default_internal = Encoding::IBM437 - BigDecimal('1.23').to_s.encoding.should equal(Encoding::US_ASCII) + it "returns a String in US-ASCII encoding when Encoding.default_internal is nil" do + Encoding.default_internal = nil + BigDecimal('1.23').to_s.encoding.should equal(Encoding::US_ASCII) + end + + it "returns a String in US-ASCII encoding when Encoding.default_internal is not nil" do + Encoding.default_internal = Encoding::IBM437 + BigDecimal('1.23').to_s.encoding.should equal(Encoding::US_ASCII) + end end end diff --git a/spec/ruby/library/bigdecimal/truncate_spec.rb b/spec/ruby/library/bigdecimal/truncate_spec.rb index 4ad9eb92d1e760..fbb5b69779413d 100644 --- a/spec/ruby/library/bigdecimal/truncate_spec.rb +++ b/spec/ruby/library/bigdecimal/truncate_spec.rb @@ -1,81 +1,84 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal#truncate" do +ruby_version_is ""..."3.4" do + require 'bigdecimal' - before :each do - @arr = ['3.14159', '8.7', "0.314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593014782083152134043E1"] - @big = BigDecimal("123456.789") - @nan = BigDecimal('NaN') - @infinity = BigDecimal('Infinity') - @infinity_negative = BigDecimal('-Infinity') - end + describe "BigDecimal#truncate" do - it "returns value of type Integer." do - @arr.each do |x| - BigDecimal(x).truncate.kind_of?(Integer).should == true + before :each do + @arr = ['3.14159', '8.7', "0.314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593014782083152134043E1"] + @big = BigDecimal("123456.789") + @nan = BigDecimal('NaN') + @infinity = BigDecimal('Infinity') + @infinity_negative = BigDecimal('-Infinity') end - end - it "returns the integer part as a BigDecimal if no precision given" do - BigDecimal(@arr[0]).truncate.should == 3 - BigDecimal(@arr[1]).truncate.should == 8 - BigDecimal(@arr[2]).truncate.should == 3 - BigDecimal('0').truncate.should == 0 - BigDecimal('0.1').truncate.should == 0 - BigDecimal('-0.1').truncate.should == 0 - BigDecimal('1.5').truncate.should == 1 - BigDecimal('-1.5').truncate.should == -1 - BigDecimal('1E10').truncate.should == BigDecimal('1E10') - BigDecimal('-1E10').truncate.should == BigDecimal('-1E10') - BigDecimal('1.8888E10').truncate.should == BigDecimal('1.8888E10') - BigDecimal('-1E-1').truncate.should == 0 - end + it "returns value of type Integer." do + @arr.each do |x| + BigDecimal(x).truncate.kind_of?(Integer).should == true + end + end - it "returns value of given precision otherwise" do - BigDecimal('-1.55').truncate(1).should == BigDecimal('-1.5') - BigDecimal('1.55').truncate(1).should == BigDecimal('1.5') - BigDecimal(@arr[0]).truncate(2).should == BigDecimal("3.14") - BigDecimal('123.456').truncate(2).should == BigDecimal("123.45") - BigDecimal('123.456789').truncate(4).should == BigDecimal("123.4567") - BigDecimal('0.456789').truncate(10).should == BigDecimal("0.456789") - BigDecimal('-1E-1').truncate(1).should == BigDecimal('-0.1') - BigDecimal('-1E-1').truncate(2).should == BigDecimal('-0.1E0') - BigDecimal('-1E-1').truncate.should == BigDecimal('0') - BigDecimal('-1E-1').truncate(0).should == BigDecimal('0') - BigDecimal('-1E-1').truncate(-1).should == BigDecimal('0') - BigDecimal('-1E-1').truncate(-2).should == BigDecimal('0') + it "returns the integer part as a BigDecimal if no precision given" do + BigDecimal(@arr[0]).truncate.should == 3 + BigDecimal(@arr[1]).truncate.should == 8 + BigDecimal(@arr[2]).truncate.should == 3 + BigDecimal('0').truncate.should == 0 + BigDecimal('0.1').truncate.should == 0 + BigDecimal('-0.1').truncate.should == 0 + BigDecimal('1.5').truncate.should == 1 + BigDecimal('-1.5').truncate.should == -1 + BigDecimal('1E10').truncate.should == BigDecimal('1E10') + BigDecimal('-1E10').truncate.should == BigDecimal('-1E10') + BigDecimal('1.8888E10').truncate.should == BigDecimal('1.8888E10') + BigDecimal('-1E-1').truncate.should == 0 + end - BigDecimal(@arr[1]).truncate(1).should == BigDecimal("8.7") - BigDecimal(@arr[2]).truncate(100).should == BigDecimal(\ - "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679") - end + it "returns value of given precision otherwise" do + BigDecimal('-1.55').truncate(1).should == BigDecimal('-1.5') + BigDecimal('1.55').truncate(1).should == BigDecimal('1.5') + BigDecimal(@arr[0]).truncate(2).should == BigDecimal("3.14") + BigDecimal('123.456').truncate(2).should == BigDecimal("123.45") + BigDecimal('123.456789').truncate(4).should == BigDecimal("123.4567") + BigDecimal('0.456789').truncate(10).should == BigDecimal("0.456789") + BigDecimal('-1E-1').truncate(1).should == BigDecimal('-0.1') + BigDecimal('-1E-1').truncate(2).should == BigDecimal('-0.1E0') + BigDecimal('-1E-1').truncate.should == BigDecimal('0') + BigDecimal('-1E-1').truncate(0).should == BigDecimal('0') + BigDecimal('-1E-1').truncate(-1).should == BigDecimal('0') + BigDecimal('-1E-1').truncate(-2).should == BigDecimal('0') - it "sets n digits left of the decimal point to 0, if given n < 0" do - @big.truncate(-1).should == BigDecimal("123450.0") - @big.truncate(-2).should == BigDecimal("123400.0") - BigDecimal(@arr[2]).truncate(-1).should == 0 - end + BigDecimal(@arr[1]).truncate(1).should == BigDecimal("8.7") + BigDecimal(@arr[2]).truncate(100).should == BigDecimal(\ + "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679") + end - it "returns NaN if self is NaN" do - @nan.truncate(-1).should.nan? - @nan.truncate(+1).should.nan? - @nan.truncate(0).should.nan? - end + it "sets n digits left of the decimal point to 0, if given n < 0" do + @big.truncate(-1).should == BigDecimal("123450.0") + @big.truncate(-2).should == BigDecimal("123400.0") + BigDecimal(@arr[2]).truncate(-1).should == 0 + end - it "returns Infinity if self is infinite" do - @infinity.truncate(-1).should == @infinity - @infinity.truncate(+1).should == @infinity - @infinity.truncate(0).should == @infinity + it "returns NaN if self is NaN" do + @nan.truncate(-1).should.nan? + @nan.truncate(+1).should.nan? + @nan.truncate(0).should.nan? + end - @infinity_negative.truncate(-1).should == @infinity_negative - @infinity_negative.truncate(+1).should == @infinity_negative - @infinity_negative.truncate(0).should == @infinity_negative - end + it "returns Infinity if self is infinite" do + @infinity.truncate(-1).should == @infinity + @infinity.truncate(+1).should == @infinity + @infinity.truncate(0).should == @infinity - it "returns the same value if self is special value" do - -> { @nan.truncate }.should raise_error(FloatDomainError) - -> { @infinity.truncate }.should raise_error(FloatDomainError) - -> { @infinity_negative.truncate }.should raise_error(FloatDomainError) + @infinity_negative.truncate(-1).should == @infinity_negative + @infinity_negative.truncate(+1).should == @infinity_negative + @infinity_negative.truncate(0).should == @infinity_negative + end + + it "returns the same value if self is special value" do + -> { @nan.truncate }.should raise_error(FloatDomainError) + -> { @infinity.truncate }.should raise_error(FloatDomainError) + -> { @infinity_negative.truncate }.should raise_error(FloatDomainError) + end end end diff --git a/spec/ruby/library/bigdecimal/uminus_spec.rb b/spec/ruby/library/bigdecimal/uminus_spec.rb index c780cdfac5acae..612321915f325d 100644 --- a/spec/ruby/library/bigdecimal/uminus_spec.rb +++ b/spec/ruby/library/bigdecimal/uminus_spec.rb @@ -1,58 +1,61 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal#-@" do - before :each do - @one = BigDecimal("1") - @zero = BigDecimal("0") - @zero_pos = BigDecimal("+0") - @zero_neg = BigDecimal("-0") - @nan = BigDecimal("NaN") - @infinity = BigDecimal("Infinity") - @infinity_minus = BigDecimal("-Infinity") - @one_minus = BigDecimal("-1") - @frac_1 = BigDecimal("1E-99999") - @frac_2 = BigDecimal("0.9E-99999") - @big = BigDecimal("333E99999") - @big_neg = BigDecimal("-333E99999") - @values = [@one, @zero, @zero_pos, @zero_neg, @infinity, - @infinity_minus, @one_minus, @frac_1, @frac_2, @big, @big_neg] - end +ruby_version_is ""..."3.4" do + require 'bigdecimal' - it "negates self" do - @one.send(:-@).should == @one_minus - @one_minus.send(:-@).should == @one - @frac_1.send(:-@).should == BigDecimal("-1E-99999") - @frac_2.send(:-@).should == BigDecimal("-0.9E-99999") - @big.send(:-@).should == @big_neg - @big_neg.send(:-@).should == @big - BigDecimal("2.221").send(:-@).should == BigDecimal("-2.221") - BigDecimal("2E10000").send(:-@).should == BigDecimal("-2E10000") - some_number = BigDecimal("2455999221.5512") - some_number_neg = BigDecimal("-2455999221.5512") - some_number.send(:-@).should == some_number_neg - (-BigDecimal("-5.5")).should == BigDecimal("5.5") - another_number = BigDecimal("-8.551551551551551551") - another_number_pos = BigDecimal("8.551551551551551551") - another_number.send(:-@).should == another_number_pos - @values.each do |val| - (val.send(:-@).send(:-@)).should == val + describe "BigDecimal#-@" do + before :each do + @one = BigDecimal("1") + @zero = BigDecimal("0") + @zero_pos = BigDecimal("+0") + @zero_neg = BigDecimal("-0") + @nan = BigDecimal("NaN") + @infinity = BigDecimal("Infinity") + @infinity_minus = BigDecimal("-Infinity") + @one_minus = BigDecimal("-1") + @frac_1 = BigDecimal("1E-99999") + @frac_2 = BigDecimal("0.9E-99999") + @big = BigDecimal("333E99999") + @big_neg = BigDecimal("-333E99999") + @values = [@one, @zero, @zero_pos, @zero_neg, @infinity, + @infinity_minus, @one_minus, @frac_1, @frac_2, @big, @big_neg] end - end - it "properly handles special values" do - @infinity.send(:-@).should == @infinity_minus - @infinity_minus.send(:-@).should == @infinity - @infinity.send(:-@).infinite?.should == -1 - @infinity_minus.send(:-@).infinite?.should == 1 + it "negates self" do + @one.send(:-@).should == @one_minus + @one_minus.send(:-@).should == @one + @frac_1.send(:-@).should == BigDecimal("-1E-99999") + @frac_2.send(:-@).should == BigDecimal("-0.9E-99999") + @big.send(:-@).should == @big_neg + @big_neg.send(:-@).should == @big + BigDecimal("2.221").send(:-@).should == BigDecimal("-2.221") + BigDecimal("2E10000").send(:-@).should == BigDecimal("-2E10000") + some_number = BigDecimal("2455999221.5512") + some_number_neg = BigDecimal("-2455999221.5512") + some_number.send(:-@).should == some_number_neg + (-BigDecimal("-5.5")).should == BigDecimal("5.5") + another_number = BigDecimal("-8.551551551551551551") + another_number_pos = BigDecimal("8.551551551551551551") + another_number.send(:-@).should == another_number_pos + @values.each do |val| + (val.send(:-@).send(:-@)).should == val + end + end - @zero.send(:-@).should == @zero - @zero.send(:-@).sign.should == -1 - @zero_pos.send(:-@).should == @zero - @zero_pos.send(:-@).sign.should == -1 - @zero_neg.send(:-@).should == @zero - @zero_neg.send(:-@).sign.should == 1 + it "properly handles special values" do + @infinity.send(:-@).should == @infinity_minus + @infinity_minus.send(:-@).should == @infinity + @infinity.send(:-@).infinite?.should == -1 + @infinity_minus.send(:-@).infinite?.should == 1 - @nan.send(:-@).should.nan? + @zero.send(:-@).should == @zero + @zero.send(:-@).sign.should == -1 + @zero_pos.send(:-@).should == @zero + @zero_pos.send(:-@).sign.should == -1 + @zero_neg.send(:-@).should == @zero + @zero_neg.send(:-@).sign.should == 1 + + @nan.send(:-@).should.nan? + end end end diff --git a/spec/ruby/library/bigdecimal/uplus_spec.rb b/spec/ruby/library/bigdecimal/uplus_spec.rb index 77483046b749b2..9610593401cfab 100644 --- a/spec/ruby/library/bigdecimal/uplus_spec.rb +++ b/spec/ruby/library/bigdecimal/uplus_spec.rb @@ -1,17 +1,20 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal#+@" do - it "returns the same value with same sign (twos complement)" do - first = BigDecimal("34.56") - first.send(:+@).should == first - second = BigDecimal("-34.56") - second.send(:+@).should == second - third = BigDecimal("0.0") - third.send(:+@).should == third - fourth = BigDecimal("2E1000000") - fourth.send(:+@).should == fourth - fifth = BigDecimal("123456789E-1000000") - fifth.send(:+@).should == fifth +ruby_version_is ""..."3.4" do + require 'bigdecimal' + + describe "BigDecimal#+@" do + it "returns the same value with same sign (twos complement)" do + first = BigDecimal("34.56") + first.send(:+@).should == first + second = BigDecimal("-34.56") + second.send(:+@).should == second + third = BigDecimal("0.0") + third.send(:+@).should == third + fourth = BigDecimal("2E1000000") + fourth.send(:+@).should == fourth + fifth = BigDecimal("123456789E-1000000") + fifth.send(:+@).should == fifth + end end end diff --git a/spec/ruby/library/bigdecimal/util_spec.rb b/spec/ruby/library/bigdecimal/util_spec.rb index fc67fcf200bebd..4ef82935d15500 100644 --- a/spec/ruby/library/bigdecimal/util_spec.rb +++ b/spec/ruby/library/bigdecimal/util_spec.rb @@ -1,40 +1,43 @@ require_relative '../../spec_helper' -require 'bigdecimal' -require 'bigdecimal/util' -describe "BigDecimal's util method definitions" do - describe "#to_d" do - it "should define #to_d on Integer" do - 42.to_d.should == BigDecimal(42) - end +ruby_version_is ""..."3.4" do + require 'bigdecimal' + require 'bigdecimal/util' - it "should define #to_d on Float" do - 0.5.to_d.should == BigDecimal(0.5, Float::DIG) - 1.234.to_d(2).should == BigDecimal(1.234, 2) - end + describe "BigDecimal's util method definitions" do + describe "#to_d" do + it "should define #to_d on Integer" do + 42.to_d.should == BigDecimal(42) + end - it "should define #to_d on String" do - "0.5".to_d.should == BigDecimal(0.5, Float::DIG) - "45.67 degrees".to_d.should == BigDecimal(45.67, Float::DIG) - end + it "should define #to_d on Float" do + 0.5.to_d.should == BigDecimal(0.5, Float::DIG) + 1.234.to_d(2).should == BigDecimal(1.234, 2) + end - it "should define #to_d on BigDecimal" do - bd = BigDecimal("3.14") - bd.to_d.should equal(bd) - end + it "should define #to_d on String" do + "0.5".to_d.should == BigDecimal(0.5, Float::DIG) + "45.67 degrees".to_d.should == BigDecimal(45.67, Float::DIG) + end - it "should define #to_d on Rational" do - Rational(22, 7).to_d(3).should == BigDecimal(3.14, 3) - end + it "should define #to_d on BigDecimal" do + bd = BigDecimal("3.14") + bd.to_d.should equal(bd) + end + + it "should define #to_d on Rational" do + Rational(22, 7).to_d(3).should == BigDecimal(3.14, 3) + end - it "should define #to_d on nil" do - nil.to_d.should == BigDecimal(0) + it "should define #to_d on nil" do + nil.to_d.should == BigDecimal(0) + end end - end - describe "#to_digits" do - it "should define #to_digits on BigDecimal" do - BigDecimal("3.14").to_digits.should == "3.14" + describe "#to_digits" do + it "should define #to_digits on BigDecimal" do + BigDecimal("3.14").to_digits.should == "3.14" + end end end end diff --git a/spec/ruby/library/bigdecimal/zero_spec.rb b/spec/ruby/library/bigdecimal/zero_spec.rb index 2563210939e251..94bd7d1a40722c 100644 --- a/spec/ruby/library/bigdecimal/zero_spec.rb +++ b/spec/ruby/library/bigdecimal/zero_spec.rb @@ -1,27 +1,30 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal#zero?" do +ruby_version_is ""..."3.4" do + require 'bigdecimal' - it "returns true if self does equal zero" do - really_small_zero = BigDecimal("0E-200000000") - really_big_zero = BigDecimal("0E200000000000") - really_small_zero.should.zero? - really_big_zero.should.zero? - BigDecimal("0.000000000000000000000000").should.zero? - BigDecimal("0").should.zero? - BigDecimal("0E0").should.zero? - BigDecimal("+0").should.zero? - BigDecimal("-0").should.zero? - end + describe "BigDecimal#zero?" do - it "returns false otherwise" do - BigDecimal("0000000001").should_not.zero? - BigDecimal("2E40001").should_not.zero? - BigDecimal("3E-20001").should_not.zero? - BigDecimal("Infinity").should_not.zero? - BigDecimal("-Infinity").should_not.zero? - BigDecimal("NaN").should_not.zero? - end + it "returns true if self does equal zero" do + really_small_zero = BigDecimal("0E-200000000") + really_big_zero = BigDecimal("0E200000000000") + really_small_zero.should.zero? + really_big_zero.should.zero? + BigDecimal("0.000000000000000000000000").should.zero? + BigDecimal("0").should.zero? + BigDecimal("0E0").should.zero? + BigDecimal("+0").should.zero? + BigDecimal("-0").should.zero? + end + it "returns false otherwise" do + BigDecimal("0000000001").should_not.zero? + BigDecimal("2E40001").should_not.zero? + BigDecimal("3E-20001").should_not.zero? + BigDecimal("Infinity").should_not.zero? + BigDecimal("-Infinity").should_not.zero? + BigDecimal("NaN").should_not.zero? + end + + end end From 44d74f22c8da3c13aa5363769418e2f5fd29f65a Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 17 Jan 2024 13:50:48 +0900 Subject: [PATCH 269/640] Guard bigdecimal related examples spec/mspec/tool/wrap_with_guard.rb 'ruby_version_is ""..."3.4"' spec/ruby/core/integer/coerce_spec.rb spec/mspec/tool/wrap_with_guard.rb 'ruby_version_is ""..."3.4"' spec/ruby/shared/rational/coerce.rb spec/mspec/tool/wrap_with_guard.rb 'ruby_version_is ""..."3.4"' spec/ruby/library/bigmath/log_spec.rb and example of at_spec.rb --- spec/ruby/core/integer/coerce_spec.rb | 157 +++++++++++++------------- spec/ruby/core/time/at_spec.rb | 10 +- spec/ruby/library/bigmath/log_spec.rb | 15 ++- spec/ruby/shared/rational/coerce.rb | 53 +++++---- 4 files changed, 123 insertions(+), 112 deletions(-) diff --git a/spec/ruby/core/integer/coerce_spec.rb b/spec/ruby/core/integer/coerce_spec.rb index f1f32560323924..c967b0dea31a7a 100644 --- a/spec/ruby/core/integer/coerce_spec.rb +++ b/spec/ruby/core/integer/coerce_spec.rb @@ -1,104 +1,107 @@ require_relative '../../spec_helper' -require 'bigdecimal' - -describe "Integer#coerce" do - context "fixnum" do - describe "when given a Fixnum" do - it "returns an array containing two Fixnums" do - 1.coerce(2).should == [2, 1] - 1.coerce(2).map { |i| i.class }.should == [Integer, Integer] - end - end +ruby_version_is ""..."3.4" do - describe "when given a String" do - it "raises an ArgumentError when trying to coerce with a non-number String" do - -> { 1.coerce(":)") }.should raise_error(ArgumentError) + require 'bigdecimal' + + describe "Integer#coerce" do + context "fixnum" do + describe "when given a Fixnum" do + it "returns an array containing two Fixnums" do + 1.coerce(2).should == [2, 1] + 1.coerce(2).map { |i| i.class }.should == [Integer, Integer] + end end - it "returns an array containing two Floats" do - 1.coerce("2").should == [2.0, 1.0] - 1.coerce("-2").should == [-2.0, 1.0] + describe "when given a String" do + it "raises an ArgumentError when trying to coerce with a non-number String" do + -> { 1.coerce(":)") }.should raise_error(ArgumentError) + end + + it "returns an array containing two Floats" do + 1.coerce("2").should == [2.0, 1.0] + 1.coerce("-2").should == [-2.0, 1.0] + end end - end - it "raises a TypeError when trying to coerce with nil" do - -> { 1.coerce(nil) }.should raise_error(TypeError) - end + it "raises a TypeError when trying to coerce with nil" do + -> { 1.coerce(nil) }.should raise_error(TypeError) + end - it "tries to convert the given Object into a Float by using #to_f" do - (obj = mock('1.0')).should_receive(:to_f).and_return(1.0) - 2.coerce(obj).should == [1.0, 2.0] + it "tries to convert the given Object into a Float by using #to_f" do + (obj = mock('1.0')).should_receive(:to_f).and_return(1.0) + 2.coerce(obj).should == [1.0, 2.0] - (obj = mock('0')).should_receive(:to_f).and_return('0') - -> { 2.coerce(obj).should == [1.0, 2.0] }.should raise_error(TypeError) - end + (obj = mock('0')).should_receive(:to_f).and_return('0') + -> { 2.coerce(obj).should == [1.0, 2.0] }.should raise_error(TypeError) + end - it "raises a TypeError when given an Object that does not respond to #to_f" do - -> { 1.coerce(mock('x')) }.should raise_error(TypeError) - -> { 1.coerce(1..4) }.should raise_error(TypeError) - -> { 1.coerce(:test) }.should raise_error(TypeError) + it "raises a TypeError when given an Object that does not respond to #to_f" do + -> { 1.coerce(mock('x')) }.should raise_error(TypeError) + -> { 1.coerce(1..4) }.should raise_error(TypeError) + -> { 1.coerce(:test) }.should raise_error(TypeError) + end end - end - context "bignum" do - it "coerces other to a Bignum and returns [other, self] when passed a Fixnum" do - a = bignum_value - ary = a.coerce(2) + context "bignum" do + it "coerces other to a Bignum and returns [other, self] when passed a Fixnum" do + a = bignum_value + ary = a.coerce(2) - ary[0].should be_kind_of(Integer) - ary[1].should be_kind_of(Integer) - ary.should == [2, a] - end + ary[0].should be_kind_of(Integer) + ary[1].should be_kind_of(Integer) + ary.should == [2, a] + end - it "returns [other, self] when passed a Bignum" do - a = bignum_value - b = bignum_value - ary = a.coerce(b) + it "returns [other, self] when passed a Bignum" do + a = bignum_value + b = bignum_value + ary = a.coerce(b) - ary[0].should be_kind_of(Integer) - ary[1].should be_kind_of(Integer) - ary.should == [b, a] - end + ary[0].should be_kind_of(Integer) + ary[1].should be_kind_of(Integer) + ary.should == [b, a] + end - it "raises a TypeError when not passed a Fixnum or Bignum" do - a = bignum_value + it "raises a TypeError when not passed a Fixnum or Bignum" do + a = bignum_value - -> { a.coerce(nil) }.should raise_error(TypeError) - -> { a.coerce(mock('str')) }.should raise_error(TypeError) - -> { a.coerce(1..4) }.should raise_error(TypeError) - -> { a.coerce(:test) }.should raise_error(TypeError) - end + -> { a.coerce(nil) }.should raise_error(TypeError) + -> { a.coerce(mock('str')) }.should raise_error(TypeError) + -> { a.coerce(1..4) }.should raise_error(TypeError) + -> { a.coerce(:test) }.should raise_error(TypeError) + end - it "coerces both values to Floats and returns [other, self] when passed a Float" do - a = bignum_value - a.coerce(1.2).should == [1.2, a.to_f] - end + it "coerces both values to Floats and returns [other, self] when passed a Float" do + a = bignum_value + a.coerce(1.2).should == [1.2, a.to_f] + end - it "coerces both values to Floats and returns [other, self] when passed a String" do - a = bignum_value - a.coerce("123").should == [123.0, a.to_f] - end + it "coerces both values to Floats and returns [other, self] when passed a String" do + a = bignum_value + a.coerce("123").should == [123.0, a.to_f] + end - it "calls #to_f to coerce other to a Float" do - b = mock("bignum value") - b.should_receive(:to_f).and_return(1.2) + it "calls #to_f to coerce other to a Float" do + b = mock("bignum value") + b.should_receive(:to_f).and_return(1.2) - a = bignum_value - ary = a.coerce(b) + a = bignum_value + ary = a.coerce(b) - ary.should == [1.2, a.to_f] + ary.should == [1.2, a.to_f] + end end - end - context "bigdecimal" do - it "produces Floats" do - x, y = 3.coerce(BigDecimal("3.4")) - x.class.should == Float - x.should == 3.4 - y.class.should == Float - y.should == 3.0 + context "bigdecimal" do + it "produces Floats" do + x, y = 3.coerce(BigDecimal("3.4")) + x.class.should == Float + x.should == 3.4 + y.class.should == Float + y.should == 3.0 + end end - end + end end diff --git a/spec/ruby/core/time/at_spec.rb b/spec/ruby/core/time/at_spec.rb index 0459589f0192a9..25056f20115722 100644 --- a/spec/ruby/core/time/at_spec.rb +++ b/spec/ruby/core/time/at_spec.rb @@ -32,10 +32,12 @@ t2.nsec.should == t.nsec end - describe "passed BigDecimal" do - it "doesn't round input value" do - require 'bigdecimal' - Time.at(BigDecimal('1.1')).to_f.should == 1.1 + ruby_version_is ""..."3.4" do + describe "passed BigDecimal" do + it "doesn't round input value" do + require 'bigdecimal' + Time.at(BigDecimal('1.1')).to_f.should == 1.1 + end end end diff --git a/spec/ruby/library/bigmath/log_spec.rb b/spec/ruby/library/bigmath/log_spec.rb index 2ffbf8b6b9cbdf..22df38bb294ae0 100644 --- a/spec/ruby/library/bigmath/log_spec.rb +++ b/spec/ruby/library/bigmath/log_spec.rb @@ -1,10 +1,13 @@ require_relative '../../spec_helper' -require 'bigdecimal' -describe "BigDecimal#log" do - it "handles high-precision Rational arguments" do - result = BigDecimal('0.22314354220170971436137296411949880462556361100856391620766259404746040597133837784E0') - r = Rational(1_234_567_890, 987_654_321) - BigMath.log(r, 50).should == result +ruby_version_is ""..."3.4" do + require 'bigdecimal' + + describe "BigDecimal#log" do + it "handles high-precision Rational arguments" do + result = BigDecimal('0.22314354220170971436137296411949880462556361100856391620766259404746040597133837784E0') + r = Rational(1_234_567_890, 987_654_321) + BigMath.log(r, 50).should == result + end end end diff --git a/spec/ruby/shared/rational/coerce.rb b/spec/ruby/shared/rational/coerce.rb index ccc8901ba0a76c..1650668fe6e940 100644 --- a/spec/ruby/shared/rational/coerce.rb +++ b/spec/ruby/shared/rational/coerce.rb @@ -1,34 +1,37 @@ require_relative '../../spec_helper' -require 'bigdecimal' +ruby_version_is ""..."3.4" do -describe :rational_coerce, shared: true do - it "returns the passed argument, self as Float, when given a Float" do - result = Rational(3, 4).coerce(1.0) - result.should == [1.0, 0.75] - result.first.is_a?(Float).should be_true - result.last.is_a?(Float).should be_true - end + require 'bigdecimal' - it "returns the passed argument, self as Rational, when given an Integer" do - result = Rational(3, 4).coerce(10) - result.should == [Rational(10, 1), Rational(3, 4)] - result.first.is_a?(Rational).should be_true - result.last.is_a?(Rational).should be_true - end + describe :rational_coerce, shared: true do + it "returns the passed argument, self as Float, when given a Float" do + result = Rational(3, 4).coerce(1.0) + result.should == [1.0, 0.75] + result.first.is_a?(Float).should be_true + result.last.is_a?(Float).should be_true + end - it "coerces to Rational, when given a Complex" do - Rational(3, 4).coerce(Complex(5)).should == [Rational(5, 1), Rational(3, 4)] - Rational(12, 4).coerce(Complex(5, 1)).should == [Complex(5, 1), Complex(3)] - end + it "returns the passed argument, self as Rational, when given an Integer" do + result = Rational(3, 4).coerce(10) + result.should == [Rational(10, 1), Rational(3, 4)] + result.first.is_a?(Rational).should be_true + result.last.is_a?(Rational).should be_true + end - it "returns [argument, self] when given a Rational" do - Rational(3, 7).coerce(Rational(9, 2)).should == [Rational(9, 2), Rational(3, 7)] - end + it "coerces to Rational, when given a Complex" do + Rational(3, 4).coerce(Complex(5)).should == [Rational(5, 1), Rational(3, 4)] + Rational(12, 4).coerce(Complex(5, 1)).should == [Complex(5, 1), Complex(3)] + end + + it "returns [argument, self] when given a Rational" do + Rational(3, 7).coerce(Rational(9, 2)).should == [Rational(9, 2), Rational(3, 7)] + end - it "raises an error when passed a BigDecimal" do - -> { - Rational(500, 3).coerce(BigDecimal('166.666666666')) - }.should raise_error(TypeError, /BigDecimal can't be coerced into Rational/) + it "raises an error when passed a BigDecimal" do + -> { + Rational(500, 3).coerce(BigDecimal('166.666666666')) + }.should raise_error(TypeError, /BigDecimal can't be coerced into Rational/) + end end end From 7cb1125446a5f25a4c2d7163bfd2b41b811df467 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 17 Jan 2024 14:08:03 +0900 Subject: [PATCH 270/640] spec/mspec/tool/wrap_with_guard.rb 'ruby_version_is ""..."3.4"' spec/ruby/core/rational/coerce_spec.rb --- spec/ruby/core/rational/coerce_spec.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/spec/ruby/core/rational/coerce_spec.rb b/spec/ruby/core/rational/coerce_spec.rb index 9c0f05829b42e5..bba0c810cca331 100644 --- a/spec/ruby/core/rational/coerce_spec.rb +++ b/spec/ruby/core/rational/coerce_spec.rb @@ -1,6 +1,9 @@ require_relative "../../spec_helper" -require_relative '../../shared/rational/coerce' -describe "Rational#coerce" do - it_behaves_like :rational_coerce, :coerce +ruby_version_is ""..."3.4" do + require_relative '../../shared/rational/coerce' + + describe "Rational#coerce" do + it_behaves_like :rational_coerce, :coerce + end end From fd81c887f9067dbc3b594dfc7a23de1c35919daf Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 17 Jan 2024 13:24:58 +0900 Subject: [PATCH 271/640] Use fixed commit for failing result of test-bundled-gems https://github.com/ruby/ruby/actions/runs/7550805131/job/20557022764?pr=9573 https://github.com/ruby/bigdecimal/commit/338e896234bdcf672b91f2c2052527b09e2870f8 --- gems/bundled_gems | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gems/bundled_gems b/gems/bundled_gems index 042ca947e77d3b..cb1505a4c9b9f0 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -24,4 +24,4 @@ racc 1.7.3 https://github.com/ruby/racc mutex_m 0.2.0 https://github.com/ruby/mutex_m getoptlong 0.2.1 https://github.com/ruby/getoptlong base64 0.2.0 https://github.com/ruby/base64 -bigdecimal 3.1.5 https://github.com/ruby/bigdecimal +bigdecimal 3.1.5 https://github.com/ruby/bigdecimal 3d185d286dfca7bc0d3c4a9d56261b8b22fcf52c From 6ddd583ad2505a3a6d7a9eb4885ab9b857158f6e Mon Sep 17 00:00:00 2001 From: git Date: Wed, 17 Jan 2024 22:44:42 +0000 Subject: [PATCH 272/640] Update bundled gems list at fd81c887f9067dbc3b594dfc7a23de [ci skip] --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index f7c634425b5121..ec89a88c862318 100644 --- a/NEWS.md +++ b/NEWS.md @@ -48,6 +48,7 @@ The following bundled gems are promoted from default gems. * mutex_m 0.2.0 * getoptlong 0.2.1 * base64 0.2.0 +* bigdecimal 3.1.5 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. From 8370b3bc3255791004a273c8ea1d71ab0566b06d Mon Sep 17 00:00:00 2001 From: Kazuhiro NISHIYAMA Date: Thu, 18 Jan 2024 08:40:16 +0900 Subject: [PATCH 273/640] Add baseruby version message Because `--with-baseruby=/usr/bin/ruby` on macOS is Ruby 2.6, I was confused why `--with-baseruby` was ignored. --- tool/missing-baseruby.bat | 1 + 1 file changed, 1 insertion(+) diff --git a/tool/missing-baseruby.bat b/tool/missing-baseruby.bat index d6d66a4d86e894..b1c11aecb8c187 100755 --- a/tool/missing-baseruby.bat +++ b/tool/missing-baseruby.bat @@ -2,4 +2,5 @@ @echo off : " echo executable host ruby is required. use --with-baseruby option. +echo Note that BASERUBY must be Ruby 2.7.0 or later. exit 1 From 42177a8987c06678f0afed713457fa327d606c62 Mon Sep 17 00:00:00 2001 From: Kazuhiro NISHIYAMA Date: Thu, 18 Jan 2024 08:45:09 +0900 Subject: [PATCH 274/640] [DOC] Update ruby version in Building Ruby Dependencies --- doc/contributing/building_ruby.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/contributing/building_ruby.md b/doc/contributing/building_ruby.md index b2a7b007ebe981..411e9a60f957a8 100644 --- a/doc/contributing/building_ruby.md +++ b/doc/contributing/building_ruby.md @@ -17,7 +17,7 @@ * autoconf - 2.67 or later * gperf - 3.1 or later * Usually unneeded; only if you edit some source files using gperf - * ruby - 2.5 or later + * ruby - 2.7 or later * We can upgrade this version to system ruby version of the latest Ubuntu LTS. 2. Install optional, recommended dependencies: From af60cdf6747316b23bf254128d8472e6c3c0d969 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 18 Jan 2024 10:35:52 +0900 Subject: [PATCH 275/640] [ruby/io-console] Bump up version to 0.7.2 https://github.com/ruby/io-console/commit/1f2877a185 --- ext/io/console/console.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/io/console/console.c b/ext/io/console/console.c index 7859373438a99e..7130c29a8b5fae 100644 --- a/ext/io/console/console.c +++ b/ext/io/console/console.c @@ -4,7 +4,7 @@ */ static const char *const -IO_CONSOLE_VERSION = "0.7.2.dev.1"; +IO_CONSOLE_VERSION = "0.7.2"; #include "ruby.h" #include "ruby/io.h" From 4095191f2c037a665353caf8824c7f5eef67efe4 Mon Sep 17 00:00:00 2001 From: git Date: Thu, 18 Jan 2024 01:37:52 +0000 Subject: [PATCH 276/640] Update default gems list at af60cdf6747316b23bf254128d8472 [ci skip] --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index ec89a88c862318..6aec86ac6c49d8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -27,7 +27,7 @@ The following default gems are updated. * csv 3.2.9 * erb 4.0.4 * fiddle 1.1.3 -* io-console 0.7.2.dev.1 +* io-console 0.7.2 * net-http 0.4.1 * reline 0.4.2 * stringio 3.1.1 From fd1bafc11f74cb2bb74bf97bcba4ef694a533aec Mon Sep 17 00:00:00 2001 From: tomoya ishida Date: Thu, 18 Jan 2024 12:42:15 +0900 Subject: [PATCH 277/640] [ruby/stringio] Fix ascii_only? flag in strio_write (https://github.com/ruby/stringio/pull/77) Followup of #79 `rb_str_resize()` was changed by https://github.com/ruby/ruby/commit/b0b9f7201acab05c2a3ad92c3043a1f01df3e17f . ```c rb_str_resize(string, shorter) // clear ENC_CODERANGE in some case rb_str_resize(string, longer) // does not clear ENC_CODERANGE anymore ``` ```c // rb_str_resize in string.c if (slen > len && ENC_CODERANGE(str) != ENC_CODERANGE_7BIT) { ENC_CODERANGE_CLEAR(str); } ``` I think this change is based on an assumption that appending null bytes will not change flag `ascii_only?`. `strio_extend()` will make the string longer if needed, and update the flags correctly for appending null bytes. Before `memmove()`, we need to `rb_str_modify()` because updated flags are not updated for `memmove()`. https://github.com/ruby/stringio/commit/b31a538576 --- ext/stringio/stringio.c | 10 +--------- test/stringio/test_stringio.rb | 6 ++++++ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c index 4eb15117875cb3..27c7f65408e9ae 100644 --- a/ext/stringio/stringio.c +++ b/ext/stringio/stringio.c @@ -915,9 +915,6 @@ strio_extend(struct StringIO *ptr, long pos, long len) if (pos > olen) MEMZERO(RSTRING_PTR(ptr->string) + olen, char, pos - olen); } - else { - rb_str_modify(ptr->string); - } } /* @@ -1464,14 +1461,9 @@ strio_write(VALUE self, VALUE str) } } else { - int cr0 = ENC_CODERANGE(ptr->string); - int cr = ENC_CODERANGE_UNKNOWN; - if (rb_enc_asciicompat(enc) && rb_enc_asciicompat(enc2)) { - cr = ENC_CODERANGE_AND(cr0, ENC_CODERANGE(str)); - } strio_extend(ptr, ptr->pos, len); + rb_str_modify(ptr->string); memmove(RSTRING_PTR(ptr->string)+ptr->pos, RSTRING_PTR(str), len); - if (cr != cr0) ENC_CODERANGE_SET(ptr->string, cr); } RB_GC_GUARD(str); ptr->pos += len; diff --git a/test/stringio/test_stringio.rb b/test/stringio/test_stringio.rb index 15fcc21146308b..8afbcf35458c53 100644 --- a/test/stringio/test_stringio.rb +++ b/test/stringio/test_stringio.rb @@ -961,6 +961,12 @@ def test_coderange_after_overwrite assert_predicate(s.string, :ascii_only?) s.write "\u{431 43e 433 443 441}" assert_not_predicate(s.string, :ascii_only?) + + s = StringIO.new("\u{3042}") + s.rewind + assert_not_predicate(s.string, :ascii_only?) + s.write('aaaa') + assert_predicate(s.string, :ascii_only?) end def assert_string(content, encoding, str, mesg = nil) From a660e1de18fb4b21f5603198d228de7f8c9e3a07 Mon Sep 17 00:00:00 2001 From: Edwing123 <40911825+Edwing123@users.noreply.github.com> Date: Thu, 18 Jan 2024 00:56:42 -0600 Subject: [PATCH 278/640] [DOC] correct doc comment for rb_ary_aset Signed-off-by: Edwin Garcia --- array.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/array.c b/array.c index e64390298a8451..93e0cc9be42651 100644 --- a/array.c +++ b/array.c @@ -2338,7 +2338,7 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val) * a[1, 5] = 'foo' # => "foo" * a # => [:foo, "foo"] * - * When Range argument +range+ is given and +object+ is an \Array, + * When Range argument +range+ is given and +object+ is not an \Array, * removes length - 1 elements beginning at offset +start+, * and assigns +object+ at offset +start+: * @@ -2353,7 +2353,8 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val) * a # => [:foo, "foo"] * * If the array length is less than range.begin, - * assigns +object+ at offset range.begin, and ignores +length+: + * extends the array with +nil+, assigns +object+ at offset range.begin, + * and ignores +length+: * * a = [:foo, 'bar', 2] * a[6..50] = 'foo' # => "foo" From 419f4260aa4827c633b3172d95a9fa5f9aa7b8e2 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 18 Jan 2024 16:01:02 +0900 Subject: [PATCH 279/640] Use released version of bigdecimal --- gems/bundled_gems | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gems/bundled_gems b/gems/bundled_gems index cb1505a4c9b9f0..38ddd252fae5ee 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -24,4 +24,4 @@ racc 1.7.3 https://github.com/ruby/racc mutex_m 0.2.0 https://github.com/ruby/mutex_m getoptlong 0.2.1 https://github.com/ruby/getoptlong base64 0.2.0 https://github.com/ruby/base64 -bigdecimal 3.1.5 https://github.com/ruby/bigdecimal 3d185d286dfca7bc0d3c4a9d56261b8b22fcf52c +bigdecimal 3.1.6 https://github.com/ruby/bigdecimal From 74ce7905d792da93b163ba32e6c06a4b2d430f3a Mon Sep 17 00:00:00 2001 From: git Date: Thu, 18 Jan 2024 07:23:49 +0000 Subject: [PATCH 280/640] Update bundled gems list at 419f4260aa4827c633b3172d95a9fa [ci skip] --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 6aec86ac6c49d8..009c308836f7a9 100644 --- a/NEWS.md +++ b/NEWS.md @@ -48,7 +48,7 @@ The following bundled gems are promoted from default gems. * mutex_m 0.2.0 * getoptlong 0.2.1 * base64 0.2.0 -* bigdecimal 3.1.5 +* bigdecimal 3.1.6 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. From a3e6546e7ef98b9734e2c69d73c1295b60bba395 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 18 Jan 2024 16:36:09 +0900 Subject: [PATCH 281/640] Print error messages to the stderr [ci skip] --- tool/missing-baseruby.bat | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tool/missing-baseruby.bat b/tool/missing-baseruby.bat index b1c11aecb8c187..d5da5e1c725b9f 100755 --- a/tool/missing-baseruby.bat +++ b/tool/missing-baseruby.bat @@ -1,6 +1,6 @@ : " @echo off : " -echo executable host ruby is required. use --with-baseruby option. -echo Note that BASERUBY must be Ruby 2.7.0 or later. +echo>&2 executable host ruby is required. use --with-baseruby option. +echo>&2 Note that BASERUBY must be Ruby 2.7.0 or later. exit 1 From 264b7363aa7e47a7868b91038a0578970bc19c1f Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 18 Jan 2024 18:09:42 +0900 Subject: [PATCH 282/640] Preserve spaces in messages [ci skip] --- tool/missing-baseruby.bat | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tool/missing-baseruby.bat b/tool/missing-baseruby.bat index d5da5e1c725b9f..9b65e79cfceae5 100755 --- a/tool/missing-baseruby.bat +++ b/tool/missing-baseruby.bat @@ -1,6 +1,15 @@ : " -@echo off +@echo off || ( + :warn + echo>&2.%~1 + goto :eof + :abort + exit /b 1 +) : " -echo>&2 executable host ruby is required. use --with-baseruby option. -echo>&2 Note that BASERUBY must be Ruby 2.7.0 or later. -exit 1 +: ; call:warn() { echo "$1" >&2; } +: ; call:abort () { exit 1; } + +call:warn "executable host ruby is required. use --with-baseruby option." +call:warn "Note that BASERUBY must be Ruby 2.7.0 or later." +call:abort From 97721fa4e19c497d34a3bf94169930f99179f48d Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 18 Jan 2024 19:56:52 +0900 Subject: [PATCH 283/640] Old sh does not allow `:` in function names [ci skip] --- tool/missing-baseruby.bat | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tool/missing-baseruby.bat b/tool/missing-baseruby.bat index 9b65e79cfceae5..5b615bd9a80eb6 100755 --- a/tool/missing-baseruby.bat +++ b/tool/missing-baseruby.bat @@ -7,9 +7,10 @@ exit /b 1 ) : " -: ; call:warn() { echo "$1" >&2; } -: ; call:abort () { exit 1; } +: ; call() { local call=${1#:}; shift; $call "$@"; } +: ; warn() { echo "$1" >&2; } +: ; abort () { exit 1; } -call:warn "executable host ruby is required. use --with-baseruby option." -call:warn "Note that BASERUBY must be Ruby 2.7.0 or later." -call:abort +call :warn "executable host ruby is required. use --with-baseruby option." +call :warn "Note that BASERUBY must be Ruby 2.7.0 or later." +call :abort From ef685554c90e78f1ce8ed3a26745b0bd58df278e Mon Sep 17 00:00:00 2001 From: Burdette Lamar Date: Thu, 18 Jan 2024 09:15:25 -0600 Subject: [PATCH 284/640] [DOC] RDoc for ARGF (#9558) --- io.c | 267 ++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 236 insertions(+), 31 deletions(-) diff --git a/io.c b/io.c index bcad437339c24a..f8963b504f6063 100644 --- a/io.c +++ b/io.c @@ -14700,47 +14700,252 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y) /* * Document-class: ARGF * - * ARGF is a stream designed for use in scripts that process files given as - * command-line arguments or passed in via STDIN. + * == \ARGF and +ARGV+ * - * The arguments passed to your script are stored in the +ARGV+ Array, one - * argument per element. ARGF assumes that any arguments that aren't - * filenames have been removed from +ARGV+. For example: + * The \ARGF object works with the array at global variable +ARGV+ + * to make $stdin and file streams available in the Ruby program: * - * $ ruby argf.rb --verbose file1 file2 + * - **ARGV** may be thought of as the argument vector array. * - * ARGV #=> ["--verbose", "file1", "file2"] - * option = ARGV.shift #=> "--verbose" - * ARGV #=> ["file1", "file2"] + * Initially, it contains the command-line arguments and options + * that are passed to the Ruby program; + * the program can modify that array as it likes. * - * You can now use ARGF to work with a concatenation of each of these named - * files. For instance, ARGF.read will return the contents of _file1_ - * followed by the contents of _file2_. + * - **ARGF** may be thought of as the argument files object. * - * After a file in +ARGV+ has been read ARGF removes it from the Array. - * Thus, after all files have been read +ARGV+ will be empty. + * It can access file streams and/or the $stdin stream, + * based on what it finds in +ARGV+. + * This provides a convenient way for the command line + * to specify streams for a Ruby program to read. * - * You can manipulate +ARGV+ yourself to control what ARGF operates on. If - * you remove a file from +ARGV+, it is ignored by ARGF; if you add files to - * +ARGV+, they are treated as if they were named on the command line. For - * example: + * == Reading * - * ARGV.replace ["file1"] - * ARGF.readlines # Returns the contents of file1 as an Array - * ARGV #=> [] - * ARGV.replace ["file2", "file3"] - * ARGF.read # Returns the contents of file2 and file3 + * \ARGF may read from _source_ streams, + * which at any particular time are determined by the content of +ARGV+. * - * If +ARGV+ is empty, ARGF acts as if it contained "-" that - * makes ARGF read from STDIN, i.e. the data piped or typed to your - * script. For example: + * === Simplest Case * - * $ echo "glark" | ruby -e 'p ARGF.read' - * "glark\n" + * When the very first \ARGF read occurs with an empty +ARGV+ ([]), + * the source is $stdin: + * + * - \File +t.rb+: + * + * p ['ARGV', ARGV] + * p ['ARGF.read', ARGF.read] + * + * - Commands and outputs + * (see below for the content of files +foo.txt+ and +bar.txt+): + * + * $ echo "Open the pod bay doors, Hal." | ruby t.rb + * ["ARGV", []] + * ["ARGF.read", "Open the pod bay doors, Hal.\n"] + * + * $ cat foo.txt bar.txt | ruby t.rb + * ["ARGV", []] + * ["ARGF.read", "Foo 0\nFoo 1\nBar 0\nBar 1\nBar 2\nBar 3\n"] + * + * === About the Examples + * + * Many examples here assume the existence of files +foo.txt+ and +bar.txt+: + * + * $ cat foo.txt + * Foo 0 + * Foo 1 + * $ cat bar.txt + * Bar 0 + * Bar 1 + * Bar 2 + * Bar 3 + * + * === Sources in +ARGV+ + * + * For any \ARGF read _except_ the {simplest case}[rdoc-ref:ARGF@Simplest+Case] + * (that is, _except_ for the very first \ARGF read with an empty +ARGV+), + * the sources are found in +ARGV+. + * + * \ARGF assumes that each element in array +ARGV+ is a potential source, + * and is one of: + * + * - The string path to a file that may be opened as a stream. + * - The character '-', meaning stream $stdin. + * + * Each element that is _not_ one of these + * should be removed from +ARGV+ before \ARGF accesses that source. + * + * In the following example: + * + * - Filepaths +foo.txt+ and +bar.txt+ may be retained as potential sources. + * - Options --xyzzy and --mojo should be removed. + * + * Example: + * + * - \File +t.rb+: + * + * # Print arguments (and options, if any) found on command line. + * p ['ARGV', ARGV] + * + * - Command and output: + * + * $ ruby t.rb --xyzzy --mojo foo.txt bar.txt + * ["ARGV", ["--xyzzy", "--mojo", "foo.txt", "bar.txt"]] + * + * \ARGF's stream access considers the elements of +ARGV+, left to right: + * + * - \File +t.rb+: + * + * p "ARGV: #{ARGV}" + * p "Line: #{ARGF.read}" # Read everything from all specified streams. + * + * - Command and output: + * + * $ ruby t.rb foo.txt bar.txt + * "ARGV: [\"foo.txt\", \"bar.txt\"]" + * "Read: Foo 0\nFoo 1\nBar 0\nBar 1\nBar 2\nBar 3\n" + * + * Because the value at +ARGV+ is an ordinary array, + * you can manipulate it to control which sources \ARGF considers: + * + * - If you remove an element from +ARGV+, \ARGF will not consider the corresponding source. + * - If you add an element to +ARGV+, \ARGF will consider the corresponding source. + * + * Each element in +ARGV+ is removed when its corresponding source is accessed; + * when all sources have been accessed, the array is empty: + * + * - \File +t.rb+: + * + * until ARGV.empty? && ARGF.eof? + * p "ARGV: #{ARGV}" + * p "Line: #{ARGF.readline}" # Read each line from each specified stream. + * end + * + * - Command and output: + * + * $ ruby t.rb foo.txt bar.txt + * "ARGV: [\"foo.txt\", \"bar.txt\"]" + * "Line: Foo 0\n" + * "ARGV: [\"bar.txt\"]" + * "Line: Foo 1\n" + * "ARGV: [\"bar.txt\"]" + * "Line: Bar 0\n" + * "ARGV: []" + * "Line: Bar 1\n" + * "ARGV: []" + * "Line: Bar 2\n" + * "ARGV: []" + * "Line: Bar 3\n" + * + * ==== Filepaths in +ARGV+ + * + * The +ARGV+ array may contain filepaths the specify sources for \ARGF reading. + * + * This program prints what it reads from files at the paths specified + * on the command line: + * + * - \File +t.rb+: + * + * p ['ARGV', ARGV] + * # Read and print all content from the specified sources. + * p ['ARGF.read', ARGF.read] + * + * - Command and output: + * + * $ ruby t.rb foo.txt bar.txt + * ["ARGV", [foo.txt, bar.txt] + * ["ARGF.read", "Foo 0\nFoo 1\nBar 0\nBar 1\nBar 2\nBar 3\n"] + * + * ==== Specifying $stdin in +ARGV+ + * + * To specify stream $stdin in +ARGV+, us the character '-': + * + * - \File +t.rb+: + * + * p ['ARGV', ARGV] + * p ['ARGF.read', ARGF.read] + * + * - Command and output: + * + * $ echo "Open the pod bay doors, Hal." | ruby t.rb - + * ["ARGV", ["-"]] + * ["ARGF.read", "Open the pod bay doors, Hal.\n"] + * + * When no character '-' is given, stream $stdin is ignored + * (exception: see {Special Case}[rdoc-ref:ARGF@Special+Case]): + * + * - Command and output: + * + * $ echo "Open the pod bay doors, Hal." | ruby t.rb foo.txt bar.txt + * "ARGV: [\"foo.txt\", \"bar.txt\"]" + * "Read: Foo 0\nFoo 1\nBar 0\nBar 1\nBar 2\nBar 3\n" + * + * ==== Mixtures and Repetitions in +ARGV+ + * + * For an \ARGF reader, +ARGV+ may contain any mixture of filepaths + * and character '-', including repetitions. + * + * ==== Modifications to +ARGV+ + * + * The running Ruby program may make any modifications to the +ARGV+ array; + * the current value of +ARGV+ affects \ARGF reading. + * + * ==== Empty +ARGV+ + * + * For an empty +ARGV+, an \ARGF read method either returns +nil+ + * or raises an exception, depending on the specific method. + * + * === More Read Methods + * + * As seen above, method ARGF#read reads the content of all sources + * into a single string. + * Other \ARGF methods provide other ways to access that content; + * these include: + * + * - Byte access: #each_byte, #getbyte, #readbyte. + * - Character access: #each_char, #getc, #readchar. + * - Codepoint access: #each_codepoint. + * - Line access: #each_line, #gets, #readline, #readlines. + * - Source access: #read, #read_nonblock, #readpartial. + * + * === About \Enumerable + * + * \ARGF includes module Enumerable. + * Virtually all methods in \Enumerable call method #each in the including class. + * + * Note well: In \ARGF, method #each returns data from the _sources_, + * _not_ from +ARGV+; + * therefore, for example, ARGF#entries returns an array of lines from the sources, + * not an array of the strings from +ARGV+: + * + * - \File +t.rb+: + * + * p ['ARGV', ARGV] + * p ['ARGF.entries', ARGF.entries] + * + * - Command and output: + * + * $ ruby t.rb foo.txt bar.txt + * ["ARGV", ["foo.txt", "bar.txt"]] + * ["ARGF.entries", ["Foo 0\n", "Foo 1\n", "Bar 0\n", "Bar 1\n", "Bar 2\n", "Bar 3\n"]] + * + * == Writing + * + * If inplace mode is in effect, + * \ARGF may write to target streams, + * which at any particular time are determined by the content of ARGV. + * + * Methods about inplace mode: + * + * - #inplace_mode + * - #inplace_mode= + * - #to_write_io + * + * Methods for writing: + * + * - #print + * - #printf + * - #putc + * - #puts + * - #write * - * $ echo Glark > file1 - * $ echo "glark" | ruby -e 'p ARGF.read' -- - file1 - * "glark\nGlark\n" */ /* From 00814fd6724fff66a10966f5be10ea6dae06c616 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Thu, 18 Jan 2024 09:51:45 -0500 Subject: [PATCH 285/640] [PRISM] Fix memory leak in iseq rb_iseq_compile_prism_node calls both rb_translate_prism and iseq_setup. Both of these functions call iseq_set_sequence. This means that the first iseq_set_sequence will leak because the iseq will be overwritten. For example: 10.times do 100_000.times do RubyVM::InstructionSequence.compile_prism("") end puts `ps -o rss= -p #{$$}` end Before: 20528 27328 33840 40208 46400 52960 59168 65600 71888 78352 After: 13696 13712 13712 13712 13712 14352 14352 14992 14992 14992 --- prism_compile.c | 1 - 1 file changed, 1 deletion(-) diff --git a/prism_compile.c b/prism_compile.c index 876278166be5a4..e87c240638b6e8 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -6901,7 +6901,6 @@ rb_translate_prism(pm_parser_t *parser, rb_iseq_t *iseq, pm_scope_node_t *scope_ scope_node->index_lookup_table = index_lookup_table; pm_compile_node(iseq, (pm_node_t *)scope_node, ret, scope_node->base.location.start, false, (pm_scope_node_t *)scope_node); - iseq_set_sequence(iseq, ret); st_free_table(index_lookup_table); From d3b07b984545ce156e02e9f71404b652c6cb5284 Mon Sep 17 00:00:00 2001 From: Robert Schulze Date: Thu, 23 Feb 2023 13:38:54 +0100 Subject: [PATCH 286/640] [ruby/psych] Add :stringify_names option to convert symbol keys to string for dumping https://github.com/ruby/psych/commit/3d051d89aa --- ext/psych/lib/psych.rb | 14 ++++++++++++ ext/psych/lib/psych/visitors/yaml_tree.rb | 5 +++-- test/psych/test_psych.rb | 26 +++++++++++++++++++++++ test/psych/test_set.rb | 7 ++++++ 4 files changed, 50 insertions(+), 2 deletions(-) diff --git a/ext/psych/lib/psych.rb b/ext/psych/lib/psych.rb index ae167472f2aee9..d87bd9040ac47a 100644 --- a/ext/psych/lib/psych.rb +++ b/ext/psych/lib/psych.rb @@ -489,6 +489,10 @@ def self.parse_stream yaml, filename: nil, &block # # Default: false. # + # [:stringify_names] Dump symbol keys in Hash objects as string. + # + # Default: false. + # # Example: # # # Dump an array, get back a YAML string @@ -502,6 +506,9 @@ def self.parse_stream yaml, filename: nil, &block # # # Dump an array to an IO with indentation set # Psych.dump(['a', ['b']], StringIO.new, indentation: 3) + # + # # Dump hash with symbol keys as string + # Psych.dump({a: "b"}, stringify_names: true) # => "---\na: b\n" def self.dump o, io = nil, options = {} if Hash === io options = io @@ -562,6 +569,10 @@ def self.dump o, io = nil, options = {} # # Default: false. # + # [:stringify_names] Dump symbol keys in Hash objects as string. + # + # Default: false. + # # Example: # # # Dump an array, get back a YAML string @@ -575,6 +586,9 @@ def self.dump o, io = nil, options = {} # # # Dump an array to an IO with indentation set # Psych.safe_dump(['a', ['b']], StringIO.new, indentation: 3) + # + # # Dump hash with symbol keys as string + # Psych.dump({a: "b"}, stringify_names: true) # => "---\na: b\n" def self.safe_dump o, io = nil, options = {} if Hash === io options = io diff --git a/ext/psych/lib/psych/visitors/yaml_tree.rb b/ext/psych/lib/psych/visitors/yaml_tree.rb index 318f5f892b28b7..a2ebc4d78189b3 100644 --- a/ext/psych/lib/psych/visitors/yaml_tree.rb +++ b/ext/psych/lib/psych/visitors/yaml_tree.rb @@ -65,6 +65,7 @@ def initialize emitter, ss, options fail(ArgumentError, "Invalid line_width #{@line_width}, must be non-negative or -1 for unlimited.") end end + @stringify_names = options[:stringify_names] @coders = [] @dispatch_cache = Hash.new do |h,klass| @@ -323,7 +324,7 @@ def visit_Hash o if o.class == ::Hash register(o, @emitter.start_mapping(nil, nil, true, Psych::Nodes::Mapping::BLOCK)) o.each do |k,v| - accept k + accept(@stringify_names && Symbol === k ? k.to_s : k) accept v end @emitter.end_mapping @@ -336,7 +337,7 @@ def visit_Psych_Set o register(o, @emitter.start_mapping(nil, '!set', false, Psych::Nodes::Mapping::BLOCK)) o.each do |k,v| - accept k + accept(@stringify_names && Symbol === k ? k.to_s : k) accept v end diff --git a/test/psych/test_psych.rb b/test/psych/test_psych.rb index c977e799e3447a..42586a87793cd7 100644 --- a/test/psych/test_psych.rb +++ b/test/psych/test_psych.rb @@ -430,6 +430,32 @@ def test_safe_dump_symbols assert_match(/\A--- :foo\n(?:\.\.\.\n)?\z/, Psych.safe_dump(:foo, permitted_symbols: [:foo])) end + def test_safe_dump_stringify_names + yaml = <<-eoyml +--- +foo: + bar: bar + 'no': special escapes + 123: number +eoyml + + payload = Psych.safe_dump({ + foo: { + bar: "bar", + no: "special escapes", + 123 => "number" + } + }, stringify_names: true) + assert_equal yaml, payload + + assert_equal("---\nfoo: :bar\n", Psych.safe_dump({foo: :bar}, stringify_names: true, permitted_symbols: [:bar])) + + error = assert_raise Psych::DisallowedClass do + Psych.safe_dump({foo: :bar}, stringify_names: true) + end + assert_equal "Tried to dump unspecified class: Symbol(:bar)", error.message + end + def test_safe_dump_aliases x = [] x << x diff --git a/test/psych/test_set.rb b/test/psych/test_set.rb index 87944d839ea09d..b4968d3425201f 100644 --- a/test/psych/test_set.rb +++ b/test/psych/test_set.rb @@ -46,5 +46,12 @@ def test_set_self_reference @set['self'] = @set assert_cycle(@set) end + + def test_stringify_names + @set[:symbol] = :value + + assert_match(/^:symbol: :value/, Psych.dump(@set)) + assert_match(/^symbol: :value/, Psych.dump(@set, stringify_names: true)) + end end end From d8ac96efc57be460a0aad5d6ae033639439506fb Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Thu, 18 Jan 2024 10:36:49 -0500 Subject: [PATCH 287/640] [PRISM] Fix memory leak in case nodes The temporary array conditions_labels is heap allocated and never freed. We can use alloca instead to stack allocate it so that we don't need to manually free it. For example: code = "case; #{100.times.map { "when #{it}; " }.join}; end" 10.times do 10_000.times do RubyVM::InstructionSequence.compile_prism(code) end puts `ps -o rss= -p #{$$}` end Before: 21376 30304 38800 47184 55456 64192 72288 80400 89040 97104 After: 13088 13632 13760 14016 14688 14992 15120 15232 15744 15744 --- prism_compile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prism_compile.c b/prism_compile.c index e87c240638b6e8..9dd39e9b948fe7 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -3502,7 +3502,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_node_list_t conditions = case_node->conditions; - LABEL **conditions_labels = (LABEL **)ALLOC_N(VALUE, conditions.size + 1); + LABEL **conditions_labels = (LABEL **)ALLOCA_N(VALUE, conditions.size + 1); LABEL *label; for (size_t i = 0; i < conditions.size; i++) { From 33306a08d119fe6e178314a48b8b3f22ae1bb617 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Thu, 18 Jan 2024 11:40:11 -0800 Subject: [PATCH 288/640] YJIT: Stop incrementing chain_depth on defer_compilation (#9597) --- yjit/src/backend/ir.rs | 5 +++ yjit/src/codegen.rs | 14 ++++---- yjit/src/core.rs | 75 ++++++++++++++++++++++++++++++++++-------- 3 files changed, 73 insertions(+), 21 deletions(-) diff --git a/yjit/src/backend/ir.rs b/yjit/src/backend/ir.rs index 613e7048d46e19..303026d830d500 100644 --- a/yjit/src/backend/ir.rs +++ b/yjit/src/backend/ir.rs @@ -946,6 +946,7 @@ pub struct SideExitContext { pub sp_offset: i8, pub reg_temps: RegTemps, pub is_return_landing: bool, + pub is_deferred: bool, } impl SideExitContext { @@ -957,6 +958,7 @@ impl SideExitContext { sp_offset: ctx.get_sp_offset(), reg_temps: ctx.get_reg_temps(), is_return_landing: ctx.is_return_landing(), + is_deferred: ctx.is_deferred(), }; if cfg!(debug_assertions) { // Assert that we're not losing any mandatory metadata @@ -974,6 +976,9 @@ impl SideExitContext { if self.is_return_landing { ctx.set_as_return_landing(); } + if self.is_deferred { + ctx.mark_as_deferred(); + } ctx } } diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 378b397fe493f9..0471f7a20743dc 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -848,7 +848,7 @@ fn jump_to_next_insn( // Reset the depth since in current usages we only ever jump to to // chain_depth > 0 from the same instruction. let mut reset_depth = asm.ctx; - reset_depth.reset_chain_depth(); + reset_depth.reset_chain_depth_and_defer(); let jump_block = BlockId { iseq: jit.iseq, @@ -1029,7 +1029,7 @@ pub fn gen_single_block( // For now, reset the chain depth after each instruction as only the // first instruction in the block can concern itself with the depth. - asm.ctx.reset_chain_depth(); + asm.ctx.reset_chain_depth_and_defer(); // Move to the next instruction to compile insn_idx += insn_len(opcode) as u16; @@ -4702,7 +4702,7 @@ fn jit_rb_int_lshift( } // Fallback to a C call if the shift amount varies - if asm.ctx.get_chain_depth() > 1 { + if asm.ctx.get_chain_depth() > 0 { return false; } @@ -4716,7 +4716,7 @@ fn jit_rb_int_lshift( jit, asm, ocb, - 2, // defer_compilation increments chain_depth + 1, Counter::lshift_amount_changed, ); @@ -4761,7 +4761,7 @@ fn jit_rb_int_rshift( } // Fallback to a C call if the shift amount varies - if asm.ctx.get_chain_depth() > 2 { + if asm.ctx.get_chain_depth() > 1 { return false; } @@ -4775,7 +4775,7 @@ fn jit_rb_int_rshift( jit, asm, ocb, - 2, // defer_compilation increments chain_depth + 1, Counter::rshift_amount_changed, ); @@ -6875,7 +6875,7 @@ fn gen_send_iseq( return_asm.ctx = asm.ctx; return_asm.stack_pop(sp_offset.try_into().unwrap()); return_asm.ctx.set_sp_offset(0); // We set SP on the caller's frame above - return_asm.ctx.reset_chain_depth(); + return_asm.ctx.reset_chain_depth_and_defer(); return_asm.ctx.set_as_return_landing(); // Write the JIT return address on the callee frame diff --git a/yjit/src/core.rs b/yjit/src/core.rs index 064a7b5e8f772c..27c3541b59407c 100644 --- a/yjit/src/core.rs +++ b/yjit/src/core.rs @@ -439,6 +439,11 @@ impl RegTemps { } } +/// Bits for chain_depth_return_landing_defer +const RETURN_LANDING_BIT: u8 = 0b10000000; +const DEFER_BIT: u8 = 0b01000000; +const CHAIN_DEPTH_MASK: u8 = 0b00111111; // 63 + /// Code generation context /// Contains information we can use to specialize/optimize code /// There are a lot of context objects so we try to keep the size small. @@ -456,10 +461,10 @@ pub struct Context { reg_temps: RegTemps, /// Fields packed into u8 - /// - Lower 7 bits: Depth of this block in the sidechain (eg: inline-cache chain) - /// - Top bit: Whether this code is the target of a JIT-to-JIT Ruby return - /// ([Self::is_return_landing]) - chain_depth_return_landing: u8, + /// - 1st bit from the left: Whether this code is the target of a JIT-to-JIT Ruby return ([Self::is_return_landing]) + /// - 2nd bit from the left: Whether the compilation of this code has been deferred ([Self::is_deferred]) + /// - Last 6 bits (max: 63): Depth of this block in the sidechain (eg: inline-cache chain) + chain_depth_and_flags: u8, // Type we track for self self_type: Type, @@ -1674,6 +1679,9 @@ impl Context { if self.is_return_landing() { generic_ctx.set_as_return_landing(); } + if self.is_deferred() { + generic_ctx.mark_as_deferred(); + } generic_ctx } @@ -1704,30 +1712,39 @@ impl Context { } pub fn get_chain_depth(&self) -> u8 { - self.chain_depth_return_landing & 0x7f + self.chain_depth_and_flags & CHAIN_DEPTH_MASK } - pub fn reset_chain_depth(&mut self) { - self.chain_depth_return_landing &= 0x80; + pub fn reset_chain_depth_and_defer(&mut self) { + self.chain_depth_and_flags &= !CHAIN_DEPTH_MASK; + self.chain_depth_and_flags &= !DEFER_BIT; } pub fn increment_chain_depth(&mut self) { - if self.get_chain_depth() == 0x7f { + if self.get_chain_depth() == CHAIN_DEPTH_MASK { panic!("max block version chain depth reached!"); } - self.chain_depth_return_landing += 1; + self.chain_depth_and_flags += 1; } pub fn set_as_return_landing(&mut self) { - self.chain_depth_return_landing |= 0x80; + self.chain_depth_and_flags |= RETURN_LANDING_BIT; } pub fn clear_return_landing(&mut self) { - self.chain_depth_return_landing &= 0x7f; + self.chain_depth_and_flags &= !RETURN_LANDING_BIT; } pub fn is_return_landing(&self) -> bool { - self.chain_depth_return_landing & 0x80 > 0 + self.chain_depth_and_flags & RETURN_LANDING_BIT != 0 + } + + pub fn mark_as_deferred(&mut self) { + self.chain_depth_and_flags |= DEFER_BIT; + } + + pub fn is_deferred(&self) -> bool { + self.chain_depth_and_flags & DEFER_BIT != 0 } /// Get an operand for the adjusted stack pointer address @@ -2023,6 +2040,10 @@ impl Context { return TypeDiff::Incompatible; } + if src.is_deferred() != dst.is_deferred() { + return TypeDiff::Incompatible; + } + if dst.stack_size != src.stack_size { return TypeDiff::Incompatible; } @@ -3021,13 +3042,13 @@ pub fn defer_compilation( asm: &mut Assembler, ocb: &mut OutlinedCb, ) { - if asm.ctx.get_chain_depth() != 0 { + if asm.ctx.is_deferred() { panic!("Double defer!"); } let mut next_ctx = asm.ctx; - next_ctx.increment_chain_depth(); + next_ctx.mark_as_deferred(); let branch = new_pending_branch(jit, BranchGenFn::JumpToTarget0(Cell::new(BranchShape::Default))); @@ -3505,6 +3526,32 @@ mod tests { // TODO: write more tests for Context type diff } + #[test] + fn context_chain_depth() { + let mut ctx = Context::default(); + assert_eq!(ctx.get_chain_depth(), 0); + assert_eq!(ctx.is_return_landing(), false); + assert_eq!(ctx.is_deferred(), false); + + for _ in 0..5 { + ctx.increment_chain_depth(); + } + assert_eq!(ctx.get_chain_depth(), 5); + + ctx.set_as_return_landing(); + assert_eq!(ctx.is_return_landing(), true); + + ctx.clear_return_landing(); + assert_eq!(ctx.is_return_landing(), false); + + ctx.mark_as_deferred(); + assert_eq!(ctx.is_deferred(), true); + + ctx.reset_chain_depth_and_defer(); + assert_eq!(ctx.get_chain_depth(), 0); + assert_eq!(ctx.is_deferred(), false); + } + #[test] fn shift_stack_for_send() { let mut asm = Assembler::new(); From 686b1655a008f194d4daccf2d423d94c30633206 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Thu, 18 Jan 2024 14:59:59 -0500 Subject: [PATCH 289/640] [PRISM] Fix indentation in switch [ci skip] --- prism_compile.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 9dd39e9b948fe7..43ac0af1600cbb 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -6058,23 +6058,23 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n) // ^^^^^^^^^^ case PM_MULTI_TARGET_NODE: { - required_multis_hidden_index = local_index; - local = rb_make_temporary_id(local_index); - local_table_for_iseq->ids[local_index] = local; - break; + required_multis_hidden_index = local_index; + local = rb_make_temporary_id(local_index); + local_table_for_iseq->ids[local_index] = local; + break; } // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n) // ^ case PM_REQUIRED_PARAMETER_NODE: { - pm_required_parameter_node_t * param = (pm_required_parameter_node_t *)required; + pm_required_parameter_node_t * param = (pm_required_parameter_node_t *)required; - if (!PM_NODE_FLAG_P(required, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { - pm_insert_local_index(param->name, local_index, index_lookup_table, local_table_for_iseq, scope_node); - } - break; + if (!PM_NODE_FLAG_P(required, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + pm_insert_local_index(param->name, local_index, index_lookup_table, local_table_for_iseq, scope_node); + } + break; } default: { - rb_bug("Unsupported node in requireds in parameters %s", pm_node_type_to_str(PM_NODE_TYPE(node))); + rb_bug("Unsupported node in requireds in parameters %s", pm_node_type_to_str(PM_NODE_TYPE(node))); } } } From 8a3e7f08b85a9a21077c420b6fa76f56899e90ee Mon Sep 17 00:00:00 2001 From: Matt Valentine-House Date: Wed, 17 Jan 2024 16:44:58 +0000 Subject: [PATCH 290/640] [PRISM] Fix case splat with no predicate --- prism_compile.c | 5 +++-- test/ruby/test_compile_prism.rb | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 43ac0af1600cbb..2d1dd993889870 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -3514,10 +3514,11 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_node_t *condition_node = when_node->conditions.nodes[i]; if (PM_NODE_TYPE_P(condition_node, PM_SPLAT_NODE)) { + int checkmatch_type = has_predicate ? VM_CHECKMATCH_TYPE_CASE : VM_CHECKMATCH_TYPE_WHEN; ADD_INSN (ret, &dummy_line_node, dup); PM_COMPILE_NOT_POPPED(condition_node); - ADD_INSN1(ret, &dummy_line_node, splatarray, Qfalse); - ADD_INSN1(ret, &dummy_line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE | VM_CHECKMATCH_ARRAY)); + ADD_INSN1(ret, &dummy_line_node, checkmatch, + INT2FIX(checkmatch_type | VM_CHECKMATCH_ARRAY)); } else { PM_COMPILE_NOT_POPPED(condition_node); diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index f1274fccf5d9d6..0765a946a571ca 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -857,6 +857,17 @@ def self.prism_test_case_node end RUBY + # Test splat in when + assert_prism_eval(<<~RUBY) + ary = [1, 2] + case 1 + when :foo, *ary + :ok + else + :ng + end + RUBY + # Test case without predicate assert_prism_eval(<<~RUBY) case @@ -866,6 +877,16 @@ def self.prism_test_case_node :ok end RUBY + + # test splat with no predicate + assert_prism_eval(<<~RUBY) + case + when *[true] + :ok + else + :ng + end + RUBY end def test_ElseNode From 60dd731125fb540a1a222e2fcffa4fed020703fc Mon Sep 17 00:00:00 2001 From: Matt Valentine-House Date: Thu, 18 Jan 2024 14:39:32 +0000 Subject: [PATCH 291/640] [PRISM] Correct checkmatch flags for splat in rescue --- prism_compile.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/prism_compile.c b/prism_compile.c index 2d1dd993889870..ea8c3c6387229f 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -5693,7 +5693,11 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, for (size_t index = 0; index < exceptions->size; index++) { ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0); PM_COMPILE(exceptions->nodes[index]); - ADD_INSN1(ret, &dummy_line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE)); + int checkmatch_flags = VM_CHECKMATCH_TYPE_RESCUE; + if (PM_NODE_TYPE_P(exceptions->nodes[index], PM_SPLAT_NODE)) { + checkmatch_flags |= VM_CHECKMATCH_ARRAY; + } + ADD_INSN1(ret, &dummy_line_node, checkmatch, INT2FIX(checkmatch_flags)); ADD_INSN1(ret, &dummy_line_node, branchif, exception_match_label); } } else { From 47081c3ee321f477d09c90c09909bea36521efd2 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Thu, 18 Jan 2024 11:38:53 -0500 Subject: [PATCH 292/640] [PRISM] Pass pm_scope_node_t by reference We can pass pm_scope_node_t by reference to pm_new_child_iseq rather than by value. --- prism_compile.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index ea8c3c6387229f..5a8b27963f9baa 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -830,12 +830,12 @@ pm_constant_id_lookup(pm_scope_node_t *scope_node, pm_constant_id_t constant_id) } static rb_iseq_t * -pm_new_child_iseq(rb_iseq_t *iseq, pm_scope_node_t node, pm_parser_t *parser, +pm_new_child_iseq(rb_iseq_t *iseq, pm_scope_node_t *node, pm_parser_t *parser, VALUE name, const rb_iseq_t *parent, enum rb_iseq_type type, int line_no) { debugs("[new_child_iseq]> ---------------------------------------\n"); int isolated_depth = ISEQ_COMPILE_DATA(iseq)->isolated_depth; - rb_iseq_t * ret_iseq = pm_iseq_new_with_opt(&node, parser, name, + rb_iseq_t *ret_iseq = pm_iseq_new_with_opt(node, parser, name, rb_iseq_path(iseq), rb_iseq_realpath(iseq), line_no, parent, isolated_depth ? isolated_depth + 1 : 0, @@ -2841,8 +2841,7 @@ pm_compile_call(rb_iseq_t *iseq, const pm_call_node_t *call_node, LINK_ANCHOR *c // Scope associated with the block pm_scope_node_t next_scope_node; pm_scope_node_init(call_node->block, &next_scope_node, scope_node, parser); - - block_iseq = NEW_CHILD_ISEQ(next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, lineno); + block_iseq = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, lineno); if (ISEQ_BODY(block_iseq)->catch_table) { ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, start, end_label, block_iseq, end_label); } @@ -3244,7 +3243,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_scope_node_t rescue_scope_node; pm_scope_node_init((pm_node_t *)begin_node->rescue_clause, &rescue_scope_node, scope_node, parser); - rb_iseq_t *rescue_iseq = NEW_CHILD_ISEQ(rescue_scope_node, + rb_iseq_t *rescue_iseq = NEW_CHILD_ISEQ(&rescue_scope_node, rb_str_concat(rb_str_new2("rescue in"), ISEQ_BODY(iseq)->location.label), ISEQ_TYPE_RESCUE, 1); @@ -3312,7 +3311,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_scope_node_t next_scope_node; pm_scope_node_init((pm_node_t *)begin_node->ensure_clause, &next_scope_node, scope_node, parser); - child_iseq = NEW_CHILD_ISEQ(next_scope_node, + child_iseq = NEW_CHILD_ISEQ(&next_scope_node, rb_str_new2("ensure in"), ISEQ_TYPE_ENSURE, lineno); ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq; @@ -3729,7 +3728,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, VALUE class_name = rb_str_freeze(rb_sprintf("", rb_id2str(class_id))); - const rb_iseq_t *class_iseq = NEW_CHILD_ISEQ(next_scope_node, class_name, ISEQ_TYPE_CLASS, lineno); + const rb_iseq_t *class_iseq = NEW_CHILD_ISEQ(&next_scope_node, class_name, ISEQ_TYPE_CLASS, lineno); // TODO: Once we merge constant path nodes correctly, fix this flag const int flags = VM_DEFINECLASS_TYPE_CLASS | @@ -4147,7 +4146,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, ID method_name = pm_constant_id_lookup(scope_node, def_node->name); pm_scope_node_t next_scope_node; pm_scope_node_init((pm_node_t *)def_node, &next_scope_node, scope_node, parser); - rb_iseq_t *method_iseq = NEW_ISEQ(next_scope_node, rb_id2str(method_name), ISEQ_TYPE_METHOD, lineno); + rb_iseq_t *method_iseq = NEW_ISEQ(&next_scope_node, rb_id2str(method_name), ISEQ_TYPE_METHOD, lineno); if (def_node->receiver) { PM_COMPILE_NOT_POPPED(def_node->receiver); @@ -4259,7 +4258,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, PM_COMPILE_NOT_POPPED(for_node->collection); - child_iseq = NEW_CHILD_ISEQ(next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, lineno); + child_iseq = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, lineno); + ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq; ADD_SEND_WITH_BLOCK(ret, &dummy_line_node, idEach, INT2FIX(0), child_iseq); @@ -4283,7 +4283,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, if (forwarding_super_node->block) { pm_scope_node_t next_scope_node; pm_scope_node_init((pm_node_t *)forwarding_super_node->block, &next_scope_node, scope_node, parser); - block = NEW_CHILD_ISEQ(next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, lineno); + block = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, lineno); + RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)block); } @@ -4811,7 +4812,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_scope_node_t next_scope_node; pm_scope_node_init((pm_node_t*)node, &next_scope_node, scope_node, parser); - block_iseq = NEW_CHILD_ISEQ(next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, lineno); + block_iseq = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, lineno); ISEQ_COMPILE_DATA(iseq)->current_block = block_iseq; ADD_INSN2(ret, &dummy_line_node, once, block_iseq, INT2FIX(ic_index)); @@ -4892,7 +4893,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_scope_node_t next_scope_node; pm_scope_node_init(node, &next_scope_node, scope_node, parser); - const rb_iseq_t *block = NEW_CHILD_ISEQ(next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, lineno); + const rb_iseq_t *block = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, lineno); VALUE argc = INT2FIX(0); ADD_INSN1(ret, &dummy_line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); @@ -5205,7 +5206,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, ID module_id = pm_constant_id_lookup(scope_node, module_node->name); VALUE module_name = rb_str_freeze(rb_sprintf("", rb_id2str(module_id))); - const rb_iseq_t *module_iseq = NEW_CHILD_ISEQ(next_scope_node, module_name, ISEQ_TYPE_CLASS, lineno); + const rb_iseq_t *module_iseq = NEW_CHILD_ISEQ(&next_scope_node, module_name, ISEQ_TYPE_CLASS, lineno); const int flags = VM_DEFINECLASS_TYPE_MODULE | pm_compile_class_path(ret, iseq, module_node->constant_path, &dummy_line_node, src, false, scope_node); @@ -5543,7 +5544,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_scope_node_t next_scope_node; pm_scope_node_init(node, &next_scope_node, scope_node, parser); - child_iseq = NEW_CHILD_ISEQ(next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, lineno); + child_iseq = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, lineno); ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq; int is_index = ISEQ_BODY(iseq)->ise_size++; @@ -5800,8 +5801,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_scope_node_t rescue_scope_node; pm_rescue_modifier_node_t *rescue_node = (pm_rescue_modifier_node_t *)node; pm_scope_node_init((pm_node_t *)rescue_node, &rescue_scope_node, scope_node, parser); - - rb_iseq_t *rescue_iseq = NEW_CHILD_ISEQ(rescue_scope_node, + rb_iseq_t *rescue_iseq = NEW_CHILD_ISEQ(&rescue_scope_node, rb_str_concat(rb_str_new2("rescue in"), ISEQ_BODY(iseq)->location.label), ISEQ_TYPE_RESCUE, 1); @@ -6541,7 +6541,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_scope_node_t next_scope_node; pm_scope_node_init((pm_node_t *)post_execution_node->statements, &next_scope_node, scope_node, parser); - const rb_iseq_t *block = NEW_CHILD_ISEQ(next_scope_node, make_name_for_block(body->parent_iseq), ISEQ_TYPE_BLOCK, lineno); + const rb_iseq_t *block = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(body->parent_iseq), ISEQ_TYPE_BLOCK, lineno); ADD_CALL_WITH_BLOCK(ret, &dummy_line_node, id_core_set_postexe, INT2FIX(0), block); break; @@ -6650,8 +6650,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_singleton_class_node_t *singleton_class_node = (pm_singleton_class_node_t *)node; pm_scope_node_t next_scope_node; pm_scope_node_init((pm_node_t *)singleton_class_node, &next_scope_node, scope_node, parser); - - const rb_iseq_t *singleton_class = NEW_ISEQ(next_scope_node, rb_fstring_lit("singleton class"), ISEQ_TYPE_CLASS, lineno); + const rb_iseq_t *singleton_class = NEW_ISEQ(&next_scope_node, rb_fstring_lit("singleton class"), ISEQ_TYPE_CLASS, lineno); PM_COMPILE_NOT_POPPED(singleton_class_node->expression); PM_PUTNIL; @@ -6763,7 +6762,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, case PM_BLOCK_NODE: { pm_scope_node_t next_scope_node; pm_scope_node_init(super_node->block, &next_scope_node, scope_node, parser); - parent_block = NEW_CHILD_ISEQ(next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, lineno); + parent_block = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, lineno); break; } default: { From c28094d3850939cba360877780c4fec79f959764 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Thu, 18 Jan 2024 11:55:31 -0500 Subject: [PATCH 293/640] [PRISM] Add function to free scope node pm_scope_node_destroy frees the scope node after we're done using it to make sure that the index_lookup_table is not leaked. For example: 10.times do 100_000.times do RubyVM::InstructionSequence.compile_prism("begin; 1; rescue; 2; end") end puts `ps -o rss= -p #{$$}` end Before: 33056 50304 67776 84544 101520 118448 135712 152352 169136 186656 After: 15264 15296 15408 17040 17152 17152 18320 18352 18400 18608 --- iseq.c | 1 + prism_compile.c | 65 +++++++++++++++++++++++++++++++++++-------------- prism_compile.h | 1 + 3 files changed, 49 insertions(+), 18 deletions(-) diff --git a/iseq.c b/iseq.c index 4f1c39d2ae51b1..36dcf7bf43079d 100644 --- a/iseq.c +++ b/iseq.c @@ -1442,6 +1442,7 @@ iseqw_s_compile_prism_compile(pm_parser_t *parser, VALUE opt, rb_iseq_t *iseq, V rb_iseq_compile_prism_node(iseq, &scope_node, parser); finish_iseq_build(iseq); + pm_scope_node_destroy(&scope_node); pm_node_destroy(parser, node); free(constants); } diff --git a/prism_compile.c b/prism_compile.c index 5a8b27963f9baa..250f2afacd9293 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2476,6 +2476,14 @@ pm_scope_node_init(const pm_node_t *node, pm_scope_node_t *scope, pm_scope_node_ } } +void +pm_scope_node_destroy(pm_scope_node_t *scope_node) +{ + if (scope_node->index_lookup_table) { + st_free_table(scope_node->index_lookup_table); + } +} + static void pm_compile_call(rb_iseq_t *iseq, const pm_call_node_t *call_node, LINK_ANCHOR *const ret, const uint8_t *src, bool popped, pm_scope_node_t *scope_node, ID method_id, LABEL *start); void @@ -2842,6 +2850,8 @@ pm_compile_call(rb_iseq_t *iseq, const pm_call_node_t *call_node, LINK_ANCHOR *c pm_scope_node_t next_scope_node; pm_scope_node_init(call_node->block, &next_scope_node, scope_node, parser); block_iseq = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, lineno); + pm_scope_node_destroy(&next_scope_node); + if (ISEQ_BODY(block_iseq)->catch_table) { ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, start, end_label, block_iseq, end_label); } @@ -3240,13 +3250,15 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, LABEL *lstart = NEW_LABEL(lineno); LABEL *lend = NEW_LABEL(lineno); LABEL *lcont = NEW_LABEL(lineno); + pm_scope_node_t rescue_scope_node; pm_scope_node_init((pm_node_t *)begin_node->rescue_clause, &rescue_scope_node, scope_node, parser); - rb_iseq_t *rescue_iseq = NEW_CHILD_ISEQ(&rescue_scope_node, rb_str_concat(rb_str_new2("rescue in"), ISEQ_BODY(iseq)->location.label), ISEQ_TYPE_RESCUE, 1); + pm_scope_node_destroy(&rescue_scope_node); + lstart->rescued = LABEL_RESCUE_BEG; lend->rescued = LABEL_RESCUE_END; ADD_LABEL(ret, lstart); @@ -3310,12 +3322,12 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_scope_node_t next_scope_node; pm_scope_node_init((pm_node_t *)begin_node->ensure_clause, &next_scope_node, scope_node, parser); - child_iseq = NEW_CHILD_ISEQ(&next_scope_node, rb_str_new2("ensure in"), ISEQ_TYPE_ENSURE, lineno); - ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq; + pm_scope_node_destroy(&next_scope_node); + ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq; erange = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack->erange; if (estart->link.next != &eend->link) { @@ -3721,14 +3733,15 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } case PM_CLASS_NODE: { pm_class_node_t *class_node = (pm_class_node_t *)node; - pm_scope_node_t next_scope_node; - pm_scope_node_init((pm_node_t *)class_node, &next_scope_node, scope_node, parser); ID class_id = pm_constant_id_lookup(scope_node, class_node->name); VALUE class_name = rb_str_freeze(rb_sprintf("", rb_id2str(class_id))); + pm_scope_node_t next_scope_node; + pm_scope_node_init((pm_node_t *)class_node, &next_scope_node, scope_node, parser); const rb_iseq_t *class_iseq = NEW_CHILD_ISEQ(&next_scope_node, class_name, ISEQ_TYPE_CLASS, lineno); + pm_scope_node_destroy(&next_scope_node); // TODO: Once we merge constant path nodes correctly, fix this flag const int flags = VM_DEFINECLASS_TYPE_CLASS | @@ -4144,9 +4157,11 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, case PM_DEF_NODE: { pm_def_node_t *def_node = (pm_def_node_t *) node; ID method_name = pm_constant_id_lookup(scope_node, def_node->name); + pm_scope_node_t next_scope_node; pm_scope_node_init((pm_node_t *)def_node, &next_scope_node, scope_node, parser); rb_iseq_t *method_iseq = NEW_ISEQ(&next_scope_node, rb_id2str(method_name), ISEQ_TYPE_METHOD, lineno); + pm_scope_node_destroy(&next_scope_node); if (def_node->receiver) { PM_COMPILE_NOT_POPPED(def_node->receiver); @@ -4248,9 +4263,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, LABEL *retry_label = NEW_LABEL(lineno); LABEL *retry_end_l = NEW_LABEL(lineno); - pm_scope_node_t next_scope_node; - pm_scope_node_init((pm_node_t *)for_node, &next_scope_node, scope_node, parser); - pm_constant_id_list_t locals; pm_constant_id_list_init(&locals); @@ -4258,7 +4270,10 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, PM_COMPILE_NOT_POPPED(for_node->collection); + pm_scope_node_t next_scope_node; + pm_scope_node_init((pm_node_t *)for_node, &next_scope_node, scope_node, parser); child_iseq = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, lineno); + pm_scope_node_destroy(&next_scope_node); ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq; ADD_SEND_WITH_BLOCK(ret, &dummy_line_node, idEach, INT2FIX(0), child_iseq); @@ -4284,6 +4299,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_scope_node_t next_scope_node; pm_scope_node_init((pm_node_t *)forwarding_super_node->block, &next_scope_node, scope_node, parser); block = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, lineno); + pm_scope_node_destroy(&next_scope_node); RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)block); } @@ -4811,8 +4827,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_scope_node_t next_scope_node; pm_scope_node_init((pm_node_t*)node, &next_scope_node, scope_node, parser); - block_iseq = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, lineno); + pm_scope_node_destroy(&next_scope_node); + ISEQ_COMPILE_DATA(iseq)->current_block = block_iseq; ADD_INSN2(ret, &dummy_line_node, once, block_iseq, INT2FIX(ic_index)); @@ -4892,8 +4909,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, case PM_LAMBDA_NODE: { pm_scope_node_t next_scope_node; pm_scope_node_init(node, &next_scope_node, scope_node, parser); - const rb_iseq_t *block = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, lineno); + pm_scope_node_destroy(&next_scope_node); + VALUE argc = INT2FIX(0); ADD_INSN1(ret, &dummy_line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); @@ -5200,13 +5218,14 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } case PM_MODULE_NODE: { pm_module_node_t *module_node = (pm_module_node_t *)node; - pm_scope_node_t next_scope_node; - pm_scope_node_init((pm_node_t *)module_node, &next_scope_node, scope_node, parser); ID module_id = pm_constant_id_lookup(scope_node, module_node->name); VALUE module_name = rb_str_freeze(rb_sprintf("", rb_id2str(module_id))); + pm_scope_node_t next_scope_node; + pm_scope_node_init((pm_node_t *)module_node, &next_scope_node, scope_node, parser); const rb_iseq_t *module_iseq = NEW_CHILD_ISEQ(&next_scope_node, module_name, ISEQ_TYPE_CLASS, lineno); + pm_scope_node_destroy(&next_scope_node); const int flags = VM_DEFINECLASS_TYPE_MODULE | pm_compile_class_path(ret, iseq, module_node->constant_path, &dummy_line_node, src, false, scope_node); @@ -5543,8 +5562,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_scope_node_t next_scope_node; pm_scope_node_init(node, &next_scope_node, scope_node, parser); - child_iseq = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, lineno); + pm_scope_node_destroy(&next_scope_node); + ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq; int is_index = ISEQ_BODY(iseq)->ise_size++; @@ -5798,13 +5818,15 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, return; } case PM_RESCUE_MODIFIER_NODE: { - pm_scope_node_t rescue_scope_node; pm_rescue_modifier_node_t *rescue_node = (pm_rescue_modifier_node_t *)node; + + pm_scope_node_t rescue_scope_node; pm_scope_node_init((pm_node_t *)rescue_node, &rescue_scope_node, scope_node, parser); rb_iseq_t *rescue_iseq = NEW_CHILD_ISEQ(&rescue_scope_node, rb_str_concat(rb_str_new2("rescue in"), ISEQ_BODY(iseq)->location.label), ISEQ_TYPE_RESCUE, 1); + pm_scope_node_destroy(&rescue_scope_node); LABEL *lstart = NEW_LABEL(lineno); LABEL *lend = NEW_LABEL(lineno); @@ -6415,6 +6437,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // We set the index_lookup_table on the scope node so we can // refer to the parameters correctly + if (scope_node->index_lookup_table) { + st_free_table(scope_node->index_lookup_table); + } scope_node->index_lookup_table = index_lookup_table; iseq_calc_param_size(iseq); iseq_set_local_table(iseq, local_table_for_iseq); @@ -6540,6 +6565,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // We create another ScopeNode from the statements within the PostExecutionNode pm_scope_node_t next_scope_node; pm_scope_node_init((pm_node_t *)post_execution_node->statements, &next_scope_node, scope_node, parser); + pm_scope_node_destroy(&next_scope_node); const rb_iseq_t *block = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(body->parent_iseq), ISEQ_TYPE_BLOCK, lineno); @@ -6634,8 +6660,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } } - st_free_table(index_lookup_table); - if (!PM_NODE_TYPE_P(scope_node->ast_node, PM_ENSURE_NODE)) { ADD_INSN(ret, &dummy_line_node, leave); } @@ -6648,9 +6672,11 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, return; case PM_SINGLETON_CLASS_NODE: { pm_singleton_class_node_t *singleton_class_node = (pm_singleton_class_node_t *)node; + pm_scope_node_t next_scope_node; pm_scope_node_init((pm_node_t *)singleton_class_node, &next_scope_node, scope_node, parser); const rb_iseq_t *singleton_class = NEW_ISEQ(&next_scope_node, rb_fstring_lit("singleton class"), ISEQ_TYPE_CLASS, lineno); + pm_scope_node_destroy(&next_scope_node); PM_COMPILE_NOT_POPPED(singleton_class_node->expression); PM_PUTNIL; @@ -6763,6 +6789,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_scope_node_t next_scope_node; pm_scope_node_init(super_node->block, &next_scope_node, scope_node, parser); parent_block = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, lineno); + pm_scope_node_destroy(&next_scope_node); break; } default: { @@ -6902,12 +6929,14 @@ rb_translate_prism(pm_parser_t *parser, rb_iseq_t *iseq, pm_scope_node_t *scope_ for (size_t i = 0; i < locals->size; i++) { st_insert(index_lookup_table, locals->ids[i], i); } + + if (scope_node->index_lookup_table) { + st_free_table(scope_node->index_lookup_table); + } scope_node->index_lookup_table = index_lookup_table; pm_compile_node(iseq, (pm_node_t *)scope_node, ret, scope_node->base.location.start, false, (pm_scope_node_t *)scope_node); - st_free_table(index_lookup_table); - return Qnil; } diff --git a/prism_compile.h b/prism_compile.h index 578eed0243dc7e..36fdb77f177210 100644 --- a/prism_compile.h +++ b/prism_compile.h @@ -33,4 +33,5 @@ typedef struct pm_scope_node { } pm_scope_node_t; void pm_scope_node_init(const pm_node_t *node, pm_scope_node_t *scope, pm_scope_node_t *previous, pm_parser_t *parser); +void pm_scope_node_destroy(pm_scope_node_t *scope_node); bool *rb_ruby_prism_ptr(void); From 08edad31a6d5c9efd86bede1e942a32cff498427 Mon Sep 17 00:00:00 2001 From: Olle Jonsson Date: Thu, 18 Jan 2024 13:16:18 +0100 Subject: [PATCH 294/640] [rubygems/rubygems] Drop two TODOs from specification.rb These were introduced 13 years ago, in a documentation update. Perhaps we can let the TODOs go, without taking any action? https://github.com/rubygems/rubygems/commit/fb23fa84f9 --- lib/rubygems/specification.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb index 169002d7c7b9e1..f7012f1efdf9ee 100644 --- a/lib/rubygems/specification.rb +++ b/lib/rubygems/specification.rb @@ -1003,8 +1003,6 @@ def self.each def self.find_all_by_name(name, *requirements) requirements = Gem::Requirement.default if requirements.empty? - # TODO: maybe try: find_all { |s| spec === dep } - Gem::Dependency.new(name, *requirements).matching_specs end @@ -1022,8 +1020,6 @@ def self.find_all_by_full_name(full_name) def self.find_by_name(name, *requirements) requirements = Gem::Requirement.default if requirements.empty? - # TODO: maybe try: find { |s| spec === dep } - Gem::Dependency.new(name, *requirements).to_spec end From 807714447ef02c77bb0e17fe27d96ee2692264f8 Mon Sep 17 00:00:00 2001 From: KJ Tsanaktsidis Date: Sun, 12 Nov 2023 13:24:55 +1100 Subject: [PATCH 295/640] Pass down "stack start" variables from closer to the top of the stack This commit changes how stack extents are calculated for both the main thread and other threads. Ruby uses the address of a local variable as part of the calculation for machine stack extents: * pthreads uses it as a lower-bound on the start of the stack, because glibc (and maybe other libcs) can store its own data on the stack before calling into user code on thread creation. * win32 uses it as an argument to VirtualQuery, which gets the extent of the memory mapping which contains the variable However, the local being used for this is actually too low (too close to the leaf function call) in both the main thread case and the new thread case. In the main thread case, we have the `INIT_STACK` macro, which is used for pthreads to set the `native_main_thread->stack_start` value. This value is correctly captured at the very top level of the program (in main.c). However, this is _not_ what's used to set the execution context machine stack (`th->ec->machine_stack.stack_start`); that gets set as part of a call to `ruby_thread_init_stack` in `Init_BareVM`, using the address of a local variable allocated _inside_ `Init_BareVM`. This is too low; we need to use a local allocated closer to the top of the program. In the new thread case, the lolcal is allocated inside `native_thread_init_stack`, which is, again, too low. In both cases, this means that we might have VALUEs lying outside the bounds of `th->ec->machine.stack_{start,end}`, which won't be marked correctly by the GC machinery. To fix this, * In the main thread case: We already have `INIT_STACK` at the right level, so just pass that local var to `ruby_thread_init_stack`. * In the new thread case: Allocate the local one level above the call to `native_thread_init_stack` in `call_thread_start_func2`. [Bug #20001] fix --- eval.c | 6 ------ include/ruby/internal/interpreter.h | 2 +- thread.c | 4 ++-- thread_none.c | 7 +------ thread_pthread.c | 32 +++++++++++++++++++++-------- thread_win32.c | 14 +++++-------- vm.c | 11 +++++++++- vm_core.h | 2 +- 8 files changed, 44 insertions(+), 34 deletions(-) diff --git a/eval.c b/eval.c index aa0eae08727588..13f455786204f3 100644 --- a/eval.c +++ b/eval.c @@ -70,8 +70,6 @@ ruby_setup(void) if (GET_VM()) return 0; - ruby_init_stack((void *)&state); - /* * Disable THP early before mallocs happen because we want this to * affect as many future pages as possible for CoW-friendliness @@ -115,7 +113,6 @@ ruby_options(int argc, char **argv) enum ruby_tag_type state; void *volatile iseq = 0; - 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)); @@ -205,7 +202,6 @@ rb_ec_cleanup(rb_execution_context_t *ec, enum ruby_tag_type ex) step_0: step++; save_error = ec->errinfo; if (THROW_DATA_P(ec->errinfo)) ec->errinfo = Qnil; - ruby_init_stack(&message); /* exits with failure but silently when an exception raised * here */ @@ -324,14 +320,12 @@ ruby_run_node(void *n) 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)); } int ruby_exec_node(void *n) { - ruby_init_stack((void *)&n); return rb_ec_exec_node(GET_EC(), n); } diff --git a/include/ruby/internal/interpreter.h b/include/ruby/internal/interpreter.h index 662d39c0ec5702..a10e7ad2d850c4 100644 --- a/include/ruby/internal/interpreter.h +++ b/include/ruby/internal/interpreter.h @@ -141,7 +141,7 @@ void ruby_show_copyright(void); * * @param[in] addr A pointer somewhere on the stack, near its bottom. */ -void ruby_init_stack(volatile VALUE *addr); +void ruby_init_stack(void *addr); /** * Initializes the VM and builtin libraries. diff --git a/thread.c b/thread.c index 070d1bbdfaba88..e7a9d7cd9bdcc7 100644 --- a/thread.c +++ b/thread.c @@ -522,9 +522,9 @@ static VALUE rb_threadptr_raise(rb_thread_t *, int, VALUE *); static VALUE rb_thread_to_s(VALUE thread); void -ruby_thread_init_stack(rb_thread_t *th) +ruby_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame) { - native_thread_init_stack(th); + native_thread_init_stack(th, local_in_parent_frame); } const VALUE * diff --git a/thread_none.c b/thread_none.c index 4d53d3bf4d89c4..cb35aea708869c 100644 --- a/thread_none.c +++ b/thread_none.c @@ -139,13 +139,8 @@ ruby_mn_threads_params(void) { } -void -ruby_init_stack(volatile VALUE *addr) -{ -} - static int -native_thread_init_stack(rb_thread_t *th) +native_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame) { #if defined(__wasm__) && !defined(__EMSCRIPTEN__) th->ec->machine.stack_start = (VALUE *)rb_wasm_stack_get_base(); diff --git a/thread_pthread.c b/thread_pthread.c index 6d2f55a9573ed7..58bc49b17cd6ff 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -1962,9 +1962,8 @@ reserve_stack(volatile char *limit, size_t size) # define reserve_stack(limit, size) ((void)(limit), (void)(size)) #endif -#undef ruby_init_stack -void -ruby_init_stack(volatile VALUE *addr) +static void +native_thread_init_main_thread_stack(void *addr) { native_main_thread.id = pthread_self(); @@ -1987,7 +1986,7 @@ ruby_init_stack(volatile VALUE *addr) if (!native_main_thread.stack_start || STACK_UPPER((VALUE *)(void *)&addr, native_main_thread.stack_start > addr, - native_main_thread.stack_start < addr)) { + native_main_thread.stack_start < (VALUE *)addr)) { native_main_thread.stack_start = (VALUE *)addr; } #endif @@ -2049,10 +2048,16 @@ ruby_init_stack(volatile VALUE *addr) {int err = (expr); if (err) {rb_bug_errno(#expr, err);}} static int -native_thread_init_stack(rb_thread_t *th) +native_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame) { rb_nativethread_id_t curr = pthread_self(); + if (!native_main_thread.id) { + /* This thread is the first thread, must be the main thread - + * configure the native_main_thread object */ + native_thread_init_main_thread_stack(local_in_parent_frame); + } + if (pthread_equal(curr, native_main_thread.id)) { th->ec->machine.stack_start = native_main_thread.stack_start; th->ec->machine.stack_maxsize = native_main_thread.stack_maxsize; @@ -2064,8 +2069,8 @@ native_thread_init_stack(rb_thread_t *th) size_t size; if (get_stack(&start, &size) == 0) { - uintptr_t diff = (uintptr_t)start - (uintptr_t)&curr; - th->ec->machine.stack_start = (VALUE *)&curr; + uintptr_t diff = (uintptr_t)start - (uintptr_t)local_in_parent_frame; + th->ec->machine.stack_start = (uintptr_t)local_in_parent_frame; th->ec->machine.stack_maxsize = size - diff; } } @@ -2185,8 +2190,19 @@ native_thread_create_dedicated(rb_thread_t *th) static void call_thread_start_func_2(rb_thread_t *th) { - native_thread_init_stack(th); + /* Capture the address of a local in this stack frame to mark the beginning of the + machine stack for this thread. This is required even if we can tell the real + stack beginning from the pthread API in native_thread_init_stack, because + glibc stores some of its own data on the stack before calling into user code + on a new thread, and replacing that data on fiber-switch would break it (see + bug #13887) */ + VALUE stack_start = 0; + VALUE *stack_start_addr = &stack_start; + native_thread_init_stack(th, stack_start_addr); thread_start_func_2(th, th->ec->machine.stack_start); + + /* Ensure that stack_start really was spilled to the stack */ + RB_GC_GUARD(stack_start) } static void * diff --git a/thread_win32.c b/thread_win32.c index bd983e0bd9fb62..af007d587758b3 100644 --- a/thread_win32.c +++ b/thread_win32.c @@ -581,10 +581,6 @@ rb_native_cond_destroy(rb_nativethread_cond_t *cond) /* */ } -void -ruby_init_stack(volatile VALUE *addr) -{ -} #define CHECK_ERR(expr) \ {if (!(expr)) {rb_bug("err: %lu - %s", GetLastError(), #expr);}} @@ -594,20 +590,20 @@ COMPILER_WARNING_PUSH COMPILER_WARNING_IGNORED(-Wmaybe-uninitialized) #endif static inline SIZE_T -query_memory_basic_info(PMEMORY_BASIC_INFORMATION mi) +query_memory_basic_info(PMEMORY_BASIC_INFORMATION mi, void *local_in_parent_frame) { - return VirtualQuery(mi, mi, sizeof(*mi)); + return VirtualQuery(local_in_parent_frame, mi, sizeof(*mi)); } COMPILER_WARNING_POP static void -native_thread_init_stack(rb_thread_t *th) +native_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame) { MEMORY_BASIC_INFORMATION mi; char *base, *end; DWORD size, space; - CHECK_ERR(query_memory_basic_info(&mi)); + CHECK_ERR(query_memory_basic_info(&mi, local_in_parent_frame)); base = mi.AllocationBase; end = mi.BaseAddress; end += mi.RegionSize; @@ -638,7 +634,7 @@ thread_start_func_1(void *th_ptr) rb_thread_t *th = th_ptr; volatile HANDLE thread_id = th->nt->thread_id; - native_thread_init_stack(th); + native_thread_init_stack(th, &th); th->nt->interrupt_event = CreateEvent(0, TRUE, FALSE, 0); /* run */ diff --git a/vm.c b/vm.c index a2a17f8fe7578d..98e280bf28e4b3 100644 --- a/vm.c +++ b/vm.c @@ -54,6 +54,8 @@ int ruby_assert_critical_section_entered = 0; #endif +static void *native_main_thread_stack_top; + VALUE rb_str_concat_literals(size_t, const VALUE*); VALUE vm_exec(rb_execution_context_t *); @@ -4206,7 +4208,8 @@ Init_BareVM(void) th_init(th, 0, vm); rb_ractor_set_current_ec(th->ractor, th->ec); - ruby_thread_init_stack(th); + /* n.b. native_main_thread_stack_top is set by the INIT_STACK macro */ + ruby_thread_init_stack(th, native_main_thread_stack_top); // setup ractor system rb_native_mutex_initialize(&vm->ractor.sync.lock); @@ -4217,6 +4220,12 @@ Init_BareVM(void) #endif } +void +ruby_init_stack(void *addr) +{ + native_main_thread_stack_top = addr; +} + #ifndef _WIN32 #include #include diff --git a/vm_core.h b/vm_core.h index 7cd8fa76c5ad17..f1928d1ee2456c 100644 --- a/vm_core.h +++ b/vm_core.h @@ -1840,7 +1840,7 @@ rb_control_frame_t *rb_vm_get_binding_creatable_next_cfp(const rb_execution_cont VALUE *rb_vm_svar_lep(const rb_execution_context_t *ec, const rb_control_frame_t *cfp); int rb_vm_get_sourceline(const rb_control_frame_t *); void rb_vm_stack_to_heap(rb_execution_context_t *ec); -void ruby_thread_init_stack(rb_thread_t *th); +void ruby_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame); rb_thread_t * ruby_thread_from_native(void); int ruby_thread_set_native(rb_thread_t *th); int rb_vm_control_frame_id_and_class(const rb_control_frame_t *cfp, ID *idp, ID *called_idp, VALUE *klassp); From cabdaebc701217049d8a6457c5100f23910f4423 Mon Sep 17 00:00:00 2001 From: KJ Tsanaktsidis Date: Sun, 12 Nov 2023 13:34:43 +1100 Subject: [PATCH 296/640] Make stack bounds detection work with ASAN Where a local variable is used as part of the stack bounds detection, it has to actually be on the stack. ASAN can put local variable on "fake stacks", however, with addresses in different memory mappings. This completely destroys the stack bounds calculation, and can lead to e.g. things not getting GC marked on the machine stack or stackoverflow checks that always fail. The __asan_addr_is_in_fake_stack helper can be used to get the _real_ stack address of such variables, and thus perform the stack size calculation properly [Bug #20001] --- internal/sanitizers.h | 26 ++++++++++++++++++++++++++ thread_pthread.c | 15 ++++++++++----- thread_win32.c | 3 ++- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/internal/sanitizers.h b/internal/sanitizers.h index 7b7d166c747d4e..6b2a1319251a8d 100644 --- a/internal/sanitizers.h +++ b/internal/sanitizers.h @@ -64,6 +64,8 @@ # define __asan_poison_memory_region(x, y) # define __asan_unpoison_memory_region(x, y) # define __asan_region_is_poisoned(x, y) 0 +# define __asan_get_current_fake_stack() NULL +# define __asan_addr_is_in_fake_stack(fake_stack, slot, start, end) NULL #endif #if !__has_feature(memory_sanitizer) @@ -183,4 +185,28 @@ asan_unpoison_object(VALUE obj, bool newobj_p) asan_unpoison_memory_region(ptr, SIZEOF_VALUE, newobj_p); } + +/*! + * Checks if the given pointer is on an ASAN fake stack. If so, it returns the + * address this variable has on the real frame; if not, it returns the origin + * address unmodified. + * + * n.b. - _dereferencing_ the returned address is meaningless and should not + * be done; even though ASAN reserves space for the variable in both the real and + * fake stacks, the _value_ of that variable is only in the fake stack. + * + * n.b. - this only works for addresses passed in from local variables on the same + * thread, because the ASAN fake stacks are threadlocal. + * + * \param[in] slot the address of some local variable + * \retval a pointer to something from that frame on the _real_ machine stack + */ +static inline void * +asan_get_real_stack_addr(void* slot) +{ + VALUE *addr; + addr = __asan_addr_is_in_fake_stack(__asan_get_current_fake_stack(), slot, NULL, NULL); + return addr ? addr : slot; +} + #endif /* INTERNAL_SANITIZERS_H */ diff --git a/thread_pthread.c b/thread_pthread.c index 58bc49b17cd6ff..c90a29a6432e18 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -12,6 +12,7 @@ #ifdef THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION #include "internal/gc.h" +#include "internal/sanitizers.h" #include "rjit.h" #ifdef HAVE_SYS_RESOURCE_H @@ -1966,6 +1967,9 @@ static void native_thread_init_main_thread_stack(void *addr) { native_main_thread.id = pthread_self(); +#ifdef RUBY_ASAN_ENABLED + addr = asan_get_real_stack_addr((void *)addr); +#endif #if MAINSTACKADDR_AVAILABLE if (native_main_thread.stack_maxsize) return; @@ -2051,6 +2055,9 @@ static int native_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame) { rb_nativethread_id_t curr = pthread_self(); +#ifdef RUBY_ASAN_ENABLED + local_in_parent_frame = asan_get_real_stack_addr(local_in_parent_frame); +#endif if (!native_main_thread.id) { /* This thread is the first thread, must be the main thread - @@ -2070,7 +2077,7 @@ native_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame) if (get_stack(&start, &size) == 0) { uintptr_t diff = (uintptr_t)start - (uintptr_t)local_in_parent_frame; - th->ec->machine.stack_start = (uintptr_t)local_in_parent_frame; + th->ec->machine.stack_start = local_in_parent_frame; th->ec->machine.stack_maxsize = size - diff; } } @@ -2197,12 +2204,10 @@ call_thread_start_func_2(rb_thread_t *th) on a new thread, and replacing that data on fiber-switch would break it (see bug #13887) */ VALUE stack_start = 0; - VALUE *stack_start_addr = &stack_start; + VALUE *stack_start_addr = asan_get_real_stack_addr(&stack_start); + native_thread_init_stack(th, stack_start_addr); thread_start_func_2(th, th->ec->machine.stack_start); - - /* Ensure that stack_start really was spilled to the stack */ - RB_GC_GUARD(stack_start) } static void * diff --git a/thread_win32.c b/thread_win32.c index af007d587758b3..9e6d10b188e8bd 100644 --- a/thread_win32.c +++ b/thread_win32.c @@ -11,6 +11,7 @@ #ifdef THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION +#include "internal/sanitizers.h" #include #define TIME_QUANTUM_USEC (10 * 1000) @@ -592,7 +593,7 @@ COMPILER_WARNING_IGNORED(-Wmaybe-uninitialized) static inline SIZE_T query_memory_basic_info(PMEMORY_BASIC_INFORMATION mi, void *local_in_parent_frame) { - return VirtualQuery(local_in_parent_frame, mi, sizeof(*mi)); + return VirtualQuery(asan_get_real_stack_addr(local_in_parent_frame), mi, sizeof(*mi)); } COMPILER_WARNING_POP From 3cfcb45ecfb8dde9920220ae65ea6040e456bbd1 Mon Sep 17 00:00:00 2001 From: KJ Tsanaktsidis Date: Sun, 12 Nov 2023 14:57:10 +1100 Subject: [PATCH 297/640] Define special macros for asan/msan being enabled __has_feature is a clang-ism, and GCC has a different way to tell if sanitizers are enabled. For this reason, I don't want to spray __has_feature all over the codebase for other places where conditional compilation based on sanitizers is required. [Bug #20001] --- internal/sanitizers.h | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/internal/sanitizers.h b/internal/sanitizers.h index 6b2a1319251a8d..d444903aa0b36e 100644 --- a/internal/sanitizers.h +++ b/internal/sanitizers.h @@ -16,11 +16,15 @@ #endif #ifdef HAVE_SANITIZER_ASAN_INTERFACE_H -# include +# if __has_feature(address_sanitizer) +# define RUBY_ASAN_ENABLED +# include +# endif #endif #ifdef HAVE_SANITIZER_MSAN_INTERFACE_H # if __has_feature(memory_sanitizer) +# define RUBY_MSAN_ENABLED # include # endif #endif @@ -29,10 +33,10 @@ #include "ruby/ruby.h" /* for VALUE */ #if 0 -#elif __has_feature(memory_sanitizer) && __has_feature(address_sanitizer) +#elif defined(RUBY_ASAN_ENABLED) && defined(RUBY_MSAN_ENABLED) # define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \ __attribute__((__no_sanitize__("memory, address"), __noinline__)) x -#elif __has_feature(address_sanitizer) +#elif defined(RUBY_ASAN_ENABLED) # define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \ __attribute__((__no_sanitize__("address"), __noinline__)) x #elif defined(NO_SANITIZE_ADDRESS) @@ -60,7 +64,7 @@ # define NO_SANITIZE(x, y) y #endif -#if !__has_feature(address_sanitizer) +#ifndef RUBY_ASAN_ENABLED # define __asan_poison_memory_region(x, y) # define __asan_unpoison_memory_region(x, y) # define __asan_region_is_poisoned(x, y) 0 @@ -68,7 +72,7 @@ # define __asan_addr_is_in_fake_stack(fake_stack, slot, start, end) NULL #endif -#if !__has_feature(memory_sanitizer) +#ifndef RUBY_MSAN_ENABLED # define __msan_allocated_memory(x, y) ((void)(x), (void)(y)) # define __msan_poison(x, y) ((void)(x), (void)(y)) # define __msan_unpoison(x, y) ((void)(x), (void)(y)) @@ -123,12 +127,12 @@ asan_poison_object(VALUE obj) asan_poison_memory_region(ptr, SIZEOF_VALUE); } -#if !__has_feature(address_sanitizer) -#define asan_poison_object_if(ptr, obj) ((void)(ptr), (void)(obj)) -#else +#ifdef RUBY_ASAN_ENABLED #define asan_poison_object_if(ptr, obj) do { \ if (ptr) asan_poison_object(obj); \ } while (0) +#else +#define asan_poison_object_if(ptr, obj) ((void)(ptr), (void)(obj)) #endif /*! From 61da90c1b8d5c9a62d429ef66f000117eca675b3 Mon Sep 17 00:00:00 2001 From: KJ Tsanaktsidis Date: Wed, 17 Jan 2024 11:45:33 +1100 Subject: [PATCH 298/640] Mark asan fake stacks during machine stack marking ASAN leaves a pointer to the fake frame on the stack; we can use the __asan_addr_is_in_fake_stack API to work out the extent of the fake stack and thus mark any VALUEs contained therein. [Bug #20001] --- common.mk | 43 +++++++++++++++++++++++++++++ ext/objspace/depend | 1 + ext/ripper/depend | 1 + ext/socket/depend | 15 ++++++++++ gc.c | 36 ++++++++++++++++++++++-- internal/sanitizers.h | 64 +++++++++++++++++++++++++++++++++++++++++++ thread.c | 3 ++ vm_core.h | 6 ++++ 8 files changed, 167 insertions(+), 2 deletions(-) diff --git a/common.mk b/common.mk index c4b6dec1533680..bfbdfc6594ee01 100644 --- a/common.mk +++ b/common.mk @@ -2000,6 +2000,7 @@ array.$(OBJEXT): $(top_srcdir)/internal/numeric.h array.$(OBJEXT): $(top_srcdir)/internal/object.h array.$(OBJEXT): $(top_srcdir)/internal/proc.h array.$(OBJEXT): $(top_srcdir)/internal/rational.h +array.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h array.$(OBJEXT): $(top_srcdir)/internal/serial.h array.$(OBJEXT): $(top_srcdir)/internal/static_assert.h array.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -2213,6 +2214,7 @@ ast.$(OBJEXT): $(top_srcdir)/internal/numeric.h ast.$(OBJEXT): $(top_srcdir)/internal/parse.h ast.$(OBJEXT): $(top_srcdir)/internal/rational.h ast.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +ast.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h ast.$(OBJEXT): $(top_srcdir)/internal/serial.h ast.$(OBJEXT): $(top_srcdir)/internal/static_assert.h ast.$(OBJEXT): $(top_srcdir)/internal/symbol.h @@ -2648,6 +2650,7 @@ builtin.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h builtin.$(OBJEXT): $(top_srcdir)/internal/compilers.h builtin.$(OBJEXT): $(top_srcdir)/internal/gc.h builtin.$(OBJEXT): $(top_srcdir)/internal/imemo.h +builtin.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h builtin.$(OBJEXT): $(top_srcdir)/internal/serial.h builtin.$(OBJEXT): $(top_srcdir)/internal/static_assert.h builtin.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -2877,6 +2880,7 @@ class.$(OBJEXT): $(top_srcdir)/internal/gc.h class.$(OBJEXT): $(top_srcdir)/internal/hash.h class.$(OBJEXT): $(top_srcdir)/internal/imemo.h class.$(OBJEXT): $(top_srcdir)/internal/object.h +class.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h class.$(OBJEXT): $(top_srcdir)/internal/serial.h class.$(OBJEXT): $(top_srcdir)/internal/static_assert.h class.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -3274,6 +3278,7 @@ compile.$(OBJEXT): $(top_srcdir)/internal/object.h compile.$(OBJEXT): $(top_srcdir)/internal/rational.h compile.$(OBJEXT): $(top_srcdir)/internal/re.h compile.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +compile.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h compile.$(OBJEXT): $(top_srcdir)/internal/serial.h compile.$(OBJEXT): $(top_srcdir)/internal/static_assert.h compile.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -3527,6 +3532,7 @@ complex.$(OBJEXT): $(top_srcdir)/internal/math.h complex.$(OBJEXT): $(top_srcdir)/internal/numeric.h complex.$(OBJEXT): $(top_srcdir)/internal/object.h complex.$(OBJEXT): $(top_srcdir)/internal/rational.h +complex.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h complex.$(OBJEXT): $(top_srcdir)/internal/serial.h complex.$(OBJEXT): $(top_srcdir)/internal/static_assert.h complex.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -3971,6 +3977,7 @@ debug.$(OBJEXT): $(top_srcdir)/internal/class.h debug.$(OBJEXT): $(top_srcdir)/internal/compilers.h debug.$(OBJEXT): $(top_srcdir)/internal/gc.h debug.$(OBJEXT): $(top_srcdir)/internal/imemo.h +debug.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h debug.$(OBJEXT): $(top_srcdir)/internal/serial.h debug.$(OBJEXT): $(top_srcdir)/internal/signal.h debug.$(OBJEXT): $(top_srcdir)/internal/static_assert.h @@ -4348,6 +4355,7 @@ dir.$(OBJEXT): $(top_srcdir)/internal/gc.h dir.$(OBJEXT): $(top_srcdir)/internal/imemo.h dir.$(OBJEXT): $(top_srcdir)/internal/io.h dir.$(OBJEXT): $(top_srcdir)/internal/object.h +dir.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h dir.$(OBJEXT): $(top_srcdir)/internal/serial.h dir.$(OBJEXT): $(top_srcdir)/internal/static_assert.h dir.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -6271,6 +6279,7 @@ enumerator.$(OBJEXT): $(top_srcdir)/internal/imemo.h enumerator.$(OBJEXT): $(top_srcdir)/internal/numeric.h enumerator.$(OBJEXT): $(top_srcdir)/internal/range.h enumerator.$(OBJEXT): $(top_srcdir)/internal/rational.h +enumerator.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h enumerator.$(OBJEXT): $(top_srcdir)/internal/serial.h enumerator.$(OBJEXT): $(top_srcdir)/internal/static_assert.h enumerator.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -6483,6 +6492,7 @@ error.$(OBJEXT): $(top_srcdir)/internal/io.h error.$(OBJEXT): $(top_srcdir)/internal/load.h error.$(OBJEXT): $(top_srcdir)/internal/object.h error.$(OBJEXT): $(top_srcdir)/internal/process.h +error.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h error.$(OBJEXT): $(top_srcdir)/internal/serial.h error.$(OBJEXT): $(top_srcdir)/internal/static_assert.h error.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -6699,6 +6709,7 @@ eval.$(OBJEXT): $(top_srcdir)/internal/imemo.h eval.$(OBJEXT): $(top_srcdir)/internal/inits.h eval.$(OBJEXT): $(top_srcdir)/internal/io.h eval.$(OBJEXT): $(top_srcdir)/internal/object.h +eval.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h eval.$(OBJEXT): $(top_srcdir)/internal/serial.h eval.$(OBJEXT): $(top_srcdir)/internal/static_assert.h eval.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -7434,6 +7445,7 @@ goruby.$(OBJEXT): $(top_srcdir)/internal/imemo.h goruby.$(OBJEXT): $(top_srcdir)/internal/numeric.h goruby.$(OBJEXT): $(top_srcdir)/internal/rational.h goruby.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +goruby.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h goruby.$(OBJEXT): $(top_srcdir)/internal/serial.h goruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h goruby.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -7670,6 +7682,7 @@ hash.$(OBJEXT): $(top_srcdir)/internal/hash.h hash.$(OBJEXT): $(top_srcdir)/internal/imemo.h hash.$(OBJEXT): $(top_srcdir)/internal/object.h hash.$(OBJEXT): $(top_srcdir)/internal/proc.h +hash.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h hash.$(OBJEXT): $(top_srcdir)/internal/serial.h hash.$(OBJEXT): $(top_srcdir)/internal/st.h hash.$(OBJEXT): $(top_srcdir)/internal/static_assert.h @@ -8082,6 +8095,7 @@ io.$(OBJEXT): $(top_srcdir)/internal/io.h io.$(OBJEXT): $(top_srcdir)/internal/numeric.h io.$(OBJEXT): $(top_srcdir)/internal/object.h io.$(OBJEXT): $(top_srcdir)/internal/process.h +io.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h io.$(OBJEXT): $(top_srcdir)/internal/serial.h io.$(OBJEXT): $(top_srcdir)/internal/static_assert.h io.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -8756,6 +8770,7 @@ load.$(OBJEXT): $(top_srcdir)/internal/numeric.h load.$(OBJEXT): $(top_srcdir)/internal/parse.h load.$(OBJEXT): $(top_srcdir)/internal/rational.h load.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +load.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h load.$(OBJEXT): $(top_srcdir)/internal/serial.h load.$(OBJEXT): $(top_srcdir)/internal/static_assert.h load.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -9485,6 +9500,7 @@ marshal.$(OBJEXT): $(top_srcdir)/internal/hash.h marshal.$(OBJEXT): $(top_srcdir)/internal/imemo.h marshal.$(OBJEXT): $(top_srcdir)/internal/numeric.h marshal.$(OBJEXT): $(top_srcdir)/internal/object.h +marshal.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h marshal.$(OBJEXT): $(top_srcdir)/internal/serial.h marshal.$(OBJEXT): $(top_srcdir)/internal/static_assert.h marshal.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -9869,6 +9885,7 @@ memory_view.$(OBJEXT): $(top_srcdir)/internal/compilers.h memory_view.$(OBJEXT): $(top_srcdir)/internal/gc.h memory_view.$(OBJEXT): $(top_srcdir)/internal/hash.h memory_view.$(OBJEXT): $(top_srcdir)/internal/imemo.h +memory_view.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h memory_view.$(OBJEXT): $(top_srcdir)/internal/serial.h memory_view.$(OBJEXT): $(top_srcdir)/internal/static_assert.h memory_view.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -10080,6 +10097,7 @@ miniinit.$(OBJEXT): $(top_srcdir)/internal/imemo.h miniinit.$(OBJEXT): $(top_srcdir)/internal/numeric.h miniinit.$(OBJEXT): $(top_srcdir)/internal/rational.h miniinit.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h miniinit.$(OBJEXT): $(top_srcdir)/internal/serial.h miniinit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h miniinit.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -10328,6 +10346,7 @@ node.$(OBJEXT): $(top_srcdir)/internal/compilers.h node.$(OBJEXT): $(top_srcdir)/internal/gc.h node.$(OBJEXT): $(top_srcdir)/internal/hash.h node.$(OBJEXT): $(top_srcdir)/internal/imemo.h +node.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h node.$(OBJEXT): $(top_srcdir)/internal/serial.h node.$(OBJEXT): $(top_srcdir)/internal/static_assert.h node.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -10535,6 +10554,7 @@ node_dump.$(OBJEXT): $(top_srcdir)/internal/imemo.h node_dump.$(OBJEXT): $(top_srcdir)/internal/numeric.h node_dump.$(OBJEXT): $(top_srcdir)/internal/rational.h node_dump.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +node_dump.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h node_dump.$(OBJEXT): $(top_srcdir)/internal/serial.h node_dump.$(OBJEXT): $(top_srcdir)/internal/static_assert.h node_dump.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -10743,6 +10763,7 @@ numeric.$(OBJEXT): $(top_srcdir)/internal/imemo.h numeric.$(OBJEXT): $(top_srcdir)/internal/numeric.h numeric.$(OBJEXT): $(top_srcdir)/internal/object.h numeric.$(OBJEXT): $(top_srcdir)/internal/rational.h +numeric.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h numeric.$(OBJEXT): $(top_srcdir)/internal/serial.h numeric.$(OBJEXT): $(top_srcdir)/internal/static_assert.h numeric.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -10956,6 +10977,7 @@ object.$(OBJEXT): $(top_srcdir)/internal/imemo.h object.$(OBJEXT): $(top_srcdir)/internal/inits.h object.$(OBJEXT): $(top_srcdir)/internal/numeric.h object.$(OBJEXT): $(top_srcdir)/internal/object.h +object.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h object.$(OBJEXT): $(top_srcdir)/internal/serial.h object.$(OBJEXT): $(top_srcdir)/internal/st.h object.$(OBJEXT): $(top_srcdir)/internal/static_assert.h @@ -11170,6 +11192,7 @@ pack.$(OBJEXT): $(top_srcdir)/internal/bits.h pack.$(OBJEXT): $(top_srcdir)/internal/compilers.h pack.$(OBJEXT): $(top_srcdir)/internal/gc.h pack.$(OBJEXT): $(top_srcdir)/internal/imemo.h +pack.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h pack.$(OBJEXT): $(top_srcdir)/internal/serial.h pack.$(OBJEXT): $(top_srcdir)/internal/static_assert.h pack.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -11389,6 +11412,7 @@ parse.$(OBJEXT): $(top_srcdir)/internal/parse.h parse.$(OBJEXT): $(top_srcdir)/internal/rational.h parse.$(OBJEXT): $(top_srcdir)/internal/re.h parse.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +parse.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h parse.$(OBJEXT): $(top_srcdir)/internal/serial.h parse.$(OBJEXT): $(top_srcdir)/internal/static_assert.h parse.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -12641,6 +12665,7 @@ proc.$(OBJEXT): $(top_srcdir)/internal/gc.h proc.$(OBJEXT): $(top_srcdir)/internal/imemo.h proc.$(OBJEXT): $(top_srcdir)/internal/object.h proc.$(OBJEXT): $(top_srcdir)/internal/proc.h +proc.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h proc.$(OBJEXT): $(top_srcdir)/internal/serial.h proc.$(OBJEXT): $(top_srcdir)/internal/static_assert.h proc.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -12885,6 +12910,7 @@ process.$(OBJEXT): $(top_srcdir)/internal/io.h process.$(OBJEXT): $(top_srcdir)/internal/numeric.h process.$(OBJEXT): $(top_srcdir)/internal/object.h process.$(OBJEXT): $(top_srcdir)/internal/process.h +process.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h process.$(OBJEXT): $(top_srcdir)/internal/serial.h process.$(OBJEXT): $(top_srcdir)/internal/static_assert.h process.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -13107,6 +13133,7 @@ ractor.$(OBJEXT): $(top_srcdir)/internal/hash.h ractor.$(OBJEXT): $(top_srcdir)/internal/imemo.h ractor.$(OBJEXT): $(top_srcdir)/internal/numeric.h ractor.$(OBJEXT): $(top_srcdir)/internal/rational.h +ractor.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h ractor.$(OBJEXT): $(top_srcdir)/internal/serial.h ractor.$(OBJEXT): $(top_srcdir)/internal/static_assert.h ractor.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -13729,6 +13756,7 @@ rational.$(OBJEXT): $(top_srcdir)/internal/imemo.h rational.$(OBJEXT): $(top_srcdir)/internal/numeric.h rational.$(OBJEXT): $(top_srcdir)/internal/object.h rational.$(OBJEXT): $(top_srcdir)/internal/rational.h +rational.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h rational.$(OBJEXT): $(top_srcdir)/internal/serial.h rational.$(OBJEXT): $(top_srcdir)/internal/static_assert.h rational.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -13935,6 +13963,7 @@ re.$(OBJEXT): $(top_srcdir)/internal/imemo.h re.$(OBJEXT): $(top_srcdir)/internal/object.h re.$(OBJEXT): $(top_srcdir)/internal/ractor.h re.$(OBJEXT): $(top_srcdir)/internal/re.h +re.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h re.$(OBJEXT): $(top_srcdir)/internal/serial.h re.$(OBJEXT): $(top_srcdir)/internal/static_assert.h re.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -15118,6 +15147,7 @@ rjit.$(OBJEXT): $(top_srcdir)/internal/gc.h rjit.$(OBJEXT): $(top_srcdir)/internal/hash.h rjit.$(OBJEXT): $(top_srcdir)/internal/imemo.h rjit.$(OBJEXT): $(top_srcdir)/internal/process.h +rjit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h rjit.$(OBJEXT): $(top_srcdir)/internal/serial.h rjit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h rjit.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -15647,6 +15677,7 @@ ruby.$(OBJEXT): $(top_srcdir)/internal/object.h ruby.$(OBJEXT): $(top_srcdir)/internal/parse.h ruby.$(OBJEXT): $(top_srcdir)/internal/rational.h ruby.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +ruby.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h ruby.$(OBJEXT): $(top_srcdir)/internal/serial.h ruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h ruby.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -16067,6 +16098,7 @@ scheduler.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h scheduler.$(OBJEXT): $(top_srcdir)/internal/compilers.h scheduler.$(OBJEXT): $(top_srcdir)/internal/gc.h scheduler.$(OBJEXT): $(top_srcdir)/internal/imemo.h +scheduler.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h scheduler.$(OBJEXT): $(top_srcdir)/internal/serial.h scheduler.$(OBJEXT): $(top_srcdir)/internal/static_assert.h scheduler.$(OBJEXT): $(top_srcdir)/internal/thread.h @@ -16431,6 +16463,7 @@ shape.$(OBJEXT): $(top_srcdir)/internal/error.h shape.$(OBJEXT): $(top_srcdir)/internal/gc.h shape.$(OBJEXT): $(top_srcdir)/internal/imemo.h shape.$(OBJEXT): $(top_srcdir)/internal/object.h +shape.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h shape.$(OBJEXT): $(top_srcdir)/internal/serial.h shape.$(OBJEXT): $(top_srcdir)/internal/static_assert.h shape.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -17647,6 +17680,7 @@ struct.$(OBJEXT): $(top_srcdir)/internal/hash.h struct.$(OBJEXT): $(top_srcdir)/internal/imemo.h struct.$(OBJEXT): $(top_srcdir)/internal/object.h struct.$(OBJEXT): $(top_srcdir)/internal/proc.h +struct.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h struct.$(OBJEXT): $(top_srcdir)/internal/serial.h struct.$(OBJEXT): $(top_srcdir)/internal/static_assert.h struct.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -17857,6 +17891,7 @@ symbol.$(OBJEXT): $(top_srcdir)/internal/gc.h symbol.$(OBJEXT): $(top_srcdir)/internal/hash.h symbol.$(OBJEXT): $(top_srcdir)/internal/imemo.h symbol.$(OBJEXT): $(top_srcdir)/internal/object.h +symbol.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h symbol.$(OBJEXT): $(top_srcdir)/internal/serial.h symbol.$(OBJEXT): $(top_srcdir)/internal/static_assert.h symbol.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -18078,6 +18113,7 @@ thread.$(OBJEXT): $(top_srcdir)/internal/imemo.h thread.$(OBJEXT): $(top_srcdir)/internal/io.h thread.$(OBJEXT): $(top_srcdir)/internal/object.h thread.$(OBJEXT): $(top_srcdir)/internal/proc.h +thread.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h thread.$(OBJEXT): $(top_srcdir)/internal/serial.h thread.$(OBJEXT): $(top_srcdir)/internal/signal.h thread.$(OBJEXT): $(top_srcdir)/internal/static_assert.h @@ -18331,6 +18367,7 @@ time.$(OBJEXT): $(top_srcdir)/internal/hash.h time.$(OBJEXT): $(top_srcdir)/internal/imemo.h time.$(OBJEXT): $(top_srcdir)/internal/numeric.h time.$(OBJEXT): $(top_srcdir)/internal/rational.h +time.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h time.$(OBJEXT): $(top_srcdir)/internal/serial.h time.$(OBJEXT): $(top_srcdir)/internal/static_assert.h time.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -18894,6 +18931,7 @@ variable.$(OBJEXT): $(top_srcdir)/internal/hash.h variable.$(OBJEXT): $(top_srcdir)/internal/imemo.h variable.$(OBJEXT): $(top_srcdir)/internal/object.h variable.$(OBJEXT): $(top_srcdir)/internal/re.h +variable.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h variable.$(OBJEXT): $(top_srcdir)/internal/serial.h variable.$(OBJEXT): $(top_srcdir)/internal/static_assert.h variable.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -19106,6 +19144,7 @@ version.$(OBJEXT): $(top_srcdir)/internal/cmdlineopt.h version.$(OBJEXT): $(top_srcdir)/internal/compilers.h version.$(OBJEXT): $(top_srcdir)/internal/gc.h version.$(OBJEXT): $(top_srcdir)/internal/imemo.h +version.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h version.$(OBJEXT): $(top_srcdir)/internal/serial.h version.$(OBJEXT): $(top_srcdir)/internal/static_assert.h version.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -19594,6 +19633,7 @@ vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/compilers.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/error.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/gc.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/imemo.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/serial.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/static_assert.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -19823,6 +19863,7 @@ vm_dump.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/compilers.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/gc.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/imemo.h +vm_dump.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/serial.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/static_assert.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -20051,6 +20092,7 @@ vm_sync.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/compilers.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/gc.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/imemo.h +vm_sync.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/serial.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/static_assert.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/thread.h @@ -20259,6 +20301,7 @@ vm_trace.$(OBJEXT): $(top_srcdir)/internal/compilers.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/gc.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/hash.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/imemo.h +vm_trace.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/serial.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/static_assert.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/symbol.h diff --git a/ext/objspace/depend b/ext/objspace/depend index 85e99a71b4149a..aa0c5c5d7dd1b9 100644 --- a/ext/objspace/depend +++ b/ext/objspace/depend @@ -182,6 +182,7 @@ object_tracing.o: $(top_srcdir)/internal/basic_operators.h object_tracing.o: $(top_srcdir)/internal/compilers.h object_tracing.o: $(top_srcdir)/internal/gc.h object_tracing.o: $(top_srcdir)/internal/imemo.h +object_tracing.o: $(top_srcdir)/internal/sanitizers.h object_tracing.o: $(top_srcdir)/internal/serial.h object_tracing.o: $(top_srcdir)/internal/static_assert.h object_tracing.o: $(top_srcdir)/internal/vm.h diff --git a/ext/ripper/depend b/ext/ripper/depend index a07825fd405de8..3b9b890de8347a 100644 --- a/ext/ripper/depend +++ b/ext/ripper/depend @@ -593,6 +593,7 @@ ripper.o: $(top_srcdir)/internal/parse.h ripper.o: $(top_srcdir)/internal/rational.h ripper.o: $(top_srcdir)/internal/re.h ripper.o: $(top_srcdir)/internal/ruby_parser.h +ripper.o: $(top_srcdir)/internal/sanitizers.h ripper.o: $(top_srcdir)/internal/serial.h ripper.o: $(top_srcdir)/internal/static_assert.h ripper.o: $(top_srcdir)/internal/string.h diff --git a/ext/socket/depend b/ext/socket/depend index 3db153bb1ccbf5..e95555ea921a41 100644 --- a/ext/socket/depend +++ b/ext/socket/depend @@ -199,6 +199,7 @@ ancdata.o: $(top_srcdir)/internal/error.h ancdata.o: $(top_srcdir)/internal/gc.h ancdata.o: $(top_srcdir)/internal/imemo.h ancdata.o: $(top_srcdir)/internal/io.h +ancdata.o: $(top_srcdir)/internal/sanitizers.h ancdata.o: $(top_srcdir)/internal/serial.h ancdata.o: $(top_srcdir)/internal/static_assert.h ancdata.o: $(top_srcdir)/internal/string.h @@ -408,6 +409,7 @@ basicsocket.o: $(top_srcdir)/internal/error.h basicsocket.o: $(top_srcdir)/internal/gc.h basicsocket.o: $(top_srcdir)/internal/imemo.h basicsocket.o: $(top_srcdir)/internal/io.h +basicsocket.o: $(top_srcdir)/internal/sanitizers.h basicsocket.o: $(top_srcdir)/internal/serial.h basicsocket.o: $(top_srcdir)/internal/static_assert.h basicsocket.o: $(top_srcdir)/internal/string.h @@ -617,6 +619,7 @@ constants.o: $(top_srcdir)/internal/error.h constants.o: $(top_srcdir)/internal/gc.h constants.o: $(top_srcdir)/internal/imemo.h constants.o: $(top_srcdir)/internal/io.h +constants.o: $(top_srcdir)/internal/sanitizers.h constants.o: $(top_srcdir)/internal/serial.h constants.o: $(top_srcdir)/internal/static_assert.h constants.o: $(top_srcdir)/internal/string.h @@ -827,6 +830,7 @@ ifaddr.o: $(top_srcdir)/internal/error.h ifaddr.o: $(top_srcdir)/internal/gc.h ifaddr.o: $(top_srcdir)/internal/imemo.h ifaddr.o: $(top_srcdir)/internal/io.h +ifaddr.o: $(top_srcdir)/internal/sanitizers.h ifaddr.o: $(top_srcdir)/internal/serial.h ifaddr.o: $(top_srcdir)/internal/static_assert.h ifaddr.o: $(top_srcdir)/internal/string.h @@ -1036,6 +1040,7 @@ init.o: $(top_srcdir)/internal/error.h init.o: $(top_srcdir)/internal/gc.h init.o: $(top_srcdir)/internal/imemo.h init.o: $(top_srcdir)/internal/io.h +init.o: $(top_srcdir)/internal/sanitizers.h init.o: $(top_srcdir)/internal/serial.h init.o: $(top_srcdir)/internal/static_assert.h init.o: $(top_srcdir)/internal/string.h @@ -1245,6 +1250,7 @@ ipsocket.o: $(top_srcdir)/internal/error.h ipsocket.o: $(top_srcdir)/internal/gc.h ipsocket.o: $(top_srcdir)/internal/imemo.h ipsocket.o: $(top_srcdir)/internal/io.h +ipsocket.o: $(top_srcdir)/internal/sanitizers.h ipsocket.o: $(top_srcdir)/internal/serial.h ipsocket.o: $(top_srcdir)/internal/static_assert.h ipsocket.o: $(top_srcdir)/internal/string.h @@ -1454,6 +1460,7 @@ option.o: $(top_srcdir)/internal/error.h option.o: $(top_srcdir)/internal/gc.h option.o: $(top_srcdir)/internal/imemo.h option.o: $(top_srcdir)/internal/io.h +option.o: $(top_srcdir)/internal/sanitizers.h option.o: $(top_srcdir)/internal/serial.h option.o: $(top_srcdir)/internal/static_assert.h option.o: $(top_srcdir)/internal/string.h @@ -1663,6 +1670,7 @@ raddrinfo.o: $(top_srcdir)/internal/error.h raddrinfo.o: $(top_srcdir)/internal/gc.h raddrinfo.o: $(top_srcdir)/internal/imemo.h raddrinfo.o: $(top_srcdir)/internal/io.h +raddrinfo.o: $(top_srcdir)/internal/sanitizers.h raddrinfo.o: $(top_srcdir)/internal/serial.h raddrinfo.o: $(top_srcdir)/internal/static_assert.h raddrinfo.o: $(top_srcdir)/internal/string.h @@ -1872,6 +1880,7 @@ socket.o: $(top_srcdir)/internal/error.h socket.o: $(top_srcdir)/internal/gc.h socket.o: $(top_srcdir)/internal/imemo.h socket.o: $(top_srcdir)/internal/io.h +socket.o: $(top_srcdir)/internal/sanitizers.h socket.o: $(top_srcdir)/internal/serial.h socket.o: $(top_srcdir)/internal/static_assert.h socket.o: $(top_srcdir)/internal/string.h @@ -2081,6 +2090,7 @@ sockssocket.o: $(top_srcdir)/internal/error.h sockssocket.o: $(top_srcdir)/internal/gc.h sockssocket.o: $(top_srcdir)/internal/imemo.h sockssocket.o: $(top_srcdir)/internal/io.h +sockssocket.o: $(top_srcdir)/internal/sanitizers.h sockssocket.o: $(top_srcdir)/internal/serial.h sockssocket.o: $(top_srcdir)/internal/static_assert.h sockssocket.o: $(top_srcdir)/internal/string.h @@ -2290,6 +2300,7 @@ tcpserver.o: $(top_srcdir)/internal/error.h tcpserver.o: $(top_srcdir)/internal/gc.h tcpserver.o: $(top_srcdir)/internal/imemo.h tcpserver.o: $(top_srcdir)/internal/io.h +tcpserver.o: $(top_srcdir)/internal/sanitizers.h tcpserver.o: $(top_srcdir)/internal/serial.h tcpserver.o: $(top_srcdir)/internal/static_assert.h tcpserver.o: $(top_srcdir)/internal/string.h @@ -2499,6 +2510,7 @@ tcpsocket.o: $(top_srcdir)/internal/error.h tcpsocket.o: $(top_srcdir)/internal/gc.h tcpsocket.o: $(top_srcdir)/internal/imemo.h tcpsocket.o: $(top_srcdir)/internal/io.h +tcpsocket.o: $(top_srcdir)/internal/sanitizers.h tcpsocket.o: $(top_srcdir)/internal/serial.h tcpsocket.o: $(top_srcdir)/internal/static_assert.h tcpsocket.o: $(top_srcdir)/internal/string.h @@ -2708,6 +2720,7 @@ udpsocket.o: $(top_srcdir)/internal/error.h udpsocket.o: $(top_srcdir)/internal/gc.h udpsocket.o: $(top_srcdir)/internal/imemo.h udpsocket.o: $(top_srcdir)/internal/io.h +udpsocket.o: $(top_srcdir)/internal/sanitizers.h udpsocket.o: $(top_srcdir)/internal/serial.h udpsocket.o: $(top_srcdir)/internal/static_assert.h udpsocket.o: $(top_srcdir)/internal/string.h @@ -2917,6 +2930,7 @@ unixserver.o: $(top_srcdir)/internal/error.h unixserver.o: $(top_srcdir)/internal/gc.h unixserver.o: $(top_srcdir)/internal/imemo.h unixserver.o: $(top_srcdir)/internal/io.h +unixserver.o: $(top_srcdir)/internal/sanitizers.h unixserver.o: $(top_srcdir)/internal/serial.h unixserver.o: $(top_srcdir)/internal/static_assert.h unixserver.o: $(top_srcdir)/internal/string.h @@ -3126,6 +3140,7 @@ unixsocket.o: $(top_srcdir)/internal/error.h unixsocket.o: $(top_srcdir)/internal/gc.h unixsocket.o: $(top_srcdir)/internal/imemo.h unixsocket.o: $(top_srcdir)/internal/io.h +unixsocket.o: $(top_srcdir)/internal/sanitizers.h unixsocket.o: $(top_srcdir)/internal/serial.h unixsocket.o: $(top_srcdir)/internal/static_assert.h unixsocket.o: $(top_srcdir)/internal/string.h diff --git a/gc.c b/gc.c index a4de9573402bbe..2870b39bcf28a3 100644 --- a/gc.c +++ b/gc.c @@ -953,6 +953,11 @@ typedef struct rb_objspace { rb_darray(VALUE *) weak_references; rb_postponed_job_handle_t finalize_deferred_pjob; + +#ifdef RUBY_ASAN_ENABLED + rb_execution_context_t *marking_machine_context_ec; +#endif + } rb_objspace_t; @@ -6821,6 +6826,26 @@ mark_const_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl) static void each_stack_location(rb_objspace_t *objspace, const rb_execution_context_t *ec, const VALUE *stack_start, const VALUE *stack_end, void (*cb)(rb_objspace_t *, VALUE)); +static void +gc_mark_machine_stack_location_maybe(rb_objspace_t *objspace, VALUE obj) +{ + gc_mark_maybe(objspace, obj); + +#ifdef RUBY_ASAN_ENABLED + rb_execution_context_t *ec = objspace->marking_machine_context_ec; + void *fake_frame_start; + void *fake_frame_end; + bool is_fake_frame = asan_get_fake_stack_extents( + ec->thread_ptr->asan_fake_stack_handle, obj, + ec->machine.stack_start, ec->machine.stack_end, + &fake_frame_start, &fake_frame_end + ); + if (is_fake_frame) { + each_stack_location(objspace, ec, fake_frame_start, fake_frame_end, gc_mark_maybe); + } +#endif +} + #if defined(__wasm__) @@ -6882,9 +6907,16 @@ mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec SET_STACK_END; GET_STACK_BOUNDS(stack_start, stack_end, 1); - each_location(objspace, save_regs_gc_mark.v, numberof(save_regs_gc_mark.v), gc_mark_maybe); +#ifdef RUBY_ASAN_ENABLED + objspace->marking_machine_context_ec = ec; +#endif - each_stack_location(objspace, ec, stack_start, stack_end, gc_mark_maybe); + each_location(objspace, save_regs_gc_mark.v, numberof(save_regs_gc_mark.v), gc_mark_machine_stack_location_maybe); + each_stack_location(objspace, ec, stack_start, stack_end, gc_mark_machine_stack_location_maybe); + +#ifdef RUBY_ASAN_ENABLED + objspace->marking_machine_context_ec = NULL; +#endif } #endif diff --git a/internal/sanitizers.h b/internal/sanitizers.h index d444903aa0b36e..a0d099e525a983 100644 --- a/internal/sanitizers.h +++ b/internal/sanitizers.h @@ -213,4 +213,68 @@ asan_get_real_stack_addr(void* slot) return addr ? addr : slot; } +/*! + * Gets the current thread's fake stack handle, which can be passed into get_fake_stack_extents + * + * \retval An opaque value which can be passed to asan_get_fake_stack_extents + */ +static inline void * +asan_get_thread_fake_stack_handle(void) +{ + return __asan_get_current_fake_stack(); +} + +/*! + * Checks if the given VALUE _actually_ represents a pointer to an ASAN fake stack. + * + * If the given slot _is_ actually a reference to an ASAN fake stack, and that fake stack + * contains the real values for the passed-in range of machine stack addresses, returns true + * and the range of the fake stack through the outparams. + * + * Otherwise, returns false, and sets the outparams to NULL. + * + * Note that this function expects "start" to be > "end" on downward-growing stack architectures; + * + * \param[in] thread_fake_stack_handle The asan fake stack reference for the thread we're scanning + * \param[in] slot The value on the machine stack we want to inspect + * \param[in] machine_stack_start The extents of the real machine stack on which slot lives + * \param[in] machine_stack_end The extents of the real machine stack on which slot lives + * \param[out] fake_stack_start_out The extents of the fake stack which contains real VALUEs + * \param[out] fake_stack_end_out The extents of the fake stack which contains real VALUEs + * \return Whether slot is a pointer to a fake stack for the given machine stack range +*/ + +static inline bool +asan_get_fake_stack_extents(void *thread_fake_stack_handle, VALUE slot, + void *machine_stack_start, void *machine_stack_end, + void **fake_stack_start_out, void **fake_stack_end_out) +{ + /* the ifdef is needed here to suppress a warning about fake_frame_{start/end} being + uninitialized if __asan_addr_is_in_fake_stack is an empty macro */ +#ifdef RUBY_ASAN_ENABLED + void *fake_frame_start; + void *fake_frame_end; + void *real_stack_frame = __asan_addr_is_in_fake_stack( + thread_fake_stack_handle, (void *)slot, &fake_frame_start, &fake_frame_end + ); + if (real_stack_frame) { + bool in_range; +#if STACK_GROW_DIRECTION < 0 + in_range = machine_stack_start >= real_stack_frame && real_stack_frame >= machine_stack_end; +#else + in_range = machine_stack_start <= real_stack_frame && real_stack_frame <= machine_stack_end; +#endif + if (in_range) { + *fake_stack_start_out = fake_frame_start; + *fake_stack_end_out = fake_frame_end; + return true; + } + } +#endif + *fake_stack_start_out = 0; + *fake_stack_end_out = 0; + return false; +} + + #endif /* INTERNAL_SANITIZERS_H */ diff --git a/thread.c b/thread.c index e7a9d7cd9bdcc7..27a6ffb95589d1 100644 --- a/thread.c +++ b/thread.c @@ -525,6 +525,9 @@ void ruby_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame) { native_thread_init_stack(th, local_in_parent_frame); +#ifdef RUBY_ASAN_ENABLED + th->asan_fake_stack_handle = asan_get_thread_fake_stack_handle(); +#endif } const VALUE * diff --git a/vm_core.h b/vm_core.h index f1928d1ee2456c..743071ac85fd64 100644 --- a/vm_core.h +++ b/vm_core.h @@ -94,6 +94,7 @@ extern int ruby_assert_critical_section_entered; #include "internal.h" #include "internal/array.h" #include "internal/basic_operators.h" +#include "internal/sanitizers.h" #include "internal/serial.h" #include "internal/vm.h" #include "method.h" @@ -1153,6 +1154,11 @@ typedef struct rb_thread_struct { void **specific_storage; struct rb_ext_config ext_config; + +#ifdef RUBY_ASAN_ENABLED + void *asan_fake_stack_handle; +#endif + } rb_thread_t; static inline unsigned int From bbd249e351af7e4929b518a5de73a832b5617273 Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Thu, 18 Jan 2024 19:26:03 -0500 Subject: [PATCH 299/640] YJIT: Properly reject keyword splat with `yield` We don't have support for keyword splat anywhere, but we tried to compile these anyways in case of `invokeblock`. This led to bad things happening such as passing the wrong value and passing a hash into rb_yjit_array_len(), which raised in the middle of compilation. [Bug #20192] --- bootstraptest/test_yjit.rb | 7 +++++++ yjit/src/codegen.rs | 9 +++++++++ yjit/src/stats.rs | 2 ++ 3 files changed, 18 insertions(+) diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index 5b53e8089bfbf4..a6b0f8f19c82ad 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -11,6 +11,13 @@ def call_foo call_foo } +# regression test for keyword splat with yield +assert_equal 'nil', %q{ + def splat_kw(kwargs) = yield(**kwargs) + + splat_kw({}) { _1 }.inspect +} + # regression test for arity check with splat assert_equal '[:ae, :ae]', %q{ def req_one(a_, b_ = 1) = raise diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 0471f7a20743dc..956bcb1aeb3cf4 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -6131,6 +6131,7 @@ fn gen_send_iseq( exit_if_tail_call(asm, ci)?; exit_if_has_post(asm, iseq)?; exit_if_has_kwrest(asm, iseq)?; + exit_if_kw_splat(asm, flags)?; exit_if_splat_and_ruby2_keywords(asm, jit, flags)?; exit_if_has_rest_and_captured(asm, iseq_has_rest, captured_opnd)?; exit_if_has_rest_and_supplying_kws(asm, iseq_has_rest, iseq, supplying_kws)?; @@ -6261,6 +6262,9 @@ fn gen_send_iseq( let array = jit.peek_at_stack(&asm.ctx, if block_arg { 1 } else { 0 }) ; let array_length = if array == Qnil { 0 + } else if unsafe { !RB_TYPE_P(array, RUBY_T_ARRAY) } { + gen_counter_incr(asm, Counter::send_iseq_splat_not_array); + return None; } else { unsafe { rb_yjit_array_len(array) as u32} }; @@ -6939,6 +6943,11 @@ fn exit_if_has_kwrest(asm: &mut Assembler, iseq: *const rb_iseq_t) -> Option<()> exit_if(asm, unsafe { get_iseq_flags_has_kwrest(iseq) }, Counter::send_iseq_has_kwrest) } +#[must_use] +fn exit_if_kw_splat(asm: &mut Assembler, flags: u32) -> Option<()> { + exit_if(asm, flags & VM_CALL_KW_SPLAT != 0, Counter::send_iseq_kw_splat) +} + #[must_use] fn exit_if_splat_and_ruby2_keywords(asm: &mut Assembler, jit: &mut JITState, flags: u32) -> Option<()> { // In order to handle backwards compatibility between ruby 3 and 2 diff --git a/yjit/src/stats.rs b/yjit/src/stats.rs index 264843117a683b..1dd5f57b2bb16f 100644 --- a/yjit/src/stats.rs +++ b/yjit/src/stats.rs @@ -333,6 +333,7 @@ make_counters! { send_iseq_clobbering_block_arg, send_iseq_leaf_builtin_block_arg_block_param, send_iseq_only_keywords, + send_iseq_kw_splat, send_iseq_kwargs_req_and_opt_missing, send_iseq_kwargs_mismatch, send_iseq_has_post, @@ -340,6 +341,7 @@ make_counters! { send_iseq_has_no_kw, send_iseq_accepts_no_kwarg, send_iseq_materialized_block, + send_iseq_splat_not_array, send_iseq_splat_with_opt, send_iseq_splat_with_kw, send_iseq_missing_optional_kw, From 7b253cfea4212bc97a37514b9ffa8405de04748c Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Thu, 18 Jan 2024 19:53:28 -0500 Subject: [PATCH 300/640] RJIT: Properly reject keyword splat with `yield` See the fix for YJIT. --- lib/ruby_vm/rjit/insn_compiler.rb | 5 +++++ rjit_c.h | 1 + rjit_c.rb | 1 + 3 files changed, 7 insertions(+) diff --git a/lib/ruby_vm/rjit/insn_compiler.rb b/lib/ruby_vm/rjit/insn_compiler.rb index 6440944944e34d..b1f031a9ae1e2b 100644 --- a/lib/ruby_vm/rjit/insn_compiler.rb +++ b/lib/ruby_vm/rjit/insn_compiler.rb @@ -4452,6 +4452,11 @@ def jit_call_iseq(jit, ctx, asm, cme, calling, iseq, frame_type: nil, prev_ep: n return CantCompile end + if flags & C::VM_CALL_KW_SPLAT != 0 + asm.incr_counter(:send_iseq_kw_splat) + return CantCompile + end + if iseq_has_rest && opt_num != 0 asm.incr_counter(:send_iseq_has_rest_and_optional) return CantCompile diff --git a/rjit_c.h b/rjit_c.h index 339dfc38fc85b7..029f811637b534 100644 --- a/rjit_c.h +++ b/rjit_c.h @@ -69,6 +69,7 @@ RJIT_RUNTIME_COUNTERS( send_iseq_has_rest, send_iseq_block_arg0_splat, send_iseq_kw_call, + send_iseq_kw_splat, send_iseq_splat, send_iseq_has_rest_and_optional, send_iseq_arity_error, diff --git a/rjit_c.rb b/rjit_c.rb index f660e879eeecf0..67ac8729d4f574 100644 --- a/rjit_c.rb +++ b/rjit_c.rb @@ -1388,6 +1388,7 @@ def C.rb_rjit_runtime_counters send_iseq_has_rest: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_has_rest)")], send_iseq_block_arg0_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_block_arg0_splat)")], send_iseq_kw_call: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_kw_call)")], + send_iseq_kw_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_kw_splat)")], send_iseq_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_splat)")], send_iseq_has_rest_and_optional: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_has_rest_and_optional)")], send_iseq_arity_error: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_arity_error)")], From 4e47671073f2b9d03430a1ba05f5b0451343f006 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 17 Jan 2024 19:10:53 +0100 Subject: [PATCH 301/640] [rubygems/rubygems] Test that regular gems don't shadow default gems https://github.com/rubygems/rubygems/commit/b8ca5950a6 --- test/rubygems/test_require.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/rubygems/test_require.rb b/test/rubygems/test_require.rb index fc5f219490d7fc..b3926afe1525ae 100644 --- a/test/rubygems/test_require.rb +++ b/test/rubygems/test_require.rb @@ -489,6 +489,17 @@ def test_default_gem_and_normal_gem assert_equal %w[default-3.0], loaded_spec_names end + def test_normal_gem_does_not_shadow_default_gem + default_gem_spec = new_default_spec("foo", "2.0", nil, "foo.rb") + install_default_gems(default_gem_spec) + + normal_gem_spec = util_spec("fake-foo", "3.0", nil, "lib/foo.rb") + install_specs(normal_gem_spec) + + assert_require "foo" + assert_equal %w[foo-2.0], loaded_spec_names + end + def test_normal_gems_with_overridden_load_error_message normal_gem_spec = util_spec("normal", "3.0", nil, "lib/normal/gem.rb") From ac636f5709feb1d9d7a0c46a86be153be765cf21 Mon Sep 17 00:00:00 2001 From: Sutou Kouhei Date: Sat, 13 Jan 2024 06:34:58 +0900 Subject: [PATCH 302/640] [ruby/strscan] Bump version https://github.com/ruby/strscan/commit/d6f97ec102 --- ext/strscan/strscan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/strscan/strscan.c b/ext/strscan/strscan.c index 7dbd971ae98d33..4598d13c9096be 100644 --- a/ext/strscan/strscan.c +++ b/ext/strscan/strscan.c @@ -22,7 +22,7 @@ extern size_t onig_region_memsize(const struct re_registers *regs); #include -#define STRSCAN_VERSION "3.0.8" +#define STRSCAN_VERSION "3.0.9" /* ======================================================================= Data Type Definitions From 91f35305807f7303bfb58ccdffe86820a2300b8c Mon Sep 17 00:00:00 2001 From: NAITOH Jun Date: Sun, 14 Jan 2024 21:26:10 +0900 Subject: [PATCH 303/640] [ruby/strscan] Add test to check encoding for empty string (https://github.com/ruby/strscan/pull/80) See: https://github.com/ruby/strscan/issues/78#issuecomment-1890849891 https://github.com/ruby/strscan/commit/d0508518a9 --- test/strscan/test_stringscanner.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/strscan/test_stringscanner.rb b/test/strscan/test_stringscanner.rb index 29626b159f7032..d15c1d85684897 100644 --- a/test/strscan/test_stringscanner.rb +++ b/test/strscan/test_stringscanner.rb @@ -558,6 +558,16 @@ def test_matched_size assert_nil s.matched_size end + def test_empty_encoding_utf8 + ss = create_string_scanner('') + assert_equal(Encoding::UTF_8, ss.rest.encoding) + end + + def test_empty_encoding_ascii_8bit + ss = create_string_scanner(''.dup.force_encoding("ASCII-8BIT")) + assert_equal(Encoding::ASCII_8BIT, ss.rest.encoding) + end + def test_encoding ss = create_string_scanner("\xA1\xA2".dup.force_encoding("euc-jp")) assert_equal(Encoding::EUC_JP, ss.scan(/./e).encoding) From b2ec4308d69a13f3ff3b1b3128d52b3cb0222d34 Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Tue, 9 Jan 2024 13:20:08 +0000 Subject: [PATCH 304/640] [ruby/irb] Bump version to v1.11.1 (https://github.com/ruby/irb/pull/837) https://github.com/ruby/irb/commit/f052097c4b --- lib/irb/version.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/irb/version.rb b/lib/irb/version.rb index c0be6d91e59c07..f2e0e7d7f16cc8 100644 --- a/lib/irb/version.rb +++ b/lib/irb/version.rb @@ -5,7 +5,7 @@ # module IRB # :nodoc: - VERSION = "1.11.0" + VERSION = "1.11.1" @RELEASE_VERSION = VERSION - @LAST_UPDATE_DATE = "2023-12-19" + @LAST_UPDATE_DATE = "2024-01-08" end From 74e5665ec14312dab702e607c37b024fecf91c7c Mon Sep 17 00:00:00 2001 From: git Date: Fri, 19 Jan 2024 02:16:35 +0000 Subject: [PATCH 305/640] Update default gems list at b2ec4308d69a13f3ff3b1b3128d52b [ci skip] --- NEWS.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 009c308836f7a9..3dd6e7847c8737 100644 --- a/NEWS.md +++ b/NEWS.md @@ -28,10 +28,11 @@ The following default gems are updated. * erb 4.0.4 * fiddle 1.1.3 * io-console 0.7.2 +* irb 1.11.1 * net-http 0.4.1 * reline 0.4.2 * stringio 3.1.1 -* strscan 3.0.8 +* strscan 3.0.9 The following bundled gems are updated. From 8044e57907bc5a066ca9ef309d90c62906f8e2ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 11 Jan 2024 23:02:11 +0100 Subject: [PATCH 306/640] [rubygems/rubygems] Add a comment to explain default gem activation https://github.com/rubygems/rubygems/commit/291128268f --- lib/rubygems/core_ext/kernel_require.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/rubygems/core_ext/kernel_require.rb b/lib/rubygems/core_ext/kernel_require.rb index bbd7852e92f8c6..46954c534da324 100644 --- a/lib/rubygems/core_ext/kernel_require.rb +++ b/lib/rubygems/core_ext/kernel_require.rb @@ -39,6 +39,9 @@ def require(path) # :doc: RUBYGEMS_ACTIVATION_MONITOR.synchronize do path = File.path(path) + # If +path+ belongs to a default gem, we activate it and then go straight + # to normal require + if spec = Gem.find_unresolved_default_spec(path) # Ensure -I beats a default gem resolved_path = begin From f1f5f22d22a149f20e019728b1ab35593d29d81a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 11 Jan 2024 21:53:26 +0100 Subject: [PATCH 307/640] [rubygems/rubygems] Fix `require` of a default gem when unresolved gems depend on it The following conditions must be met: * A default gem is required. * A previous require left some gems unresolved, and those dependencies themselves depend on the default gem. In this case, rubygems require will first activate the default version of the gem, then try to activate another unresolved version of the default gem that conflicts with the first activation. The solution is, if we are in the middle of requiring a default gem, skip this step, because we have already activated it successfully. https://github.com/rubygems/rubygems/commit/8cd5608db5 Co-authored-by: Stan Hu --- lib/rubygems/core_ext/kernel_require.rb | 2 ++ test/rubygems/test_require.rb | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/lib/rubygems/core_ext/kernel_require.rb b/lib/rubygems/core_ext/kernel_require.rb index 46954c534da324..50e3ea89b4b884 100644 --- a/lib/rubygems/core_ext/kernel_require.rb +++ b/lib/rubygems/core_ext/kernel_require.rb @@ -62,6 +62,8 @@ def require(path) # :doc: Kernel.send(:gem, spec.name, Gem::Requirement.default_prerelease) unless resolved_path + + next end # If there are no unresolved deps, then we can use just try diff --git a/test/rubygems/test_require.rb b/test/rubygems/test_require.rb index b3926afe1525ae..7f5584ea8ace42 100644 --- a/test/rubygems/test_require.rb +++ b/test/rubygems/test_require.rb @@ -540,6 +540,26 @@ def test_default_gem_prerelease assert_equal %w[default-3.0.0.rc2], loaded_spec_names end + def test_default_gem_with_unresolved_gems_depending_on_it + net_http_old = util_spec "net-http", "0.1.1", nil, "lib/net/http.rb" + install_gem net_http_old + + net_http_default = new_default_spec "net-http", "0.3.0", nil, "net/http.rb" + install_default_gems net_http_default + + faraday_1 = util_spec "faraday", "1", { "net-http" => ">= 0" } + install_gem faraday_1 + + faraday_2 = util_spec "faraday", "2", { "net-http" => ">= 0" } + install_gem faraday_2 + + chef = util_spec "chef", "1", { "faraday" => [">= 1", "< 3"] }, "lib/chef.rb" + install_gem chef + + assert_require "chef" + assert_require "net/http" + end + def loaded_spec_names Gem.loaded_specs.values.map(&:full_name).sort end From db44088c2a92040879386aa5f268db4c858e4e5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 12 Jan 2024 14:53:40 +0100 Subject: [PATCH 308/640] [rubygems/rubygems] Fix activation conflicts when circularly requiring a gem If a gem is required circular, and there are unresolved specs depending on it, we may end up in an activation conflict. The solution is to not try to activate unresolved gems when requiring a default gem, regardless of it having already been activated or not. https://github.com/rubygems/rubygems/commit/3b2b8f4e3e --- lib/rubygems.rb | 7 +++++ lib/rubygems/core_ext/kernel_require.rb | 8 +++-- test/rubygems/test_require.rb | 39 +++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/lib/rubygems.rb b/lib/rubygems.rb index 47b1ce69d26608..ad7ab1075636a8 100644 --- a/lib/rubygems.rb +++ b/lib/rubygems.rb @@ -1216,6 +1216,13 @@ def register_default_spec(spec) ## # Find a Gem::Specification of default gem from +path+ + def find_default_spec(path) + @path_to_default_spec_map[path] + end + + ## + # Find an unresolved Gem::Specification of default gem from +path+ + def find_unresolved_default_spec(path) default_spec = @path_to_default_spec_map[path] default_spec if default_spec && loaded_specs[default_spec.name] != default_spec diff --git a/lib/rubygems/core_ext/kernel_require.rb b/lib/rubygems/core_ext/kernel_require.rb index 50e3ea89b4b884..073966b696ccde 100644 --- a/lib/rubygems/core_ext/kernel_require.rb +++ b/lib/rubygems/core_ext/kernel_require.rb @@ -42,7 +42,11 @@ def require(path) # :doc: # If +path+ belongs to a default gem, we activate it and then go straight # to normal require - if spec = Gem.find_unresolved_default_spec(path) + if spec = Gem.find_default_spec(path) + name = spec.name + + next if Gem.loaded_specs[name] + # Ensure -I beats a default gem resolved_path = begin rp = nil @@ -60,7 +64,7 @@ def require(path) # :doc: rp end - Kernel.send(:gem, spec.name, Gem::Requirement.default_prerelease) unless + Kernel.send(:gem, name, Gem::Requirement.default_prerelease) unless resolved_path next diff --git a/test/rubygems/test_require.rb b/test/rubygems/test_require.rb index 7f5584ea8ace42..f595d8e08ecd2e 100644 --- a/test/rubygems/test_require.rb +++ b/test/rubygems/test_require.rb @@ -560,6 +560,45 @@ def test_default_gem_with_unresolved_gems_depending_on_it assert_require "net/http" end + def test_default_gem_required_circulary_with_unresolved_gems_depending_on_it + net_http_old = util_spec "net-http", "0.1.1", nil, "lib/net/http.rb" + install_gem net_http_old + + net_http_default = new_default_spec "net-http", "0.3.0", nil, "net/http.rb" + net_http_default_path = File.join(@tempdir, "default_gems", "lib", "net/http.rb") + install_default_gems net_http_default + File.write(net_http_default_path, 'require "net/http"') + + faraday_1 = util_spec "faraday", "1", { "net-http" => ">= 0" } + install_gem faraday_1 + + faraday_2 = util_spec "faraday", "2", { "net-http" => ">= 0" } + install_gem faraday_2 + + chef = util_spec "chef", "1", { "faraday" => [">= 1", "< 3"] }, "lib/chef.rb" + install_gem chef + + assert_require "chef" + + out, err = capture_output do + assert_require "net/http" + end + + assert_empty out + + circular_require_warning = false + + err_lines = err.split("\n").reject do |line| + if line.include?("circular require") + circular_require_warning = true + elsif circular_require_warning # ignore backtrace lines for circular require warning + circular_require_warning = line.start_with?(/[\s]/) + end + end + + assert_empty err_lines + end + def loaded_spec_names Gem.loaded_specs.values.map(&:full_name).sort end From a8fa28ab8089011695618d9cdac87c2d6a188482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 15 Jan 2024 16:03:52 +0100 Subject: [PATCH 309/640] Bump uri version used in development --- tool/bundler/dev_gems.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tool/bundler/dev_gems.rb b/tool/bundler/dev_gems.rb index 5e5ba94ec215cf..cb4b556d2fbc66 100644 --- a/tool/bundler/dev_gems.rb +++ b/tool/bundler/dev_gems.rb @@ -13,7 +13,7 @@ gem "rspec-core", "~> 3.12" gem "rspec-expectations", "~> 3.12" gem "rspec-mocks", "~> 3.12" -gem "uri", "~> 0.12.0" +gem "uri", "~> 0.13.0" group :doc do gem "nronn", "~> 0.11.1", platform: :ruby From 7265a5be01c269dcc54550ca8cd8ba1ce780f9ef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 02:08:06 +0000 Subject: [PATCH 310/640] Bump actions/upload-artifact from 4.1.0 to 4.2.0 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.1.0 to 4.2.0. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/1eb3cb2b3e0f29609092a73eb033bb759a334595...694cdabd8bdb0f10b2cea11669e1bf5453eed0a6) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/wasm.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml index c6ab3ffa40c921..3586e3ebe223e0 100644 --- a/.github/workflows/wasm.yml +++ b/.github/workflows/wasm.yml @@ -136,7 +136,7 @@ jobs: - run: tar cfz ../install.tar.gz -C ../install . - name: Upload artifacts - uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 + uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 with: name: ruby-wasm-install path: ${{ github.workspace }}/install.tar.gz @@ -164,7 +164,7 @@ jobs: - name: Save Pull Request number if: ${{ github.event_name == 'pull_request' }} run: echo "${{ github.event.pull_request.number }}" >> ${{ github.workspace }}/github-pr-info.txt - - uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 + - uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 if: ${{ github.event_name == 'pull_request' }} with: name: github-pr-info From 04cf66765a8a9d48baea6d9aee266dc9aa21df27 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 19 Jan 2024 11:53:45 +0900 Subject: [PATCH 311/640] Revert "[rubygems/rubygems] Fix activation conflicts when circularly requiring a gem" This reverts commit db44088c2a92040879386aa5f268db4c858e4e5b. https://github.com/ruby/ruby/actions/runs/7578672002/job/20641640821 https://github.com/ruby/ruby/actions/runs/7578672002/job/20641641212 https://github.com/ruby/ruby/actions/runs/7578672002/job/20641642031 --- lib/rubygems.rb | 7 ----- lib/rubygems/core_ext/kernel_require.rb | 8 ++--- test/rubygems/test_require.rb | 39 ------------------------- 3 files changed, 2 insertions(+), 52 deletions(-) diff --git a/lib/rubygems.rb b/lib/rubygems.rb index ad7ab1075636a8..47b1ce69d26608 100644 --- a/lib/rubygems.rb +++ b/lib/rubygems.rb @@ -1216,13 +1216,6 @@ def register_default_spec(spec) ## # Find a Gem::Specification of default gem from +path+ - def find_default_spec(path) - @path_to_default_spec_map[path] - end - - ## - # Find an unresolved Gem::Specification of default gem from +path+ - def find_unresolved_default_spec(path) default_spec = @path_to_default_spec_map[path] default_spec if default_spec && loaded_specs[default_spec.name] != default_spec diff --git a/lib/rubygems/core_ext/kernel_require.rb b/lib/rubygems/core_ext/kernel_require.rb index 073966b696ccde..50e3ea89b4b884 100644 --- a/lib/rubygems/core_ext/kernel_require.rb +++ b/lib/rubygems/core_ext/kernel_require.rb @@ -42,11 +42,7 @@ def require(path) # :doc: # If +path+ belongs to a default gem, we activate it and then go straight # to normal require - if spec = Gem.find_default_spec(path) - name = spec.name - - next if Gem.loaded_specs[name] - + if spec = Gem.find_unresolved_default_spec(path) # Ensure -I beats a default gem resolved_path = begin rp = nil @@ -64,7 +60,7 @@ def require(path) # :doc: rp end - Kernel.send(:gem, name, Gem::Requirement.default_prerelease) unless + Kernel.send(:gem, spec.name, Gem::Requirement.default_prerelease) unless resolved_path next diff --git a/test/rubygems/test_require.rb b/test/rubygems/test_require.rb index f595d8e08ecd2e..7f5584ea8ace42 100644 --- a/test/rubygems/test_require.rb +++ b/test/rubygems/test_require.rb @@ -560,45 +560,6 @@ def test_default_gem_with_unresolved_gems_depending_on_it assert_require "net/http" end - def test_default_gem_required_circulary_with_unresolved_gems_depending_on_it - net_http_old = util_spec "net-http", "0.1.1", nil, "lib/net/http.rb" - install_gem net_http_old - - net_http_default = new_default_spec "net-http", "0.3.0", nil, "net/http.rb" - net_http_default_path = File.join(@tempdir, "default_gems", "lib", "net/http.rb") - install_default_gems net_http_default - File.write(net_http_default_path, 'require "net/http"') - - faraday_1 = util_spec "faraday", "1", { "net-http" => ">= 0" } - install_gem faraday_1 - - faraday_2 = util_spec "faraday", "2", { "net-http" => ">= 0" } - install_gem faraday_2 - - chef = util_spec "chef", "1", { "faraday" => [">= 1", "< 3"] }, "lib/chef.rb" - install_gem chef - - assert_require "chef" - - out, err = capture_output do - assert_require "net/http" - end - - assert_empty out - - circular_require_warning = false - - err_lines = err.split("\n").reject do |line| - if line.include?("circular require") - circular_require_warning = true - elsif circular_require_warning # ignore backtrace lines for circular require warning - circular_require_warning = line.start_with?(/[\s]/) - end - end - - assert_empty err_lines - end - def loaded_spec_names Gem.loaded_specs.values.map(&:full_name).sort end From 54552b89e73fc616ba47c1c87d33625af99cbce9 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 19 Jan 2024 12:12:33 +0900 Subject: [PATCH 312/640] Revert "[rubygems/rubygems] Fix `require` of a default gem when unresolved gems depend on it" This reverts commit f1f5f22d22a149f20e019728b1ab35593d29d81a. --- lib/rubygems/core_ext/kernel_require.rb | 2 -- test/rubygems/test_require.rb | 20 -------------------- 2 files changed, 22 deletions(-) diff --git a/lib/rubygems/core_ext/kernel_require.rb b/lib/rubygems/core_ext/kernel_require.rb index 50e3ea89b4b884..46954c534da324 100644 --- a/lib/rubygems/core_ext/kernel_require.rb +++ b/lib/rubygems/core_ext/kernel_require.rb @@ -62,8 +62,6 @@ def require(path) # :doc: Kernel.send(:gem, spec.name, Gem::Requirement.default_prerelease) unless resolved_path - - next end # If there are no unresolved deps, then we can use just try diff --git a/test/rubygems/test_require.rb b/test/rubygems/test_require.rb index 7f5584ea8ace42..b3926afe1525ae 100644 --- a/test/rubygems/test_require.rb +++ b/test/rubygems/test_require.rb @@ -540,26 +540,6 @@ def test_default_gem_prerelease assert_equal %w[default-3.0.0.rc2], loaded_spec_names end - def test_default_gem_with_unresolved_gems_depending_on_it - net_http_old = util_spec "net-http", "0.1.1", nil, "lib/net/http.rb" - install_gem net_http_old - - net_http_default = new_default_spec "net-http", "0.3.0", nil, "net/http.rb" - install_default_gems net_http_default - - faraday_1 = util_spec "faraday", "1", { "net-http" => ">= 0" } - install_gem faraday_1 - - faraday_2 = util_spec "faraday", "2", { "net-http" => ">= 0" } - install_gem faraday_2 - - chef = util_spec "chef", "1", { "faraday" => [">= 1", "< 3"] }, "lib/chef.rb" - install_gem chef - - assert_require "chef" - assert_require "net/http" - end - def loaded_spec_names Gem.loaded_specs.values.map(&:full_name).sort end From 385a1b15efb4736a2462eff10057cd14f213ffe2 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 19 Jan 2024 14:00:08 +0900 Subject: [PATCH 313/640] Fixed upstream URL at bundled gems --- doc/maintainers.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/maintainers.md b/doc/maintainers.md index 57a4d93bdcd80c..5e18f1832c8e29 100644 --- a/doc/maintainers.md +++ b/doc/maintainers.md @@ -422,7 +422,7 @@ have commit right, others don't. ## Bundled gems upstream repositories ### minitest -* https://github.com/seattlerb/minitest +* https://github.com/minitest/minitest ### power_assert * https://github.com/ruby/power_assert @@ -479,7 +479,7 @@ have commit right, others don't. * https://github.com/ruby/base64 #### ext/bigdecimal -* https://rubygems.org/gems/bigdecimal +* https://github.com/ruby/bigdecimal ## Platform Maintainers ### mswin64 (Microsoft Windows) From 68b403c45a8e2b81d204448309deaa4717c586ed Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 19 Jan 2024 14:01:30 +0900 Subject: [PATCH 314/640] Fixed inconsistent library name --- doc/maintainers.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/maintainers.md b/doc/maintainers.md index 5e18f1832c8e29..71d4338bbcff83 100644 --- a/doc/maintainers.md +++ b/doc/maintainers.md @@ -472,13 +472,13 @@ have commit right, others don't. #### mutex_m * https://github.com/ruby/mutex_m -#### lib/getoptlong.rb +#### getoptlong * https://github.com/ruby/getoptlong -#### lib/base64.rb +#### base64 * https://github.com/ruby/base64 -#### ext/bigdecimal +#### bigdecimal * https://github.com/ruby/bigdecimal ## Platform Maintainers From 176a4428838cb9a416c236b72b9b56f69afa7e12 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 19 Jan 2024 13:57:43 +0900 Subject: [PATCH 315/640] Extract observer as bundled gems --- gems/bundled_gems | 1 + lib/observer.gemspec | 32 ------ lib/observer.rb | 229 ------------------------------------------ test/test_observer.rb | 66 ------------ 4 files changed, 1 insertion(+), 327 deletions(-) delete mode 100644 lib/observer.gemspec delete mode 100644 lib/observer.rb delete mode 100644 test/test_observer.rb diff --git a/gems/bundled_gems b/gems/bundled_gems index 38ddd252fae5ee..d0364181820ab9 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -25,3 +25,4 @@ mutex_m 0.2.0 https://github.com/ruby/mutex_m getoptlong 0.2.1 https://github.com/ruby/getoptlong base64 0.2.0 https://github.com/ruby/base64 bigdecimal 3.1.6 https://github.com/ruby/bigdecimal +observer 0.1.2 https://github.com/ruby/observer diff --git a/lib/observer.gemspec b/lib/observer.gemspec deleted file mode 100644 index 93e61b8c842d07..00000000000000 --- a/lib/observer.gemspec +++ /dev/null @@ -1,32 +0,0 @@ -# frozen_string_literal: true - -name = File.basename(__FILE__, ".gemspec") -version = ["lib", Array.new(name.count("-")+1, ".").join("/")].find do |dir| - break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line| - /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1 - end rescue nil -end - -Gem::Specification.new do |spec| - spec.name = name - spec.version = version - spec.authors = ["Yukihiro Matsumoto"] - spec.email = ["matz@ruby-lang.org"] - - spec.summary = %q{Implementation of the Observer object-oriented design pattern.} - spec.description = spec.summary - spec.homepage = "https://github.com/ruby/observer" - spec.licenses = ["Ruby", "BSD-2-Clause"] - - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = spec.homepage - - # Specify which files should be added to the gem when it is released. - # The `git ls-files -z` loads the files in the RubyGem that have been added into git. - spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do - `git ls-files -z 2>#{IO::NULL}`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } - end - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } - spec.require_paths = ["lib"] -end diff --git a/lib/observer.rb b/lib/observer.rb deleted file mode 100644 index 75832cace23c0c..00000000000000 --- a/lib/observer.rb +++ /dev/null @@ -1,229 +0,0 @@ -# frozen_string_literal: true -# -# Implementation of the _Observer_ object-oriented design pattern. The -# following documentation is copied, with modifications, from "Programming -# Ruby", by Hunt and Thomas; http://www.ruby-doc.org/docs/ProgrammingRuby/html/lib_patterns.html. -# -# See Observable for more info. - -# The Observer pattern (also known as publish/subscribe) provides a simple -# mechanism for one object to inform a set of interested third-party objects -# when its state changes. -# -# == Mechanism -# -# The notifying class mixes in the +Observable+ -# module, which provides the methods for managing the associated observer -# objects. -# -# The observable object must: -# * assert that it has +#changed+ -# * call +#notify_observers+ -# -# An observer subscribes to updates using Observable#add_observer, which also -# specifies the method called via #notify_observers. The default method for -# #notify_observers is #update. -# -# === Example -# -# The following example demonstrates this nicely. A +Ticker+, when run, -# continually receives the stock +Price+ for its @symbol. A +Warner+ -# is a general observer of the price, and two warners are demonstrated, a -# +WarnLow+ and a +WarnHigh+, which print a warning if the price is below or -# above their set limits, respectively. -# -# The +update+ callback allows the warners to run without being explicitly -# called. The system is set up with the +Ticker+ and several observers, and the -# observers do their duty without the top-level code having to interfere. -# -# Note that the contract between publisher and subscriber (observable and -# observer) is not declared or enforced. The +Ticker+ publishes a time and a -# price, and the warners receive that. But if you don't ensure that your -# contracts are correct, nothing else can warn you. -# -# require "observer" -# -# class Ticker ### Periodically fetch a stock price. -# include Observable -# -# def initialize(symbol) -# @symbol = symbol -# end -# -# def run -# last_price = nil -# loop do -# price = Price.fetch(@symbol) -# print "Current price: #{price}\n" -# if price != last_price -# changed # notify observers -# last_price = price -# notify_observers(Time.now, price) -# end -# sleep 1 -# end -# end -# end -# -# class Price ### A mock class to fetch a stock price (60 - 140). -# def self.fetch(symbol) -# 60 + rand(80) -# end -# end -# -# class Warner ### An abstract observer of Ticker objects. -# def initialize(ticker, limit) -# @limit = limit -# ticker.add_observer(self) -# end -# end -# -# class WarnLow < Warner -# def update(time, price) # callback for observer -# if price < @limit -# print "--- #{time.to_s}: Price below #@limit: #{price}\n" -# end -# end -# end -# -# class WarnHigh < Warner -# def update(time, price) # callback for observer -# if price > @limit -# print "+++ #{time.to_s}: Price above #@limit: #{price}\n" -# end -# end -# end -# -# ticker = Ticker.new("MSFT") -# WarnLow.new(ticker, 80) -# WarnHigh.new(ticker, 120) -# ticker.run -# -# Produces: -# -# Current price: 83 -# Current price: 75 -# --- Sun Jun 09 00:10:25 CDT 2002: Price below 80: 75 -# Current price: 90 -# Current price: 134 -# +++ Sun Jun 09 00:10:25 CDT 2002: Price above 120: 134 -# Current price: 134 -# Current price: 112 -# Current price: 79 -# --- Sun Jun 09 00:10:25 CDT 2002: Price below 80: 79 -# -# === Usage with procs -# -# The +#notify_observers+ method can also be used with +proc+s by using -# the +:call+ as +func+ parameter. -# -# The following example illustrates the use of a lambda: -# -# require 'observer' -# -# class Ticker -# include Observable -# -# def run -# # logic to retrieve the price (here 77.0) -# changed -# notify_observers(77.0) -# end -# end -# -# ticker = Ticker.new -# warner = ->(price) { puts "New price received: #{price}" } -# ticker.add_observer(warner, :call) -# ticker.run -module Observable - VERSION = "0.1.2" - - # - # Add +observer+ as an observer on this object. So that it will receive - # notifications. - # - # +observer+:: the object that will be notified of changes. - # +func+:: Symbol naming the method that will be called when this Observable - # has changes. - # - # This method must return true for +observer.respond_to?+ and will - # receive *arg when #notify_observers is called, where - # *arg is the value passed to #notify_observers by this - # Observable - def add_observer(observer, func=:update) - @observer_peers = {} unless defined? @observer_peers - unless observer.respond_to? func - raise NoMethodError, "observer does not respond to `#{func}'" - end - @observer_peers[observer] = func - end - - # - # Remove +observer+ as an observer on this object so that it will no longer - # receive notifications. - # - # +observer+:: An observer of this Observable - def delete_observer(observer) - @observer_peers.delete observer if defined? @observer_peers - end - - # - # Remove all observers associated with this object. - # - def delete_observers - @observer_peers.clear if defined? @observer_peers - end - - # - # Return the number of observers associated with this object. - # - def count_observers - if defined? @observer_peers - @observer_peers.size - else - 0 - end - end - - # - # Set the changed state of this object. Notifications will be sent only if - # the changed +state+ is +true+. - # - # +state+:: Boolean indicating the changed state of this Observable. - # - def changed(state=true) - @observer_state = state - end - - # - # Returns true if this object's state has been changed since the last - # #notify_observers call. - # - def changed? - if defined? @observer_state and @observer_state - true - else - false - end - end - - # - # Notify observers of a change in state *if* this object's changed state is - # +true+. - # - # This will invoke the method named in #add_observer, passing *arg. - # The changed state is then set to +false+. - # - # *arg:: Any arguments to pass to the observers. - def notify_observers(*arg) - if defined? @observer_state and @observer_state - if defined? @observer_peers - @observer_peers.each do |k, v| - k.__send__(v, *arg) - end - end - @observer_state = false - end - end - -end diff --git a/test/test_observer.rb b/test/test_observer.rb deleted file mode 100644 index 8f8f24b3c59579..00000000000000 --- a/test/test_observer.rb +++ /dev/null @@ -1,66 +0,0 @@ -# frozen_string_literal: true -require 'test/unit' -require 'observer' - -class TestObserver < Test::Unit::TestCase - class TestObservable - include Observable - - def notify(*args) - changed - notify_observers(*args) - end - end - - class TestWatcher - def initialize(observable) - @notifications = [] - observable.add_observer(self) - end - - attr_reader :notifications - - def update(*args) - @notifications << args - end - end - - def test_observers - observable = TestObservable.new - - assert_equal(0, observable.count_observers) - - watcher1 = TestWatcher.new(observable) - - assert_equal(1, observable.count_observers) - - observable.notify("test", 123) - - watcher2 = TestWatcher.new(observable) - - assert_equal(2, observable.count_observers) - - observable.notify(42) - - assert_equal([["test", 123], [42]], watcher1.notifications) - assert_equal([[42]], watcher2.notifications) - - observable.delete_observer(watcher1) - - assert_equal(1, observable.count_observers) - - observable.notify(:cats) - - assert_equal([["test", 123], [42]], watcher1.notifications) - assert_equal([[42], [:cats]], watcher2.notifications) - - observable.delete_observers - - assert_equal(0, observable.count_observers) - - observable.notify("nope") - - assert_equal([["test", 123], [42]], watcher1.notifications) - assert_equal([[42], [:cats]], watcher2.notifications) - end -end From 8b551b0e7ac0ac46394e55674b467b35a20c3d48 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 19 Jan 2024 13:58:34 +0900 Subject: [PATCH 316/640] spec/mspec/tool/wrap_with_guard.rb 'ruby_version_is ""..."3.4"' spec/ruby/library/observer/**/*.rb --- .../library/observer/add_observer_spec.rb | 35 +++++++------ .../library/observer/count_observers_spec.rb | 37 +++++++------- .../library/observer/delete_observer_spec.rb | 29 ++++++----- .../library/observer/delete_observers_spec.rb | 29 ++++++----- .../ruby/library/observer/fixtures/classes.rb | 24 ++++----- .../library/observer/notify_observers_spec.rb | 49 ++++++++++--------- 6 files changed, 110 insertions(+), 93 deletions(-) diff --git a/spec/ruby/library/observer/add_observer_spec.rb b/spec/ruby/library/observer/add_observer_spec.rb index 5217ae6dc45d71..4c33c647348dcc 100644 --- a/spec/ruby/library/observer/add_observer_spec.rb +++ b/spec/ruby/library/observer/add_observer_spec.rb @@ -1,23 +1,26 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -describe "Observer#add_observer" do +ruby_version_is ""..."3.4" do + require_relative 'fixtures/classes' - before :each do - @observable = ObservableSpecs.new - @observer = ObserverCallbackSpecs.new - end + describe "Observer#add_observer" do - it "adds the observer" do - @observer.value.should == nil - @observable.changed - @observable.notify_observers("test") - @observer.value.should == nil + before :each do + @observable = ObservableSpecs.new + @observer = ObserverCallbackSpecs.new + end - @observable.add_observer(@observer) - @observable.changed - @observable.notify_observers("test2") - @observer.value.should == "test2" - end + it "adds the observer" do + @observer.value.should == nil + @observable.changed + @observable.notify_observers("test") + @observer.value.should == nil + @observable.add_observer(@observer) + @observable.changed + @observable.notify_observers("test2") + @observer.value.should == "test2" + end + + end end diff --git a/spec/ruby/library/observer/count_observers_spec.rb b/spec/ruby/library/observer/count_observers_spec.rb index c93674196d995f..ab733e4e40b8bc 100644 --- a/spec/ruby/library/observer/count_observers_spec.rb +++ b/spec/ruby/library/observer/count_observers_spec.rb @@ -1,23 +1,26 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -describe "Observer#count_observers" do - before :each do - @observable = ObservableSpecs.new - @observer = ObserverCallbackSpecs.new - @observer2 = ObserverCallbackSpecs.new - end +ruby_version_is ""..."3.4" do + require_relative 'fixtures/classes' - it "returns the number of observers" do - @observable.count_observers.should == 0 - @observable.add_observer(@observer) - @observable.count_observers.should == 1 - @observable.add_observer(@observer2) - @observable.count_observers.should == 2 - end + describe "Observer#count_observers" do + before :each do + @observable = ObservableSpecs.new + @observer = ObserverCallbackSpecs.new + @observer2 = ObserverCallbackSpecs.new + end + + it "returns the number of observers" do + @observable.count_observers.should == 0 + @observable.add_observer(@observer) + @observable.count_observers.should == 1 + @observable.add_observer(@observer2) + @observable.count_observers.should == 2 + end - it "returns the number of unique observers" do - 2.times { @observable.add_observer(@observer) } - @observable.count_observers.should == 1 + it "returns the number of unique observers" do + 2.times { @observable.add_observer(@observer) } + @observable.count_observers.should == 1 + end end end diff --git a/spec/ruby/library/observer/delete_observer_spec.rb b/spec/ruby/library/observer/delete_observer_spec.rb index 52be1a6cbabc85..83db19bae2c447 100644 --- a/spec/ruby/library/observer/delete_observer_spec.rb +++ b/spec/ruby/library/observer/delete_observer_spec.rb @@ -1,19 +1,22 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -describe "Observer#delete_observer" do - before :each do - @observable = ObservableSpecs.new - @observer = ObserverCallbackSpecs.new - end +ruby_version_is ""..."3.4" do + require_relative 'fixtures/classes' - it "deletes the observer" do - @observable.add_observer(@observer) - @observable.delete_observer(@observer) + describe "Observer#delete_observer" do + before :each do + @observable = ObservableSpecs.new + @observer = ObserverCallbackSpecs.new + end - @observable.changed - @observable.notify_observers("test") - @observer.value.should == nil - end + it "deletes the observer" do + @observable.add_observer(@observer) + @observable.delete_observer(@observer) + @observable.changed + @observable.notify_observers("test") + @observer.value.should == nil + end + + end end diff --git a/spec/ruby/library/observer/delete_observers_spec.rb b/spec/ruby/library/observer/delete_observers_spec.rb index 186e93a013c738..5e7fe21d741fed 100644 --- a/spec/ruby/library/observer/delete_observers_spec.rb +++ b/spec/ruby/library/observer/delete_observers_spec.rb @@ -1,19 +1,22 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -describe "Observer#delete_observers" do - before :each do - @observable = ObservableSpecs.new - @observer = ObserverCallbackSpecs.new - end +ruby_version_is ""..."3.4" do + require_relative 'fixtures/classes' - it "deletes the observers" do - @observable.add_observer(@observer) - @observable.delete_observers + describe "Observer#delete_observers" do + before :each do + @observable = ObservableSpecs.new + @observer = ObserverCallbackSpecs.new + end - @observable.changed - @observable.notify_observers("test") - @observer.value.should == nil - end + it "deletes the observers" do + @observable.add_observer(@observer) + @observable.delete_observers + @observable.changed + @observable.notify_observers("test") + @observer.value.should == nil + end + + end end diff --git a/spec/ruby/library/observer/fixtures/classes.rb b/spec/ruby/library/observer/fixtures/classes.rb index 70cd1b1be277d0..d1f9079963e17c 100644 --- a/spec/ruby/library/observer/fixtures/classes.rb +++ b/spec/ruby/library/observer/fixtures/classes.rb @@ -1,17 +1,19 @@ -require 'observer' +ruby_version_is ""..."3.4" do + require 'observer' -class ObserverCallbackSpecs - attr_reader :value + class ObserverCallbackSpecs + attr_reader :value - def initialize - @value = nil - end + def initialize + @value = nil + end - def update(value) - @value = value + def update(value) + @value = value + end end -end -class ObservableSpecs - include Observable + class ObservableSpecs + include Observable + end end diff --git a/spec/ruby/library/observer/notify_observers_spec.rb b/spec/ruby/library/observer/notify_observers_spec.rb index 31f82e9266d760..1030ae701ec0d2 100644 --- a/spec/ruby/library/observer/notify_observers_spec.rb +++ b/spec/ruby/library/observer/notify_observers_spec.rb @@ -1,31 +1,34 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' -describe "Observer#notify_observers" do +ruby_version_is ""..."3.4" do + require_relative 'fixtures/classes' - before :each do - @observable = ObservableSpecs.new - @observer = ObserverCallbackSpecs.new - @observable.add_observer(@observer) - end + describe "Observer#notify_observers" do - it "must call changed before notifying observers" do - @observer.value.should == nil - @observable.notify_observers("test") - @observer.value.should == nil - end + before :each do + @observable = ObservableSpecs.new + @observer = ObserverCallbackSpecs.new + @observable.add_observer(@observer) + end - it "verifies observer responds to update" do - -> { - @observable.add_observer(@observable) - }.should raise_error(NoMethodError) - end + it "must call changed before notifying observers" do + @observer.value.should == nil + @observable.notify_observers("test") + @observer.value.should == nil + end - it "receives the callback" do - @observer.value.should == nil - @observable.changed - @observable.notify_observers("test") - @observer.value.should == "test" - end + it "verifies observer responds to update" do + -> { + @observable.add_observer(@observable) + }.should raise_error(NoMethodError) + end + + it "receives the callback" do + @observer.value.should == nil + @observable.changed + @observable.notify_observers("test") + @observer.value.should == "test" + end + end end From fb5722c09a17d8fa2b5e354f7f2a64c5971459fa Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 19 Jan 2024 14:02:44 +0900 Subject: [PATCH 317/640] Document about observer at Ruby 3.4 --- doc/maintainers.md | 8 +++----- doc/standard_library.rdoc | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/doc/maintainers.md b/doc/maintainers.md index 71d4338bbcff83..41331da4ee1745 100644 --- a/doc/maintainers.md +++ b/doc/maintainers.md @@ -181,11 +181,6 @@ have commit right, others don't. * https://github.com/ruby/net-protocol * https://rubygems.org/gems/net-protocol -#### lib/observer.rb -* *unmaintained* -* https://github.com/ruby/observer -* https://rubygems.org/gems/observer - #### lib/open3.rb * *unmaintained* * https://github.com/ruby/open3 @@ -481,6 +476,9 @@ have commit right, others don't. #### bigdecimal * https://github.com/ruby/bigdecimal +#### observer +* https://github.com/ruby/observer + ## Platform Maintainers ### mswin64 (Microsoft Windows) * NAKAMURA Usaku (usa) diff --git a/doc/standard_library.rdoc b/doc/standard_library.rdoc index 0d7bf45bf3f4b7..b7d212f0f716cf 100644 --- a/doc/standard_library.rdoc +++ b/doc/standard_library.rdoc @@ -52,7 +52,6 @@ IRB:: Interactive Ruby command-line tool for REPL (Read Eval Print Loop) OptionParser:: Ruby-oriented class for command-line option analysis Logger:: Provides a simple logging utility for outputting messages Net::HTTP:: HTTP client api for Ruby -Observable:: Provides a mechanism for publish/subscribe pattern in Ruby Open3:: Provides access to stdin, stdout and stderr when running other programs OpenStruct:: Class to build custom data structures, similar to a Hash OpenURI:: An easy-to-use wrapper for Net::HTTP, Net::HTTPS and Net::FTP @@ -130,3 +129,4 @@ Mutex_m:: Mixin to extend objects to be handled like a Mutex GetoptLong:: Parse command line options similar to the GNU C getopt_long() Base64:: Support for encoding and decoding binary data using a Base64 representation BigDecimal:: Provides arbitrary-precision floating point decimal arithmetic +Observable:: Provides a mechanism for publish/subscribe pattern in Ruby From e8cb9e1328889bead2440ab36be9ee36ebe65b49 Mon Sep 17 00:00:00 2001 From: git Date: Fri, 19 Jan 2024 06:35:57 +0000 Subject: [PATCH 318/640] Update bundled gems list as of 2024-01-18 --- NEWS.md | 3 ++- gems/bundled_gems | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 3dd6e7847c8737..b898becdfbaaa9 100644 --- a/NEWS.md +++ b/NEWS.md @@ -36,7 +36,7 @@ The following default gems are updated. The following bundled gems are updated. -* minitest 5.21.1 +* minitest 5.21.2 * net-ftp 0.3.4 * net-imap 0.4.9.1 * net-smtp 0.4.0.1 @@ -50,6 +50,7 @@ The following bundled gems are promoted from default gems. * getoptlong 0.2.1 * base64 0.2.0 * bigdecimal 3.1.6 +* observer 0.1.2 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. diff --git a/gems/bundled_gems b/gems/bundled_gems index d0364181820ab9..fa7d39dfd2d85e 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -5,7 +5,7 @@ # - repository-url: URL from where clone for test # - revision: revision in repository-url to test # if `revision` is not given, "v"+`version` or `version` will be used. -minitest 5.21.1 https://github.com/minitest/minitest +minitest 5.21.2 https://github.com/minitest/minitest power_assert 2.0.3 https://github.com/ruby/power_assert rake 13.1.0 https://github.com/ruby/rake test-unit 3.6.1 https://github.com/test-unit/test-unit From d3898e975254aaa7b17b5a48202d3d77f5f2d152 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 19 Jan 2024 15:56:55 +0900 Subject: [PATCH 319/640] Removed sync task for observer --- tool/sync_default_gems.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb index e9ce28a87e0e94..0b0406d4518b62 100755 --- a/tool/sync_default_gems.rb +++ b/tool/sync_default_gems.rb @@ -41,7 +41,6 @@ module SyncDefaultGems json: 'flori/json', logger: 'ruby/logger', nkf: "ruby/nkf", - observer: "ruby/observer", open3: "ruby/open3", openssl: "ruby/openssl", optparse: "ruby/optparse", From b4ee5266f196afc66686e88a4033262fa0f4933d Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 19 Jan 2024 15:41:59 +0900 Subject: [PATCH 320/640] Extract abbrev as bundled gems --- gems/bundled_gems | 1 + lib/abbrev.gemspec | 30 ---------- lib/abbrev.rb | 133 -------------------------------------------- test/test_abbrev.rb | 55 ------------------ 4 files changed, 1 insertion(+), 218 deletions(-) delete mode 100644 lib/abbrev.gemspec delete mode 100644 lib/abbrev.rb delete mode 100644 test/test_abbrev.rb diff --git a/gems/bundled_gems b/gems/bundled_gems index fa7d39dfd2d85e..7fdbf0d57dda3e 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -26,3 +26,4 @@ getoptlong 0.2.1 https://github.com/ruby/getoptlong base64 0.2.0 https://github.com/ruby/base64 bigdecimal 3.1.6 https://github.com/ruby/bigdecimal observer 0.1.2 https://github.com/ruby/observer +abbrev 0.1.2 https://github.com/ruby/abbrev diff --git a/lib/abbrev.gemspec b/lib/abbrev.gemspec deleted file mode 100644 index 57ae5738b8c203..00000000000000 --- a/lib/abbrev.gemspec +++ /dev/null @@ -1,30 +0,0 @@ -name = File.basename(__FILE__, ".gemspec") -version = ["lib", Array.new(name.count("-")+1, ".").join("/")].find do |dir| - break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line| - /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1 - end rescue nil -end - -Gem::Specification.new do |spec| - spec.name = name - spec.version = version - spec.authors = ["Akinori MUSHA"] - spec.email = ["knu@idaemons.org"] - - spec.summary = %q{Calculates a set of unique abbreviations for a given set of strings} - spec.description = %q{Calculates a set of unique abbreviations for a given set of strings} - spec.homepage = "https://github.com/ruby/abbrev" - spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0") - spec.licenses = ["Ruby", "BSD-2-Clause"] - - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = spec.homepage - spec.metadata["changelog_uri"] = spec.homepage + "/releases" - - spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do - `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } - end - spec.bindir = "exe" - spec.executables = [] - spec.require_paths = ["lib"] -end diff --git a/lib/abbrev.rb b/lib/abbrev.rb deleted file mode 100644 index 312085c2898691..00000000000000 --- a/lib/abbrev.rb +++ /dev/null @@ -1,133 +0,0 @@ -# frozen_string_literal: true -#-- -# Copyright (c) 2001,2003 Akinori MUSHA -# -# All rights reserved. You can redistribute and/or modify it under -# the same terms as Ruby. -# -# $Idaemons: /home/cvs/rb/abbrev.rb,v 1.2 2001/05/30 09:37:45 knu Exp $ -# $RoughId: abbrev.rb,v 1.4 2003/10/14 19:45:42 knu Exp $ -# $Id$ -#++ - -## -# Calculates the set of unambiguous abbreviations for a given set of strings. -# -# require 'abbrev' -# require 'pp' -# -# pp Abbrev.abbrev(['ruby']) -# #=> {"ruby"=>"ruby", "rub"=>"ruby", "ru"=>"ruby", "r"=>"ruby"} -# -# pp Abbrev.abbrev(%w{ ruby rules }) -# -# _Generates:_ -# { "ruby" => "ruby", -# "rub" => "ruby", -# "rules" => "rules", -# "rule" => "rules", -# "rul" => "rules" } -# -# It also provides an array core extension, Array#abbrev. -# -# pp %w{ summer winter }.abbrev -# -# _Generates:_ -# { "summer" => "summer", -# "summe" => "summer", -# "summ" => "summer", -# "sum" => "summer", -# "su" => "summer", -# "s" => "summer", -# "winter" => "winter", -# "winte" => "winter", -# "wint" => "winter", -# "win" => "winter", -# "wi" => "winter", -# "w" => "winter" } - -module Abbrev - VERSION = "0.1.2" - - # Given a set of strings, calculate the set of unambiguous abbreviations for - # those strings, and return a hash where the keys are all the possible - # abbreviations and the values are the full strings. - # - # Thus, given +words+ is "car" and "cone", the keys pointing to "car" would - # be "ca" and "car", while those pointing to "cone" would be "co", "con", and - # "cone". - # - # require 'abbrev' - # - # Abbrev.abbrev(%w{ car cone }) - # #=> {"ca"=>"car", "con"=>"cone", "co"=>"cone", "car"=>"car", "cone"=>"cone"} - # - # The optional +pattern+ parameter is a pattern or a string. Only input - # strings that match the pattern or start with the string are included in the - # output hash. - # - # Abbrev.abbrev(%w{car box cone crab}, /b/) - # #=> {"box"=>"box", "bo"=>"box", "b"=>"box", "crab" => "crab"} - # - # Abbrev.abbrev(%w{car box cone}, 'ca') - # #=> {"car"=>"car", "ca"=>"car"} - def abbrev(words, pattern = nil) - table = {} - seen = Hash.new(0) - - if pattern.is_a?(String) - pattern = /\A#{Regexp.quote(pattern)}/ # regard as a prefix - end - - words.each do |word| - next if word.empty? - word.size.downto(1) { |len| - abbrev = word[0...len] - - next if pattern && pattern !~ abbrev - - case seen[abbrev] += 1 - when 1 - table[abbrev] = word - when 2 - table.delete(abbrev) - else - break - end - } - end - - words.each do |word| - next if pattern && pattern !~ word - - table[word] = word - end - - table - end - - module_function :abbrev -end - -class Array - # Calculates the set of unambiguous abbreviations for the strings in +self+. - # - # require 'abbrev' - # %w{ car cone }.abbrev - # #=> {"car"=>"car", "ca"=>"car", "cone"=>"cone", "con"=>"cone", "co"=>"cone"} - # - # The optional +pattern+ parameter is a pattern or a string. Only input - # strings that match the pattern or start with the string are included in the - # output hash. - # - # %w{ fast boat day }.abbrev(/^.a/) - # #=> {"fast"=>"fast", "fas"=>"fast", "fa"=>"fast", "day"=>"day", "da"=>"day"} - # - # Abbrev.abbrev(%w{car box cone}, "ca") - # #=> {"car"=>"car", "ca"=>"car"} - # - # See also Abbrev.abbrev - def abbrev(pattern = nil) - Abbrev::abbrev(self, pattern) - end -end diff --git a/test/test_abbrev.rb b/test/test_abbrev.rb deleted file mode 100644 index 67287138aa8f91..00000000000000 --- a/test/test_abbrev.rb +++ /dev/null @@ -1,55 +0,0 @@ -# frozen_string_literal: true -require 'test/unit' -require 'abbrev' - -class TestAbbrev < Test::Unit::TestCase - def test_abbrev - words = %w[summer winter win ruby rules] - - assert_equal({ - "rub" => "ruby", - "ruby" => "ruby", - "rul" => "rules", - "rule" => "rules", - "rules" => "rules", - "s" => "summer", - "su" => "summer", - "sum" => "summer", - "summ" => "summer", - "summe" => "summer", - "summer" => "summer", - "win" => "win", - "wint" => "winter", - "winte" => "winter", - "winter" => "winter", - }, words.abbrev) - - assert_equal({ - "rub" => "ruby", - "ruby" => "ruby", - "rul" => "rules", - "rule" => "rules", - "rules" => "rules", - }, words.abbrev('ru')) - - assert_equal words.abbrev, Abbrev.abbrev(words) - assert_equal words.abbrev('ru'), Abbrev.abbrev(words, 'ru') - end - - def test_abbrev_lf - words = ["abc", "abc\nd", "de"] - - assert_equal({ - "abc" => "abc", - "abc\n" => "abc\nd", - "abc\nd" => "abc\nd", - "d" => "de", - "de" => "de", - }, words.abbrev) - - assert_equal({ - "d" => "de", - "de" => "de", - }, words.abbrev('d')) - end -end From f4670b46c458cdc57eeee2fead2ffe811ea65096 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 19 Jan 2024 15:42:24 +0900 Subject: [PATCH 321/640] spec/mspec/tool/wrap_with_guard.rb 'ruby_version_is ""..."3.4"' spec/ruby/library/abbrev/**/*.rb --- spec/ruby/library/abbrev/abbrev_spec.rb | 47 +++++++++++++------------ 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/spec/ruby/library/abbrev/abbrev_spec.rb b/spec/ruby/library/abbrev/abbrev_spec.rb index 61b09265977eec..79045a080451ed 100644 --- a/spec/ruby/library/abbrev/abbrev_spec.rb +++ b/spec/ruby/library/abbrev/abbrev_spec.rb @@ -1,31 +1,34 @@ require_relative '../../spec_helper' -require 'abbrev' -#test both Abbrev.abbrev and Array#abbrev in -#the same manner, as they're more or less aliases -#of one another +ruby_version_is ""..."3.4" do + require 'abbrev' -[["Abbrev.abbrev", -> a { Abbrev.abbrev(a)}], - ["Array#abbrev", -> a { a.abbrev}] -].each do |(name, func)| + #test both Abbrev.abbrev and Array#abbrev in + #the same manner, as they're more or less aliases + #of one another - describe name do - it "returns a hash of all unambiguous abbreviations of the array of strings passed in" do - func.call(['ruby', 'rules']).should == {"rub" => "ruby", - "ruby" => "ruby", - "rul" => "rules", - "rule" => "rules", - "rules" => "rules"} + [["Abbrev.abbrev", -> a { Abbrev.abbrev(a)}], + ["Array#abbrev", -> a { a.abbrev}] + ].each do |(name, func)| - func.call(["car", "cone"]).should == {"ca" => "car", - "car" => "car", - "co" => "cone", - "con" => "cone", - "cone" => "cone"} - end + describe name do + it "returns a hash of all unambiguous abbreviations of the array of strings passed in" do + func.call(['ruby', 'rules']).should == {"rub" => "ruby", + "ruby" => "ruby", + "rul" => "rules", + "rule" => "rules", + "rules" => "rules"} + + func.call(["car", "cone"]).should == {"ca" => "car", + "car" => "car", + "co" => "cone", + "con" => "cone", + "cone" => "cone"} + end - it "returns an empty hash when called on an empty array" do - func.call([]).should == {} + it "returns an empty hash when called on an empty array" do + func.call([]).should == {} + end end end end From e28bdff94140bd9884e27ff1c42c31e121e65827 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 19 Jan 2024 15:43:08 +0900 Subject: [PATCH 322/640] Document about abbrev at Ruby 3.4 --- doc/maintainers.md | 8 ++++---- doc/standard_library.rdoc | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/maintainers.md b/doc/maintainers.md index 41331da4ee1745..a58e8bbffbbfc9 100644 --- a/doc/maintainers.md +++ b/doc/maintainers.md @@ -72,10 +72,6 @@ have commit right, others don't. ## Default gems Maintainers ### Libraries -#### lib/abbrev.rb -* Akinori MUSHA (knu) -* https://github.com/ruby/abbrev -* https://rubygems.org/gems/abbrev #### lib/benchmark.rb * *unmaintained* @@ -479,6 +475,10 @@ have commit right, others don't. #### observer * https://github.com/ruby/observer +#### abbrev +* https://github.com/ruby/abbrev + + ## Platform Maintainers ### mswin64 (Microsoft Windows) * NAKAMURA Usaku (usa) diff --git a/doc/standard_library.rdoc b/doc/standard_library.rdoc index b7d212f0f716cf..5d10a4249c4109 100644 --- a/doc/standard_library.rdoc +++ b/doc/standard_library.rdoc @@ -33,7 +33,6 @@ Socket:: Access underlying OS socket implementations == Libraries -Abbrev:: Calculates a set of unique abbreviations for a given set of strings 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 @@ -130,3 +129,4 @@ GetoptLong:: Parse command line options similar to the GNU C getopt_long() Base64:: Support for encoding and decoding binary data using a Base64 representation BigDecimal:: Provides arbitrary-precision floating point decimal arithmetic Observable:: Provides a mechanism for publish/subscribe pattern in Ruby +Abbrev:: Calculates a set of unique abbreviations for a given set of strings From 11ec59c92bab5346fc0fdce9d8ed2ac6cf95e4fd Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 19 Jan 2024 15:57:25 +0900 Subject: [PATCH 323/640] Removed sync task for abbrev --- tool/sync_default_gems.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb index 0b0406d4518b62..f12da2484dfe6d 100755 --- a/tool/sync_default_gems.rb +++ b/tool/sync_default_gems.rb @@ -19,7 +19,6 @@ module SyncDefaultGems "open-uri": "ruby/open-uri", "resolv-replace": "ruby/resolv-replace", English: "ruby/English", - abbrev: "ruby/abbrev", benchmark: "ruby/benchmark", cgi: "ruby/cgi", csv: 'ruby/csv', From 9ac316bb489dcd2111488af2aa9b421d91a85fdb Mon Sep 17 00:00:00 2001 From: git Date: Fri, 19 Jan 2024 07:28:30 +0000 Subject: [PATCH 324/640] Update bundled gems list at 11ec59c92bab5346fc0fdce9d8ed2a [ci skip] --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index b898becdfbaaa9..bcafce082fe3da 100644 --- a/NEWS.md +++ b/NEWS.md @@ -51,6 +51,7 @@ The following bundled gems are promoted from default gems. * base64 0.2.0 * bigdecimal 3.1.6 * observer 0.1.2 +* abbrev 0.1.2 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. From 99c2c703da8f31bf1cb6f0641c18be35ded7ba0f Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 19 Jan 2024 16:32:00 +0900 Subject: [PATCH 325/640] Extract resolv-replace --- gems/bundled_gems | 1 + lib/resolv-replace.gemspec | 22 ----------- lib/resolv-replace.rb | 76 -------------------------------------- 3 files changed, 1 insertion(+), 98 deletions(-) delete mode 100644 lib/resolv-replace.gemspec delete mode 100644 lib/resolv-replace.rb diff --git a/gems/bundled_gems b/gems/bundled_gems index 7fdbf0d57dda3e..23a6b457509580 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -27,3 +27,4 @@ base64 0.2.0 https://github.com/ruby/base64 bigdecimal 3.1.6 https://github.com/ruby/bigdecimal observer 0.1.2 https://github.com/ruby/observer abbrev 0.1.2 https://github.com/ruby/abbrev +resolv-replace 0.1.1 https://github.com/ruby/resolv-replace diff --git a/lib/resolv-replace.gemspec b/lib/resolv-replace.gemspec deleted file mode 100644 index 48f7108a8e2ab3..00000000000000 --- a/lib/resolv-replace.gemspec +++ /dev/null @@ -1,22 +0,0 @@ -Gem::Specification.new do |spec| - spec.name = "resolv-replace" - spec.version = "0.1.1" - spec.authors = ["Tanaka Akira"] - spec.email = ["akr@fsij.org"] - - spec.summary = %q{Replace Socket DNS with Resolv.} - spec.description = %q{Replace Socket DNS with Resolv.} - spec.homepage = "https://github.com/ruby/resolv-replace" - spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0") - spec.licenses = ["Ruby", "BSD-2-Clause"] - - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = spec.homepage - - spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do - `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } - end - spec.require_paths = ["lib"] - - spec.add_dependency "resolv" -end diff --git a/lib/resolv-replace.rb b/lib/resolv-replace.rb deleted file mode 100644 index a83e79d99603d4..00000000000000 --- a/lib/resolv-replace.rb +++ /dev/null @@ -1,76 +0,0 @@ -# frozen_string_literal: true - -require 'socket' -require 'resolv' - -class << IPSocket - # :stopdoc: - alias original_resolv_getaddress getaddress - # :startdoc: - def getaddress(host) - begin - return Resolv.getaddress(host).to_s - rescue Resolv::ResolvError - raise SocketError, "Hostname not known: #{host}" - end - end -end - -class TCPSocket < IPSocket - # :stopdoc: - alias original_resolv_initialize initialize - # :startdoc: - def initialize(host, serv, *rest) - rest[0] = IPSocket.getaddress(rest[0]) if rest[0] - original_resolv_initialize(IPSocket.getaddress(host), serv, *rest) - end -end - -class UDPSocket < IPSocket - # :stopdoc: - alias original_resolv_bind bind - # :startdoc: - def bind(host, port) - host = IPSocket.getaddress(host) if host != "" - original_resolv_bind(host, port) - end - - # :stopdoc: - alias original_resolv_connect connect - # :startdoc: - def connect(host, port) - original_resolv_connect(IPSocket.getaddress(host), port) - end - - # :stopdoc: - alias original_resolv_send send - # :startdoc: - def send(mesg, flags, *rest) - if rest.length == 2 - host, port = rest - begin - addrs = Resolv.getaddresses(host) - rescue Resolv::ResolvError - raise SocketError, "Hostname not known: #{host}" - end - addrs[0...-1].each {|addr| - begin - return original_resolv_send(mesg, flags, addr, port) - rescue SystemCallError - end - } - original_resolv_send(mesg, flags, addrs[-1], port) - else - original_resolv_send(mesg, flags, *rest) - end - end -end - -class SOCKSSocket < TCPSocket - # :stopdoc: - alias original_resolv_initialize initialize - # :startdoc: - def initialize(host, serv) - original_resolv_initialize(IPSocket.getaddress(host), port) - end -end if defined? SOCKSSocket From 6c098d145a9f468d4a7971234bda9673f9368aaf Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 19 Jan 2024 16:32:44 +0900 Subject: [PATCH 326/640] Document about resolv-replace at Ruby 3.4 --- doc/maintainers.md | 7 ++----- doc/standard_library.rdoc | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/doc/maintainers.md b/doc/maintainers.md index a58e8bbffbbfc9..173beb58d707a5 100644 --- a/doc/maintainers.md +++ b/doc/maintainers.md @@ -222,11 +222,6 @@ have commit right, others don't. * https://github.com/ruby/resolv * https://rubygems.org/gems/resolv -#### lib/resolv-replace.rb -* Tanaka Akira (akr) -* https://github.com/ruby/resolv-replace -* https://rubygems.org/gems/resolv-replace - #### lib/rdoc.rb, lib/rdoc/* * Eric Hodel (drbrain) * Hiroshi SHIBATA (hsbt) @@ -478,6 +473,8 @@ have commit right, others don't. #### abbrev * https://github.com/ruby/abbrev +#### lib/resolv-replace.rb +* https://github.com/ruby/resolv-replace ## Platform Maintainers ### mswin64 (Microsoft Windows) diff --git a/doc/standard_library.rdoc b/doc/standard_library.rdoc index 5d10a4249c4109..3fafd5932b4d07 100644 --- a/doc/standard_library.rdoc +++ b/doc/standard_library.rdoc @@ -61,7 +61,6 @@ 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 Rinda:: The Linda distributed computing paradigm in Ruby SecureRandom:: Interface for secure random number generator @@ -130,3 +129,4 @@ Base64:: Support for encoding and decoding binary data using a Base64 representa BigDecimal:: Provides arbitrary-precision floating point decimal arithmetic Observable:: Provides a mechanism for publish/subscribe pattern in Ruby Abbrev:: Calculates a set of unique abbreviations for a given set of strings +resolv-replace.rb:: Replace Socket DNS with Resolv From 36095ed3db9a449fba6a0a1cfbed9cd7d92a59b8 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 19 Jan 2024 16:33:11 +0900 Subject: [PATCH 327/640] Removed sync task for resolv-replace --- tool/sync_default_gems.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb index f12da2484dfe6d..c9eadab0468700 100755 --- a/tool/sync_default_gems.rb +++ b/tool/sync_default_gems.rb @@ -17,7 +17,6 @@ module SyncDefaultGems "net-http": "ruby/net-http", "net-protocol": "ruby/net-protocol", "open-uri": "ruby/open-uri", - "resolv-replace": "ruby/resolv-replace", English: "ruby/English", benchmark: "ruby/benchmark", cgi: "ruby/cgi", From 31a5d4a0cdf6e76708ea93854eef8b7b919e9119 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 19 Jan 2024 16:53:50 +0900 Subject: [PATCH 328/640] Skip test task for resolv-replace --- tool/test-bundled-gems.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tool/test-bundled-gems.rb b/tool/test-bundled-gems.rb index 32ac56d759890c..eeec1d7aedbf55 100644 --- a/tool/test-bundled-gems.rb +++ b/tool/test-bundled-gems.rb @@ -31,6 +31,9 @@ toplib = gem case gem + when "resolv-replace" + # Skip test suite + next when "typeprof" when "rbs" From 0f315216bb5056878e4bcffc391b2ee0de68ac17 Mon Sep 17 00:00:00 2001 From: git Date: Fri, 19 Jan 2024 08:57:54 +0000 Subject: [PATCH 329/640] Update bundled gems list as of 2024-01-19 --- NEWS.md | 3 ++- gems/bundled_gems | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index bcafce082fe3da..f11a42d8cd7b43 100644 --- a/NEWS.md +++ b/NEWS.md @@ -40,7 +40,7 @@ The following bundled gems are updated. * net-ftp 0.3.4 * net-imap 0.4.9.1 * net-smtp 0.4.0.1 -* rbs 3.4.1 +* rbs 3.4.2 * typeprof 0.21.9 * debug 1.9.1 @@ -52,6 +52,7 @@ The following bundled gems are promoted from default gems. * bigdecimal 3.1.6 * observer 0.1.2 * abbrev 0.1.2 +* resolv-replace 0.1.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. diff --git a/gems/bundled_gems b/gems/bundled_gems index 23a6b457509580..5f87058c0cb658 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -17,7 +17,7 @@ net-pop 0.1.2 https://github.com/ruby/net-pop net-smtp 0.4.0.1 https://github.com/ruby/net-smtp matrix 0.4.2 https://github.com/ruby/matrix prime 0.1.2 https://github.com/ruby/prime -rbs 3.4.1 https://github.com/ruby/rbs +rbs 3.4.2 https://github.com/ruby/rbs typeprof 0.21.9 https://github.com/ruby/typeprof debug 1.9.1 https://github.com/ruby/debug racc 1.7.3 https://github.com/ruby/racc From 411cda2d5ce6df1c24d31cd08926adf3acc0f47c Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 19 Jan 2024 18:11:29 +0900 Subject: [PATCH 330/640] Extract rinda --- gems/bundled_gems | 1 + lib/rinda/rinda.gemspec | 35 -- lib/rinda/rinda.rb | 329 ------------- lib/rinda/ring.rb | 484 ------------------- lib/rinda/tuplespace.rb | 641 ------------------------- test/rinda/test_rinda.rb | 912 ------------------------------------ test/rinda/test_tuplebag.rb | 173 ------- 7 files changed, 1 insertion(+), 2574 deletions(-) delete mode 100644 lib/rinda/rinda.gemspec delete mode 100644 lib/rinda/rinda.rb delete mode 100644 lib/rinda/ring.rb delete mode 100644 lib/rinda/tuplespace.rb delete mode 100644 test/rinda/test_rinda.rb delete mode 100644 test/rinda/test_tuplebag.rb diff --git a/gems/bundled_gems b/gems/bundled_gems index 5f87058c0cb658..6e47335e3fa89a 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -28,3 +28,4 @@ bigdecimal 3.1.6 https://github.com/ruby/bigdecimal observer 0.1.2 https://github.com/ruby/observer abbrev 0.1.2 https://github.com/ruby/abbrev resolv-replace 0.1.1 https://github.com/ruby/resolv-replace +rinda 0.2.0 https://github.com/ruby/rinda diff --git a/lib/rinda/rinda.gemspec b/lib/rinda/rinda.gemspec deleted file mode 100644 index e9f53dd86414e3..00000000000000 --- a/lib/rinda/rinda.gemspec +++ /dev/null @@ -1,35 +0,0 @@ -name = File.basename(__FILE__, ".gemspec") -version = ["lib/rinda", "."].find do |dir| - break File.foreach(File.join(__dir__, dir, "#{name}.rb")) do |line| - /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1 - end rescue nil -end - -Gem::Specification.new do |spec| - spec.name = name - spec.version = version - spec.authors = ["Masatoshi SEKI"] - spec.email = ["seki@ruby-lang.org"] - - spec.summary = %q{The Linda distributed computing paradigm in Ruby.} - spec.description = %q{The Linda distributed computing paradigm in Ruby.} - spec.homepage = "https://github.com/ruby/rinda" - spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0") - spec.licenses = ["Ruby", "BSD-2-Clause"] - - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = spec.homepage - - # Specify which files should be added to the gem when it is released. - # The `git ls-files -z` loads the files in the RubyGem that have been added into git. - spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do - `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } - end - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } - spec.require_paths = ["lib"] - - spec.add_dependency "drb" - spec.add_dependency "ipaddr" - spec.add_dependency "forwardable" -end diff --git a/lib/rinda/rinda.rb b/lib/rinda/rinda.rb deleted file mode 100644 index e1649e3248a7b5..00000000000000 --- a/lib/rinda/rinda.rb +++ /dev/null @@ -1,329 +0,0 @@ -# frozen_string_literal: false -require 'drb/drb' - -## -# A module to implement the Linda distributed computing paradigm in Ruby. -# -# Rinda is part of DRb (dRuby). -# -# == Example(s) -# -# See the sample/drb/ directory in the Ruby distribution, from 1.8.2 onwards. -# -#-- -# TODO -# == Introduction to Linda/rinda? -# -# == Why is this library separate from DRb? - -module Rinda - - VERSION = "0.2.0" - - ## - # Rinda error base class - - class RindaError < RuntimeError; end - - ## - # Raised when a hash-based tuple has an invalid key. - - class InvalidHashTupleKey < RindaError; end - - ## - # Raised when trying to use a canceled tuple. - - class RequestCanceledError < ThreadError; end - - ## - # Raised when trying to use an expired tuple. - - class RequestExpiredError < ThreadError; end - - ## - # A tuple is the elementary object in Rinda programming. - # Tuples may be matched against templates if the tuple and - # the template are the same size. - - class Tuple - - ## - # Creates a new Tuple from +ary_or_hash+ which must be an Array or Hash. - - def initialize(ary_or_hash) - if hash?(ary_or_hash) - init_with_hash(ary_or_hash) - else - init_with_ary(ary_or_hash) - end - end - - ## - # The number of elements in the tuple. - - def size - @tuple.size - end - - ## - # Accessor method for elements of the tuple. - - def [](k) - @tuple[k] - end - - ## - # Fetches item +k+ from the tuple. - - def fetch(k) - @tuple.fetch(k) - end - - ## - # Iterate through the tuple, yielding the index or key, and the - # value, thus ensuring arrays are iterated similarly to hashes. - - def each # FIXME - if Hash === @tuple - @tuple.each { |k, v| yield(k, v) } - else - @tuple.each_with_index { |v, k| yield(k, v) } - end - end - - ## - # Return the tuple itself - def value - @tuple - end - - private - - def hash?(ary_or_hash) - ary_or_hash.respond_to?(:keys) - end - - ## - # Munges +ary+ into a valid Tuple. - - def init_with_ary(ary) - @tuple = Array.new(ary.size) - @tuple.size.times do |i| - @tuple[i] = ary[i] - end - end - - ## - # Ensures +hash+ is a valid Tuple. - - def init_with_hash(hash) - @tuple = Hash.new - hash.each do |k, v| - raise InvalidHashTupleKey unless String === k - @tuple[k] = v - end - end - - end - - ## - # Templates are used to match tuples in Rinda. - - class Template < Tuple - - ## - # Matches this template against +tuple+. The +tuple+ must be the same - # size as the template. An element with a +nil+ value in a template acts - # as a wildcard, matching any value in the corresponding position in the - # tuple. Elements of the template match the +tuple+ if the are #== or - # #===. - # - # Template.new([:foo, 5]).match Tuple.new([:foo, 5]) # => true - # Template.new([:foo, nil]).match Tuple.new([:foo, 5]) # => true - # Template.new([String]).match Tuple.new(['hello']) # => true - # - # Template.new([:foo]).match Tuple.new([:foo, 5]) # => false - # Template.new([:foo, 6]).match Tuple.new([:foo, 5]) # => false - # Template.new([:foo, nil]).match Tuple.new([:foo]) # => false - # Template.new([:foo, 6]).match Tuple.new([:foo]) # => false - - def match(tuple) - return false unless tuple.respond_to?(:size) - return false unless tuple.respond_to?(:fetch) - return false unless self.size == tuple.size - each do |k, v| - begin - it = tuple.fetch(k) - rescue - return false - end - next if v.nil? - next if v == it - next if v === it - return false - end - return true - end - - ## - # Alias for #match. - - def ===(tuple) - match(tuple) - end - - end - - ## - # Documentation? - - class DRbObjectTemplate - - ## - # Creates a new DRbObjectTemplate that will match against +uri+ and +ref+. - - def initialize(uri=nil, ref=nil) - @drb_uri = uri - @drb_ref = ref - end - - ## - # This DRbObjectTemplate matches +ro+ if the remote object's drburi and - # drbref are the same. +nil+ is used as a wildcard. - - def ===(ro) - return true if super(ro) - unless @drb_uri.nil? - return false unless (@drb_uri === ro.__drburi rescue false) - end - unless @drb_ref.nil? - return false unless (@drb_ref === ro.__drbref rescue false) - end - true - end - - end - - ## - # TupleSpaceProxy allows a remote Tuplespace to appear as local. - - class TupleSpaceProxy - ## - # A Port ensures that a moved tuple arrives properly at its destination - # and does not get lost. - # - # See https://bugs.ruby-lang.org/issues/8125 - - class Port # :nodoc: - attr_reader :value - - def self.deliver - port = new - - begin - yield(port) - ensure - port.close - end - - port.value - end - - def initialize - @open = true - @value = nil - end - - ## - # Don't let the DRb thread push to it when remote sends tuple - - def close - @open = false - end - - ## - # Stores +value+ and ensure it does not get marshaled multiple times. - - def push value - raise 'port closed' unless @open - - @value = value - - nil # avoid Marshal - end - end - - ## - # Creates a new TupleSpaceProxy to wrap +ts+. - - def initialize(ts) - @ts = ts - end - - ## - # Adds +tuple+ to the proxied TupleSpace. See TupleSpace#write. - - def write(tuple, sec=nil) - @ts.write(tuple, sec) - end - - ## - # Takes +tuple+ from the proxied TupleSpace. See TupleSpace#take. - - def take(tuple, sec=nil, &block) - Port.deliver do |port| - @ts.move(DRbObject.new(port), tuple, sec, &block) - end - end - - ## - # Reads +tuple+ from the proxied TupleSpace. See TupleSpace#read. - - def read(tuple, sec=nil, &block) - @ts.read(tuple, sec, &block) - end - - ## - # Reads all tuples matching +tuple+ from the proxied TupleSpace. See - # TupleSpace#read_all. - - def read_all(tuple) - @ts.read_all(tuple) - end - - ## - # Registers for notifications of event +ev+ on the proxied TupleSpace. - # See TupleSpace#notify - - def notify(ev, tuple, sec=nil) - @ts.notify(ev, tuple, sec) - end - - end - - ## - # An SimpleRenewer allows a TupleSpace to check if a TupleEntry is still - # alive. - - class SimpleRenewer - - include DRbUndumped - - ## - # Creates a new SimpleRenewer that keeps an object alive for another +sec+ - # seconds. - - def initialize(sec=180) - @sec = sec - end - - ## - # Called by the TupleSpace to check if the object is still alive. - - def renew - @sec - end - end - -end - diff --git a/lib/rinda/ring.rb b/lib/rinda/ring.rb deleted file mode 100644 index 948cfaf20831a1..00000000000000 --- a/lib/rinda/ring.rb +++ /dev/null @@ -1,484 +0,0 @@ -# frozen_string_literal: false -# -# Note: Rinda::Ring API is unstable. -# -require 'drb/drb' -require_relative 'rinda' -require 'ipaddr' - -module Rinda - - ## - # The default port Ring discovery will use. - - Ring_PORT = 7647 - - ## - # A RingServer allows a Rinda::TupleSpace to be located via UDP broadcasts. - # Default service location uses the following steps: - # - # 1. A RingServer begins listening on the network broadcast UDP address. - # 2. A RingFinger sends a UDP packet containing the DRb URI where it will - # listen for a reply. - # 3. The RingServer receives the UDP packet and connects back to the - # provided DRb URI with the DRb service. - # - # A RingServer requires a TupleSpace: - # - # ts = Rinda::TupleSpace.new - # rs = Rinda::RingServer.new - # - # RingServer can also listen on multicast addresses for announcements. This - # allows multiple RingServers to run on the same host. To use network - # broadcast and multicast: - # - # ts = Rinda::TupleSpace.new - # rs = Rinda::RingServer.new ts, %w[Socket::INADDR_ANY, 239.0.0.1 ff02::1] - - class RingServer - - include DRbUndumped - - ## - # Special renewer for the RingServer to allow shutdown - - class Renewer # :nodoc: - include DRbUndumped - - ## - # Set to false to shutdown future requests using this Renewer - - attr_writer :renew - - def initialize # :nodoc: - @renew = true - end - - def renew # :nodoc: - @renew ? 1 : true - end - end - - ## - # Advertises +ts+ on the given +addresses+ at +port+. - # - # If +addresses+ is omitted only the UDP broadcast address is used. - # - # +addresses+ can contain multiple addresses. If a multicast address is - # given in +addresses+ then the RingServer will listen for multicast - # queries. - # - # If you use IPv4 multicast you may need to set an address of the inbound - # interface which joins a multicast group. - # - # ts = Rinda::TupleSpace.new - # rs = Rinda::RingServer.new(ts, [['239.0.0.1', '9.5.1.1']]) - # - # You can set addresses as an Array Object. The first element of the - # Array is a multicast address and the second is an inbound interface - # address. If the second is omitted then '0.0.0.0' is used. - # - # If you use IPv6 multicast you may need to set both the local interface - # address and the inbound interface index: - # - # rs = Rinda::RingServer.new(ts, [['ff02::1', '::1', 1]]) - # - # The first element is a multicast address and the second is an inbound - # interface address. The third is an inbound interface index. - # - # At this time there is no easy way to get an interface index by name. - # - # If the second is omitted then '::1' is used. - # If the third is omitted then 0 (default interface) is used. - - def initialize(ts, addresses=[Socket::INADDR_ANY], port=Ring_PORT) - @port = port - - if Integer === addresses then - addresses, @port = [Socket::INADDR_ANY], addresses - end - - @renewer = Renewer.new - - @ts = ts - @sockets = [] - addresses.each do |address| - if Array === address - make_socket(*address) - else - make_socket(address) - end - end - - @w_services = write_services - @r_service = reply_service - end - - ## - # Creates a socket at +address+ - # - # If +address+ is multicast address then +interface_address+ and - # +multicast_interface+ can be set as optional. - # - # A created socket is bound to +interface_address+. If you use IPv4 - # multicast then the interface of +interface_address+ is used as the - # inbound interface. If +interface_address+ is omitted or nil then - # '0.0.0.0' or '::1' is used. - # - # If you use IPv6 multicast then +multicast_interface+ is used as the - # inbound interface. +multicast_interface+ is a network interface index. - # If +multicast_interface+ is omitted then 0 (default interface) is used. - - def make_socket(address, interface_address=nil, multicast_interface=0) - addrinfo = Addrinfo.udp(address, @port) - - socket = Socket.new(addrinfo.pfamily, addrinfo.socktype, - addrinfo.protocol) - - if addrinfo.ipv4_multicast? or addrinfo.ipv6_multicast? then - if Socket.const_defined?(:SO_REUSEPORT) then - socket.setsockopt(:SOCKET, :SO_REUSEPORT, true) - else - socket.setsockopt(:SOCKET, :SO_REUSEADDR, true) - end - - if addrinfo.ipv4_multicast? then - interface_address = '0.0.0.0' if interface_address.nil? - socket.bind(Addrinfo.udp(interface_address, @port)) - - mreq = IPAddr.new(addrinfo.ip_address).hton + - IPAddr.new(interface_address).hton - - socket.setsockopt(:IPPROTO_IP, :IP_ADD_MEMBERSHIP, mreq) - else - interface_address = '::1' if interface_address.nil? - socket.bind(Addrinfo.udp(interface_address, @port)) - - mreq = IPAddr.new(addrinfo.ip_address).hton + - [multicast_interface].pack('I') - - socket.setsockopt(:IPPROTO_IPV6, :IPV6_JOIN_GROUP, mreq) - end - else - socket.bind(addrinfo) - end - - socket - rescue - socket = socket.close if socket - raise - ensure - @sockets << socket if socket - end - - ## - # Creates threads that pick up UDP packets and passes them to do_write for - # decoding. - - def write_services - @sockets.map do |s| - Thread.new(s) do |socket| - loop do - msg = socket.recv(1024) - do_write(msg) - end - end - end - end - - ## - # Extracts the response URI from +msg+ and adds it to TupleSpace where it - # will be picked up by +reply_service+ for notification. - - def do_write(msg) - Thread.new do - begin - tuple, sec = Marshal.load(msg) - @ts.write(tuple, sec) - rescue - end - end - end - - ## - # Creates a thread that notifies waiting clients from the TupleSpace. - - def reply_service - Thread.new do - loop do - do_reply - end - end - end - - ## - # Pulls lookup tuples out of the TupleSpace and sends their DRb object the - # address of the local TupleSpace. - - def do_reply - tuple = @ts.take([:lookup_ring, nil], @renewer) - Thread.new { tuple[1].call(@ts) rescue nil} - rescue - end - - ## - # Shuts down the RingServer - - def shutdown - @renewer.renew = false - - @w_services.each do |thread| - thread.kill - thread.join - end - - @sockets.each do |socket| - socket.close - end - - @r_service.kill - @r_service.join - end - - end - - ## - # RingFinger is used by RingServer clients to discover the RingServer's - # TupleSpace. Typically, all a client needs to do is call - # RingFinger.primary to retrieve the remote TupleSpace, which it can then - # begin using. - # - # To find the first available remote TupleSpace: - # - # Rinda::RingFinger.primary - # - # To create a RingFinger that broadcasts to a custom list: - # - # rf = Rinda::RingFinger.new ['localhost', '192.0.2.1'] - # rf.primary - # - # Rinda::RingFinger also understands multicast addresses and sets them up - # properly. This allows you to run multiple RingServers on the same host: - # - # rf = Rinda::RingFinger.new ['239.0.0.1'] - # rf.primary - # - # You can set the hop count (or TTL) for multicast searches using - # #multicast_hops. - # - # If you use IPv6 multicast you may need to set both an address and the - # outbound interface index: - # - # rf = Rinda::RingFinger.new ['ff02::1'] - # rf.multicast_interface = 1 - # rf.primary - # - # At this time there is no easy way to get an interface index by name. - - class RingFinger - - @@broadcast_list = ['', 'localhost'] - - @@finger = nil - - ## - # Creates a singleton RingFinger and looks for a RingServer. Returns the - # created RingFinger. - - def self.finger - unless @@finger - @@finger = self.new - @@finger.lookup_ring_any - end - @@finger - end - - ## - # Returns the first advertised TupleSpace. - - def self.primary - finger.primary - end - - ## - # Contains all discovered TupleSpaces except for the primary. - - def self.to_a - finger.to_a - end - - ## - # The list of addresses where RingFinger will send query packets. - - attr_accessor :broadcast_list - - ## - # Maximum number of hops for sent multicast packets (if using a multicast - # address in the broadcast list). The default is 1 (same as UDP - # broadcast). - - attr_accessor :multicast_hops - - ## - # The interface index to send IPv6 multicast packets from. - - attr_accessor :multicast_interface - - ## - # The port that RingFinger will send query packets to. - - attr_accessor :port - - ## - # Contain the first advertised TupleSpace after lookup_ring_any is called. - - attr_accessor :primary - - ## - # Creates a new RingFinger that will look for RingServers at +port+ on - # the addresses in +broadcast_list+. - # - # If +broadcast_list+ contains a multicast address then multicast queries - # will be made using the given multicast_hops and multicast_interface. - - def initialize(broadcast_list=@@broadcast_list, port=Ring_PORT) - @broadcast_list = broadcast_list || ['localhost'] - @port = port - @primary = nil - @rings = [] - - @multicast_hops = 1 - @multicast_interface = 0 - end - - ## - # Contains all discovered TupleSpaces except for the primary. - - def to_a - @rings - end - - ## - # Iterates over all discovered TupleSpaces starting with the primary. - - def each - lookup_ring_any unless @primary - return unless @primary - yield(@primary) - @rings.each { |x| yield(x) } - end - - ## - # Looks up RingServers waiting +timeout+ seconds. RingServers will be - # given +block+ as a callback, which will be called with the remote - # TupleSpace. - - def lookup_ring(timeout=5, &block) - return lookup_ring_any(timeout) unless block_given? - - msg = Marshal.dump([[:lookup_ring, DRbObject.new(block)], timeout]) - @broadcast_list.each do |it| - send_message(it, msg) - end - sleep(timeout) - end - - ## - # Returns the first found remote TupleSpace. Any further recovered - # TupleSpaces can be found by calling +to_a+. - - def lookup_ring_any(timeout=5) - queue = Thread::Queue.new - - Thread.new do - self.lookup_ring(timeout) do |ts| - queue.push(ts) - end - queue.push(nil) - end - - @primary = queue.pop - raise('RingNotFound') if @primary.nil? - - Thread.new do - while it = queue.pop - @rings.push(it) - end - end - - @primary - end - - ## - # Creates a socket for +address+ with the appropriate multicast options - # for multicast addresses. - - def make_socket(address) # :nodoc: - addrinfo = Addrinfo.udp(address, @port) - - soc = Socket.new(addrinfo.pfamily, addrinfo.socktype, addrinfo.protocol) - begin - if addrinfo.ipv4_multicast? then - soc.setsockopt(Socket::Option.ipv4_multicast_loop(1)) - soc.setsockopt(Socket::Option.ipv4_multicast_ttl(@multicast_hops)) - elsif addrinfo.ipv6_multicast? then - soc.setsockopt(:IPPROTO_IPV6, :IPV6_MULTICAST_LOOP, true) - soc.setsockopt(:IPPROTO_IPV6, :IPV6_MULTICAST_HOPS, - [@multicast_hops].pack('I')) - soc.setsockopt(:IPPROTO_IPV6, :IPV6_MULTICAST_IF, - [@multicast_interface].pack('I')) - else - soc.setsockopt(:SOL_SOCKET, :SO_BROADCAST, true) - end - - soc.connect(addrinfo) - rescue Exception - soc.close - raise - end - - soc - end - - def send_message(address, message) # :nodoc: - soc = make_socket(address) - - soc.send(message, 0) - rescue - nil - ensure - soc.close if soc - end - - end - - ## - # RingProvider uses a RingServer advertised TupleSpace as a name service. - # TupleSpace clients can register themselves with the remote TupleSpace and - # look up other provided services via the remote TupleSpace. - # - # Services are registered with a tuple of the format [:name, klass, - # DRbObject, description]. - - class RingProvider - - ## - # Creates a RingProvider that will provide a +klass+ service running on - # +front+, with a +description+. +renewer+ is optional. - - def initialize(klass, front, desc, renewer = nil) - @tuple = [:name, klass, front, desc] - @renewer = renewer || Rinda::SimpleRenewer.new - end - - ## - # Advertises this service on the primary remote TupleSpace. - - def provide - ts = Rinda::RingFinger.primary - ts.write(@tuple, @renewer) - end - - end - -end diff --git a/lib/rinda/tuplespace.rb b/lib/rinda/tuplespace.rb deleted file mode 100644 index 6a41a7ba75d503..00000000000000 --- a/lib/rinda/tuplespace.rb +++ /dev/null @@ -1,641 +0,0 @@ -# frozen_string_literal: false -require 'monitor' -require 'drb/drb' -require_relative 'rinda' -require 'forwardable' - -module Rinda - - ## - # A TupleEntry is a Tuple (i.e. a possible entry in some Tuplespace) - # together with expiry and cancellation data. - - class TupleEntry - - include DRbUndumped - - attr_accessor :expires - - ## - # Creates a TupleEntry based on +ary+ with an optional renewer or expiry - # time +sec+. - # - # A renewer must implement the +renew+ method which returns a Numeric, - # nil, or true to indicate when the tuple has expired. - - def initialize(ary, sec=nil) - @cancel = false - @expires = nil - @tuple = make_tuple(ary) - @renewer = nil - renew(sec) - end - - ## - # Marks this TupleEntry as canceled. - - def cancel - @cancel = true - end - - ## - # A TupleEntry is dead when it is canceled or expired. - - def alive? - !canceled? && !expired? - end - - ## - # Return the object which makes up the tuple itself: the Array - # or Hash. - - def value; @tuple.value; end - - ## - # Returns the canceled status. - - def canceled?; @cancel; end - - ## - # Has this tuple expired? (true/false). - # - # A tuple has expired when its expiry timer based on the +sec+ argument to - # #initialize runs out. - - def expired? - return true unless @expires - return false if @expires > Time.now - return true if @renewer.nil? - renew(@renewer) - return true unless @expires - return @expires < Time.now - end - - ## - # Reset the expiry time according to +sec_or_renewer+. - # - # +nil+:: it is set to expire in the far future. - # +true+:: it has expired. - # Numeric:: it will expire in that many seconds. - # - # Otherwise the argument refers to some kind of renewer object - # which will reset its expiry time. - - def renew(sec_or_renewer) - sec, @renewer = get_renewer(sec_or_renewer) - @expires = make_expires(sec) - end - - ## - # Returns an expiry Time based on +sec+ which can be one of: - # Numeric:: +sec+ seconds into the future - # +true+:: the expiry time is the start of 1970 (i.e. expired) - # +nil+:: it is Tue Jan 19 03:14:07 GMT Standard Time 2038 (i.e. when - # UNIX clocks will die) - - def make_expires(sec=nil) - case sec - when Numeric - Time.now + sec - when true - Time.at(1) - when nil - Time.at(2**31-1) - end - end - - ## - # Retrieves +key+ from the tuple. - - def [](key) - @tuple[key] - end - - ## - # Fetches +key+ from the tuple. - - def fetch(key) - @tuple.fetch(key) - end - - ## - # The size of the tuple. - - def size - @tuple.size - end - - ## - # Creates a Rinda::Tuple for +ary+. - - def make_tuple(ary) - Rinda::Tuple.new(ary) - end - - private - - ## - # Returns a valid argument to make_expires and the renewer or nil. - # - # Given +true+, +nil+, or Numeric, returns that value and +nil+ (no actual - # renewer). Otherwise it returns an expiry value from calling +it.renew+ - # and the renewer. - - def get_renewer(it) - case it - when Numeric, true, nil - return it, nil - else - begin - return it.renew, it - rescue Exception - return it, nil - end - end - end - - end - - ## - # A TemplateEntry is a Template together with expiry and cancellation data. - - class TemplateEntry < TupleEntry - ## - # Matches this TemplateEntry against +tuple+. See Template#match for - # details on how a Template matches a Tuple. - - def match(tuple) - @tuple.match(tuple) - end - - alias === match - - def make_tuple(ary) # :nodoc: - Rinda::Template.new(ary) - end - - end - - ## - # Documentation? - - class WaitTemplateEntry < TemplateEntry - - attr_reader :found - - def initialize(place, ary, expires=nil) - super(ary, expires) - @place = place - @cond = place.new_cond - @found = nil - end - - def cancel - super - signal - end - - def wait - @cond.wait - end - - def read(tuple) - @found = tuple - signal - end - - def signal - @place.synchronize do - @cond.signal - end - end - - end - - ## - # A NotifyTemplateEntry is returned by TupleSpace#notify and is notified of - # TupleSpace changes. You may receive either your subscribed event or the - # 'close' event when iterating over notifications. - # - # See TupleSpace#notify_event for valid notification types. - # - # == Example - # - # ts = Rinda::TupleSpace.new - # observer = ts.notify 'write', [nil] - # - # Thread.start do - # observer.each { |t| p t } - # end - # - # 3.times { |i| ts.write [i] } - # - # Outputs: - # - # ['write', [0]] - # ['write', [1]] - # ['write', [2]] - - class NotifyTemplateEntry < TemplateEntry - - ## - # Creates a new NotifyTemplateEntry that watches +place+ for +event+s that - # match +tuple+. - - def initialize(place, event, tuple, expires=nil) - ary = [event, Rinda::Template.new(tuple)] - super(ary, expires) - @queue = Thread::Queue.new - @done = false - end - - ## - # Called by TupleSpace to notify this NotifyTemplateEntry of a new event. - - def notify(ev) - @queue.push(ev) - end - - ## - # Retrieves a notification. Raises RequestExpiredError when this - # NotifyTemplateEntry expires. - - def pop - raise RequestExpiredError if @done - it = @queue.pop - @done = true if it[0] == 'close' - return it - end - - ## - # Yields event/tuple pairs until this NotifyTemplateEntry expires. - - def each # :yields: event, tuple - while !@done - it = pop - yield(it) - end - rescue - ensure - cancel - end - - end - - ## - # TupleBag is an unordered collection of tuples. It is the basis - # of Tuplespace. - - class TupleBag - class TupleBin - extend Forwardable - def_delegators '@bin', :find_all, :delete_if, :each, :empty? - - def initialize - @bin = [] - end - - def add(tuple) - @bin.push(tuple) - end - - def delete(tuple) - idx = @bin.rindex(tuple) - @bin.delete_at(idx) if idx - end - - def find - @bin.reverse_each do |x| - return x if yield(x) - end - nil - end - end - - def initialize # :nodoc: - @hash = {} - @enum = enum_for(:each_entry) - end - - ## - # +true+ if the TupleBag to see if it has any expired entries. - - def has_expires? - @enum.find do |tuple| - tuple.expires - end - end - - ## - # Add +tuple+ to the TupleBag. - - def push(tuple) - key = bin_key(tuple) - @hash[key] ||= TupleBin.new - @hash[key].add(tuple) - end - - ## - # Removes +tuple+ from the TupleBag. - - def delete(tuple) - key = bin_key(tuple) - bin = @hash[key] - return nil unless bin - bin.delete(tuple) - @hash.delete(key) if bin.empty? - tuple - end - - ## - # Finds all live tuples that match +template+. - def find_all(template) - bin_for_find(template).find_all do |tuple| - tuple.alive? && template.match(tuple) - end - end - - ## - # Finds a live tuple that matches +template+. - - def find(template) - bin_for_find(template).find do |tuple| - tuple.alive? && template.match(tuple) - end - end - - ## - # Finds all tuples in the TupleBag which when treated as templates, match - # +tuple+ and are alive. - - def find_all_template(tuple) - @enum.find_all do |template| - template.alive? && template.match(tuple) - end - end - - ## - # Delete tuples which dead tuples from the TupleBag, returning the deleted - # tuples. - - def delete_unless_alive - deleted = [] - @hash.each do |key, bin| - bin.delete_if do |tuple| - if tuple.alive? - false - else - deleted.push(tuple) - true - end - end - end - deleted - end - - private - def each_entry(&blk) - @hash.each do |k, v| - v.each(&blk) - end - end - - def bin_key(tuple) - head = tuple[0] - if head.class == Symbol - return head - else - false - end - end - - def bin_for_find(template) - key = bin_key(template) - key ? @hash.fetch(key, []) : @enum - end - end - - ## - # The Tuplespace manages access to the tuples it contains, - # ensuring mutual exclusion requirements are met. - # - # The +sec+ option for the write, take, move, read and notify methods may - # either be a number of seconds or a Renewer object. - - class TupleSpace - - include DRbUndumped - include MonitorMixin - - ## - # Creates a new TupleSpace. +period+ is used to control how often to look - # for dead tuples after modifications to the TupleSpace. - # - # If no dead tuples are found +period+ seconds after the last - # modification, the TupleSpace will stop looking for dead tuples. - - def initialize(period=60) - super() - @bag = TupleBag.new - @read_waiter = TupleBag.new - @take_waiter = TupleBag.new - @notify_waiter = TupleBag.new - @period = period - @keeper = nil - end - - ## - # Adds +tuple+ - - def write(tuple, sec=nil) - entry = create_entry(tuple, sec) - synchronize do - if entry.expired? - @read_waiter.find_all_template(entry).each do |template| - template.read(tuple) - end - notify_event('write', entry.value) - notify_event('delete', entry.value) - else - @bag.push(entry) - start_keeper if entry.expires - @read_waiter.find_all_template(entry).each do |template| - template.read(tuple) - end - @take_waiter.find_all_template(entry).each do |template| - template.signal - end - notify_event('write', entry.value) - end - end - entry - end - - ## - # Removes +tuple+ - - def take(tuple, sec=nil, &block) - move(nil, tuple, sec, &block) - end - - ## - # Moves +tuple+ to +port+. - - def move(port, tuple, sec=nil) - template = WaitTemplateEntry.new(self, tuple, sec) - yield(template) if block_given? - synchronize do - entry = @bag.find(template) - if entry - port.push(entry.value) if port - @bag.delete(entry) - notify_event('take', entry.value) - return port ? nil : entry.value - end - raise RequestExpiredError if template.expired? - - begin - @take_waiter.push(template) - start_keeper if template.expires - while true - raise RequestCanceledError if template.canceled? - raise RequestExpiredError if template.expired? - entry = @bag.find(template) - if entry - port.push(entry.value) if port - @bag.delete(entry) - notify_event('take', entry.value) - return port ? nil : entry.value - end - template.wait - end - ensure - @take_waiter.delete(template) - end - end - end - - ## - # Reads +tuple+, but does not remove it. - - def read(tuple, sec=nil) - template = WaitTemplateEntry.new(self, tuple, sec) - yield(template) if block_given? - synchronize do - entry = @bag.find(template) - return entry.value if entry - raise RequestExpiredError if template.expired? - - begin - @read_waiter.push(template) - start_keeper if template.expires - template.wait - raise RequestCanceledError if template.canceled? - raise RequestExpiredError if template.expired? - return template.found - ensure - @read_waiter.delete(template) - end - end - end - - ## - # Returns all tuples matching +tuple+. Does not remove the found tuples. - - def read_all(tuple) - template = WaitTemplateEntry.new(self, tuple, nil) - synchronize do - entry = @bag.find_all(template) - entry.collect do |e| - e.value - end - end - end - - ## - # Registers for notifications of +event+. Returns a NotifyTemplateEntry. - # See NotifyTemplateEntry for examples of how to listen for notifications. - # - # +event+ can be: - # 'write':: A tuple was added - # 'take':: A tuple was taken or moved - # 'delete':: A tuple was lost after being overwritten or expiring - # - # The TupleSpace will also notify you of the 'close' event when the - # NotifyTemplateEntry has expired. - - def notify(event, tuple, sec=nil) - template = NotifyTemplateEntry.new(self, event, tuple, sec) - synchronize do - @notify_waiter.push(template) - end - template - end - - private - - def create_entry(tuple, sec) - TupleEntry.new(tuple, sec) - end - - ## - # Removes dead tuples. - - def keep_clean - synchronize do - @read_waiter.delete_unless_alive.each do |e| - e.signal - end - @take_waiter.delete_unless_alive.each do |e| - e.signal - end - @notify_waiter.delete_unless_alive.each do |e| - e.notify(['close']) - end - @bag.delete_unless_alive.each do |e| - notify_event('delete', e.value) - end - end - end - - ## - # Notifies all registered listeners for +event+ of a status change of - # +tuple+. - - def notify_event(event, tuple) - ev = [event, tuple] - @notify_waiter.find_all_template(ev).each do |template| - template.notify(ev) - end - end - - ## - # Creates a thread that scans the tuplespace for expired tuples. - - def start_keeper - return if @keeper && @keeper.alive? - @keeper = Thread.new do - while true - sleep(@period) - synchronize do - break unless need_keeper? - keep_clean - end - end - end - end - - ## - # Checks the tuplespace to see if it needs cleaning. - - def need_keeper? - return true if @bag.has_expires? - return true if @read_waiter.has_expires? - return true if @take_waiter.has_expires? - return true if @notify_waiter.has_expires? - end - - end - -end - diff --git a/test/rinda/test_rinda.rb b/test/rinda/test_rinda.rb deleted file mode 100644 index 00404e39df7aa8..00000000000000 --- a/test/rinda/test_rinda.rb +++ /dev/null @@ -1,912 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' -require 'envutil' - -require 'drb/drb' -require 'drb/eq' -require 'rinda/ring' -require 'rinda/tuplespace' -require 'timeout' -require 'singleton' - -module Rinda - -class MockClock - include Singleton - - class MyTS < Rinda::TupleSpace - def keeper_thread - nil - end - - def stop_keeper - if @keeper - @keeper.kill - @keeper.join - @keeper = nil - end - end - end - - def initialize - @now = 2 - @reso = 1 - @ts = nil - @inf = 2**31 - 1 - end - - def start_keeper - @now = 2 - @reso = 1 - @ts&.stop_keeper - @ts = MyTS.new - @ts.write([2, :now]) - @inf = 2**31 - 1 - end - - def stop_keeper - @ts.stop_keeper - end - - def now - @now.to_f - end - - def at(n) - n - end - - def _forward(n=nil) - now ,= @ts.take([nil, :now]) - @now = now + n - @ts.write([@now, :now]) - end - - def forward(n) - while n > 0 - _forward(@reso) - n -= @reso - Thread.pass - end - end - - def rewind - @ts.take([nil, :now]) - @ts.write([@inf, :now]) - @ts.take([nil, :now]) - @now = 2 - @ts.write([2, :now]) - end - - def sleep(n=nil) - now ,= @ts.read([nil, :now]) - @ts.read([(now + n)..@inf, :now]) - 0 - end -end - -module Time - def sleep(n) - @m.sleep(n) - end - module_function :sleep - - def at(n) - n - end - module_function :at - - def now - defined?(@m) && @m ? @m.now : 2 - end - module_function :now - - def rewind - @m.rewind - end - module_function :rewind - - def forward(n) - @m.forward(n) - end - module_function :forward - - @m = MockClock.instance -end - -class TupleSpace - def sleep(n) - Kernel.sleep(n * 0.01) - end -end - -module TupleSpaceTestModule - def setup - MockClock.instance.start_keeper - end - - def teardown - MockClock.instance.stop_keeper - end - - def sleep(n) - if Thread.current == Thread.main - Time.forward(n) - else - Time.sleep(n) - end - end - - def thread_join(th) - while th.alive? - Kernel.sleep(0.1) - sleep(1) - end - th.value - end - - def test_00_tuple - tuple = Rinda::TupleEntry.new([1,2,3]) - assert(!tuple.canceled?) - assert(!tuple.expired?) - assert(tuple.alive?) - end - - def test_00_template - tmpl = Rinda::Template.new([1,2,3]) - assert_equal(3, tmpl.size) - assert_equal(3, tmpl[2]) - assert(tmpl.match([1,2,3])) - assert(!tmpl.match([1,nil,3])) - - tmpl = Rinda::Template.new([/^rinda/i, nil, :hello]) - assert_equal(3, tmpl.size) - assert(tmpl.match(['Rinda', 2, :hello])) - assert(!tmpl.match(['Rinda', 2, Symbol])) - assert(!tmpl.match([1, 2, :hello])) - assert(tmpl.match([/^rinda/i, 2, :hello])) - - tmpl = Rinda::Template.new([Symbol]) - assert_equal(1, tmpl.size) - assert(tmpl.match([:hello])) - assert(tmpl.match([Symbol])) - assert(!tmpl.match(['Symbol'])) - - tmpl = Rinda::Template.new({"message"=>String, "name"=>String}) - assert_equal(2, tmpl.size) - assert(tmpl.match({"message"=>"Hello", "name"=>"Foo"})) - assert(!tmpl.match({"message"=>"Hello", "name"=>"Foo", "1"=>2})) - assert(!tmpl.match({"message"=>"Hi", "name"=>"Foo", "age"=>1})) - assert(!tmpl.match({"message"=>"Hello", "no_name"=>"Foo"})) - - assert_raise(Rinda::InvalidHashTupleKey) do - Rinda::Template.new({:message=>String, "name"=>String}) - end - tmpl = Rinda::Template.new({"name"=>String}) - assert_equal(1, tmpl.size) - assert(tmpl.match({"name"=>"Foo"})) - assert(!tmpl.match({"message"=>"Hello", "name"=>"Foo"})) - assert(!tmpl.match({"message"=>:symbol, "name"=>"Foo", "1"=>2})) - assert(!tmpl.match({"message"=>"Hi", "name"=>"Foo", "age"=>1})) - assert(!tmpl.match({"message"=>"Hello", "no_name"=>"Foo"})) - - tmpl = Rinda::Template.new({"message"=>String, "name"=>String}) - assert_equal(2, tmpl.size) - assert(tmpl.match({"message"=>"Hello", "name"=>"Foo"})) - assert(!tmpl.match({"message"=>"Hello", "name"=>"Foo", "1"=>2})) - assert(!tmpl.match({"message"=>"Hi", "name"=>"Foo", "age"=>1})) - assert(!tmpl.match({"message"=>"Hello", "no_name"=>"Foo"})) - - tmpl = Rinda::Template.new({"message"=>String}) - assert_equal(1, tmpl.size) - assert(tmpl.match({"message"=>"Hello"})) - assert(!tmpl.match({"message"=>"Hello", "name"=>"Foo"})) - assert(!tmpl.match({"message"=>"Hello", "name"=>"Foo", "1"=>2})) - assert(!tmpl.match({"message"=>"Hi", "name"=>"Foo", "age"=>1})) - assert(!tmpl.match({"message"=>"Hello", "no_name"=>"Foo"})) - - tmpl = Rinda::Template.new({"message"=>String, "name"=>nil}) - assert_equal(2, tmpl.size) - assert(tmpl.match({"message"=>"Hello", "name"=>"Foo"})) - assert(!tmpl.match({"message"=>"Hello", "name"=>"Foo", "1"=>2})) - assert(!tmpl.match({"message"=>"Hi", "name"=>"Foo", "age"=>1})) - assert(!tmpl.match({"message"=>"Hello", "no_name"=>"Foo"})) - - assert_raise(Rinda::InvalidHashTupleKey) do - @ts.write({:message=>String, "name"=>String}) - end - - @ts.write([1, 2, 3]) - assert_equal([1, 2, 3], @ts.take([1, 2, 3])) - - @ts.write({'1'=>1, '2'=>2, '3'=>3}) - assert_equal({'1'=>1, '2'=>2, '3'=>3}, @ts.take({'1'=>1, '2'=>2, '3'=>3})) - - entry = @ts.write(['1'=>1, '2'=>2, '3'=>3]) - assert_raise(Rinda::RequestExpiredError) do - assert_equal({'1'=>1, '2'=>2, '3'=>3}, @ts.read({'1'=>1}, 0)) - end - entry.cancel - end - - def test_00_DRbObject - ro = DRbObject.new(nil, "druby://host:1234") - tmpl = Rinda::DRbObjectTemplate.new - assert(tmpl === ro) - - tmpl = Rinda::DRbObjectTemplate.new("druby://host:1234") - assert(tmpl === ro) - - tmpl = Rinda::DRbObjectTemplate.new("druby://host:12345") - assert(!(tmpl === ro)) - - tmpl = Rinda::DRbObjectTemplate.new(/^druby:\/\/host:/) - assert(tmpl === ro) - - ro = DRbObject.new_with(12345, 1234) - assert(!(tmpl === ro)) - - ro = DRbObject.new_with("druby://foo:12345", 1234) - assert(!(tmpl === ro)) - - tmpl = Rinda::DRbObjectTemplate.new(/^druby:\/\/(foo|bar):/) - assert(tmpl === ro) - - ro = DRbObject.new_with("druby://bar:12345", 1234) - assert(tmpl === ro) - - ro = DRbObject.new_with("druby://baz:12345", 1234) - assert(!(tmpl === ro)) - end - - def test_inp_rdp - assert_raise(Rinda::RequestExpiredError) do - @ts.take([:empty], 0) - end - - assert_raise(Rinda::RequestExpiredError) do - @ts.read([:empty], 0) - end - end - - def test_ruby_talk_264062 - th = Thread.new { - assert_raise(Rinda::RequestExpiredError) do - @ts.take([:empty], 1) - end - } - sleep(10) - thread_join(th) - - th = Thread.new { - assert_raise(Rinda::RequestExpiredError) do - @ts.read([:empty], 1) - end - } - sleep(10) - thread_join(th) - end - - def test_symbol_tuple - @ts.write([:symbol, :symbol]) - @ts.write(['string', :string]) - assert_equal([[:symbol, :symbol]], @ts.read_all([:symbol, nil])) - assert_equal([[:symbol, :symbol]], @ts.read_all([Symbol, nil])) - assert_equal([], @ts.read_all([:nil, nil])) - end - - def test_core_01 - 5.times do - @ts.write([:req, 2]) - end - - assert_equal([[:req, 2], [:req, 2], [:req, 2], [:req, 2], [:req, 2]], - @ts.read_all([nil, nil])) - - taker = Thread.new(5) do |count| - s = 0 - count.times do - tuple = @ts.take([:req, Integer]) - assert_equal(2, tuple[1]) - s += tuple[1] - end - @ts.write([:ans, s]) - s - end - - assert_equal(10, thread_join(taker)) - assert_equal([:ans, 10], @ts.take([:ans, 10])) - assert_equal([], @ts.read_all([nil, nil])) - end - - def test_core_02 - taker = Thread.new(5) do |count| - s = 0 - count.times do - tuple = @ts.take([:req, Integer]) - assert_equal(2, tuple[1]) - s += tuple[1] - end - @ts.write([:ans, s]) - s - end - - 5.times do - @ts.write([:req, 2]) - end - - assert_equal(10, thread_join(taker)) - assert_equal([:ans, 10], @ts.take([:ans, 10])) - assert_equal([], @ts.read_all([nil, nil])) - end - - def test_core_03_notify - notify1 = @ts.notify(nil, [:req, Integer]) - notify2 = @ts.notify(nil, {"message"=>String, "name"=>String}) - - 5.times do - @ts.write([:req, 2]) - end - - 5.times do - tuple = @ts.take([:req, Integer]) - assert_equal(2, tuple[1]) - end - - 5.times do - assert_equal(['write', [:req, 2]], notify1.pop) - end - 5.times do - assert_equal(['take', [:req, 2]], notify1.pop) - end - - @ts.write({"message"=>"first", "name"=>"3"}) - @ts.write({"message"=>"second", "name"=>"1"}) - @ts.write({"message"=>"third", "name"=>"0"}) - @ts.take({"message"=>"third", "name"=>"0"}) - @ts.take({"message"=>"first", "name"=>"3"}) - - assert_equal(["write", {"message"=>"first", "name"=>"3"}], notify2.pop) - assert_equal(["write", {"message"=>"second", "name"=>"1"}], notify2.pop) - assert_equal(["write", {"message"=>"third", "name"=>"0"}], notify2.pop) - assert_equal(["take", {"message"=>"third", "name"=>"0"}], notify2.pop) - assert_equal(["take", {"message"=>"first", "name"=>"3"}], notify2.pop) - end - - def test_cancel_01 - entry = @ts.write([:removeme, 1]) - assert_equal([[:removeme, 1]], @ts.read_all([nil, nil])) - entry.cancel - assert_equal([], @ts.read_all([nil, nil])) - - template = nil - taker = Thread.new do - assert_raise(Rinda::RequestCanceledError) do - @ts.take([:take, nil], 10) do |t| - template = t - Thread.new do - template.cancel - end - end - end - end - - sleep(2) - thread_join(taker) - - assert(template.canceled?) - - @ts.write([:take, 1]) - - assert_equal([[:take, 1]], @ts.read_all([nil, nil])) - end - - def test_cancel_02 - omit 'this test is unstable with --jit-wait' if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? - entry = @ts.write([:removeme, 1]) - assert_equal([[:removeme, 1]], @ts.read_all([nil, nil])) - entry.cancel - assert_equal([], @ts.read_all([nil, nil])) - - template = nil - reader = Thread.new do - assert_raise(Rinda::RequestCanceledError) do - @ts.read([:take, nil], 10) do |t| - template = t - Thread.new do - template.cancel - end - end - end - end - - sleep(2) - thread_join(reader) - - assert(template.canceled?) - - @ts.write([:take, 1]) - - assert_equal([[:take, 1]], @ts.read_all([nil, nil])) - end - - class SimpleRenewer - def initialize(sec, n = 1) - @sec = sec - @n = n - end - - def renew - return -1 if @n <= 0 - @n -= 1 - return @sec - end - end - - def test_00_renewer - tuple = Rinda::TupleEntry.new([1,2,3], true) - assert(!tuple.canceled?) - assert(tuple.expired?) - assert(!tuple.alive?) - - tuple = Rinda::TupleEntry.new([1,2,3], 1) - assert(!tuple.canceled?) - assert(!tuple.expired?) - assert(tuple.alive?) - sleep(2) - assert(tuple.expired?) - assert(!tuple.alive?) - - @renewer = SimpleRenewer.new(1,2) - tuple = Rinda::TupleEntry.new([1,2,3], @renewer) - assert(!tuple.canceled?) - assert(!tuple.expired?) - assert(tuple.alive?) - sleep(1) - assert(!tuple.canceled?) - assert(!tuple.expired?) - assert(tuple.alive?) - sleep(2) - assert(tuple.expired?) - assert(!tuple.alive?) - end -end - -class TupleSpaceTest < Test::Unit::TestCase - include TupleSpaceTestModule - - def setup - super - ThreadGroup.new.add(Thread.current) - @ts = Rinda::TupleSpace.new(1) - end - def teardown - # implementation-dependent - @ts.instance_eval{ - if th = @keeper - th.kill - th.join - end - } - super - end -end - -class TupleSpaceProxyTest < Test::Unit::TestCase - include TupleSpaceTestModule - - def setup - if RUBY_PLATFORM.match?(/mingw/) - @omitted = true - omit 'This test seems to randomly hang on GitHub Actions MinGW' - end - super - ThreadGroup.new.add(Thread.current) - @ts_base = Rinda::TupleSpace.new(1) - @ts = Rinda::TupleSpaceProxy.new(@ts_base) - @server = DRb.start_service("druby://localhost:0") - end - def teardown - return if @omitted - @omitted = false - - # implementation-dependent - @ts_base.instance_eval{ - if th = @keeper - th.kill - th.join - end - } - @server.stop_service - DRb::DRbConn.stop_pool - super - end - - def test_remote_array_and_hash - # Don't remove ary/hsh local variables. - # These are necessary to protect objects from GC. - ary = [1, 2, 3] - @ts.write(DRbObject.new(ary)) - assert_equal([1, 2, 3], @ts.take([1, 2, 3], 0)) - hsh = {'head' => 1, 'tail' => 2} - @ts.write(DRbObject.new(hsh)) - assert_equal({'head' => 1, 'tail' => 2}, - @ts.take({'head' => 1, 'tail' => 2}, 0)) - end - - def test_take_bug_8215 - omit "this test randomly fails on mswin" if /mswin/ =~ RUBY_PLATFORM - service = DRb.start_service("druby://localhost:0", @ts_base) - - uri = service.uri - - args = [EnvUtil.rubybin, *%W[-rdrb/drb -rdrb/eq -rrinda/ring -rrinda/tuplespace -e]] - - take = spawn(*args, <<-'end;', uri) - uri = ARGV[0] - DRb.start_service("druby://localhost:0") - ro = DRbObject.new_with_uri(uri) - ts = Rinda::TupleSpaceProxy.new(ro) - th = Thread.new do - ts.take([:test_take, nil]) - rescue Interrupt - # Expected - end - Kernel.sleep(0.1) - th.raise(Interrupt) # causes loss of the taken tuple - ts.write([:barrier, :continue]) - Kernel.sleep - end; - - @ts_base.take([:barrier, :continue]) - - write = spawn(*args, <<-'end;', uri) - uri = ARGV[0] - DRb.start_service("druby://localhost:0") - ro = DRbObject.new_with_uri(uri) - ts = Rinda::TupleSpaceProxy.new(ro) - ts.write([:test_take, 42]) - end; - - status = Process.wait(write) - - assert_equal([[:test_take, 42]], @ts_base.read_all([:test_take, nil]), - '[bug:8215] tuple lost') - ensure - service.stop_service if service - DRb::DRbConn.stop_pool - signal = /mswin|mingw/ =~ RUBY_PLATFORM ? "KILL" : "TERM" - Process.kill(signal, write) if write && status.nil? - Process.kill(signal, take) if take - Process.wait(write) if write && status.nil? - Process.wait(take) if take - end -end - -module RingIPv4 - def ipv4_mc(rf) - begin - v4mc = rf.make_socket('239.0.0.1') - rescue Errno::ENETUNREACH, Errno::ENOBUFS, Errno::ENODEV - omit 'IPv4 multicast not available' - end - - begin - yield v4mc - ensure - v4mc.close - end - end -end - -module RingIPv6 - def prepare_ipv6(r) - begin - Socket.getifaddrs.each do |ifaddr| - next unless ifaddr.addr - next unless ifaddr.addr.ipv6_linklocal? - next if ifaddr.name[0, 2] == "lo" - r.multicast_interface = ifaddr.ifindex - return ifaddr - end - rescue NotImplementedError - # ifindex() function may not be implemented on Windows. - return if - Socket.ip_address_list.any? { |addrinfo| addrinfo.ipv6? && !addrinfo.ipv6_loopback? } - end - omit 'IPv6 not available' - end - - def ipv6_mc(rf, hops = nil) - ifaddr = prepare_ipv6(rf) - rf.multicast_hops = hops if hops - begin - v6mc = rf.make_socket("ff02::1") - rescue Errno::EINVAL - # somehow Debian 6.0.7 needs ifname - v6mc = rf.make_socket("ff02::1%#{ifaddr.name}") - rescue Errno::EADDRNOTAVAIL - return # IPv6 address for multicast not available - rescue Errno::ENETDOWN - return # Network is down - rescue Errno::EHOSTUNREACH - return # Unreachable for some reason - end - begin - yield v6mc - ensure - v6mc.close - end - end -end - -class TestRingServer < Test::Unit::TestCase - include RingIPv4 - - def setup - @port = Rinda::Ring_PORT - - @ts = Rinda::TupleSpace.new - @rs = Rinda::RingServer.new(@ts, [], @port) - @server = DRb.start_service("druby://localhost:0") - end - def teardown - @rs.shutdown - # implementation-dependent - @ts.instance_eval{ - if th = @keeper - th.kill - th.join - end - } - @server.stop_service - DRb::DRbConn.stop_pool - end - - def test_do_reply - with_timeout(30) {_test_do_reply} - end - - def _test_do_reply - called = nil - - callback_orig = proc { |ts| - called = ts - } - - callback = DRb::DRbObject.new callback_orig - - @ts.write [:lookup_ring, callback] - - @rs.do_reply - - wait_for(30) {called} - - assert_same @ts, called - end - - def test_do_reply_local - omit 'timeout-based test becomes unstable with --jit-wait' if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? - with_timeout(30) {_test_do_reply_local} - end - - def _test_do_reply_local - called = nil - - callback = proc { |ts| - called = ts - } - - @ts.write [:lookup_ring, callback] - - @rs.do_reply - - wait_for(30) {called} - - assert_same @ts, called - end - - def test_make_socket_unicast - v4 = @rs.make_socket('127.0.0.1') - - assert_equal('127.0.0.1', v4.local_address.ip_address) - assert_equal(@port, v4.local_address.ip_port) - end - - def test_make_socket_ipv4_multicast - ipv4_mc(@rs) do |v4mc| - begin - if Socket.const_defined?(:SO_REUSEPORT) then - assert(v4mc.getsockopt(:SOCKET, :SO_REUSEPORT).bool) - else - assert(v4mc.getsockopt(:SOCKET, :SO_REUSEADDR).bool) - end - rescue TypeError - if /aix/ =~ RUBY_PLATFORM - omit "Known bug in getsockopt(2) on AIX" - end - raise $! - end - - assert_equal('0.0.0.0', v4mc.local_address.ip_address) - assert_equal(@port, v4mc.local_address.ip_port) - end - end - - def test_make_socket_ipv6_multicast - omit 'IPv6 not available' unless - Socket.ip_address_list.any? { |addrinfo| addrinfo.ipv6? && !addrinfo.ipv6_loopback? } - - begin - v6mc = @rs.make_socket('ff02::1') - rescue Errno::EADDRNOTAVAIL - return # IPv6 address for multicast not available - rescue Errno::ENOBUFS => e - omit "Missing multicast support in OS: #{e.message}" - end - - if Socket.const_defined?(:SO_REUSEPORT) then - assert v6mc.getsockopt(:SOCKET, :SO_REUSEPORT).bool - else - assert v6mc.getsockopt(:SOCKET, :SO_REUSEADDR).bool - end - - assert_equal('::1', v6mc.local_address.ip_address) - assert_equal(@port, v6mc.local_address.ip_port) - end - - def test_ring_server_ipv4_multicast - @rs.shutdown - begin - @rs = Rinda::RingServer.new(@ts, [['239.0.0.1', '0.0.0.0']], @port) - rescue Errno::ENOBUFS, Errno::ENODEV => e - omit "Missing multicast support in OS: #{e.message}" - end - - v4mc = @rs.instance_variable_get('@sockets').first - - begin - if Socket.const_defined?(:SO_REUSEPORT) then - assert(v4mc.getsockopt(:SOCKET, :SO_REUSEPORT).bool) - else - assert(v4mc.getsockopt(:SOCKET, :SO_REUSEADDR).bool) - end - rescue TypeError - if /aix/ =~ RUBY_PLATFORM - omit "Known bug in getsockopt(2) on AIX" - end - raise $! - end - - assert_equal('0.0.0.0', v4mc.local_address.ip_address) - assert_equal(@port, v4mc.local_address.ip_port) - end - - def test_ring_server_ipv6_multicast - omit 'IPv6 not available' unless - Socket.ip_address_list.any? { |addrinfo| addrinfo.ipv6? && !addrinfo.ipv6_loopback? } - - @rs.shutdown - begin - @rs = Rinda::RingServer.new(@ts, [['ff02::1', '::1', 0]], @port) - rescue Errno::EADDRNOTAVAIL - return # IPv6 address for multicast not available - end - - v6mc = @rs.instance_variable_get('@sockets').first - - if Socket.const_defined?(:SO_REUSEPORT) then - assert v6mc.getsockopt(:SOCKET, :SO_REUSEPORT).bool - else - assert v6mc.getsockopt(:SOCKET, :SO_REUSEADDR).bool - end - - assert_equal('::1', v6mc.local_address.ip_address) - assert_equal(@port, v6mc.local_address.ip_port) - end - - def test_shutdown - @rs.shutdown - - assert_nil(@rs.do_reply, 'otherwise should hang forever') - end - - private - - def with_timeout(n) - aoe = Thread.abort_on_exception - Thread.abort_on_exception = true - tl0 = Thread.list - tl = nil - th = Thread.new(Thread.current) do |mth| - sleep n - (tl = Thread.list - tl0).each {|t|t.raise(Timeout::Error)} - mth.raise(Timeout::Error) - end - tl0 << th - yield - rescue Timeout::Error => e - $stderr.puts "TestRingServer#with_timeout: timeout in #{n}s:" - $stderr.puts caller - if tl - bt = e.backtrace - tl.each do |t| - begin - t.value - rescue Timeout::Error => e - bt.unshift("") - bt[0, 0] = e.backtrace - end - end - end - raise Timeout::Error, "timeout", bt - ensure - if th - th.kill - th.join - end - Thread.abort_on_exception = aoe - end - - def wait_for(n) - t = n + Process.clock_gettime(Process::CLOCK_MONOTONIC, :second) - until yield - if t < Process.clock_gettime(Process::CLOCK_MONOTONIC, :second) - flunk "timeout during waiting call" - end - sleep 0.1 - end - end -end - -class TestRingFinger < Test::Unit::TestCase - include RingIPv6 - include RingIPv4 - - def setup - @rf = Rinda::RingFinger.new - end - - def test_make_socket_unicast - v4 = @rf.make_socket('127.0.0.1') - - assert(v4.getsockopt(:SOL_SOCKET, :SO_BROADCAST).bool) - rescue TypeError - if /aix/ =~ RUBY_PLATFORM - omit "Known bug in getsockopt(2) on AIX" - end - raise $! - ensure - v4.close if v4 - end - - def test_make_socket_ipv4_multicast - ipv4_mc(@rf) do |v4mc| - assert_equal(1, v4mc.getsockopt(:IPPROTO_IP, :IP_MULTICAST_LOOP).ipv4_multicast_loop) - assert_equal(1, v4mc.getsockopt(:IPPROTO_IP, :IP_MULTICAST_TTL).ipv4_multicast_ttl) - end - end - - def test_make_socket_ipv6_multicast - ipv6_mc(@rf) do |v6mc| - assert_equal(1, v6mc.getsockopt(:IPPROTO_IPV6, :IPV6_MULTICAST_LOOP).int) - assert_equal(1, v6mc.getsockopt(:IPPROTO_IPV6, :IPV6_MULTICAST_HOPS).int) - end - end - - def test_make_socket_ipv4_multicast_hops - @rf.multicast_hops = 2 - ipv4_mc(@rf) do |v4mc| - assert_equal(2, v4mc.getsockopt(:IPPROTO_IP, :IP_MULTICAST_TTL).ipv4_multicast_ttl) - end - end - - def test_make_socket_ipv6_multicast_hops - ipv6_mc(@rf, 2) do |v6mc| - assert_equal(2, v6mc.getsockopt(:IPPROTO_IPV6, :IPV6_MULTICAST_HOPS).int) - end - end - -end - -end diff --git a/test/rinda/test_tuplebag.rb b/test/rinda/test_tuplebag.rb deleted file mode 100644 index ab17ca047cff30..00000000000000 --- a/test/rinda/test_tuplebag.rb +++ /dev/null @@ -1,173 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' -require 'rinda/tuplespace' - -class TestTupleBag < Test::Unit::TestCase - - def setup - @tb = Rinda::TupleBag.new - end - - def test_delete - assert_nothing_raised do - val = @tb.delete tup(:val, 1) - assert_equal nil, val - end - - t = tup(:val, 1) - @tb.push t - - val = @tb.delete t - - assert_equal t, val - - assert_equal [], @tb.find_all(tem(:val, 1)) - - t1 = tup(:val, 1) - t2 = tup(:val, 1) - @tb.push t1 - @tb.push t2 - - val = @tb.delete t1 - - assert_equal t1, val - - assert_equal [t2], @tb.find_all(tem(:val, 1)) - end - - def test_delete_unless_alive - assert_equal [], @tb.delete_unless_alive - - t1 = tup(:val, nil) - t2 = tup(:val, nil) - - @tb.push t1 - @tb.push t2 - - assert_equal [], @tb.delete_unless_alive - - t1.cancel - - assert_equal [t1], @tb.delete_unless_alive, 'canceled' - - t2.renew Object.new - - assert_equal [t2], @tb.delete_unless_alive, 'expired' - end - - def test_find - template = tem(:val, nil) - - assert_equal nil, @tb.find(template) - - t1 = tup(:other, 1) - @tb.push t1 - - assert_equal nil, @tb.find(template) - - t2 = tup(:val, 1) - @tb.push t2 - - assert_equal t2, @tb.find(template) - - t2.cancel - - assert_equal nil, @tb.find(template), 'canceled' - - t3 = tup(:val, 3) - @tb.push t3 - - assert_equal t3, @tb.find(template) - - t3.renew Object.new - - assert_equal nil, @tb.find(template), 'expired' - end - - def test_find_all - template = tem(:val, nil) - - t1 = tup(:other, 1) - @tb.push t1 - - assert_equal [], @tb.find_all(template) - - t2 = tup(:val, 2) - t3 = tup(:val, 3) - - @tb.push t2 - @tb.push t3 - - assert_equal [t2, t3], @tb.find_all(template) - - t2.cancel - - assert_equal [t3], @tb.find_all(template), 'canceled' - - t3.renew Object.new - - assert_equal [], @tb.find_all(template), 'expired' - end - - def test_find_all_template - tuple = tup(:val, 1) - - t1 = tem(:other, nil) - @tb.push t1 - - assert_equal [], @tb.find_all_template(tuple) - - t2 = tem(:val, nil) - t3 = tem(:val, nil) - - @tb.push t2 - @tb.push t3 - - assert_equal [t2, t3], @tb.find_all_template(tuple) - - t2.cancel - - assert_equal [t3], @tb.find_all_template(tuple), 'canceled' - - t3.renew Object.new - - assert_equal [], @tb.find_all_template(tuple), 'expired' - end - - def test_has_expires_eh - assert !@tb.has_expires? - - t = tup(:val, 1) - @tb.push t - - assert @tb.has_expires? - - t.renew Object.new - - assert !@tb.has_expires? - end - - def test_push - t = tup(:val, 1) - - @tb.push t - - assert_equal t, @tb.find(tem(:val, 1)) - end - - ## - # Create a tuple with +ary+ for its contents - - def tup(*ary) - Rinda::TupleEntry.new ary - end - - ## - # Create a template with +ary+ for its contents - - def tem(*ary) - Rinda::TemplateEntry.new ary - end - -end - From ce73fbd717a254ad5daab5c5c3b0f9c1f31ff886 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 19 Jan 2024 18:12:31 +0900 Subject: [PATCH 331/640] Document about rinda at Ruby 3.4 --- doc/maintainers.md | 8 +++----- doc/standard_library.rdoc | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/doc/maintainers.md b/doc/maintainers.md index 173beb58d707a5..f53b6567b6c5d1 100644 --- a/doc/maintainers.md +++ b/doc/maintainers.md @@ -236,11 +236,6 @@ have commit right, others don't. * https://github.com/ruby/reline * https://rubygems.org/gems/reline -#### lib/rinda/* -* Masatoshi SEKI (seki) -* https://github.com/ruby/rinda -* https://rubygems.org/gems/rinda - #### lib/securerandom.rb * Tanaka Akira (akr) * https://github.com/ruby/securerandom @@ -476,6 +471,9 @@ have commit right, others don't. #### lib/resolv-replace.rb * https://github.com/ruby/resolv-replace +#### rinda +* https://github.com/ruby/rinda + ## Platform Maintainers ### mswin64 (Microsoft Windows) * NAKAMURA Usaku (usa) diff --git a/doc/standard_library.rdoc b/doc/standard_library.rdoc index 3fafd5932b4d07..d97207b53504a6 100644 --- a/doc/standard_library.rdoc +++ b/doc/standard_library.rdoc @@ -62,7 +62,6 @@ Readline:: Wrapper for Readline extencion and Reline Reline:: GNU Readline and Editline by pure Ruby implementation. Resolv:: Thread-aware DNS resolver library in Ruby RDoc:: Produces HTML and command-line documentation for Ruby -Rinda:: The Linda distributed computing paradigm in Ruby SecureRandom:: Interface for secure random number generator Set:: Provides a class to deal with collections of unordered, unique values Shellwords:: Manipulates strings with word parsing rules of UNIX Bourne shell @@ -130,3 +129,4 @@ BigDecimal:: Provides arbitrary-precision floating point decimal arithmetic Observable:: Provides a mechanism for publish/subscribe pattern in Ruby Abbrev:: Calculates a set of unique abbreviations for a given set of strings resolv-replace.rb:: Replace Socket DNS with Resolv +Rinda:: The Linda distributed computing paradigm in Ruby From fa5094e1835173bf27ca13cf2619522f6d3beb04 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 19 Jan 2024 18:12:56 +0900 Subject: [PATCH 332/640] Stop sync rinda repo --- tool/sync_default_gems.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb index c9eadab0468700..413ec9421dd727 100755 --- a/tool/sync_default_gems.rb +++ b/tool/sync_default_gems.rb @@ -53,7 +53,6 @@ module SyncDefaultGems readline: "ruby/readline", reline: 'ruby/reline', resolv: "ruby/resolv", - rinda: "ruby/rinda", rubygems: 'rubygems/rubygems', securerandom: "ruby/securerandom", set: "ruby/set", From c46d23cde7c6bfc2af762525a767cdf1a099438f Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 19 Jan 2024 19:34:20 +0900 Subject: [PATCH 333/640] Added dependencies rinda and drb --- common.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.mk b/common.mk index bfbdfc6594ee01..cae299cb8b25d5 100644 --- a/common.mk +++ b/common.mk @@ -1563,7 +1563,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 "hoe" "json-schema" "test-unit-rr" + --install-dir .bundle --conservative "hoe" "json-schema" "test-unit-rr" "drb" "ipaddr" "forwardable" "ruby2_keywords" $(ACTIONS_ENDGROUP) PREPARE_BUNDLED_GEMS = test-bundled-gems-prepare From 7b0f6d6d941b5154d9dd3e6a66924614823331a7 Mon Sep 17 00:00:00 2001 From: git Date: Fri, 19 Jan 2024 11:02:59 +0000 Subject: [PATCH 334/640] Update bundled gems list at c46d23cde7c6bfc2af762525a767cd [ci skip] --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index f11a42d8cd7b43..0bc75e0a1615c5 100644 --- a/NEWS.md +++ b/NEWS.md @@ -53,6 +53,7 @@ The following bundled gems are promoted from default gems. * observer 0.1.2 * abbrev 0.1.2 * resolv-replace 0.1.1 +* rinda 0.2.0 See GitHub releases like [GitHub Releases of Logger](https://github.com/ruby/logger/releases) or changelog for details of the default gems or bundled gems. From d29cd972f704b42a25a8de2e5f5380f8aee3144a Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 19 Jan 2024 08:38:37 -0500 Subject: [PATCH 335/640] [ruby/prism] Use inttypes for more accurate printf formatting https://github.com/ruby/prism/commit/2a22b9b72f --- prism/defines.h | 8 ++++ prism/prism.c | 54 ++++++++++++++------------- prism/templates/src/prettyprint.c.erb | 6 ++- 3 files changed, 41 insertions(+), 27 deletions(-) diff --git a/prism/defines.h b/prism/defines.h index c9715c4eb06848..c9af5fa42c6524 100644 --- a/prism/defines.h +++ b/prism/defines.h @@ -16,6 +16,14 @@ #include #include +/** + * We want to be able to use the PRI* macros for printing out integers, but on + * some platforms they aren't included unless this is already defined. + */ +#define __STDC_FORMAT_MACROS + +#include + /** * By default, we compile with -fvisibility=hidden. When this is enabled, we * need to mark certain functions as being publically-visible. This macro does diff --git a/prism/prism.c b/prism/prism.c index 22efbf33773d30..161744e4ba2281 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -996,7 +996,7 @@ static inline void * pm_alloc_node(PRISM_ATTRIBUTE_UNUSED pm_parser_t *parser, size_t size) { void *memory = calloc(1, size); if (memory == NULL) { - fprintf(stderr, "Failed to allocate %zu bytes\n", size); + fprintf(stderr, "Failed to allocate %d bytes\n", (int) size); abort(); } return memory; @@ -17800,13 +17800,13 @@ typedef struct { pm_diagnostic_t *error; /** The start line of the diagnostic message. */ - size_t line; + uint32_t line; /** The column start of the diagnostic message. */ - size_t column_start; + uint32_t column_start; /** The column end of the diagnostic message. */ - size_t column_end; + uint32_t column_end; } pm_error_t; /** The format that will be used to format the errors into the output. */ @@ -17848,8 +17848,8 @@ pm_parser_errors_format_sort(const pm_list_t *error_list, const pm_newline_list_ (index < error_list->size) && (errors[index].error != NULL) && ( - (errors[index].line < start.line) || - (errors[index].line == start.line && errors[index].column_start < start.column) + (errors[index].line < ((uint32_t) start.line)) || + (errors[index].line == ((uint32_t) start.line) && errors[index].column_start < ((uint32_t) start.column)) ) ) index++; @@ -17858,20 +17858,20 @@ pm_parser_errors_format_sort(const pm_list_t *error_list, const pm_newline_list_ memcpy(&errors[index + 1], &errors[index], sizeof(pm_error_t) * (error_list->size - index - 1)); // Finally, we'll insert the error into the array. - size_t column_end; + uint32_t column_end; if (start.line == end.line) { - column_end = end.column; + column_end = (uint32_t) end.column; } else { - column_end = newline_list->offsets[start.line + 1] - newline_list->offsets[start.line] - 1; + column_end = (uint32_t) (newline_list->offsets[start.line + 1] - newline_list->offsets[start.line] - 1); } // Ensure we have at least one column of error. - if (start.column == column_end) column_end++; + if (((uint32_t) start.column) == column_end) column_end++; errors[index] = (pm_error_t) { .error = error, - .line = start.line, - .column_start = start.column, + .line = (uint32_t) start.line, + .column_start = (uint32_t) start.column, .column_end = column_end }; } @@ -17884,14 +17884,18 @@ pm_parser_errors_format_line(const pm_parser_t *parser, const pm_newline_list_t const uint8_t *start = &parser->start[newline_list->offsets[line]]; const uint8_t *end; - if (line + 1 > newline_list->size) { + if (line + 1 >= newline_list->size) { end = parser->end; } else { end = &parser->start[newline_list->offsets[line + 1]]; } - pm_buffer_append_format(buffer, number_prefix, line + 1); + pm_buffer_append_format(buffer, number_prefix, (uint32_t) (line + 1)); pm_buffer_append_string(buffer, (const char *) start, (size_t) (end - start)); + + if (end == parser->end && end[-1] != '\n') { + pm_buffer_append_string(buffer, "\n", 1); + } } /** @@ -17916,13 +17920,13 @@ pm_parser_errors_format(const pm_parser_t *parser, pm_buffer_t *buffer, bool col if (max_line_number < 10) { if (colorize) { error_format = (pm_error_format_t) { - .number_prefix = PM_COLOR_GRAY "%1zu | " PM_COLOR_RESET, + .number_prefix = PM_COLOR_GRAY "%1" PRIu32 " | " PM_COLOR_RESET, .blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET, .divider = PM_COLOR_GRAY " ~~~~~" PM_COLOR_RESET "\n" }; } else { error_format = (pm_error_format_t) { - .number_prefix = "%1zu | ", + .number_prefix = "%1" PRIu32 " | ", .blank_prefix = " | ", .divider = " ~~~~~\n" }; @@ -17930,13 +17934,13 @@ pm_parser_errors_format(const pm_parser_t *parser, pm_buffer_t *buffer, bool col } else if (max_line_number < 100) { if (colorize) { error_format = (pm_error_format_t) { - .number_prefix = PM_COLOR_GRAY "%2zu | " PM_COLOR_RESET, + .number_prefix = PM_COLOR_GRAY "%2" PRIu32 " | " PM_COLOR_RESET, .blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET, .divider = PM_COLOR_GRAY " ~~~~~~" PM_COLOR_RESET "\n" }; } else { error_format = (pm_error_format_t) { - .number_prefix = "%2zu | ", + .number_prefix = "%2" PRIu32 " | ", .blank_prefix = " | ", .divider = " ~~~~~~\n" }; @@ -17944,13 +17948,13 @@ pm_parser_errors_format(const pm_parser_t *parser, pm_buffer_t *buffer, bool col } else if (max_line_number < 1000) { if (colorize) { error_format = (pm_error_format_t) { - .number_prefix = PM_COLOR_GRAY "%3zu | " PM_COLOR_RESET, + .number_prefix = PM_COLOR_GRAY "%3" PRIu32 " | " PM_COLOR_RESET, .blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET, .divider = PM_COLOR_GRAY " ~~~~~~~" PM_COLOR_RESET "\n" }; } else { error_format = (pm_error_format_t) { - .number_prefix = "%3zu | ", + .number_prefix = "%3" PRIu32 " | ", .blank_prefix = " | ", .divider = " ~~~~~~~\n" }; @@ -17958,13 +17962,13 @@ pm_parser_errors_format(const pm_parser_t *parser, pm_buffer_t *buffer, bool col } else if (max_line_number < 10000) { if (colorize) { error_format = (pm_error_format_t) { - .number_prefix = PM_COLOR_GRAY "%4zu | " PM_COLOR_RESET, + .number_prefix = PM_COLOR_GRAY "%4" PRIu32 " | " PM_COLOR_RESET, .blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET, .divider = PM_COLOR_GRAY " ~~~~~~~~" PM_COLOR_RESET "\n" }; } else { error_format = (pm_error_format_t) { - .number_prefix = "%4zu | ", + .number_prefix = "%4" PRIu32 " | ", .blank_prefix = " | ", .divider = " ~~~~~~~~\n" }; @@ -17972,13 +17976,13 @@ pm_parser_errors_format(const pm_parser_t *parser, pm_buffer_t *buffer, bool col } else { if (colorize) { error_format = (pm_error_format_t) { - .number_prefix = PM_COLOR_GRAY "%5zu | " PM_COLOR_RESET, + .number_prefix = PM_COLOR_GRAY "%5" PRIu32 " | " PM_COLOR_RESET, .blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET, .divider = PM_COLOR_GRAY " ~~~~~~~~" PM_COLOR_RESET "\n" }; } else { error_format = (pm_error_format_t) { - .number_prefix = "%5zu | ", + .number_prefix = "%5" PRIu32 " | ", .blank_prefix = " | ", .divider = " ~~~~~~~~\n" }; @@ -17993,7 +17997,7 @@ pm_parser_errors_format(const pm_parser_t *parser, pm_buffer_t *buffer, bool col // the source before the error to give some context. We'll be careful not to // display the same line twice in case the errors are close enough in the // source. - size_t last_line = (size_t) -1; + uint32_t last_line = (uint32_t) -1; const pm_encoding_t *encoding = parser->encoding; for (size_t index = 0; index < error_list->size; index++) { diff --git a/prism/templates/src/prettyprint.c.erb b/prism/templates/src/prettyprint.c.erb index 61831ce59b8446..02b89758b80140 100644 --- a/prism/templates/src/prettyprint.c.erb +++ b/prism/templates/src/prettyprint.c.erb @@ -152,8 +152,10 @@ prettyprint_node(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm prettyprint_source(output_buffer, location->start, (size_t) (location->end - location->start)); pm_buffer_append_string(output_buffer, "\"\n", 2); } - <%- when Prism::UInt8Field, Prism::UInt32Field -%> - pm_buffer_append_format(output_buffer, " %d\n", cast-><%= field.name %>); + <%- when Prism::UInt8Field -%> + pm_buffer_append_format(output_buffer, " %" PRIu8 "\n", cast-><%= field.name %>); + <%- when Prism::UInt32Field -%> + pm_buffer_append_format(output_buffer, " %" PRIu32 "\n", cast-><%= field.name %>); <%- when Prism::FlagsField -%> bool found = false; <%- found = flags.find { |flag| flag.name == field.kind }.tap { |found| raise "Expected to find #{field.kind}" unless found } -%> From d0b774cfb8ddf075c23d1b5ab1fc6f47123ccf65 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Wed, 17 Jan 2024 15:55:08 -0500 Subject: [PATCH 336/640] Remove null checks for xfree xfree can handle null values, so we don't need to check it. --- ext/-test-/memory_view/memory_view.c | 4 ++-- gc.c | 5 ++--- iseq.c | 5 +---- iseq.h | 4 +--- marshal.c | 6 ++---- memory_view.c | 4 +--- regcomp.c | 6 ++---- regparse.c | 7 +++---- thread_pthread.c | 6 ++---- variable.c | 4 +--- vm.c | 4 +--- 11 files changed, 18 insertions(+), 37 deletions(-) diff --git a/ext/-test-/memory_view/memory_view.c b/ext/-test-/memory_view/memory_view.c index c1df0353cfc596..63f0beb81e42aa 100644 --- a/ext/-test-/memory_view/memory_view.c +++ b/ext/-test-/memory_view/memory_view.c @@ -313,8 +313,8 @@ mdview_get_memory_view(VALUE obj, rb_memory_view_t *view, int flags) static bool mdview_release_memory_view(VALUE obj, rb_memory_view_t *view) { - if (view->shape) xfree((void *)view->shape); - if (view->strides) xfree((void *)view->strides); + xfree((void *)view->shape); + xfree((void *)view->strides); return true; } diff --git a/gc.c b/gc.c index 2870b39bcf28a3..0d32b184238db3 100644 --- a/gc.c +++ b/gc.c @@ -3584,7 +3584,7 @@ obj_free(rb_objspace_t *objspace, VALUE obj) if (rb_shape_obj_too_complex(obj)) { st_free_table((st_table *)RCLASS_IVPTR(obj)); } - else if (RCLASS_IVPTR(obj)) { + else { xfree(RCLASS_IVPTR(obj)); } @@ -3679,8 +3679,7 @@ obj_free(rb_objspace_t *objspace, VALUE obj) } #endif onig_region_free(&rm->regs, 0); - if (rm->char_offset) - xfree(rm->char_offset); + xfree(rm->char_offset); RB_DEBUG_COUNTER_INC(obj_match_ptr); } diff --git a/iseq.c b/iseq.c index 36dcf7bf43079d..046a1434c48ba4 100644 --- a/iseq.c +++ b/iseq.c @@ -182,10 +182,7 @@ rb_iseq_free(const rb_iseq_t *iseq) if (LIKELY(body->local_table != rb_iseq_shared_exc_local_tbl)) ruby_xfree((void *)body->local_table); ruby_xfree((void *)body->is_entries); - - if (body->call_data) { - ruby_xfree(body->call_data); - } + ruby_xfree(body->call_data); ruby_xfree((void *)body->catch_table); ruby_xfree((void *)body->param.opt_table); if (ISEQ_MBITS_BUFLEN(body->iseq_size) > 1 && body->mark_bits.list) { diff --git a/iseq.h b/iseq.h index d71f37ca133e89..35780f2862a05b 100644 --- a/iseq.h +++ b/iseq.h @@ -66,9 +66,7 @@ ISEQ_ORIGINAL_ISEQ_CLEAR(const rb_iseq_t *iseq) { void *ptr = ISEQ_BODY(iseq)->variable.original_iseq; ISEQ_BODY(iseq)->variable.original_iseq = NULL; - if (ptr) { - ruby_xfree(ptr); - } + ruby_xfree(ptr); } static inline VALUE * diff --git a/marshal.c b/marshal.c index 1cd71efd54fe31..0c9e93194b8a87 100644 --- a/marshal.c +++ b/marshal.c @@ -2294,10 +2294,8 @@ r_object(struct load_arg *arg) static void clear_load_arg(struct load_arg *arg) { - if (arg->buf) { - xfree(arg->buf); - arg->buf = 0; - } + xfree(arg->buf); + arg->buf = NULL; arg->buflen = 0; arg->offset = 0; arg->readable = 0; diff --git a/memory_view.c b/memory_view.c index 3fb79202f98b36..df7be91e76a656 100644 --- a/memory_view.c +++ b/memory_view.c @@ -845,9 +845,7 @@ rb_memory_view_release(rb_memory_view_t* view) if (rv) { unregister_exported_object(view->obj); view->obj = Qnil; - if (view->item_desc.components) { - xfree((void *)view->item_desc.components); - } + xfree((void *)view->item_desc.components); } return rv; } diff --git a/regcomp.c b/regcomp.c index aaf5dc99918578..13762364aad5c3 100644 --- a/regcomp.c +++ b/regcomp.c @@ -5496,10 +5496,8 @@ clear_optimize_info(regex_t* reg) reg->sub_anchor = 0; reg->exact_end = (UChar* )NULL; reg->threshold_len = 0; - if (IS_NOT_NULL(reg->exact)) { - xfree(reg->exact); - reg->exact = (UChar* )NULL; - } + xfree(reg->exact); + reg->exact = (UChar* )NULL; } #ifdef ONIG_DEBUG diff --git a/regparse.c b/regparse.c index 004e16b6d54a32..33815f24456f7a 100644 --- a/regparse.c +++ b/regparse.c @@ -763,10 +763,9 @@ names_clear(regex_t* reg) e->back_refs = (int* )NULL; } } - if (IS_NOT_NULL(t->e)) { - xfree(t->e); - t->e = NULL; - } + + xfree(t->e); + t->e = NULL; t->num = 0; } return 0; diff --git a/thread_pthread.c b/thread_pthread.c index c90a29a6432e18..1b518721991ec5 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -2327,10 +2327,8 @@ rb_threadptr_sched_free(rb_thread_t *th) // TODO: how to free nt and nt->altstack? } - if (th->sched.context) { - ruby_xfree(th->sched.context); - VM_ASSERT((th->sched.context = NULL) == NULL); - } + ruby_xfree(th->sched.context); + VM_ASSERT((th->sched.context = NULL) == NULL); #else ruby_xfree(th->sched.context_stack); native_thread_destroy(th->nt); diff --git a/variable.c b/variable.c index 7b4beb9f9aefbc..5c92fe5093411d 100644 --- a/variable.c +++ b/variable.c @@ -1459,9 +1459,7 @@ rb_obj_convert_to_too_complex(VALUE obj, st_table *table) RB_VM_LOCK_LEAVE(); } - if (old_ivptr) { - xfree(old_ivptr); - } + xfree(old_ivptr); } void diff --git a/vm.c b/vm.c index 98e280bf28e4b3..e275aa5be4d345 100644 --- a/vm.c +++ b/vm.c @@ -3443,9 +3443,7 @@ thread_free(void *ptr) rb_bug("thread_free: keeping_mutexes must be NULL (%p:%p)", (void *)th, (void *)th->keeping_mutexes); } - if (th->specific_storage) { - ruby_xfree(th->specific_storage); - } + ruby_xfree(th->specific_storage); rb_threadptr_root_fiber_release(th); From 88810f710968ff3148a444633500a4485f4080e8 Mon Sep 17 00:00:00 2001 From: Matthew Healy Date: Mon, 8 Jan 2024 20:55:07 +0100 Subject: [PATCH 337/640] [ruby/prism] Document InstanceVariableReadNode fields https://github.com/ruby/prism/commit/c0747103b0 --- prism/config.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/prism/config.yml b/prism/config.yml index ed331edbe26eca..6f6a2ba8dbf1ca 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -1815,6 +1815,18 @@ nodes: fields: - name: name type: constant + comment: | + The name of the instance variable, including the leading `@`. Variable + names begin with an underscore, alphabetical, or non-ASCII character, + followed by arbitrarily many underscores, alphanumeric or non-ASCII + characters. The exact definitions of "alphabetical" and "alphanumeric" + are encoding-dependent. + + @x # name `:@x` + + @_test # name `:@_test` + + @🌯 # name `:@🌯` comment: | Represents referencing an instance variable. From 9031fd08dc7cd8c305b2e4b19948ddaf2b973ee0 Mon Sep 17 00:00:00 2001 From: Matthew Healy Date: Mon, 8 Jan 2024 21:03:47 +0100 Subject: [PATCH 338/640] [ruby/prism] Document ClassVariableReadNode fields https://github.com/ruby/prism/commit/23ed81dd15 --- prism/config.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/prism/config.yml b/prism/config.yml index 6f6a2ba8dbf1ca..00f7a77e60fb32 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -1037,6 +1037,18 @@ nodes: fields: - name: name type: constant + comment: | + The name of the class variable, including the leading `@@`. Variable + names begin with an underscore, alphabetical, or non-ASCII character, + followed by arbitrarily many underscores, alphanumeric or non-ASCII + characters. The exact definitions of "alphabetical" and "alphanumeric" + are encoding-dependent. + + @@abc # name `:@@abc` + + @@_test # name `:@@_test` + + @@🍔 # name `:@@🍔` comment: | Represents referencing a class variable. From 512be6cee1471c627c4677c44d750884b77e174f Mon Sep 17 00:00:00 2001 From: Matthew Healy Date: Mon, 8 Jan 2024 21:20:56 +0100 Subject: [PATCH 339/640] [ruby/prism] Document GlobalVariableReadNode fields https://github.com/ruby/prism/commit/5d092e6389 --- prism/config.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/prism/config.yml b/prism/config.yml index 00f7a77e60fb32..a4488e6444de10 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -1507,6 +1507,22 @@ nodes: fields: - name: name type: constant + comment: | + The name of the global variable, including the leading `$`. Generally, + global variable names begin with an underscore, hyphen, alphabetical + or non-ASCII character, followed by arbitrarily many underscores, + alphanumeric or non-ASCII characters. The exact definitions of + "alphabetical" and "alphanumeric" are encoding-dependent. + + $foo # name `:$foo` + + $_Test # name `:$_Test` + + $🍟 # name `:$🍟` + + In addition to the above, global variable names may be one of: `$~`, + `$*`, `$$`, `$?`, `$!`, `$@`, `$/`, `$\`, `$;`, `$,`, `$.`, `$=`, + `$:`, `$<`, `$>`, `$"`, or `$0`. comment: | Represents referencing a global variable. From 3fa6dbf304b0c3f456bb14faa63820f5044ffc05 Mon Sep 17 00:00:00 2001 From: Matthew Healy Date: Mon, 8 Jan 2024 21:25:30 +0100 Subject: [PATCH 340/640] [ruby/prism] Document BackReferencedReadNode fields https://github.com/ruby/prism/commit/99a5660623 --- prism/config.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/prism/config.yml b/prism/config.yml index a4488e6444de10..73ee41a6c83663 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -633,6 +633,12 @@ nodes: fields: - name: name type: constant + comment: | + The name of the back-reference variable, including the leading `$`. + + $& # name `:$&` + + $+ # name `:$+` comment: | Represents reading a reference to a field in the previous match. From 1c5e54069f0390c6cb0171d14a822dbc1f362f46 Mon Sep 17 00:00:00 2001 From: Matthew Healy Date: Mon, 8 Jan 2024 21:34:11 +0100 Subject: [PATCH 341/640] [ruby/prism] Document NumberedReferenceReadNode fields https://github.com/ruby/prism/commit/c3148b4519 --- prism/config.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/prism/config.yml b/prism/config.yml index 73ee41a6c83663..f26494f70f83c3 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -2287,6 +2287,16 @@ nodes: fields: - name: number type: uint32 + comment: | + The (1-indexed, from the left) number of the capture group. Numbered + references that would overflow a `uint32` result in a `number` of + exactly `2**32 - 1`. + + $1 # number `1` + + $5432 # number `5432` + + $4294967296 # number `4294967295` comment: | Represents reading a numbered reference to a capture in the previous match. From b7d37e274a58cc3afa06d421627d11e226329cec Mon Sep 17 00:00:00 2001 From: Matthew Healy Date: Mon, 8 Jan 2024 21:51:21 +0100 Subject: [PATCH 342/640] [ruby/prism] Document LocalVariableReadNode fields https://github.com/ruby/prism/commit/5e9afd3729 --- prism/config.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/prism/config.yml b/prism/config.yml index f26494f70f83c3..70de2d94773dbd 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -2085,8 +2085,33 @@ nodes: fields: - name: name type: constant + comment: | + The name of the local variable. Local variable names begin with an + underscore or a lower-case letter, followed by arbitrarily many + underscores, alphanumeric or non-ASCII characters. The exact + definitions of "lower-case", "alphabetical" and "alphanumeric" are + encoding-dependent. + + x # name `:x` + + _Test # name `:_Test` + + 🌯 # name `:🌯` - name: depth type: uint32 + comment: | + The number of visible scopes searched up to find the declaration of + this local variable. + + foo = 1; foo # depth 0 + + bar = 2; tap { bar } # depth 1 + + The specific rules for calculating the depth may differ from + individual Ruby implementations, as they are not specified by the + language. + + For more information, see [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/local_variable_depth.md). comment: | Represents reading a local variable. Note that this requires that a local variable of the same name has already been written to in the same scope, From 57c138c5f4a57890f55a54c7c3f5bb55ee49c909 Mon Sep 17 00:00:00 2001 From: Matthew Healy Date: Mon, 8 Jan 2024 22:07:01 +0100 Subject: [PATCH 343/640] [ruby/prism] Document ConstantReadNode fields https://github.com/ruby/prism/commit/a1623f6451 --- prism/config.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/prism/config.yml b/prism/config.yml index 70de2d94773dbd..9720d1a83b9d3f 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -1225,6 +1225,17 @@ nodes: fields: - name: name type: constant + comment: | + The name of the constant. Constant names begin with an upper-case + letter, followed by arbitrarily many underscores, alphanumeric or + non-ASCII characters. The exact definitions of "upper-case", + and "alphanumeric" are encoding-dependent. + + X # name `:X` + + SOME_CONSTANT # name `:SOME_CONSTANT` + + F🥨 # name `:F🥨` comment: | Represents referencing a constant. From 9c06297cbb3aeef0e2fdcff689885e4ae1677002 Mon Sep 17 00:00:00 2001 From: Matthew Healy Date: Mon, 8 Jan 2024 22:24:28 +0100 Subject: [PATCH 344/640] [ruby/prism] Remove non-ASCII examples from ReadNode fields documentation This is due to a constraint, enforced in `templates/template.rb`, relating to non-UTF-8 locales prohibiting non-ASCII characters in C source files. https://github.com/ruby/prism/commit/74e9a890be --- prism/config.yml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/prism/config.yml b/prism/config.yml index 9720d1a83b9d3f..b349481b17a012 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -1053,8 +1053,6 @@ nodes: @@abc # name `:@@abc` @@_test # name `:@@_test` - - @@🍔 # name `:@@🍔` comment: | Represents referencing a class variable. @@ -1234,8 +1232,6 @@ nodes: X # name `:X` SOME_CONSTANT # name `:SOME_CONSTANT` - - F🥨 # name `:F🥨` comment: | Represents referencing a constant. @@ -1535,8 +1531,6 @@ nodes: $_Test # name `:$_Test` - $🍟 # name `:$🍟` - In addition to the above, global variable names may be one of: `$~`, `$*`, `$$`, `$?`, `$!`, `$@`, `$/`, `$\`, `$;`, `$,`, `$.`, `$=`, `$:`, `$<`, `$>`, `$"`, or `$0`. @@ -1870,8 +1864,6 @@ nodes: @x # name `:@x` @_test # name `:@_test` - - @🌯 # name `:@🌯` comment: | Represents referencing an instance variable. @@ -2106,8 +2098,6 @@ nodes: x # name `:x` _Test # name `:_Test` - - 🌯 # name `:🌯` - name: depth type: uint32 comment: | From a58e091686d9117673487b5b2ab6a793ecc81702 Mon Sep 17 00:00:00 2001 From: Matthew Healy Date: Wed, 17 Jan 2024 21:20:03 +0100 Subject: [PATCH 345/640] [ruby/prism] Extract identifier lexing documentation to separate file https://github.com/ruby/prism/commit/c9df17e3c0 --- lib/prism/prism.gemspec | 1 + prism/config.yml | 48 +++++++++++++++++------------------------ 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/lib/prism/prism.gemspec b/lib/prism/prism.gemspec index a6da1b5318d008..7ea2f8d4e74bde 100644 --- a/lib/prism/prism.gemspec +++ b/lib/prism/prism.gemspec @@ -29,6 +29,7 @@ Gem::Specification.new do |spec| "docs/fuzzing.md", "docs/heredocs.md", "docs/javascript.md", + "docs/lexing.md", "docs/local_variable_depth.md", "docs/mapping.md", "docs/releasing.md", diff --git a/prism/config.yml b/prism/config.yml index b349481b17a012..26f96326f7b0cf 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -1044,11 +1044,10 @@ nodes: - name: name type: constant comment: | - The name of the class variable, including the leading `@@`. Variable - names begin with an underscore, alphabetical, or non-ASCII character, - followed by arbitrarily many underscores, alphanumeric or non-ASCII - characters. The exact definitions of "alphabetical" and "alphanumeric" - are encoding-dependent. + The name of the class variable, including the leading `@@`. + + For more information on permitted class variable names, see + [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/lexing.md). @@abc # name `:@@abc` @@ -1224,10 +1223,10 @@ nodes: - name: name type: constant comment: | - The name of the constant. Constant names begin with an upper-case - letter, followed by arbitrarily many underscores, alphanumeric or - non-ASCII characters. The exact definitions of "upper-case", - and "alphanumeric" are encoding-dependent. + The name of the constant. + + For more information on permitted constant names, see + [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/lexing.md). X # name `:X` @@ -1521,19 +1520,14 @@ nodes: - name: name type: constant comment: | - The name of the global variable, including the leading `$`. Generally, - global variable names begin with an underscore, hyphen, alphabetical - or non-ASCII character, followed by arbitrarily many underscores, - alphanumeric or non-ASCII characters. The exact definitions of - "alphabetical" and "alphanumeric" are encoding-dependent. + The name of the global variable, including the leading `$`. + + For more information on permitted global variable names, see + [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/lexing.md). $foo # name `:$foo` $_Test # name `:$_Test` - - In addition to the above, global variable names may be one of: `$~`, - `$*`, `$$`, `$?`, `$!`, `$@`, `$/`, `$\`, `$;`, `$,`, `$.`, `$=`, - `$:`, `$<`, `$>`, `$"`, or `$0`. comment: | Represents referencing a global variable. @@ -1855,11 +1849,10 @@ nodes: - name: name type: constant comment: | - The name of the instance variable, including the leading `@`. Variable - names begin with an underscore, alphabetical, or non-ASCII character, - followed by arbitrarily many underscores, alphanumeric or non-ASCII - characters. The exact definitions of "alphabetical" and "alphanumeric" - are encoding-dependent. + The name of the instance variable, including the leading `@`. + + For more information on permitted instance variable names, see + [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/lexing.md). @x # name `:@x` @@ -2089,11 +2082,10 @@ nodes: - name: name type: constant comment: | - The name of the local variable. Local variable names begin with an - underscore or a lower-case letter, followed by arbitrarily many - underscores, alphanumeric or non-ASCII characters. The exact - definitions of "lower-case", "alphabetical" and "alphanumeric" are - encoding-dependent. + The name of the local variable. + + For more information on permitted local variable names, see + [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/lexing.md). x # name `:x` From 3c9290173a1421b0624a6d62c0844c778dbc61ad Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Fri, 19 Jan 2024 08:00:46 -0800 Subject: [PATCH 346/640] YJIT: Optimize defined?(yield) (#9599) * YJIT: Optimize defined?(yield) * Remove an irrelevant comment * s/get/gen/ --- bootstraptest/test_yjit.rb | 5 +++ yjit/bindgen/src/main.rs | 1 + yjit/src/codegen.rs | 74 +++++++++++++++++++++------------- yjit/src/cruby_bindings.inc.rs | 19 +++++++++ 4 files changed, 72 insertions(+), 27 deletions(-) diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index a6b0f8f19c82ad..3bf715f8886506 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -4364,3 +4364,8 @@ def entry assert_equal '[0, 1, -4]', %q{ [0 >> 1, 2 >> 1, -7 >> 1] } + +assert_equal '[nil, "yield"]', %q{ + def defined_yield = defined?(yield) + [defined_yield, defined_yield {}] +} diff --git a/yjit/bindgen/src/main.rs b/yjit/bindgen/src/main.rs index 848e9fadc484ba..e249181d515275 100644 --- a/yjit/bindgen/src/main.rs +++ b/yjit/bindgen/src/main.rs @@ -348,6 +348,7 @@ fn main() { .allowlist_function("rb_iseqw_to_iseq") .allowlist_function("rb_iseq_label") .allowlist_function("rb_iseq_line_no") + .allowlist_type("defined_type") // From builtin.h .allowlist_type("rb_builtin_function.*") diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 956bcb1aeb3cf4..b50cd101634f8e 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -2655,31 +2655,41 @@ fn gen_defined( let obj = jit.get_arg(1); let pushval = jit.get_arg(2); - // Save the PC and SP because the callee may allocate - // Note that this modifies REG_SP, which is why we do it first - jit_prepare_routine_call(jit, asm); + match op_type as u32 { + DEFINED_YIELD => { + asm.stack_pop(1); // v operand is not used + let out_opnd = asm.stack_push(Type::Unknown); // nil or "yield" - // Get the operands from the stack - let v_opnd = asm.stack_opnd(0); + gen_block_given(jit, asm, out_opnd, pushval.into(), Qnil.into()); + } + _ => { + // Save the PC and SP because the callee may allocate + // Note that this modifies REG_SP, which is why we do it first + jit_prepare_routine_call(jit, asm); - // Call vm_defined(ec, reg_cfp, op_type, obj, v) - let def_result = asm.ccall(rb_vm_defined as *const u8, vec![EC, CFP, op_type.into(), obj.into(), v_opnd]); - asm.stack_pop(1); // Keep it on stack during ccall for GC + // Get the operands from the stack + let v_opnd = asm.stack_opnd(0); - // if (vm_defined(ec, GET_CFP(), op_type, obj, v)) { - // val = pushval; - // } - asm.test(def_result, Opnd::UImm(255)); - let out_value = asm.csel_nz(pushval.into(), Qnil.into()); + // Call vm_defined(ec, reg_cfp, op_type, obj, v) + let def_result = asm.ccall(rb_vm_defined as *const u8, vec![EC, CFP, op_type.into(), obj.into(), v_opnd]); + asm.stack_pop(1); // Keep it on stack during ccall for GC - // Push the return value onto the stack - let out_type = if pushval.special_const_p() { - Type::UnknownImm - } else { - Type::Unknown - }; - let stack_ret = asm.stack_push(out_type); - asm.mov(stack_ret, out_value); + // if (vm_defined(ec, GET_CFP(), op_type, obj, v)) { + // val = pushval; + // } + asm.test(def_result, Opnd::UImm(255)); + let out_value = asm.csel_nz(pushval.into(), Qnil.into()); + + // Push the return value onto the stack + let out_type = if pushval.special_const_p() { + Type::UnknownImm + } else { + Type::Unknown + }; + let stack_ret = asm.stack_push(out_type); + asm.mov(stack_ret, out_value); + } + } Some(KeepCompiling) } @@ -5265,6 +5275,21 @@ fn jit_rb_f_block_given_p( _argc: i32, _known_recv_class: *const VALUE, ) -> bool { + asm.stack_pop(1); + let out_opnd = asm.stack_push(Type::UnknownImm); + + gen_block_given(jit, asm, out_opnd, Qtrue.into(), Qfalse.into()); + + true +} + +fn gen_block_given( + jit: &mut JITState, + asm: &mut Assembler, + out_opnd: Opnd, + true_opnd: Opnd, + false_opnd: Opnd, +) { asm_comment!(asm, "block_given?"); // Same as rb_vm_frame_block_handler @@ -5273,15 +5298,10 @@ fn jit_rb_f_block_given_p( Opnd::mem(64, ep_opnd, SIZEOF_VALUE_I32 * VM_ENV_DATA_INDEX_SPECVAL) ); - asm.stack_pop(1); - let out_opnd = asm.stack_push(Type::UnknownImm); - // Return `block_handler != VM_BLOCK_HANDLER_NONE` asm.cmp(block_handler, VM_BLOCK_HANDLER_NONE.into()); - let block_given = asm.csel_ne(Qtrue.into(), Qfalse.into()); + let block_given = asm.csel_ne(true_opnd, false_opnd); asm.mov(out_opnd, block_given); - - true } fn jit_thread_s_current( diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs index d71441c0bed462..d67653890c9ea5 100644 --- a/yjit/src/cruby_bindings.inc.rs +++ b/yjit/src/cruby_bindings.inc.rs @@ -874,6 +874,25 @@ pub type ruby_vminsn_type = u32; pub type rb_iseq_callback = ::std::option::Option< unsafe extern "C" fn(arg1: *const rb_iseq_t, arg2: *mut ::std::os::raw::c_void), >; +pub const DEFINED_NOT_DEFINED: defined_type = 0; +pub const DEFINED_NIL: defined_type = 1; +pub const DEFINED_IVAR: defined_type = 2; +pub const DEFINED_LVAR: defined_type = 3; +pub const DEFINED_GVAR: defined_type = 4; +pub const DEFINED_CVAR: defined_type = 5; +pub const DEFINED_CONST: defined_type = 6; +pub const DEFINED_METHOD: defined_type = 7; +pub const DEFINED_YIELD: defined_type = 8; +pub const DEFINED_ZSUPER: defined_type = 9; +pub const DEFINED_SELF: defined_type = 10; +pub const DEFINED_TRUE: defined_type = 11; +pub const DEFINED_FALSE: defined_type = 12; +pub const DEFINED_ASGN: defined_type = 13; +pub const DEFINED_EXPR: defined_type = 14; +pub const DEFINED_REF: defined_type = 15; +pub const DEFINED_FUNC: defined_type = 16; +pub const DEFINED_CONST_FROM: defined_type = 17; +pub type defined_type = u32; pub const ROBJECT_OFFSET_AS_HEAP_IVPTR: robject_offsets = 16; pub const ROBJECT_OFFSET_AS_HEAP_IV_INDEX_TBL: robject_offsets = 24; pub const ROBJECT_OFFSET_AS_ARY: robject_offsets = 16; From da521fc92c19465547f5760870df65731d1a12ca Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 19 Jan 2024 11:12:12 -0500 Subject: [PATCH 347/640] [ruby/prism] Parsing rules document https://github.com/ruby/prism/commit/57a9575543 --- lib/prism/prism.gemspec | 2 +- prism/config.yml | 54 ++++++++++++++++++++--------------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/lib/prism/prism.gemspec b/lib/prism/prism.gemspec index 7ea2f8d4e74bde..f04aa253b69b6c 100644 --- a/lib/prism/prism.gemspec +++ b/lib/prism/prism.gemspec @@ -29,9 +29,9 @@ Gem::Specification.new do |spec| "docs/fuzzing.md", "docs/heredocs.md", "docs/javascript.md", - "docs/lexing.md", "docs/local_variable_depth.md", "docs/mapping.md", + "docs/parsing_rules.md", "docs/releasing.md", "docs/ripper.md", "docs/ruby_api.md", diff --git a/prism/config.yml b/prism/config.yml index 26f96326f7b0cf..96fac677350968 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -1044,10 +1044,8 @@ nodes: - name: name type: constant comment: | - The name of the class variable, including the leading `@@`. - - For more information on permitted class variable names, see - [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/lexing.md). + The name of the class variable, which is a `@@` followed by an + [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). @@abc # name `:@@abc` @@ -1223,10 +1221,7 @@ nodes: - name: name type: constant comment: | - The name of the constant. - - For more information on permitted constant names, see - [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/lexing.md). + The name of the [constant](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#constants). X # name `:X` @@ -1520,10 +1515,10 @@ nodes: - name: name type: constant comment: | - The name of the global variable, including the leading `$`. - - For more information on permitted global variable names, see - [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/lexing.md). + The name of the global variable, which is a `$` followed by an + [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifier). + Alternatively, it can be one of the special global variables designated + by a symbol. $foo # name `:$foo` @@ -1849,10 +1844,8 @@ nodes: - name: name type: constant comment: | - The name of the instance variable, including the leading `@`. - - For more information on permitted instance variable names, see - [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/lexing.md). + The name of the instance variable, which is a `@` followed by an + [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). @x # name `:@x` @@ -2082,19 +2075,29 @@ nodes: - name: name type: constant comment: | - The name of the local variable. - - For more information on permitted local variable names, see - [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/lexing.md). + The name of the local variable, which is an + [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). x # name `:x` _Test # name `:_Test` + + Note that this can also be an underscore followed by a number for the + default block parameters. + + _1 # name `:_1` + + Finally, for the default `it` block parameter, the name is `0it`. This + is to distinguish it from an `it` local variable that is explicitly + declared. + + it # name `:0it` + - name: depth type: uint32 comment: | - The number of visible scopes searched up to find the declaration of - this local variable. + The number of visible scopes that should be searched to find the + origin of this local variable. foo = 1; foo # depth 0 @@ -2102,14 +2105,11 @@ nodes: The specific rules for calculating the depth may differ from individual Ruby implementations, as they are not specified by the - language. - - For more information, see [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/local_variable_depth.md). + language. For more information, see [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/local_variable_depth.md). comment: | Represents reading a local variable. Note that this requires that a local variable of the same name has already been written to in the same scope, - otherwise it is parsed as a method call. Note that `it` default parameter - has `0it` as the name of this node. + otherwise it is parsed as a method call. foo ^^^ From ba4b00d31c773960e80855c4ccdf687a17cb5d02 Mon Sep 17 00:00:00 2001 From: git Date: Fri, 19 Jan 2024 16:12:34 +0000 Subject: [PATCH 348/640] * remove trailing spaces. [ci skip] --- prism/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prism/config.yml b/prism/config.yml index 96fac677350968..c333f908698214 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -2075,7 +2075,7 @@ nodes: - name: name type: constant comment: | - The name of the local variable, which is an + The name of the local variable, which is an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). x # name `:x` @@ -2084,7 +2084,7 @@ nodes: Note that this can also be an underscore followed by a number for the default block parameters. - + _1 # name `:_1` Finally, for the default `it` block parameter, the name is `0it`. This From 5a5cf23d02cf0ecee73796d88526ea23bcac4d92 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Fri, 19 Jan 2024 11:18:47 -0500 Subject: [PATCH 349/640] [PRISM] Fix indentation for PM_SCOPE_NODE [ci skip] --- prism_compile.c | 96 ++++++++++++++++++++++++------------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 250f2afacd9293..4de501ed421cc4 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -6164,21 +6164,21 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n) // ^^^^^^^^^^ case PM_MULTI_TARGET_NODE: { - post_multis_hidden_index = local_index; - local = rb_make_temporary_id(local_index); - local_table_for_iseq->ids[local_index] = local; - break; + post_multis_hidden_index = local_index; + local = rb_make_temporary_id(local_index); + local_table_for_iseq->ids[local_index] = local; + break; } // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n) // ^ case PM_REQUIRED_PARAMETER_NODE: { - pm_required_parameter_node_t * param = (pm_required_parameter_node_t *)post_node; + pm_required_parameter_node_t * param = (pm_required_parameter_node_t *)post_node; - pm_insert_local_index(param->name, local_index, index_lookup_table, local_table_for_iseq, scope_node); - break; + pm_insert_local_index(param->name, local_index, index_lookup_table, local_table_for_iseq, scope_node); + break; } default: { - rb_bug("Unsupported node in posts in parameters %s", pm_node_type_to_str(PM_NODE_TYPE(node))); + rb_bug("Unsupported node in posts in parameters %s", pm_node_type_to_str(PM_NODE_TYPE(node))); } } } @@ -6275,52 +6275,52 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // ^^^^^ case PM_NO_KEYWORDS_PARAMETER_NODE: { - body->param.flags.accepts_no_kwarg = true; - break; + body->param.flags.accepts_no_kwarg = true; + break; } // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n) // ^^^ case PM_KEYWORD_REST_PARAMETER_NODE: { - pm_keyword_rest_parameter_node_t *kw_rest_node = (pm_keyword_rest_parameter_node_t *)parameters_node->keyword_rest; - if (!body->param.flags.has_kw) { - body->param.keyword = keyword = ZALLOC_N(struct rb_iseq_param_keyword, 1); - } + pm_keyword_rest_parameter_node_t *kw_rest_node = (pm_keyword_rest_parameter_node_t *)parameters_node->keyword_rest; + if (!body->param.flags.has_kw) { + body->param.keyword = keyword = ZALLOC_N(struct rb_iseq_param_keyword, 1); + } - keyword->rest_start = local_index; - body->param.flags.has_kwrest = true; + keyword->rest_start = local_index; + body->param.flags.has_kwrest = true; - pm_constant_id_t constant_id = kw_rest_node->name; - if (constant_id) { - pm_insert_local_index(constant_id, local_index, index_lookup_table, local_table_for_iseq, scope_node); - } - else { - local_table_for_iseq->ids[local_index] = idPow; - } - local_index++; - break; + pm_constant_id_t constant_id = kw_rest_node->name; + if (constant_id) { + pm_insert_local_index(constant_id, local_index, index_lookup_table, local_table_for_iseq, scope_node); + } + else { + local_table_for_iseq->ids[local_index] = idPow; + } + local_index++; + break; } // def foo(...) // ^^^ case PM_FORWARDING_PARAMETER_NODE: { - body->param.rest_start = local_index; - body->param.flags.has_rest = true; - ID local = idMULT; - local_table_for_iseq->ids[local_index] = local; - local_index++; - - body->param.block_start = local_index; - body->param.flags.has_block = true; - local = idAnd; - local_table_for_iseq->ids[local_index] = local; - local_index++; - - local = idDot3; - local_table_for_iseq->ids[local_index] = local; - local_index++; - break; + body->param.rest_start = local_index; + body->param.flags.has_rest = true; + ID local = idMULT; + local_table_for_iseq->ids[local_index] = local; + local_index++; + + body->param.block_start = local_index; + body->param.flags.has_block = true; + local = idAnd; + local_table_for_iseq->ids[local_index] = local; + local_index++; + + local = idDot3; + local_table_for_iseq->ids[local_index] = local; + local_index++; + break; } default: { - rb_bug("node type %s not expected as keyword_rest", pm_node_type_to_str(PM_NODE_TYPE(parameters_node->keyword_rest))); + rb_bug("node type %s not expected as keyword_rest", pm_node_type_to_str(PM_NODE_TYPE(parameters_node->keyword_rest))); } } } @@ -6398,16 +6398,16 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, switch (PM_NODE_TYPE(scope_node->ast_node)) { case PM_BLOCK_NODE: { - locals_body_index = ((pm_block_node_t *)scope_node->ast_node)->locals_body_index; - break; + locals_body_index = ((pm_block_node_t *)scope_node->ast_node)->locals_body_index; + break; } case PM_DEF_NODE: { - locals_body_index = ((pm_def_node_t *)scope_node->ast_node)->locals_body_index; - break; + locals_body_index = ((pm_def_node_t *)scope_node->ast_node)->locals_body_index; + break; } case PM_LAMBDA_NODE: { - locals_body_index = ((pm_lambda_node_t *)scope_node->ast_node)->locals_body_index; - break; + locals_body_index = ((pm_lambda_node_t *)scope_node->ast_node)->locals_body_index; + break; } default: { } From 400341aee9aad650b1e75bc840362d1dc8dd108d Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 19 Jan 2024 11:22:40 -0500 Subject: [PATCH 350/640] [PRISM] Sync to latest --- prism/config.yml | 111 ++++++++++++++--------------------------------- 1 file changed, 33 insertions(+), 78 deletions(-) diff --git a/prism/config.yml b/prism/config.yml index c333f908698214..35a3f29ef450bb 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -476,8 +476,7 @@ nodes: - name: left type: node comment: | - Represents the left side of the expression. It can be any kind of node - that represents a non-void expression. + Represents the left side of the expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). left and right ^^^^ @@ -487,8 +486,7 @@ nodes: - name: right type: node comment: | - Represents the right side of the expression. It can be any kind of - node that represents a non-void expression. + Represents the right side of the expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). left && right ^^^^^ @@ -531,8 +529,7 @@ nodes: - name: closing_loc type: location? comment: | - Represents an array literal. This can be a regular array using brackets or - a special array using % like %w or %i. + Represents an array literal. This can be a regular array using brackets or a special array using % like %w or %i. [1, 2, 3] ^^^^^^^^^ @@ -572,8 +569,7 @@ nodes: - name: key type: node comment: | - The key of the association. This can be any node that represents a - non-void expression. + The key of the association. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). { a: b } ^ @@ -586,9 +582,7 @@ nodes: - name: value type: node? comment: | - The value of the association, if present. This can be any node that - represents a non-void expression. It can be optionally omitted if this - node is an element in a `HashPatternNode`. + The value of the association, if present. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). It can be optionally omitted if this node is an element in a `HashPatternNode`. { foo => bar } ^^^ @@ -612,8 +606,7 @@ nodes: - name: value type: node? comment: | - The value to be splatted, if present. Will be missing when keyword - rest argument forwarding is used. + The value to be splatted, if present. Will be missing when keyword rest argument forwarding is used. { **foo } ^^^ @@ -793,9 +786,7 @@ nodes: - name: receiver type: node? comment: | - The object that the method is being called on. This can be either - `nil` or a node representing any kind of expression that returns a - non-void value. + The object that the method is being called on. This can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). foo.bar ^^^ @@ -1044,8 +1035,7 @@ nodes: - name: name type: constant comment: | - The name of the class variable, which is a `@@` followed by an - [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + The name of the class variable, which is a `@@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). @@abc # name `:@@abc` @@ -1236,8 +1226,7 @@ nodes: - name: name type: constant comment: | - Represents writing to a constant in a context that doesn't have an - explicit value. + Represents writing to a constant in a context that doesn't have an explicit value. Foo, Bar = baz ^^^ ^^^ @@ -1515,10 +1504,7 @@ nodes: - name: name type: constant comment: | - The name of the global variable, which is a `$` followed by an - [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifier). - Alternatively, it can be one of the special global variables designated - by a symbol. + The name of the global variable, which is a `$` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifier). Alternatively, it can be one of the special global variables designated by a symbol. $foo # name `:$foo` @@ -1641,8 +1627,7 @@ nodes: - name: value type: node comment: | - Represents a node that is implicitly being added to the tree but doesn't - correspond directly to a node in the source. + Represents a node that is implicitly being added to the tree but doesn't correspond directly to a node in the source. { foo: } ^^^^ @@ -1844,8 +1829,7 @@ nodes: - name: name type: constant comment: | - The name of the instance variable, which is a `@` followed by an - [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + The name of the instance variable, which is a `@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). @x # name `:@x` @@ -1902,9 +1886,7 @@ nodes: type: location newline: parts comment: | - Represents a regular expression literal that contains interpolation that - is being used in the predicate of a conditional to implicitly match - against the last line read by an IO object. + Represents a regular expression literal that contains interpolation that is being used in the predicate of a conditional to implicitly match against the last line read by an IO object. if /foo #{bar} baz/ then end ^^^^^^^^^^^^^^^^ @@ -2075,41 +2057,32 @@ nodes: - name: name type: constant comment: | - The name of the local variable, which is an - [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). + The name of the local variable, which is an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers). x # name `:x` _Test # name `:_Test` - Note that this can also be an underscore followed by a number for the - default block parameters. + Note that this can also be an underscore followed by a number for the default block parameters. _1 # name `:_1` - Finally, for the default `it` block parameter, the name is `0it`. This - is to distinguish it from an `it` local variable that is explicitly - declared. + Finally, for the default `it` block parameter, the name is `0it`. This is to distinguish it from an `it` local variable that is explicitly declared. it # name `:0it` - name: depth type: uint32 comment: | - The number of visible scopes that should be searched to find the - origin of this local variable. + The number of visible scopes that should be searched to find the origin of this local variable. foo = 1; foo # depth 0 bar = 2; tap { bar } # depth 1 - The specific rules for calculating the depth may differ from - individual Ruby implementations, as they are not specified by the - language. For more information, see [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/local_variable_depth.md). + The specific rules for calculating the depth may differ from individual Ruby implementations, as they are not specified by the language. For more information, see [the Prism documentation](https://github.com/ruby/prism/blob/main/docs/local_variable_depth.md). comment: | - Represents reading a local variable. Note that this requires that a local - variable of the same name has already been written to in the same scope, - otherwise it is parsed as a method call. + Represents reading a local variable. Note that this requires that a local variable of the same name has already been written to in the same scope, otherwise it is parsed as a method call. foo ^^^ @@ -2155,9 +2128,7 @@ nodes: - name: unescaped type: string comment: | - Represents a regular expression literal used in the predicate of a - conditional to implicitly match against the last line read by an IO - object. + Represents a regular expression literal used in the predicate of a conditional to implicitly match against the last line read by an IO object. if /foo/i then end ^^^^^^ @@ -2195,15 +2166,13 @@ nodes: - name: targets type: node[] comment: | - Represents writing local variables using a regular expression match with - named capture groups. + Represents writing local variables using a regular expression match with named capture groups. /(?bar)/ =~ baz ^^^^^^^^^^^^^^^^^^^^ - name: MissingNode comment: | - Represents a node that is missing from the source and results in a syntax - error. + Represents a node that is missing from the source and results in a syntax error. - name: ModuleNode fields: - name: locals @@ -2296,8 +2265,7 @@ nodes: - name: maximum type: uint8 comment: | - Represents an implicit set of parameters through the use of numbered - parameters within a block or lambda. + Represents an implicit set of parameters through the use of numbered parameters within a block or lambda. -> { _1 + _2 } ^^^^^^^^^^^^^^ @@ -2306,9 +2274,7 @@ nodes: - name: number type: uint32 comment: | - The (1-indexed, from the left) number of the capture group. Numbered - references that would overflow a `uint32` result in a `number` of - exactly `2**32 - 1`. + The (1-indexed, from the left) number of the capture group. Numbered references that would overflow a `uint32` result in a `number` of exactly `2**32 - 1`. $1 # number `1` @@ -2361,8 +2327,7 @@ nodes: - name: left type: node comment: | - Represents the left side of the expression. It can be any kind of node - that represents a non-void expression. + Represents the left side of the expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). left or right ^^^^ @@ -2372,8 +2337,7 @@ nodes: - name: right type: node comment: | - Represents the right side of the expression. It can be any kind of - node that represents a non-void expression. + Represents the right side of the expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). left || right ^^^^^ @@ -2440,8 +2404,7 @@ nodes: - name: rparen_loc type: location comment: | - Represents the use of the `^` operator for pinning an expression in a - pattern matching expression. + Represents the use of the `^` operator for pinning an expression in a pattern matching expression. foo in ^(bar) ^^^^^^ @@ -2452,8 +2415,7 @@ nodes: - name: operator_loc type: location comment: | - Represents the use of the `^` operator for pinning a variable in a pattern - matching expression. + Represents the use of the `^` operator for pinning a variable in a pattern matching expression. foo in ^bar ^^^^ @@ -2505,9 +2467,7 @@ nodes: - name: left type: node? comment: | - The left-hand side of the range, if present. Can be either `nil` or - a node representing any kind of expression that returns a non-void - value. + The left-hand side of the range, if present. It can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). 1... ^ @@ -2517,17 +2477,14 @@ nodes: - name: right type: node? comment: | - The right-hand side of the range, if present. Can be either `nil` or - a node representing any kind of expression that returns a non-void - value. + The right-hand side of the range, if present. It can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). ..5 ^ 1...foo ^^^ - If neither right-hand or left-hand side was included, this will be a - MissingNode. + If neither right-hand or left-hand side was included, this will be a MissingNode. - name: operator_loc type: location comment: | @@ -2640,8 +2597,7 @@ nodes: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ end - `Foo, *splat, Bar` are in the `exceptions` field. - `ex` is in the `exception` field. + `Foo, *splat, Bar` are in the `exceptions` field. `ex` is in the `exception` field. - name: RestParameterNode fields: - name: flags @@ -2757,8 +2713,7 @@ nodes: - name: unescaped type: string comment: | - Represents a string literal, a string contained within a `%w` list, or - plain string content within an interpolated string. + Represents a string literal, a string contained within a `%w` list, or plain string content within an interpolated string. "foo" ^^^^^ From 200d3cc14d4c98bfee3826bda9c0e09a1113d939 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 18 Jan 2024 12:35:52 -0800 Subject: [PATCH 351/640] add assert on SP --- compile.c | 1 + 1 file changed, 1 insertion(+) diff --git a/compile.c b/compile.c index 5c69c860e0f131..8d3588c81bec5b 100644 --- a/compile.c +++ b/compile.c @@ -2855,6 +2855,7 @@ iseq_set_exception_table(rb_iseq_t *iseq) if (entry->type == CATCH_TYPE_RESCUE || entry->type == CATCH_TYPE_BREAK || entry->type == CATCH_TYPE_NEXT) { + RUBY_ASSERT(entry->sp > 0); entry->sp--; } } From efe4b8ac0f5de49dcb20806f5a6c2d90273e8d52 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 18 Jan 2024 15:11:17 -0800 Subject: [PATCH 352/640] Fix ensure code when running break in a while loop We need to run ensure code when breaking from a while loop Co-authored-by: John Hawthorn Co-authored-by: Kevin Newton --- prism_compile.c | 24 +++++++++++++++--------- test/ruby/test_compile_prism.rb | 14 ++++++++++++++ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 4de501ed421cc4..cc2a71ce1078d3 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -3289,6 +3289,16 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, LABEL *estart = NEW_LABEL(lineno); LABEL *eend = NEW_LABEL(lineno); LABEL *econt = NEW_LABEL(lineno); + + struct ensure_range er; + struct iseq_compile_data_ensure_node_stack enl; + struct ensure_range *erange; + + er.begin = estart; + er.end = eend; + er.next = 0; + push_ensure_entry(iseq, &enl, &er, (void *)begin_node->ensure_clause); + ADD_LABEL(ret, estart); if (!begin_node->rescue_clause) { if (begin_node->statements) { @@ -3311,15 +3321,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, PM_POP_UNLESS_POPPED; } - struct ensure_range er; - struct iseq_compile_data_ensure_node_stack enl; - struct ensure_range *erange; - - er.begin = estart; - er.end = eend; - er.next = 0; - push_ensure_entry(iseq, &enl, &er, (void *)begin_node->ensure_clause); - pm_scope_node_t next_scope_node; pm_scope_node_init((pm_node_t *)begin_node->ensure_clause, &next_scope_node, scope_node, parser); child_iseq = NEW_CHILD_ISEQ(&next_scope_node, @@ -3336,6 +3337,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, erange = erange->next; } } + ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = enl.prev; } if (!begin_node->rescue_clause && !begin_node->ensure_clause) { @@ -3369,6 +3371,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, else { PM_PUTNIL; } + + pm_add_ensure_iseq(ret, iseq, 0, src, scope_node); ADD_INSNL(ret, &dummy_line_node, jump, ISEQ_COMPILE_DATA(iseq)->end_label); ADD_ADJUST_RESTORE(ret, splabel); @@ -4213,8 +4217,10 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, LABEL *end = NEW_LABEL(lineno); ADD_LABEL(ret, start); if (ensure_node->statements) { + LABEL *prev_end_label = ISEQ_COMPILE_DATA(iseq)->end_label; ISEQ_COMPILE_DATA(iseq)->end_label = end; PM_COMPILE((pm_node_t *)ensure_node->statements); + ISEQ_COMPILE_DATA(iseq)->end_label = prev_end_label; } ADD_LABEL(ret, end); return; diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 0765a946a571ca..e1bd5cfb69d6ca 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -961,6 +961,20 @@ def test_BreakNode assert_prism_eval("[true].map { break }") end + def test_break_runs_ensure + assert_prism_eval(<<-CODE) +a = [] +while true + begin + break + ensure + a << 1 + end +end +a + CODE + end + def test_EnsureNode assert_prism_eval("begin; 1; ensure; 2; end") assert_prism_eval("begin; 1; begin; 3; ensure; 4; end; ensure; 2; end") From 740f0b52e051d6fd022bf4b9eeab078c841b49a2 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Fri, 19 Jan 2024 11:26:28 -0500 Subject: [PATCH 353/640] [PRISM] Fix typo with pm_scope_node_destroy We need to run the pm_scope_node_destroy after compiling the iseq. --- prism_compile.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index cc2a71ce1078d3..186b6742a300b9 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -6571,9 +6571,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // We create another ScopeNode from the statements within the PostExecutionNode pm_scope_node_t next_scope_node; pm_scope_node_init((pm_node_t *)post_execution_node->statements, &next_scope_node, scope_node, parser); - pm_scope_node_destroy(&next_scope_node); - const rb_iseq_t *block = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(body->parent_iseq), ISEQ_TYPE_BLOCK, lineno); + pm_scope_node_destroy(&next_scope_node); ADD_CALL_WITH_BLOCK(ret, &dummy_line_node, id_core_set_postexe, INT2FIX(0), block); break; From e0f7cee8c54691127277d32b4560e44b8394cdc7 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Fri, 19 Jan 2024 11:51:35 -0800 Subject: [PATCH 354/640] YJIT: Avoid doubly splitting Opnd::Value on CSel (#9617) YJIT: Avoid doubly splitting Opnd::Value --- yjit/src/backend/x86_64/mod.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/yjit/src/backend/x86_64/mod.rs b/yjit/src/backend/x86_64/mod.rs index 25c92642d3d5ce..1569af93cb5959 100644 --- a/yjit/src/backend/x86_64/mod.rs +++ b/yjit/src/backend/x86_64/mod.rs @@ -271,7 +271,11 @@ impl Assembler *truthy = asm.load(*truthy); } }, - Opnd::UImm(_) | Opnd::Imm(_) | Opnd::Value(_) => { + Opnd::UImm(_) | Opnd::Imm(_) => { + *truthy = asm.load(*truthy); + }, + // Opnd::Value could have already been split + Opnd::Value(_) if !matches!(truthy, Opnd::InsnOut { .. }) => { *truthy = asm.load(*truthy); }, _ => {} @@ -1270,4 +1274,22 @@ mod tests { 0xe: mov qword ptr [rbx], rax "}); } + + #[test] + fn test_csel_split() { + let (mut asm, mut cb) = setup_asm(); + + let stack_top = Opnd::mem(64, SP, 0); + let elem_opnd = asm.csel_ne(VALUE(0x7f22c88d1930).into(), Qnil.into()); + asm.mov(stack_top, elem_opnd); + + asm.compile_with_num_regs(&mut cb, 3); + + assert_disasm!(cb, "48b830198dc8227f0000b904000000480f44c1488903", {" + 0x0: movabs rax, 0x7f22c88d1930 + 0xa: mov ecx, 4 + 0xf: cmove rax, rcx + 0x13: mov qword ptr [rbx], rax + "}); + } } From 4778b0eedaf4b490fe6b1fe2df9b58c1fe8e7639 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 19 Jan 2024 12:00:35 -0800 Subject: [PATCH 355/640] Fix kwarg ordering Required keyword arguments need to come first. Fixes: https://github.com/ruby/prism/issues/2158 Co-authored-by: Kevin Newton --- prism_compile.c | 46 +++++++++++++++++++-------------- test/ruby/test_compile_prism.rb | 4 +++ 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 186b6742a300b9..7109e0fcb738b9 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -6203,14 +6203,31 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, ID *ids = xcalloc(keywords_list->size, sizeof(ID)); - for (size_t i = 0; i < keywords_list->size; i++, local_index++) { + size_t kw_index = 0; + + for (size_t i = 0; i < keywords_list->size; i++) { pm_node_t *keyword_parameter_node = keywords_list->nodes[i]; pm_constant_id_t name; - switch (PM_NODE_TYPE(keyword_parameter_node)) { - // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n) - // ^^^^ - case PM_OPTIONAL_KEYWORD_PARAMETER_NODE: { + // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n) + // ^^ + if (PM_NODE_TYPE_P(keyword_parameter_node, PM_REQUIRED_KEYWORD_PARAMETER_NODE)) { + name = ((pm_required_keyword_parameter_node_t *)keyword_parameter_node)->name; + keyword->required_num++; + ID local = pm_constant_id_lookup(scope_node, name); + pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node); + local_index++; + ids[kw_index++] = local; + } + } + + for (size_t i = 0; i < keywords_list->size; i++) { + pm_node_t *keyword_parameter_node = keywords_list->nodes[i]; + pm_constant_id_t name; + + // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n) + // ^^^^ + if (PM_NODE_TYPE_P(keyword_parameter_node, PM_OPTIONAL_KEYWORD_PARAMETER_NODE)) { pm_optional_keyword_parameter_node_t *cast = ((pm_optional_keyword_parameter_node_t *)keyword_parameter_node); pm_node_t *value = cast->value; @@ -6227,23 +6244,12 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, rb_ary_push(default_values, complex_mark); } - break; - } - // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n) - // ^^ - case PM_REQUIRED_KEYWORD_PARAMETER_NODE: { - name = ((pm_required_keyword_parameter_node_t *)keyword_parameter_node)->name; - keyword->required_num++; - break; - } - default: { - rb_bug("Unexpected keyword parameter node type %s", pm_node_type_to_str(PM_NODE_TYPE(keyword_parameter_node))); - } + ID local = pm_constant_id_lookup(scope_node, name); + pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node); + ids[kw_index++] = local; + local_index++; } - ID local = pm_constant_id_lookup(scope_node, name); - pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node); - ids[i] = local; } keyword->bits_start = local_index; diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index e1bd5cfb69d6ca..b675e23351c005 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1464,6 +1464,10 @@ def self.prism_test_def_node(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, CODE end + def test_required_kwarg_ordering + assert_prism_eval("def self.foo(a: 1, b:); [a, b]; end; foo(b: 2)") + end + def test_trailing_keyword_method_params # foo(1, b: 2, c: 3) # argc -> 3 assert_prism_eval("def self.foo(a, b:, c:); [a, b, c]; end; foo(1, b: 2, c: 3)") From ed50161bd6dd27da21bd18c37b1a52d47c82a997 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Fri, 19 Jan 2024 14:55:52 -0500 Subject: [PATCH 356/640] [PRISM] Fix ensure code running twice Fixes: ruby/prism#2212 --- prism_compile.c | 12 +++++++----- test/ruby/test_compile_prism.rb | 12 ++++++++++++ tool/prism_btests | 2 +- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 7109e0fcb738b9..c0324133ee0df1 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -3315,11 +3315,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, if (!popped) { PM_NOP; } - pm_statements_node_t *statements = begin_node->ensure_clause->statements; - if (statements) { - PM_COMPILE((pm_node_t *)statements); - PM_POP_UNLESS_POPPED; - } pm_scope_node_t next_scope_node; pm_scope_node_init((pm_node_t *)begin_node->ensure_clause, &next_scope_node, scope_node, parser); @@ -3338,6 +3333,13 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } } ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = enl.prev; + + // Compile the ensure entry + pm_statements_node_t *statements = begin_node->ensure_clause->statements; + if (statements) { + PM_COMPILE((pm_node_t *)statements); + PM_POP_UNLESS_POPPED; + } } if (!begin_node->rescue_clause && !begin_node->ensure_clause) { diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index b675e23351c005..917d16381e2101 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -961,6 +961,18 @@ def test_BreakNode assert_prism_eval("[true].map { break }") end + def test_ensure_in_methods + assert_prism_eval(<<-CODE) +def self.m + a = [] +ensure + a << 5 + return a +end +m + CODE + end + def test_break_runs_ensure assert_prism_eval(<<-CODE) a = [] diff --git a/tool/prism_btests b/tool/prism_btests index 1c96438545df1c..9770a8342b303d 100644 --- a/tool/prism_btests +++ b/tool/prism_btests @@ -26,7 +26,7 @@ ../src/bootstraptest/test_yjit_30k_ifelse.rb ../src/bootstraptest/test_yjit_30k_methods.rb # ../src/bootstraptest/test_exception.rb -# ../src/bootstraptest/test_flow.rb +../src/bootstraptest/test_flow.rb # ../src/bootstraptest/test_insns.rb # ../src/bootstraptest/test_method.rb # ../src/bootstraptest/test_ractor.rb From cfabe9c51cfa11f4020de119aa2bc707db15cf89 Mon Sep 17 00:00:00 2001 From: Adam Hess Date: Thu, 18 Jan 2024 15:18:14 -0800 Subject: [PATCH 357/640] [ruby/prism] Handle stovetop start in constant path fullname https://github.com/ruby/prism/commit/3a216e63fe --- lib/prism/node_ext.rb | 2 +- test/prism/constant_path_node_test.rb | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb index 974052e84bfc76..e39579f534524c 100644 --- a/lib/prism/node_ext.rb +++ b/lib/prism/node_ext.rb @@ -118,7 +118,7 @@ def full_name_parts current = current.parent end - unless current.is_a?(ConstantReadNode) + unless current.is_a?(ConstantReadNode) || current == nil raise DynamicPartsInConstantPathError, "Constant path contains dynamic parts. Cannot compute full name" end diff --git a/test/prism/constant_path_node_test.rb b/test/prism/constant_path_node_test.rb index 9842be0c497523..aeab6e01e9487b 100644 --- a/test/prism/constant_path_node_test.rb +++ b/test/prism/constant_path_node_test.rb @@ -52,5 +52,16 @@ def test_full_name_for_constant_path_target node = Prism.parse(source).value.statements.body.first assert_equal("Foo::Bar::Baz::Qux", node.lefts.first.full_name) end + + def test_full_name_for_constant_path_with_stovetop_start + source = <<~RUBY + ::Foo:: # comment + Bar::Baz:: + Qux, Something = [1, 2] + RUBY + + node = Prism.parse(source).value.statements.body.first + assert_equal("::Foo::Bar::Baz::Qux", node.lefts.first.full_name) + end end end From ac4046d34b4e0850e9ff7573b795284fea6c2741 Mon Sep 17 00:00:00 2001 From: Adam Hess Date: Fri, 19 Jan 2024 12:41:23 -0800 Subject: [PATCH 358/640] [ruby/prism] switch unless to if https://github.com/ruby/prism/commit/29bdbf4212 Co-authored-by: Kevin Newton --- lib/prism/node_ext.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb index e39579f534524c..1a78759e2ccfa9 100644 --- a/lib/prism/node_ext.rb +++ b/lib/prism/node_ext.rb @@ -118,7 +118,7 @@ def full_name_parts current = current.parent end - unless current.is_a?(ConstantReadNode) || current == nil + if !current.is_a?(ConstantReadNode) && !current.nil? raise DynamicPartsInConstantPathError, "Constant path contains dynamic parts. Cannot compute full name" end From 99d6e2f1eeeea66b22b9bd68a4aaa2fdb881036b Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 12 Jan 2024 15:23:47 -0500 Subject: [PATCH 359/640] [PRISM] Revisit target nodes --- prism_compile.c | 1000 +++++++++++++++++++++++++++------------------ tool/prism_btests | 4 +- 2 files changed, 615 insertions(+), 389 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index c0324133ee0df1..ddb1a0c54cedcb 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -1229,118 +1229,6 @@ pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinf return orig_argc; } -/** - * A callinfo struct basically mirrors the information that is going to be - * passed to a callinfo object that will be used on a send instruction. We use - * it to communicate the information between the function that derives it and - * the function that uses it. - */ -typedef struct { - int argc; - int flags; - struct rb_callinfo_kwarg *kwargs; -} pm_callinfo_t; - -/** - * Derive the callinfo from the given arguments node. It assumes the pointer to - * the callinfo struct is zeroed memory. - */ -static void -pm_arguments_node_callinfo(pm_callinfo_t *callinfo, const pm_arguments_node_t *node, const pm_scope_node_t *scope_node, const pm_parser_t *parser) -{ - if (node == NULL) { - if (callinfo->flags & VM_CALL_FCALL) { - callinfo->flags |= VM_CALL_VCALL; - } - } else { - const pm_node_list_t *arguments = &node->arguments; - bool has_splat = false; - - for (size_t argument_index = 0; argument_index < arguments->size; argument_index++) { - const pm_node_t *argument = arguments->nodes[argument_index]; - - switch (PM_NODE_TYPE(argument)) { - case PM_KEYWORD_HASH_NODE: { - pm_keyword_hash_node_t *keyword_hash = (pm_keyword_hash_node_t *) argument; - size_t elements_size = keyword_hash->elements.size; - - if (PM_NODE_FLAG_P(node, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT)) { - for (size_t element_index = 0; element_index < elements_size; element_index++) { - const pm_node_t *element = keyword_hash->elements.nodes[element_index]; - - switch (PM_NODE_TYPE(element)) { - case PM_ASSOC_NODE: - callinfo->argc++; - break; - case PM_ASSOC_SPLAT_NODE: - if (elements_size > 1) callinfo->flags |= VM_CALL_KW_SPLAT_MUT; - callinfo->flags |= VM_CALL_KW_SPLAT; - break; - default: - rb_bug("Unknown type in keyword argument %s\n", pm_node_type_to_str(PM_NODE_TYPE(element))); - } - } - break; - } else if (PM_NODE_FLAG_P(keyword_hash, PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS)) { - // We need to first figure out if all elements of the - // KeywordHashNode are AssocNode nodes with symbol keys. If - // they are all symbol keys then we can pass them as keyword - // arguments. - callinfo->flags |= VM_CALL_KWARG; - - callinfo->kwargs = rb_xmalloc_mul_add(elements_size, sizeof(VALUE), sizeof(struct rb_callinfo_kwarg)); - callinfo->kwargs->references = 0; - callinfo->kwargs->keyword_len = (int) elements_size; - - VALUE *keywords = callinfo->kwargs->keywords; - for (size_t element_index = 0; element_index < elements_size; element_index++) { - pm_assoc_node_t *assoc = (pm_assoc_node_t *) keyword_hash->elements.nodes[element_index]; - keywords[element_index] = pm_static_literal_value(assoc->key, scope_node, parser); - } - } else { - // If they aren't all symbol keys then we need to construct - // a new hash and pass that as an argument. - callinfo->argc++; - callinfo->flags |= VM_CALL_KW_SPLAT; - - if (elements_size > 1) { - // A new hash will be created for the keyword arguments - // in this case, so mark the method as passing mutable - // keyword splat. - callinfo->flags |= VM_CALL_KW_SPLAT_MUT; - } - } - break; - } - case PM_SPLAT_NODE: { - // Splat nodes add a splat flag and can change the way the - // arguments are loaded by combining them into a single array. - callinfo->flags |= VM_CALL_ARGS_SPLAT; - if (((pm_splat_node_t *) argument)->expression != NULL) callinfo->argc++; - has_splat = true; - break; - } - case PM_FORWARDING_ARGUMENTS_NODE: { - // Forwarding arguments indicate that a splat and a block are - // present, and increase the argument count by one. - callinfo->flags |= VM_CALL_ARGS_BLOCKARG | VM_CALL_ARGS_SPLAT; - callinfo->argc++; - break; - } - default: { - // A regular argument increases the argument count by one. If - // there is a splat and this is the last argument, then the - // argument count becomes 1 because it gets grouped into a - // single array. - callinfo->argc++; - if (has_splat && (argument_index == arguments->size - 1)) callinfo->argc = 1; - break; - } - } - } - } -} - static void pm_compile_index_and_or_write_node(bool and_node, pm_node_t *receiver, pm_node_t *value, pm_arguments_node_t *arguments, pm_node_t *block, LINK_ANCHOR *const ret, rb_iseq_t *iseq, int lineno, const uint8_t * src, bool popped, pm_scope_node_t *scope_node, pm_parser_t *parser) { @@ -1400,78 +1288,6 @@ pm_compile_index_and_or_write_node(bool and_node, pm_node_t *receiver, pm_node_t return; } -/** - * In order to properly compile multiple-assignment, some preprocessing needs to - * be performed in the case of call or constant path targets. This is when they - * are read, the "parent" of each of these nodes should only be read once (the - * receiver in the case of a call, the parent constant in the case of a constant - * path). - */ -static uint8_t -pm_compile_multi_write_lhs(rb_iseq_t *iseq, NODE dummy_line_node, const uint8_t *src, bool popped, const pm_node_t *node, LINK_ANCHOR *const ret, pm_scope_node_t *scope_node, uint8_t pushed, bool nested) -{ - switch (PM_NODE_TYPE(node)) { - case PM_INDEX_TARGET_NODE: { - pm_index_target_node_t *cast = (pm_index_target_node_t *)node; - PM_COMPILE_NOT_POPPED((pm_node_t *)cast->receiver); - pushed++; - - if (cast->arguments) { - for (size_t i = 0; i < cast->arguments->arguments.size; i++) { - PM_COMPILE_NOT_POPPED((pm_node_t *)cast->arguments->arguments.nodes[i]); - } - pushed += cast->arguments->arguments.size; - } - break; - } - case PM_CALL_TARGET_NODE: { - pm_call_target_node_t *cast = (pm_call_target_node_t *)node; - PM_COMPILE_NOT_POPPED((pm_node_t *)cast->receiver); - pushed++; - break; - } - case PM_MULTI_TARGET_NODE: { - pm_multi_target_node_t *cast = (pm_multi_target_node_t *) node; - for (size_t index = 0; index < cast->lefts.size; index++) { - pushed = pm_compile_multi_write_lhs(iseq, dummy_line_node, src, popped, cast->lefts.nodes[index], ret, scope_node, pushed, false); - } - break; - } - case PM_CONSTANT_PATH_TARGET_NODE: { - pm_constant_path_target_node_t *cast = (pm_constant_path_target_node_t *)node; - if (cast->parent) { - PM_PUTNIL; - pushed = pm_compile_multi_write_lhs(iseq, dummy_line_node, src, popped, cast->parent, ret, scope_node, pushed, false); - } else { - ADD_INSN1(ret, &dummy_line_node, putobject, rb_cObject); - } - break; - } - case PM_CONSTANT_PATH_NODE: { - pm_constant_path_node_t *cast = (pm_constant_path_node_t *) node; - if (cast->parent) { - pushed = pm_compile_multi_write_lhs(iseq, dummy_line_node, src, popped, cast->parent, ret, scope_node, pushed, false); - } else { - PM_POP; - ADD_INSN1(ret, &dummy_line_node, putobject, rb_cObject); - } - pushed = pm_compile_multi_write_lhs(iseq, dummy_line_node, src, popped, cast->child, ret, scope_node, pushed, cast->parent); - break; - } - case PM_CONSTANT_READ_NODE: { - pm_constant_read_node_t *cast = (pm_constant_read_node_t *) node; - ADD_INSN1(ret, &dummy_line_node, putobject, RBOOL(!nested)); - ADD_INSN1(ret, &dummy_line_node, getconstant, ID2SYM(pm_constant_id_lookup(scope_node, cast->name))); - pushed = pushed + 2; - break; - } - default: - break; - } - - return pushed; -} - // When we compile a pattern matching expression, we use the stack as a scratch // space to store lots of different values (consider it like we have a pattern // matching function and we need space for a bunch of different local @@ -2179,7 +1995,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t // of a pattern. For example, foo in bar. This results in the value // being matched being written to that local variable. pm_local_variable_target_node_t *cast = (pm_local_variable_target_node_t *) node; - pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, cast->name, 0); + pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, cast->name, cast->depth); // If this local variable is being written from within an alternation // pattern, then it cannot actually be added to the local table since @@ -3007,6 +2823,516 @@ pm_compile_multi_assign_params(pm_multi_target_node_t *multi, st_table *index_lo return local_index; } +typedef struct pm_multi_target_state_node { + // The pointer to the topn instruction that will need to be modified after + // we know the total stack size of all of the targets. + INSN *topn; + + // The index of the stack from the base of the entire multi target at which + // the parent expression is located. + size_t stack_index; + + // The number of slots in the stack that this node occupies. + size_t stack_size; + + // The position of the node in the list of targets. + size_t position; + + // A pointer to the next node in this linked list. + struct pm_multi_target_state_node *next; +} pm_multi_target_state_node_t; + +typedef struct { + // The total number of slots in the stack that this multi target occupies. + size_t stack_size; + + // The position of the current node being compiled. This is forwarded to + // nodes when they are allocated. + size_t position; + + // A pointer to the head of this linked list. + pm_multi_target_state_node_t *head; + + // A pointer to the tail of this linked list. + pm_multi_target_state_node_t *tail; +} pm_multi_target_state_t; + +/** + * Push a new state node onto the multi target state. + */ +static void +pm_multi_target_state_push(pm_multi_target_state_t *state, INSN *topn, size_t stack_size) { + pm_multi_target_state_node_t *node = ALLOC(pm_multi_target_state_node_t); + node->topn = topn; + node->stack_index = state->stack_size + 1; + node->stack_size = stack_size; + node->position = state->position; + node->next = NULL; + + if (state->head == NULL) { + state->head = node; + state->tail = node; + } else { + state->tail->next = node; + state->tail = node; + } + + state->stack_size += stack_size; +} + +/** + * Walk through a multi target state's linked list and update the topn + * instructions that were inserted into the write sequence to make sure they can + * correctly retrieve their parent expressions. + */ +static void +pm_multi_target_state_update(pm_multi_target_state_t *state) { + // If nothing was ever pushed onto the stack, then we don't need to do any + // kind of updates. + if (state->stack_size == 0) return; + + pm_multi_target_state_node_t *current = state->head; + pm_multi_target_state_node_t *previous; + + while (current != NULL) { + VALUE offset = INT2FIX(state->stack_size - current->stack_index + current->position); + current->topn->operands[0] = offset; + + // stack_size will be > 1 in the case that we compiled an index target + // and it had arguments. In this case, we use multiple topn instructions + // to grab up all of the arguments as well, so those offsets need to be + // updated as well. + if (current->stack_size > 1) { + INSN *insn = current->topn; + + for (size_t index = 1; index < current->stack_size; index += 1) { + LINK_ELEMENT *element = get_next_insn(insn); + RUBY_ASSERT(IS_INSN(element)); + + insn = (INSN *) element; + RUBY_ASSERT(insn->insn_id == BIN(topn)); + + insn->operands[0] = offset; + } + } + + previous = current; + current = current->next; + + free(previous); + } +} + +static size_t +pm_compile_multi_target_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const parents, LINK_ANCHOR *const writes, LINK_ANCHOR *const cleanup, const uint8_t *src, pm_scope_node_t *scope_node, pm_multi_target_state_t *state); + +/** + * A target node represents an indirect write to a variable or a method call to + * a method ending in =. Compiling one of these nodes requires three sequences: + * + * * The first is to compile retrieving the parent expression if there is one. + * This could be the object that owns a constant or the receiver of a method + * call. + * * The second is to compile the writes to the targets. This could be writing + * to variables, or it could be performing method calls. + * * The third is to compile any cleanup that needs to happen, i.e., popping the + * appropriate number of values off the stack. + * + * When there is a parent expression and this target is part of a multi write, a + * topn instruction will be inserted into the write sequence. This is to move + * the parent expression to the top of the stack so that it can be used as the + * receiver of the method call or the owner of the constant. To facilitate this, + * we return a pointer to the topn instruction that was used to be later + * modified with the correct offset. + * + * These nodes can appear in a couple of places, but most commonly: + * + * * For loops - the index variable is a target node + * * Rescue clauses - the exception reference variable is a target node + * * Multi writes - the left hand side contains a list of target nodes + * + * For the comments with examples within this function, we'll use for loops as + * the containing node. + */ +static void +pm_compile_target_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const parents, LINK_ANCHOR *const writes, LINK_ANCHOR *const cleanup, const uint8_t *src, pm_scope_node_t *scope_node, pm_multi_target_state_t *state) { + int lineno = (int) pm_newline_list_line_column(&scope_node->parser->newline_list, node->location.start).line; + NODE dummy_line_node = generate_dummy_line_node(lineno, lineno); + + switch (PM_NODE_TYPE(node)) { + case PM_LOCAL_VARIABLE_TARGET_NODE: { + // Local variable targets have no parent expression, so they only need + // to compile the write. + // + // for i in []; end + // + pm_local_variable_target_node_t *cast = (pm_local_variable_target_node_t *) node; + pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, cast->name, 0); + + ADD_SETLOCAL(writes, &dummy_line_node, index.index, index.level); + break; + } + case PM_CLASS_VARIABLE_TARGET_NODE: { + // Class variable targets have no parent expression, so they only need + // to compile the write. + // + // for @@i in []; end + // + pm_class_variable_target_node_t *cast = (pm_class_variable_target_node_t *) node; + ID name = pm_constant_id_lookup(scope_node, cast->name); + + ADD_INSN2(writes, &dummy_line_node, setclassvariable, ID2SYM(name), get_cvar_ic_value(iseq, name)); + break; + } + case PM_CONSTANT_TARGET_NODE: { + // Constant targets have no parent expression, so they only need to + // compile the write. + // + // for I in []; end + // + pm_constant_target_node_t *cast = (pm_constant_target_node_t *) node; + ID name = pm_constant_id_lookup(scope_node, cast->name); + + ADD_INSN1(writes, &dummy_line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE)); + ADD_INSN1(writes, &dummy_line_node, setconstant, ID2SYM(name)); + break; + } + case PM_GLOBAL_VARIABLE_TARGET_NODE: { + // Global variable targets have no parent expression, so they only need + // to compile the write. + // + // for $i in []; end + // + pm_global_variable_target_node_t *cast = (pm_global_variable_target_node_t *) node; + ID name = pm_constant_id_lookup(scope_node, cast->name); + + ADD_INSN1(writes, &dummy_line_node, setglobal, ID2SYM(name)); + break; + } + case PM_INSTANCE_VARIABLE_TARGET_NODE: { + // Instance variable targets have no parent expression, so they only + // need to compile the write. + // + // for @i in []; end + // + pm_instance_variable_target_node_t *cast = (pm_instance_variable_target_node_t *) node; + ID name = pm_constant_id_lookup(scope_node, cast->name); + + ADD_INSN2(writes, &dummy_line_node, setinstancevariable, ID2SYM(name), get_ivar_ic_value(iseq, name)); + break; + } + case PM_CONSTANT_PATH_TARGET_NODE: { + // Constant path targets have a parent expression that is the object + // that owns the constant. This needs to be compiled first into the + // parents sequence. If no parent is found, then it represents using the + // unary :: operator to indicate a top-level constant. In that case we + // need to push Object onto the stack. + // + // for I::J in []; end + // + const pm_constant_path_target_node_t *cast = (const pm_constant_path_target_node_t *) node; + ID name = pm_constant_id_lookup(scope_node, ((const pm_constant_read_node_t *) cast->child)->name); + + if (cast->parent != NULL) { + pm_compile_node(iseq, cast->parent, parents, src, false, scope_node); + } else { + ADD_INSN1(parents, &dummy_line_node, putobject, rb_cObject); + } + + if (state == NULL) { + ADD_INSN(writes, &dummy_line_node, swap); + } else { + ADD_INSN1(writes, &dummy_line_node, topn, INT2FIX(1)); + pm_multi_target_state_push(state, (INSN *) LAST_ELEMENT(writes), 1); + } + + ADD_INSN1(writes, &dummy_line_node, setconstant, ID2SYM(name)); + + if (state != NULL) { + ADD_INSN(cleanup, &dummy_line_node, pop); + } + + break; + } + case PM_CALL_TARGET_NODE: { + // Call targets have a parent expression that is the receiver of the + // method being called. This needs to be compiled first into the parents + // sequence. These nodes cannot have arguments, so the method call is + // compiled with a single argument which represents the value being + // written. + // + // for i.j in []; end + // + const pm_call_target_node_t *cast = (const pm_call_target_node_t *) node; + ID method_id = pm_constant_id_lookup(scope_node, cast->name); + + pm_compile_node(iseq, cast->receiver, parents, src, false, scope_node); + + if (state != NULL) { + ADD_INSN1(writes, &dummy_line_node, topn, INT2FIX(1)); + pm_multi_target_state_push(state, (INSN *) LAST_ELEMENT(writes), 1); + ADD_INSN(writes, &dummy_line_node, swap); + } + + ADD_SEND(writes, &dummy_line_node, method_id, INT2NUM(1)); + ADD_INSN(writes, &dummy_line_node, pop); + + if (state != NULL) { + ADD_INSN(cleanup, &dummy_line_node, pop); + } + + break; + } + case PM_INDEX_TARGET_NODE: { + // Index targets have a parent expression that is the receiver of the + // method being called and any additional arguments that are being + // passed along with the value being written. The receiver and arguments + // both need to be on the stack. Note that this is even more complicated + // by the fact that these nodes can hold a block using the unary & + // operator. + // + // for i[:j] in []; end + // + const pm_index_target_node_t *cast = (const pm_index_target_node_t *) node; + + pm_compile_node(iseq, cast->receiver, parents, src, false, scope_node); + + int flags = 0; + struct rb_callinfo_kwarg *kwargs = NULL; + int argc = pm_setup_args(cast->arguments, &flags, &kwargs, iseq, parents, src, false, scope_node, dummy_line_node, scope_node->parser); + + if (cast->block != NULL) { + flags |= VM_CALL_ARGS_BLOCKARG; + if (cast->block != NULL) pm_compile_node(iseq, cast->block, writes, src, false, scope_node); + } + + if (state != NULL) { + ADD_INSN1(writes, &dummy_line_node, topn, INT2FIX(argc + 1)); + pm_multi_target_state_push(state, (INSN *) LAST_ELEMENT(writes), argc + 1); + + if (argc == 0) { + ADD_INSN(writes, &dummy_line_node, swap); + } else { + for (int index = 0; index < argc; index++) { + ADD_INSN1(writes, &dummy_line_node, topn, INT2FIX(argc + 1)); + } + ADD_INSN1(writes, &dummy_line_node, topn, INT2FIX(argc + 1)); + } + } + + ADD_SEND_R(writes, &dummy_line_node, idASET, INT2NUM(argc + 1), NULL, INT2FIX(flags), kwargs); + ADD_INSN(writes, &dummy_line_node, pop); + + if (state != NULL) { + if (argc != 0) { + ADD_INSN(writes, &dummy_line_node, pop); + } + + for (int index = 0; index < argc + 1; index++) { + ADD_INSN(cleanup, &dummy_line_node, pop); + } + } + + break; + } + case PM_MULTI_TARGET_NODE: { + // Multi target nodes represent a set of writes to multiple variables. + // The parent expressions are the combined set of the parent expressions + // of its inner target nodes. + // + // for i, j in []; end + // + pm_compile_multi_target_node(iseq, node, parents, writes, cleanup, src, scope_node, state); + break; + } + default: + rb_bug("Unexpected node type: %s", pm_node_type_to_str(PM_NODE_TYPE(node))); + break; + } +} + +/** + * Compile a multi target or multi write node. It returns the number of values + * on the stack that correspond to the parent expressions of the various + * targets. + */ +static size_t +pm_compile_multi_target_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const parents, LINK_ANCHOR *const writes, LINK_ANCHOR *const cleanup, const uint8_t *src, pm_scope_node_t *scope_node, pm_multi_target_state_t *state) { + int lineno = (int) pm_newline_list_line_column(&scope_node->parser->newline_list, node->location.start).line; + NODE dummy_line_node = generate_dummy_line_node(lineno, lineno); + + const pm_node_list_t *lefts; + const pm_node_t *rest; + const pm_node_list_t *rights; + + switch (PM_NODE_TYPE(node)) { + case PM_MULTI_TARGET_NODE: { + pm_multi_target_node_t *cast = (pm_multi_target_node_t *) node; + lefts = &cast->lefts; + rest = cast->rest; + rights = &cast->rights; + break; + } + case PM_MULTI_WRITE_NODE: { + pm_multi_write_node_t *cast = (pm_multi_write_node_t *) node; + lefts = &cast->lefts; + rest = cast->rest; + rights = &cast->rights; + break; + } + default: + rb_bug("Unsupported node %s", pm_node_type_to_str(PM_NODE_TYPE(node))); + break; + } + + bool has_rest = (rest != NULL) && PM_NODE_TYPE_P(rest, PM_SPLAT_NODE) && ((pm_splat_node_t *) rest)->expression != NULL; + bool has_posts = rights->size > 0; + + // The first instruction in the writes sequence is going to spread the + // top value of the stack onto the number of values that we're going to + // write. + ADD_INSN2(writes, &dummy_line_node, expandarray, INT2FIX(lefts->size), INT2FIX((has_rest || has_posts) ? 1 : 0)); + + // We need to keep track of some additional state information as we're + // going through the targets because we will need to revisit them once + // we know how many values are being pushed onto the stack. + pm_multi_target_state_t target_state = { 0 }; + size_t base_position = state == NULL ? 0 : state->position; + size_t splat_position = has_rest ? 1 : 0; + + // Next, we'll iterate through all of the leading targets. + for (size_t index = 0; index < lefts->size; index++) { + const pm_node_t *target = lefts->nodes[index]; + target_state.position = lefts->size - index + splat_position + base_position; + pm_compile_target_node(iseq, target, parents, writes, cleanup, src, scope_node, &target_state); + } + + // Next, we'll compile the rest target if there is one. + if (has_rest) { + const pm_node_t *target = ((pm_splat_node_t *) rest)->expression; + target_state.position = 1 + rights->size + base_position; + + if (has_posts) { + ADD_INSN2(writes, &dummy_line_node, expandarray, INT2FIX(rights->size), INT2FIX(3)); + } + + pm_compile_target_node(iseq, target, parents, writes, cleanup, src, scope_node, &target_state); + } + + // Finally, we'll compile the trailing targets. + if (has_posts) { + if (!has_rest && rest != NULL) { + ADD_INSN2(writes, &dummy_line_node, expandarray, INT2FIX(rights->size), INT2FIX(2)); + } + + for (size_t index = 0; index < rights->size; index++) { + const pm_node_t *target = rights->nodes[index]; + target_state.position = rights->size - index + base_position; + pm_compile_target_node(iseq, target, parents, writes, cleanup, src, scope_node, &target_state); + } + } + + // Now, we need to go back and modify the topn instructions in order to + // ensure they can correctly retrieve the parent expressions. + pm_multi_target_state_update(&target_state); + return target_state.stack_size; +} + +/** + * When compiling a for loop, we need to write the iteration variable to + * whatever expression exists in the index slot. This function performs that + * compilation. + */ +static void +pm_compile_for_node_index(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, const uint8_t *src, pm_scope_node_t *scope_node) { + int lineno = (int) pm_newline_list_line_column(&scope_node->parser->newline_list, node->location.start).line; + NODE dummy_line_node = generate_dummy_line_node(lineno, lineno); + + switch (PM_NODE_TYPE(node)) { + case PM_LOCAL_VARIABLE_TARGET_NODE: { + // For local variables, all we have to do is retrieve the value and then + // compile the index node. + ADD_GETLOCAL(ret, &dummy_line_node, 1, 0); + pm_compile_target_node(iseq, node, ret, ret, ret, src, scope_node, NULL); + break; + } + case PM_CLASS_VARIABLE_TARGET_NODE: + case PM_CONSTANT_TARGET_NODE: + case PM_GLOBAL_VARIABLE_TARGET_NODE: + case PM_INSTANCE_VARIABLE_TARGET_NODE: + case PM_CONSTANT_PATH_TARGET_NODE: + case PM_CALL_TARGET_NODE: + case PM_INDEX_TARGET_NODE: { + // For other targets, we need to potentially compile the parent or + // owning expression of this target, then retrieve the value, expand it, + // and then compile the necessary writes. + DECL_ANCHOR(writes); + INIT_ANCHOR(writes); + + DECL_ANCHOR(cleanup); + INIT_ANCHOR(cleanup); + + pm_multi_target_state_t state = { 0 }; + state.position = 1; + pm_compile_target_node(iseq, node, ret, writes, cleanup, src, scope_node, &state); + + ADD_GETLOCAL(ret, &dummy_line_node, 1, 0); + ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(1), INT2FIX(0)); + + ADD_SEQ(ret, writes); + ADD_SEQ(ret, cleanup); + + pm_multi_target_state_update(&state); + break; + } + case PM_MULTI_TARGET_NODE: { + DECL_ANCHOR(writes); + INIT_ANCHOR(writes); + + DECL_ANCHOR(cleanup); + INIT_ANCHOR(cleanup); + + pm_compile_target_node(iseq, node, ret, writes, cleanup, src, scope_node, NULL); + + LABEL *not_single = NEW_LABEL(lineno); + LABEL *not_ary = NEW_LABEL(lineno); + + // When there are multiple targets, we'll do a bunch of work to convert + // the value into an array before we expand it. Effectively we're trying + // to accomplish: + // + // (args.length == 1 && Array.try_convert(args[0])) || args + // + ADD_GETLOCAL(ret, &dummy_line_node, 1, 0); + ADD_INSN(ret, &dummy_line_node, dup); + ADD_CALL(ret, &dummy_line_node, idLength, INT2FIX(0)); + ADD_INSN1(ret, &dummy_line_node, putobject, INT2FIX(1)); + ADD_CALL(ret, &dummy_line_node, idEq, INT2FIX(1)); + ADD_INSNL(ret, &dummy_line_node, branchunless, not_single); + ADD_INSN(ret, &dummy_line_node, dup); + ADD_INSN1(ret, &dummy_line_node, putobject, INT2FIX(0)); + ADD_CALL(ret, &dummy_line_node, idAREF, INT2FIX(1)); + ADD_INSN1(ret, &dummy_line_node, putobject, rb_cArray); + ADD_INSN(ret, &dummy_line_node, swap); + ADD_CALL(ret, &dummy_line_node, rb_intern("try_convert"), INT2FIX(1)); + ADD_INSN(ret, &dummy_line_node, dup); + ADD_INSNL(ret, &dummy_line_node, branchunless, not_ary); + ADD_INSN(ret, &dummy_line_node, swap); + + ADD_LABEL(ret, not_ary); + ADD_INSN(ret, &dummy_line_node, pop); + + ADD_LABEL(ret, not_single); + ADD_SEQ(ret, writes); + ADD_SEQ(ret, cleanup); + break; + } + default: + rb_bug("Unexpected node type for index in for node: %s", pm_node_type_to_str(PM_NODE_TYPE(node))); + break; + } +} + /* * Compiles a prism node into instruction sequences * @@ -4261,35 +4587,59 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, return; } case PM_FOR_NODE: { - pm_for_node_t *for_node = (pm_for_node_t *)node; - - ISEQ_COMPILE_DATA(iseq)->catch_except_p = true; - - const rb_iseq_t *child_iseq; - const rb_iseq_t *prevblock = ISEQ_COMPILE_DATA(iseq)->current_block; + pm_for_node_t *cast = (pm_for_node_t *) node; LABEL *retry_label = NEW_LABEL(lineno); LABEL *retry_end_l = NEW_LABEL(lineno); - pm_constant_id_list_t locals; - pm_constant_id_list_init(&locals); - + // First, compile the collection that we're going to be iterating over. ADD_LABEL(ret, retry_label); + PM_COMPILE_NOT_POPPED(cast->collection); - PM_COMPILE_NOT_POPPED(for_node->collection); - + // Next, create the new scope that is going to contain the block that + // will be passed to the each method. pm_scope_node_t next_scope_node; - pm_scope_node_init((pm_node_t *)for_node, &next_scope_node, scope_node, parser); - child_iseq = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, lineno); + pm_scope_node_init((pm_node_t *) cast, &next_scope_node, scope_node, parser); + + const rb_iseq_t *child_iseq = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, lineno); pm_scope_node_destroy(&next_scope_node); + const rb_iseq_t *prev_block = ISEQ_COMPILE_DATA(iseq)->current_block; ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq; + + // Now, create the method call to each that will be used to iterate over + // the collection, and pass the newly created iseq as the block. ADD_SEND_WITH_BLOCK(ret, &dummy_line_node, idEach, INT2FIX(0), child_iseq); - ADD_LABEL(ret, retry_end_l); - PM_POP_IF_POPPED; + // 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); - ISEQ_COMPILE_DATA(iseq)->current_block = prevblock; + // 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; + } + } + + PM_POP_IF_POPPED; + ISEQ_COMPILE_DATA(iseq)->current_block = prev_block; ADD_CATCH_ENTRY(CATCH_TYPE_BREAK, retry_label, retry_end_l, child_iseq, retry_end_l); return; } @@ -5283,116 +5633,34 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, return; } case PM_MULTI_WRITE_NODE: { - pm_multi_write_node_t *multi_write_node = (pm_multi_write_node_t *)node; - pm_node_list_t *lefts = &multi_write_node->lefts; - pm_node_list_t *rights = &multi_write_node->rights; - bool has_rest_expression = (multi_write_node->rest && - PM_NODE_TYPE_P(multi_write_node->rest, PM_SPLAT_NODE)); - size_t argc = 1; - - // pre-process the left hand side of multi-assignments. - uint8_t pushed = 0; - for (size_t index = 0; index < lefts->size; index++) { - pushed = pm_compile_multi_write_lhs(iseq, dummy_line_node, src, popped, lefts->nodes[index], ret, scope_node, pushed, false); - } - - PM_COMPILE_NOT_POPPED(multi_write_node->value); - PM_DUP_UNLESS_POPPED; - - pm_node_t *rest_expression = NULL; - if (multi_write_node->rest && PM_NODE_TYPE_P(multi_write_node->rest, PM_SPLAT_NODE)) { - pm_splat_node_t *rest_splat = ((pm_splat_node_t *)multi_write_node->rest); - rest_expression = rest_splat->expression; - } - - size_t remainder = pushed; - if (popped) remainder--; - - if (lefts->size) { - ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(lefts->size), INT2FIX((int) (bool) (rights->size || rest_expression))); - for (size_t index = 0; index < lefts->size; index++) { - pm_node_t *considered_node = lefts->nodes[index]; - - if (PM_NODE_TYPE_P(considered_node, PM_CONSTANT_PATH_TARGET_NODE) && pushed > 0) { - pm_constant_path_target_node_t *cast = (pm_constant_path_target_node_t *) considered_node; - ID name = pm_constant_id_lookup(scope_node, ((pm_constant_read_node_t * ) cast->child)->name); - - pushed -= 2; + // A multi write node represents writing to multiple values using an = + // operator. Importantly these nodes are only parsed when the left-hand + // side of the operator has multiple targets. The right-hand side of the + // operator having multiple targets represents an implicit array + // instead. + const pm_multi_write_node_t *cast = (const pm_multi_write_node_t *) node; - ADD_INSN1(ret, &dummy_line_node, topn, INT2FIX(pushed)); - ADD_INSN1(ret, &dummy_line_node, setconstant, ID2SYM(name)); - } else if (PM_NODE_TYPE_P(considered_node, PM_INDEX_TARGET_NODE)) { - pm_index_target_node_t *cast = (pm_index_target_node_t *)considered_node; + DECL_ANCHOR(writes); + INIT_ANCHOR(writes); - if (cast->arguments) { - pm_arguments_node_t *args = (pm_arguments_node_t *)cast->arguments; - argc = args->arguments.size + 1; - } - - if (argc == 1) { - ADD_INSN(ret, &dummy_line_node, swap); - } - else { - VALUE vals = INT2FIX(remainder + (lefts->size - index)); - ADD_INSN1(ret, &dummy_line_node, topn, vals); - for (size_t i = 1; i < argc; i++) { - ADD_INSN1(ret, &dummy_line_node, topn, vals); - } - ADD_INSN1(ret, &dummy_line_node, topn, INT2FIX(argc)); - } - - ADD_SEND(ret, &dummy_line_node, idASET, INT2FIX(argc)); - PM_POP; - PM_POP; - remainder -= argc; + DECL_ANCHOR(cleanup); + INIT_ANCHOR(cleanup); - } else if (PM_NODE_TYPE_P(considered_node, PM_CALL_TARGET_NODE)) { - pm_call_target_node_t *cast = (pm_call_target_node_t *)considered_node; + pm_multi_target_state_t state = { 0 }; + state.position = popped ? 0 : 1; + size_t stack_size = pm_compile_multi_target_node(iseq, node, ret, writes, cleanup, src, scope_node, &state); - VALUE vals = INT2FIX(remainder + (lefts->size - index)); - ADD_INSN1(ret, &dummy_line_node, topn, vals); - ADD_INSN(ret, &dummy_line_node, swap); + PM_COMPILE_NOT_POPPED(cast->value); + PM_DUP_UNLESS_POPPED; - ID method_id = pm_constant_id_lookup(scope_node, cast->name); - ADD_SEND(ret, &dummy_line_node, method_id, INT2FIX(argc)); - PM_POP; - remainder -= argc; - } else { - PM_COMPILE(lefts->nodes[index]); - } - } + ADD_SEQ(ret, writes); + if (!popped && stack_size >= 1) { + // Make sure the value on the right-hand side of the = operator is + // being returned before we pop the parent expressions. + ADD_INSN1(ret, &dummy_line_node, setn, INT2FIX(stack_size)); } - if ((pushed)) { - if (!popped) { - ADD_INSN1(ret, &dummy_line_node, setn, INT2FIX(pushed)); - } - for (uint8_t index = 0; index < (pushed); index++) { - PM_POP; - } - } - - if (rights->size) { - if (rest_expression) { - ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(rights->size), INT2FIX(3)); - PM_COMPILE(rest_expression); - } - else { - ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(rights->size), INT2FIX(2)); - } - - for (size_t index = 0; index < rights->size; index++) { - PM_COMPILE(rights->nodes[index]); - } - } - else if (has_rest_expression) { - if (rest_expression) { - ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(0), INT2FIX(1)); - PM_COMPILE(rest_expression); - } else if (!lefts->size && !PM_NODE_TYPE_P(multi_write_node->value, PM_SPLAT_NODE)){ - ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(0), INT2FIX(0)); - } - } + ADD_SEQ(ret, cleanup); return; } @@ -5750,56 +6018,17 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // into the instruction sequence. This can look quite different // depending on the kind of write being performed. if (cast->reference) { - switch (PM_NODE_TYPE(cast->reference)) { - case PM_CALL_TARGET_NODE: { - // begin; rescue => Foo.bar; end - const pm_call_target_node_t *reference = (const pm_call_target_node_t *) cast->reference; - ID method_id = pm_constant_id_lookup(scope_node, reference->name); + DECL_ANCHOR(writes); + INIT_ANCHOR(writes); - PM_COMPILE((pm_node_t *) reference); - ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0); + DECL_ANCHOR(cleanup); + INIT_ANCHOR(cleanup); - ADD_SEND(ret, &dummy_line_node, method_id, INT2NUM(1)); - ADD_INSN(ret, &dummy_line_node, pop); - break; - } - case PM_CONSTANT_PATH_TARGET_NODE: { - // begin; rescue => Foo::Bar; end - const pm_constant_path_target_node_t *reference = (const pm_constant_path_target_node_t *) cast->reference; - const pm_constant_read_node_t *constant = (const pm_constant_read_node_t *) reference->child; - - PM_COMPILE((pm_node_t *) reference); - ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0); - - ADD_INSN(ret, &dummy_line_node, swap); - ADD_INSN1(ret, &dummy_line_node, setconstant, ID2SYM(pm_constant_id_lookup(scope_node, constant->name))); - break; - } - case PM_INDEX_TARGET_NODE: { - // begin; rescue => foo[:bar]; end - const pm_index_target_node_t *reference = (const pm_index_target_node_t *) cast->reference; - - pm_callinfo_t callinfo = { 0 }; - pm_arguments_node_callinfo(&callinfo, reference->arguments, scope_node, parser); - - PM_COMPILE((pm_node_t *) reference); - ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0); - - if (reference->block != NULL) { - callinfo.flags |= VM_CALL_ARGS_BLOCKARG; - PM_COMPILE_NOT_POPPED((pm_node_t *) reference->block); - } + pm_compile_target_node(iseq, cast->reference, ret, writes, cleanup, src, scope_node, NULL); + ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0); - ADD_SEND_R(ret, &dummy_line_node, idASET, INT2FIX(callinfo.argc + 1), NULL, INT2FIX(callinfo.flags), callinfo.kwargs); - ADD_INSN(ret, &dummy_line_node, pop); - break; - } - default: - // Indirectly writing to a variable or constant. - ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0); - PM_COMPILE((pm_node_t *) cast->reference); - break; - } + ADD_SEQ(ret, writes); + ADD_SEQ(ret, cleanup); } // If we have statements to execute, we'll compile them here. Otherwise @@ -5986,10 +6215,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, int table_size = (int) locals_size; - if (PM_NODE_TYPE_P(scope_node->ast_node, PM_FOR_NODE)) { - body->param.lead_num = 1; - table_size++; - } + // For nodes have a hidden iteration variable. We add that to the local + // table size here. + if (PM_NODE_TYPE_P(scope_node->ast_node, PM_FOR_NODE)) table_size++; if (keywords_list && keywords_list->size) { table_size++; @@ -6390,6 +6618,13 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // Set any anonymous locals for the for node if (PM_NODE_TYPE_P(scope_node->ast_node, PM_FOR_NODE)) { + if (PM_NODE_TYPE_P(((const pm_for_node_t *) scope_node->ast_node)->index, PM_LOCAL_VARIABLE_TARGET_NODE)) { + body->param.lead_num++; + } else { + body->param.rest_start = local_index; + body->param.flags.has_rest = true; + } + ID local = rb_make_temporary_id(local_index); local_table_for_iseq->ids[local_index] = local; local_index++; @@ -6558,18 +6793,24 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, 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); + NODE dummy_line_node = generate_dummy_line_node(body->location.first_lineno, -1); 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(body->location.first_lineno, -1); - if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0) { - PM_NOP; + // For nodes automatically assign the iteration variable to whatever + // index variable. We need to handle that write here because it has + // to happen in the context of the block. Note that this happens + // before the B_CALL tracepoint event. + if (PM_NODE_TYPE_P(scope_node->ast_node, PM_FOR_NODE)) { + pm_compile_for_node_index(iseq, ((const pm_for_node_t *) scope_node->ast_node)->index, ret, src, scope_node); } + + ADD_TRACE(ret, RUBY_EVENT_B_CALL); + PM_NOP; ADD_LABEL(ret, start); - if (scope_node->body) { + if (scope_node->body != NULL) { switch (PM_NODE_TYPE(scope_node->ast_node)) { case PM_POST_EXECUTION_NODE: { pm_post_execution_node_t *post_execution_node = (pm_post_execution_node_t *)scope_node->ast_node; @@ -6585,20 +6826,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, ADD_CALL_WITH_BLOCK(ret, &dummy_line_node, id_core_set_postexe, INT2FIX(0), block); break; } - case PM_FOR_NODE: { - pm_for_node_t *for_node = (pm_for_node_t *)scope_node->ast_node; - LABEL *target = NEW_LABEL(lineno); - LABEL *old_start = ISEQ_COMPILE_DATA(iseq)->start_label; - - ADD_GETLOCAL(ret, &dummy_line_node, 1, 0); - PM_COMPILE(for_node->index); - PM_NOP; - ADD_LABEL(ret, target); - ISEQ_COMPILE_DATA(iseq)->start_label = target; - pm_compile_node(iseq, (pm_node_t *)(scope_node->body), ret, src, popped, scope_node); - ISEQ_COMPILE_DATA(iseq)->start_label = old_start; - break; - } case PM_INTERPOLATED_REGULAR_EXPRESSION_NODE: { pm_interpolated_regular_expression_node_t *cast = (pm_interpolated_regular_expression_node_t *) scope_node->ast_node; @@ -6612,12 +6839,11 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, ADD_INSN2(ret, &dummy_line_node, toregexp, INT2FIX(pm_reg_flags((pm_node_t *)cast)), INT2FIX(parts_size)); break; } - default: { - pm_compile_node(iseq, (pm_node_t *)(scope_node->body), ret, src, popped, scope_node); - } + default: + pm_compile_node(iseq, scope_node->body, ret, src, popped, scope_node); + break; } - } - else { + } else { PM_PUTNIL; } @@ -6629,8 +6855,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, ADD_CATCH_ENTRY(CATCH_TYPE_REDO, start, end, NULL, start); ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, start, end, NULL, end); break; - } - case ISEQ_TYPE_ENSURE: { + } + case ISEQ_TYPE_ENSURE: { iseq_set_exception_local_table(iseq); if (scope_node->body) { @@ -6640,8 +6866,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, ADD_GETLOCAL(ret, &dummy_line_node, 1, 0); ADD_INSN1(ret, &dummy_line_node, throw, INT2FIX(0)); return; - } - case ISEQ_TYPE_RESCUE: { + } + case ISEQ_TYPE_RESCUE: { iseq_set_exception_local_table(iseq); if (PM_NODE_TYPE_P(scope_node->ast_node, PM_RESCUE_MODIFIER_NODE)) { LABEL *lab = NEW_LABEL(lineno); @@ -6663,14 +6889,14 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, ADD_INSN1(ret, &dummy_line_node, throw, INT2FIX(0)); return; - } - default: + } + default: if (scope_node->body) { PM_COMPILE((pm_node_t *)scope_node->body); - } - else { + } else { PM_PUTNIL; } + break; } if (!PM_NODE_TYPE_P(scope_node->ast_node, PM_ENSURE_NODE)) { diff --git a/tool/prism_btests b/tool/prism_btests index 9770a8342b303d..e6777540f91cfe 100644 --- a/tool/prism_btests +++ b/tool/prism_btests @@ -8,6 +8,7 @@ ../src/bootstraptest/test_fiber.rb ../src/bootstraptest/test_finalizer.rb ../src/bootstraptest/test_flip.rb +../src/bootstraptest/test_flow.rb ../src/bootstraptest/test_fork.rb ../src/bootstraptest/test_gc.rb ../src/bootstraptest/test_io.rb @@ -25,11 +26,10 @@ ../src/bootstraptest/test_thread.rb ../src/bootstraptest/test_yjit_30k_ifelse.rb ../src/bootstraptest/test_yjit_30k_methods.rb +../src/bootstraptest/test_yjit_rust_port.rb # ../src/bootstraptest/test_exception.rb -../src/bootstraptest/test_flow.rb # ../src/bootstraptest/test_insns.rb # ../src/bootstraptest/test_method.rb # ../src/bootstraptest/test_ractor.rb # ../src/bootstraptest/test_syntax.rb -# ../src/bootstraptest/test_yjit_rust_port.rb # ../src/bootstraptest/test_yjit.rb From 366b14c0cd850d07f11b7c2f13d0456ece1c1036 Mon Sep 17 00:00:00 2001 From: BurdetteLamar Date: Fri, 19 Jan 2024 17:03:20 +0000 Subject: [PATCH 360/640] More tests --- test/ruby/test_argf.rb | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/ruby/test_argf.rb b/test/ruby/test_argf.rb index 12f7d6485a1193..fed1bf88b46997 100644 --- a/test/ruby/test_argf.rb +++ b/test/ruby/test_argf.rb @@ -1140,4 +1140,40 @@ def test_sized_read argf.close end end + + def test_putc + t = make_tempfile0("argf-#{__method__}") + t.puts 'bar' + t.close + ruby('-pi-', '-e', "print ARGF.putc('x')", t.path) do |f| + end + assert_equal("xxbar\n", File.read(t.path)) + end + + def test_puts + t = make_tempfile0("argf-#{__method__}") + t.puts 'bar' + t.close + ruby('-pi-', '-e', "print ARGF.puts('foo')", t.path) do |f| + end + assert_equal("foo\nbar\n", File.read(t.path)) + end + + def test_print + t = make_tempfile0("argf-#{__method__}") + t.puts 'bar' + t.close + ruby('-pi-', '-e', "print ARGF.print('foo')", t.path) do |f| + end + assert_equal("foobar\n", File.read(t.path)) + end + + def test_printf + t = make_tempfile0("argf-#{__method__}") + t.puts 'bar' + t.close + ruby('-pi-', '-e', "print ARGF.printf('%s', 'foo')", t.path) do |f| + end + assert_equal("foobar\n", File.read(t.path)) + end end From e2e15ddd676f4ec69589599bad0961c435c5aba5 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 21 Jan 2024 18:41:41 +0900 Subject: [PATCH 361/640] [DOC] `echo` command may not be a shell built-in --- process.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/process.c b/process.c index eeafc4c48382bb..df284a135c0318 100644 --- a/process.c +++ b/process.c @@ -3083,7 +3083,7 @@ NORETURN(static VALUE f_exec(int c, const VALUE *a, VALUE _)); * or contain meta characters: * * exec('if true; then echo "Foo"; fi') # Shell reserved word. - * exec('echo') # Built-in. + * exec('exit') # Built-in. * exec('date > date.tmp') # Contains meta character. * * The command line may also contain arguments and options for the command: @@ -4772,14 +4772,14 @@ rb_spawn(int argc, const VALUE *argv) * or contain meta characters: * * system('if true; then echo "Foo"; fi') # => true # Shell reserved word. - * system('echo') # => true # Built-in. + * system('exit') # => true # Built-in. * system('date > /tmp/date.tmp') # => true # Contains meta character. * system('date > /nop/date.tmp') # => false * system('date > /nop/date.tmp', exception: true) # Raises RuntimeError. * * Assigns the command's error status to $?: * - * system('echo') # => true # Built-in. + * system('exit') # => true # Built-in. * $? # => # * system('date > /nop/date.tmp') # => false * $? # => # @@ -4948,7 +4948,7 @@ rb_f_system(int argc, VALUE *argv, VALUE _) * * spawn('if true; then echo "Foo"; fi') # => 798847 # Shell reserved word. * Process.wait # => 798847 - * spawn('echo') # => 798848 # Built-in. + * spawn('exit') # => 798848 # Built-in. * Process.wait # => 798848 * spawn('date > /tmp/date.tmp') # => 798879 # Contains meta character. * Process.wait # => 798849 @@ -8848,7 +8848,7 @@ proc_warmup(VALUE _) * or contain meta characters: * * system('if true; then echo "Foo"; fi') # => true # Shell reserved word. - * system('echo') # => true # Built-in. + * system('exit') # => true # Built-in. * system('date > /tmp/date.tmp') # => true # Contains meta character. * system('date > /nop/date.tmp') # => false * system('date > /nop/date.tmp', exception: true) # Raises RuntimeError. From c6b548accbd211b69b0611b584e7673147aaea41 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Thu, 18 Jan 2024 19:45:05 -0600 Subject: [PATCH 362/640] [ruby/nkf] Add JRuby extension to the gem This pulls in the nkf extension implementation from JRuby. The build and load logic has been updated along the same lines as ruby/digest and the gem appears to build correctly for the -java platform. Fixes https://github.com/ruby/nkf/pull/13 https://github.com/ruby/nkf/commit/18f57f36ed --- ext/nkf/nkf.gemspec | 14 +++++++++++--- lib/nkf.rb | 6 ++++++ 2 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 lib/nkf.rb diff --git a/ext/nkf/nkf.gemspec b/ext/nkf/nkf.gemspec index 097a9485ed7a6d..7fb5cc3be0b844 100644 --- a/ext/nkf/nkf.gemspec +++ b/ext/nkf/nkf.gemspec @@ -11,8 +11,8 @@ end Gem::Specification.new do |spec| spec.name = "nkf" spec.version = source_version - spec.authors = ["NARUSE Yui"] - spec.email = ["naruse@airemix.jp"] + spec.authors = ["NARUSE Yui", "Charles Oliver Nutter"] + spec.email = ["naruse@airemix.jp", "headius@headius.com"] spec.summary = %q{Ruby extension for Network Kanji Filter} spec.description = %q{Ruby extension for Network Kanji Filter} @@ -28,8 +28,16 @@ Gem::Specification.new do |spec| spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } end + + if Gem::Platform === spec.platform and spec.platform =~ 'java' or RUBY_ENGINE == 'jruby' + spec.platform = 'java' + + spec.files += Dir["lib/nkf.jar"] + else + spec.extensions = ["ext/nkf/extconf.rb"] + end + spec.bindir = "exe" spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.extensions = ["ext/nkf/extconf.rb"] end diff --git a/lib/nkf.rb b/lib/nkf.rb new file mode 100644 index 00000000000000..d71717d8d8b7d0 --- /dev/null +++ b/lib/nkf.rb @@ -0,0 +1,6 @@ +if RUBY_ENGINE == "jruby" + require 'nkf.jar' + JRuby::Util.load_ext('org.jruby.ext.nkf.NKFLibrary') +else + require 'nkf.so' +end From 34c5e78760d36277b8997be8c09a79b5cdd65407 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Fri, 19 Jan 2024 00:13:05 -0600 Subject: [PATCH 363/640] [ruby/nkf] Drop GPL and add licenses to gemspec https://github.com/ruby/nkf/commit/19df7138f7 --- ext/nkf/nkf.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/nkf/nkf.gemspec b/ext/nkf/nkf.gemspec index 7fb5cc3be0b844..62a767c94b58eb 100644 --- a/ext/nkf/nkf.gemspec +++ b/ext/nkf/nkf.gemspec @@ -31,7 +31,7 @@ Gem::Specification.new do |spec| if Gem::Platform === spec.platform and spec.platform =~ 'java' or RUBY_ENGINE == 'jruby' spec.platform = 'java' - + spec.licenses += ["EPL-2.0", "LGPL-2.1"] spec.files += Dir["lib/nkf.jar"] else spec.extensions = ["ext/nkf/extconf.rb"] From 94af1e5b811f13f9c1b9be6ab6a9eea192a713f8 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 19 Jan 2024 20:09:32 +0900 Subject: [PATCH 364/640] [ruby/uri] Removed commented-out code https://github.com/ruby/uri/commit/feb8e0dd73 --- lib/uri/generic.rb | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/lib/uri/generic.rb b/lib/uri/generic.rb index 9ea2335ceaf5b6..baa6a4c34c3de3 100644 --- a/lib/uri/generic.rb +++ b/lib/uri/generic.rb @@ -1402,19 +1402,6 @@ def eql?(oth) self.component_ary.eql?(oth.component_ary) end -=begin - ---- URI::Generic#===(oth) - -=end -# def ===(oth) -# raise NotImplementedError -# end - -=begin -=end - - # Returns an Array of the components defined from the COMPONENT Array. def component_ary component.collect do |x| From d51f4c9288a2195fbf6889fca8790587f71a1cd9 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 19 Jan 2024 13:32:45 +0900 Subject: [PATCH 365/640] Reapply "[rubygems/rubygems] Fix `require` of a default gem when unresolved gems depend on it" This reverts commit 54552b89e73fc616ba47c1c87d33625af99cbce9. --- lib/rubygems/core_ext/kernel_require.rb | 2 ++ test/rubygems/test_require.rb | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/lib/rubygems/core_ext/kernel_require.rb b/lib/rubygems/core_ext/kernel_require.rb index 46954c534da324..50e3ea89b4b884 100644 --- a/lib/rubygems/core_ext/kernel_require.rb +++ b/lib/rubygems/core_ext/kernel_require.rb @@ -62,6 +62,8 @@ def require(path) # :doc: Kernel.send(:gem, spec.name, Gem::Requirement.default_prerelease) unless resolved_path + + next end # If there are no unresolved deps, then we can use just try diff --git a/test/rubygems/test_require.rb b/test/rubygems/test_require.rb index b3926afe1525ae..7f5584ea8ace42 100644 --- a/test/rubygems/test_require.rb +++ b/test/rubygems/test_require.rb @@ -540,6 +540,26 @@ def test_default_gem_prerelease assert_equal %w[default-3.0.0.rc2], loaded_spec_names end + def test_default_gem_with_unresolved_gems_depending_on_it + net_http_old = util_spec "net-http", "0.1.1", nil, "lib/net/http.rb" + install_gem net_http_old + + net_http_default = new_default_spec "net-http", "0.3.0", nil, "net/http.rb" + install_default_gems net_http_default + + faraday_1 = util_spec "faraday", "1", { "net-http" => ">= 0" } + install_gem faraday_1 + + faraday_2 = util_spec "faraday", "2", { "net-http" => ">= 0" } + install_gem faraday_2 + + chef = util_spec "chef", "1", { "faraday" => [">= 1", "< 3"] }, "lib/chef.rb" + install_gem chef + + assert_require "chef" + assert_require "net/http" + end + def loaded_spec_names Gem.loaded_specs.values.map(&:full_name).sort end From 00dc1cace803fa557c685e7cb395bfaa77bc03a9 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 19 Jan 2024 13:32:53 +0900 Subject: [PATCH 366/640] Reapply "[rubygems/rubygems] Fix activation conflicts when circularly requiring a gem" This reverts commit 04cf66765a8a9d48baea6d9aee266dc9aa21df27. --- lib/rubygems.rb | 7 +++++ lib/rubygems/core_ext/kernel_require.rb | 8 +++-- test/rubygems/test_require.rb | 39 +++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/lib/rubygems.rb b/lib/rubygems.rb index 47b1ce69d26608..ad7ab1075636a8 100644 --- a/lib/rubygems.rb +++ b/lib/rubygems.rb @@ -1216,6 +1216,13 @@ def register_default_spec(spec) ## # Find a Gem::Specification of default gem from +path+ + def find_default_spec(path) + @path_to_default_spec_map[path] + end + + ## + # Find an unresolved Gem::Specification of default gem from +path+ + def find_unresolved_default_spec(path) default_spec = @path_to_default_spec_map[path] default_spec if default_spec && loaded_specs[default_spec.name] != default_spec diff --git a/lib/rubygems/core_ext/kernel_require.rb b/lib/rubygems/core_ext/kernel_require.rb index 50e3ea89b4b884..073966b696ccde 100644 --- a/lib/rubygems/core_ext/kernel_require.rb +++ b/lib/rubygems/core_ext/kernel_require.rb @@ -42,7 +42,11 @@ def require(path) # :doc: # If +path+ belongs to a default gem, we activate it and then go straight # to normal require - if spec = Gem.find_unresolved_default_spec(path) + if spec = Gem.find_default_spec(path) + name = spec.name + + next if Gem.loaded_specs[name] + # Ensure -I beats a default gem resolved_path = begin rp = nil @@ -60,7 +64,7 @@ def require(path) # :doc: rp end - Kernel.send(:gem, spec.name, Gem::Requirement.default_prerelease) unless + Kernel.send(:gem, name, Gem::Requirement.default_prerelease) unless resolved_path next diff --git a/test/rubygems/test_require.rb b/test/rubygems/test_require.rb index 7f5584ea8ace42..f595d8e08ecd2e 100644 --- a/test/rubygems/test_require.rb +++ b/test/rubygems/test_require.rb @@ -560,6 +560,45 @@ def test_default_gem_with_unresolved_gems_depending_on_it assert_require "net/http" end + def test_default_gem_required_circulary_with_unresolved_gems_depending_on_it + net_http_old = util_spec "net-http", "0.1.1", nil, "lib/net/http.rb" + install_gem net_http_old + + net_http_default = new_default_spec "net-http", "0.3.0", nil, "net/http.rb" + net_http_default_path = File.join(@tempdir, "default_gems", "lib", "net/http.rb") + install_default_gems net_http_default + File.write(net_http_default_path, 'require "net/http"') + + faraday_1 = util_spec "faraday", "1", { "net-http" => ">= 0" } + install_gem faraday_1 + + faraday_2 = util_spec "faraday", "2", { "net-http" => ">= 0" } + install_gem faraday_2 + + chef = util_spec "chef", "1", { "faraday" => [">= 1", "< 3"] }, "lib/chef.rb" + install_gem chef + + assert_require "chef" + + out, err = capture_output do + assert_require "net/http" + end + + assert_empty out + + circular_require_warning = false + + err_lines = err.split("\n").reject do |line| + if line.include?("circular require") + circular_require_warning = true + elsif circular_require_warning # ignore backtrace lines for circular require warning + circular_require_warning = line.start_with?(/[\s]/) + end + end + + assert_empty err_lines + end + def loaded_spec_names Gem.loaded_specs.values.map(&:full_name).sort end From 67b00f721dd4a8e2a137fcc4d69071ba2f5cbd8c Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Fri, 19 Jan 2024 14:48:52 -0800 Subject: [PATCH 367/640] Make tests play with upstream Ruby tests CI broke in https://github.com/ruby/ruby/pull/9604 because if any Ruby tests run `require 'net/http'`, they will pollute the `$LOADED_FEATURES` for the RubyGems tests. We can fix this by renaming the test default gem from `net-http` to `my-http`. See https://github.com/rubygems/rubygems/pull/7379#issuecomment-1901241299 for more details. --- test/rubygems/test_require.rb | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/test/rubygems/test_require.rb b/test/rubygems/test_require.rb index f595d8e08ecd2e..30a4a477f9dfcc 100644 --- a/test/rubygems/test_require.rb +++ b/test/rubygems/test_require.rb @@ -541,38 +541,38 @@ def test_default_gem_prerelease end def test_default_gem_with_unresolved_gems_depending_on_it - net_http_old = util_spec "net-http", "0.1.1", nil, "lib/net/http.rb" - install_gem net_http_old + my_http_old = util_spec "my-http", "0.1.1", nil, "lib/my/http.rb" + install_gem my_http_old - net_http_default = new_default_spec "net-http", "0.3.0", nil, "net/http.rb" - install_default_gems net_http_default + my_http_default = new_default_spec "my-http", "0.3.0", nil, "my/http.rb" + install_default_gems my_http_default - faraday_1 = util_spec "faraday", "1", { "net-http" => ">= 0" } + faraday_1 = util_spec "faraday", "1", { "my-http" => ">= 0" } install_gem faraday_1 - faraday_2 = util_spec "faraday", "2", { "net-http" => ">= 0" } + faraday_2 = util_spec "faraday", "2", { "my-http" => ">= 0" } install_gem faraday_2 chef = util_spec "chef", "1", { "faraday" => [">= 1", "< 3"] }, "lib/chef.rb" install_gem chef assert_require "chef" - assert_require "net/http" + assert_require "my/http" end def test_default_gem_required_circulary_with_unresolved_gems_depending_on_it - net_http_old = util_spec "net-http", "0.1.1", nil, "lib/net/http.rb" - install_gem net_http_old + my_http_old = util_spec "my-http", "0.1.1", nil, "lib/my/http.rb" + install_gem my_http_old - net_http_default = new_default_spec "net-http", "0.3.0", nil, "net/http.rb" - net_http_default_path = File.join(@tempdir, "default_gems", "lib", "net/http.rb") - install_default_gems net_http_default - File.write(net_http_default_path, 'require "net/http"') + my_http_default = new_default_spec "my-http", "0.3.0", nil, "my/http.rb" + my_http_default_path = File.join(@tempdir, "default_gems", "lib", "my/http.rb") + install_default_gems my_http_default + File.write(my_http_default_path, 'require "my/http"') - faraday_1 = util_spec "faraday", "1", { "net-http" => ">= 0" } + faraday_1 = util_spec "faraday", "1", { "my-http" => ">= 0" } install_gem faraday_1 - faraday_2 = util_spec "faraday", "2", { "net-http" => ">= 0" } + faraday_2 = util_spec "faraday", "2", { "my-http" => ">= 0" } install_gem faraday_2 chef = util_spec "chef", "1", { "faraday" => [">= 1", "< 3"] }, "lib/chef.rb" @@ -581,7 +581,7 @@ def test_default_gem_required_circulary_with_unresolved_gems_depending_on_it assert_require "chef" out, err = capture_output do - assert_require "net/http" + assert_require "my/http" end assert_empty out From 36fc5ee64f8c42836bfad57c8d6df833ce29d7d7 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 22 Jan 2024 10:10:06 +0900 Subject: [PATCH 368/640] Extract drb --- gems/bundled_gems | 1 + lib/drb.rb | 3 - lib/drb/acl.rb | 239 ----- lib/drb/drb.gemspec | 43 - lib/drb/drb.rb | 1943 ---------------------------------- lib/drb/eq.rb | 15 - lib/drb/extserv.rb | 44 - lib/drb/extservm.rb | 94 -- lib/drb/gw.rb | 161 --- lib/drb/invokemethod.rb | 35 - lib/drb/observer.rb | 26 - lib/drb/ssl.rb | 354 ------- lib/drb/timeridconv.rb | 97 -- lib/drb/unix.rb | 118 --- lib/drb/version.rb | 3 - lib/drb/weakidconv.rb | 59 -- test/drb/drbtest.rb | 396 ------- test/drb/ignore_test_drb.rb | 14 - test/drb/test_acl.rb | 207 ---- test/drb/test_drb.rb | 371 ------- test/drb/test_drbobject.rb | 69 -- test/drb/test_drbssl.rb | 84 -- test/drb/test_drbunix.rb | 60 -- test/drb/ut_array.rb | 17 - test/drb/ut_array_drbssl.rb | 43 - test/drb/ut_array_drbunix.rb | 17 - test/drb/ut_drb.rb | 189 ---- test/drb/ut_drb_drbssl.rb | 40 - test/drb/ut_drb_drbunix.rb | 18 - test/drb/ut_eq.rb | 37 - test/drb/ut_large.rb | 62 -- test/drb/ut_port.rb | 16 - test/drb/ut_safe1.rb | 17 - test/drb/ut_timerholder.rb | 74 -- 34 files changed, 1 insertion(+), 4965 deletions(-) delete mode 100644 lib/drb.rb delete mode 100644 lib/drb/acl.rb delete mode 100644 lib/drb/drb.gemspec delete mode 100644 lib/drb/drb.rb delete mode 100644 lib/drb/eq.rb delete mode 100644 lib/drb/extserv.rb delete mode 100644 lib/drb/extservm.rb delete mode 100644 lib/drb/gw.rb delete mode 100644 lib/drb/invokemethod.rb delete mode 100644 lib/drb/observer.rb delete mode 100644 lib/drb/ssl.rb delete mode 100644 lib/drb/timeridconv.rb delete mode 100644 lib/drb/unix.rb delete mode 100644 lib/drb/version.rb delete mode 100644 lib/drb/weakidconv.rb delete mode 100644 test/drb/drbtest.rb delete mode 100644 test/drb/ignore_test_drb.rb delete mode 100644 test/drb/test_acl.rb delete mode 100644 test/drb/test_drb.rb delete mode 100644 test/drb/test_drbobject.rb delete mode 100644 test/drb/test_drbssl.rb delete mode 100644 test/drb/test_drbunix.rb delete mode 100644 test/drb/ut_array.rb delete mode 100644 test/drb/ut_array_drbssl.rb delete mode 100644 test/drb/ut_array_drbunix.rb delete mode 100644 test/drb/ut_drb.rb delete mode 100644 test/drb/ut_drb_drbssl.rb delete mode 100644 test/drb/ut_drb_drbunix.rb delete mode 100644 test/drb/ut_eq.rb delete mode 100644 test/drb/ut_large.rb delete mode 100644 test/drb/ut_port.rb delete mode 100644 test/drb/ut_safe1.rb delete mode 100644 test/drb/ut_timerholder.rb diff --git a/gems/bundled_gems b/gems/bundled_gems index 6e47335e3fa89a..23945f045ef43b 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -29,3 +29,4 @@ observer 0.1.2 https://github.com/ruby/observer abbrev 0.1.2 https://github.com/ruby/abbrev resolv-replace 0.1.1 https://github.com/ruby/resolv-replace rinda 0.2.0 https://github.com/ruby/rinda +drb 2.2.0 https://github.com/ruby/drb diff --git a/lib/drb.rb b/lib/drb.rb deleted file mode 100644 index 2bb4716fa22d2a..00000000000000 --- a/lib/drb.rb +++ /dev/null @@ -1,3 +0,0 @@ -# frozen_string_literal: false -require 'drb/drb' - diff --git a/lib/drb/acl.rb b/lib/drb/acl.rb deleted file mode 100644 index b004656f09dc44..00000000000000 --- a/lib/drb/acl.rb +++ /dev/null @@ -1,239 +0,0 @@ -# frozen_string_literal: false -# Copyright (c) 2000,2002,2003 Masatoshi SEKI -# -# acl.rb is copyrighted free software by Masatoshi SEKI. -# You can redistribute it and/or modify it under the same terms as Ruby. - -require 'ipaddr' - -## -# Simple Access Control Lists. -# -# Access control lists are composed of "allow" and "deny" halves to control -# access. Use "all" or "*" to match any address. To match a specific address -# use any address or address mask that IPAddr can understand. -# -# Example: -# -# list = %w[ -# deny all -# allow 192.168.1.1 -# allow ::ffff:192.168.1.2 -# allow 192.168.1.3 -# ] -# -# # From Socket#peeraddr, see also ACL#allow_socket? -# addr = ["AF_INET", 10, "lc630", "192.168.1.3"] -# -# acl = ACL.new -# p acl.allow_addr?(addr) # => true -# -# acl = ACL.new(list, ACL::DENY_ALLOW) -# p acl.allow_addr?(addr) # => true - -class ACL - - ## - # The current version of ACL - - VERSION=["2.0.0"] - - ## - # An entry in an ACL - - class ACLEntry - - ## - # Creates a new entry using +str+. - # - # +str+ may be "*" or "all" to match any address, an IP address string - # to match a specific address, an IP address mask per IPAddr, or one - # containing "*" to match part of an IPv4 address. - # - # IPAddr::InvalidPrefixError may be raised when an IP network - # address with an invalid netmask/prefix is given. - - def initialize(str) - if str == '*' or str == 'all' - @pat = [:all] - elsif str.include?('*') - @pat = [:name, dot_pat(str)] - else - begin - @pat = [:ip, IPAddr.new(str)] - rescue IPAddr::InvalidPrefixError - # In this case, `str` shouldn't be a host name pattern - # because it contains a slash. - raise - rescue ArgumentError - @pat = [:name, dot_pat(str)] - end - end - end - - private - - ## - # Creates a regular expression to match IPv4 addresses - - def dot_pat_str(str) - list = str.split('.').collect { |s| - (s == '*') ? '.+' : s - } - list.join("\\.") - end - - private - - ## - # Creates a Regexp to match an address. - - def dot_pat(str) - /\A#{dot_pat_str(str)}\z/ - end - - public - - ## - # Matches +addr+ against this entry. - - def match(addr) - case @pat[0] - when :all - true - when :ip - begin - ipaddr = IPAddr.new(addr[3]) - ipaddr = ipaddr.ipv4_mapped if @pat[1].ipv6? && ipaddr.ipv4? - rescue ArgumentError - return false - end - (@pat[1].include?(ipaddr)) ? true : false - when :name - (@pat[1] =~ addr[2]) ? true : false - else - false - end - end - end - - ## - # A list of ACLEntry objects. Used to implement the allow and deny halves - # of an ACL - - class ACLList - - ## - # Creates an empty ACLList - - def initialize - @list = [] - end - - public - - ## - # Matches +addr+ against each ACLEntry in this list. - - def match(addr) - @list.each do |e| - return true if e.match(addr) - end - false - end - - public - - ## - # Adds +str+ as an ACLEntry in this list - - def add(str) - @list.push(ACLEntry.new(str)) - end - - end - - ## - # Default to deny - - DENY_ALLOW = 0 - - ## - # Default to allow - - ALLOW_DENY = 1 - - ## - # Creates a new ACL from +list+ with an evaluation +order+ of DENY_ALLOW or - # ALLOW_DENY. - # - # An ACL +list+ is an Array of "allow" or "deny" and an address or address - # mask or "all" or "*" to match any address: - # - # %w[ - # deny all - # allow 192.0.2.2 - # allow 192.0.2.128/26 - # ] - - def initialize(list=nil, order = DENY_ALLOW) - @order = order - @deny = ACLList.new - @allow = ACLList.new - install_list(list) if list - end - - public - - ## - # Allow connections from Socket +soc+? - - def allow_socket?(soc) - allow_addr?(soc.peeraddr) - end - - public - - ## - # Allow connections from addrinfo +addr+? It must be formatted like - # Socket#peeraddr: - # - # ["AF_INET", 10, "lc630", "192.0.2.1"] - - def allow_addr?(addr) - case @order - when DENY_ALLOW - return true if @allow.match(addr) - return false if @deny.match(addr) - return true - when ALLOW_DENY - return false if @deny.match(addr) - return true if @allow.match(addr) - return false - else - false - end - end - - public - - ## - # Adds +list+ of ACL entries to this ACL. - - def install_list(list) - i = 0 - while i < list.size - permission, domain = list.slice(i,2) - case permission.downcase - when 'allow' - @allow.add(domain) - when 'deny' - @deny.add(domain) - else - raise "Invalid ACL entry #{list}" - end - i += 2 - end - end - -end diff --git a/lib/drb/drb.gemspec b/lib/drb/drb.gemspec deleted file mode 100644 index c9d7e40a514479..00000000000000 --- a/lib/drb/drb.gemspec +++ /dev/null @@ -1,43 +0,0 @@ -begin - require_relative "lib/drb/version" -rescue LoadError # Fallback to load version file in ruby core repository - require_relative "version" -end - -Gem::Specification.new do |spec| - spec.name = "drb" - spec.version = DRb::VERSION - spec.authors = ["Masatoshi SEKI"] - spec.email = ["seki@ruby-lang.org"] - - spec.summary = %q{Distributed object system for Ruby} - spec.description = %q{Distributed object system for Ruby} - spec.homepage = "https://github.com/ruby/drb" - spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0") - spec.licenses = ["Ruby", "BSD-2-Clause"] - - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = spec.homepage - - spec.files = %w[ - LICENSE.txt - drb.gemspec - lib/drb.rb - lib/drb/acl.rb - lib/drb/drb.rb - lib/drb/eq.rb - lib/drb/extserv.rb - lib/drb/extservm.rb - lib/drb/gw.rb - lib/drb/invokemethod.rb - lib/drb/observer.rb - lib/drb/ssl.rb - lib/drb/timeridconv.rb - lib/drb/unix.rb - lib/drb/version.rb - lib/drb/weakidconv.rb - ] - spec.require_paths = ["lib"] - - spec.add_dependency "ruby2_keywords" -end diff --git a/lib/drb/drb.rb b/lib/drb/drb.rb deleted file mode 100644 index 5a85e429755e5a..00000000000000 --- a/lib/drb/drb.rb +++ /dev/null @@ -1,1943 +0,0 @@ -# frozen_string_literal: false -# -# = drb/drb.rb -# -# Distributed Ruby: _dRuby_ -# -# Copyright (c) 1999-2003 Masatoshi SEKI. You can redistribute it and/or -# modify it under the same terms as Ruby. -# -# Author:: Masatoshi SEKI -# -# Documentation:: William Webber (william@williamwebber.com) -# -# == Overview -# -# dRuby is a distributed object system for Ruby. It allows an object in one -# Ruby process to invoke methods on an object in another Ruby process on the -# same or a different machine. -# -# The Ruby standard library contains the core classes of the dRuby package. -# However, the full package also includes access control lists and the -# Rinda tuple-space distributed task management system, as well as a -# large number of samples. The full dRuby package can be downloaded from -# the dRuby home page (see *References*). -# -# For an introduction and examples of usage see the documentation to the -# DRb module. -# -# == References -# -# [http://www2a.biglobe.ne.jp/~seki/ruby/druby.html] -# The dRuby home page, in Japanese. Contains the full dRuby package -# and links to other Japanese-language sources. -# -# [http://www2a.biglobe.ne.jp/~seki/ruby/druby.en.html] -# The English version of the dRuby home page. -# -# [http://pragprog.com/book/sidruby/the-druby-book] -# The dRuby Book: Distributed and Parallel Computing with Ruby -# by Masatoshi Seki and Makoto Inoue -# -# [http://www.ruby-doc.org/docs/ProgrammingRuby/html/ospace.html] -# The chapter from *Programming* *Ruby* by Dave Thomas and Andy Hunt -# which discusses dRuby. -# -# [http://www.clio.ne.jp/home/web-i31s/Flotuard/Ruby/PRC2K_seki/dRuby.en.html] -# Translation of presentation on Ruby by Masatoshi Seki. - -require 'socket' -require 'io/wait' -require 'monitor' -require_relative 'eq' -require_relative 'version' - -# -# == Overview -# -# dRuby is a distributed object system for Ruby. It is written in -# pure Ruby and uses its own protocol. No add-in services are needed -# beyond those provided by the Ruby runtime, such as TCP sockets. It -# does not rely on or interoperate with other distributed object -# systems such as CORBA, RMI, or .NET. -# -# dRuby allows methods to be called in one Ruby process upon a Ruby -# object located in another Ruby process, even on another machine. -# References to objects can be passed between processes. Method -# arguments and return values are dumped and loaded in marshalled -# format. All of this is done transparently to both the caller of the -# remote method and the object that it is called upon. -# -# An object in a remote process is locally represented by a -# DRb::DRbObject instance. This acts as a sort of proxy for the -# remote object. Methods called upon this DRbObject instance are -# forwarded to its remote object. This is arranged dynamically at run -# time. There are no statically declared interfaces for remote -# objects, such as CORBA's IDL. -# -# dRuby calls made into a process are handled by a DRb::DRbServer -# instance within that process. This reconstitutes the method call, -# invokes it upon the specified local object, and returns the value to -# the remote caller. Any object can receive calls over dRuby. There -# is no need to implement a special interface, or mixin special -# functionality. Nor, in the general case, does an object need to -# explicitly register itself with a DRbServer in order to receive -# dRuby calls. -# -# One process wishing to make dRuby calls upon another process must -# somehow obtain an initial reference to an object in the remote -# process by some means other than as the return value of a remote -# method call, as there is initially no remote object reference it can -# invoke a method upon. This is done by attaching to the server by -# URI. Each DRbServer binds itself to a URI such as -# 'druby://example.com:8787'. A DRbServer can have an object attached -# to it that acts as the server's *front* *object*. A DRbObject can -# be explicitly created from the server's URI. This DRbObject's -# remote object will be the server's front object. This front object -# can then return references to other Ruby objects in the DRbServer's -# process. -# -# Method calls made over dRuby behave largely the same as normal Ruby -# method calls made within a process. Method calls with blocks are -# supported, as are raising exceptions. In addition to a method's -# standard errors, a dRuby call may also raise one of the -# dRuby-specific errors, all of which are subclasses of DRb::DRbError. -# -# Any type of object can be passed as an argument to a dRuby call or -# returned as its return value. By default, such objects are dumped -# or marshalled at the local end, then loaded or unmarshalled at the -# remote end. The remote end therefore receives a copy of the local -# object, not a distributed reference to it; methods invoked upon this -# copy are executed entirely in the remote process, not passed on to -# the local original. This has semantics similar to pass-by-value. -# -# However, if an object cannot be marshalled, a dRuby reference to it -# is passed or returned instead. This will turn up at the remote end -# as a DRbObject instance. All methods invoked upon this remote proxy -# are forwarded to the local object, as described in the discussion of -# DRbObjects. This has semantics similar to the normal Ruby -# pass-by-reference. -# -# The easiest way to signal that we want an otherwise marshallable -# object to be passed or returned as a DRbObject reference, rather -# than marshalled and sent as a copy, is to include the -# DRb::DRbUndumped mixin module. -# -# dRuby supports calling remote methods with blocks. As blocks (or -# rather the Proc objects that represent them) are not marshallable, -# the block executes in the local, not the remote, context. Each -# value yielded to the block is passed from the remote object to the -# local block, then the value returned by each block invocation is -# passed back to the remote execution context to be collected, before -# the collected values are finally returned to the local context as -# the return value of the method invocation. -# -# == Examples of usage -# -# For more dRuby samples, see the +samples+ directory in the full -# dRuby distribution. -# -# === dRuby in client/server mode -# -# This illustrates setting up a simple client-server drb -# system. Run the server and client code in different terminals, -# starting the server code first. -# -# ==== Server code -# -# require 'drb/drb' -# -# # The URI for the server to connect to -# URI="druby://localhost:8787" -# -# class TimeServer -# -# def get_current_time -# return Time.now -# end -# -# end -# -# # The object that handles requests on the server -# FRONT_OBJECT=TimeServer.new -# -# DRb.start_service(URI, FRONT_OBJECT) -# # Wait for the drb server thread to finish before exiting. -# DRb.thread.join -# -# ==== Client code -# -# require 'drb/drb' -# -# # The URI to connect to -# SERVER_URI="druby://localhost:8787" -# -# # Start a local DRbServer to handle callbacks. -# # -# # Not necessary for this small example, but will be required -# # as soon as we pass a non-marshallable object as an argument -# # to a dRuby call. -# # -# # Note: this must be called at least once per process to take any effect. -# # This is particularly important if your application forks. -# DRb.start_service -# -# timeserver = DRbObject.new_with_uri(SERVER_URI) -# puts timeserver.get_current_time -# -# === Remote objects under dRuby -# -# This example illustrates returning a reference to an object -# from a dRuby call. The Logger instances live in the server -# process. References to them are returned to the client process, -# where methods can be invoked upon them. These methods are -# executed in the server process. -# -# ==== Server code -# -# require 'drb/drb' -# -# URI="druby://localhost:8787" -# -# class Logger -# -# # Make dRuby send Logger instances as dRuby references, -# # not copies. -# include DRb::DRbUndumped -# -# def initialize(n, fname) -# @name = n -# @filename = fname -# end -# -# def log(message) -# File.open(@filename, "a") do |f| -# f.puts("#{Time.now}: #{@name}: #{message}") -# end -# end -# -# end -# -# # We have a central object for creating and retrieving loggers. -# # This retains a local reference to all loggers created. This -# # is so an existing logger can be looked up by name, but also -# # to prevent loggers from being garbage collected. A dRuby -# # reference to an object is not sufficient to prevent it being -# # garbage collected! -# class LoggerFactory -# -# def initialize(bdir) -# @basedir = bdir -# @loggers = {} -# end -# -# def get_logger(name) -# if !@loggers.has_key? name -# # make the filename safe, then declare it to be so -# fname = name.gsub(/[.\/\\\:]/, "_") -# @loggers[name] = Logger.new(name, @basedir + "/" + fname) -# end -# return @loggers[name] -# end -# -# end -# -# FRONT_OBJECT=LoggerFactory.new("/tmp/dlog") -# -# DRb.start_service(URI, FRONT_OBJECT) -# DRb.thread.join -# -# ==== Client code -# -# require 'drb/drb' -# -# SERVER_URI="druby://localhost:8787" -# -# DRb.start_service -# -# log_service=DRbObject.new_with_uri(SERVER_URI) -# -# ["loga", "logb", "logc"].each do |logname| -# -# logger=log_service.get_logger(logname) -# -# logger.log("Hello, world!") -# logger.log("Goodbye, world!") -# logger.log("=== EOT ===") -# -# end -# -# == Security -# -# As with all network services, security needs to be considered when -# using dRuby. By allowing external access to a Ruby object, you are -# not only allowing outside clients to call the methods you have -# defined for that object, but by default to execute arbitrary Ruby -# code on your server. Consider the following: -# -# # !!! UNSAFE CODE !!! -# ro = DRbObject::new_with_uri("druby://your.server.com:8989") -# class << ro -# undef :instance_eval # force call to be passed to remote object -# end -# ro.instance_eval("`rm -rf *`") -# -# The dangers posed by instance_eval and friends are such that a -# DRbServer should only be used when clients are trusted. -# -# A DRbServer can be configured with an access control list to -# selectively allow or deny access from specified IP addresses. The -# main druby distribution provides the ACL class for this purpose. In -# general, this mechanism should only be used alongside, rather than -# as a replacement for, a good firewall. -# -# == dRuby internals -# -# dRuby is implemented using three main components: a remote method -# call marshaller/unmarshaller; a transport protocol; and an -# ID-to-object mapper. The latter two can be directly, and the first -# indirectly, replaced, in order to provide different behaviour and -# capabilities. -# -# Marshalling and unmarshalling of remote method calls is performed by -# a DRb::DRbMessage instance. This uses the Marshal module to dump -# the method call before sending it over the transport layer, then -# reconstitute it at the other end. There is normally no need to -# replace this component, and no direct way is provided to do so. -# However, it is possible to implement an alternative marshalling -# scheme as part of an implementation of the transport layer. -# -# The transport layer is responsible for opening client and server -# network connections and forwarding dRuby request across them. -# Normally, it uses DRb::DRbMessage internally to manage marshalling -# and unmarshalling. The transport layer is managed by -# DRb::DRbProtocol. Multiple protocols can be installed in -# DRbProtocol at the one time; selection between them is determined by -# the scheme of a dRuby URI. The default transport protocol is -# selected by the scheme 'druby:', and implemented by -# DRb::DRbTCPSocket. This uses plain TCP/IP sockets for -# communication. An alternative protocol, using UNIX domain sockets, -# is implemented by DRb::DRbUNIXSocket in the file drb/unix.rb, and -# selected by the scheme 'drbunix:'. A sample implementation over -# HTTP can be found in the samples accompanying the main dRuby -# distribution. -# -# The ID-to-object mapping component maps dRuby object ids to the -# objects they refer to, and vice versa. The implementation to use -# can be specified as part of a DRb::DRbServer's configuration. The -# default implementation is provided by DRb::DRbIdConv. It uses an -# object's ObjectSpace id as its dRuby id. This means that the dRuby -# reference to that object only remains meaningful for the lifetime of -# the object's process and the lifetime of the object within that -# process. A modified implementation is provided by DRb::TimerIdConv -# in the file drb/timeridconv.rb. This implementation retains a local -# reference to all objects exported over dRuby for a configurable -# period of time (defaulting to ten minutes), to prevent them being -# garbage-collected within this time. Another sample implementation -# is provided in sample/name.rb in the main dRuby distribution. This -# allows objects to specify their own id or "name". A dRuby reference -# can be made persistent across processes by having each process -# register an object using the same dRuby name. -# -module DRb - - # Superclass of all errors raised in the DRb module. - class DRbError < RuntimeError; end - - # Error raised when an error occurs on the underlying communication - # protocol. - class DRbConnError < DRbError; end - - # Class responsible for converting between an object and its id. - # - # This, the default implementation, uses an object's local ObjectSpace - # __id__ as its id. This means that an object's identification over - # drb remains valid only while that object instance remains alive - # within the server runtime. - # - # For alternative mechanisms, see DRb::TimerIdConv in drb/timeridconv.rb - # and DRbNameIdConv in sample/name.rb in the full drb distribution. - class DRbIdConv - - # Convert an object reference id to an object. - # - # This implementation looks up the reference id in the local object - # space and returns the object it refers to. - def to_obj(ref) - ObjectSpace._id2ref(ref) - end - - # Convert an object into a reference id. - # - # This implementation returns the object's __id__ in the local - # object space. - def to_id(obj) - case obj - when Object - obj.nil? ? nil : obj.__id__ - when BasicObject - obj.__id__ - end - end - end - - # Mixin module making an object undumpable or unmarshallable. - # - # If an object which includes this module is returned by method - # called over drb, then the object remains in the server space - # and a reference to the object is returned, rather than the - # object being marshalled and moved into the client space. - module DRbUndumped - def _dump(dummy) # :nodoc: - raise TypeError, 'can\'t dump' - end - end - - # Error raised by the DRb module when an attempt is made to refer to - # the context's current drb server but the context does not have one. - # See #current_server. - class DRbServerNotFound < DRbError; end - - # Error raised by the DRbProtocol module when it cannot find any - # protocol implementation support the scheme specified in a URI. - class DRbBadURI < DRbError; end - - # Error raised by a dRuby protocol when it doesn't support the - # scheme specified in a URI. See DRb::DRbProtocol. - class DRbBadScheme < DRbError; end - - # An exception wrapping a DRb::DRbUnknown object - class DRbUnknownError < DRbError - - # Create a new DRbUnknownError for the DRb::DRbUnknown object +unknown+ - def initialize(unknown) - @unknown = unknown - super(unknown.name) - end - - # Get the wrapped DRb::DRbUnknown object. - attr_reader :unknown - - def self._load(s) # :nodoc: - Marshal::load(s) - end - - def _dump(lv) # :nodoc: - Marshal::dump(@unknown) - end - end - - # An exception wrapping an error object - class DRbRemoteError < DRbError - - # Creates a new remote error that wraps the Exception +error+ - def initialize(error) - @reason = error.class.to_s - super("#{error.message} (#{error.class})") - set_backtrace(error.backtrace) - end - - # the class of the error, as a string. - attr_reader :reason - end - - # Class wrapping a marshalled object whose type is unknown locally. - # - # If an object is returned by a method invoked over drb, but the - # class of the object is unknown in the client namespace, or - # the object is a constant unknown in the client namespace, then - # the still-marshalled object is returned wrapped in a DRbUnknown instance. - # - # If this object is passed as an argument to a method invoked over - # drb, then the wrapped object is passed instead. - # - # The class or constant name of the object can be read from the - # +name+ attribute. The marshalled object is held in the +buf+ - # attribute. - class DRbUnknown - - # Create a new DRbUnknown object. - # - # +buf+ is a string containing a marshalled object that could not - # be unmarshalled. +err+ is the error message that was raised - # when the unmarshalling failed. It is used to determine the - # name of the unmarshalled object. - def initialize(err, buf) - case err.to_s - when /uninitialized constant (\S+)/ - @name = $1 - when /undefined class\/module (\S+)/ - @name = $1 - else - @name = nil - end - @buf = buf - end - - # The name of the unknown thing. - # - # Class name for unknown objects; variable name for unknown - # constants. - attr_reader :name - - # Buffer contained the marshalled, unknown object. - attr_reader :buf - - def self._load(s) # :nodoc: - begin - Marshal::load(s) - rescue NameError, ArgumentError - DRbUnknown.new($!, s) - end - end - - def _dump(lv) # :nodoc: - @buf - end - - # Attempt to load the wrapped marshalled object again. - # - # If the class of the object is now known locally, the object - # will be unmarshalled and returned. Otherwise, a new - # but identical DRbUnknown object will be returned. - def reload - self.class._load(@buf) - end - - # Create a DRbUnknownError exception containing this object. - def exception - DRbUnknownError.new(self) - end - end - - # An Array wrapper that can be sent to another server via DRb. - # - # All entries in the array will be dumped or be references that point to - # the local server. - - class DRbArray - - # Creates a new DRbArray that either dumps or wraps all the items in the - # Array +ary+ so they can be loaded by a remote DRb server. - - def initialize(ary) - @ary = ary.collect { |obj| - if obj.kind_of? DRbUndumped - DRbObject.new(obj) - else - begin - Marshal.dump(obj) - obj - rescue - DRbObject.new(obj) - end - end - } - end - - def self._load(s) # :nodoc: - Marshal::load(s) - end - - def _dump(lv) # :nodoc: - Marshal.dump(@ary) - end - end - - # Handler for sending and receiving drb messages. - # - # This takes care of the low-level marshalling and unmarshalling - # of drb requests and responses sent over the wire between server - # and client. This relieves the implementor of a new drb - # protocol layer with having to deal with these details. - # - # The user does not have to directly deal with this object in - # normal use. - class DRbMessage - def initialize(config) # :nodoc: - @load_limit = config[:load_limit] - @argc_limit = config[:argc_limit] - end - - def dump(obj, error=false) # :nodoc: - case obj - when DRbUndumped - obj = make_proxy(obj, error) - when Object - # nothing - else - obj = make_proxy(obj, error) - end - begin - str = Marshal::dump(obj) - rescue - str = Marshal::dump(make_proxy(obj, error)) - end - [str.size].pack('N') + str - end - - def load(soc) # :nodoc: - begin - sz = soc.read(4) # sizeof (N) - rescue - raise(DRbConnError, $!.message, $!.backtrace) - end - raise(DRbConnError, 'connection closed') if sz.nil? - raise(DRbConnError, 'premature header') if sz.size < 4 - sz = sz.unpack('N')[0] - raise(DRbConnError, "too large packet #{sz}") if @load_limit < sz - begin - str = soc.read(sz) - rescue - raise(DRbConnError, $!.message, $!.backtrace) - end - raise(DRbConnError, 'connection closed') if str.nil? - raise(DRbConnError, 'premature marshal format(can\'t read)') if str.size < sz - DRb.mutex.synchronize do - begin - Marshal::load(str) - rescue NameError, ArgumentError - DRbUnknown.new($!, str) - end - end - end - - def send_request(stream, ref, msg_id, arg, b) # :nodoc: - ary = [] - ary.push(dump(ref.__drbref)) - ary.push(dump(msg_id.id2name)) - ary.push(dump(arg.length)) - arg.each do |e| - ary.push(dump(e)) - end - ary.push(dump(b)) - stream.write(ary.join('')) - rescue - raise(DRbConnError, $!.message, $!.backtrace) - end - - def recv_request(stream) # :nodoc: - ref = load(stream) - ro = DRb.to_obj(ref) - msg = load(stream) - argc = load(stream) - raise(DRbConnError, "too many arguments") if @argc_limit < argc - argv = Array.new(argc, nil) - argc.times do |n| - argv[n] = load(stream) - end - block = load(stream) - return ro, msg, argv, block - end - - def send_reply(stream, succ, result) # :nodoc: - stream.write(dump(succ) + dump(result, !succ)) - rescue - raise(DRbConnError, $!.message, $!.backtrace) - end - - def recv_reply(stream) # :nodoc: - succ = load(stream) - result = load(stream) - [succ, result] - end - - private - def make_proxy(obj, error=false) # :nodoc: - if error - DRbRemoteError.new(obj) - else - DRbObject.new(obj) - end - end - end - - # Module managing the underlying network protocol(s) used by drb. - # - # By default, drb uses the DRbTCPSocket protocol. Other protocols - # can be defined. A protocol must define the following class methods: - # - # [open(uri, config)] Open a client connection to the server at +uri+, - # using configuration +config+. Return a protocol - # instance for this connection. - # [open_server(uri, config)] Open a server listening at +uri+, - # using configuration +config+. Return a - # protocol instance for this listener. - # [uri_option(uri, config)] Take a URI, possibly containing an option - # component (e.g. a trailing '?param=val'), - # and return a [uri, option] tuple. - # - # All of these methods should raise a DRbBadScheme error if the URI - # does not identify the protocol they support (e.g. "druby:" for - # the standard Ruby protocol). This is how the DRbProtocol module, - # given a URI, determines which protocol implementation serves that - # protocol. - # - # The protocol instance returned by #open_server must have the - # following methods: - # - # [accept] Accept a new connection to the server. Returns a protocol - # instance capable of communicating with the client. - # [close] Close the server connection. - # [uri] Get the URI for this server. - # - # The protocol instance returned by #open must have the following methods: - # - # [send_request (ref, msg_id, arg, b)] - # Send a request to +ref+ with the given message id and arguments. - # This is most easily implemented by calling DRbMessage.send_request, - # providing a stream that sits on top of the current protocol. - # [recv_reply] - # Receive a reply from the server and return it as a [success-boolean, - # reply-value] pair. This is most easily implemented by calling - # DRb.recv_reply, providing a stream that sits on top of the - # current protocol. - # [alive?] - # Is this connection still alive? - # [close] - # Close this connection. - # - # The protocol instance returned by #open_server().accept() must have - # the following methods: - # - # [recv_request] - # Receive a request from the client and return a [object, message, - # args, block] tuple. This is most easily implemented by calling - # DRbMessage.recv_request, providing a stream that sits on top of - # the current protocol. - # [send_reply(succ, result)] - # Send a reply to the client. This is most easily implemented - # by calling DRbMessage.send_reply, providing a stream that sits - # on top of the current protocol. - # [close] - # Close this connection. - # - # A new protocol is registered with the DRbProtocol module using - # the add_protocol method. - # - # For examples of other protocols, see DRbUNIXSocket in drb/unix.rb, - # and HTTP0 in sample/http0.rb and sample/http0serv.rb in the full - # drb distribution. - module DRbProtocol - - # Add a new protocol to the DRbProtocol module. - def add_protocol(prot) - @protocol.push(prot) - end - module_function :add_protocol - - # Open a client connection to +uri+ with the configuration +config+. - # - # The DRbProtocol module asks each registered protocol in turn to - # try to open the URI. Each protocol signals that it does not handle that - # URI by raising a DRbBadScheme error. If no protocol recognises the - # URI, then a DRbBadURI error is raised. If a protocol accepts the - # URI, but an error occurs in opening it, a DRbConnError is raised. - def open(uri, config, first=true) - @protocol.each do |prot| - begin - return prot.open(uri, config) - rescue DRbBadScheme - rescue DRbConnError - raise($!) - rescue - raise(DRbConnError, "#{uri} - #{$!.inspect}") - end - end - if first && (config[:auto_load] != false) - auto_load(uri) - return open(uri, config, false) - end - raise DRbBadURI, 'can\'t parse uri:' + uri - end - module_function :open - - # Open a server listening for connections at +uri+ with - # configuration +config+. - # - # The DRbProtocol module asks each registered protocol in turn to - # try to open a server at the URI. Each protocol signals that it does - # not handle that URI by raising a DRbBadScheme error. If no protocol - # recognises the URI, then a DRbBadURI error is raised. If a protocol - # accepts the URI, but an error occurs in opening it, the underlying - # error is passed on to the caller. - def open_server(uri, config, first=true) - @protocol.each do |prot| - begin - return prot.open_server(uri, config) - rescue DRbBadScheme - end - end - if first && (config[:auto_load] != false) - auto_load(uri) - return open_server(uri, config, false) - end - raise DRbBadURI, 'can\'t parse uri:' + uri - end - module_function :open_server - - # Parse +uri+ into a [uri, option] pair. - # - # The DRbProtocol module asks each registered protocol in turn to - # try to parse the URI. Each protocol signals that it does not handle that - # URI by raising a DRbBadScheme error. If no protocol recognises the - # URI, then a DRbBadURI error is raised. - def uri_option(uri, config, first=true) - @protocol.each do |prot| - begin - uri, opt = prot.uri_option(uri, config) - # opt = nil if opt == '' - return uri, opt - rescue DRbBadScheme - end - end - if first && (config[:auto_load] != false) - auto_load(uri) - return uri_option(uri, config, false) - end - raise DRbBadURI, 'can\'t parse uri:' + uri - end - module_function :uri_option - - def auto_load(uri) # :nodoc: - if /\Adrb([a-z0-9]+):/ =~ uri - require("drb/#{$1}") rescue nil - end - end - module_function :auto_load - end - - # The default drb protocol which communicates over a TCP socket. - # - # The DRb TCP protocol URI looks like: - # druby://:?. The option is optional. - - class DRbTCPSocket - # :stopdoc: - private - def self.parse_uri(uri) - if /\Adruby:\/\/(.*?):(\d+)(\?(.*))?\z/ =~ uri - host = $1 - port = $2.to_i - option = $4 - [host, port, option] - else - raise(DRbBadScheme, uri) unless uri.start_with?('druby:') - raise(DRbBadURI, 'can\'t parse uri:' + uri) - end - end - - public - - # Open a client connection to +uri+ (DRb URI string) using configuration - # +config+. - # - # This can raise DRb::DRbBadScheme or DRb::DRbBadURI if +uri+ is not for a - # recognized protocol. See DRb::DRbServer.new for information on built-in - # URI protocols. - def self.open(uri, config) - host, port, = parse_uri(uri) - soc = TCPSocket.open(host, port) - self.new(uri, soc, config) - end - - # Returns the hostname of this server - def self.getservername - host = Socket::gethostname - begin - Socket::getaddrinfo(host, nil, - Socket::AF_UNSPEC, - Socket::SOCK_STREAM, - 0, - Socket::AI_PASSIVE)[0][3] - rescue - 'localhost' - end - end - - # For the families available for +host+, returns a TCPServer on +port+. - # If +port+ is 0 the first available port is used. IPv4 servers are - # preferred over IPv6 servers. - def self.open_server_inaddr_any(host, port) - infos = Socket::getaddrinfo(host, nil, - Socket::AF_UNSPEC, - Socket::SOCK_STREAM, - 0, - Socket::AI_PASSIVE) - families = Hash[*infos.collect { |af, *_| af }.uniq.zip([]).flatten] - return TCPServer.open('0.0.0.0', port) if families.has_key?('AF_INET') - return TCPServer.open('::', port) if families.has_key?('AF_INET6') - return TCPServer.open(port) - # :stopdoc: - end - - # Open a server listening for connections at +uri+ using - # configuration +config+. - def self.open_server(uri, config) - uri = 'druby://:0' unless uri - host, port, _ = parse_uri(uri) - config = {:tcp_original_host => host}.update(config) - if host.size == 0 - host = getservername - soc = open_server_inaddr_any(host, port) - else - soc = TCPServer.open(host, port) - end - port = soc.addr[1] if port == 0 - config[:tcp_port] = port - uri = "druby://#{host}:#{port}" - self.new(uri, soc, config) - end - - # Parse +uri+ into a [uri, option] pair. - def self.uri_option(uri, config) - host, port, option = parse_uri(uri) - return "druby://#{host}:#{port}", option - end - - # Create a new DRbTCPSocket instance. - # - # +uri+ is the URI we are connected to. - # +soc+ is the tcp socket we are bound to. +config+ is our - # configuration. - def initialize(uri, soc, config={}) - @uri = uri - @socket = soc - @config = config - @acl = config[:tcp_acl] - @msg = DRbMessage.new(config) - set_sockopt(@socket) - @shutdown_pipe_r, @shutdown_pipe_w = IO.pipe - end - - # Get the URI that we are connected to. - attr_reader :uri - - # Get the address of our TCP peer (the other end of the socket - # we are bound to. - def peeraddr - @socket.peeraddr - end - - # Get the socket. - def stream; @socket; end - - # On the client side, send a request to the server. - def send_request(ref, msg_id, arg, b) - @msg.send_request(stream, ref, msg_id, arg, b) - end - - # On the server side, receive a request from the client. - def recv_request - @msg.recv_request(stream) - end - - # On the server side, send a reply to the client. - def send_reply(succ, result) - @msg.send_reply(stream, succ, result) - end - - # On the client side, receive a reply from the server. - def recv_reply - @msg.recv_reply(stream) - end - - public - - # Close the connection. - # - # If this is an instance returned by #open_server, then this stops - # listening for new connections altogether. If this is an instance - # returned by #open or by #accept, then it closes this particular - # client-server session. - def close - shutdown - if @socket - @socket.close - @socket = nil - end - close_shutdown_pipe - end - - def close_shutdown_pipe - @shutdown_pipe_w.close - @shutdown_pipe_r.close - end - private :close_shutdown_pipe - - # On the server side, for an instance returned by #open_server, - # accept a client connection and return a new instance to handle - # the server's side of this client-server session. - def accept - while true - s = accept_or_shutdown - return nil unless s - break if (@acl ? @acl.allow_socket?(s) : true) - s.close - end - if @config[:tcp_original_host].to_s.size == 0 - uri = "druby://#{s.addr[3]}:#{@config[:tcp_port]}" - else - uri = @uri - end - self.class.new(uri, s, @config) - end - - def accept_or_shutdown - readables, = IO.select([@socket, @shutdown_pipe_r]) - if readables.include? @shutdown_pipe_r - return nil - end - @socket.accept - end - private :accept_or_shutdown - - # Graceful shutdown - def shutdown - @shutdown_pipe_w.close - end - - # Check to see if this connection is alive. - def alive? - return false unless @socket - if @socket.to_io.wait_readable(0) - close - return false - end - true - end - - def set_sockopt(soc) # :nodoc: - soc.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) - rescue IOError, Errno::ECONNRESET, Errno::EINVAL - # closed/shutdown socket, ignore error - end - end - - module DRbProtocol - @protocol = [DRbTCPSocket] # default - end - - class DRbURIOption # :nodoc: I don't understand the purpose of this class... - def initialize(option) - @option = option.to_s - end - attr_reader :option - def to_s; @option; end - - def ==(other) - return false unless DRbURIOption === other - @option == other.option - end - - def hash - @option.hash - end - - alias eql? == - end - - # Object wrapping a reference to a remote drb object. - # - # Method calls on this object are relayed to the remote - # object that this object is a stub for. - class DRbObject - - # Unmarshall a marshalled DRbObject. - # - # If the referenced object is located within the local server, then - # the object itself is returned. Otherwise, a new DRbObject is - # created to act as a stub for the remote referenced object. - def self._load(s) - uri, ref = Marshal.load(s) - - if DRb.here?(uri) - obj = DRb.to_obj(ref) - return obj - end - - self.new_with(uri, ref) - end - - # Creates a DRb::DRbObject given the reference information to the remote - # host +uri+ and object +ref+. - - def self.new_with(uri, ref) - it = self.allocate - it.instance_variable_set(:@uri, uri) - it.instance_variable_set(:@ref, ref) - it - end - - # Create a new DRbObject from a URI alone. - def self.new_with_uri(uri) - self.new(nil, uri) - end - - # Marshall this object. - # - # The URI and ref of the object are marshalled. - def _dump(lv) - Marshal.dump([@uri, @ref]) - end - - # Create a new remote object stub. - # - # +obj+ is the (local) object we want to create a stub for. Normally - # this is +nil+. +uri+ is the URI of the remote object that this - # will be a stub for. - def initialize(obj, uri=nil) - @uri = nil - @ref = nil - case obj - when Object - is_nil = obj.nil? - when BasicObject - is_nil = false - end - - if is_nil - return if uri.nil? - @uri, option = DRbProtocol.uri_option(uri, DRb.config) - @ref = DRbURIOption.new(option) unless option.nil? - else - @uri = uri ? uri : (DRb.uri rescue nil) - @ref = obj ? DRb.to_id(obj) : nil - end - end - - # Get the URI of the remote object. - def __drburi - @uri - end - - # Get the reference of the object, if local. - def __drbref - @ref - end - - undef :to_s - undef :to_a if respond_to?(:to_a) - - # Routes respond_to? to the referenced remote object. - def respond_to?(msg_id, priv=false) - case msg_id - when :_dump - true - when :marshal_dump - false - else - method_missing(:respond_to?, msg_id, priv) - end - end - - # Routes method calls to the referenced remote object. - ruby2_keywords def method_missing(msg_id, *a, &b) - if DRb.here?(@uri) - obj = DRb.to_obj(@ref) - DRb.current_server.check_insecure_method(obj, msg_id) - return obj.__send__(msg_id, *a, &b) - end - - succ, result = self.class.with_friend(@uri) do - DRbConn.open(@uri) do |conn| - conn.send_message(self, msg_id, a, b) - end - end - - if succ - return result - elsif DRbUnknown === result - raise result - else - bt = self.class.prepare_backtrace(@uri, result) - result.set_backtrace(bt + caller) - raise result - end - end - - # Given the +uri+ of another host executes the block provided. - def self.with_friend(uri) # :nodoc: - friend = DRb.fetch_server(uri) - return yield() unless friend - - save = Thread.current['DRb'] - Thread.current['DRb'] = { 'server' => friend } - return yield - ensure - Thread.current['DRb'] = save if friend - end - - # Returns a modified backtrace from +result+ with the +uri+ where each call - # in the backtrace came from. - def self.prepare_backtrace(uri, result) # :nodoc: - prefix = "(#{uri}) " - bt = [] - result.backtrace.each do |x| - break if /`__send__'$/ =~ x - if /\A\(druby:\/\// =~ x - bt.push(x) - else - bt.push(prefix + x) - end - end - bt - end - - def pretty_print(q) # :nodoc: - q.pp_object(self) - end - - def pretty_print_cycle(q) # :nodoc: - q.object_address_group(self) { - q.breakable - q.text '...' - } - end - end - - class ThreadObject - include MonitorMixin - - def initialize(&blk) - super() - @wait_ev = new_cond - @req_ev = new_cond - @res_ev = new_cond - @status = :wait - @req = nil - @res = nil - @thread = Thread.new(self, &blk) - end - - def alive? - @thread.alive? - end - - def kill - @thread.kill - @thread.join - end - - def method_missing(msg, *arg, &blk) - synchronize do - @wait_ev.wait_until { @status == :wait } - @req = [msg] + arg - @status = :req - @req_ev.broadcast - @res_ev.wait_until { @status == :res } - value = @res - @req = @res = nil - @status = :wait - @wait_ev.broadcast - return value - end - end - - def _execute() - synchronize do - @req_ev.wait_until { @status == :req } - @res = yield(@req) - @status = :res - @res_ev.signal - end - end - end - - # Class handling the connection between a DRbObject and the - # server the real object lives on. - # - # This class maintains a pool of connections, to reduce the - # overhead of starting and closing down connections for each - # method call. - # - # This class is used internally by DRbObject. The user does - # not normally need to deal with it directly. - class DRbConn - POOL_SIZE = 16 # :nodoc: - - def self.make_pool - ThreadObject.new do |queue| - pool = [] - while true - queue._execute do |message| - case(message[0]) - when :take then - remote_uri = message[1] - conn = nil - new_pool = [] - pool.each do |c| - if conn.nil? and c.uri == remote_uri - conn = c if c.alive? - else - new_pool.push c - end - end - pool = new_pool - conn - when :store then - conn = message[1] - pool.unshift(conn) - pool.pop.close while pool.size > POOL_SIZE - conn - else - nil - end - end - end - end - end - @pool_proxy = nil - - def self.stop_pool - @pool_proxy&.kill - @pool_proxy = nil - end - - def self.open(remote_uri) # :nodoc: - begin - @pool_proxy = make_pool unless @pool_proxy&.alive? - - conn = @pool_proxy.take(remote_uri) - conn = self.new(remote_uri) unless conn - succ, result = yield(conn) - return succ, result - - ensure - if conn - if succ - @pool_proxy.store(conn) - else - conn.close - end - end - end - end - - def initialize(remote_uri) # :nodoc: - @uri = remote_uri - @protocol = DRbProtocol.open(remote_uri, DRb.config) - end - attr_reader :uri # :nodoc: - - def send_message(ref, msg_id, arg, block) # :nodoc: - @protocol.send_request(ref, msg_id, arg, block) - @protocol.recv_reply - end - - def close # :nodoc: - @protocol.close - @protocol = nil - end - - def alive? # :nodoc: - return false unless @protocol - @protocol.alive? - end - end - - # Class representing a drb server instance. - # - # A DRbServer must be running in the local process before any incoming - # dRuby calls can be accepted, or any local objects can be passed as - # dRuby references to remote processes, even if those local objects are - # never actually called remotely. You do not need to start a DRbServer - # in the local process if you are only making outgoing dRuby calls - # passing marshalled parameters. - # - # Unless multiple servers are being used, the local DRbServer is normally - # started by calling DRb.start_service. - class DRbServer - @@acl = nil - @@idconv = DRbIdConv.new - @@secondary_server = nil - @@argc_limit = 256 - @@load_limit = 0xffffffff - @@verbose = false - - # Set the default value for the :argc_limit option. - # - # See #new(). The initial default value is 256. - def self.default_argc_limit(argc) - @@argc_limit = argc - end - - # Set the default value for the :load_limit option. - # - # See #new(). The initial default value is 25 MB. - def self.default_load_limit(sz) - @@load_limit = sz - end - - # Set the default access control list to +acl+. The default ACL is +nil+. - # - # See also DRb::ACL and #new() - def self.default_acl(acl) - @@acl = acl - end - - # Set the default value for the :id_conv option. - # - # See #new(). The initial default value is a DRbIdConv instance. - def self.default_id_conv(idconv) - @@idconv = idconv - end - - # Set the default value of the :verbose option. - # - # See #new(). The initial default value is false. - def self.verbose=(on) - @@verbose = on - end - - # Get the default value of the :verbose option. - def self.verbose - @@verbose - end - - def self.make_config(hash={}) # :nodoc: - default_config = { - :idconv => @@idconv, - :verbose => @@verbose, - :tcp_acl => @@acl, - :load_limit => @@load_limit, - :argc_limit => @@argc_limit, - } - default_config.update(hash) - end - - # Create a new DRbServer instance. - # - # +uri+ is the URI to bind to. This is normally of the form - # 'druby://:' where is a hostname of - # the local machine. If nil, then the system's default hostname - # will be bound to, on a port selected by the system; these value - # can be retrieved from the +uri+ attribute. 'druby:' specifies - # the default dRuby transport protocol: another protocol, such - # as 'drbunix:', can be specified instead. - # - # +front+ is the front object for the server, that is, the object - # to which remote method calls on the server will be passed. If - # nil, then the server will not accept remote method calls. - # - # If +config_or_acl+ is a hash, it is the configuration to - # use for this server. The following options are recognised: - # - # :idconv :: an id-to-object conversion object. This defaults - # to an instance of the class DRb::DRbIdConv. - # :verbose :: if true, all unsuccessful remote calls on objects - # in the server will be logged to $stdout. false - # by default. - # :tcp_acl :: the access control list for this server. See - # the ACL class from the main dRuby distribution. - # :load_limit :: the maximum message size in bytes accepted by - # the server. Defaults to 25 MB (26214400). - # :argc_limit :: the maximum number of arguments to a remote - # method accepted by the server. Defaults to - # 256. - # The default values of these options can be modified on - # a class-wide basis by the class methods #default_argc_limit, - # #default_load_limit, #default_acl, #default_id_conv, - # and #verbose= - # - # If +config_or_acl+ is not a hash, but is not nil, it is - # assumed to be the access control list for this server. - # See the :tcp_acl option for more details. - # - # If no other server is currently set as the primary server, - # this will become the primary server. - # - # The server will immediately start running in its own thread. - def initialize(uri=nil, front=nil, config_or_acl=nil) - if Hash === config_or_acl - config = config_or_acl.dup - else - acl = config_or_acl || @@acl - config = { - :tcp_acl => acl - } - end - - @config = self.class.make_config(config) - - @protocol = DRbProtocol.open_server(uri, @config) - @uri = @protocol.uri - @exported_uri = [@uri] - - @front = front - @idconv = @config[:idconv] - - @grp = ThreadGroup.new - @thread = run - - DRb.regist_server(self) - end - - # The URI of this DRbServer. - attr_reader :uri - - # The main thread of this DRbServer. - # - # This is the thread that listens for and accepts connections - # from clients, not that handles each client's request-response - # session. - attr_reader :thread - - # The front object of the DRbServer. - # - # This object receives remote method calls made on the server's - # URI alone, with an object id. - attr_reader :front - - # The configuration of this DRbServer - attr_reader :config - - # Set whether to operate in verbose mode. - # - # In verbose mode, failed calls are logged to stdout. - def verbose=(v); @config[:verbose]=v; end - - # Get whether the server is in verbose mode. - # - # In verbose mode, failed calls are logged to stdout. - def verbose; @config[:verbose]; end - - # Is this server alive? - def alive? - @thread.alive? - end - - # Is +uri+ the URI for this server? - def here?(uri) - @exported_uri.include?(uri) - end - - # Stop this server. - def stop_service - DRb.remove_server(self) - if Thread.current['DRb'] && Thread.current['DRb']['server'] == self - Thread.current['DRb']['stop_service'] = true - else - shutdown - end - end - - # Convert a dRuby reference to the local object it refers to. - def to_obj(ref) - return front if ref.nil? - return front[ref.to_s] if DRbURIOption === ref - @idconv.to_obj(ref) - end - - # Convert a local object to a dRuby reference. - def to_id(obj) - return nil if obj.__id__ == front.__id__ - @idconv.to_id(obj) - end - - private - - def shutdown - current = Thread.current - if @protocol.respond_to? :shutdown - @protocol.shutdown - else - [@thread, *@grp.list].each { |thread| - thread.kill unless thread == current # xxx: Thread#kill - } - end - @thread.join unless @thread == current - end - - ## - # Starts the DRb main loop in a new thread. - - def run - Thread.start do - begin - while main_loop - end - ensure - @protocol.close if @protocol - end - end - end - - # List of insecure methods. - # - # These methods are not callable via dRuby. - INSECURE_METHOD = [ - :__send__ - ] - - # Has a method been included in the list of insecure methods? - def insecure_method?(msg_id) - INSECURE_METHOD.include?(msg_id) - end - - # Coerce an object to a string, providing our own representation if - # to_s is not defined for the object. - def any_to_s(obj) - "#{obj}:#{obj.class}" - rescue - Kernel.instance_method(:to_s).bind_call(obj) - end - - # Check that a method is callable via dRuby. - # - # +obj+ is the object we want to invoke the method on. +msg_id+ is the - # method name, as a Symbol. - # - # If the method is an insecure method (see #insecure_method?) a - # SecurityError is thrown. If the method is private or undefined, - # a NameError is thrown. - def check_insecure_method(obj, msg_id) - return true if Proc === obj && msg_id == :__drb_yield - raise(ArgumentError, "#{any_to_s(msg_id)} is not a symbol") unless Symbol == msg_id.class - raise(SecurityError, "insecure method `#{msg_id}'") if insecure_method?(msg_id) - - case obj - when Object - if obj.private_methods.include?(msg_id) - desc = any_to_s(obj) - raise NoMethodError, "private method `#{msg_id}' called for #{desc}" - elsif obj.protected_methods.include?(msg_id) - desc = any_to_s(obj) - raise NoMethodError, "protected method `#{msg_id}' called for #{desc}" - else - true - end - else - if Kernel.instance_method(:private_methods).bind(obj).call.include?(msg_id) - desc = any_to_s(obj) - raise NoMethodError, "private method `#{msg_id}' called for #{desc}" - elsif Kernel.instance_method(:protected_methods).bind(obj).call.include?(msg_id) - desc = any_to_s(obj) - raise NoMethodError, "protected method `#{msg_id}' called for #{desc}" - else - true - end - end - end - public :check_insecure_method - - class InvokeMethod # :nodoc: - def initialize(drb_server, client) - @drb_server = drb_server - @client = client - end - - def perform - begin - setup_message - ensure - @result = nil - @succ = false - end - - if @block - @result = perform_with_block - else - @result = perform_without_block - end - @succ = true - case @result - when Array - if @msg_id == :to_ary - @result = DRbArray.new(@result) - end - end - return @succ, @result - rescue NoMemoryError, SystemExit, SystemStackError, SecurityError - raise - rescue Exception - @result = $! - return @succ, @result - end - - private - def init_with_client - obj, msg, argv, block = @client.recv_request - @obj = obj - @msg_id = msg.intern - @argv = argv - @block = block - end - - def check_insecure_method - @drb_server.check_insecure_method(@obj, @msg_id) - end - - def setup_message - init_with_client - check_insecure_method - end - - def perform_without_block - if Proc === @obj && @msg_id == :__drb_yield - if @argv.size == 1 - ary = @argv - else - ary = [@argv] - end - ary.collect(&@obj)[0] - else - @obj.__send__(@msg_id, *@argv) - end - end - - end - - require_relative 'invokemethod' - class InvokeMethod - include InvokeMethod18Mixin - end - - def error_print(exception) - exception.backtrace.inject(true) do |first, x| - if first - $stderr.puts "#{x}: #{exception} (#{exception.class})" - else - $stderr.puts "\tfrom #{x}" - end - false - end - end - - # The main loop performed by a DRbServer's internal thread. - # - # Accepts a connection from a client, and starts up its own - # thread to handle it. This thread loops, receiving requests - # from the client, invoking them on a local object, and - # returning responses, until the client closes the connection - # or a local method call fails. - def main_loop - client0 = @protocol.accept - return nil if !client0 - Thread.start(client0) do |client| - @grp.add Thread.current - Thread.current['DRb'] = { 'client' => client , - 'server' => self } - DRb.mutex.synchronize do - client_uri = client.uri - @exported_uri << client_uri unless @exported_uri.include?(client_uri) - end - _last_invoke_method = nil - loop do - begin - succ = false - invoke_method = InvokeMethod.new(self, client) - succ, result = invoke_method.perform - error_print(result) if !succ && verbose - unless DRbConnError === result && result.message == 'connection closed' - client.send_reply(succ, result) - end - rescue Exception => e - error_print(e) if verbose - ensure - _last_invoke_method = invoke_method - client.close unless succ - if Thread.current['DRb']['stop_service'] - shutdown - break - end - break unless succ - end - end - end - end - end - - @primary_server = nil - - # Start a dRuby server locally. - # - # The new dRuby server will become the primary server, even - # if another server is currently the primary server. - # - # +uri+ is the URI for the server to bind to. If nil, - # the server will bind to random port on the default local host - # name and use the default dRuby protocol. - # - # +front+ is the server's front object. This may be nil. - # - # +config+ is the configuration for the new server. This may - # be nil. - # - # See DRbServer::new. - def start_service(uri=nil, front=nil, config=nil) - @primary_server = DRbServer.new(uri, front, config) - end - module_function :start_service - - # The primary local dRuby server. - # - # This is the server created by the #start_service call. - attr_accessor :primary_server - module_function :primary_server=, :primary_server - - # Get the 'current' server. - # - # In the context of execution taking place within the main - # thread of a dRuby server (typically, as a result of a remote - # call on the server or one of its objects), the current - # server is that server. Otherwise, the current server is - # the primary server. - # - # If the above rule fails to find a server, a DRbServerNotFound - # error is raised. - def current_server - drb = Thread.current['DRb'] - server = (drb && drb['server']) ? drb['server'] : @primary_server - raise DRbServerNotFound unless server - return server - end - module_function :current_server - - # Stop the local dRuby server. - # - # This operates on the primary server. If there is no primary - # server currently running, it is a noop. - def stop_service - @primary_server.stop_service if @primary_server - @primary_server = nil - end - module_function :stop_service - - # Get the URI defining the local dRuby space. - # - # This is the URI of the current server. See #current_server. - def uri - drb = Thread.current['DRb'] - client = (drb && drb['client']) - if client - uri = client.uri - return uri if uri - end - current_server.uri - end - module_function :uri - - # Is +uri+ the URI for the current local server? - def here?(uri) - current_server.here?(uri) rescue false - # (current_server.uri rescue nil) == uri - end - module_function :here? - - # Get the configuration of the current server. - # - # If there is no current server, this returns the default configuration. - # See #current_server and DRbServer::make_config. - def config - current_server.config - rescue - DRbServer.make_config - end - module_function :config - - # Get the front object of the current server. - # - # This raises a DRbServerNotFound error if there is no current server. - # See #current_server. - def front - current_server.front - end - module_function :front - - # Convert a reference into an object using the current server. - # - # This raises a DRbServerNotFound error if there is no current server. - # See #current_server. - def to_obj(ref) - current_server.to_obj(ref) - end - - # Get a reference id for an object using the current server. - # - # This raises a DRbServerNotFound error if there is no current server. - # See #current_server. - def to_id(obj) - current_server.to_id(obj) - end - module_function :to_id - module_function :to_obj - - # Get the thread of the primary server. - # - # This returns nil if there is no primary server. See #primary_server. - def thread - @primary_server ? @primary_server.thread : nil - end - module_function :thread - - # Set the default id conversion object. - # - # This is expected to be an instance such as DRb::DRbIdConv that responds to - # #to_id and #to_obj that can convert objects to and from DRb references. - # - # See DRbServer#default_id_conv. - def install_id_conv(idconv) - DRbServer.default_id_conv(idconv) - end - module_function :install_id_conv - - # Set the default ACL to +acl+. - # - # See DRb::DRbServer.default_acl. - def install_acl(acl) - DRbServer.default_acl(acl) - end - module_function :install_acl - - @mutex = Thread::Mutex.new - def mutex # :nodoc: - @mutex - end - module_function :mutex - - @server = {} - # Registers +server+ with DRb. - # - # This is called when a new DRb::DRbServer is created. - # - # If there is no primary server then +server+ becomes the primary server. - # - # Example: - # - # require 'drb' - # - # s = DRb::DRbServer.new # automatically calls regist_server - # DRb.fetch_server s.uri #=> # - def regist_server(server) - @server[server.uri] = server - mutex.synchronize do - @primary_server = server unless @primary_server - end - end - module_function :regist_server - - # Removes +server+ from the list of registered servers. - def remove_server(server) - @server.delete(server.uri) - mutex.synchronize do - if @primary_server == server - @primary_server = nil - end - end - end - module_function :remove_server - - # Retrieves the server with the given +uri+. - # - # See also regist_server and remove_server. - def fetch_server(uri) - @server[uri] - end - module_function :fetch_server -end - -# :stopdoc: -DRbObject = DRb::DRbObject -DRbUndumped = DRb::DRbUndumped -DRbIdConv = DRb::DRbIdConv diff --git a/lib/drb/eq.rb b/lib/drb/eq.rb deleted file mode 100644 index 15ca5cae42aa32..00000000000000 --- a/lib/drb/eq.rb +++ /dev/null @@ -1,15 +0,0 @@ -# frozen_string_literal: false -module DRb - class DRbObject # :nodoc: - def ==(other) - return false unless DRbObject === other - (@ref == other.__drbref) && (@uri == other.__drburi) - end - - def hash - [@uri, @ref].hash - end - - alias eql? == - end -end diff --git a/lib/drb/extserv.rb b/lib/drb/extserv.rb deleted file mode 100644 index 9523fe84e35b81..00000000000000 --- a/lib/drb/extserv.rb +++ /dev/null @@ -1,44 +0,0 @@ -# frozen_string_literal: false -=begin - external service - Copyright (c) 2000,2002 Masatoshi SEKI -=end - -require_relative 'drb' -require 'monitor' - -module DRb - class ExtServ - include MonitorMixin - include DRbUndumped - - def initialize(there, name, server=nil) - super() - @server = server || DRb::primary_server - @name = name - ro = DRbObject.new(nil, there) - synchronize do - @invoker = ro.register(name, DRbObject.new(self, @server.uri)) - end - end - attr_reader :server - - def front - DRbObject.new(nil, @server.uri) - end - - def stop_service - synchronize do - @invoker.unregister(@name) - server = @server - @server = nil - server.stop_service - true - end - end - - def alive? - @server ? @server.alive? : false - end - end -end diff --git a/lib/drb/extservm.rb b/lib/drb/extservm.rb deleted file mode 100644 index 9333a108e5dfa8..00000000000000 --- a/lib/drb/extservm.rb +++ /dev/null @@ -1,94 +0,0 @@ -# frozen_string_literal: false -=begin - external service manager - Copyright (c) 2000 Masatoshi SEKI -=end - -require_relative 'drb' -require 'monitor' - -module DRb - class ExtServManager - include DRbUndumped - include MonitorMixin - - @@command = {} - - def self.command - @@command - end - - def self.command=(cmd) - @@command = cmd - end - - def initialize - super() - @cond = new_cond - @servers = {} - @waiting = [] - @queue = Thread::Queue.new - @thread = invoke_thread - @uri = nil - end - attr_accessor :uri - - def service(name) - synchronize do - while true - server = @servers[name] - return server if server && server.alive? # server may be `false' - invoke_service(name) - @cond.wait - end - end - end - - def register(name, ro) - synchronize do - @servers[name] = ro - @cond.signal - end - self - end - alias regist register - - def unregister(name) - synchronize do - @servers.delete(name) - end - end - alias unregist unregister - - private - def invoke_thread - Thread.new do - while name = @queue.pop - invoke_service_command(name, @@command[name]) - end - end - end - - def invoke_service(name) - @queue.push(name) - end - - def invoke_service_command(name, command) - raise "invalid command. name: #{name}" unless command - synchronize do - return if @servers.include?(name) - @servers[name] = false - end - uri = @uri || DRb.uri - if command.respond_to? :to_ary - command = command.to_ary + [uri, name] - pid = spawn(*command) - else - pid = spawn("#{command} #{uri} #{name}") - end - th = Process.detach(pid) - th[:drb_service] = name - th - end - end -end diff --git a/lib/drb/gw.rb b/lib/drb/gw.rb deleted file mode 100644 index 65a525476ec549..00000000000000 --- a/lib/drb/gw.rb +++ /dev/null @@ -1,161 +0,0 @@ -# frozen_string_literal: false -require_relative 'drb' -require 'monitor' - -module DRb - - # Gateway id conversion forms a gateway between different DRb protocols or - # networks. - # - # The gateway needs to install this id conversion and create servers for - # each of the protocols or networks it will be a gateway between. It then - # needs to create a server that attaches to each of these networks. For - # example: - # - # require 'drb/drb' - # require 'drb/unix' - # require 'drb/gw' - # - # DRb.install_id_conv DRb::GWIdConv.new - # gw = DRb::GW.new - # s1 = DRb::DRbServer.new 'drbunix:/path/to/gateway', gw - # s2 = DRb::DRbServer.new 'druby://example:10000', gw - # - # s1.thread.join - # s2.thread.join - # - # Each client must register services with the gateway, for example: - # - # DRb.start_service 'drbunix:', nil # an anonymous server - # gw = DRbObject.new nil, 'drbunix:/path/to/gateway' - # gw[:unix] = some_service - # DRb.thread.join - - class GWIdConv < DRbIdConv - def to_obj(ref) # :nodoc: - if Array === ref && ref[0] == :DRbObject - return DRbObject.new_with(ref[1], ref[2]) - end - super(ref) - end - end - - # The GW provides a synchronized store for participants in the gateway to - # communicate. - - class GW - include MonitorMixin - - # Creates a new GW - - def initialize - super() - @hash = {} - end - - # Retrieves +key+ from the GW - - def [](key) - synchronize do - @hash[key] - end - end - - # Stores value +v+ at +key+ in the GW - - def []=(key, v) - synchronize do - @hash[key] = v - end - end - end - - class DRbObject # :nodoc: - def self._load(s) - uri, ref = Marshal.load(s) - if DRb.uri == uri - return ref ? DRb.to_obj(ref) : DRb.front - end - - self.new_with(DRb.uri, [:DRbObject, uri, ref]) - end - - def _dump(lv) - if DRb.uri == @uri - if Array === @ref && @ref[0] == :DRbObject - Marshal.dump([@ref[1], @ref[2]]) - else - Marshal.dump([@uri, @ref]) # ?? - end - else - Marshal.dump([DRb.uri, [:DRbObject, @uri, @ref]]) - end - end - end -end - -=begin -DRb.install_id_conv(DRb::GWIdConv.new) - -front = DRb::GW.new - -s1 = DRb::DRbServer.new('drbunix:/tmp/gw_b_a', front) -s2 = DRb::DRbServer.new('drbunix:/tmp/gw_b_c', front) - -s1.thread.join -s2.thread.join -=end - -=begin -# foo.rb - -require 'drb/drb' - -class Foo - include DRbUndumped - def initialize(name, peer=nil) - @name = name - @peer = peer - end - - def ping(obj) - puts "#{@name}: ping: #{obj.inspect}" - @peer.ping(self) if @peer - end -end -=end - -=begin -# gw_a.rb -require 'drb/unix' -require 'foo' - -obj = Foo.new('a') -DRb.start_service("drbunix:/tmp/gw_a", obj) - -robj = DRbObject.new_with_uri('drbunix:/tmp/gw_b_a') -robj[:a] = obj - -DRb.thread.join -=end - -=begin -# gw_c.rb -require 'drb/unix' -require 'foo' - -foo = Foo.new('c', nil) - -DRb.start_service("drbunix:/tmp/gw_c", nil) - -robj = DRbObject.new_with_uri("drbunix:/tmp/gw_b_c") - -puts "c->b" -a = robj[:a] -sleep 2 - -a.ping(foo) - -DRb.thread.join -=end - diff --git a/lib/drb/invokemethod.rb b/lib/drb/invokemethod.rb deleted file mode 100644 index 0fae6d52b6a1c8..00000000000000 --- a/lib/drb/invokemethod.rb +++ /dev/null @@ -1,35 +0,0 @@ -# frozen_string_literal: false -# for ruby-1.8.0 - -module DRb # :nodoc: all - class DRbServer - module InvokeMethod18Mixin - def block_yield(x) - if x.size == 1 && x[0].class == Array - x[0] = DRbArray.new(x[0]) - end - @block.call(*x) - end - - def perform_with_block - @obj.__send__(@msg_id, *@argv) do |*x| - jump_error = nil - begin - block_value = block_yield(x) - rescue LocalJumpError - jump_error = $! - end - if jump_error - case jump_error.reason - when :break - break(jump_error.exit_value) - else - raise jump_error - end - end - block_value - end - end - end - end -end diff --git a/lib/drb/observer.rb b/lib/drb/observer.rb deleted file mode 100644 index 0fb7301edfb12f..00000000000000 --- a/lib/drb/observer.rb +++ /dev/null @@ -1,26 +0,0 @@ -# frozen_string_literal: false -require 'observer' - -module DRb - # The Observable module extended to DRb. See Observable for details. - module DRbObservable - include Observable - - # Notifies observers of a change in state. See also - # Observable#notify_observers - def notify_observers(*arg) - if defined? @observer_state and @observer_state - if defined? @observer_peers - @observer_peers.each do |observer, method| - begin - observer.__send__(method, *arg) - rescue - delete_observer(observer) - end - end - end - @observer_state = false - end - end - end -end diff --git a/lib/drb/ssl.rb b/lib/drb/ssl.rb deleted file mode 100644 index 392d6560e9e0d9..00000000000000 --- a/lib/drb/ssl.rb +++ /dev/null @@ -1,354 +0,0 @@ -# frozen_string_literal: false -require 'socket' -require 'openssl' -require_relative 'drb' -require 'singleton' - -module DRb - - # The protocol for DRb over an SSL socket - # - # The URI for a DRb socket over SSL is: - # drbssl://:?. The option is optional - class DRbSSLSocket < DRbTCPSocket - - # SSLConfig handles the needed SSL information for establishing a - # DRbSSLSocket connection, including generating the X509 / RSA pair. - # - # An instance of this config can be passed to DRbSSLSocket.new, - # DRbSSLSocket.open and DRbSSLSocket.open_server - # - # See DRb::DRbSSLSocket::SSLConfig.new for more details - class SSLConfig - - # Default values for a SSLConfig instance. - # - # See DRb::DRbSSLSocket::SSLConfig.new for more details - DEFAULT = { - :SSLCertificate => nil, - :SSLPrivateKey => nil, - :SSLClientCA => nil, - :SSLCACertificatePath => nil, - :SSLCACertificateFile => nil, - :SSLTmpDhCallback => nil, - :SSLVerifyMode => ::OpenSSL::SSL::VERIFY_NONE, - :SSLVerifyDepth => nil, - :SSLVerifyCallback => nil, # custom verification - :SSLCertificateStore => nil, - # Must specify if you use auto generated certificate. - :SSLCertName => nil, # e.g. [["CN","fqdn.example.com"]] - :SSLCertComment => "Generated by Ruby/OpenSSL" - } - - # Create a new DRb::DRbSSLSocket::SSLConfig instance - # - # The DRb::DRbSSLSocket will take either a +config+ Hash or an instance - # of SSLConfig, and will setup the certificate for its session for the - # configuration. If want it to generate a generic certificate, the bare - # minimum is to provide the :SSLCertName - # - # === Config options - # - # From +config+ Hash: - # - # :SSLCertificate :: - # An instance of OpenSSL::X509::Certificate. If this is not provided, - # then a generic X509 is generated, with a correspond :SSLPrivateKey - # - # :SSLPrivateKey :: - # A private key instance, like OpenSSL::PKey::RSA. This key must be - # the key that signed the :SSLCertificate - # - # :SSLClientCA :: - # An OpenSSL::X509::Certificate, or Array of certificates that will - # used as ClientCAs in the SSL Context - # - # :SSLCACertificatePath :: - # A path to the directory of CA certificates. The certificates must - # be in PEM format. - # - # :SSLCACertificateFile :: - # A path to a CA certificate file, in PEM format. - # - # :SSLTmpDhCallback :: - # A DH callback. See OpenSSL::SSL::SSLContext.tmp_dh_callback - # - # :SSLMinVersion :: - # This is the minimum SSL version to allow. See - # OpenSSL::SSL::SSLContext#min_version=. - # - # :SSLMaxVersion :: - # This is the maximum SSL version to allow. See - # OpenSSL::SSL::SSLContext#max_version=. - # - # :SSLVerifyMode :: - # This is the SSL verification mode. See OpenSSL::SSL::VERIFY_* for - # available modes. The default is OpenSSL::SSL::VERIFY_NONE - # - # :SSLVerifyDepth :: - # Number of CA certificates to walk, when verifying a certificate - # chain. - # - # :SSLVerifyCallback :: - # A callback to be used for additional verification. See - # OpenSSL::SSL::SSLContext.verify_callback - # - # :SSLCertificateStore :: - # A OpenSSL::X509::Store used for verification of certificates - # - # :SSLCertName :: - # Issuer name for the certificate. This is required when generating - # the certificate (if :SSLCertificate and :SSLPrivateKey were not - # given). The value of this is to be an Array of pairs: - # - # [["C", "Raleigh"], ["ST","North Carolina"], - # ["CN","fqdn.example.com"]] - # - # See also OpenSSL::X509::Name - # - # :SSLCertComment :: - # A comment to be used for generating the certificate. The default is - # "Generated by Ruby/OpenSSL" - # - # - # === Example - # - # These values can be added after the fact, like a Hash. - # - # require 'drb/ssl' - # c = DRb::DRbSSLSocket::SSLConfig.new {} - # c[:SSLCertificate] = - # OpenSSL::X509::Certificate.new(File.read('mycert.crt')) - # c[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(File.read('mycert.key')) - # c[:SSLVerifyMode] = OpenSSL::SSL::VERIFY_PEER - # c[:SSLCACertificatePath] = "/etc/ssl/certs/" - # c.setup_certificate - # - # or - # - # require 'drb/ssl' - # c = DRb::DRbSSLSocket::SSLConfig.new({ - # :SSLCertName => [["CN" => DRb::DRbSSLSocket.getservername]] - # }) - # c.setup_certificate - # - def initialize(config) - @config = config - @cert = config[:SSLCertificate] - @pkey = config[:SSLPrivateKey] - @ssl_ctx = nil - end - - # A convenience method to access the values like a Hash - def [](key); - @config[key] || DEFAULT[key] - end - - # Connect to IO +tcp+, with context of the current certificate - # configuration - def connect(tcp) - ssl = ::OpenSSL::SSL::SSLSocket.new(tcp, @ssl_ctx) - ssl.sync = true - ssl.connect - ssl - end - - # Accept connection to IO +tcp+, with context of the current certificate - # configuration - def accept(tcp) - ssl = OpenSSL::SSL::SSLSocket.new(tcp, @ssl_ctx) - ssl.sync = true - ssl.accept - ssl - end - - # Ensures that :SSLCertificate and :SSLPrivateKey have been provided - # or that a new certificate is generated with the other parameters - # provided. - def setup_certificate - if @cert && @pkey - return - end - - rsa = OpenSSL::PKey::RSA.new(2048){|p, n| - next unless self[:verbose] - case p - when 0; $stderr.putc "." # BN_generate_prime - when 1; $stderr.putc "+" # BN_generate_prime - when 2; $stderr.putc "*" # searching good prime, - # n = #of try, - # but also data from BN_generate_prime - when 3; $stderr.putc "\n" # found good prime, n==0 - p, n==1 - q, - # but also data from BN_generate_prime - else; $stderr.putc "*" # BN_generate_prime - end - } - - cert = OpenSSL::X509::Certificate.new - cert.version = 3 - cert.serial = 0 - name = OpenSSL::X509::Name.new(self[:SSLCertName]) - cert.subject = name - cert.issuer = name - cert.not_before = Time.now - cert.not_after = Time.now + (365*24*60*60) - cert.public_key = rsa.public_key - - ef = OpenSSL::X509::ExtensionFactory.new(nil,cert) - cert.extensions = [ - ef.create_extension("basicConstraints","CA:FALSE"), - ef.create_extension("subjectKeyIdentifier", "hash") ] - ef.issuer_certificate = cert - cert.add_extension(ef.create_extension("authorityKeyIdentifier", - "keyid:always,issuer:always")) - if comment = self[:SSLCertComment] - cert.add_extension(ef.create_extension("nsComment", comment)) - end - cert.sign(rsa, "SHA256") - - @cert = cert - @pkey = rsa - end - - # Establish the OpenSSL::SSL::SSLContext with the configuration - # parameters provided. - def setup_ssl_context - ctx = ::OpenSSL::SSL::SSLContext.new - ctx.cert = @cert - ctx.key = @pkey - ctx.min_version = self[:SSLMinVersion] - ctx.max_version = self[:SSLMaxVersion] - ctx.client_ca = self[:SSLClientCA] - ctx.ca_path = self[:SSLCACertificatePath] - ctx.ca_file = self[:SSLCACertificateFile] - ctx.tmp_dh_callback = self[:SSLTmpDhCallback] - ctx.verify_mode = self[:SSLVerifyMode] - ctx.verify_depth = self[:SSLVerifyDepth] - ctx.verify_callback = self[:SSLVerifyCallback] - ctx.cert_store = self[:SSLCertificateStore] - @ssl_ctx = ctx - end - end - - # Parse the dRuby +uri+ for an SSL connection. - # - # Expects drbssl://... - # - # Raises DRbBadScheme or DRbBadURI if +uri+ is not matching or malformed - def self.parse_uri(uri) # :nodoc: - if /\Adrbssl:\/\/(.*?):(\d+)(\?(.*))?\z/ =~ uri - host = $1 - port = $2.to_i - option = $4 - [host, port, option] - else - raise(DRbBadScheme, uri) unless uri.start_with?('drbssl:') - raise(DRbBadURI, 'can\'t parse uri:' + uri) - end - end - - # Return an DRb::DRbSSLSocket instance as a client-side connection, - # with the SSL connected. This is called from DRb::start_service or while - # connecting to a remote object: - # - # DRb.start_service 'drbssl://localhost:0', front, config - # - # +uri+ is the URI we are connected to, - # 'drbssl://localhost:0' above, +config+ is our - # configuration. Either a Hash or DRb::DRbSSLSocket::SSLConfig - def self.open(uri, config) - host, port, = parse_uri(uri) - soc = TCPSocket.open(host, port) - ssl_conf = SSLConfig::new(config) - ssl_conf.setup_ssl_context - ssl = ssl_conf.connect(soc) - self.new(uri, ssl, ssl_conf, true) - end - - # Returns a DRb::DRbSSLSocket instance as a server-side connection, with - # the SSL connected. This is called from DRb::start_service or while - # connecting to a remote object: - # - # DRb.start_service 'drbssl://localhost:0', front, config - # - # +uri+ is the URI we are connected to, - # 'drbssl://localhost:0' above, +config+ is our - # configuration. Either a Hash or DRb::DRbSSLSocket::SSLConfig - def self.open_server(uri, config) - uri = 'drbssl://:0' unless uri - host, port, = parse_uri(uri) - if host.size == 0 - host = getservername - soc = open_server_inaddr_any(host, port) - else - soc = TCPServer.open(host, port) - end - port = soc.addr[1] if port == 0 - @uri = "drbssl://#{host}:#{port}" - - ssl_conf = SSLConfig.new(config) - ssl_conf.setup_certificate - ssl_conf.setup_ssl_context - self.new(@uri, soc, ssl_conf, false) - end - - # This is a convenience method to parse +uri+ and separate out any - # additional options appended in the +uri+. - # - # Returns an option-less uri and the option => [uri,option] - # - # The +config+ is completely unused, so passing nil is sufficient. - def self.uri_option(uri, config) # :nodoc: - host, port, option = parse_uri(uri) - return "drbssl://#{host}:#{port}", option - end - - # Create a DRb::DRbSSLSocket instance. - # - # +uri+ is the URI we are connected to. - # +soc+ is the tcp socket we are bound to. - # +config+ is our configuration. Either a Hash or SSLConfig - # +is_established+ is a boolean of whether +soc+ is currently established - # - # This is called automatically based on the DRb protocol. - def initialize(uri, soc, config, is_established) - @ssl = is_established ? soc : nil - super(uri, soc.to_io, config) - end - - # Returns the SSL stream - def stream; @ssl; end # :nodoc: - - # Closes the SSL stream before closing the dRuby connection. - def close # :nodoc: - if @ssl - @ssl.close - @ssl = nil - end - super - end - - def accept # :nodoc: - begin - while true - soc = accept_or_shutdown - return nil unless soc - break if (@acl ? @acl.allow_socket?(soc) : true) - soc.close - end - begin - ssl = @config.accept(soc) - rescue Exception - soc.close - raise - end - self.class.new(uri, ssl, @config, true) - rescue OpenSSL::SSL::SSLError - warn("#{$!.message} (#{$!.class})", uplevel: 0) if @config[:verbose] - retry - end - end - end - - DRbProtocol.add_protocol(DRbSSLSocket) -end diff --git a/lib/drb/timeridconv.rb b/lib/drb/timeridconv.rb deleted file mode 100644 index 3ead98a7f24527..00000000000000 --- a/lib/drb/timeridconv.rb +++ /dev/null @@ -1,97 +0,0 @@ -# frozen_string_literal: false -require_relative 'drb' -require 'monitor' - -module DRb - - # Timer id conversion keeps objects alive for a certain amount of time after - # their last access. The default time period is 600 seconds and can be - # changed upon initialization. - # - # To use TimerIdConv: - # - # DRb.install_id_conv TimerIdConv.new 60 # one minute - - class TimerIdConv < DRbIdConv - class TimerHolder2 # :nodoc: - include MonitorMixin - - class InvalidIndexError < RuntimeError; end - - def initialize(keeping=600) - super() - @sentinel = Object.new - @gc = {} - @renew = {} - @keeping = keeping - @expires = nil - end - - def add(obj) - synchronize do - rotate - key = obj.__id__ - @renew[key] = obj - invoke_keeper - return key - end - end - - def fetch(key) - synchronize do - rotate - obj = peek(key) - raise InvalidIndexError if obj == @sentinel - @renew[key] = obj # KeepIt - return obj - end - end - - private - def peek(key) - return @renew.fetch(key) { @gc.fetch(key, @sentinel) } - end - - def invoke_keeper - return if @expires - @expires = Time.now + @keeping - on_gc - end - - def on_gc - return unless Thread.main.alive? - return if @expires.nil? - Thread.new { rotate } if @expires < Time.now - ObjectSpace.define_finalizer(Object.new) {on_gc} - end - - def rotate - synchronize do - if @expires &.< Time.now - @gc = @renew # GCed - @renew = {} - @expires = @gc.empty? ? nil : Time.now + @keeping - end - end - end - end - - # Creates a new TimerIdConv which will hold objects for +keeping+ seconds. - def initialize(keeping=600) - @holder = TimerHolder2.new(keeping) - end - - def to_obj(ref) # :nodoc: - return super if ref.nil? - @holder.fetch(ref) - rescue TimerHolder2::InvalidIndexError - raise "invalid reference" - end - - def to_id(obj) # :nodoc: - return @holder.add(obj) - end - end -end - -# DRb.install_id_conv(TimerIdConv.new) diff --git a/lib/drb/unix.rb b/lib/drb/unix.rb deleted file mode 100644 index 1629ad3bcd04b0..00000000000000 --- a/lib/drb/unix.rb +++ /dev/null @@ -1,118 +0,0 @@ -# frozen_string_literal: false -require 'socket' -require_relative 'drb' -require 'tmpdir' - -raise(LoadError, "UNIXServer is required") unless defined?(UNIXServer) - -module DRb - - # Implements DRb over a UNIX socket - # - # DRb UNIX socket URIs look like drbunix:?. The - # option is optional. - - class DRbUNIXSocket < DRbTCPSocket - # :stopdoc: - def self.parse_uri(uri) - if /\Adrbunix:(.*?)(\?(.*))?\z/ =~ uri - filename = $1 - option = $3 - [filename, option] - else - raise(DRbBadScheme, uri) unless uri.start_with?('drbunix:') - raise(DRbBadURI, 'can\'t parse uri:' + uri) - end - end - - def self.open(uri, config) - filename, = parse_uri(uri) - soc = UNIXSocket.open(filename) - self.new(uri, soc, config) - end - - def self.open_server(uri, config) - filename, = parse_uri(uri) - if filename.size == 0 - soc = temp_server - filename = soc.path - uri = 'drbunix:' + soc.path - else - soc = UNIXServer.open(filename) - end - owner = config[:UNIXFileOwner] - group = config[:UNIXFileGroup] - if owner || group - require 'etc' - owner = Etc.getpwnam( owner ).uid if owner - group = Etc.getgrnam( group ).gid if group - File.chown owner, group, filename - end - mode = config[:UNIXFileMode] - File.chmod(mode, filename) if mode - - self.new(uri, soc, config, true) - end - - def self.uri_option(uri, config) - filename, option = parse_uri(uri) - return "drbunix:#{filename}", option - end - - def initialize(uri, soc, config={}, server_mode = false) - super(uri, soc, config) - set_sockopt(@socket) - @server_mode = server_mode - @acl = nil - end - - # import from tempfile.rb - Max_try = 10 - private - def self.temp_server - tmpdir = Dir::tmpdir - n = 0 - while true - begin - tmpname = sprintf('%s/druby%d.%d', tmpdir, $$, n) - lock = tmpname + '.lock' - unless File.exist?(tmpname) or File.exist?(lock) - Dir.mkdir(lock) - break - end - rescue - raise "cannot generate tempfile `%s'" % tmpname if n >= Max_try - #sleep(1) - end - n += 1 - end - soc = UNIXServer.new(tmpname) - Dir.rmdir(lock) - soc - end - - public - def close - return unless @socket - shutdown # DRbProtocol#shutdown - path = @socket.path if @server_mode - @socket.close - File.unlink(path) if @server_mode - @socket = nil - close_shutdown_pipe - end - - def accept - s = accept_or_shutdown - return nil unless s - self.class.new(nil, s, @config) - end - - def set_sockopt(soc) - # no-op for now - end - end - - DRbProtocol.add_protocol(DRbUNIXSocket) - # :startdoc: -end diff --git a/lib/drb/version.rb b/lib/drb/version.rb deleted file mode 100644 index 73fa4c18fd94dd..00000000000000 --- a/lib/drb/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -module DRb - VERSION = "2.2.0" -end diff --git a/lib/drb/weakidconv.rb b/lib/drb/weakidconv.rb deleted file mode 100644 index ecf0bf515fb9f1..00000000000000 --- a/lib/drb/weakidconv.rb +++ /dev/null @@ -1,59 +0,0 @@ -# frozen_string_literal: false -require_relative 'drb' -require 'monitor' - -module DRb - - # To use WeakIdConv: - # - # DRb.start_service(nil, nil, {:idconv => DRb::WeakIdConv.new}) - - class WeakIdConv < DRbIdConv - class WeakSet - include MonitorMixin - def initialize - super() - @immutable = {} - @map = ObjectSpace::WeakMap.new - end - - def add(obj) - synchronize do - begin - @map[obj] = self - rescue ArgumentError - @immutable[obj.__id__] = obj - end - return obj.__id__ - end - end - - def fetch(ref) - synchronize do - @immutable.fetch(ref) { - @map.each { |key, _| - return key if key.__id__ == ref - } - raise RangeError.new("invalid reference") - } - end - end - end - - def initialize() - super() - @weak_set = WeakSet.new - end - - def to_obj(ref) # :nodoc: - return super if ref.nil? - @weak_set.fetch(ref) - end - - def to_id(obj) # :nodoc: - return @weak_set.add(obj) - end - end -end - -# DRb.install_id_conv(WeakIdConv.new) diff --git a/test/drb/drbtest.rb b/test/drb/drbtest.rb deleted file mode 100644 index 72220f32ef8bfc..00000000000000 --- a/test/drb/drbtest.rb +++ /dev/null @@ -1,396 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' -require 'envutil' -require 'drb/drb' -require 'drb/extservm' -require 'timeout' - -module DRbTests - -class DRbService - @@ruby = [EnvUtil.rubybin] - @@ruby << "-d" if $DEBUG - def self.add_service_command(nm) - dir = File.dirname(File.expand_path(__FILE__)) - DRb::ExtServManager.command[nm] = @@ruby + ["#{dir}/#{nm}"] - end - - %w(ut_drb.rb ut_array.rb ut_port.rb ut_large.rb ut_safe1.rb ut_eq.rb).each do |nm| - add_service_command(nm) - end - - def initialize - @manager = DRb::ExtServManager.new - start - @manager.uri = server.uri - end - - def start - @server = DRb::DRbServer.new('druby://localhost:0', manager, {}) - end - - attr_reader :manager - attr_reader :server - - def ext_service(name) - EnvUtil.timeout(100, RuntimeError) do - manager.service(name) - end - end - - def finish - server.instance_variable_get(:@grp).list.each {|th| th.join } - server.stop_service - manager.instance_variable_get(:@queue)&.push(nil) - manager.instance_variable_get(:@thread)&.join - DRb::DRbConn.stop_pool - end -end - -class Onecky - include DRbUndumped - def initialize(n) - @num = n - end - - def to_i - @num.to_i - end - - def sleep(n) - Kernel.sleep(n) - to_i - end -end - -class FailOnecky < Onecky - class OneckyError < RuntimeError; end - def to_i - raise(OneckyError, @num.to_s) - end -end - -class XArray < Array - def initialize(ary) - ary.each do |x| - self.push(x) - end - end -end - -module DRbBase - def setup - @drb_service ||= DRbService.new - end - - def setup_service(service_name) - @service_name = service_name - @ext = @drb_service.ext_service(@service_name) - @there = @ext.front - end - - def teardown - return if @omitted - @ext.stop_service if defined?(@ext) && @ext - if defined?(@service_name) && @service_name - @drb_service.manager.unregist(@service_name) - while (@there&&@there.to_s rescue nil) - # nop - end - signal = /mswin|mingw/ =~ RUBY_PLATFORM ? :KILL : :TERM - Thread.list.each {|th| - if th.respond_to?(:pid) && th[:drb_service] == @service_name - 10.times do - begin - Process.kill signal, th.pid - break - rescue Errno::ESRCH - break - rescue Errno::EPERM # on Windows - sleep 0.1 - retry - end - end - th.join - end - } - end - @drb_service.finish - DRb::DRbConn.stop_pool - end -end - -module DRbCore - include DRbBase - - def test_00_DRbObject - ro = DRbObject.new(nil, 'druby://localhost:12345') - assert_equal('druby://localhost:12345', ro.__drburi) - assert_equal(nil, ro.__drbref) - - ro = DRbObject.new_with_uri('druby://localhost:12345') - assert_equal('druby://localhost:12345', ro.__drburi) - assert_equal(nil, ro.__drbref) - - ro = DRbObject.new_with_uri('druby://localhost:12345?foobar') - assert_equal('druby://localhost:12345', ro.__drburi) - assert_equal(DRb::DRbURIOption.new('foobar'), ro.__drbref) - end - - def test_01 - assert_equal("hello", @there.hello) - onecky = Onecky.new('3') - assert_equal(6, @there.sample(onecky, 1, 2)) - ary = @there.to_a - assert_kind_of(DRb::DRbObject, ary) - - assert_respond_to(@there, [:to_a, true]) - assert_respond_to(@there, [:eval, true]) - assert_not_respond_to(@there, [:eval, false]) - assert_not_respond_to(@there, :eval) - end - - def test_01_02_loop - onecky = Onecky.new('3') - 50.times do - assert_equal(6, @there.sample(onecky, 1, 2)) - ary = @there.to_a - assert_kind_of(DRb::DRbObject, ary) - end - end - - def test_02_basic_object - obj = @there.basic_object - assert_kind_of(DRb::DRbObject, obj) - assert_equal(1, obj.foo) - assert_raise(NoMethodError){obj.prot} - assert_raise(NoMethodError){obj.priv} - end - - def test_02_unknown - obj = @there.unknown_class - assert_kind_of(DRb::DRbUnknown, obj) - assert_equal('DRbTests::Unknown2', obj.name) - - obj = @there.unknown_module - assert_kind_of(DRb::DRbUnknown, obj) - assert_equal('DRbTests::DRbEx::', obj.name) - - assert_raise(DRb::DRbUnknownError) do - @there.unknown_error - end - - onecky = FailOnecky.new('3') - - assert_raise(FailOnecky::OneckyError) do - @there.sample(onecky, 1, 2) - end - end - - def test_03 - assert_equal(8, @there.sum(1, 1, 1, 1, 1, 1, 1, 1)) - assert_raise(DRb::DRbConnError) do - @there.sum(1, 1, 1, 1, 1, 1, 1, 1, 1) - end - assert_raise(DRb::DRbConnError) do - @there.sum('1' * 4096) - end - end - - def test_04 - assert_respond_to(@there, 'sum') - assert_not_respond_to(@there, "foobar") - end - - def test_05_eq - a = @there.to_a[0] - b = @there.to_a[0] - assert_not_same(a, b) - assert_equal(a, b) - assert_equal(a, @there) - assert_equal(a.hash, b.hash) - assert_equal(a.hash, @there.hash) - assert_operator(a, :eql?, b) - assert_operator(a, :eql?, @there) - end - - def test_06_timeout - omit if RUBY_PLATFORM.include?("armv7l-linux") - omit if RUBY_PLATFORM.include?("sparc-solaris2.10") - omit if RUBY_PLATFORM.include?("freebsd") - omit if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # expecting a certain delay is difficult for --jit-wait CI - Timeout.timeout(60) do - ten = Onecky.new(10) - assert_raise(Timeout::Error) do - @there.do_timeout(ten) - end - assert_raise(Timeout::Error) do - @there.do_timeout(ten) - end - end - end - - def test_07_private_missing - e = assert_raise(NoMethodError) { - @there.method_missing(:eval, 'nil') - } - assert_match(/^private method \`eval\'/, e.message) - - e = assert_raise(NoMethodError) { - @there.call_private_method - } - assert_match(/^private method \`call_private_method\'/, e.message) - end - - def test_07_protected_missing - e = assert_raise(NoMethodError) { - @there.call_protected_method - } - assert_match(/^protected method \`call_protected_method\'/, e.message) - end - - def test_07_public_missing - e = assert_raise(NoMethodError) { - @there.method_missing(:undefined_method_test) - } - assert_match(/^undefined method \`undefined_method_test\'/, e.message) - end - - def test_07_send_missing - assert_raise(DRb::DRbConnError) do - @there.method_missing(:__send__, :to_s) - end - assert_equal(true, @there.missing) - end - - def test_08_here - ro = DRbObject.new(nil, DRb.uri) - assert_kind_of(String, ro.to_s) - - ro = DRbObject.new_with_uri(DRb.uri) - assert_kind_of(String, ro.to_s) - end - - def uri_concat_option(uri, opt) - "#{uri}?#{opt}" - end - - def test_09_option - uri = uri_concat_option(@there.__drburi, "foo") - ro = DRbObject.new_with_uri(uri) - assert_equal(ro.__drburi, @there.__drburi) - assert_equal(3, ro.size) - - uri = uri_concat_option(@there.__drburi, "") - ro = DRbObject.new_with_uri(uri) - assert_equal(ro.__drburi, @there.__drburi) - assert_equal(DRb::DRbURIOption.new(''), ro.__drbref) - - uri = uri_concat_option(@there.__drburi, "hello?world") - ro = DRbObject.new_with_uri(uri) - assert_equal(DRb::DRbURIOption.new('hello?world'), ro.__drbref) - - uri = uri_concat_option(@there.__drburi, "?hello?world") - ro = DRbObject.new_with_uri(uri) - assert_equal(DRb::DRbURIOption.new('?hello?world'), ro.__drbref) - end - - def test_10_yield - @there.simple_hash.each do |k, v| - assert_kind_of(String, k) - assert_kind_of(Symbol, v) - end - end - - def test_10_yield_undumped - @there.xarray2_hash.each do |k, v| - assert_kind_of(String, k) - assert_kind_of(DRbObject, v) - end - end - - def test_11_remote_no_method_error - assert_raise(DRb::DRbRemoteError) do - @there.remote_no_method_error - end - begin - @there.remote_no_method_error - rescue - error = $! - assert_match(/^undefined method .*\(NoMethodError\)/, error.message) - assert_equal('NoMethodError', error.reason) - end - end -end - -module DRbAry - include DRbBase - - def test_01 - assert_kind_of(DRb::DRbObject, @there) - end - - def test_02_collect - ary = @there.collect do |x| x + x end - assert_kind_of(Array, ary) - assert_equal([2, 4, 'IIIIII', 8, 'fivefive', 12], ary) - end - - def test_03_redo - ary = [] - count = 0 - @there.each do |x| - count += 1 - ary.push x - redo if count == 3 - end - assert_equal([1, 2, 'III', 'III', 4, 'five', 6], ary) - end - - # retry in block is not supported on ruby 1.9 - #def test_04_retry - # retried = false - # ary = [] - # @there.each do |x| - # ary.push x - # if x == 4 && !retried - # retried = true - # retry - # end - # end - # assert_equal([1, 2, 'III', 4, 1, 2, 'III', 4, 'five', 6], ary) - #end - - def test_05_break - ary = [] - @there.each do |x| - ary.push x - break if x == 4 - end - assert_equal([1, 2, 'III', 4], ary) - end - - def test_06_next - ary = [] - @there.each do |x| - next if String === x - ary.push x - end - assert_equal([1, 2, 4, 6], ary) - end - - class_eval <\z/, server.any_to_s(BO.new)) - server.stop_service - server.thread.join - DRb::DRbConn.stop_pool - end -end - -class TestDRbTCP < Test::Unit::TestCase - def test_immediate_close - omit 'MinGW leaks a thread in this test' if /mingw/ =~ RUBY_PLATFORM - server = DRb::DRbServer.new('druby://localhost:0') - host, port, = DRb::DRbTCPSocket.send(:parse_uri, server.uri) - socket = TCPSocket.open host, port - socket.shutdown - socket.close - client = DRb::DRbTCPSocket.new(server.uri, socket) - assert client - ensure - client&.close - socket&.close - server&.stop_service - server&.thread&.join - DRb::DRbConn.stop_pool - end -end - -class TestBug16634 < Test::Unit::TestCase - include DRbBase - - def setup - super - setup_service 'ut_drb.rb' - end - - def test_bug16634 - assert_equal(42, @there.keyword_test1(a: 42)) - assert_equal("default", @there.keyword_test2) - assert_equal(42, @there.keyword_test2(b: 42)) - assert_equal({:a=>42, :b=>42}, @there.keyword_test3(a: 42, b: 42)) - end -end - -end diff --git a/test/drb/test_drbobject.rb b/test/drb/test_drbobject.rb deleted file mode 100644 index 2b0e2061ee4b5c..00000000000000 --- a/test/drb/test_drbobject.rb +++ /dev/null @@ -1,69 +0,0 @@ -require 'test/unit' -require 'drb' -require 'drb/timeridconv' -require 'drb/weakidconv' - -module DRbObjectTest - class Foo - def initialize - @foo = 'foo' - end - end - - def teardown - DRb.stop_service - DRb::DRbConn.stop_pool - end - - def drb_eq(obj) - proxy = DRbObject.new(obj) - assert_equal(obj, DRb.to_obj(proxy.__drbref)) - end - - def test_DRbObject_id_dereference - drb_eq(Foo.new) - drb_eq(Foo) - drb_eq(File) - drb_eq(Enumerable) - drb_eq(nil) - drb_eq(1) - drb_eq($stdout) - drb_eq([]) - end -end - -class TestDRbObject < Test::Unit::TestCase - include DRbObjectTest - - def setup - DRb.start_service - end -end - -class TestDRbObjectTimerIdConv < Test::Unit::TestCase - include DRbObjectTest - - def setup - @idconv = DRb::TimerIdConv.new - DRb.start_service(nil, nil, {:idconv => @idconv}) - end - - def teardown - super - # stop DRb::TimerIdConv::TimerHolder2#on_gc - @idconv.instance_eval do - @holder.instance_eval do - @expires = nil - end - end - GC.start - end -end - -class TestDRbObjectWeakIdConv < Test::Unit::TestCase - include DRbObjectTest - - def setup - DRb.start_service(nil, nil, {:idconv => DRb::WeakIdConv.new}) - end -end diff --git a/test/drb/test_drbssl.rb b/test/drb/test_drbssl.rb deleted file mode 100644 index f2d9a20271a59c..00000000000000 --- a/test/drb/test_drbssl.rb +++ /dev/null @@ -1,84 +0,0 @@ -# frozen_string_literal: false -require_relative 'drbtest' - -begin - require 'drb/ssl' -rescue LoadError -end - -module DRbTests - -if Object.const_defined?("OpenSSL") - - -class DRbSSLService < DRbService - %w(ut_drb_drbssl.rb ut_array_drbssl.rb).each do |nm| - add_service_command(nm) - end - - def start - config = Hash.new - - config[:SSLVerifyMode] = OpenSSL::SSL::VERIFY_PEER - config[:SSLVerifyCallback] = lambda{ |ok,x509_store| - true - } - if RUBY_PLATFORM.match?(/openbsd/) - config[:SSLMinVersion] = OpenSSL::SSL::TLS1_2_VERSION - config[:SSLMaxVersion] = OpenSSL::SSL::TLS1_2_VERSION - end - begin - data = open("sample.key"){|io| io.read } - config[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(data) - data = open("sample.crt"){|io| io.read } - config[:SSLCertificate] = OpenSSL::X509::Certificate.new(data) - rescue - # $stderr.puts "Switching to use self-signed certificate" - config[:SSLCertName] = - [ ["C","JP"], ["O","Foo.DRuby.Org"], ["CN", "Sample"] ] - end - - @server = DRb::DRbServer.new('drbssl://localhost:0', manager, config) - end -end - -class TestDRbSSLCore < Test::Unit::TestCase - include DRbCore - def setup - if RUBY_PLATFORM.match?(/mswin|mingw/) - @omitted = true - omit 'This test seems to randomly hang on Windows' - end - @drb_service = DRbSSLService.new - super - setup_service 'ut_drb_drbssl.rb' - end - - def test_02_unknown - end - - def test_01_02_loop - end - - def test_05_eq - end -end - -class TestDRbSSLAry < Test::Unit::TestCase - include DRbAry - def setup - if RUBY_PLATFORM.match?(/mswin|mingw/) - @omitted = true - omit 'This test seems to randomly hang on Windows' - end - LeakChecker.skip if defined?(LeakChecker) - @drb_service = DRbSSLService.new - super - setup_service 'ut_array_drbssl.rb' - end -end - - -end - -end diff --git a/test/drb/test_drbunix.rb b/test/drb/test_drbunix.rb deleted file mode 100644 index 95b3c3ca91a362..00000000000000 --- a/test/drb/test_drbunix.rb +++ /dev/null @@ -1,60 +0,0 @@ -# frozen_string_literal: false -require_relative 'drbtest' - -begin - require 'drb/unix' -rescue LoadError -end - -module DRbTests - -if Object.const_defined?("UNIXServer") - - -class DRbUNIXService < DRbService - %w(ut_drb_drbunix.rb ut_array_drbunix.rb).each do |nm| - add_service_command(nm) - end - - def start - @server = DRb::DRbServer.new('drbunix:', manager, {}) - end -end - -class TestDRbUNIXCore < Test::Unit::TestCase - include DRbCore - def setup - @drb_service = DRbUNIXService.new - super - setup_service 'ut_drb_drbunix.rb' - end - - def test_02_unknown - end - - def test_01_02_loop - end - - def test_05_eq - end - - def test_bad_uri - assert_raise(DRb::DRbBadURI) do - DRb::DRbServer.new("badfile\n""drbunix:") - end - end -end - -class TestDRbUNIXAry < Test::Unit::TestCase - include DRbAry - def setup - @drb_service = DRbUNIXService.new - super - setup_service 'ut_array_drbunix.rb' - end -end - - -end - -end diff --git a/test/drb/ut_array.rb b/test/drb/ut_array.rb deleted file mode 100644 index d13dda3d8e500a..00000000000000 --- a/test/drb/ut_array.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: false -require 'drb/drb' -require 'drb/extserv' - -if __FILE__ == $0 - def ARGV.shift - it = super() - raise "usage: #{$0} " unless it - it - end - - DRb.start_service('druby://localhost:0', [1, 2, 'III', 4, "five", 6]) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join - es.stop_service if es.alive? -end - diff --git a/test/drb/ut_array_drbssl.rb b/test/drb/ut_array_drbssl.rb deleted file mode 100644 index 778021a0b5f96a..00000000000000 --- a/test/drb/ut_array_drbssl.rb +++ /dev/null @@ -1,43 +0,0 @@ -# frozen_string_literal: false -require 'drb/drb' -require 'drb/extserv' -require 'drb/ssl' - -if __FILE__ == $0 - def ARGV.shift - it = super() - raise "usage: #{$0} " unless it - it - end - - module DRbTests - - TEST_KEY_DH1024 = OpenSSL::PKey::DH.new <<-_end_of_pem_ ------BEGIN DH PARAMETERS----- -MIGHAoGBAKnKQ8MNK6nYZzLrrcuTsLxuiJGXoOO5gT+tljOTbHBuiktdMTITzIY0 -pFxIvjG05D7HoBZQfrR0c92NGWPkAiCkhQKB8JCbPVzwNLDy6DZ0pmofDKrEsYHG -AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC ------END DH PARAMETERS----- - _end_of_pem_ - - end - - config = Hash.new - config[:SSLTmpDhCallback] = proc { DRbTests::TEST_KEY_DH1024 } - if RUBY_PLATFORM.match?(/openbsd/) - config[:SSLMinVersion] = OpenSSL::SSL::TLS1_2_VERSION - config[:SSLMaxVersion] = OpenSSL::SSL::TLS1_2_VERSION - end - config[:SSLVerifyMode] = OpenSSL::SSL::VERIFY_PEER - config[:SSLVerifyCallback] = lambda{|ok,x509_store| - true - } - config[:SSLCertName] = - [ ["C","JP"], ["O","Foo.DRuby.Org"], ["CN", "Sample"] ] - - DRb.start_service('drbssl://localhost:0', [1, 2, 'III', 4, "five", 6], config) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join - es.stop_service if es.alive? -end - diff --git a/test/drb/ut_array_drbunix.rb b/test/drb/ut_array_drbunix.rb deleted file mode 100644 index b656cdaddd8476..00000000000000 --- a/test/drb/ut_array_drbunix.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: false -require 'drb/drb' -require 'drb/extserv' - -if __FILE__ == $0 - def ARGV.shift - it = super() - raise "usage: #{$0} " unless it - it - end - - DRb.start_service('drbunix:', [1, 2, 'III', 4, "five", 6]) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join - es.stop_service if es.alive? -end - diff --git a/test/drb/ut_drb.rb b/test/drb/ut_drb.rb deleted file mode 100644 index 7c0603b009b221..00000000000000 --- a/test/drb/ut_drb.rb +++ /dev/null @@ -1,189 +0,0 @@ -# frozen_string_literal: false -require 'drb/drb' -require 'drb/extserv' -require 'timeout' - -module DRbTests - -class XArray < Array - def initialize(ary) - ary.each do |x| - self.push(x) - end - end -end - -class XArray2 < XArray - include DRbUndumped -end - -class Unknown2 - def initialize - @foo = 'unknown2' - end -end - -class DRbEx - include DRbUndumped - - class FooBar - def initialize - @foo = 'bar' - end - end - - class UError < RuntimeError; end - - def initialize - @xary2_hash = nil - @hash = nil - @hello = 'hello' - end - attr_reader :hello - - def sample(a, b, c) - a.to_i + b.to_i + c.to_i - end - - def sum(*a) - s = 0 - a.each do |e| - s += e.to_i - end - s - end - - def do_timeout(n) - Timeout.timeout(0.1) do - n.sleep(2) - end - end - - def unknown_module - FooBar.new - end - - class BO < ::BasicObject - def foo; 1 end - protected def prot; 2; end - private def priv; 3; end - end - def basic_object - @basic_object = BO.new - end - - def unknown_class - Unknown2.new - end - - def unknown_error - raise UError - end - - def remote_no_method_error - invoke_no_method(self) - end - - def test_yield - yield - yield([]) - yield(*[]) - end - - def echo_yield(*arg) - yield(*arg) - nil - end - - def echo_yield_0 - yield - nil - end - - def echo_yield_1(one) - yield(one) - nil - end - - def echo_yield_2(one, two) - yield(one, two) - nil - end - - def xarray_each - xary = [XArray.new([0])] - xary.each do |x| - yield(x) - end - nil - end - - def xarray2_hash - unless @xary2_hash - @xary2_hash = { "a" => XArray2.new([0]), "b" => XArray2.new([1]) } - end - DRbObject.new(@xary2_hash) - end - - def simple_hash - unless @hash - @hash = { 'a'=>:a, 'b'=>:b } - end - DRbObject.new(@hash) - end - - def [](key) - key.to_s - end - - def to_a - [self] - end - - def method_missing(msg, *a, &b) - if msg == :missing - return true - else - super(msg, *a, &b) - end - end - - def keyword_test1(a:) - a - end - - def keyword_test2(b: "default") - b - end - - def keyword_test3(**opt) - opt - end - - private - def call_private_method - true - end - - protected - def call_protected_method - true - end -end - -end - -if __FILE__ == $0 - def ARGV.shift - it = super() - raise "usage: #{$0} " unless it - it - end - - DRb::DRbServer.default_argc_limit(8) - DRb::DRbServer.default_load_limit(4096) - DRb.start_service('druby://localhost:0', DRbTests::DRbEx.new) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join - es.stop_service if es.alive? -end diff --git a/test/drb/ut_drb_drbssl.rb b/test/drb/ut_drb_drbssl.rb deleted file mode 100644 index c8251716d6d687..00000000000000 --- a/test/drb/ut_drb_drbssl.rb +++ /dev/null @@ -1,40 +0,0 @@ -# frozen_string_literal: false -require_relative "ut_drb" -require 'drb/ssl' - -if __FILE__ == $0 - def ARGV.shift - it = super() - raise "usage: #{$0} " unless it - it - end - - module DRbTests - - TEST_KEY_DH1024 = OpenSSL::PKey::DH.new <<-_end_of_pem_ ------BEGIN DH PARAMETERS----- -MIGHAoGBAKnKQ8MNK6nYZzLrrcuTsLxuiJGXoOO5gT+tljOTbHBuiktdMTITzIY0 -pFxIvjG05D7HoBZQfrR0c92NGWPkAiCkhQKB8JCbPVzwNLDy6DZ0pmofDKrEsYHG -AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC ------END DH PARAMETERS----- - _end_of_pem_ - - end - - config = Hash.new - config[:SSLTmpDhCallback] = proc { DRbTests::TEST_KEY_DH1024 } - config[:SSLVerifyMode] = OpenSSL::SSL::VERIFY_PEER - config[:SSLVerifyCallback] = lambda{|ok,x509_store| - true - } - config[:SSLCertName] = - [ ["C","JP"], ["O","Foo.DRuby.Org"], ["CN", "Sample"] ] - - DRb::DRbServer.default_argc_limit(8) - DRb::DRbServer.default_load_limit(4096) - DRb.start_service('drbssl://localhost:0', DRbTests::DRbEx.new, config) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join - es.stop_service if es.alive? -end - diff --git a/test/drb/ut_drb_drbunix.rb b/test/drb/ut_drb_drbunix.rb deleted file mode 100644 index ecf0920451a78d..00000000000000 --- a/test/drb/ut_drb_drbunix.rb +++ /dev/null @@ -1,18 +0,0 @@ -# frozen_string_literal: false -require "#{File.dirname(File.expand_path(__FILE__))}/ut_drb" - -if __FILE__ == $0 - def ARGV.shift - it = super() - raise "usage: #{$0} " unless it - it - end - - DRb::DRbServer.default_argc_limit(8) - DRb::DRbServer.default_load_limit(4096) - DRb.start_service('drbunix:', DRbTests::DRbEx.new) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join - es.stop_service if es.alive? -end - diff --git a/test/drb/ut_eq.rb b/test/drb/ut_eq.rb deleted file mode 100644 index 56285a384f35d5..00000000000000 --- a/test/drb/ut_eq.rb +++ /dev/null @@ -1,37 +0,0 @@ -# frozen_string_literal: false -require 'drb/drb' -require 'drb/extserv' - -module DRbTests - -class Foo - include DRbUndumped -end - -class Bar - include DRbUndumped - def initialize - @foo = Foo.new - end - attr_reader :foo - - def foo?(foo) - @foo == foo - end -end - -end - -if __FILE__ == $0 - def ARGV.shift - it = super() - raise "usage: #{$0} " unless it - it - end - - DRb.start_service('druby://localhost:0', DRbTests::Bar.new) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join - es.stop_service if es.alive? -end - diff --git a/test/drb/ut_large.rb b/test/drb/ut_large.rb deleted file mode 100644 index 9376ff119df45c..00000000000000 --- a/test/drb/ut_large.rb +++ /dev/null @@ -1,62 +0,0 @@ -# frozen_string_literal: false -require 'drb/drb' -require 'drb/extserv' -require 'timeout' - -module DRbTests - -class DRbLarge - include DRbUndumped - - def size(ary) - ary.size - end - - def sum(ary) - ary.inject(:+) - end - - def multiply(ary) - ary.inject(:*) - end - - def avg(ary) - return if ary.empty? - if ary.any? {|n| n.is_a? String} - raise TypeError - else - sum(ary).to_f / ary.count - end - end - - def median(ary) - return if ary.empty? - if ary.any? {|n| n.is_a? String} - raise TypeError - else - avg ary.sort[((ary.length - 1) / 2)..(ary.length / 2)] - end - end - - def arg_test(*arg) - # nop - end -end - -end - -if __FILE__ == $0 - def ARGV.shift - it = super() - raise "usage: #{$0} " unless it - it - end - - DRb::DRbServer.default_argc_limit(3) - DRb::DRbServer.default_load_limit(100000) - DRb.start_service('druby://localhost:0', DRbTests::DRbLarge.new) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join - es.stop_service if es.alive? -end - diff --git a/test/drb/ut_port.rb b/test/drb/ut_port.rb deleted file mode 100644 index d317a307cc12d4..00000000000000 --- a/test/drb/ut_port.rb +++ /dev/null @@ -1,16 +0,0 @@ -# frozen_string_literal: false -require 'drb/drb' -require 'drb/extserv' - -if __FILE__ == $0 - def ARGV.shift - it = super() - raise "usage: #{$0} " unless it - it - end - - DRb.start_service('druby://:8473', [1, 2, 'III', 4, "five", 6]) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join - es.stop_service if es.alive? -end diff --git a/test/drb/ut_safe1.rb b/test/drb/ut_safe1.rb deleted file mode 100644 index 4b16fa7d6d8eb7..00000000000000 --- a/test/drb/ut_safe1.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: false -require 'drb/drb' -require 'drb/extserv' - -if __FILE__ == $0 - def ARGV.shift - it = super() - raise "usage: #{$0} " unless it - it - end - - DRb.start_service('druby://localhost:0', [1, 2, 'III', 4, "five", 6], - {:safe_level => 1}) - es = DRb::ExtServ.new(ARGV.shift, ARGV.shift) - DRb.thread.join - es.stop_service if es.alive? -end diff --git a/test/drb/ut_timerholder.rb b/test/drb/ut_timerholder.rb deleted file mode 100644 index 1753b30c74a9f5..00000000000000 --- a/test/drb/ut_timerholder.rb +++ /dev/null @@ -1,74 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' -require 'drb/timeridconv' - -module DRbTests - -class TimerIdConvTest < Test::Unit::TestCase - def test_usecase_01 - keeping = 0.1 - idconv = DRb::TimerIdConv.new(keeping) - - key = idconv.to_id(self) - assert_equal(key, self.__id__) - sleep(keeping) - assert_equal(idconv.to_id(false), false.__id__) - assert_equal(idconv.to_obj(key), self) - sleep(keeping) - - assert_equal(idconv.to_obj(key), self) - sleep(keeping) - - assert_equal(idconv.to_id(true), true.__id__) - sleep(keeping) - - assert_raise do - assert_equal(idconv.to_obj(key), self) - end - - assert_raise do - assert_equal(idconv.to_obj(false.__id__), false) - end - - key = idconv.to_id(self) - assert_equal(key, self.__id__) - assert_equal(idconv.to_id(true), true.__id__) - sleep(keeping) - GC.start - sleep(keeping) - GC.start - assert_raise do - assert_equal(idconv.to_obj(key), self) - end - end - - def test_usecase_02 - keeping = 0.1 - idconv = DRb::TimerIdConv.new(keeping) - - key = idconv.to_id(self) - assert_equal(key, self.__id__) - sleep(keeping) - GC.start - sleep(keeping) - GC.start - assert_raise do - assert_equal(idconv.to_obj(key), self) - end - GC.start - - key = idconv.to_id(self) - assert_equal(key, self.__id__) - sleep(keeping) - GC.start - sleep(keeping) - GC.start - assert_raise do - assert_equal(idconv.to_obj(key), self) - end - end -end - - -end - From 87f16fbc6d21b5b20e38789dfd010e2b94f22efc Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 22 Jan 2024 10:10:39 +0900 Subject: [PATCH 369/640] spec/mspec/tool/wrap_with_guard.rb 'ruby_version_is ""..."3.4"' spec/ruby/library/drb/start_service_spec.rb --- spec/ruby/library/drb/start_service_spec.rb | 45 +++++++++++---------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/spec/ruby/library/drb/start_service_spec.rb b/spec/ruby/library/drb/start_service_spec.rb index 016c8b2cffbb73..1ed2081d80e266 100644 --- a/spec/ruby/library/drb/start_service_spec.rb +++ b/spec/ruby/library/drb/start_service_spec.rb @@ -1,28 +1,31 @@ require_relative '../../spec_helper' -require_relative 'fixtures/test_server' -require 'drb' -describe "DRb.start_service" do - before :each do - @server = DRb.start_service("druby://localhost:0", TestServer.new) - end +ruby_version_is ""..."3.4" do + require_relative 'fixtures/test_server' + require 'drb' - after :each do - DRb.stop_service if @server - end + describe "DRb.start_service" do + before :each do + @server = DRb.start_service("druby://localhost:0", TestServer.new) + end - it "runs a basic remote call" do - DRb.current_server.should == @server - obj = DRbObject.new(nil, @server.uri) - obj.add(1,2,3).should == 6 - end + after :each do + DRb.stop_service if @server + end + + it "runs a basic remote call" do + DRb.current_server.should == @server + obj = DRbObject.new(nil, @server.uri) + obj.add(1,2,3).should == 6 + end - it "runs a basic remote call passing a block" do - DRb.current_server.should == @server - obj = DRbObject.new(nil, @server.uri) - obj.add_yield(2) do |i| - i.should == 2 - i+1 - end.should == 4 + it "runs a basic remote call passing a block" do + DRb.current_server.should == @server + obj = DRbObject.new(nil, @server.uri) + obj.add_yield(2) do |i| + i.should == 2 + i+1 + end.should == 4 + end end end From 854b1f6072298ea96139e282d70e1276a959761e Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 22 Jan 2024 10:11:34 +0900 Subject: [PATCH 370/640] Document about drb at Ruby 3.4 --- doc/maintainers.md | 8 +++----- doc/standard_library.rdoc | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/doc/maintainers.md b/doc/maintainers.md index f53b6567b6c5d1..f4b09b2db607c5 100644 --- a/doc/maintainers.md +++ b/doc/maintainers.md @@ -114,11 +114,6 @@ have commit right, others don't. * https://github.com/ruby/digest * https://rubygems.org/gems/digest -#### lib/drb.rb, lib/drb/* -* Masatoshi SEKI (seki) -* https://github.com/ruby/drb -* https://rubygems.org/gems/drb - #### lib/erb.rb * Masatoshi SEKI (seki) * Takashi Kokubun (k0kubun) @@ -474,6 +469,9 @@ have commit right, others don't. #### rinda * https://github.com/ruby/rinda +#### drb +* https://github.com/ruby/drb + ## Platform Maintainers ### mswin64 (Microsoft Windows) * NAKAMURA Usaku (usa) diff --git a/doc/standard_library.rdoc b/doc/standard_library.rdoc index d97207b53504a6..4833defe45d9f6 100644 --- a/doc/standard_library.rdoc +++ b/doc/standard_library.rdoc @@ -39,7 +39,6 @@ CGI:: Support for the Common Gateway Interface protocol CSV:: Provides an interface to read and write CSV files and data 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 @@ -130,3 +129,4 @@ Observable:: Provides a mechanism for publish/subscribe pattern in Ruby Abbrev:: Calculates a set of unique abbreviations for a given set of strings resolv-replace.rb:: Replace Socket DNS with Resolv Rinda:: The Linda distributed computing paradigm in Ruby +DRb:: Distributed object system for Ruby From 220f7c9d8e5905bcb9dfceb9fa71628f1e9127f4 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 22 Jan 2024 10:11:52 +0900 Subject: [PATCH 371/640] Re-use drb from bundled gems --- common.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.mk b/common.mk index cae299cb8b25d5..4310042736da8e 100644 --- a/common.mk +++ b/common.mk @@ -1563,7 +1563,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 "hoe" "json-schema" "test-unit-rr" "drb" "ipaddr" "forwardable" "ruby2_keywords" + --install-dir .bundle --conservative "hoe" "json-schema" "test-unit-rr" "ipaddr" "forwardable" "ruby2_keywords" $(ACTIONS_ENDGROUP) PREPARE_BUNDLED_GEMS = test-bundled-gems-prepare From 52fc93cab71e56699fb2b216faca1216f8bfc862 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 22 Jan 2024 10:36:06 +0900 Subject: [PATCH 372/640] added redirect wrapper for envutil --- gems/lib/envutil.rb | 1 + 1 file changed, 1 insertion(+) create mode 100644 gems/lib/envutil.rb diff --git a/gems/lib/envutil.rb b/gems/lib/envutil.rb new file mode 100644 index 00000000000000..d684c22cf21182 --- /dev/null +++ b/gems/lib/envutil.rb @@ -0,0 +1 @@ +require_relative "../../tool/lib/envutil.rb" From 0fadac4c7d229fe077cc34cfc73a90a8e72fe245 Mon Sep 17 00:00:00 2001 From: git Date: Mon, 22 Jan 2024 02:09:35 +0000 Subject: [PATCH 373/640] Update bundled gems list at 52fc93cab71e56699fb2b216faca12 [ci skip] --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index 0bc75e0a1615c5..f9908a53a89526 100644 --- a/NEWS.md +++ b/NEWS.md @@ -54,6 +54,7 @@ The following bundled gems are promoted from default gems. * abbrev 0.1.2 * resolv-replace 0.1.1 * rinda 0.2.0 +* drb 2.2.0 See GitHub releases like [GitHub Releases of Logger](https://github.com/ruby/logger/releases) or changelog for details of the default gems or bundled gems. From 33290896dcf23e8f84f9626d87c6f1c4d7cfa04e Mon Sep 17 00:00:00 2001 From: KJ Tsanaktsidis Date: Mon, 22 Jan 2024 09:13:35 +1100 Subject: [PATCH 374/640] Disable NSS modules when using the leakchecker The leakchecker will report leaked file descriptors when tests do things like access `Etc.getgrgid`, for example, if NSS modules (like `sss`) handle these lookups by connecting to a daemon like `sssd` and leave the connection open. To address this, we can call glibc's `__nss_configure_lookup` to override NSS modules configured in /etc/nsswitch.conf and only use ordinary file/DNS lookups. (This is a cherry-pick of a patch applied to ruby/mspec here: https://github.com/ruby/mspec/pull/62) --- .../lib/mspec/runner/actions/leakchecker.rb | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/spec/mspec/lib/mspec/runner/actions/leakchecker.rb b/spec/mspec/lib/mspec/runner/actions/leakchecker.rb index 69181b71d3a4ad..9cf5cefa3fb163 100644 --- a/spec/mspec/lib/mspec/runner/actions/leakchecker.rb +++ b/spec/mspec/lib/mspec/runner/actions/leakchecker.rb @@ -301,6 +301,7 @@ def register end def start + disable_nss_modules @checker = LeakChecker.new end @@ -316,4 +317,58 @@ def after(state) end end end + + private + + # This function is intended to disable all NSS modules when ruby is compiled + # against glibc. NSS modules allow the system administrator to load custom + # shared objects into all processes using glibc, and use them to customise + # the behaviour of username, groupname, hostname, etc lookups. This is + # normally configured in the file /etc/nsswitch.conf. + # These modules often do things like open cache files or connect to system + # daemons like sssd or dbus, which of course means they have open file + # descriptors of their own. This can cause the leak-checking functionality + # in this file to report that such descriptors have been leaked, and fail + # the test suite. + # This function uses glibc's __nss_configure_lookup function to override any + # configuration in /etc/nsswitch.conf, and just use the built in files/dns + # name lookup functionality (which is of course perfectly sufficient for + # running ruby/spec). + def disable_nss_modules + begin + require 'fiddle' + rescue LoadError + # Make sure it's possible to run the test suite on a ruby implementation + # which does not (yet?) have Fiddle. + return + end + + begin + libc = Fiddle.dlopen(nil) + nss_configure_lookup = Fiddle::Function.new( + libc['__nss_configure_lookup'], + [Fiddle::Types::CONST_STRING, Fiddle::Types::CONST_STRING], + Fiddle::Types::INT + ) + rescue Fiddle::DLError + # We're not running with glibc - no need to do this. + return + end + + nss_configure_lookup.call 'passwd', 'files' + nss_configure_lookup.call 'shadow', 'files' + nss_configure_lookup.call 'group', 'files' + nss_configure_lookup.call 'hosts', 'files dns' + nss_configure_lookup.call 'services', 'files' + nss_configure_lookup.call 'netgroup', 'files' + nss_configure_lookup.call 'automount', 'files' + nss_configure_lookup.call 'aliases', 'files' + nss_configure_lookup.call 'ethers', 'files' + nss_configure_lookup.call 'gshadow', 'files' + nss_configure_lookup.call 'initgroups', 'files' + nss_configure_lookup.call 'networks', 'files dns' + nss_configure_lookup.call 'protocols', 'files' + nss_configure_lookup.call 'publickey', 'files' + nss_configure_lookup.call 'rpc', 'files' + end end From 4a11f50f79e7fd592a300f46302e11f56e04a983 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 22 Jan 2024 12:06:00 +0900 Subject: [PATCH 375/640] [DOC] Update command_injection.rdoc - Add missing `Kernel.exec` and `Kernel.spawn`. - Elaborate arguments that can cause injections. --- doc/command_injection.rdoc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/doc/command_injection.rdoc b/doc/command_injection.rdoc index 246b2e6afe0afd..ee33d4a04e6629 100644 --- a/doc/command_injection.rdoc +++ b/doc/command_injection.rdoc @@ -7,11 +7,17 @@ They should not be called with unknown or unsanitized commands. These methods include: +- Kernel.exec +- Kernel.spawn - Kernel.system -- Kernel.open - {\`command` (backtick method)}[rdoc-ref:Kernel#`] (also called by the expression %x[command]). -- IO.popen(command). +- IO.popen (when called with other than "-"). + +Some methods execute a system command only if the given path name starts +with a |: + +- Kernel.open(command). - IO.read(command). - IO.write(command). - IO.binread(command). @@ -21,7 +27,7 @@ These methods include: - URI.open(command). Note that some of these methods do not execute commands when called -from subclass \File: +from subclass +File+: - File.read(path). - File.write(path). From 5b109ff14d274d0599839c61c77b32628c2d1971 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 22 Jan 2024 11:13:53 +0900 Subject: [PATCH 376/640] [ruby/nkf] Bump up version to 0.2.0 https://github.com/ruby/nkf/commit/65506fecfd --- ext/nkf/nkf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/nkf/nkf.c b/ext/nkf/nkf.c index 73b616a54fd0bb..3d1ad42e9f457e 100644 --- a/ext/nkf/nkf.c +++ b/ext/nkf/nkf.c @@ -9,7 +9,7 @@ #define RUBY_NKF_REVISION "$Revision$" #define RUBY_NKF_VERSION NKF_VERSION " (" NKF_RELEASE_DATE ")" -#define NKF_GEM_VERSION "0.1.3" +#define NKF_GEM_VERSION "0.2.0" #include "ruby/ruby.h" #include "ruby/encoding.h" From 12e697f99d1b0ac541814c250d0ac21ace95bdbd Mon Sep 17 00:00:00 2001 From: git Date: Mon, 22 Jan 2024 03:31:13 +0000 Subject: [PATCH 377/640] Update default gems list at 5b109ff14d274d0599839c61c77b32 [ci skip] --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index f9908a53a89526..ab4c8e3e54bb84 100644 --- a/NEWS.md +++ b/NEWS.md @@ -30,6 +30,7 @@ The following default gems are updated. * io-console 0.7.2 * irb 1.11.1 * net-http 0.4.1 +* nkf 0.2.0 * reline 0.4.2 * stringio 3.1.1 * strscan 3.0.9 From ce5e7629b57904c34a529372f365e04d4f9abb06 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 02:58:55 +0000 Subject: [PATCH 378/640] Bump ruby/setup-ruby from 1.167.0 to 1.168.0 Bumps [ruby/setup-ruby](https://github.com/ruby/setup-ruby) from 1.167.0 to 1.168.0. - [Release notes](https://github.com/ruby/setup-ruby/releases) - [Commits](https://github.com/ruby/setup-ruby/compare/b203567269b5bbc256dbc1c84f7495913f977353...432702e864cadc1b56247e31aa341be5be3e129a) --- updated-dependencies: - dependency-name: ruby/setup-ruby dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/baseruby.yml | 2 +- .github/workflows/mingw.yml | 2 +- .github/workflows/rjit-bindgen.yml | 2 +- .github/workflows/spec_guards.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/baseruby.yml b/.github/workflows/baseruby.yml index a77fe3c56fd727..020d181adc25dd 100644 --- a/.github/workflows/baseruby.yml +++ b/.github/workflows/baseruby.yml @@ -57,7 +57,7 @@ jobs: - ruby-3.3 steps: - - uses: ruby/setup-ruby@b203567269b5bbc256dbc1c84f7495913f977353 # v1.167.0 + - uses: ruby/setup-ruby@432702e864cadc1b56247e31aa341be5be3e129a # v1.168.0 with: ruby-version: ${{ matrix.ruby }} bundler: none diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml index fecdd39fd818e9..e05c410db4415b 100644 --- a/.github/workflows/mingw.yml +++ b/.github/workflows/mingw.yml @@ -74,7 +74,7 @@ jobs: steps: - name: Set up Ruby & MSYS2 - uses: ruby/setup-ruby@b203567269b5bbc256dbc1c84f7495913f977353 # v1.167.0 + uses: ruby/setup-ruby@432702e864cadc1b56247e31aa341be5be3e129a # v1.168.0 with: ruby-version: ${{ matrix.baseruby }} diff --git a/.github/workflows/rjit-bindgen.yml b/.github/workflows/rjit-bindgen.yml index b64e34b4c19809..c7303827583e26 100644 --- a/.github/workflows/rjit-bindgen.yml +++ b/.github/workflows/rjit-bindgen.yml @@ -52,7 +52,7 @@ jobs: steps: - name: Set up Ruby - uses: ruby/setup-ruby@b203567269b5bbc256dbc1c84f7495913f977353 # v1.167.0 + uses: ruby/setup-ruby@432702e864cadc1b56247e31aa341be5be3e129a # v1.168.0 with: ruby-version: '3.1' diff --git a/.github/workflows/spec_guards.yml b/.github/workflows/spec_guards.yml index eb9e38bd8e3143..230ada8f09b815 100644 --- a/.github/workflows/spec_guards.yml +++ b/.github/workflows/spec_guards.yml @@ -48,7 +48,7 @@ jobs: steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - uses: ruby/setup-ruby@b203567269b5bbc256dbc1c84f7495913f977353 # v1.167.0 + - uses: ruby/setup-ruby@432702e864cadc1b56247e31aa341be5be3e129a # v1.168.0 with: ruby-version: ${{ matrix.ruby }} bundler: none From 6c0e58a54e3fda604386d9c409e2a9998bbc9352 Mon Sep 17 00:00:00 2001 From: KJ Tsanaktsidis Date: Mon, 22 Jan 2024 12:06:03 +1100 Subject: [PATCH 379/640] Make sure the correct error is raised for EAI_SYSTEM resolver fail In case of EAI_SYSTEM, getaddrinfo is supposed to set more detail in errno; however, because we call getaddrinfo on a thread now, and errno is threadlocal, that information is being lost. Instead, we just raise whatever errno happens to be on the calling thread (which can be something very confusing, like `ECHILD`). Fix it by explicitly propagating errno back to the calling thread through the getaddrinfo_arg structure. [Bug #20198] --- ext/socket/raddrinfo.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/ext/socket/raddrinfo.c b/ext/socket/raddrinfo.c index 560312741f6820..cdb785f268fee5 100644 --- a/ext/socket/raddrinfo.c +++ b/ext/socket/raddrinfo.c @@ -345,7 +345,7 @@ struct getaddrinfo_arg char *node, *service; struct addrinfo hints; struct addrinfo *ai; - int err, refcount, done, cancelled; + int err, gai_errno, refcount, done, cancelled; rb_nativethread_lock_t lock; rb_nativethread_cond_t cond; }; @@ -406,8 +406,9 @@ do_getaddrinfo(void *ptr) { struct getaddrinfo_arg *arg = (struct getaddrinfo_arg *)ptr; - int err; + int err, gai_errno; err = getaddrinfo(arg->node, arg->service, &arg->hints, &arg->ai); + gai_errno = errno; #ifdef __linux__ /* On Linux (mainly Ubuntu 13.04) /etc/nsswitch.conf has mdns4 and * it cause getaddrinfo to return EAI_SYSTEM/ENOENT. [ruby-list:49420] @@ -420,6 +421,7 @@ do_getaddrinfo(void *ptr) rb_nativethread_lock_lock(&arg->lock); { arg->err = err; + arg->gai_errno = gai_errno; if (arg->cancelled) { freeaddrinfo(arg->ai); } @@ -479,7 +481,7 @@ rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hint { int retry; struct getaddrinfo_arg *arg; - int err; + int err, gai_errno; start: retry = 0; @@ -503,6 +505,7 @@ rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hint { if (arg->done) { err = arg->err; + gai_errno = arg->gai_errno; if (err == 0) *ai = arg->ai; } else if (arg->cancelled) { @@ -525,6 +528,10 @@ rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hint rb_thread_check_ints(); if (retry) goto start; + /* Because errno is threadlocal, the errno value we got from the call to getaddrinfo() in the thread + * (in case of EAI_SYSTEM return value) is not propagated to the caller of _this_ function. Set errno + * explicitly, as round-tripped through struct getaddrinfo_arg, to deal with that */ + errno = gai_errno; return err; } @@ -591,7 +598,7 @@ struct getnameinfo_arg size_t hostlen; char *serv; size_t servlen; - int err, refcount, done, cancelled; + int err, gni_errno, refcount, done, cancelled; rb_nativethread_lock_t lock; rb_nativethread_cond_t cond; }; @@ -644,12 +651,14 @@ do_getnameinfo(void *ptr) { struct getnameinfo_arg *arg = (struct getnameinfo_arg *)ptr; - int err; + int err, gni_errno; err = getnameinfo(arg->sa, arg->salen, arg->host, (socklen_t)arg->hostlen, arg->serv, (socklen_t)arg->servlen, arg->flags); + gni_errno = errno; int need_free = 0; rb_nativethread_lock_lock(&arg->lock); arg->err = err; + arg->gni_errno = gni_errno; if (!arg->cancelled) { arg->done = 1; rb_native_cond_signal(&arg->cond); @@ -691,7 +700,7 @@ rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, { int retry; struct getnameinfo_arg *arg; - int err; + int err, gni_errno; start: retry = 0; @@ -714,6 +723,7 @@ rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, rb_nativethread_lock_lock(&arg->lock); if (arg->done) { err = arg->err; + gni_errno = arg->gni_errno; if (err == 0) { if (host) memcpy(host, arg->host, hostlen); if (serv) memcpy(serv, arg->serv, servlen); @@ -738,6 +748,9 @@ rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, rb_thread_check_ints(); if (retry) goto start; + /* Make sure we copy the thread-local errno value from the getnameinfo thread back to this thread, so + * calling code sees the correct errno */ + errno = gni_errno; return err; } From c44d15c639cfd227bd46037805d7393d0fbe8023 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 22 Jan 2024 12:31:51 +0900 Subject: [PATCH 380/640] Stop sync drb repo --- tool/sync_default_gems.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb index 413ec9421dd727..af7658b61a7d94 100755 --- a/tool/sync_default_gems.rb +++ b/tool/sync_default_gems.rb @@ -25,7 +25,6 @@ module SyncDefaultGems delegate: "ruby/delegate", did_you_mean: "ruby/did_you_mean", digest: "ruby/digest", - drb: "ruby/drb", erb: "ruby/erb", error_highlight: "ruby/error_highlight", etc: 'ruby/etc', From 3b3f03666ae74ed79b5387261c63052c3de0022e Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 22 Jan 2024 12:32:15 +0900 Subject: [PATCH 381/640] Refine entry title --- doc/maintainers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/maintainers.md b/doc/maintainers.md index f4b09b2db607c5..2a6a0545ef0dbd 100644 --- a/doc/maintainers.md +++ b/doc/maintainers.md @@ -463,7 +463,7 @@ have commit right, others don't. #### abbrev * https://github.com/ruby/abbrev -#### lib/resolv-replace.rb +#### resolv-replace * https://github.com/ruby/resolv-replace #### rinda From 34315510d34543cf14fe0ac9e8adb1d86b5beebf Mon Sep 17 00:00:00 2001 From: Eddie Lebow Date: Sun, 21 Jan 2024 23:35:59 -0500 Subject: [PATCH 382/640] [ruby/irb] Fix documentation typo, `niL` -> `nil` https://github.com/ruby/irb/commit/79086a9dda --- lib/irb.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/irb.rb b/lib/irb.rb index 4de8dda071ce28..5ced3d98a9cf12 100644 --- a/lib/irb.rb +++ b/lib/irb.rb @@ -365,7 +365,7 @@ # You can change the initial behavior and suppress all echoing by: # # - Adding to the configuration file: IRB.conf[:ECHO] = false. -# (The default value for this entry is +niL+, which means the same as +true+.) +# (The default value for this entry is +nil+, which means the same as +true+.) # - Giving command-line option --noecho. # (The default is --echo.) # From df70faa9c92beec4d78bbd5d0a8e0f24e16fdb7c Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 22 Jan 2024 12:33:14 +0900 Subject: [PATCH 383/640] Extract nkf --- ext/nkf/depend | 181 - ext/nkf/extconf.rb | 3 - ext/nkf/lib/kconv.rb | 283 - ext/nkf/nkf-utf8/config.h | 51 - ext/nkf/nkf-utf8/nkf.c | 7205 ----------------- ext/nkf/nkf-utf8/nkf.h | 189 - ext/nkf/nkf-utf8/utf8tbl.c | 14638 ----------------------------------- ext/nkf/nkf-utf8/utf8tbl.h | 72 - ext/nkf/nkf.c | 506 -- ext/nkf/nkf.gemspec | 43 - gems/bundled_gems | 1 + lib/nkf.rb | 6 - test/nkf/test_kconv.rb | 82 - test/nkf/test_nkf.rb | 23 - 14 files changed, 1 insertion(+), 23282 deletions(-) delete mode 100644 ext/nkf/depend delete mode 100644 ext/nkf/extconf.rb delete mode 100644 ext/nkf/lib/kconv.rb delete mode 100644 ext/nkf/nkf-utf8/config.h delete mode 100644 ext/nkf/nkf-utf8/nkf.c delete mode 100644 ext/nkf/nkf-utf8/nkf.h delete mode 100644 ext/nkf/nkf-utf8/utf8tbl.c delete mode 100644 ext/nkf/nkf-utf8/utf8tbl.h delete mode 100644 ext/nkf/nkf.c delete mode 100644 ext/nkf/nkf.gemspec delete mode 100644 lib/nkf.rb delete mode 100644 test/nkf/test_kconv.rb delete mode 100644 test/nkf/test_nkf.rb diff --git a/ext/nkf/depend b/ext/nkf/depend deleted file mode 100644 index 98afc5f201fcc8..00000000000000 --- a/ext/nkf/depend +++ /dev/null @@ -1,181 +0,0 @@ -# BSD make needs "nkf.o: nkf.c" dependency BEFORE "nkf.o: nkf-utf8/nkf.c". -# It seems BSD make searches the target for implicit rule in dependencies at first. -nkf.o: nkf.c - -# AUTOGENERATED DEPENDENCIES START -nkf.o: $(RUBY_EXTCONF_H) -nkf.o: $(arch_hdrdir)/ruby/config.h -nkf.o: $(hdrdir)/ruby/assert.h -nkf.o: $(hdrdir)/ruby/backward.h -nkf.o: $(hdrdir)/ruby/backward/2/assume.h -nkf.o: $(hdrdir)/ruby/backward/2/attributes.h -nkf.o: $(hdrdir)/ruby/backward/2/bool.h -nkf.o: $(hdrdir)/ruby/backward/2/inttypes.h -nkf.o: $(hdrdir)/ruby/backward/2/limits.h -nkf.o: $(hdrdir)/ruby/backward/2/long_long.h -nkf.o: $(hdrdir)/ruby/backward/2/stdalign.h -nkf.o: $(hdrdir)/ruby/backward/2/stdarg.h -nkf.o: $(hdrdir)/ruby/defines.h -nkf.o: $(hdrdir)/ruby/encoding.h -nkf.o: $(hdrdir)/ruby/intern.h -nkf.o: $(hdrdir)/ruby/internal/abi.h -nkf.o: $(hdrdir)/ruby/internal/anyargs.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/char.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/double.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/int.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/long.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/short.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -nkf.o: $(hdrdir)/ruby/internal/assume.h -nkf.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -nkf.o: $(hdrdir)/ruby/internal/attr/artificial.h -nkf.o: $(hdrdir)/ruby/internal/attr/cold.h -nkf.o: $(hdrdir)/ruby/internal/attr/const.h -nkf.o: $(hdrdir)/ruby/internal/attr/constexpr.h -nkf.o: $(hdrdir)/ruby/internal/attr/deprecated.h -nkf.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -nkf.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -nkf.o: $(hdrdir)/ruby/internal/attr/error.h -nkf.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -nkf.o: $(hdrdir)/ruby/internal/attr/forceinline.h -nkf.o: $(hdrdir)/ruby/internal/attr/format.h -nkf.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -nkf.o: $(hdrdir)/ruby/internal/attr/noalias.h -nkf.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -nkf.o: $(hdrdir)/ruby/internal/attr/noexcept.h -nkf.o: $(hdrdir)/ruby/internal/attr/noinline.h -nkf.o: $(hdrdir)/ruby/internal/attr/nonnull.h -nkf.o: $(hdrdir)/ruby/internal/attr/noreturn.h -nkf.o: $(hdrdir)/ruby/internal/attr/packed_struct.h -nkf.o: $(hdrdir)/ruby/internal/attr/pure.h -nkf.o: $(hdrdir)/ruby/internal/attr/restrict.h -nkf.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h -nkf.o: $(hdrdir)/ruby/internal/attr/warning.h -nkf.o: $(hdrdir)/ruby/internal/attr/weakref.h -nkf.o: $(hdrdir)/ruby/internal/cast.h -nkf.o: $(hdrdir)/ruby/internal/compiler_is.h -nkf.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -nkf.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -nkf.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -nkf.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -nkf.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -nkf.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -nkf.o: $(hdrdir)/ruby/internal/compiler_since.h -nkf.o: $(hdrdir)/ruby/internal/config.h -nkf.o: $(hdrdir)/ruby/internal/constant_p.h -nkf.o: $(hdrdir)/ruby/internal/core.h -nkf.o: $(hdrdir)/ruby/internal/core/rarray.h -nkf.o: $(hdrdir)/ruby/internal/core/rbasic.h -nkf.o: $(hdrdir)/ruby/internal/core/rbignum.h -nkf.o: $(hdrdir)/ruby/internal/core/rclass.h -nkf.o: $(hdrdir)/ruby/internal/core/rdata.h -nkf.o: $(hdrdir)/ruby/internal/core/rfile.h -nkf.o: $(hdrdir)/ruby/internal/core/rhash.h -nkf.o: $(hdrdir)/ruby/internal/core/robject.h -nkf.o: $(hdrdir)/ruby/internal/core/rregexp.h -nkf.o: $(hdrdir)/ruby/internal/core/rstring.h -nkf.o: $(hdrdir)/ruby/internal/core/rstruct.h -nkf.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -nkf.o: $(hdrdir)/ruby/internal/ctype.h -nkf.o: $(hdrdir)/ruby/internal/dllexport.h -nkf.o: $(hdrdir)/ruby/internal/dosish.h -nkf.o: $(hdrdir)/ruby/internal/encoding/coderange.h -nkf.o: $(hdrdir)/ruby/internal/encoding/ctype.h -nkf.o: $(hdrdir)/ruby/internal/encoding/encoding.h -nkf.o: $(hdrdir)/ruby/internal/encoding/pathname.h -nkf.o: $(hdrdir)/ruby/internal/encoding/re.h -nkf.o: $(hdrdir)/ruby/internal/encoding/sprintf.h -nkf.o: $(hdrdir)/ruby/internal/encoding/string.h -nkf.o: $(hdrdir)/ruby/internal/encoding/symbol.h -nkf.o: $(hdrdir)/ruby/internal/encoding/transcode.h -nkf.o: $(hdrdir)/ruby/internal/error.h -nkf.o: $(hdrdir)/ruby/internal/eval.h -nkf.o: $(hdrdir)/ruby/internal/event.h -nkf.o: $(hdrdir)/ruby/internal/fl_type.h -nkf.o: $(hdrdir)/ruby/internal/gc.h -nkf.o: $(hdrdir)/ruby/internal/glob.h -nkf.o: $(hdrdir)/ruby/internal/globals.h -nkf.o: $(hdrdir)/ruby/internal/has/attribute.h -nkf.o: $(hdrdir)/ruby/internal/has/builtin.h -nkf.o: $(hdrdir)/ruby/internal/has/c_attribute.h -nkf.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -nkf.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -nkf.o: $(hdrdir)/ruby/internal/has/extension.h -nkf.o: $(hdrdir)/ruby/internal/has/feature.h -nkf.o: $(hdrdir)/ruby/internal/has/warning.h -nkf.o: $(hdrdir)/ruby/internal/intern/array.h -nkf.o: $(hdrdir)/ruby/internal/intern/bignum.h -nkf.o: $(hdrdir)/ruby/internal/intern/class.h -nkf.o: $(hdrdir)/ruby/internal/intern/compar.h -nkf.o: $(hdrdir)/ruby/internal/intern/complex.h -nkf.o: $(hdrdir)/ruby/internal/intern/cont.h -nkf.o: $(hdrdir)/ruby/internal/intern/dir.h -nkf.o: $(hdrdir)/ruby/internal/intern/enum.h -nkf.o: $(hdrdir)/ruby/internal/intern/enumerator.h -nkf.o: $(hdrdir)/ruby/internal/intern/error.h -nkf.o: $(hdrdir)/ruby/internal/intern/eval.h -nkf.o: $(hdrdir)/ruby/internal/intern/file.h -nkf.o: $(hdrdir)/ruby/internal/intern/hash.h -nkf.o: $(hdrdir)/ruby/internal/intern/io.h -nkf.o: $(hdrdir)/ruby/internal/intern/load.h -nkf.o: $(hdrdir)/ruby/internal/intern/marshal.h -nkf.o: $(hdrdir)/ruby/internal/intern/numeric.h -nkf.o: $(hdrdir)/ruby/internal/intern/object.h -nkf.o: $(hdrdir)/ruby/internal/intern/parse.h -nkf.o: $(hdrdir)/ruby/internal/intern/proc.h -nkf.o: $(hdrdir)/ruby/internal/intern/process.h -nkf.o: $(hdrdir)/ruby/internal/intern/random.h -nkf.o: $(hdrdir)/ruby/internal/intern/range.h -nkf.o: $(hdrdir)/ruby/internal/intern/rational.h -nkf.o: $(hdrdir)/ruby/internal/intern/re.h -nkf.o: $(hdrdir)/ruby/internal/intern/ruby.h -nkf.o: $(hdrdir)/ruby/internal/intern/select.h -nkf.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -nkf.o: $(hdrdir)/ruby/internal/intern/signal.h -nkf.o: $(hdrdir)/ruby/internal/intern/sprintf.h -nkf.o: $(hdrdir)/ruby/internal/intern/string.h -nkf.o: $(hdrdir)/ruby/internal/intern/struct.h -nkf.o: $(hdrdir)/ruby/internal/intern/thread.h -nkf.o: $(hdrdir)/ruby/internal/intern/time.h -nkf.o: $(hdrdir)/ruby/internal/intern/variable.h -nkf.o: $(hdrdir)/ruby/internal/intern/vm.h -nkf.o: $(hdrdir)/ruby/internal/interpreter.h -nkf.o: $(hdrdir)/ruby/internal/iterator.h -nkf.o: $(hdrdir)/ruby/internal/memory.h -nkf.o: $(hdrdir)/ruby/internal/method.h -nkf.o: $(hdrdir)/ruby/internal/module.h -nkf.o: $(hdrdir)/ruby/internal/newobj.h -nkf.o: $(hdrdir)/ruby/internal/scan_args.h -nkf.o: $(hdrdir)/ruby/internal/special_consts.h -nkf.o: $(hdrdir)/ruby/internal/static_assert.h -nkf.o: $(hdrdir)/ruby/internal/stdalign.h -nkf.o: $(hdrdir)/ruby/internal/stdbool.h -nkf.o: $(hdrdir)/ruby/internal/symbol.h -nkf.o: $(hdrdir)/ruby/internal/value.h -nkf.o: $(hdrdir)/ruby/internal/value_type.h -nkf.o: $(hdrdir)/ruby/internal/variable.h -nkf.o: $(hdrdir)/ruby/internal/warning_push.h -nkf.o: $(hdrdir)/ruby/internal/xmalloc.h -nkf.o: $(hdrdir)/ruby/missing.h -nkf.o: $(hdrdir)/ruby/onigmo.h -nkf.o: $(hdrdir)/ruby/oniguruma.h -nkf.o: $(hdrdir)/ruby/ruby.h -nkf.o: $(hdrdir)/ruby/st.h -nkf.o: $(hdrdir)/ruby/subst.h -nkf.o: nkf-utf8/config.h -nkf.o: nkf-utf8/nkf.c -nkf.o: nkf-utf8/nkf.h -nkf.o: nkf-utf8/utf8tbl.c -nkf.o: nkf-utf8/utf8tbl.h -nkf.o: nkf.c -# AUTOGENERATED DEPENDENCIES END diff --git a/ext/nkf/extconf.rb b/ext/nkf/extconf.rb deleted file mode 100644 index f41f6b11dc8fbf..00000000000000 --- a/ext/nkf/extconf.rb +++ /dev/null @@ -1,3 +0,0 @@ -# frozen_string_literal: false -require 'mkmf' -create_makefile('nkf') diff --git a/ext/nkf/lib/kconv.rb b/ext/nkf/lib/kconv.rb deleted file mode 100644 index f52b755288b78b..00000000000000 --- a/ext/nkf/lib/kconv.rb +++ /dev/null @@ -1,283 +0,0 @@ -# frozen_string_literal: false -# -# kconv.rb - Kanji Converter. -# -# $Id$ -# -# ---- -# -# kconv.rb implements the Kconv class for Kanji Converter. Additionally, -# some methods in String classes are added to allow easy conversion. -# - -require 'nkf' - -# -# Kanji Converter for Ruby. -# -module Kconv - # - # Public Constants - # - - #Constant of Encoding - - # Auto-Detect - AUTO = NKF::AUTO - # ISO-2022-JP - JIS = NKF::JIS - # EUC-JP - EUC = NKF::EUC - # Shift_JIS - SJIS = NKF::SJIS - # BINARY - BINARY = NKF::BINARY - # NOCONV - NOCONV = NKF::NOCONV - # ASCII - ASCII = NKF::ASCII - # UTF-8 - UTF8 = NKF::UTF8 - # UTF-16 - UTF16 = NKF::UTF16 - # UTF-32 - UTF32 = NKF::UTF32 - # UNKNOWN - UNKNOWN = NKF::UNKNOWN - - # - # Public Methods - # - - # call-seq: - # Kconv.kconv(str, to_enc, from_enc=nil) - # - # Convert str to to_enc. - # to_enc and from_enc are given as constants of Kconv or Encoding objects. - def kconv(str, to_enc, from_enc=nil) - opt = '' - opt += ' --ic=' + from_enc.to_s if from_enc - opt += ' --oc=' + to_enc.to_s if to_enc - - ::NKF::nkf(opt, str) - end - module_function :kconv - - # - # Encode to - # - - # call-seq: - # Kconv.tojis(str) => string - # - # Convert str to ISO-2022-JP - def tojis(str) - kconv(str, JIS) - end - module_function :tojis - - # call-seq: - # Kconv.toeuc(str) => string - # - # Convert str to EUC-JP - def toeuc(str) - kconv(str, EUC) - end - module_function :toeuc - - # call-seq: - # Kconv.tosjis(str) => string - # - # Convert str to Shift_JIS - def tosjis(str) - kconv(str, SJIS) - end - module_function :tosjis - - # call-seq: - # Kconv.toutf8(str) => string - # - # Convert str to UTF-8 - def toutf8(str) - kconv(str, UTF8) - end - module_function :toutf8 - - # call-seq: - # Kconv.toutf16(str) => string - # - # Convert str to UTF-16 - def toutf16(str) - kconv(str, UTF16) - end - module_function :toutf16 - - # call-seq: - # Kconv.toutf32(str) => string - # - # Convert str to UTF-32 - def toutf32(str) - kconv(str, UTF32) - end - module_function :toutf32 - - # call-seq: - # Kconv.tolocale => string - # - # Convert self to locale encoding - def tolocale(str) - kconv(str, Encoding.locale_charmap) - end - module_function :tolocale - - # - # guess - # - - # call-seq: - # Kconv.guess(str) => encoding - # - # Guess input encoding by NKF.guess - def guess(str) - ::NKF::guess(str) - end - module_function :guess - - # - # isEncoding - # - - # call-seq: - # Kconv.iseuc(str) => true or false - # - # Returns whether input encoding is EUC-JP or not. - # - # *Note* don't expect this return value is MatchData. - def iseuc(str) - str.dup.force_encoding(EUC).valid_encoding? - end - module_function :iseuc - - # call-seq: - # Kconv.issjis(str) => true or false - # - # Returns whether input encoding is Shift_JIS or not. - def issjis(str) - str.dup.force_encoding(SJIS).valid_encoding? - end - module_function :issjis - - # call-seq: - # Kconv.isjis(str) => true or false - # - # Returns whether input encoding is ISO-2022-JP or not. - def isjis(str) - /\A [\t\n\r\x20-\x7E]* - (?: - (?:\x1b \x28 I [\x21-\x7E]* - |\x1b \x28 J [\x21-\x7E]* - |\x1b \x24 @ (?:[\x21-\x7E]{2})* - |\x1b \x24 B (?:[\x21-\x7E]{2})* - |\x1b \x24 \x28 D (?:[\x21-\x7E]{2})* - )* - \x1b \x28 B [\t\n\r\x20-\x7E]* - )* - \z/nox =~ str.dup.force_encoding('BINARY') ? true : false - end - module_function :isjis - - # call-seq: - # Kconv.isutf8(str) => true or false - # - # Returns whether input encoding is UTF-8 or not. - def isutf8(str) - str.dup.force_encoding(UTF8).valid_encoding? - end - module_function :isutf8 -end - -class String - # call-seq: - # String#kconv(to_enc, from_enc) - # - # Convert self to to_enc. - # to_enc and from_enc are given as constants of Kconv or Encoding objects. - def kconv(to_enc, from_enc=nil) - from_enc = self.encoding if !from_enc && self.encoding != Encoding.list[0] - Kconv::kconv(self, to_enc, from_enc) - end - - # - # to Encoding - # - - # call-seq: - # String#tojis => string - # - # Convert self to ISO-2022-JP - def tojis; Kconv.tojis(self) end - - # call-seq: - # String#toeuc => string - # - # Convert self to EUC-JP - def toeuc; Kconv.toeuc(self) end - - # call-seq: - # String#tosjis => string - # - # Convert self to Shift_JIS - def tosjis; Kconv.tosjis(self) end - - # call-seq: - # String#toutf8 => string - # - # Convert self to UTF-8 - def toutf8; Kconv.toutf8(self) end - - # call-seq: - # String#toutf16 => string - # - # Convert self to UTF-16 - def toutf16; Kconv.toutf16(self) end - - # call-seq: - # String#toutf32 => string - # - # Convert self to UTF-32 - def toutf32; Kconv.toutf32(self) end - - # call-seq: - # String#tolocale => string - # - # Convert self to locale encoding - def tolocale; Kconv.tolocale(self) end - - # - # is Encoding - # - - # call-seq: - # String#iseuc => true or false - # - # Returns whether self's encoding is EUC-JP or not. - def iseuc; Kconv.iseuc(self) end - - # call-seq: - # String#issjis => true or false - # - # Returns whether self's encoding is Shift_JIS or not. - def issjis; Kconv.issjis(self) end - - # call-seq: - # String#isjis => true or false - # - # Returns whether self's encoding is ISO-2022-JP or not. - def isjis; Kconv.isjis(self) end - - # call-seq: - # String#isutf8 => true or false - # - # Returns whether self's encoding is UTF-8 or not. - def isutf8; Kconv.isutf8(self) end -end diff --git a/ext/nkf/nkf-utf8/config.h b/ext/nkf/nkf-utf8/config.h deleted file mode 100644 index 36898c0b4b1d98..00000000000000 --- a/ext/nkf/nkf-utf8/config.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _CONFIG_H_ -#define _CONFIG_H_ - -/* UTF8 input and output */ -#define UTF8_INPUT_ENABLE -#define UTF8_OUTPUT_ENABLE - -/* invert characters invalid in Shift_JIS to CP932 */ -#define SHIFTJIS_CP932 - -/* fix input encoding when given by option */ -#define INPUT_CODE_FIX - -/* --overwrite option */ -/* by Satoru Takabayashi */ -#define OVERWRITE - -/* --cap-input, --url-input option */ -#define INPUT_OPTION - -/* --numchar-input option */ -#define NUMCHAR_OPTION - -/* --debug, --no-output option */ -#define CHECK_OPTION - -/* JIS X0212 */ -#define X0212_ENABLE - -/* --exec-in, --exec-out option - * require pipe, fork, execvp and so on. - * please undef this on MS-DOS, MinGW - * this is still buggy around child process - */ -/* #define EXEC_IO */ - -/* Unicode Normalization */ -#define UNICODE_NORMALIZATION - -/* - * Select Default Output Encoding - * - */ - -/* #define DEFAULT_CODE_JIS */ -/* #define DEFAULT_CODE_SJIS */ -/* #define DEFAULT_CODE_WINDOWS_31J */ -/* #define DEFAULT_CODE_EUC */ -/* #define DEFAULT_CODE_UTF8 */ - -#endif /* _CONFIG_H_ */ diff --git a/ext/nkf/nkf-utf8/nkf.c b/ext/nkf/nkf-utf8/nkf.c deleted file mode 100644 index 6888a439183c67..00000000000000 --- a/ext/nkf/nkf-utf8/nkf.c +++ /dev/null @@ -1,7205 +0,0 @@ -/* - * Copyright (c) 1987, Fujitsu LTD. (Itaru ICHIKAWA). - * Copyright (c) 1996-2018, The nkf Project. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source distribution. - */ -#define NKF_VERSION "2.1.5" -#define NKF_RELEASE_DATE "2018-12-15" -#define COPY_RIGHT \ - "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa).\n" \ - "Copyright (C) 1996-2018, The nkf Project." - -#include "config.h" -#include "nkf.h" -#include "utf8tbl.h" -#ifdef __WIN32__ -#include -#include -#endif -#if defined(__OS2__) -# define INCL_DOS -# define INCL_DOSERRORS -# include -#endif -#include - - -/* state of output_mode and input_mode - - c2 0 means ASCII - JIS_X_0201_1976_K - ISO_8859_1 - JIS_X_0208 - EOF all termination - c1 32bit data - - */ - -/* MIME ENCODE */ - -#define FIXED_MIME 7 -#define STRICT_MIME 8 - -/* byte order */ -enum byte_order { - ENDIAN_BIG = 1, - ENDIAN_LITTLE = 2, - ENDIAN_2143 = 3, - ENDIAN_3412 = 4 -}; - -/* ASCII CODE */ - -#define BS 0x08 -#define TAB 0x09 -#define LF 0x0a -#define CR 0x0d -#define ESC 0x1b -#define SP 0x20 -#define DEL 0x7f -#define SI 0x0f -#define SO 0x0e -#define SS2 0x8e -#define SS3 0x8f -#define CRLF 0x0D0A - - -/* encodings */ - -enum nkf_encodings { - ASCII, - ISO_8859_1, - ISO_2022_JP, - CP50220, - CP50221, - CP50222, - ISO_2022_JP_1, - ISO_2022_JP_3, - ISO_2022_JP_2004, - SHIFT_JIS, - WINDOWS_31J, - CP10001, - EUC_JP, - EUCJP_NKF, - CP51932, - EUCJP_MS, - EUCJP_ASCII, - SHIFT_JISX0213, - SHIFT_JIS_2004, - EUC_JISX0213, - EUC_JIS_2004, - UTF_8, - UTF_8N, - UTF_8_BOM, - UTF8_MAC, - UTF_16, - UTF_16BE, - UTF_16BE_BOM, - UTF_16LE, - UTF_16LE_BOM, - UTF_32, - UTF_32BE, - UTF_32BE_BOM, - UTF_32LE, - UTF_32LE_BOM, - BINARY, - NKF_ENCODING_TABLE_SIZE, - JIS_X_0201_1976_K = 0x1013, /* I */ /* JIS C 6220-1969 */ - /* JIS_X_0201_1976_R = 0x1014, */ /* J */ /* JIS C 6220-1969 */ - /* JIS_X_0208_1978 = 0x1040, */ /* @ */ /* JIS C 6226-1978 */ - /* JIS_X_0208_1983 = 0x1087, */ /* B */ /* JIS C 6226-1983 */ - JIS_X_0208 = 0x1168, /* @B */ - JIS_X_0212 = 0x1159, /* D */ - /* JIS_X_0213_2000_1 = 0x1228, */ /* O */ - JIS_X_0213_2 = 0x1229, /* P */ - JIS_X_0213_1 = 0x1233 /* Q */ -}; - -static nkf_char s_iconv(nkf_char c2, nkf_char c1, nkf_char c0); -static nkf_char e_iconv(nkf_char c2, nkf_char c1, nkf_char c0); -static nkf_char w_iconv(nkf_char c2, nkf_char c1, nkf_char c0); -static nkf_char w_iconv16(nkf_char c2, nkf_char c1, nkf_char c0); -static nkf_char w_iconv32(nkf_char c2, nkf_char c1, nkf_char c0); -static void j_oconv(nkf_char c2, nkf_char c1); -static void s_oconv(nkf_char c2, nkf_char c1); -static void e_oconv(nkf_char c2, nkf_char c1); -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 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); -} nkf_native_encoding; - -nkf_native_encoding NkfEncodingASCII = { "ASCII", e_iconv, e_oconv }; -nkf_native_encoding NkfEncodingISO_2022_JP = { "ISO-2022-JP", e_iconv, j_oconv }; -nkf_native_encoding NkfEncodingShift_JIS = { "Shift_JIS", s_iconv, s_oconv }; -nkf_native_encoding NkfEncodingEUC_JP = { "EUC-JP", e_iconv, e_oconv }; -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 const struct { - int id; - const char *name; - nkf_native_encoding *base_encoding; -} nkf_encoding; - -nkf_encoding nkf_encoding_table[] = { - {ASCII, "US-ASCII", &NkfEncodingASCII}, - {ISO_8859_1, "ISO-8859-1", &NkfEncodingASCII}, - {ISO_2022_JP, "ISO-2022-JP", &NkfEncodingISO_2022_JP}, - {CP50220, "CP50220", &NkfEncodingISO_2022_JP}, - {CP50221, "CP50221", &NkfEncodingISO_2022_JP}, - {CP50222, "CP50222", &NkfEncodingISO_2022_JP}, - {ISO_2022_JP_1, "ISO-2022-JP-1", &NkfEncodingISO_2022_JP}, - {ISO_2022_JP_3, "ISO-2022-JP-3", &NkfEncodingISO_2022_JP}, - {ISO_2022_JP_2004, "ISO-2022-JP-2004", &NkfEncodingISO_2022_JP}, - {SHIFT_JIS, "Shift_JIS", &NkfEncodingShift_JIS}, - {WINDOWS_31J, "Windows-31J", &NkfEncodingShift_JIS}, - {CP10001, "CP10001", &NkfEncodingShift_JIS}, - {EUC_JP, "EUC-JP", &NkfEncodingEUC_JP}, - {EUCJP_NKF, "eucJP-nkf", &NkfEncodingEUC_JP}, - {CP51932, "CP51932", &NkfEncodingEUC_JP}, - {EUCJP_MS, "eucJP-MS", &NkfEncodingEUC_JP}, - {EUCJP_ASCII, "eucJP-ASCII", &NkfEncodingEUC_JP}, - {SHIFT_JISX0213, "Shift_JISX0213", &NkfEncodingShift_JIS}, - {SHIFT_JIS_2004, "Shift_JIS-2004", &NkfEncodingShift_JIS}, - {EUC_JISX0213, "EUC-JISX0213", &NkfEncodingEUC_JP}, - {EUC_JIS_2004, "EUC-JIS-2004", &NkfEncodingEUC_JP}, - {UTF_8, "UTF-8", &NkfEncodingUTF_8}, - {UTF_8N, "UTF-8N", &NkfEncodingUTF_8}, - {UTF_8_BOM, "UTF-8-BOM", &NkfEncodingUTF_8}, - {UTF8_MAC, "UTF8-MAC", &NkfEncodingUTF_8}, - {UTF_16, "UTF-16", &NkfEncodingUTF_16}, - {UTF_16BE, "UTF-16BE", &NkfEncodingUTF_16}, - {UTF_16BE_BOM, "UTF-16BE-BOM", &NkfEncodingUTF_16}, - {UTF_16LE, "UTF-16LE", &NkfEncodingUTF_16}, - {UTF_16LE_BOM, "UTF-16LE-BOM", &NkfEncodingUTF_16}, - {UTF_32, "UTF-32", &NkfEncodingUTF_32}, - {UTF_32BE, "UTF-32BE", &NkfEncodingUTF_32}, - {UTF_32BE_BOM, "UTF-32BE-BOM", &NkfEncodingUTF_32}, - {UTF_32LE, "UTF-32LE", &NkfEncodingUTF_32}, - {UTF_32LE_BOM, "UTF-32LE-BOM", &NkfEncodingUTF_32}, - {BINARY, "BINARY", &NkfEncodingASCII}, - {-1, NULL, NULL} -}; - -static const struct { - const char *name; - int id; -} encoding_name_to_id_table[] = { - {"US-ASCII", ASCII}, - {"ASCII", ASCII}, - {"646", ASCII}, - {"ROMAN8", ASCII}, - {"ISO-2022-JP", ISO_2022_JP}, - {"ISO2022JP-CP932", CP50220}, - {"CP50220", CP50220}, - {"CP50221", CP50221}, - {"CSISO2022JP", CP50221}, - {"CP50222", CP50222}, - {"ISO-2022-JP-1", ISO_2022_JP_1}, - {"ISO-2022-JP-3", ISO_2022_JP_3}, - {"ISO-2022-JP-2004", ISO_2022_JP_2004}, - {"SHIFT_JIS", SHIFT_JIS}, - {"SJIS", SHIFT_JIS}, - {"MS_Kanji", SHIFT_JIS}, - {"PCK", SHIFT_JIS}, - {"WINDOWS-31J", WINDOWS_31J}, - {"CSWINDOWS31J", WINDOWS_31J}, - {"CP932", WINDOWS_31J}, - {"MS932", WINDOWS_31J}, - {"CP10001", CP10001}, - {"EUCJP", EUC_JP}, - {"EUC-JP", EUC_JP}, - {"EUCJP-NKF", EUCJP_NKF}, - {"CP51932", CP51932}, - {"EUC-JP-MS", EUCJP_MS}, - {"EUCJP-MS", EUCJP_MS}, - {"EUCJPMS", EUCJP_MS}, - {"EUC-JP-ASCII", EUCJP_ASCII}, - {"EUCJP-ASCII", EUCJP_ASCII}, - {"SHIFT_JISX0213", SHIFT_JISX0213}, - {"SHIFT_JIS-2004", SHIFT_JIS_2004}, - {"EUC-JISX0213", EUC_JISX0213}, - {"EUC-JIS-2004", EUC_JIS_2004}, - {"UTF-8", UTF_8}, - {"UTF-8N", UTF_8N}, - {"UTF-8-BOM", UTF_8_BOM}, - {"UTF8-MAC", UTF8_MAC}, - {"UTF-8-MAC", UTF8_MAC}, - {"UTF-16", UTF_16}, - {"UTF-16BE", UTF_16BE}, - {"UTF-16BE-BOM", UTF_16BE_BOM}, - {"UTF-16LE", UTF_16LE}, - {"UTF-16LE-BOM", UTF_16LE_BOM}, - {"UTF-32", UTF_32}, - {"UTF-32BE", UTF_32BE}, - {"UTF-32BE-BOM", UTF_32BE_BOM}, - {"UTF-32LE", UTF_32LE}, - {"UTF-32LE-BOM", UTF_32LE_BOM}, - {"BINARY", BINARY}, - {NULL, -1} -}; - -#if defined(DEFAULT_CODE_JIS) -#define DEFAULT_ENCIDX ISO_2022_JP -#elif defined(DEFAULT_CODE_SJIS) -#define DEFAULT_ENCIDX SHIFT_JIS -#elif defined(DEFAULT_CODE_WINDOWS_31J) -#define DEFAULT_ENCIDX WINDOWS_31J -#elif defined(DEFAULT_CODE_EUC) -#define DEFAULT_ENCIDX EUC_JP -#elif defined(DEFAULT_CODE_UTF8) -#define DEFAULT_ENCIDX UTF_8 -#endif - - -#define is_alnum(c) \ - (('a'<=c && c<='z')||('A'<= c && c<='Z')||('0'<=c && c<='9')) - -/* I don't trust portablity of toupper */ -#define nkf_toupper(c) (('a'<=c && c<='z')?(c-('a'-'A')):c) -#define nkf_isoctal(c) ('0'<=c && c<='7') -#define nkf_isdigit(c) ('0'<=c && c<='9') -#define nkf_isxdigit(c) (nkf_isdigit(c) || ('a'<=c && c<='f') || ('A'<=c && c <= 'F')) -#define nkf_isblank(c) (c == SP || c == TAB) -#define nkf_isspace(c) (nkf_isblank(c) || c == CR || c == LF) -#define nkf_isalpha(c) (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) -#define nkf_isalnum(c) (nkf_isdigit(c) || nkf_isalpha(c)) -#define nkf_isprint(c) (SP<=c && c<='~') -#define nkf_isgraph(c) ('!'<=c && c<='~') -#define hex2bin(c) (('0'<=c&&c<='9') ? (c-'0') : \ - ('A'<=c&&c<='F') ? (c-'A'+10) : \ - ('a'<=c&&c<='f') ? (c-'a'+10) : 0) -#define bin2hex(c) ("0123456789ABCDEF"[c&15]) -#define is_eucg3(c2) (((unsigned short)c2 >> 8) == SS3) -#define nkf_noescape_mime(c) ((c == CR) || (c == LF) || \ - ((c > SP) && (c < DEL) && (c != '?') && (c != '=') && (c != '_') \ - && (c != '(') && (c != ')') && (c != '.') && (c != 0x22))) - -#define is_ibmext_in_sjis(c2) (CP932_TABLE_BEGIN <= c2 && c2 <= CP932_TABLE_END) -#define nkf_byte_jisx0201_katakana_p(c) (SP <= c && c <= 0x5F) - -#define HOLD_SIZE 1024 -#if defined(INT_IS_SHORT) -#define IOBUF_SIZE 2048 -#else -#define IOBUF_SIZE 16384 -#endif - -#define DEFAULT_J 'B' -#define DEFAULT_R 'B' - - -#define GETA1 0x22 -#define GETA2 0x2e - - -/* MIME preprocessor */ - -#ifdef EASYWIN /*Easy Win */ -extern POINT _BufferSize; -#endif - -struct input_code{ - const char *name; - nkf_char stat; - nkf_char score; - nkf_char index; - nkf_char buf[3]; - void (*status_func)(struct input_code *, nkf_char); - nkf_char (*iconv_func)(nkf_char c2, nkf_char c1, nkf_char c0); - int _file_stat; -}; - -static const char *input_codename = NULL; /* NULL: unestablished, "": BINARY */ -static nkf_encoding *input_encoding = NULL; -static nkf_encoding *output_encoding = NULL; - -#if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE) -/* UCS Mapping - * 0: Shift_JIS, eucJP-ascii - * 1: eucJP-ms - * 2: CP932, CP51932 - * 3: CP10001 - */ -#define UCS_MAP_ASCII 0 -#define UCS_MAP_MS 1 -#define UCS_MAP_CP932 2 -#define UCS_MAP_CP10001 3 -static int ms_ucs_map_f = UCS_MAP_ASCII; -#endif -#ifdef UTF8_INPUT_ENABLE -/* no NEC special, NEC-selected IBM extended and IBM extended characters */ -static int no_cp932ext_f = FALSE; -/* ignore ZERO WIDTH NO-BREAK SPACE */ -static int no_best_fit_chars_f = FALSE; -static int input_endian = ENDIAN_BIG; -static int input_bom_f = FALSE; -static nkf_char unicode_subchar = '?'; /* the regular substitution character */ -static void (*encode_fallback)(nkf_char c) = NULL; -static void w_status(struct input_code *, nkf_char); -#endif -#ifdef UTF8_OUTPUT_ENABLE -static int output_bom_f = FALSE; -static int output_endian = ENDIAN_BIG; -#endif - -static void std_putc(nkf_char c); -static nkf_char std_getc(FILE *f); -static nkf_char std_ungetc(nkf_char c,FILE *f); - -static nkf_char broken_getc(FILE *f); -static nkf_char broken_ungetc(nkf_char c,FILE *f); - -static nkf_char mime_getc(FILE *f); - -static void mime_putc(nkf_char c); - -/* buffers */ - -#if !defined(PERL_XS) && !defined(WIN32DLL) -static unsigned char stdibuf[IOBUF_SIZE]; -static unsigned char stdobuf[IOBUF_SIZE]; -#endif - -#define NKF_UNSPECIFIED (-TRUE) - -/* flags */ -static int unbuf_f = FALSE; -static int estab_f = FALSE; -static int nop_f = FALSE; -static int binmode_f = TRUE; /* binary mode */ -static int rot_f = FALSE; /* rot14/43 mode */ -static int hira_f = FALSE; /* hira/kata henkan */ -static int alpha_f = FALSE; /* convert JIx0208 alphbet to ASCII */ -static int mime_f = MIME_DECODE_DEFAULT; /* convert MIME B base64 or Q */ -static int mime_decode_f = FALSE; /* mime decode is explicitly on */ -static int mimebuf_f = FALSE; /* MIME buffered input */ -static int broken_f = FALSE; /* convert ESC-less broken JIS */ -static int iso8859_f = FALSE; /* ISO8859 through */ -static int mimeout_f = FALSE; /* base64 mode */ -static int x0201_f = NKF_UNSPECIFIED; /* convert JIS X 0201 */ -static int iso2022jp_f = FALSE; /* replace non ISO-2022-JP with GETA */ - -#ifdef UNICODE_NORMALIZATION -static int nfc_f = FALSE; -static nkf_char (*i_nfc_getc)(FILE *) = std_getc; /* input of ugetc */ -static nkf_char (*i_nfc_ungetc)(nkf_char c ,FILE *f) = std_ungetc; -#endif - -#ifdef INPUT_OPTION -static int cap_f = FALSE; -static nkf_char (*i_cgetc)(FILE *) = std_getc; /* input of cgetc */ -static nkf_char (*i_cungetc)(nkf_char c ,FILE *f) = std_ungetc; - -static int url_f = FALSE; -static nkf_char (*i_ugetc)(FILE *) = std_getc; /* input of ugetc */ -static nkf_char (*i_uungetc)(nkf_char c ,FILE *f) = std_ungetc; -#endif - -#define PREFIX_EUCG3 NKF_INT32_C(0x8F00) -#define CLASS_MASK NKF_INT32_C(0xFF000000) -#define CLASS_UNICODE NKF_INT32_C(0x01000000) -#define VALUE_MASK NKF_INT32_C(0x00FFFFFF) -#define UNICODE_BMP_MAX NKF_INT32_C(0x0000FFFF) -#define UNICODE_MAX NKF_INT32_C(0x0010FFFF) -#define nkf_char_euc3_new(c) ((c) | PREFIX_EUCG3) -#define nkf_char_unicode_new(c) ((c) | CLASS_UNICODE) -#define nkf_char_unicode_p(c) ((c & CLASS_MASK) == CLASS_UNICODE) -#define nkf_char_unicode_bmp_p(c) ((c & VALUE_MASK) <= UNICODE_BMP_MAX) -#define nkf_char_unicode_value_p(c) ((c & VALUE_MASK) <= UNICODE_MAX) - -#define UTF16_TO_UTF32(lead, trail) (((lead) << 10) + (trail) - NKF_INT32_C(0x35FDC00)) - -#ifdef NUMCHAR_OPTION -static int numchar_f = FALSE; -static nkf_char (*i_ngetc)(FILE *) = std_getc; /* input of ugetc */ -static nkf_char (*i_nungetc)(nkf_char c ,FILE *f) = std_ungetc; -#endif - -#ifdef CHECK_OPTION -static int noout_f = FALSE; -static void no_putc(nkf_char c); -static int debug_f = FALSE; -static void debug(const char *str); -static nkf_char (*iconv_for_check)(nkf_char c2,nkf_char c1,nkf_char c0) = 0; -#endif - -static int guess_f = 0; /* 0: OFF, 1: ON, 2: VERBOSE */ -static void set_input_codename(const char *codename); - -#ifdef EXEC_IO -static int exec_f = 0; -#endif - -#ifdef SHIFTJIS_CP932 -/* invert IBM extended characters to others */ -static int cp51932_f = FALSE; - -/* invert NEC-selected IBM extended characters to IBM extended characters */ -static int cp932inv_f = TRUE; - -/* static nkf_char cp932_conv(nkf_char c2, nkf_char c1); */ -#endif /* SHIFTJIS_CP932 */ - -static int x0212_f = FALSE; -static int x0213_f = FALSE; - -static unsigned char prefix_table[256]; - -static void e_status(struct input_code *, nkf_char); -static void s_status(struct input_code *, nkf_char); - -struct input_code input_code_list[] = { - {"EUC-JP", 0, 0, 0, {0, 0, 0}, e_status, e_iconv, 0}, - {"Shift_JIS", 0, 0, 0, {0, 0, 0}, s_status, s_iconv, 0}, -#ifdef UTF8_INPUT_ENABLE - {"UTF-8", 0, 0, 0, {0, 0, 0}, w_status, w_iconv, 0}, - {"UTF-16", 0, 0, 0, {0, 0, 0}, NULL, w_iconv16, 0}, - {"UTF-32", 0, 0, 0, {0, 0, 0}, NULL, w_iconv32, 0}, -#endif - {NULL, 0, 0, 0, {0, 0, 0}, NULL, NULL, 0} -}; - -static int mimeout_mode = 0; /* 0, -1, 'Q', 'B', 1, 2 */ -static int base64_count = 0; - -/* X0208 -> ASCII converter */ - -/* fold parameter */ -static int f_line = 0; /* chars in line */ -static int f_prev = 0; -static int fold_preserve_f = FALSE; /* preserve new lines */ -static int fold_f = FALSE; -static int fold_len = 0; - -/* options */ -static unsigned char kanji_intro = DEFAULT_J; -static unsigned char ascii_intro = DEFAULT_R; - -/* Folding */ - -#define FOLD_MARGIN 10 -#define DEFAULT_FOLD 60 - -static int fold_margin = FOLD_MARGIN; - -/* process default */ - -static nkf_char -no_connection2(ARG_UNUSED nkf_char c2, ARG_UNUSED nkf_char c1, ARG_UNUSED nkf_char c0) -{ - fprintf(stderr,"nkf internal module connection failure.\n"); - exit(EXIT_FAILURE); - return 0; /* LINT */ -} - -static void -no_connection(nkf_char c2, nkf_char c1) -{ - no_connection2(c2,c1,0); -} - -static nkf_char (*iconv)(nkf_char c2,nkf_char c1,nkf_char c0) = no_connection2; -static void (*oconv)(nkf_char c2,nkf_char c1) = no_connection; - -static void (*o_zconv)(nkf_char c2,nkf_char c1) = no_connection; -static void (*o_fconv)(nkf_char c2,nkf_char c1) = no_connection; -static void (*o_eol_conv)(nkf_char c2,nkf_char c1) = no_connection; -static void (*o_rot_conv)(nkf_char c2,nkf_char c1) = no_connection; -static void (*o_hira_conv)(nkf_char c2,nkf_char c1) = no_connection; -static void (*o_base64conv)(nkf_char c2,nkf_char c1) = no_connection; -static void (*o_iso2022jp_check_conv)(nkf_char c2,nkf_char c1) = no_connection; - -/* static redirections */ - -static void (*o_putc)(nkf_char c) = std_putc; - -static nkf_char (*i_getc)(FILE *f) = std_getc; /* general input */ -static nkf_char (*i_ungetc)(nkf_char c,FILE *f) =std_ungetc; - -static nkf_char (*i_bgetc)(FILE *) = std_getc; /* input of mgetc */ -static nkf_char (*i_bungetc)(nkf_char c ,FILE *f) = std_ungetc; - -static void (*o_mputc)(nkf_char c) = std_putc ; /* output of mputc */ - -static nkf_char (*i_mgetc)(FILE *) = std_getc; /* input of mgetc */ -static nkf_char (*i_mungetc)(nkf_char c ,FILE *f) = std_ungetc; - -/* for strict mime */ -static nkf_char (*i_mgetc_buf)(FILE *) = std_getc; /* input of mgetc_buf */ -static nkf_char (*i_mungetc_buf)(nkf_char c,FILE *f) = std_ungetc; - -/* Global states */ -static int output_mode = ASCII; /* output kanji mode */ -static int input_mode = ASCII; /* input kanji mode */ -static int mime_decode_mode = FALSE; /* MIME mode B base64, Q hex */ - -/* X0201 / X0208 conversion tables */ - -/* X0201 kana conversion table */ -/* 90-9F A0-DF */ -static const unsigned char cv[]= { - 0x21,0x21,0x21,0x23,0x21,0x56,0x21,0x57, - 0x21,0x22,0x21,0x26,0x25,0x72,0x25,0x21, - 0x25,0x23,0x25,0x25,0x25,0x27,0x25,0x29, - 0x25,0x63,0x25,0x65,0x25,0x67,0x25,0x43, - 0x21,0x3c,0x25,0x22,0x25,0x24,0x25,0x26, - 0x25,0x28,0x25,0x2a,0x25,0x2b,0x25,0x2d, - 0x25,0x2f,0x25,0x31,0x25,0x33,0x25,0x35, - 0x25,0x37,0x25,0x39,0x25,0x3b,0x25,0x3d, - 0x25,0x3f,0x25,0x41,0x25,0x44,0x25,0x46, - 0x25,0x48,0x25,0x4a,0x25,0x4b,0x25,0x4c, - 0x25,0x4d,0x25,0x4e,0x25,0x4f,0x25,0x52, - 0x25,0x55,0x25,0x58,0x25,0x5b,0x25,0x5e, - 0x25,0x5f,0x25,0x60,0x25,0x61,0x25,0x62, - 0x25,0x64,0x25,0x66,0x25,0x68,0x25,0x69, - 0x25,0x6a,0x25,0x6b,0x25,0x6c,0x25,0x6d, - 0x25,0x6f,0x25,0x73,0x21,0x2b,0x21,0x2c, - 0x00,0x00}; - - -/* X0201 kana conversion table for dakuten */ -/* 90-9F A0-DF */ -static const unsigned char dv[]= { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x74, - 0x00,0x00,0x00,0x00,0x25,0x2c,0x25,0x2e, - 0x25,0x30,0x25,0x32,0x25,0x34,0x25,0x36, - 0x25,0x38,0x25,0x3a,0x25,0x3c,0x25,0x3e, - 0x25,0x40,0x25,0x42,0x25,0x45,0x25,0x47, - 0x25,0x49,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x25,0x50,0x25,0x53, - 0x25,0x56,0x25,0x59,0x25,0x5c,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00}; - -/* X0201 kana conversion table for han-dakuten */ -/* 90-9F A0-DF */ -static const unsigned char ev[]= { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x25,0x51,0x25,0x54, - 0x25,0x57,0x25,0x5a,0x25,0x5d,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00}; - -/* X0201 kana to X0213 conversion table for han-dakuten */ -/* 90-9F A0-DF */ -static const unsigned char ev_x0213[]= { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x25,0x77,0x25,0x78, - 0x25,0x79,0x25,0x7a,0x25,0x7b,0x00,0x00, - 0x00,0x00,0x00,0x00,0x25,0x7c,0x00,0x00, - 0x00,0x00,0x00,0x00,0x25,0x7d,0x00,0x00, - 0x25,0x7e,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00}; - - -/* X0208 kigou conversion table */ -/* 0x8140 - 0x819e */ -static const unsigned char fv[] = { - - 0x00,0x00,0x00,0x00,0x2c,0x2e,0x00,0x3a, - 0x3b,0x3f,0x21,0x00,0x00,0x27,0x60,0x00, - 0x5e,0x00,0x5f,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x2d,0x00,0x2f, - 0x5c,0x00,0x00,0x7c,0x00,0x00,0x60,0x27, - 0x22,0x22,0x28,0x29,0x00,0x00,0x5b,0x5d, - 0x7b,0x7d,0x3c,0x3e,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x2b,0x2d,0x00,0x00, - 0x00,0x3d,0x00,0x3c,0x3e,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x24,0x00,0x00,0x25,0x23,0x26,0x2a,0x40, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -} ; - - - -static int option_mode = 0; -static int file_out_f = FALSE; -#ifdef OVERWRITE -static int overwrite_f = FALSE; -static int preserve_time_f = FALSE; -static int backup_f = FALSE; -static char *backup_suffix = ""; -#endif - -static int eolmode_f = 0; /* CR, LF, CRLF */ -static int input_eol = 0; /* 0: unestablished, EOF: MIXED */ -static nkf_char prev_cr = 0; /* CR or 0 */ -#ifdef EASYWIN /*Easy Win */ -static int end_check; -#endif /*Easy Win */ - -static void * -nkf_xmalloc(size_t size) -{ - void *ptr; - - if (size == 0) size = 1; - - ptr = malloc(size); - if (ptr == NULL) { - perror("can't malloc"); - exit(EXIT_FAILURE); - } - - return ptr; -} - -static void * -nkf_xrealloc(void *ptr, size_t size) -{ - if (size == 0) size = 1; - - ptr = realloc(ptr, size); - if (ptr == NULL) { - perror("can't realloc"); - exit(EXIT_FAILURE); - } - - return ptr; -} - -#define nkf_xfree(ptr) free(ptr) - -static int -nkf_str_caseeql(const char *src, const char *target) -{ - int i; - for (i = 0; src[i] && target[i]; i++) { - if (nkf_toupper(src[i]) != nkf_toupper(target[i])) return FALSE; - } - if (src[i] || target[i]) return FALSE; - else return TRUE; -} - -static nkf_encoding* -nkf_enc_from_index(int idx) -{ - if (idx < 0 || NKF_ENCODING_TABLE_SIZE <= idx) { - return 0; - } - return &nkf_encoding_table[idx]; -} - -static int -nkf_enc_find_index(const char *name) -{ - int i; - if (name[0] == 'X' && *(name+1) == '-') name += 2; - for (i = 0; encoding_name_to_id_table[i].id >= 0; i++) { - if (nkf_str_caseeql(encoding_name_to_id_table[i].name, name)) { - return encoding_name_to_id_table[i].id; - } - } - return -1; -} - -static nkf_encoding* -nkf_enc_find(const char *name) -{ - int idx = -1; - idx = nkf_enc_find_index(name); - if (idx < 0) return 0; - return nkf_enc_from_index(idx); -} - -#define nkf_enc_name(enc) (enc)->name -#define nkf_enc_to_index(enc) (enc)->id -#define nkf_enc_to_base_encoding(enc) (enc)->base_encoding -#define nkf_enc_to_iconv(enc) nkf_enc_to_base_encoding(enc)->iconv -#define nkf_enc_to_oconv(enc) nkf_enc_to_base_encoding(enc)->oconv -#define nkf_enc_asciicompat(enc) (\ - nkf_enc_to_base_encoding(enc) == &NkfEncodingASCII ||\ - nkf_enc_to_base_encoding(enc) == &NkfEncodingISO_2022_JP) -#define nkf_enc_unicode_p(enc) (\ - nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_8 ||\ - nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_16 ||\ - nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_32) -#define nkf_enc_cp5022x_p(enc) (\ - nkf_enc_to_index(enc) == CP50220 ||\ - nkf_enc_to_index(enc) == CP50221 ||\ - nkf_enc_to_index(enc) == CP50222) - -#ifdef DEFAULT_CODE_LOCALE -static const char* -nkf_locale_charmap(void) -{ -#ifdef HAVE_LANGINFO_H - return nl_langinfo(CODESET); -#elif defined(__WIN32__) - static char buf[16]; - sprintf(buf, "CP%d", GetACP()); - return buf; -#elif defined(__OS2__) -# if defined(INT_IS_SHORT) - /* OS/2 1.x */ - return NULL; -# else - /* OS/2 32bit */ - static char buf[16]; - ULONG ulCP[1], ulncp; - DosQueryCp(sizeof(ulCP), ulCP, &ulncp); - if (ulCP[0] == 932 || ulCP[0] == 943) - strcpy(buf, "Shift_JIS"); - else - sprintf(buf, "CP%lu", ulCP[0]); - return buf; -# endif -#endif - return NULL; -} - -static nkf_encoding* -nkf_locale_encoding(void) -{ - nkf_encoding *enc = 0; - const char *encname = nkf_locale_charmap(); - if (encname) - enc = nkf_enc_find(encname); - return enc; -} -#endif /* DEFAULT_CODE_LOCALE */ - -static nkf_encoding* -nkf_utf8_encoding(void) -{ - return &nkf_encoding_table[UTF_8]; -} - -static nkf_encoding* -nkf_default_encoding(void) -{ - nkf_encoding *enc = 0; -#ifdef DEFAULT_CODE_LOCALE - enc = nkf_locale_encoding(); -#elif defined(DEFAULT_ENCIDX) - enc = nkf_enc_from_index(DEFAULT_ENCIDX); -#endif - if (!enc) enc = nkf_utf8_encoding(); - return enc; -} - -typedef struct { - long capa; - long len; - nkf_char *ptr; -} nkf_buf_t; - -static nkf_buf_t * -nkf_buf_new(int length) -{ - nkf_buf_t *buf = nkf_xmalloc(sizeof(nkf_buf_t)); - buf->ptr = nkf_xmalloc(sizeof(nkf_char) * length); - buf->capa = length; - buf->len = 0; - return buf; -} - -#if 0 -static void -nkf_buf_dispose(nkf_buf_t *buf) -{ - nkf_xfree(buf->ptr); - nkf_xfree(buf); -} -#endif - -#define nkf_buf_length(buf) ((buf)->len) -#define nkf_buf_empty_p(buf) ((buf)->len == 0) - -static nkf_char -nkf_buf_at(nkf_buf_t *buf, int index) -{ - assert(index <= buf->len); - return buf->ptr[index]; -} - -static void -nkf_buf_clear(nkf_buf_t *buf) -{ - buf->len = 0; -} - -static void -nkf_buf_push(nkf_buf_t *buf, nkf_char c) -{ - if (buf->capa <= buf->len) { - exit(EXIT_FAILURE); - } - buf->ptr[buf->len++] = c; -} - -static nkf_char -nkf_buf_pop(nkf_buf_t *buf) -{ - assert(!nkf_buf_empty_p(buf)); - return buf->ptr[--buf->len]; -} - -/* Normalization Form C */ -#ifndef PERL_XS -#ifdef WIN32DLL -#define fprintf dllprintf -#endif - -static void -version(void) -{ - fprintf(HELP_OUTPUT,"Network Kanji Filter Version " NKF_VERSION " (" NKF_RELEASE_DATE ") \n" COPY_RIGHT "\n"); -} - -static void -usage(void) -{ - fprintf(HELP_OUTPUT, - "Usage: nkf -[flags] [--] [in file] .. [out file for -O flag]\n" -#ifdef UTF8_OUTPUT_ENABLE - " j/s/e/w Specify output encoding ISO-2022-JP, Shift_JIS, EUC-JP\n" - " UTF options is -w[8[0],{16,32}[{B,L}[0]]]\n" -#else -#endif -#ifdef UTF8_INPUT_ENABLE - " J/S/E/W Specify input encoding ISO-2022-JP, Shift_JIS, EUC-JP\n" - " UTF option is -W[8,[16,32][B,L]]\n" -#else - " J/S/E Specify output encoding ISO-2022-JP, Shift_JIS, EUC-JP\n" -#endif - ); - fprintf(HELP_OUTPUT, - " m[BQSN0] MIME decode [B:base64,Q:quoted,S:strict,N:nonstrict,0:no decode]\n" - " M[BQ] MIME encode [B:base64 Q:quoted]\n" - " f/F Folding: -f60 or -f or -f60-10 (fold margin 10) F preserve nl\n" - ); - fprintf(HELP_OUTPUT, - " Z[0-4] Default/0: Convert JISX0208 Alphabet to ASCII\n" - " 1: Kankaku to one space 2: to two spaces 3: HTML Entity\n" - " 4: JISX0208 Katakana to JISX0201 Katakana\n" - " X,x Convert Halfwidth Katakana to Fullwidth or preserve it\n" - ); - fprintf(HELP_OUTPUT, - " O Output to File (DEFAULT 'nkf.out')\n" - " L[uwm] Line mode u:LF w:CRLF m:CR (DEFAULT noconversion)\n" - ); - fprintf(HELP_OUTPUT, - " --ic= Specify the input encoding\n" - " --oc= Specify the output encoding\n" - " --hiragana --katakana Hiragana/Katakana Conversion\n" - " --katakana-hiragana Converts each other\n" - ); - fprintf(HELP_OUTPUT, -#ifdef INPUT_OPTION - " --{cap, url}-input Convert hex after ':' or '%%'\n" -#endif -#ifdef NUMCHAR_OPTION - " --numchar-input Convert Unicode Character Reference\n" -#endif -#ifdef UTF8_INPUT_ENABLE - " --fb-{skip, html, xml, perl, java, subchar}\n" - " Specify unassigned character's replacement\n" -#endif - ); - fprintf(HELP_OUTPUT, -#ifdef OVERWRITE - " --in-place[=SUF] Overwrite original files\n" - " --overwrite[=SUF] Preserve timestamp of original files\n" -#endif - " -g --guess Guess the input code\n" - " -v --version Print the version\n" - " --help/-V Print this help / configuration\n" - ); - version(); -} - -static void -show_configuration(void) -{ - fprintf(HELP_OUTPUT, - "Summary of my nkf " NKF_VERSION " (" NKF_RELEASE_DATE ") configuration:\n" - " Compile-time options:\n" - " Compiled at: " __DATE__ " " __TIME__ "\n" - ); - fprintf(HELP_OUTPUT, - " Default output encoding: " -#ifdef DEFAULT_CODE_LOCALE - "LOCALE (%s)\n", nkf_enc_name(nkf_default_encoding()) -#elif defined(DEFAULT_ENCIDX) - "CONFIG (%s)\n", nkf_enc_name(nkf_default_encoding()) -#else - "NONE\n" -#endif - ); - fprintf(HELP_OUTPUT, - " Default output end of line: " -#if DEFAULT_NEWLINE == CR - "CR" -#elif DEFAULT_NEWLINE == CRLF - "CRLF" -#else - "LF" -#endif - "\n" - " Decode MIME encoded string: " -#if MIME_DECODE_DEFAULT - "ON" -#else - "OFF" -#endif - "\n" - " Convert JIS X 0201 Katakana: " -#if X0201_DEFAULT - "ON" -#else - "OFF" -#endif - "\n" - " --help, --version output: " -#if HELP_OUTPUT_HELP_OUTPUT - "HELP_OUTPUT" -#else - "STDOUT" -#endif - "\n"); -} -#endif /*PERL_XS*/ - -#ifdef OVERWRITE -static char* -get_backup_filename(const char *suffix, const char *filename) -{ - char *backup_filename; - int asterisk_count = 0; - int i, j; - int filename_length = strlen(filename); - - for(i = 0; suffix[i]; i++){ - if(suffix[i] == '*') asterisk_count++; - } - - if(asterisk_count){ - backup_filename = nkf_xmalloc(strlen(suffix) + (asterisk_count * (filename_length - 1)) + 1); - for(i = 0, j = 0; suffix[i];){ - if(suffix[i] == '*'){ - backup_filename[j] = '\0'; - strncat(backup_filename, filename, filename_length); - i++; - j += filename_length; - }else{ - backup_filename[j++] = suffix[i++]; - } - } - backup_filename[j] = '\0'; - }else{ - j = filename_length + strlen(suffix); - backup_filename = nkf_xmalloc(j + 1); - strcpy(backup_filename, filename); - strcat(backup_filename, suffix); - backup_filename[j] = '\0'; - } - return backup_filename; -} -#endif - -#ifdef UTF8_INPUT_ENABLE -static void -nkf_each_char_to_hex(void (*f)(nkf_char c2,nkf_char c1), nkf_char c) -{ - int shift = 20; - c &= VALUE_MASK; - while(shift >= 0){ - if(c >= NKF_INT32_C(1)<= 0){ - (*f)(0, bin2hex(c>>shift)); - shift -= 4; - } - }else{ - shift -= 4; - } - } - return; -} - -static void -encode_fallback_html(nkf_char c) -{ - (*oconv)(0, '&'); - (*oconv)(0, '#'); - c &= VALUE_MASK; - if(c >= NKF_INT32_C(1000000)) - (*oconv)(0, 0x30+(c/NKF_INT32_C(1000000))%10); - if(c >= NKF_INT32_C(100000)) - (*oconv)(0, 0x30+(c/NKF_INT32_C(100000) )%10); - if(c >= 10000) - (*oconv)(0, 0x30+(c/10000 )%10); - if(c >= 1000) - (*oconv)(0, 0x30+(c/1000 )%10); - if(c >= 100) - (*oconv)(0, 0x30+(c/100 )%10); - if(c >= 10) - (*oconv)(0, 0x30+(c/10 )%10); - if(c >= 0) - (*oconv)(0, 0x30+ c %10); - (*oconv)(0, ';'); - return; -} - -static void -encode_fallback_xml(nkf_char c) -{ - (*oconv)(0, '&'); - (*oconv)(0, '#'); - (*oconv)(0, 'x'); - nkf_each_char_to_hex(oconv, c); - (*oconv)(0, ';'); - return; -} - -static void -encode_fallback_java(nkf_char c) -{ - (*oconv)(0, '\\'); - c &= VALUE_MASK; - if(!nkf_char_unicode_bmp_p(c)){ - int high = (c >> 10) + NKF_INT32_C(0xD7C0); /* high surrogate */ - int low = (c & 0x3FF) + NKF_INT32_C(0xDC00); /* low surrogate */ - (*oconv)(0, 'u'); - (*oconv)(0, bin2hex(high>>12)); - (*oconv)(0, bin2hex(high>> 8)); - (*oconv)(0, bin2hex(high>> 4)); - (*oconv)(0, bin2hex(high )); - (*oconv)(0, '\\'); - (*oconv)(0, 'u'); - (*oconv)(0, bin2hex(low>>12)); - (*oconv)(0, bin2hex(low>> 8)); - (*oconv)(0, bin2hex(low>> 4)); - (*oconv)(0, bin2hex(low )); - }else{ - (*oconv)(0, 'u'); - (*oconv)(0, bin2hex(c>>12)); - (*oconv)(0, bin2hex(c>> 8)); - (*oconv)(0, bin2hex(c>> 4)); - (*oconv)(0, bin2hex(c )); - } - return; -} - -static void -encode_fallback_perl(nkf_char c) -{ - (*oconv)(0, '\\'); - (*oconv)(0, 'x'); - (*oconv)(0, '{'); - nkf_each_char_to_hex(oconv, c); - (*oconv)(0, '}'); - return; -} - -static void -encode_fallback_subchar(nkf_char c) -{ - c = unicode_subchar; - (*oconv)((c>>8)&0xFF, c&0xFF); - return; -} -#endif - -static const struct { - const char *name; - const char *alias; -} long_option[] = { - {"ic=", ""}, - {"oc=", ""}, - {"base64","jMB"}, - {"euc","e"}, - {"euc-input","E"}, - {"fj","jm"}, - {"help",""}, - {"jis","j"}, - {"jis-input","J"}, - {"mac","sLm"}, - {"mime","jM"}, - {"mime-input","m"}, - {"msdos","sLw"}, - {"sjis","s"}, - {"sjis-input","S"}, - {"unix","eLu"}, - {"version","v"}, - {"windows","sLw"}, - {"hiragana","h1"}, - {"katakana","h2"}, - {"katakana-hiragana","h3"}, - {"guess=", ""}, - {"guess", "g2"}, - {"cp932", ""}, - {"no-cp932", ""}, -#ifdef X0212_ENABLE - {"x0212", ""}, -#endif -#ifdef UTF8_OUTPUT_ENABLE - {"utf8", "w"}, - {"utf16", "w16"}, - {"ms-ucs-map", ""}, - {"fb-skip", ""}, - {"fb-html", ""}, - {"fb-xml", ""}, - {"fb-perl", ""}, - {"fb-java", ""}, - {"fb-subchar", ""}, - {"fb-subchar=", ""}, -#endif -#ifdef UTF8_INPUT_ENABLE - {"utf8-input", "W"}, - {"utf16-input", "W16"}, - {"no-cp932ext", ""}, - {"no-best-fit-chars",""}, -#endif -#ifdef UNICODE_NORMALIZATION - {"utf8mac-input", ""}, -#endif -#ifdef OVERWRITE - {"overwrite", ""}, - {"overwrite=", ""}, - {"in-place", ""}, - {"in-place=", ""}, -#endif -#ifdef INPUT_OPTION - {"cap-input", ""}, - {"url-input", ""}, -#endif -#ifdef NUMCHAR_OPTION - {"numchar-input", ""}, -#endif -#ifdef CHECK_OPTION - {"no-output", ""}, - {"debug", ""}, -#endif -#ifdef SHIFTJIS_CP932 - {"cp932inv", ""}, -#endif -#ifdef EXEC_IO - {"exec-in", ""}, - {"exec-out", ""}, -#endif - {"prefix=", ""}, -}; - -static void -set_input_encoding(nkf_encoding *enc) -{ - switch (nkf_enc_to_index(enc)) { - case ISO_8859_1: - iso8859_f = TRUE; - break; - case CP50221: - case CP50222: - if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */ - case CP50220: -#ifdef SHIFTJIS_CP932 - cp51932_f = TRUE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_CP932; -#endif - break; - case ISO_2022_JP_1: - x0212_f = TRUE; - break; - case ISO_2022_JP_3: - x0212_f = TRUE; - x0213_f = TRUE; - break; - case ISO_2022_JP_2004: - x0212_f = TRUE; - x0213_f = TRUE; - break; - case SHIFT_JIS: - break; - case WINDOWS_31J: - if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */ -#ifdef SHIFTJIS_CP932 - cp51932_f = TRUE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_CP932; -#endif - break; - break; - case CP10001: -#ifdef SHIFTJIS_CP932 - cp51932_f = TRUE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_CP10001; -#endif - break; - case EUC_JP: - break; - case EUCJP_NKF: - break; - case CP51932: - if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */ -#ifdef SHIFTJIS_CP932 - cp51932_f = TRUE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_CP932; -#endif - break; - case EUCJP_MS: - if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */ -#ifdef SHIFTJIS_CP932 - cp51932_f = FALSE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_MS; -#endif - break; - case EUCJP_ASCII: - if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */ -#ifdef SHIFTJIS_CP932 - cp51932_f = FALSE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_ASCII; -#endif - break; - case SHIFT_JISX0213: - case SHIFT_JIS_2004: - x0213_f = TRUE; -#ifdef SHIFTJIS_CP932 - cp51932_f = FALSE; - if (cp932inv_f == TRUE) cp932inv_f = FALSE; -#endif - break; - case EUC_JISX0213: - case EUC_JIS_2004: - x0213_f = TRUE; -#ifdef SHIFTJIS_CP932 - cp51932_f = FALSE; -#endif - break; -#ifdef UTF8_INPUT_ENABLE -#ifdef UNICODE_NORMALIZATION - case UTF8_MAC: - nfc_f = TRUE; - break; -#endif - case UTF_16: - case UTF_16BE: - case UTF_16BE_BOM: - input_endian = ENDIAN_BIG; - break; - case UTF_16LE: - case UTF_16LE_BOM: - input_endian = ENDIAN_LITTLE; - break; - case UTF_32: - case UTF_32BE: - case UTF_32BE_BOM: - input_endian = ENDIAN_BIG; - break; - case UTF_32LE: - case UTF_32LE_BOM: - input_endian = ENDIAN_LITTLE; - break; -#endif - } -} - -static void -set_output_encoding(nkf_encoding *enc) -{ - switch (nkf_enc_to_index(enc)) { - case CP50220: -#ifdef SHIFTJIS_CP932 - if (cp932inv_f == TRUE) cp932inv_f = FALSE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_CP932; -#endif - break; - case CP50221: - if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */ -#ifdef SHIFTJIS_CP932 - if (cp932inv_f == TRUE) cp932inv_f = FALSE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_CP932; -#endif - break; - case ISO_2022_JP: -#ifdef SHIFTJIS_CP932 - if (cp932inv_f == TRUE) cp932inv_f = FALSE; -#endif - break; - case ISO_2022_JP_1: - x0212_f = TRUE; -#ifdef SHIFTJIS_CP932 - if (cp932inv_f == TRUE) cp932inv_f = FALSE; -#endif - break; - case ISO_2022_JP_3: - case ISO_2022_JP_2004: - x0212_f = TRUE; - x0213_f = TRUE; -#ifdef SHIFTJIS_CP932 - if (cp932inv_f == TRUE) cp932inv_f = FALSE; -#endif - break; - case SHIFT_JIS: - break; - case WINDOWS_31J: - if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */ -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_CP932; -#endif - break; - case CP10001: -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_CP10001; -#endif - break; - case EUC_JP: - x0212_f = TRUE; -#ifdef SHIFTJIS_CP932 - if (cp932inv_f == TRUE) cp932inv_f = FALSE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_ASCII; -#endif - break; - case EUCJP_NKF: - x0212_f = FALSE; -#ifdef SHIFTJIS_CP932 - if (cp932inv_f == TRUE) cp932inv_f = FALSE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_ASCII; -#endif - break; - case CP51932: - if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */ -#ifdef SHIFTJIS_CP932 - if (cp932inv_f == TRUE) cp932inv_f = FALSE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_CP932; -#endif - break; - case EUCJP_MS: - if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */ - x0212_f = TRUE; -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_MS; -#endif - break; - case EUCJP_ASCII: - if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */ - x0212_f = TRUE; -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_ASCII; -#endif - break; - case SHIFT_JISX0213: - case SHIFT_JIS_2004: - x0213_f = TRUE; -#ifdef SHIFTJIS_CP932 - if (cp932inv_f == TRUE) cp932inv_f = FALSE; -#endif - break; - case EUC_JISX0213: - case EUC_JIS_2004: - x0212_f = TRUE; - x0213_f = TRUE; -#ifdef SHIFTJIS_CP932 - if (cp932inv_f == TRUE) cp932inv_f = FALSE; -#endif - break; -#ifdef UTF8_OUTPUT_ENABLE - case UTF_8_BOM: - output_bom_f = TRUE; - break; - case UTF_16: - case UTF_16BE_BOM: - output_bom_f = TRUE; - break; - case UTF_16LE: - output_endian = ENDIAN_LITTLE; - output_bom_f = FALSE; - break; - case UTF_16LE_BOM: - output_endian = ENDIAN_LITTLE; - output_bom_f = TRUE; - break; - case UTF_32: - case UTF_32BE_BOM: - output_bom_f = TRUE; - break; - case UTF_32LE: - output_endian = ENDIAN_LITTLE; - output_bom_f = FALSE; - break; - case UTF_32LE_BOM: - output_endian = ENDIAN_LITTLE; - output_bom_f = TRUE; - break; -#endif - } -} - -static struct input_code* -find_inputcode_byfunc(nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0)) -{ - if (iconv_func){ - struct input_code *p = input_code_list; - while (p->name){ - if (iconv_func == p->iconv_func){ - return p; - } - p++; - } - } - return 0; -} - -static void -set_iconv(nkf_char f, nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0)) -{ -#ifdef INPUT_CODE_FIX - if (f || !input_encoding) -#endif - if (estab_f != f){ - estab_f = f; - } - - if (iconv_func -#ifdef INPUT_CODE_FIX - && (f == -TRUE || !input_encoding) /* -TRUE means "FORCE" */ -#endif - ){ - iconv = iconv_func; - } -#ifdef CHECK_OPTION - if (estab_f && iconv_for_check != iconv){ - struct input_code *p = find_inputcode_byfunc(iconv); - if (p){ - set_input_codename(p->name); - debug(p->name); - } - iconv_for_check = iconv; - } -#endif -} - -#ifdef X0212_ENABLE -static nkf_char -x0212_shift(nkf_char c) -{ - nkf_char ret = c; - c &= 0x7f; - if (is_eucg3(ret)){ - if (0x75 <= c && c <= 0x7f){ - ret = c + (0x109 - 0x75); - } - }else{ - if (0x75 <= c && c <= 0x7f){ - ret = c + (0x113 - 0x75); - } - } - return ret; -} - - -static nkf_char -x0212_unshift(nkf_char c) -{ - nkf_char ret = c; - if (0x7f <= c && c <= 0x88){ - ret = c + (0x75 - 0x7f); - }else if (0x89 <= c && c <= 0x92){ - ret = PREFIX_EUCG3 | 0x80 | (c + (0x75 - 0x89)); - } - return ret; -} -#endif /* X0212_ENABLE */ - -static int -is_x0213_2_in_x0212(nkf_char c1) -{ - static const char x0213_2_table[] = - {0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1}; - int ku = c1 - 0x20; - if (ku <= 15) - return x0213_2_table[ku]; /* 1, 3-5, 8, 12-15 */ - if (78 <= ku && ku <= 94) - return 1; - return 0; -} - -static nkf_char -e2s_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1) -{ - nkf_char ndx; - if (is_eucg3(c2)){ - ndx = c2 & 0x7f; - if (x0213_f && is_x0213_2_in_x0212(ndx)){ - if((0x21 <= ndx && ndx <= 0x2F)){ - if (p2) *p2 = ((ndx - 1) >> 1) + 0xec - ndx / 8 * 3; - if (p1) *p1 = c1 + ((ndx & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e); - return 0; - }else if(0x6E <= ndx && ndx <= 0x7E){ - if (p2) *p2 = ((ndx - 1) >> 1) + 0xbe; - if (p1) *p1 = c1 + ((ndx & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e); - return 0; - } - return 1; - } -#ifdef X0212_ENABLE - else if(nkf_isgraph(ndx)){ - nkf_char val = 0; - const unsigned short *ptr; - ptr = x0212_shiftjis[ndx - 0x21]; - if (ptr){ - val = ptr[(c1 & 0x7f) - 0x21]; - } - if (val){ - c2 = val >> 8; - c1 = val & 0xff; - if (p2) *p2 = c2; - if (p1) *p1 = c1; - return 0; - } - c2 = x0212_shift(c2); - } -#endif /* X0212_ENABLE */ - } - if(0x7F < c2) return 1; - if (p2) *p2 = ((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1); - if (p1) *p1 = c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e); - return 0; -} - -static nkf_char -s2e_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1) -{ -#if defined(SHIFTJIS_CP932) || defined(X0212_ENABLE) - nkf_char val; -#endif - static const char shift_jisx0213_s1a3_table[5][2] ={ { 1, 8}, { 3, 4}, { 5,12}, {13,14}, {15, 0} }; - if (0xFC < c1) return 1; -#ifdef SHIFTJIS_CP932 - if (!cp932inv_f && !x0213_f && is_ibmext_in_sjis(c2)){ - val = shiftjis_cp932[c2 - CP932_TABLE_BEGIN][c1 - 0x40]; - if (val){ - c2 = val >> 8; - c1 = val & 0xff; - } - } - if (cp932inv_f - && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){ - val = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40]; - if (val){ - c2 = val >> 8; - c1 = val & 0xff; - } - } -#endif /* SHIFTJIS_CP932 */ -#ifdef X0212_ENABLE - if (!x0213_f && is_ibmext_in_sjis(c2)){ - val = shiftjis_x0212[c2 - 0xfa][c1 - 0x40]; - if (val){ - if (val > 0x7FFF){ - c2 = PREFIX_EUCG3 | ((val >> 8) & 0x7f); - c1 = val & 0xff; - }else{ - c2 = val >> 8; - c1 = val & 0xff; - } - if (p2) *p2 = c2; - if (p1) *p1 = c1; - return 0; - } - } -#endif - if(c2 >= 0x80){ - if(x0213_f && c2 >= 0xF0){ - if(c2 <= 0xF3 || (c2 == 0xF4 && c1 < 0x9F)){ /* k=1, 3<=k<=5, k=8, 12<=k<=15 */ - c2 = PREFIX_EUCG3 | 0x20 | shift_jisx0213_s1a3_table[c2 - 0xF0][0x9E < c1]; - }else{ /* 78<=k<=94 */ - c2 = PREFIX_EUCG3 | (c2 * 2 - 0x17B); - if (0x9E < c1) c2++; - } - }else{ -#define SJ0162 0x00e1 /* 01 - 62 ku offset */ -#define SJ6394 0x0161 /* 63 - 94 ku offset */ - c2 = c2 + c2 - ((c2 <= 0x9F) ? SJ0162 : SJ6394); - if (0x9E < c1) c2++; - } - if (c1 < 0x9F) - c1 = c1 - ((c1 > DEL) ? SP : 0x1F); - else { - c1 = c1 - 0x7E; - } - } - -#ifdef X0212_ENABLE - c2 = x0212_unshift(c2); -#endif - if (p2) *p2 = c2; - if (p1) *p1 = c1; - return 0; -} - -#if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE) -static void -nkf_unicode_to_utf8(nkf_char val, nkf_char *p1, nkf_char *p2, nkf_char *p3, nkf_char *p4) -{ - val &= VALUE_MASK; - if (val < 0x80){ - *p1 = val; - *p2 = 0; - *p3 = 0; - *p4 = 0; - }else if (val < 0x800){ - *p1 = 0xc0 | (val >> 6); - *p2 = 0x80 | (val & 0x3f); - *p3 = 0; - *p4 = 0; - } else if (nkf_char_unicode_bmp_p(val)) { - *p1 = 0xe0 | (val >> 12); - *p2 = 0x80 | ((val >> 6) & 0x3f); - *p3 = 0x80 | ( val & 0x3f); - *p4 = 0; - } else if (nkf_char_unicode_value_p(val)) { - *p1 = 0xf0 | (val >> 18); - *p2 = 0x80 | ((val >> 12) & 0x3f); - *p3 = 0x80 | ((val >> 6) & 0x3f); - *p4 = 0x80 | ( val & 0x3f); - } else { - *p1 = 0; - *p2 = 0; - *p3 = 0; - *p4 = 0; - } -} - -static nkf_char -nkf_utf8_to_unicode(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4) -{ - nkf_char wc; - if (c1 <= 0x7F) { - /* single byte */ - wc = c1; - } - else if (c1 <= 0xC1) { - /* trail byte or invalid */ - return -1; - } - else if (c1 <= 0xDF) { - /* 2 bytes */ - wc = (c1 & 0x1F) << 6; - wc |= (c2 & 0x3F); - } - else if (c1 <= 0xEF) { - /* 3 bytes */ - wc = (c1 & 0x0F) << 12; - wc |= (c2 & 0x3F) << 6; - wc |= (c3 & 0x3F); - } - else if (c2 <= 0xF4) { - /* 4 bytes */ - wc = (c1 & 0x0F) << 18; - wc |= (c2 & 0x3F) << 12; - wc |= (c3 & 0x3F) << 6; - wc |= (c4 & 0x3F); - } - else { - return -1; - } - return wc; -} -#endif - -#ifdef UTF8_INPUT_ENABLE -static int -unicode_to_jis_common2(nkf_char c1, nkf_char c0, - const unsigned short *const *pp, nkf_char psize, - nkf_char *p2, nkf_char *p1) -{ - nkf_char c2; - const unsigned short *p; - unsigned short val; - - if (pp == 0) return 1; - - c1 -= 0x80; - if (c1 < 0 || psize <= c1) return 1; - p = pp[c1]; - if (p == 0) return 1; - - c0 -= 0x80; - if (c0 < 0 || sizeof_utf8_to_euc_C2 <= c0) return 1; - val = p[c0]; - if (val == 0) return 1; - if (no_cp932ext_f && ( - (val>>8) == 0x2D || /* NEC special characters */ - val > NKF_INT32_C(0xF300) /* IBM extended characters */ - )) return 1; - - c2 = val >> 8; - if (val > 0x7FFF){ - c2 &= 0x7f; - c2 |= PREFIX_EUCG3; - } - if (c2 == SO) c2 = JIS_X_0201_1976_K; - c1 = val & 0xFF; - if (p2) *p2 = c2; - if (p1) *p1 = c1; - return 0; -} - -static int -unicode_to_jis_common(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char *p1) -{ - const unsigned short *const *pp; - const unsigned short *const *const *ppp; - static const char no_best_fit_chars_table_C2[] = - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 2, 1, 1, 2, - 0, 0, 1, 1, 0, 1, 0, 1, 2, 1, 1, 1, 1, 1, 1, 1}; - static const char no_best_fit_chars_table_C2_ms[] = - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, - 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0}; - static const char no_best_fit_chars_table_932_C2[] = - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0}; - static const char no_best_fit_chars_table_932_C3[] = - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1}; - nkf_char ret = 0; - - if(c2 < 0x80){ - *p2 = 0; - *p1 = c2; - }else if(c2 < 0xe0){ - if(no_best_fit_chars_f){ - if(ms_ucs_map_f == UCS_MAP_CP932){ - switch(c2){ - case 0xC2: - if(no_best_fit_chars_table_932_C2[c1&0x3F]) return 1; - break; - case 0xC3: - if(no_best_fit_chars_table_932_C3[c1&0x3F]) return 1; - break; - } - }else if(!cp932inv_f){ - switch(c2){ - case 0xC2: - if(no_best_fit_chars_table_C2[c1&0x3F]) return 1; - break; - case 0xC3: - if(no_best_fit_chars_table_932_C3[c1&0x3F]) return 1; - break; - } - }else if(ms_ucs_map_f == UCS_MAP_MS){ - if(c2 == 0xC2 && no_best_fit_chars_table_C2_ms[c1&0x3F]) return 1; - }else if(ms_ucs_map_f == UCS_MAP_CP10001){ - switch(c2){ - case 0xC2: - switch(c1){ - case 0xA2: - case 0xA3: - case 0xA5: - case 0xA6: - case 0xAC: - case 0xAF: - case 0xB8: - return 1; - } - break; - } - } - } - pp = - ms_ucs_map_f == UCS_MAP_CP932 ? utf8_to_euc_2bytes_932 : - ms_ucs_map_f == UCS_MAP_MS ? utf8_to_euc_2bytes_ms : - ms_ucs_map_f == UCS_MAP_CP10001 ? utf8_to_euc_2bytes_mac : - x0213_f ? utf8_to_euc_2bytes_x0213 : - utf8_to_euc_2bytes; - ret = unicode_to_jis_common2(c2, c1, pp, sizeof_utf8_to_euc_2bytes, p2, p1); - }else if(c0 < 0xF0){ - if(no_best_fit_chars_f){ - if(ms_ucs_map_f == UCS_MAP_CP932){ - if(c2 == 0xE3 && c1 == 0x82 && c0 == 0x94) return 1; - }else if(ms_ucs_map_f == UCS_MAP_MS){ - switch(c2){ - case 0xE2: - switch(c1){ - case 0x80: - if(c0 == 0x94 || c0 == 0x96 || c0 == 0xBE) return 1; - break; - case 0x88: - if(c0 == 0x92) return 1; - break; - } - break; - case 0xE3: - if(c1 == 0x80 || c0 == 0x9C) return 1; - break; - } - }else if(ms_ucs_map_f == UCS_MAP_CP10001){ - switch(c2){ - case 0xE3: - switch(c1){ - case 0x82: - if(c0 == 0x94) return 1; - break; - case 0x83: - if(c0 == 0xBB) return 1; - break; - } - break; - } - }else{ - switch(c2){ - case 0xE2: - switch(c1){ - case 0x80: - if(c0 == 0x95) return 1; - break; - case 0x88: - if(c0 == 0xA5) return 1; - break; - } - break; - case 0xEF: - switch(c1){ - case 0xBC: - if(c0 == 0x8D) return 1; - break; - case 0xBD: - if(c0 == 0x9E && !cp932inv_f) return 1; - break; - case 0xBF: - if(0xA0 <= c0 && c0 <= 0xA5) return 1; - break; - } - break; - } - } - } - ppp = - ms_ucs_map_f == UCS_MAP_CP932 ? utf8_to_euc_3bytes_932 : - ms_ucs_map_f == UCS_MAP_MS ? utf8_to_euc_3bytes_ms : - ms_ucs_map_f == UCS_MAP_CP10001 ? utf8_to_euc_3bytes_mac : - x0213_f ? utf8_to_euc_3bytes_x0213 : - utf8_to_euc_3bytes; - ret = unicode_to_jis_common2(c1, c0, ppp[c2 - 0xE0], sizeof_utf8_to_euc_C2, p2, p1); - }else return -1; -#ifdef SHIFTJIS_CP932 - if (!ret&& is_eucg3(*p2)) { - if (cp932inv_f) { - if (encode_fallback) ret = 1; - } - else { - nkf_char s2, s1; - if (e2s_conv(*p2, *p1, &s2, &s1) == 0) { - s2e_conv(s2, s1, p2, p1); - }else{ - ret = 1; - } - } - } -#endif - return ret; -} - -#ifdef UTF8_OUTPUT_ENABLE -#define X0213_SURROGATE_FIND(tbl, size, euc) do { \ - int i; \ - for (i = 0; i < size; i++) \ - if (tbl[i][0] == euc) { \ - low = tbl[i][2]; \ - break; \ - } \ - } while (0) - -static nkf_char -e2w_conv(nkf_char c2, nkf_char c1) -{ - const unsigned short *p; - - if (c2 == JIS_X_0201_1976_K) { - if (ms_ucs_map_f == UCS_MAP_CP10001) { - switch (c1) { - case 0x20: - return 0xA0; - case 0x7D: - return 0xA9; - } - } - p = euc_to_utf8_1byte; -#ifdef X0212_ENABLE - } else if (is_eucg3(c2)){ - if(ms_ucs_map_f == UCS_MAP_ASCII&& c2 == NKF_INT32_C(0x8F22) && c1 == 0x43){ - return 0xA6; - } - c2 = (c2&0x7f) - 0x21; - if (0<=c2 && c2= sizeof_x0213_combining_chars) - return 0; - euc = (c2&0x7f)<<8 | (c1&0x7f); - for (i = 0; i < sizeof_x0213_combining_table; i++) - if (x0213_combining_table[i][0] == euc) - return x0213_combining_table[i][1]; - return 0; -} -#endif - -static nkf_char -w2e_conv(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char *p1) -{ - nkf_char ret = 0; - - if (!c1){ - *p2 = 0; - *p1 = c2; - }else if (0xc0 <= c2 && c2 <= 0xef) { - ret = unicode_to_jis_common(c2, c1, c0, p2, p1); -#ifdef NUMCHAR_OPTION - if (ret > 0){ - if (p2) *p2 = 0; - if (p1) *p1 = nkf_char_unicode_new(nkf_utf8_to_unicode(c2, c1, c0, 0)); - ret = 0; - } -#endif - } - return ret; -} - -#ifdef UTF8_INPUT_ENABLE -static nkf_char -w16e_conv(nkf_char val, nkf_char *p2, nkf_char *p1) -{ - nkf_char c1, c2, c3, c4; - nkf_char ret = 0; - val &= VALUE_MASK; - if (val < 0x80) { - *p2 = 0; - *p1 = val; - } - else if (nkf_char_unicode_bmp_p(val)){ - nkf_unicode_to_utf8(val, &c1, &c2, &c3, &c4); - ret = unicode_to_jis_common(c1, c2, c3, p2, p1); - if (ret > 0){ - *p2 = 0; - *p1 = nkf_char_unicode_new(val); - ret = 0; - } - } - else { - int i; - if (x0213_f) { - c1 = (val >> 10) + NKF_INT32_C(0xD7C0); /* high surrogate */ - c2 = (val & 0x3FF) + NKF_INT32_C(0xDC00); /* low surrogate */ - for (i = 0; i < sizeof_x0213_1_surrogate_table; i++) - if (x0213_1_surrogate_table[i][1] == c1 && x0213_1_surrogate_table[i][2] == c2) { - val = x0213_1_surrogate_table[i][0]; - *p2 = val >> 8; - *p1 = val & 0xFF; - return 0; - } - for (i = 0; i < sizeof_x0213_2_surrogate_table; i++) - if (x0213_2_surrogate_table[i][1] == c1 && x0213_2_surrogate_table[i][2] == c2) { - val = x0213_2_surrogate_table[i][0]; - *p2 = PREFIX_EUCG3 | (val >> 8); - *p1 = val & 0xFF; - return 0; - } - } - *p2 = 0; - *p1 = nkf_char_unicode_new(val); - } - return ret; -} -#endif - -static nkf_char -e_iconv(nkf_char c2, nkf_char c1, nkf_char c0) -{ - if (c2 == JIS_X_0201_1976_K || c2 == SS2){ - if (iso2022jp_f && !x0201_f) { - c2 = GETA1; c1 = GETA2; - } else { - c2 = JIS_X_0201_1976_K; - c1 &= 0x7f; - } -#ifdef X0212_ENABLE - }else if (c2 == 0x8f){ - if (c0 == 0){ - return -1; - } - if (!cp51932_f && !x0213_f && 0xF5 <= c1 && c1 <= 0xFE && 0xA1 <= c0 && c0 <= 0xFE) { - /* encoding is eucJP-ms, so invert to Unicode Private User Area */ - c1 = nkf_char_unicode_new((c1 - 0xF5) * 94 + c0 - 0xA1 + 0xE3AC); - c2 = 0; - } else { - c2 = (c2 << 8) | (c1 & 0x7f); - c1 = c0 & 0x7f; -#ifdef SHIFTJIS_CP932 - if (cp51932_f){ - nkf_char s2, s1; - if (e2s_conv(c2, c1, &s2, &s1) == 0){ - s2e_conv(s2, s1, &c2, &c1); - if (c2 < 0x100){ - c1 &= 0x7f; - c2 &= 0x7f; - } - } - } -#endif /* SHIFTJIS_CP932 */ - } -#endif /* X0212_ENABLE */ - } else if ((c2 == EOF) || (c2 == 0) || c2 < SP || c2 == ISO_8859_1) { - /* NOP */ - } else { - if (!cp51932_f && ms_ucs_map_f && 0xF5 <= c2 && c2 <= 0xFE && 0xA1 <= c1 && c1 <= 0xFE) { - /* encoding is eucJP-ms, so invert to Unicode Private User Area */ - c1 = nkf_char_unicode_new((c2 - 0xF5) * 94 + c1 - 0xA1 + 0xE000); - c2 = 0; - } else { - c1 &= 0x7f; - c2 &= 0x7f; -#ifdef SHIFTJIS_CP932 - if (cp51932_f && 0x79 <= c2 && c2 <= 0x7c){ - nkf_char s2, s1; - if (e2s_conv(c2, c1, &s2, &s1) == 0){ - s2e_conv(s2, s1, &c2, &c1); - if (c2 < 0x100){ - c1 &= 0x7f; - c2 &= 0x7f; - } - } - } -#endif /* SHIFTJIS_CP932 */ - } - } - (*oconv)(c2, c1); - return 0; -} - -static nkf_char -s_iconv(ARG_UNUSED nkf_char c2, nkf_char c1, ARG_UNUSED nkf_char c0) -{ - if (c2 == JIS_X_0201_1976_K || (0xA1 <= c2 && c2 <= 0xDF)) { - if (iso2022jp_f && !x0201_f) { - c2 = GETA1; c1 = GETA2; - } else { - c1 &= 0x7f; - } - } else if ((c2 == EOF) || (c2 == 0) || c2 < SP) { - /* NOP */ - } else if (!x0213_f && 0xF0 <= c2 && c2 <= 0xF9 && 0x40 <= c1 && c1 <= 0xFC) { - /* CP932 UDC */ - if(c1 == 0x7F) return 0; - c1 = nkf_char_unicode_new((c2 - 0xF0) * 188 + (c1 - 0x40 - (0x7E < c1)) + 0xE000); - c2 = 0; - } else { - nkf_char ret = s2e_conv(c2, c1, &c2, &c1); - if (ret) return ret; - } - (*oconv)(c2, c1); - return 0; -} - -static int -x0213_wait_combining_p(nkf_char wc) -{ - int i; - for (i = 0; i < sizeof_x0213_combining_table; i++) { - if (x0213_combining_table[i][1] == wc) { - return TRUE; - } - } - return FALSE; -} - -static int -x0213_combining_p(nkf_char wc) -{ - int i; - for (i = 0; i < sizeof_x0213_combining_chars; i++) { - if (x0213_combining_chars[i] == wc) { - return TRUE; - } - } - return FALSE; -} - -static nkf_char -w_iconv(nkf_char c1, nkf_char c2, nkf_char c3) -{ - nkf_char ret = 0, c4 = 0; - static const char w_iconv_utf8_1st_byte[] = - { /* 0xC0 - 0xFF */ - 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 33, 33, - 40, 41, 41, 41, 42, 43, 43, 43, 50, 50, 50, 50, 60, 60, 70, 70}; - - if (c3 > 0xFF) { - c4 = c3 & 0xFF; - c3 >>= 8; - } - - if (c1 < 0 || 0xff < c1) { - }else if (c1 == 0) { /* 0 : 1 byte*/ - c3 = 0; - } else if ((c1 & 0xC0) == 0x80) { /* 0x80-0xbf : trail byte */ - return 0; - } else{ - switch (w_iconv_utf8_1st_byte[c1 - 0xC0]) { - case 21: - if (c2 < 0x80 || 0xBF < c2) return 0; - break; - case 30: - if (c3 == 0) return -1; - if (c2 < 0xA0 || 0xBF < c2 || (c3 & 0xC0) != 0x80) - return 0; - break; - case 31: - case 33: - if (c3 == 0) return -1; - if ((c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80) - return 0; - break; - case 32: - if (c3 == 0) return -1; - if (c2 < 0x80 || 0x9F < c2 || (c3 & 0xC0) != 0x80) - return 0; - break; - case 40: - if (c3 == 0) return -2; - if (c2 < 0x90 || 0xBF < c2 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) - return 0; - break; - case 41: - if (c3 == 0) return -2; - if (c2 < 0x80 || 0xBF < c2 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) - return 0; - break; - case 42: - if (c3 == 0) return -2; - if (c2 < 0x80 || 0x8F < c2 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) - return 0; - break; - default: - return 0; - break; - } - } - if (c1 == 0 || c1 == EOF){ - } else if ((c1 & 0xf8) == 0xf0) { /* 4 bytes */ - c2 = nkf_char_unicode_new(nkf_utf8_to_unicode(c1, c2, c3, c4)); - c1 = 0; - } else { - if (x0213_f && x0213_wait_combining_p(nkf_utf8_to_unicode(c1, c2, c3, c4))) - return -3; - ret = w2e_conv(c1, c2, c3, &c1, &c2); - } - if (ret == 0){ - (*oconv)(c1, c2); - } - return ret; -} - -static nkf_char -w_iconv_nocombine(nkf_char c1, nkf_char c2, nkf_char c3) -{ - /* continue from the line below 'return -3;' in w_iconv() */ - nkf_char ret = w2e_conv(c1, c2, c3, &c1, &c2); - if (ret == 0){ - (*oconv)(c1, c2); - } - return ret; -} - -#define NKF_ICONV_INVALID_CODE_RANGE -13 -#define NKF_ICONV_WAIT_COMBINING_CHAR -14 -#define NKF_ICONV_NOT_COMBINED -15 -static size_t -unicode_iconv(nkf_char wc, int nocombine) -{ - nkf_char c1, c2; - int ret = 0; - - if (wc < 0x80) { - c2 = 0; - c1 = wc; - }else if ((wc>>11) == 27) { - /* unpaired surrogate */ - return NKF_ICONV_INVALID_CODE_RANGE; - }else if (wc < 0xFFFF) { - if (!nocombine && x0213_f && x0213_wait_combining_p(wc)) - return NKF_ICONV_WAIT_COMBINING_CHAR; - ret = w16e_conv(wc, &c2, &c1); - if (ret) return ret; - }else if (wc < 0x10FFFF) { - c2 = 0; - c1 = nkf_char_unicode_new(wc); - } else { - return NKF_ICONV_INVALID_CODE_RANGE; - } - (*oconv)(c2, c1); - return 0; -} - -static nkf_char -unicode_iconv_combine(nkf_char wc, nkf_char wc2) -{ - nkf_char c1, c2; - int i; - - if (wc2 < 0x80) { - return NKF_ICONV_NOT_COMBINED; - }else if ((wc2>>11) == 27) { - /* unpaired surrogate */ - return NKF_ICONV_INVALID_CODE_RANGE; - }else if (wc2 < 0xFFFF) { - if (!x0213_combining_p(wc2)) - return NKF_ICONV_NOT_COMBINED; - for (i = 0; i < sizeof_x0213_combining_table; i++) { - if (x0213_combining_table[i][1] == wc && - x0213_combining_table[i][2] == wc2) { - c2 = x0213_combining_table[i][0] >> 8; - c1 = x0213_combining_table[i][0] & 0x7f; - (*oconv)(c2, c1); - return 0; - } - } - }else if (wc2 < 0x10FFFF) { - return NKF_ICONV_NOT_COMBINED; - } else { - return NKF_ICONV_INVALID_CODE_RANGE; - } - return NKF_ICONV_NOT_COMBINED; -} - -static nkf_char -w_iconv_combine(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4, nkf_char c5, nkf_char c6) -{ - nkf_char wc, wc2; - wc = nkf_utf8_to_unicode(c1, c2, c3, 0); - wc2 = nkf_utf8_to_unicode(c4, c5, c6, 0); - if (wc2 < 0) - return wc2; - return unicode_iconv_combine(wc, wc2); -} - -#define NKF_ICONV_NEED_ONE_MORE_BYTE (size_t)-1 -#define NKF_ICONV_NEED_TWO_MORE_BYTES (size_t)-2 -static size_t -nkf_iconv_utf_16(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4) -{ - nkf_char wc; - - if (c1 == EOF) { - (*oconv)(EOF, 0); - return 0; - } - - if (input_endian == ENDIAN_BIG) { - if (0xD8 <= c1 && c1 <= 0xDB) { - if (0xDC <= c3 && c3 <= 0xDF) { - wc = UTF16_TO_UTF32(c1 << 8 | c2, c3 << 8 | c4); - } else return NKF_ICONV_NEED_TWO_MORE_BYTES; - } else { - wc = c1 << 8 | c2; - } - } else { - if (0xD8 <= c2 && c2 <= 0xDB) { - if (0xDC <= c4 && c4 <= 0xDF) { - wc = UTF16_TO_UTF32(c2 << 8 | c1, c4 << 8 | c3); - } else return NKF_ICONV_NEED_TWO_MORE_BYTES; - } else { - wc = c2 << 8 | c1; - } - } - - return (*unicode_iconv)(wc, FALSE); -} - -static size_t -nkf_iconv_utf_16_combine(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4) -{ - nkf_char wc, wc2; - - if (input_endian == ENDIAN_BIG) { - if (0xD8 <= c3 && c3 <= 0xDB) { - return NKF_ICONV_NOT_COMBINED; - } else { - wc = c1 << 8 | c2; - wc2 = c3 << 8 | c4; - } - } else { - if (0xD8 <= c2 && c2 <= 0xDB) { - return NKF_ICONV_NOT_COMBINED; - } else { - wc = c2 << 8 | c1; - wc2 = c4 << 8 | c3; - } - } - - return unicode_iconv_combine(wc, wc2); -} - -static size_t -nkf_iconv_utf_16_nocombine(nkf_char c1, nkf_char c2) -{ - nkf_char wc; - if (input_endian == ENDIAN_BIG) - wc = c1 << 8 | c2; - else - wc = c2 << 8 | c1; - return (*unicode_iconv)(wc, TRUE); -} - -static nkf_char -w_iconv16(nkf_char c2, nkf_char c1, ARG_UNUSED nkf_char c0) -{ - (*oconv)(c2, c1); - return 16; /* different from w_iconv32 */ -} - -static nkf_char -w_iconv32(nkf_char c2, nkf_char c1, ARG_UNUSED nkf_char c0) -{ - (*oconv)(c2, c1); - return 32; /* different from w_iconv16 */ -} - -static nkf_char -utf32_to_nkf_char(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4) -{ - nkf_char wc; - - switch(input_endian){ - case ENDIAN_BIG: - wc = c2 << 16 | c3 << 8 | c4; - break; - case ENDIAN_LITTLE: - wc = c3 << 16 | c2 << 8 | c1; - break; - case ENDIAN_2143: - wc = c1 << 16 | c4 << 8 | c3; - break; - case ENDIAN_3412: - wc = c4 << 16 | c1 << 8 | c2; - break; - default: - return NKF_ICONV_INVALID_CODE_RANGE; - } - return wc; -} - -static size_t -nkf_iconv_utf_32(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4) -{ - nkf_char wc; - - if (c1 == EOF) { - (*oconv)(EOF, 0); - return 0; - } - - wc = utf32_to_nkf_char(c1, c2, c3, c4); - if (wc < 0) - return wc; - - return (*unicode_iconv)(wc, FALSE); -} - -static nkf_char -nkf_iconv_utf_32_combine(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4, nkf_char c5, nkf_char c6, nkf_char c7, nkf_char c8) -{ - nkf_char wc, wc2; - - wc = utf32_to_nkf_char(c1, c2, c3, c4); - if (wc < 0) - return wc; - wc2 = utf32_to_nkf_char(c5, c6, c7, c8); - if (wc2 < 0) - return wc2; - - return unicode_iconv_combine(wc, wc2); -} - -static size_t -nkf_iconv_utf_32_nocombine(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4) -{ - nkf_char wc; - - wc = utf32_to_nkf_char(c1, c2, c3, c4); - return (*unicode_iconv)(wc, TRUE); -} -#endif - -#define output_ascii_escape_sequence(mode) do { \ - if (output_mode != ASCII && output_mode != ISO_8859_1) { \ - (*o_putc)(ESC); \ - (*o_putc)('('); \ - (*o_putc)(ascii_intro); \ - output_mode = mode; \ - } \ - } while (0) - -static void -output_escape_sequence(int mode) -{ - if (output_mode == mode) - return; - switch(mode) { - case ISO_8859_1: - (*o_putc)(ESC); - (*o_putc)('.'); - (*o_putc)('A'); - break; - case JIS_X_0201_1976_K: - (*o_putc)(ESC); - (*o_putc)('('); - (*o_putc)('I'); - break; - case JIS_X_0208: - (*o_putc)(ESC); - (*o_putc)('$'); - (*o_putc)(kanji_intro); - break; - case JIS_X_0212: - (*o_putc)(ESC); - (*o_putc)('$'); - (*o_putc)('('); - (*o_putc)('D'); - break; - case JIS_X_0213_1: - (*o_putc)(ESC); - (*o_putc)('$'); - (*o_putc)('('); - (*o_putc)('Q'); - break; - case JIS_X_0213_2: - (*o_putc)(ESC); - (*o_putc)('$'); - (*o_putc)('('); - (*o_putc)('P'); - break; - } - output_mode = mode; -} - -static void -j_oconv(nkf_char c2, nkf_char c1) -{ -#ifdef NUMCHAR_OPTION - if (c2 == 0 && nkf_char_unicode_p(c1)){ - w16e_conv(c1, &c2, &c1); - if (c2 == 0 && nkf_char_unicode_p(c1)){ - c2 = c1 & VALUE_MASK; - if (ms_ucs_map_f && 0xE000 <= c2 && c2 <= 0xE757) { - /* CP5022x UDC */ - c1 &= 0xFFF; - c2 = 0x7F + c1 / 94; - c1 = 0x21 + c1 % 94; - } else { - if (encode_fallback) (*encode_fallback)(c1); - return; - } - } - } -#endif - if (c2 == 0) { - output_ascii_escape_sequence(ASCII); - (*o_putc)(c1); - } - else if (c2 == EOF) { - output_ascii_escape_sequence(ASCII); - (*o_putc)(EOF); - } - else if (c2 == ISO_8859_1) { - output_ascii_escape_sequence(ISO_8859_1); - (*o_putc)(c1|0x80); - } - else if (c2 == JIS_X_0201_1976_K) { - output_escape_sequence(JIS_X_0201_1976_K); - (*o_putc)(c1); -#ifdef X0212_ENABLE - } else if (is_eucg3(c2)){ - output_escape_sequence(x0213_f ? JIS_X_0213_2 : JIS_X_0212); - (*o_putc)(c2 & 0x7f); - (*o_putc)(c1); -#endif - } else { - if(ms_ucs_map_f - ? c2<0x20 || 0x92 0x3e); - (*o_putc)(c2); - (*o_putc)(c1); - return; - } else { - if(encode_fallback)(*encode_fallback)(c1); - return; - } - } - } -#endif - if (c2 == EOF) { - (*o_putc)(EOF); - return; - } else if (c2 == 0) { - output_mode = ASCII; - (*o_putc)(c1); - } else if (c2 == JIS_X_0201_1976_K) { - output_mode = SHIFT_JIS; - (*o_putc)(c1|0x80); - } else if (c2 == ISO_8859_1) { - output_mode = ISO_8859_1; - (*o_putc)(c1 | 0x080); -#ifdef X0212_ENABLE - } else if (is_eucg3(c2)){ - output_mode = SHIFT_JIS; - if (e2s_conv(c2, c1, &c2, &c1) == 0){ - (*o_putc)(c2); - (*o_putc)(c1); - } -#endif - } else { - if (!nkf_isprint(c1) || !nkf_isprint(c2)) { - set_iconv(FALSE, 0); - return; /* too late to rescue this char */ - } - output_mode = SHIFT_JIS; - e2s_conv(c2, c1, &c2, &c1); - -#ifdef SHIFTJIS_CP932 - if (cp932inv_f - && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){ - nkf_char c = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40]; - if (c){ - c2 = c >> 8; - c1 = c & 0xff; - } - } -#endif /* SHIFTJIS_CP932 */ - - (*o_putc)(c2); - if (prefix_table[(unsigned char)c1]){ - (*o_putc)(prefix_table[(unsigned char)c1]); - } - (*o_putc)(c1); - } -} - -#ifdef UTF8_OUTPUT_ENABLE -#define OUTPUT_UTF8(val) do { \ - nkf_unicode_to_utf8(val, &c1, &c2, &c3, &c4); \ - (*o_putc)(c1); \ - if (c2) (*o_putc)(c2); \ - if (c3) (*o_putc)(c3); \ - if (c4) (*o_putc)(c4); \ - } while (0) - -static void -w_oconv(nkf_char c2, nkf_char c1) -{ - nkf_char c3, c4; - nkf_char val, val2; - - if (output_bom_f) { - output_bom_f = FALSE; - (*o_putc)('\357'); - (*o_putc)('\273'); - (*o_putc)('\277'); - } - - if (c2 == EOF) { - (*o_putc)(EOF); - return; - } - - if (c2 == 0 && nkf_char_unicode_p(c1)){ - val = c1 & VALUE_MASK; - OUTPUT_UTF8(val); - return; - } - - if (c2 == 0) { - (*o_putc)(c1); - } else { - val = e2w_conv(c2, c1); - if (val){ - val2 = e2w_combining(val, c2, c1); - if (val2) - OUTPUT_UTF8(val2); - OUTPUT_UTF8(val); - } - } -} - -#define OUTPUT_UTF16_BYTES(c1, c2) do { \ - if (output_endian == ENDIAN_LITTLE){ \ - (*o_putc)(c1); \ - (*o_putc)(c2); \ - }else{ \ - (*o_putc)(c2); \ - (*o_putc)(c1); \ - } \ - } while (0) - -#define OUTPUT_UTF16(val) do { \ - if (nkf_char_unicode_bmp_p(val)) { \ - c2 = (val >> 8) & 0xff; \ - c1 = val & 0xff; \ - OUTPUT_UTF16_BYTES(c1, c2); \ - } else { \ - val &= VALUE_MASK; \ - if (val <= UNICODE_MAX) { \ - c2 = (val >> 10) + NKF_INT32_C(0xD7C0); /* high surrogate */ \ - c1 = (val & 0x3FF) + NKF_INT32_C(0xDC00); /* low surrogate */ \ - OUTPUT_UTF16_BYTES(c2 & 0xff, (c2 >> 8) & 0xff); \ - OUTPUT_UTF16_BYTES(c1 & 0xff, (c1 >> 8) & 0xff); \ - } \ - } \ - } while (0) - -static void -w_oconv16(nkf_char c2, nkf_char c1) -{ - if (output_bom_f) { - output_bom_f = FALSE; - OUTPUT_UTF16_BYTES(0xFF, 0xFE); - } - - if (c2 == EOF) { - (*o_putc)(EOF); - return; - } - - if (c2 == 0 && nkf_char_unicode_p(c1)) { - OUTPUT_UTF16(c1); - } else if (c2) { - nkf_char val, val2; - val = e2w_conv(c2, c1); - if (!val) return; - val2 = e2w_combining(val, c2, c1); - if (val2) - OUTPUT_UTF16(val2); - OUTPUT_UTF16(val); - } else { - OUTPUT_UTF16_BYTES(c1, c2); - } -} - -#define OUTPUT_UTF32(c) do { \ - if (output_endian == ENDIAN_LITTLE){ \ - (*o_putc)( (c) & 0xFF); \ - (*o_putc)(((c) >> 8) & 0xFF); \ - (*o_putc)(((c) >> 16) & 0xFF); \ - (*o_putc)(0); \ - }else{ \ - (*o_putc)(0); \ - (*o_putc)(((c) >> 16) & 0xFF); \ - (*o_putc)(((c) >> 8) & 0xFF); \ - (*o_putc)( (c) & 0xFF); \ - } \ - } while (0) - -static void -w_oconv32(nkf_char c2, nkf_char c1) -{ - if (output_bom_f) { - output_bom_f = FALSE; - if (output_endian == ENDIAN_LITTLE){ - (*o_putc)(0xFF); - (*o_putc)(0xFE); - (*o_putc)(0); - (*o_putc)(0); - }else{ - (*o_putc)(0); - (*o_putc)(0); - (*o_putc)(0xFE); - (*o_putc)(0xFF); - } - } - - if (c2 == EOF) { - (*o_putc)(EOF); - return; - } - - if (c2 == ISO_8859_1) { - c1 |= 0x80; - } else if (c2 == 0 && nkf_char_unicode_p(c1)) { - c1 &= VALUE_MASK; - } else if (c2) { - nkf_char val, val2; - val = e2w_conv(c2, c1); - if (!val) return; - val2 = e2w_combining(val, c2, c1); - if (val2) - OUTPUT_UTF32(val2); - c1 = val; - } - OUTPUT_UTF32(c1); -} -#endif - -#define SCORE_L2 (1) /* Kanji Level 2 */ -#define SCORE_KANA (SCORE_L2 << 1) /* Halfwidth Katakana */ -#define SCORE_DEPEND (SCORE_KANA << 1) /* MD Characters */ -#define SCORE_CP932 (SCORE_DEPEND << 1) /* IBM extended characters */ -#define SCORE_X0212 (SCORE_CP932 << 1) /* JIS X 0212 */ -#define SCORE_X0213 (SCORE_X0212 << 1) /* JIS X 0213 */ -#define SCORE_NO_EXIST (SCORE_X0213 << 1) /* Undefined Characters */ -#define SCORE_iMIME (SCORE_NO_EXIST << 1) /* MIME selected */ -#define SCORE_ERROR (SCORE_iMIME << 1) /* Error */ - -#define SCORE_INIT (SCORE_iMIME) - -static const nkf_char score_table_A0[] = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND, - SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND, SCORE_X0213, -}; - -static const nkf_char score_table_F0[] = { - SCORE_L2, SCORE_L2, SCORE_L2, SCORE_L2, - SCORE_L2, SCORE_DEPEND, SCORE_X0213, SCORE_X0213, - SCORE_DEPEND, SCORE_DEPEND, SCORE_CP932, SCORE_CP932, - SCORE_CP932, SCORE_X0213, SCORE_X0213, SCORE_ERROR, -}; - -static const nkf_char score_table_8FA0[] = { - 0, SCORE_X0213, SCORE_X0212, SCORE_X0213, - SCORE_X0213, SCORE_X0213, SCORE_X0212, SCORE_X0212, - SCORE_X0213, SCORE_X0212, SCORE_X0212, SCORE_X0212, - SCORE_X0213, SCORE_X0213, SCORE_X0213, SCORE_X0213, -}; - -static const nkf_char score_table_8FE0[] = { - SCORE_X0212, SCORE_X0212, SCORE_X0212, SCORE_X0212, - SCORE_X0212, SCORE_X0212, SCORE_X0212, SCORE_X0212, - SCORE_X0212, SCORE_X0212, SCORE_X0212, SCORE_X0212, - SCORE_X0212, SCORE_X0212, SCORE_X0213, SCORE_X0213, -}; - -static const nkf_char score_table_8FF0[] = { - SCORE_X0213, SCORE_X0213, SCORE_X0213, SCORE_X0212, - SCORE_X0212, SCORE_X0213, SCORE_X0213, SCORE_X0213, - SCORE_X0213, SCORE_X0213, SCORE_X0213, SCORE_X0213, - SCORE_X0213, SCORE_X0213, SCORE_X0213, SCORE_X0213, -}; - -static void -set_code_score(struct input_code *ptr, nkf_char score) -{ - if (ptr){ - ptr->score |= score; - } -} - -static void -clr_code_score(struct input_code *ptr, nkf_char score) -{ - if (ptr){ - ptr->score &= ~score; - } -} - -static void -code_score(struct input_code *ptr) -{ - nkf_char c2 = ptr->buf[0]; - nkf_char c1 = ptr->buf[1]; - if (c2 < 0){ - set_code_score(ptr, SCORE_ERROR); - }else if (c2 == SS2){ - set_code_score(ptr, SCORE_KANA); - }else if (c2 == 0x8f){ - if ((c1 & 0x70) == 0x20){ - set_code_score(ptr, score_table_8FA0[c1 & 0x0f]); - }else if ((c1 & 0x70) == 0x60){ - set_code_score(ptr, score_table_8FE0[c1 & 0x0f]); - }else if ((c1 & 0x70) == 0x70){ - set_code_score(ptr, score_table_8FF0[c1 & 0x0f]); - }else{ - set_code_score(ptr, SCORE_X0212); - } -#ifdef UTF8_OUTPUT_ENABLE - }else if (!e2w_conv(c2, c1)){ - set_code_score(ptr, SCORE_NO_EXIST); -#endif - }else if ((c2 & 0x70) == 0x20){ - set_code_score(ptr, score_table_A0[c2 & 0x0f]); - }else if ((c2 & 0x70) == 0x70){ - set_code_score(ptr, score_table_F0[c2 & 0x0f]); - }else if ((c2 & 0x70) >= 0x50){ - set_code_score(ptr, SCORE_L2); - } -} - -static void -status_disable(struct input_code *ptr) -{ - ptr->stat = -1; - ptr->buf[0] = -1; - code_score(ptr); - if (iconv == ptr->iconv_func) set_iconv(FALSE, 0); -} - -static void -status_push_ch(struct input_code *ptr, nkf_char c) -{ - ptr->buf[ptr->index++] = c; -} - -static void -status_clear(struct input_code *ptr) -{ - ptr->stat = 0; - ptr->index = 0; -} - -static void -status_reset(struct input_code *ptr) -{ - status_clear(ptr); - ptr->score = SCORE_INIT; -} - -static void -status_reinit(struct input_code *ptr) -{ - status_reset(ptr); - ptr->_file_stat = 0; -} - -static void -status_check(struct input_code *ptr, nkf_char c) -{ - if (c <= DEL && estab_f){ - status_reset(ptr); - } -} - -static void -s_status(struct input_code *ptr, nkf_char c) -{ - switch(ptr->stat){ - case -1: - status_check(ptr, c); - break; - case 0: - if (c <= DEL){ - break; - }else if (nkf_char_unicode_p(c)){ - break; - }else if (0xa1 <= c && c <= 0xdf){ - status_push_ch(ptr, SS2); - status_push_ch(ptr, c); - code_score(ptr); - status_clear(ptr); - }else if ((0x81 <= c && c < 0xa0) || (0xe0 <= c && c <= 0xea)){ - ptr->stat = 1; - status_push_ch(ptr, c); - }else if (0xed <= c && c <= 0xee){ - ptr->stat = 3; - status_push_ch(ptr, c); -#ifdef SHIFTJIS_CP932 - }else if (is_ibmext_in_sjis(c)){ - ptr->stat = 2; - status_push_ch(ptr, c); -#endif /* SHIFTJIS_CP932 */ -#ifdef X0212_ENABLE - }else if (0xf0 <= c && c <= 0xfc){ - ptr->stat = 1; - status_push_ch(ptr, c); -#endif /* X0212_ENABLE */ - }else{ - status_disable(ptr); - } - break; - case 1: - if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){ - status_push_ch(ptr, c); - s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]); - code_score(ptr); - status_clear(ptr); - }else{ - status_disable(ptr); - } - break; - case 2: -#ifdef SHIFTJIS_CP932 - if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)) { - status_push_ch(ptr, c); - if (s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]) == 0) { - set_code_score(ptr, SCORE_CP932); - status_clear(ptr); - break; - } - } -#endif /* SHIFTJIS_CP932 */ - status_disable(ptr); - break; - case 3: - if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){ - status_push_ch(ptr, c); - s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]); - set_code_score(ptr, SCORE_CP932); - status_clear(ptr); - }else{ - status_disable(ptr); - } - break; - } -} - -static void -e_status(struct input_code *ptr, nkf_char c) -{ - switch (ptr->stat){ - case -1: - status_check(ptr, c); - break; - case 0: - if (c <= DEL){ - break; - }else if (nkf_char_unicode_p(c)){ - break; - }else if (SS2 == c || (0xa1 <= c && c <= 0xfe)){ - ptr->stat = 1; - status_push_ch(ptr, c); -#ifdef X0212_ENABLE - }else if (0x8f == c){ - ptr->stat = 2; - status_push_ch(ptr, c); -#endif /* X0212_ENABLE */ - }else{ - status_disable(ptr); - } - break; - case 1: - if (0xa1 <= c && c <= 0xfe){ - status_push_ch(ptr, c); - code_score(ptr); - status_clear(ptr); - }else{ - status_disable(ptr); - } - break; -#ifdef X0212_ENABLE - case 2: - if (0xa1 <= c && c <= 0xfe){ - ptr->stat = 1; - status_push_ch(ptr, c); - }else{ - status_disable(ptr); - } -#endif /* X0212_ENABLE */ - } -} - -#ifdef UTF8_INPUT_ENABLE -static void -w_status(struct input_code *ptr, nkf_char c) -{ - switch (ptr->stat){ - case -1: - status_check(ptr, c); - break; - case 0: - if (c <= DEL){ - break; - }else if (nkf_char_unicode_p(c)){ - break; - }else if (0xc0 <= c && c <= 0xdf){ - ptr->stat = 1; - status_push_ch(ptr, c); - }else if (0xe0 <= c && c <= 0xef){ - ptr->stat = 2; - status_push_ch(ptr, c); - }else if (0xf0 <= c && c <= 0xf4){ - ptr->stat = 3; - status_push_ch(ptr, c); - }else{ - status_disable(ptr); - } - break; - case 1: - case 2: - if (0x80 <= c && c <= 0xbf){ - status_push_ch(ptr, c); - if (ptr->index > ptr->stat){ - int bom = (ptr->buf[0] == 0xef && ptr->buf[1] == 0xbb - && ptr->buf[2] == 0xbf); - w2e_conv(ptr->buf[0], ptr->buf[1], ptr->buf[2], - &ptr->buf[0], &ptr->buf[1]); - if (!bom){ - code_score(ptr); - } - status_clear(ptr); - } - }else{ - status_disable(ptr); - } - break; - case 3: - if (0x80 <= c && c <= 0xbf){ - if (ptr->index < ptr->stat){ - status_push_ch(ptr, c); - } else { - status_clear(ptr); - } - }else{ - status_disable(ptr); - } - break; - } -} -#endif - -static void -code_status(nkf_char c) -{ - int action_flag = 1; - struct input_code *result = 0; - struct input_code *p = input_code_list; - while (p->name){ - if (!p->status_func) { - ++p; - continue; - } - if (!p->status_func) - continue; - (p->status_func)(p, c); - if (p->stat > 0){ - action_flag = 0; - }else if(p->stat == 0){ - if (result){ - action_flag = 0; - }else{ - result = p; - } - } - ++p; - } - - if (action_flag){ - if (result && !estab_f){ - set_iconv(TRUE, result->iconv_func); - }else if (c <= DEL){ - struct input_code *ptr = input_code_list; - while (ptr->name){ - status_reset(ptr); - ++ptr; - } - } - } -} - -typedef struct { - nkf_buf_t *std_gc_buf; - nkf_char broken_state; - nkf_buf_t *broken_buf; - nkf_char mimeout_state; - nkf_buf_t *nfc_buf; -} nkf_state_t; - -static nkf_state_t *nkf_state = NULL; - -#define STD_GC_BUFSIZE (256) - -static void -nkf_state_init(void) -{ - if (nkf_state) { - nkf_buf_clear(nkf_state->std_gc_buf); - nkf_buf_clear(nkf_state->broken_buf); - nkf_buf_clear(nkf_state->nfc_buf); - } - else { - nkf_state = nkf_xmalloc(sizeof(nkf_state_t)); - nkf_state->std_gc_buf = nkf_buf_new(STD_GC_BUFSIZE); - nkf_state->broken_buf = nkf_buf_new(3); - nkf_state->nfc_buf = nkf_buf_new(9); - } - nkf_state->broken_state = 0; - nkf_state->mimeout_state = 0; -} - -#ifndef WIN32DLL -static nkf_char -std_getc(FILE *f) -{ - if (!nkf_buf_empty_p(nkf_state->std_gc_buf)){ - return nkf_buf_pop(nkf_state->std_gc_buf); - } - return getc(f); -} -#endif /*WIN32DLL*/ - -static nkf_char -std_ungetc(nkf_char c, ARG_UNUSED FILE *f) -{ - nkf_buf_push(nkf_state->std_gc_buf, c); - return c; -} - -#ifndef WIN32DLL -static void -std_putc(nkf_char c) -{ - if(c!=EOF) - putchar(c); -} -#endif /*WIN32DLL*/ - -static nkf_char hold_buf[HOLD_SIZE*2]; -static int hold_count = 0; -static nkf_char -push_hold_buf(nkf_char c2) -{ - if (hold_count >= HOLD_SIZE*2) - return (EOF); - hold_buf[hold_count++] = c2; - return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count); -} - -static int -h_conv(FILE *f, nkf_char c1, nkf_char c2) -{ - int ret; - int hold_index; - int fromhold_count; - nkf_char c3, c4; - - /** it must NOT be in the kanji shifte sequence */ - /** it must NOT be written in JIS7 */ - /** and it must be after 2 byte 8bit code */ - - hold_count = 0; - push_hold_buf(c1); - push_hold_buf(c2); - - while ((c2 = (*i_getc)(f)) != EOF) { - if (c2 == ESC){ - (*i_ungetc)(c2,f); - break; - } - code_status(c2); - if (push_hold_buf(c2) == EOF || estab_f) { - break; - } - } - - if (!estab_f) { - struct input_code *p = input_code_list; - struct input_code *result = p; - if (c2 == EOF) { - code_status(c2); - } - while (p->name) { - if (p->status_func && p->score < result->score) { - result = p; - } - p++; - } - set_iconv(TRUE, result->iconv_func); - } - - - /** now, - ** 1) EOF is detected, or - ** 2) Code is established, or - ** 3) Buffer is FULL (but last word is pushed) - ** - ** in 1) and 3) cases, we continue to use - ** Kanji codes by oconv and leave estab_f unchanged. - **/ - - ret = c2; - hold_index = 0; - while (hold_index < hold_count){ - c1 = hold_buf[hold_index++]; - if (nkf_char_unicode_p(c1)) { - (*oconv)(0, c1); - continue; - } - else if (c1 <= DEL){ - (*iconv)(0, c1, 0); - continue; - }else if (iconv == s_iconv && 0xa1 <= c1 && c1 <= 0xdf){ - (*iconv)(JIS_X_0201_1976_K, c1, 0); - continue; - } - fromhold_count = 1; - if (hold_index < hold_count){ - c2 = hold_buf[hold_index++]; - fromhold_count++; - }else{ - c2 = (*i_getc)(f); - if (c2 == EOF){ - c4 = EOF; - break; - } - code_status(c2); - } - c3 = 0; - switch ((*iconv)(c1, c2, 0)) { /* can be EUC/SJIS/UTF-8 */ - case -2: - /* 4 bytes UTF-8 */ - if (hold_index < hold_count){ - c3 = hold_buf[hold_index++]; - } else if ((c3 = (*i_getc)(f)) == EOF) { - ret = EOF; - break; - } - code_status(c3); - if (hold_index < hold_count){ - c4 = hold_buf[hold_index++]; - } else if ((c4 = (*i_getc)(f)) == EOF) { - c3 = ret = EOF; - break; - } - code_status(c4); - (*iconv)(c1, c2, (c3<<8)|c4); - break; - case -3: - /* 4 bytes UTF-8 (check combining character) */ - if (hold_index < hold_count){ - c3 = hold_buf[hold_index++]; - fromhold_count++; - } else if ((c3 = (*i_getc)(f)) == EOF) { - w_iconv_nocombine(c1, c2, 0); - break; - } - if (hold_index < hold_count){ - c4 = hold_buf[hold_index++]; - fromhold_count++; - } else if ((c4 = (*i_getc)(f)) == EOF) { - w_iconv_nocombine(c1, c2, 0); - if (fromhold_count <= 2) - (*i_ungetc)(c3,f); - else - hold_index--; - continue; - } - if (w_iconv_combine(c1, c2, 0, c3, c4, 0)) { - w_iconv_nocombine(c1, c2, 0); - if (fromhold_count <= 2) { - (*i_ungetc)(c4,f); - (*i_ungetc)(c3,f); - } else if (fromhold_count == 3) { - (*i_ungetc)(c4,f); - hold_index--; - } else { - hold_index -= 2; - } - } - break; - case -1: - /* 3 bytes EUC or UTF-8 */ - if (hold_index < hold_count){ - c3 = hold_buf[hold_index++]; - fromhold_count++; - } else if ((c3 = (*i_getc)(f)) == EOF) { - ret = EOF; - break; - } else { - code_status(c3); - } - if ((*iconv)(c1, c2, c3) == -3) { - /* 6 bytes UTF-8 (check combining character) */ - nkf_char c5, c6; - if (hold_index < hold_count){ - c4 = hold_buf[hold_index++]; - fromhold_count++; - } else if ((c4 = (*i_getc)(f)) == EOF) { - w_iconv_nocombine(c1, c2, c3); - continue; - } - if (hold_index < hold_count){ - c5 = hold_buf[hold_index++]; - fromhold_count++; - } else if ((c5 = (*i_getc)(f)) == EOF) { - w_iconv_nocombine(c1, c2, c3); - if (fromhold_count == 4) - hold_index--; - else - (*i_ungetc)(c4,f); - continue; - } - if (hold_index < hold_count){ - c6 = hold_buf[hold_index++]; - fromhold_count++; - } else if ((c6 = (*i_getc)(f)) == EOF) { - w_iconv_nocombine(c1, c2, c3); - if (fromhold_count == 5) { - hold_index -= 2; - } else if (fromhold_count == 4) { - hold_index--; - (*i_ungetc)(c5,f); - } else { - (*i_ungetc)(c5,f); - (*i_ungetc)(c4,f); - } - continue; - } - if (w_iconv_combine(c1, c2, c3, c4, c5, c6)) { - w_iconv_nocombine(c1, c2, c3); - if (fromhold_count == 6) { - hold_index -= 3; - } else if (fromhold_count == 5) { - hold_index -= 2; - (*i_ungetc)(c6,f); - } else if (fromhold_count == 4) { - hold_index--; - (*i_ungetc)(c6,f); - (*i_ungetc)(c5,f); - } else { - (*i_ungetc)(c6,f); - (*i_ungetc)(c5,f); - (*i_ungetc)(c4,f); - } - } - } - break; - } - if (c3 == EOF) break; - } - return ret; -} - -/* - * Check and Ignore BOM - */ -static void -check_bom(FILE *f) -{ - int c2; - input_bom_f = FALSE; - switch(c2 = (*i_getc)(f)){ - case 0x00: - if((c2 = (*i_getc)(f)) == 0x00){ - if((c2 = (*i_getc)(f)) == 0xFE){ - if((c2 = (*i_getc)(f)) == 0xFF){ - if(!input_encoding){ - set_iconv(TRUE, w_iconv32); - } - if (iconv == w_iconv32) { - input_bom_f = TRUE; - input_endian = ENDIAN_BIG; - return; - } - (*i_ungetc)(0xFF,f); - }else (*i_ungetc)(c2,f); - (*i_ungetc)(0xFE,f); - }else if(c2 == 0xFF){ - if((c2 = (*i_getc)(f)) == 0xFE){ - if(!input_encoding){ - set_iconv(TRUE, w_iconv32); - } - if (iconv == w_iconv32) { - input_endian = ENDIAN_2143; - return; - } - (*i_ungetc)(0xFF,f); - }else (*i_ungetc)(c2,f); - (*i_ungetc)(0xFF,f); - }else (*i_ungetc)(c2,f); - (*i_ungetc)(0x00,f); - }else (*i_ungetc)(c2,f); - (*i_ungetc)(0x00,f); - break; - case 0xEF: - if((c2 = (*i_getc)(f)) == 0xBB){ - if((c2 = (*i_getc)(f)) == 0xBF){ - if(!input_encoding){ - set_iconv(TRUE, w_iconv); - } - if (iconv == w_iconv) { - input_bom_f = TRUE; - return; - } - (*i_ungetc)(0xBF,f); - }else (*i_ungetc)(c2,f); - (*i_ungetc)(0xBB,f); - }else (*i_ungetc)(c2,f); - (*i_ungetc)(0xEF,f); - break; - case 0xFE: - if((c2 = (*i_getc)(f)) == 0xFF){ - if((c2 = (*i_getc)(f)) == 0x00){ - if((c2 = (*i_getc)(f)) == 0x00){ - if(!input_encoding){ - set_iconv(TRUE, w_iconv32); - } - if (iconv == w_iconv32) { - input_endian = ENDIAN_3412; - return; - } - (*i_ungetc)(0x00,f); - }else (*i_ungetc)(c2,f); - (*i_ungetc)(0x00,f); - }else (*i_ungetc)(c2,f); - if(!input_encoding){ - set_iconv(TRUE, w_iconv16); - } - if (iconv == w_iconv16) { - input_endian = ENDIAN_BIG; - input_bom_f = TRUE; - return; - } - (*i_ungetc)(0xFF,f); - }else (*i_ungetc)(c2,f); - (*i_ungetc)(0xFE,f); - break; - case 0xFF: - if((c2 = (*i_getc)(f)) == 0xFE){ - if((c2 = (*i_getc)(f)) == 0x00){ - if((c2 = (*i_getc)(f)) == 0x00){ - if(!input_encoding){ - set_iconv(TRUE, w_iconv32); - } - if (iconv == w_iconv32) { - input_endian = ENDIAN_LITTLE; - input_bom_f = TRUE; - return; - } - (*i_ungetc)(0x00,f); - }else (*i_ungetc)(c2,f); - (*i_ungetc)(0x00,f); - }else (*i_ungetc)(c2,f); - if(!input_encoding){ - set_iconv(TRUE, w_iconv16); - } - if (iconv == w_iconv16) { - input_endian = ENDIAN_LITTLE; - input_bom_f = TRUE; - return; - } - (*i_ungetc)(0xFE,f); - }else (*i_ungetc)(c2,f); - (*i_ungetc)(0xFF,f); - break; - default: - (*i_ungetc)(c2,f); - break; - } -} - -static nkf_char -broken_getc(FILE *f) -{ - nkf_char c, c1; - - if (!nkf_buf_empty_p(nkf_state->broken_buf)) { - return nkf_buf_pop(nkf_state->broken_buf); - } - c = (*i_bgetc)(f); - if (c=='$' && nkf_state->broken_state != ESC - && (input_mode == ASCII || input_mode == JIS_X_0201_1976_K)) { - c1= (*i_bgetc)(f); - nkf_state->broken_state = 0; - if (c1=='@'|| c1=='B') { - nkf_buf_push(nkf_state->broken_buf, c1); - nkf_buf_push(nkf_state->broken_buf, c); - return ESC; - } else { - (*i_bungetc)(c1,f); - return c; - } - } else if (c=='(' && nkf_state->broken_state != ESC - && (input_mode == JIS_X_0208 || input_mode == JIS_X_0201_1976_K)) { - c1= (*i_bgetc)(f); - nkf_state->broken_state = 0; - if (c1=='J'|| c1=='B') { - nkf_buf_push(nkf_state->broken_buf, c1); - nkf_buf_push(nkf_state->broken_buf, c); - return ESC; - } else { - (*i_bungetc)(c1,f); - return c; - } - } else { - nkf_state->broken_state = c; - return c; - } -} - -static nkf_char -broken_ungetc(nkf_char c, ARG_UNUSED FILE *f) -{ - if (nkf_buf_length(nkf_state->broken_buf) < 2) - nkf_buf_push(nkf_state->broken_buf, c); - return c; -} - -static void -eol_conv(nkf_char c2, nkf_char c1) -{ - if (guess_f && input_eol != EOF) { - if (c2 == 0 && c1 == LF) { - if (!input_eol) input_eol = prev_cr ? CRLF : LF; - else if (input_eol != (prev_cr ? CRLF : LF)) input_eol = EOF; - } else if (c2 == 0 && c1 == CR && input_eol == LF) input_eol = EOF; - else if (!prev_cr); - else if (!input_eol) input_eol = CR; - else if (input_eol != CR) input_eol = EOF; - } - if (prev_cr || (c2 == 0 && c1 == LF)) { - prev_cr = 0; - if (eolmode_f != LF) (*o_eol_conv)(0, CR); - if (eolmode_f != CR) (*o_eol_conv)(0, LF); - } - if (c2 == 0 && c1 == CR) prev_cr = CR; - else if (c2 != 0 || c1 != LF) (*o_eol_conv)(c2, c1); -} - -static void -put_newline(void (*func)(nkf_char)) -{ - switch (eolmode_f ? eolmode_f : DEFAULT_NEWLINE) { - case CRLF: - (*func)(0x0D); - (*func)(0x0A); - break; - case CR: - (*func)(0x0D); - break; - case LF: - (*func)(0x0A); - break; - } -} - -static void -oconv_newline(void (*func)(nkf_char, nkf_char)) -{ - switch (eolmode_f ? eolmode_f : DEFAULT_NEWLINE) { - case CRLF: - (*func)(0, 0x0D); - (*func)(0, 0x0A); - break; - case CR: - (*func)(0, 0x0D); - break; - case LF: - (*func)(0, 0x0A); - break; - } -} - -/* - Return value of fold_conv() - - LF add newline and output char - CR add newline and output nothing - SP space - 0 skip - 1 (or else) normal output - - fold state in prev (previous character) - - >0x80 Japanese (X0208/X0201) - <0x80 ASCII - LF new line - SP space - - This fold algorithm does not preserve heading space in a line. - This is the main difference from fmt. - */ - -#define char_size(c2,c1) (c2?2:1) - -static void -fold_conv(nkf_char c2, nkf_char c1) -{ - nkf_char prev0; - nkf_char fold_state; - - if (c1== CR && !fold_preserve_f) { - fold_state=0; /* ignore cr */ - }else if (c1== LF&&f_prev==CR && fold_preserve_f) { - f_prev = LF; - fold_state=0; /* ignore cr */ - } else if (c1== BS) { - if (f_line>0) f_line--; - fold_state = 1; - } else if (c2==EOF && f_line != 0) { /* close open last line */ - fold_state = LF; - } else if ((c1==LF && !fold_preserve_f) - || ((c1==CR||(c1==LF&&f_prev!=CR)) - && fold_preserve_f)) { - /* new line */ - if (fold_preserve_f) { - f_prev = c1; - f_line = 0; - fold_state = CR; - } else if ((f_prev == c1) - || (f_prev == LF) - ) { /* duplicate newline */ - if (f_line) { - f_line = 0; - fold_state = LF; /* output two newline */ - } else { - f_line = 0; - fold_state = 1; - } - } else { - if (f_prev&0x80) { /* Japanese? */ - f_prev = c1; - fold_state = 0; /* ignore given single newline */ - } else if (f_prev==SP) { - fold_state = 0; - } else { - f_prev = c1; - if (++f_line<=fold_len) - fold_state = SP; - else { - f_line = 0; - fold_state = CR; /* fold and output nothing */ - } - } - } - } else if (c1=='\f') { - f_prev = LF; - f_line = 0; - fold_state = LF; /* output newline and clear */ - } else if ((c2==0 && nkf_isblank(c1)) || (c2 == '!' && c1 == '!')) { - /* X0208 kankaku or ascii space */ - if (f_prev == SP) { - fold_state = 0; /* remove duplicate spaces */ - } else { - f_prev = SP; - if (++f_line<=fold_len) - fold_state = SP; /* output ASCII space only */ - else { - f_prev = SP; f_line = 0; - fold_state = CR; /* fold and output nothing */ - } - } - } else { - prev0 = f_prev; /* we still need this one... , but almost done */ - f_prev = c1; - if (c2 || c2 == JIS_X_0201_1976_K) - f_prev |= 0x80; /* this is Japanese */ - f_line += c2 == JIS_X_0201_1976_K ? 1: char_size(c2,c1); - if (f_line<=fold_len) { /* normal case */ - fold_state = 1; - } else { - if (f_line>fold_len+fold_margin) { /* too many kinsoku suspension */ - f_line = char_size(c2,c1); - fold_state = LF; /* We can't wait, do fold now */ - } else if (c2 == JIS_X_0201_1976_K) { - /* simple kinsoku rules return 1 means no folding */ - if (c1==(0xde&0x7f)) fold_state = 1; /* $B!+(B*/ - else if (c1==(0xdf&0x7f)) fold_state = 1; /* $B!,(B*/ - else if (c1==(0xa4&0x7f)) fold_state = 1; /* $B!#(B*/ - else if (c1==(0xa3&0x7f)) fold_state = 1; /* $B!$(B*/ - else if (c1==(0xa1&0x7f)) fold_state = 1; /* $B!W(B*/ - else if (c1==(0xb0&0x7f)) fold_state = 1; /* - */ - else if (SP<=c1 && c1<=(0xdf&0x7f)) { /* X0201 */ - f_line = 1; - fold_state = LF;/* add one new f_line before this character */ - } else { - f_line = 1; - fold_state = LF;/* add one new f_line before this character */ - } - } else if (c2==0) { - /* kinsoku point in ASCII */ - if ( c1==')'|| /* { [ ( */ - c1==']'|| - c1=='}'|| - c1=='.'|| - c1==','|| - c1=='!'|| - c1=='?'|| - c1=='/'|| - c1==':'|| - c1==';') { - fold_state = 1; - /* just after special */ - } else if (!is_alnum(prev0)) { - f_line = char_size(c2,c1); - fold_state = LF; - } else if ((prev0==SP) || /* ignored new f_line */ - (prev0==LF)|| /* ignored new f_line */ - (prev0&0x80)) { /* X0208 - ASCII */ - f_line = char_size(c2,c1); - fold_state = LF;/* add one new f_line before this character */ - } else { - fold_state = 1; /* default no fold in ASCII */ - } - } else { - if (c2=='!') { - if (c1=='"') fold_state = 1; /* $B!"(B */ - else if (c1=='#') fold_state = 1; /* $B!#(B */ - else if (c1=='W') fold_state = 1; /* $B!W(B */ - else if (c1=='K') fold_state = 1; /* $B!K(B */ - else if (c1=='$') fold_state = 1; /* $B!$(B */ - else if (c1=='%') fold_state = 1; /* $B!%(B */ - else if (c1=='\'') fold_state = 1; /* $B!\(B */ - else if (c1=='(') fold_state = 1; /* $B!((B */ - else if (c1==')') fold_state = 1; /* $B!)(B */ - else if (c1=='*') fold_state = 1; /* $B!*(B */ - else if (c1=='+') fold_state = 1; /* $B!+(B */ - else if (c1==',') fold_state = 1; /* $B!,(B */ - /* default no fold in kinsoku */ - else { - fold_state = LF; - f_line = char_size(c2,c1); - /* add one new f_line before this character */ - } - } else { - f_line = char_size(c2,c1); - fold_state = LF; - /* add one new f_line before this character */ - } - } - } - } - /* terminator process */ - switch(fold_state) { - case LF: - oconv_newline(o_fconv); - (*o_fconv)(c2,c1); - break; - case 0: - return; - case CR: - oconv_newline(o_fconv); - break; - case TAB: - case SP: - (*o_fconv)(0,SP); - break; - default: - (*o_fconv)(c2,c1); - } -} - -static nkf_char z_prev2=0,z_prev1=0; - -static void -z_conv(nkf_char c2, nkf_char c1) -{ - - /* if (c2) c1 &= 0x7f; assertion */ - - if (c2 == JIS_X_0201_1976_K && (c1 == 0x20 || c1 == 0x7D || c1 == 0x7E)) { - (*o_zconv)(c2,c1); - return; - } - - if (x0201_f) { - if (z_prev2 == JIS_X_0201_1976_K) { - if (c2 == JIS_X_0201_1976_K) { - if (c1 == (0xde&0x7f)) { /* $BByE@(B */ - z_prev2 = 0; - (*o_zconv)(dv[(z_prev1-SP)*2], dv[(z_prev1-SP)*2+1]); - return; - } else if (c1 == (0xdf&0x7f) && ev[(z_prev1-SP)*2]) { /* $BH>ByE@(B */ - z_prev2 = 0; - (*o_zconv)(ev[(z_prev1-SP)*2], ev[(z_prev1-SP)*2+1]); - return; - } else if (x0213_f && c1 == (0xdf&0x7f) && ev_x0213[(z_prev1-SP)*2]) { /* $BH>ByE@(B */ - z_prev2 = 0; - (*o_zconv)(ev_x0213[(z_prev1-SP)*2], ev_x0213[(z_prev1-SP)*2+1]); - return; - } - } - z_prev2 = 0; - (*o_zconv)(cv[(z_prev1-SP)*2], cv[(z_prev1-SP)*2+1]); - } - if (c2 == JIS_X_0201_1976_K) { - if (dv[(c1-SP)*2] || ev[(c1-SP)*2] || (x0213_f && ev_x0213[(c1-SP)*2])) { - /* wait for $BByE@(B or $BH>ByE@(B */ - z_prev1 = c1; - z_prev2 = c2; - return; - } else { - (*o_zconv)(cv[(c1-SP)*2], cv[(c1-SP)*2+1]); - return; - } - } - } - - if (c2 == EOF) { - (*o_zconv)(c2, c1); - return; - } - - if (alpha_f&1 && c2 == 0x23) { - /* JISX0208 Alphabet */ - c2 = 0; - } else if (c2 == 0x21) { - /* JISX0208 Kigou */ - if (0x21==c1) { - if (alpha_f&2) { - c2 = 0; - c1 = SP; - } else if (alpha_f&4) { - (*o_zconv)(0, SP); - (*o_zconv)(0, SP); - return; - } - } else if (alpha_f&1 && 0x20': entity = ">"; break; - case '<': entity = "<"; break; - case '\"': entity = """; break; - case '&': entity = "&"; break; - } - if (entity){ - while (*entity) (*o_zconv)(0, *entity++); - return; - } - } - - if (alpha_f & 16) { - /* JIS X 0208 Katakana to JIS X 0201 Katakana */ - if (c2 == 0x21) { - nkf_char c = 0; - switch (c1) { - case 0x23: - /* U+3002 (0x8142) Ideographic Full Stop -> U+FF61 (0xA1) Halfwidth Ideographic Full Stop */ - c = 0xA1; - break; - case 0x56: - /* U+300C (0x8175) Left Corner Bracket -> U+FF62 (0xA2) Halfwidth Left Corner Bracket */ - c = 0xA2; - break; - case 0x57: - /* U+300D (0x8176) Right Corner Bracket -> U+FF63 (0xA3) Halfwidth Right Corner Bracket */ - c = 0xA3; - break; - case 0x22: - /* U+3001 (0x8141) Ideographic Comma -> U+FF64 (0xA4) Halfwidth Ideographic Comma */ - c = 0xA4; - break; - case 0x26: - /* U+30FB (0x8145) Katakana Middle Dot -> U+FF65 (0xA5) Halfwidth Katakana Middle Dot */ - c = 0xA5; - break; - case 0x3C: - /* U+30FC (0x815B) Katakana-Hiragana Prolonged Sound Mark -> U+FF70 (0xB0) Halfwidth Katakana-Hiragana Prolonged Sound Mark */ - c = 0xB0; - break; - case 0x2B: - /* U+309B (0x814A) Katakana-Hiragana Voiced Sound Mark -> U+FF9E (0xDE) Halfwidth Katakana Voiced Sound Mark */ - c = 0xDE; - break; - case 0x2C: - /* U+309C (0x814B) Katakana-Hiragana Semi-Voiced Sound Mark -> U+FF9F (0xDF) Halfwidth Katakana Semi-Voiced Sound Mark */ - c = 0xDF; - break; - } - if (c) { - (*o_zconv)(JIS_X_0201_1976_K, c); - return; - } - } else if (c2 == 0x25) { - /* JISX0208 Katakana */ - static const int fullwidth_to_halfwidth[] = - { - 0x0000, 0x2700, 0x3100, 0x2800, 0x3200, 0x2900, 0x3300, 0x2A00, - 0x3400, 0x2B00, 0x3500, 0x3600, 0x365E, 0x3700, 0x375E, 0x3800, - 0x385E, 0x3900, 0x395E, 0x3A00, 0x3A5E, 0x3B00, 0x3B5E, 0x3C00, - 0x3C5E, 0x3D00, 0x3D5E, 0x3E00, 0x3E5E, 0x3F00, 0x3F5E, 0x4000, - 0x405E, 0x4100, 0x415E, 0x2F00, 0x4200, 0x425E, 0x4300, 0x435E, - 0x4400, 0x445E, 0x4500, 0x4600, 0x4700, 0x4800, 0x4900, 0x4A00, - 0x4A5E, 0x4A5F, 0x4B00, 0x4B5E, 0x4B5F, 0x4C00, 0x4C5E, 0x4C5F, - 0x4D00, 0x4D5E, 0x4D5F, 0x4E00, 0x4E5E, 0x4E5F, 0x4F00, 0x5000, - 0x5100, 0x5200, 0x5300, 0x2C00, 0x5400, 0x2D00, 0x5500, 0x2E00, - 0x5600, 0x5700, 0x5800, 0x5900, 0x5A00, 0x5B00, 0x0000, 0x5C00, - 0x0000, 0x0000, 0x2600, 0x5D00, 0x335E, 0x0000, 0x0000, 0x365F, - 0x375F, 0x385F, 0x395F, 0x3A5F, 0x3E5F, 0x425F, 0x445F, 0x0000 - }; - if (fullwidth_to_halfwidth[c1-0x20]){ - c2 = fullwidth_to_halfwidth[c1-0x20]; - (*o_zconv)(JIS_X_0201_1976_K, c2>>8); - if (c2 & 0xFF) { - (*o_zconv)(JIS_X_0201_1976_K, c2&0xFF); - } - return; - } - } else if (c2 == 0 && nkf_char_unicode_p(c1) && - ((c1&VALUE_MASK) == 0x3099 || (c1&VALUE_MASK) == 0x309A)) { /* $B9g@.MQByE@!&H>ByE@(B */ - (*o_zconv)(JIS_X_0201_1976_K, 0x5E + (c1&VALUE_MASK) - 0x3099); - return; - } - } - (*o_zconv)(c2,c1); -} - - -#define rot13(c) ( \ - ( c < 'A') ? c: \ - (c <= 'M') ? (c + 13): \ - (c <= 'Z') ? (c - 13): \ - (c < 'a') ? (c): \ - (c <= 'm') ? (c + 13): \ - (c <= 'z') ? (c - 13): \ - (c) \ - ) - -#define rot47(c) ( \ - ( c < '!') ? c: \ - ( c <= 'O') ? (c + 47) : \ - ( c <= '~') ? (c - 47) : \ - c \ - ) - -static void -rot_conv(nkf_char c2, nkf_char c1) -{ - if (c2 == 0 || c2 == JIS_X_0201_1976_K || c2 == ISO_8859_1) { - c1 = rot13(c1); - } else if (c2) { - c1 = rot47(c1); - c2 = rot47(c2); - } - (*o_rot_conv)(c2,c1); -} - -static void -hira_conv(nkf_char c2, nkf_char c1) -{ - if (hira_f & 1) { - if (c2 == 0x25) { - if (0x20 < c1 && c1 < 0x74) { - c2 = 0x24; - (*o_hira_conv)(c2,c1); - return; - } else if (c1 == 0x74 && nkf_enc_unicode_p(output_encoding)) { - c2 = 0; - c1 = nkf_char_unicode_new(0x3094); - (*o_hira_conv)(c2,c1); - return; - } - } else if (c2 == 0x21 && (c1 == 0x33 || c1 == 0x34)) { - c1 += 2; - (*o_hira_conv)(c2,c1); - return; - } - } - if (hira_f & 2) { - if (c2 == 0 && c1 == nkf_char_unicode_new(0x3094)) { - c2 = 0x25; - c1 = 0x74; - } else if (c2 == 0x24 && 0x20 < c1 && c1 < 0x74) { - c2 = 0x25; - } else if (c2 == 0x21 && (c1 == 0x35 || c1 == 0x36)) { - c1 -= 2; - } - } - (*o_hira_conv)(c2,c1); -} - - -static void -iso2022jp_check_conv(nkf_char c2, nkf_char c1) -{ -#define RANGE_NUM_MAX 18 - static const nkf_char range[RANGE_NUM_MAX][2] = { - {0x222f, 0x2239,}, - {0x2242, 0x2249,}, - {0x2251, 0x225b,}, - {0x226b, 0x2271,}, - {0x227a, 0x227d,}, - {0x2321, 0x232f,}, - {0x233a, 0x2340,}, - {0x235b, 0x2360,}, - {0x237b, 0x237e,}, - {0x2474, 0x247e,}, - {0x2577, 0x257e,}, - {0x2639, 0x2640,}, - {0x2659, 0x267e,}, - {0x2742, 0x2750,}, - {0x2772, 0x277e,}, - {0x2841, 0x287e,}, - {0x4f54, 0x4f7e,}, - {0x7425, 0x747e}, - }; - nkf_char i; - nkf_char start, end, c; - - if(c2 >= 0x00 && c2 <= 0x20 && c1 >= 0x7f && c1 <= 0xff) { - c2 = GETA1; - c1 = GETA2; - } - if((c2 >= 0x29 && c2 <= 0x2f) || (c2 >= 0x75 && c2 <= 0x7e)) { - c2 = GETA1; - c1 = GETA2; - } - - for (i = 0; i < RANGE_NUM_MAX; i++) { - start = range[i][0]; - end = range[i][1]; - c = (c2 << 8) + c1; - if (c >= start && c <= end) { - c2 = GETA1; - c1 = GETA2; - } - } - (*o_iso2022jp_check_conv)(c2,c1); -} - - -/* This converts =?ISO-2022-JP?B?HOGE HOGE?= */ - -static const unsigned char *mime_pattern[] = { - (const unsigned char *)"\075?EUC-JP?B?", - (const unsigned char *)"\075?SHIFT_JIS?B?", - (const unsigned char *)"\075?ISO-8859-1?Q?", - (const unsigned char *)"\075?ISO-8859-1?B?", - (const unsigned char *)"\075?ISO-2022-JP?B?", - (const unsigned char *)"\075?ISO-2022-JP?B?", - (const unsigned char *)"\075?ISO-2022-JP?Q?", -#if defined(UTF8_INPUT_ENABLE) - (const unsigned char *)"\075?UTF-8?B?", - (const unsigned char *)"\075?UTF-8?Q?", -#endif - (const unsigned char *)"\075?US-ASCII?Q?", - NULL -}; - - -/* $B3:Ev$9$k%3!<%I$NM%@hEY$r>e$2$k$?$a$NL\0u(B */ -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, -#endif - 0, -}; - -static const nkf_char mime_encode[] = { - EUC_JP, SHIFT_JIS, ISO_8859_1, ISO_8859_1, JIS_X_0208, JIS_X_0201_1976_K, JIS_X_0201_1976_K, -#if defined(UTF8_INPUT_ENABLE) - UTF_8, UTF_8, -#endif - ASCII, - 0 -}; - -static const nkf_char mime_encode_method[] = { - 'B', 'B','Q', 'B', 'B', 'B', 'Q', -#if defined(UTF8_INPUT_ENABLE) - 'B', 'Q', -#endif - 'Q', - 0 -}; - - -/* MIME preprocessor fifo */ - -#define MIME_BUF_SIZE (1024) /* 2^n ring buffer */ -#define MIME_BUF_MASK (MIME_BUF_SIZE-1) -#define mime_input_buf(n) mime_input_state.buf[(n)&MIME_BUF_MASK] -static struct { - unsigned char buf[MIME_BUF_SIZE]; - unsigned int top; - unsigned int last; /* decoded */ - unsigned int input; /* undecoded */ -} mime_input_state; -static nkf_char (*mime_iconv_back)(nkf_char c2,nkf_char c1,nkf_char c0) = NULL; - -#define MAXRECOVER 20 - -static void -mime_input_buf_unshift(nkf_char c) -{ - mime_input_buf(--mime_input_state.top) = (unsigned char)c; -} - -static nkf_char -mime_ungetc(nkf_char c, ARG_UNUSED FILE *f) -{ - mime_input_buf_unshift(c); - return c; -} - -static nkf_char -mime_ungetc_buf(nkf_char c, FILE *f) -{ - if (mimebuf_f) - (*i_mungetc_buf)(c,f); - else - mime_input_buf(--mime_input_state.input) = (unsigned char)c; - return c; -} - -static nkf_char -mime_getc_buf(FILE *f) -{ - /* we don't keep eof of mime_input_buf, because it contains ?= as - a terminator. It was checked in mime_integrity. */ - return ((mimebuf_f)? - (*i_mgetc_buf)(f):mime_input_buf(mime_input_state.input++)); -} - -static void -switch_mime_getc(void) -{ - if (i_getc!=mime_getc) { - i_mgetc = i_getc; i_getc = mime_getc; - i_mungetc = i_ungetc; i_ungetc = mime_ungetc; - if(mime_f==STRICT_MIME) { - i_mgetc_buf = i_mgetc; i_mgetc = mime_getc_buf; - i_mungetc_buf = i_mungetc; i_mungetc = mime_ungetc_buf; - } - } -} - -static void -unswitch_mime_getc(void) -{ - if(mime_f==STRICT_MIME) { - i_mgetc = i_mgetc_buf; - i_mungetc = i_mungetc_buf; - } - i_getc = i_mgetc; - i_ungetc = i_mungetc; - if(mime_iconv_back)set_iconv(FALSE, mime_iconv_back); - mime_iconv_back = NULL; -} - -static nkf_char -mime_integrity(FILE *f, const unsigned char *p) -{ - nkf_char c,d; - unsigned int q; - /* In buffered mode, read until =? or NL or buffer full - */ - mime_input_state.input = mime_input_state.top; - mime_input_state.last = mime_input_state.top; - - while(*p) mime_input_buf(mime_input_state.input++) = *p++; - d = 0; - q = mime_input_state.input; - while((c=(*i_getc)(f))!=EOF) { - if (((mime_input_state.input-mime_input_state.top)&MIME_BUF_MASK)==0) { - break; /* buffer full */ - } - if (c=='=' && d=='?') { - /* checked. skip header, start decode */ - mime_input_buf(mime_input_state.input++) = (unsigned char)c; - /* mime_last_input = mime_input_state.input; */ - mime_input_state.input = q; - switch_mime_getc(); - return 1; - } - if (!( (c=='+'||c=='/'|| c=='=' || c=='?' || is_alnum(c)))) - break; - /* Should we check length mod 4? */ - mime_input_buf(mime_input_state.input++) = (unsigned char)c; - d=c; - } - /* In case of Incomplete MIME, no MIME decode */ - mime_input_buf(mime_input_state.input++) = (unsigned char)c; - mime_input_state.last = mime_input_state.input; /* point undecoded buffer */ - mime_decode_mode = 1; /* no decode on mime_input_buf last in mime_getc */ - switch_mime_getc(); /* anyway we need buffered getc */ - return 1; -} - -static nkf_char -mime_begin_strict(FILE *f) -{ - nkf_char c1 = 0; - int i,j,k; - const unsigned char *p,*q; - nkf_char r[MAXRECOVER]; /* recovery buffer, max mime pattern length */ - - mime_decode_mode = FALSE; - /* =? has been checked */ - j = 0; - p = mime_pattern[j]; - r[0]='='; r[1]='?'; - - for(i=2;p[i]>SP;i++) { /* start at =? */ - if (((r[i] = c1 = (*i_getc)(f))==EOF) || nkf_toupper(c1) != p[i]) { - /* pattern fails, try next one */ - q = p; - while (mime_pattern[++j]) { - p = mime_pattern[j]; - for(k=2;k i */ - if (p[k]!=q[k]) break; - if (k==i && nkf_toupper(c1)==p[k]) break; - } - p = mime_pattern[j]; - if (p) continue; /* found next one, continue */ - /* all fails, output from recovery buffer */ - (*i_ungetc)(c1,f); - for(j=0;jscore & (SCORE_DEPEND|SCORE_CP932)) - input_codename = "CP932"; - } else if (strcmp(input_codename, "EUC-JP") == 0) { - if (p->score & SCORE_X0213) - input_codename = "EUC-JIS-2004"; - else if (p->score & (SCORE_X0212)) - input_codename = "EUCJP-MS"; - else if (p->score & (SCORE_DEPEND|SCORE_CP932)) - input_codename = "CP51932"; - } else if (strcmp(input_codename, "ISO-2022-JP") == 0) { - if (p->score & (SCORE_KANA)) - input_codename = "CP50221"; - else if (p->score & (SCORE_DEPEND|SCORE_CP932)) - input_codename = "CP50220"; - } - } - return input_codename; -} - -#if !defined(PERL_XS) && !defined(WIN32DLL) -static void -print_guessed_code(char *filename) -{ - if (filename != NULL) printf("%s: ", filename); - if (input_codename && !*input_codename) { - printf("BINARY\n"); - } else { - input_codename = get_guessed_code(); - if (guess_f == 1) { - printf("%s\n", input_codename); - } else { - printf("%s%s%s%s\n", - input_codename, - iconv != w_iconv16 && iconv != w_iconv32 ? "" : - input_endian == ENDIAN_LITTLE ? " LE" : - input_endian == ENDIAN_BIG ? " BE" : - "[BUG]", - input_bom_f ? " (BOM)" : "", - input_eol == CR ? " (CR)" : - input_eol == LF ? " (LF)" : - input_eol == CRLF ? " (CRLF)" : - input_eol == EOF ? " (MIXED NL)" : - ""); - } - } -} -#endif /*WIN32DLL*/ - -#ifdef INPUT_OPTION - -static nkf_char -hex_getc(nkf_char ch, FILE *f, nkf_char (*g)(FILE *f), nkf_char (*u)(nkf_char c, FILE *f)) -{ - nkf_char c1, c2, c3; - c1 = (*g)(f); - if (c1 != ch){ - return c1; - } - c2 = (*g)(f); - if (!nkf_isxdigit(c2)){ - (*u)(c2, f); - return c1; - } - c3 = (*g)(f); - if (!nkf_isxdigit(c3)){ - (*u)(c2, f); - (*u)(c3, f); - return c1; - } - return (hex2bin(c2) << 4) | hex2bin(c3); -} - -static nkf_char -cap_getc(FILE *f) -{ - return hex_getc(':', f, i_cgetc, i_cungetc); -} - -static nkf_char -cap_ungetc(nkf_char c, FILE *f) -{ - return (*i_cungetc)(c, f); -} - -static nkf_char -url_getc(FILE *f) -{ - return hex_getc('%', f, i_ugetc, i_uungetc); -} - -static nkf_char -url_ungetc(nkf_char c, FILE *f) -{ - return (*i_uungetc)(c, f); -} -#endif - -#ifdef NUMCHAR_OPTION -static nkf_char -numchar_getc(FILE *f) -{ - nkf_char (*g)(FILE *) = i_ngetc; - nkf_char (*u)(nkf_char c ,FILE *f) = i_nungetc; - int i = 0, j; - nkf_char buf[12]; - nkf_char c = -1; - - buf[i] = (*g)(f); - if (buf[i] == '&'){ - buf[++i] = (*g)(f); - if (buf[i] == '#'){ - c = 0; - buf[++i] = (*g)(f); - if (buf[i] == 'x' || buf[i] == 'X'){ - for (j = 0; j < 7; j++){ - buf[++i] = (*g)(f); - if (!nkf_isxdigit(buf[i])){ - if (buf[i] != ';'){ - c = -1; - } - break; - } - c <<= 4; - c |= hex2bin(buf[i]); - } - }else{ - for (j = 0; j < 8; j++){ - if (j){ - buf[++i] = (*g)(f); - } - if (!nkf_isdigit(buf[i])){ - if (buf[i] != ';'){ - c = -1; - } - break; - } - c *= 10; - c += hex2bin(buf[i]); - } - } - } - } - if (c != -1){ - return nkf_char_unicode_new(c); - } - while (i > 0){ - (*u)(buf[i], f); - --i; - } - return buf[0]; -} - -static nkf_char -numchar_ungetc(nkf_char c, FILE *f) -{ - return (*i_nungetc)(c, f); -} -#endif - -#ifdef UNICODE_NORMALIZATION - -static nkf_char -nfc_getc(FILE *f) -{ - nkf_char (*g)(FILE *f) = i_nfc_getc; - nkf_char (*u)(nkf_char c ,FILE *f) = i_nfc_ungetc; - nkf_buf_t *buf = nkf_state->nfc_buf; - const unsigned char *array; - int lower=0, upper=NORMALIZATION_TABLE_LENGTH-1; - nkf_char c = (*g)(f); - - if (c == EOF || c > 0xFF || (c & 0xc0) == 0x80) return c; - - nkf_buf_push(buf, c); - do { - while (lower <= upper) { - int mid = (lower+upper) / 2; - int len; - array = normalization_table[mid].nfd; - for (len=0; len < NORMALIZATION_TABLE_NFD_LENGTH && array[len]; len++) { - if (len >= nkf_buf_length(buf)) { - c = (*g)(f); - if (c == EOF) { - len = 0; - lower = 1, upper = 0; - break; - } - nkf_buf_push(buf, c); - } - if (array[len] != nkf_buf_at(buf, len)) { - if (array[len] < nkf_buf_at(buf, len)) lower = mid + 1; - else upper = mid - 1; - len = 0; - break; - } - } - if (len > 0) { - int i; - array = normalization_table[mid].nfc; - nkf_buf_clear(buf); - for (i=0; i < NORMALIZATION_TABLE_NFC_LENGTH && array[i]; i++) - nkf_buf_push(buf, array[i]); - break; - } - } - } while (lower <= upper); - - while (nkf_buf_length(buf) > 1) (*u)(nkf_buf_pop(buf), f); - c = nkf_buf_pop(buf); - - return c; -} - -static nkf_char -nfc_ungetc(nkf_char c, FILE *f) -{ - return (*i_nfc_ungetc)(c, f); -} -#endif /* UNICODE_NORMALIZATION */ - - -static nkf_char -base64decode(nkf_char c) -{ - int i; - if (c > '@') { - if (c < '[') { - i = c - 'A'; /* A..Z 0-25 */ - } else if (c == '_') { - i = '?' /* 63 */ ; /* _ 63 */ - } else { - i = c - 'G' /* - 'a' + 26 */ ; /* a..z 26-51 */ - } - } else if (c > '/') { - i = c - '0' + '4' /* - '0' + 52 */ ; /* 0..9 52-61 */ - } else if (c == '+' || c == '-') { - i = '>' /* 62 */ ; /* + and - 62 */ - } else { - i = '?' /* 63 */ ; /* / 63 */ - } - return (i); -} - -static nkf_char -mime_getc(FILE *f) -{ - nkf_char c1, c2, c3, c4, cc; - nkf_char t1, t2, t3, t4, mode, exit_mode; - nkf_char lwsp_count; - char *lwsp_buf; - char *lwsp_buf_new; - nkf_char lwsp_size = 128; - - if (mime_input_state.top != mime_input_state.last) { /* Something is in FIFO */ - return mime_input_buf(mime_input_state.top++); - } - if (mime_decode_mode==1 ||mime_decode_mode==FALSE) { - mime_decode_mode=FALSE; - unswitch_mime_getc(); - return (*i_getc)(f); - } - - if (mimebuf_f == FIXED_MIME) - exit_mode = mime_decode_mode; - else - exit_mode = FALSE; - if (mime_decode_mode == 'Q') { - if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF); - restart_mime_q: - if (c1=='_' && mimebuf_f != FIXED_MIME) return SP; - if (c1<=SP || DEL<=c1) { - mime_decode_mode = exit_mode; /* prepare for quit */ - return c1; - } - if (c1!='=' && (c1!='?' || mimebuf_f == FIXED_MIME)) { - return c1; - } - - mime_decode_mode = exit_mode; /* prepare for quit */ - if ((c2 = (*i_mgetc)(f)) == EOF) return (EOF); - if (c1=='?'&&c2=='=' && mimebuf_f != FIXED_MIME) { - /* end Q encoding */ - input_mode = exit_mode; - lwsp_count = 0; - lwsp_buf = nkf_xmalloc((lwsp_size+5)*sizeof(char)); - while ((c1=(*i_getc)(f))!=EOF) { - switch (c1) { - case LF: - case CR: - if (c1==LF) { - if ((c1=(*i_getc)(f))!=EOF && nkf_isblank(c1)) { - i_ungetc(SP,f); - continue; - } else { - i_ungetc(c1,f); - } - c1 = LF; - } else { - if ((c1=(*i_getc)(f))!=EOF && c1 == LF) { - if ((c1=(*i_getc)(f))!=EOF && nkf_isblank(c1)) { - i_ungetc(SP,f); - continue; - } else { - i_ungetc(c1,f); - } - i_ungetc(LF,f); - } else { - i_ungetc(c1,f); - } - c1 = CR; - } - break; - case SP: - case TAB: - lwsp_buf[lwsp_count] = (unsigned char)c1; - if (lwsp_count++>lwsp_size){ - lwsp_size <<= 1; - lwsp_buf_new = nkf_xrealloc(lwsp_buf, (lwsp_size+5)*sizeof(char)); - lwsp_buf = lwsp_buf_new; - } - continue; - } - break; - } - if (lwsp_count > 0 && (c1 != '=' || (lwsp_buf[lwsp_count-1] != SP && lwsp_buf[lwsp_count-1] != TAB))) { - i_ungetc(c1,f); - for(lwsp_count--;lwsp_count>0;lwsp_count--) - i_ungetc(lwsp_buf[lwsp_count],f); - c1 = lwsp_buf[0]; - } - nkf_xfree(lwsp_buf); - return c1; - } - if (c1=='='&&c20;lwsp_count--) - i_ungetc(lwsp_buf[lwsp_count],f); - c1 = lwsp_buf[0]; - } - nkf_xfree(lwsp_buf); - return c1; - } - mime_c3_retry: - if ((c3 = (*i_mgetc)(f))<=SP) { - if (c3==EOF) - return (EOF); - if (mime_f != STRICT_MIME) goto mime_c3_retry; - if (mimebuf_f!=FIXED_MIME) input_mode = ASCII; - return c3; - } - mime_c4_retry: - if ((c4 = (*i_mgetc)(f))<=SP) { - if (c4==EOF) - return (EOF); - if (mime_f != STRICT_MIME) goto mime_c4_retry; - if (mimebuf_f!=FIXED_MIME) input_mode = ASCII; - return c4; - } - - mime_decode_mode = mode; /* still in MIME sigh... */ - - /* BASE 64 decoding */ - - t1 = 0x3f & base64decode(c1); - t2 = 0x3f & base64decode(c2); - t3 = 0x3f & base64decode(c3); - t4 = 0x3f & base64decode(c4); - cc = ((t1 << 2) & 0x0fc) | ((t2 >> 4) & 0x03); - if (c2 != '=') { - mime_input_buf(mime_input_state.last++) = (unsigned char)cc; - cc = ((t2 << 4) & 0x0f0) | ((t3 >> 2) & 0x0f); - if (c3 != '=') { - mime_input_buf(mime_input_state.last++) = (unsigned char)cc; - cc = ((t3 << 6) & 0x0c0) | (t4 & 0x3f); - if (c4 != '=') - mime_input_buf(mime_input_state.last++) = (unsigned char)cc; - } - } else { - return c1; - } - return mime_input_buf(mime_input_state.top++); -} - -static const char basis_64[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -#define MIMEOUT_BUF_LENGTH 74 -static struct { - unsigned char buf[MIMEOUT_BUF_LENGTH+1]; - int count; -} mimeout_state; - -/*nkf_char mime_lastchar2, mime_lastchar1;*/ - -static void -open_mime(nkf_char mode) -{ - const unsigned char *p; - int i; - int j; - p = mime_pattern[0]; - for(i=0;mime_pattern[i];i++) { - if (mode == mime_encode[i]) { - p = mime_pattern[i]; - break; - } - } - mimeout_mode = mime_encode_method[i]; - i = 0; - if (base64_count>45) { - if (mimeout_state.count>0 && nkf_isblank(mimeout_state.buf[i])){ - (*o_mputc)(mimeout_state.buf[i]); - i++; - } - put_newline(o_mputc); - (*o_mputc)(SP); - base64_count = 1; - if (mimeout_state.count>0 && nkf_isspace(mimeout_state.buf[i])) { - i++; - } - } - for (;i 0){ - if (c2 == EOF){ - if (base64_count + mimeout_state.count/3*4> 73){ - (*o_base64conv)(EOF,0); - oconv_newline(o_base64conv); - (*o_base64conv)(0,SP); - base64_count = 1; - } - } else { - if ((c2 != 0 || c1 > DEL) && base64_count + mimeout_state.count/3*4> 66) { - (*o_base64conv)(EOF,0); - oconv_newline(o_base64conv); - (*o_base64conv)(0,SP); - base64_count = 1; - mimeout_mode = -1; - } - } - } else if (c2) { - if (c2 != EOF && base64_count + mimeout_state.count/3*4> 60) { - mimeout_mode = (output_mode==ASCII ||output_mode == ISO_8859_1) ? 'Q' : 'B'; - open_mime(output_mode); - (*o_base64conv)(EOF,0); - oconv_newline(o_base64conv); - (*o_base64conv)(0,SP); - base64_count = 1; - mimeout_mode = -1; - } - } -} - -static void -close_mime(void) -{ - (*o_mputc)('?'); - (*o_mputc)('='); - base64_count += 2; - mimeout_mode = 0; -} - -static void -eof_mime(void) -{ - switch(mimeout_mode) { - case 'Q': - case 'B': - break; - case 2: - (*o_mputc)(basis_64[((nkf_state->mimeout_state & 0x3)<< 4)]); - (*o_mputc)('='); - (*o_mputc)('='); - base64_count += 3; - break; - case 1: - (*o_mputc)(basis_64[((nkf_state->mimeout_state & 0xF) << 2)]); - (*o_mputc)('='); - base64_count += 2; - break; - } - if (mimeout_mode > 0) { - if (mimeout_f!=FIXED_MIME) { - close_mime(); - } else if (mimeout_mode != 'Q') - mimeout_mode = 'B'; - } -} - -static void -mimeout_addchar(nkf_char c) -{ - switch(mimeout_mode) { - case 'Q': - if (c==CR||c==LF) { - (*o_mputc)(c); - base64_count = 0; - } else if(!nkf_isalnum(c)) { - (*o_mputc)('='); - (*o_mputc)(bin2hex(((c>>4)&0xf))); - (*o_mputc)(bin2hex((c&0xf))); - base64_count += 3; - } else { - (*o_mputc)(c); - base64_count++; - } - break; - case 'B': - nkf_state->mimeout_state=c; - (*o_mputc)(basis_64[c>>2]); - mimeout_mode=2; - base64_count ++; - break; - case 2: - (*o_mputc)(basis_64[((nkf_state->mimeout_state & 0x3)<< 4) | ((c & 0xF0) >> 4)]); - nkf_state->mimeout_state=c; - mimeout_mode=1; - base64_count ++; - break; - case 1: - (*o_mputc)(basis_64[((nkf_state->mimeout_state & 0xF) << 2) | ((c & 0xC0) >>6)]); - (*o_mputc)(basis_64[c & 0x3F]); - mimeout_mode='B'; - base64_count += 2; - break; - default: - (*o_mputc)(c); - base64_count++; - break; - } -} - -static void -mime_putc(nkf_char c) -{ - int i, j; - nkf_char lastchar; - - if (mimeout_f == FIXED_MIME){ - if (mimeout_mode == 'Q'){ - if (base64_count > 71){ - if (c!=CR && c!=LF) { - (*o_mputc)('='); - put_newline(o_mputc); - } - base64_count = 0; - } - }else{ - if (base64_count > 71){ - eof_mime(); - put_newline(o_mputc); - base64_count = 0; - } - if (c == EOF) { /* c==EOF */ - eof_mime(); - } - } - if (c != EOF) { /* c==EOF */ - mimeout_addchar(c); - } - return; - } - - /* mimeout_f != FIXED_MIME */ - - if (c == EOF) { /* c==EOF */ - if (mimeout_mode == -1 && mimeout_state.count > 1) open_mime(output_mode); - j = mimeout_state.count; - mimeout_state.count = 0; - i = 0; - if (mimeout_mode > 0) { - if (!nkf_isblank(mimeout_state.buf[j-1])) { - for (;i 0){ - lastchar = mimeout_state.buf[mimeout_state.count - 1]; - }else{ - lastchar = -1; - } - - if (mimeout_mode=='Q') { - if (c <= DEL && (output_mode==ASCII ||output_mode == ISO_8859_1)) { - if (c == CR || c == LF) { - close_mime(); - (*o_mputc)(c); - base64_count = 0; - return; - } else if (c <= SP) { - close_mime(); - if (base64_count > 70) { - put_newline(o_mputc); - base64_count = 0; - } - if (!nkf_isblank(c)) { - (*o_mputc)(SP); - base64_count++; - } - } else { - if (base64_count > 70) { - close_mime(); - put_newline(o_mputc); - (*o_mputc)(SP); - base64_count = 1; - open_mime(output_mode); - } - if (!nkf_noescape_mime(c)) { - mimeout_addchar(c); - return; - } - } - if (c != 0x1B) { - (*o_mputc)(c); - base64_count++; - return; - } - } - } - - if (mimeout_mode <= 0) { - if (c <= DEL && (output_mode==ASCII || output_mode == ISO_8859_1 || - output_mode == UTF_8)) { - if (nkf_isspace(c)) { - int flag = 0; - if (mimeout_mode == -1) { - flag = 1; - } - if (c==CR || c==LF) { - if (flag) { - open_mime(output_mode); - output_mode = 0; - } else { - base64_count = 0; - } - } - for (i=0;i 1 - && base64_count + mimeout_state.count > 76 - && mimeout_state.buf[0] != CR && mimeout_state.buf[0] != LF){ - static const char *str = "boundary=\""; - static int len = 10; - i = 0; - - for (; i < mimeout_state.count - len; ++i) { - if (!strncmp((char *)(mimeout_state.buf+i), str, len)) { - i += len - 2; - break; - } - } - - if (i == 0 || i == mimeout_state.count - len) { - put_newline(o_mputc); - base64_count = 0; - if (!nkf_isspace(mimeout_state.buf[0])){ - (*o_mputc)(SP); - base64_count++; - } - } - else { - int j; - for (j = 0; j <= i; ++j) { - (*o_mputc)(mimeout_state.buf[j]); - } - put_newline(o_mputc); - base64_count = 1; - for (; j <= mimeout_state.count; ++j) { - mimeout_state.buf[j - i] = mimeout_state.buf[j]; - } - mimeout_state.count -= i; - } - } - mimeout_state.buf[mimeout_state.count++] = (char)c; - if (mimeout_state.count>MIMEOUT_BUF_LENGTH) { - open_mime(output_mode); - } - } - return; - }else{ - if (lastchar==CR || lastchar == LF){ - for (i=0;iMIMEOUT_BUF_LENGTH) { - eof_mime(); - for (j=0;j0 && SPMIMEOUT_BUF_LENGTH) { - j = mimeout_state.count; - mimeout_state.count = 0; - for (i=0;i0) { - j = mimeout_state.count; - mimeout_state.count = 0; - for (i=0;iinput_buffer_size = IOBUF_SIZE; - converter->input_buffer = nkf_xmalloc(converter->input_buffer_size); - converter->output_buffer_size = IOBUF_SIZE * 2; - converter->output_buffer = nkf_xmalloc(converter->output_buffer_size); - converter->cd = iconv_open(tocode, fromcode); - if (converter->cd == (iconv_t)-1) - { - switch (errno) { - case EINVAL: - perror(fprintf("iconv doesn't support %s to %s conversion.", fromcode, tocode)); - return -1; - default: - perror("can't iconv_open"); - } - } -} - -static size_t -nkf_iconv_convert(nkf_iconv_t *converter, FILE *input) -{ - size_t invalid = (size_t)0; - char *input_buffer = converter->input_buffer; - size_t input_length = (size_t)0; - char *output_buffer = converter->output_buffer; - size_t output_length = converter->output_buffer_size; - int c; - - do { - if (c != EOF) { - while ((c = (*i_getc)(f)) != EOF) { - input_buffer[input_length++] = c; - if (input_length < converter->input_buffer_size) break; - } - } - - size_t ret = iconv(converter->cd, &input_buffer, &input_length, &output_buffer, &output_length); - while (output_length-- > 0) { - (*o_putc)(output_buffer[converter->output_buffer_size-output_length]); - } - if (ret == (size_t) - 1) { - switch (errno) { - case EINVAL: - if (input_buffer != converter->input_buffer) - memmove(converter->input_buffer, input_buffer, input_length); - break; - case E2BIG: - converter->output_buffer_size *= 2; - output_buffer = realloc(converter->outbuf, converter->output_buffer_size); - if (output_buffer == NULL) { - perror("can't realloc"); - return -1; - } - converter->output_buffer = output_buffer; - break; - default: - perror("can't iconv"); - return -1; - } - } else { - invalid += ret; - } - } while (1); - - return invalid; -} - - -static void -nkf_iconv_close(nkf_iconv_t *convert) -{ - nkf_xfree(converter->inbuf); - nkf_xfree(converter->outbuf); - iconv_close(converter->cd); -} -#endif - - -static void -reinit(void) -{ - { - struct input_code *p = input_code_list; - while (p->name){ - status_reinit(p++); - } - } - unbuf_f = FALSE; - estab_f = FALSE; - nop_f = FALSE; - binmode_f = TRUE; - rot_f = FALSE; - hira_f = FALSE; - alpha_f = FALSE; - mime_f = MIME_DECODE_DEFAULT; - mime_decode_f = FALSE; - mimebuf_f = FALSE; - broken_f = FALSE; - iso8859_f = FALSE; - mimeout_f = FALSE; - x0201_f = NKF_UNSPECIFIED; - iso2022jp_f = FALSE; -#if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE) - ms_ucs_map_f = UCS_MAP_ASCII; -#endif -#ifdef UTF8_INPUT_ENABLE - no_cp932ext_f = FALSE; - no_best_fit_chars_f = FALSE; - encode_fallback = NULL; - unicode_subchar = '?'; - input_endian = ENDIAN_BIG; -#endif -#ifdef UTF8_OUTPUT_ENABLE - output_bom_f = FALSE; - output_endian = ENDIAN_BIG; -#endif -#ifdef UNICODE_NORMALIZATION - nfc_f = FALSE; -#endif -#ifdef INPUT_OPTION - cap_f = FALSE; - url_f = FALSE; - numchar_f = FALSE; -#endif -#ifdef CHECK_OPTION - noout_f = FALSE; - debug_f = FALSE; -#endif - guess_f = 0; -#ifdef EXEC_IO - exec_f = 0; -#endif -#ifdef SHIFTJIS_CP932 - cp51932_f = TRUE; - cp932inv_f = TRUE; -#endif -#ifdef X0212_ENABLE - x0212_f = FALSE; - x0213_f = FALSE; -#endif - { - int i; - for (i = 0; i < 256; i++){ - prefix_table[i] = 0; - } - } - hold_count = 0; - mimeout_state.count = 0; - mimeout_mode = 0; - base64_count = 0; - f_line = 0; - f_prev = 0; - fold_preserve_f = FALSE; - fold_f = FALSE; - fold_len = 0; - kanji_intro = DEFAULT_J; - ascii_intro = DEFAULT_R; - fold_margin = FOLD_MARGIN; - o_zconv = no_connection; - o_fconv = no_connection; - o_eol_conv = no_connection; - o_rot_conv = no_connection; - o_hira_conv = no_connection; - o_base64conv = no_connection; - o_iso2022jp_check_conv = no_connection; - o_putc = std_putc; - i_getc = std_getc; - i_ungetc = std_ungetc; - i_bgetc = std_getc; - i_bungetc = std_ungetc; - o_mputc = std_putc; - i_mgetc = std_getc; - i_mungetc = std_ungetc; - i_mgetc_buf = std_getc; - i_mungetc_buf = std_ungetc; - output_mode = ASCII; - input_mode = ASCII; - mime_decode_mode = FALSE; - file_out_f = FALSE; - eolmode_f = 0; - input_eol = 0; - prev_cr = 0; - option_mode = 0; - z_prev2=0,z_prev1=0; -#ifdef CHECK_OPTION - iconv_for_check = 0; -#endif - input_codename = NULL; - input_encoding = NULL; - output_encoding = NULL; - nkf_state_init(); -#ifdef WIN32DLL - reinitdll(); -#endif /*WIN32DLL*/ -} - -static int -module_connection(void) -{ - if (input_encoding) set_input_encoding(input_encoding); - if (!output_encoding) { - output_encoding = nkf_default_encoding(); - } - if (!output_encoding) { - if (noout_f || guess_f) output_encoding = nkf_enc_from_index(ISO_2022_JP); - else return -1; - } - set_output_encoding(output_encoding); - oconv = nkf_enc_to_oconv(output_encoding); - o_putc = std_putc; - if (nkf_enc_unicode_p(output_encoding)) - output_mode = UTF_8; - - if (x0201_f == NKF_UNSPECIFIED) { - x0201_f = X0201_DEFAULT; - } - - /* replace continuation module, from output side */ - - /* output redirection */ -#ifdef CHECK_OPTION - if (noout_f || guess_f){ - o_putc = no_putc; - } -#endif - if (mimeout_f) { - o_mputc = o_putc; - o_putc = mime_putc; - if (mimeout_f == TRUE) { - o_base64conv = oconv; oconv = base64_conv; - } - /* base64_count = 0; */ - } - - if (eolmode_f || guess_f) { - o_eol_conv = oconv; oconv = eol_conv; - } - if (rot_f) { - o_rot_conv = oconv; oconv = rot_conv; - } - if (iso2022jp_f) { - o_iso2022jp_check_conv = oconv; oconv = iso2022jp_check_conv; - } - if (hira_f) { - o_hira_conv = oconv; oconv = hira_conv; - } - if (fold_f) { - o_fconv = oconv; oconv = fold_conv; - f_line = 0; - } - if (alpha_f || x0201_f) { - o_zconv = oconv; oconv = z_conv; - } - - i_getc = std_getc; - i_ungetc = std_ungetc; - /* input redirection */ -#ifdef INPUT_OPTION - if (cap_f){ - i_cgetc = i_getc; i_getc = cap_getc; - i_cungetc = i_ungetc; i_ungetc= cap_ungetc; - } - if (url_f){ - i_ugetc = i_getc; i_getc = url_getc; - i_uungetc = i_ungetc; i_ungetc= url_ungetc; - } -#endif -#ifdef NUMCHAR_OPTION - if (numchar_f){ - i_ngetc = i_getc; i_getc = numchar_getc; - i_nungetc = i_ungetc; i_ungetc= numchar_ungetc; - } -#endif -#ifdef UNICODE_NORMALIZATION - if (nfc_f){ - i_nfc_getc = i_getc; i_getc = nfc_getc; - i_nfc_ungetc = i_ungetc; i_ungetc= nfc_ungetc; - } -#endif - if (mime_f && mimebuf_f==FIXED_MIME) { - i_mgetc = i_getc; i_getc = mime_getc; - i_mungetc = i_ungetc; i_ungetc = mime_ungetc; - } - if (broken_f & 1) { - i_bgetc = i_getc; i_getc = broken_getc; - i_bungetc = i_ungetc; i_ungetc = broken_ungetc; - } - if (input_encoding) { - set_iconv(-TRUE, nkf_enc_to_iconv(input_encoding)); - } else { - set_iconv(FALSE, e_iconv); - } - - { - struct input_code *p = input_code_list; - while (p->name){ - status_reinit(p++); - } - } - return 0; -} - -/* - Conversion main loop. Code detection only. - */ - -#if !defined(PERL_XS) && !defined(WIN32DLL) -static nkf_char -noconvert(FILE *f) -{ - nkf_char c; - - if (nop_f == 2) - module_connection(); - while ((c = (*i_getc)(f)) != EOF) - (*o_putc)(c); - (*o_putc)(EOF); - return 1; -} -#endif - -#define NEXT continue /* no output, get next */ -#define SKIP c2=0;continue /* no output, get next */ -#define MORE c2=c1;continue /* need one more byte */ -#define SEND (void)0 /* output c1 and c2, get next */ -#define LAST break /* end of loop, go closing */ -#define set_input_mode(mode) do { \ - input_mode = mode; \ - shift_mode = 0; \ - set_input_codename("ISO-2022-JP"); \ - debug("ISO-2022-JP"); \ -} while (0) - -static int -kanji_convert(FILE *f) -{ - nkf_char c1=0, c2=0, c3=0, c4=0; - int shift_mode = 0; /* 0, 1, 2, 3 */ - int g2 = 0; - int is_8bit = FALSE; - - if (input_encoding && !nkf_enc_asciicompat(input_encoding)) { - is_8bit = TRUE; - } - - input_mode = ASCII; - output_mode = ASCII; - - if (module_connection() < 0) { -#if !defined(PERL_XS) && !defined(WIN32DLL) - fprintf(stderr, "no output encoding given\n"); -#endif - return -1; - } - check_bom(f); - -#ifdef UTF8_INPUT_ENABLE - if(iconv == w_iconv32){ - while ((c1 = (*i_getc)(f)) != EOF && - (c2 = (*i_getc)(f)) != EOF && - (c3 = (*i_getc)(f)) != EOF && - (c4 = (*i_getc)(f)) != EOF) { - nkf_char c5, c6, c7, c8; - if (nkf_iconv_utf_32(c1, c2, c3, c4) == (size_t)NKF_ICONV_WAIT_COMBINING_CHAR) { - if ((c5 = (*i_getc)(f)) != EOF && - (c6 = (*i_getc)(f)) != EOF && - (c7 = (*i_getc)(f)) != EOF && - (c8 = (*i_getc)(f)) != EOF) { - if (nkf_iconv_utf_32_combine(c1, c2, c3, c4, c5, c6, c7, c8)) { - (*i_ungetc)(c8, f); - (*i_ungetc)(c7, f); - (*i_ungetc)(c6, f); - (*i_ungetc)(c5, f); - nkf_iconv_utf_32_nocombine(c1, c2, c3, c4); - } - } else { - nkf_iconv_utf_32_nocombine(c1, c2, c3, c4); - } - } - } - goto finished; - } - else if (iconv == w_iconv16) { - while ((c1 = (*i_getc)(f)) != EOF && - (c2 = (*i_getc)(f)) != EOF) { - size_t ret = nkf_iconv_utf_16(c1, c2, 0, 0); - if (ret == NKF_ICONV_NEED_TWO_MORE_BYTES && - (c3 = (*i_getc)(f)) != EOF && - (c4 = (*i_getc)(f)) != EOF) { - nkf_iconv_utf_16(c1, c2, c3, c4); - } else if (ret == (size_t)NKF_ICONV_WAIT_COMBINING_CHAR) { - if ((c3 = (*i_getc)(f)) != EOF && - (c4 = (*i_getc)(f)) != EOF) { - if (nkf_iconv_utf_16_combine(c1, c2, c3, c4)) { - (*i_ungetc)(c4, f); - (*i_ungetc)(c3, f); - nkf_iconv_utf_16_nocombine(c1, c2); - } - } else { - nkf_iconv_utf_16_nocombine(c1, c2); - } - } - } - goto finished; - } -#endif - - while ((c1 = (*i_getc)(f)) != EOF) { -#ifdef INPUT_CODE_FIX - if (!input_encoding) -#endif - code_status(c1); - if (c2) { - /* second byte */ - if (c2 > ((input_encoding && nkf_enc_cp5022x_p(input_encoding)) ? 0x92 : DEL)) { - /* in case of 8th bit is on */ - if (!estab_f&&!mime_decode_mode) { - /* in case of not established yet */ - /* It is still ambiguous */ - if (h_conv(f, c2, c1)==EOF) { - LAST; - } - else { - SKIP; - } - } - else { - /* in case of already established */ - if (c1 < 0x40) { - /* ignore bogus code */ - SKIP; - } else { - SEND; - } - } - } - else { - /* 2nd byte of 7 bit code or SJIS */ - SEND; - } - } - else if (nkf_char_unicode_p(c1)) { - (*oconv)(0, c1); - NEXT; - } - else { - /* first byte */ - if (input_mode == JIS_X_0208 && DEL <= c1 && c1 < 0x92) { - /* CP5022x */ - MORE; - }else if (input_codename && input_codename[0] == 'I' && - 0xA1 <= c1 && c1 <= 0xDF) { - /* JIS X 0201 Katakana in 8bit JIS */ - c2 = JIS_X_0201_1976_K; - c1 &= 0x7f; - SEND; - } else if (c1 > DEL) { - /* 8 bit code */ - if (!estab_f && !iso8859_f) { - /* not established yet */ - MORE; - } else { /* estab_f==TRUE */ - if (iso8859_f) { - c2 = ISO_8859_1; - c1 &= 0x7f; - SEND; - } - else if ((iconv == s_iconv && 0xA0 <= c1 && c1 <= 0xDF) || - (ms_ucs_map_f == UCS_MAP_CP10001 && (c1 == 0xFD || c1 == 0xFE))) { - /* JIS X 0201 */ - c2 = JIS_X_0201_1976_K; - c1 &= 0x7f; - SEND; - } - else { - /* already established */ - MORE; - } - } - } else if (SP < c1 && c1 < DEL) { - /* in case of Roman characters */ - if (shift_mode) { - /* output 1 shifted byte */ - if (iso8859_f) { - c2 = ISO_8859_1; - SEND; - } else if (nkf_byte_jisx0201_katakana_p(c1)){ - /* output 1 shifted byte */ - c2 = JIS_X_0201_1976_K; - SEND; - } else { - /* look like bogus code */ - SKIP; - } - } else if (input_mode == JIS_X_0208 || input_mode == JIS_X_0212 || - input_mode == JIS_X_0213_1 || input_mode == JIS_X_0213_2) { - /* in case of Kanji shifted */ - MORE; - } else if (c1 == '=' && mime_f && !mime_decode_mode) { - /* Check MIME code */ - if ((c1 = (*i_getc)(f)) == EOF) { - (*oconv)(0, '='); - LAST; - } else if (c1 == '?') { - /* =? is mime conversion start sequence */ - if(mime_f == STRICT_MIME) { - /* check in real detail */ - if (mime_begin_strict(f) == EOF) - LAST; - SKIP; - } else if (mime_begin(f) == EOF) - LAST; - SKIP; - } else { - (*oconv)(0, '='); - (*i_ungetc)(c1,f); - SKIP; - } - } else { - /* normal ASCII code */ - SEND; - } - } else if (c1 == SI && (!is_8bit || mime_decode_mode)) { - shift_mode = 0; - SKIP; - } else if (c1 == SO && (!is_8bit || mime_decode_mode)) { - shift_mode = 1; - SKIP; - } else if (c1 == ESC && (!is_8bit || mime_decode_mode)) { - if ((c1 = (*i_getc)(f)) == EOF) { - (*oconv)(0, ESC); - LAST; - } - else if (c1 == '&') { - /* IRR */ - if ((c1 = (*i_getc)(f)) == EOF) { - LAST; - } else { - SKIP; - } - } - else if (c1 == '$') { - /* GZDMx */ - if ((c1 = (*i_getc)(f)) == EOF) { - /* don't send bogus code - (*oconv)(0, ESC); - (*oconv)(0, '$'); */ - LAST; - } else if (c1 == '@' || c1 == 'B') { - /* JIS X 0208 */ - set_input_mode(JIS_X_0208); - SKIP; - } else if (c1 == '(') { - /* GZDM4 */ - if ((c1 = (*i_getc)(f)) == EOF) { - /* don't send bogus code - (*oconv)(0, ESC); - (*oconv)(0, '$'); - (*oconv)(0, '('); - */ - LAST; - } else if (c1 == '@'|| c1 == 'B') { - /* JIS X 0208 */ - set_input_mode(JIS_X_0208); - SKIP; -#ifdef X0212_ENABLE - } else if (c1 == 'D'){ - set_input_mode(JIS_X_0212); - SKIP; -#endif /* X0212_ENABLE */ - } else if (c1 == 'O' || c1 == 'Q'){ - set_input_mode(JIS_X_0213_1); - SKIP; - } else if (c1 == 'P'){ - set_input_mode(JIS_X_0213_2); - SKIP; - } else { - /* could be some special code */ - (*oconv)(0, ESC); - (*oconv)(0, '$'); - (*oconv)(0, '('); - (*oconv)(0, c1); - SKIP; - } - } else if (broken_f&0x2) { - /* accept any ESC-(-x as broken code ... */ - input_mode = JIS_X_0208; - shift_mode = 0; - SKIP; - } else { - (*oconv)(0, ESC); - (*oconv)(0, '$'); - (*oconv)(0, c1); - SKIP; - } - } else if (c1 == '(') { - /* GZD4 */ - if ((c1 = (*i_getc)(f)) == EOF) { - /* don't send bogus code - (*oconv)(0, ESC); - (*oconv)(0, '('); */ - LAST; - } - else if (c1 == 'I') { - /* JIS X 0201 Katakana */ - set_input_mode(JIS_X_0201_1976_K); - shift_mode = 1; - SKIP; - } - else if (c1 == 'B' || c1 == 'J' || c1 == 'H') { - /* ISO-646IRV:1983 or JIS X 0201 Roman or JUNET */ - set_input_mode(ASCII); - SKIP; - } - else if (broken_f&0x2) { - set_input_mode(ASCII); - SKIP; - } - else { - (*oconv)(0, ESC); - (*oconv)(0, '('); - SEND; - } - } - else if (c1 == '.') { - /* G2D6 */ - if ((c1 = (*i_getc)(f)) == EOF) { - LAST; - } - else if (c1 == 'A') { - /* ISO-8859-1 */ - g2 = ISO_8859_1; - SKIP; - } - else { - (*oconv)(0, ESC); - (*oconv)(0, '.'); - SEND; - } - } - else if (c1 == 'N') { - /* SS2 */ - c1 = (*i_getc)(f); - if (g2 == ISO_8859_1) { - c2 = ISO_8859_1; - SEND; - }else{ - (*i_ungetc)(c1, f); - /* lonely ESC */ - (*oconv)(0, ESC); - SEND; - } - } - else { - i_ungetc(c1,f); - /* lonely ESC */ - (*oconv)(0, ESC); - SKIP; - } - } else if (c1 == ESC && iconv == s_iconv) { - /* ESC in Shift_JIS */ - if ((c1 = (*i_getc)(f)) == EOF) { - (*oconv)(0, ESC); - LAST; - } else if (c1 == '$') { - /* J-PHONE emoji */ - if ((c1 = (*i_getc)(f)) == EOF) { - LAST; - } else if (('E' <= c1 && c1 <= 'G') || - ('O' <= c1 && c1 <= 'Q')) { - /* - NUM : 0 1 2 3 4 5 - BYTE: G E F O P Q - C%7 : 1 6 0 2 3 4 - C%7 : 0 1 2 3 4 5 6 - NUM : 2 0 3 4 5 X 1 - */ - static const nkf_char jphone_emoji_first_table[7] = - {0xE1E0, 0xDFE0, 0xE2E0, 0xE3E0, 0xE4E0, 0xDFE0, 0xE0E0}; - c3 = nkf_char_unicode_new(jphone_emoji_first_table[c1 % 7]); - if ((c1 = (*i_getc)(f)) == EOF) LAST; - while (SP <= c1 && c1 <= 'z') { - (*oconv)(0, c1 + c3); - if ((c1 = (*i_getc)(f)) == EOF) LAST; - } - SKIP; - } - else { - (*oconv)(0, ESC); - (*oconv)(0, '$'); - SEND; - } - } - else { - i_ungetc(c1,f); - /* lonely ESC */ - (*oconv)(0, ESC); - SKIP; - } - } else if (c1 == LF || c1 == CR) { - if (broken_f&4) { - input_mode = ASCII; set_iconv(FALSE, 0); - SEND; - } else if (mime_decode_f && !mime_decode_mode){ - if (c1 == LF) { - if ((c1=(*i_getc)(f))!=EOF && c1 == SP) { - i_ungetc(SP,f); - continue; - } else { - i_ungetc(c1,f); - } - c1 = LF; - SEND; - } else { /* if (c1 == CR)*/ - if ((c1=(*i_getc)(f))!=EOF) { - if (c1==SP) { - i_ungetc(SP,f); - continue; - } else if (c1 == LF && (c1=(*i_getc)(f))!=EOF && c1 == SP) { - i_ungetc(SP,f); - continue; - } else { - i_ungetc(c1,f); - } - i_ungetc(LF,f); - } else { - i_ungetc(c1,f); - } - c1 = CR; - SEND; - } - } - } else - SEND; - } - /* send: */ - switch(input_mode){ - case ASCII: - switch ((*iconv)(c2, c1, 0)) { /* can be EUC / SJIS / UTF-8 */ - case -2: - /* 4 bytes UTF-8 */ - if ((c3 = (*i_getc)(f)) != EOF) { - code_status(c3); - c3 <<= 8; - if ((c4 = (*i_getc)(f)) != EOF) { - code_status(c4); - (*iconv)(c2, c1, c3|c4); - } - } - break; - case -3: - /* 4 bytes UTF-8 (check combining character) */ - if ((c3 = (*i_getc)(f)) != EOF) { - if ((c4 = (*i_getc)(f)) != EOF) { - if (w_iconv_combine(c2, c1, 0, c3, c4, 0)) { - (*i_ungetc)(c4, f); - (*i_ungetc)(c3, f); - w_iconv_nocombine(c2, c1, 0); - } - } else { - (*i_ungetc)(c3, f); - w_iconv_nocombine(c2, c1, 0); - } - } else { - w_iconv_nocombine(c2, c1, 0); - } - break; - case -1: - /* 3 bytes EUC or UTF-8 */ - if ((c3 = (*i_getc)(f)) != EOF) { - code_status(c3); - if ((*iconv)(c2, c1, c3) == -3) { - /* 6 bytes UTF-8 (check combining character) */ - nkf_char c5, c6; - if ((c4 = (*i_getc)(f)) != EOF) { - if ((c5 = (*i_getc)(f)) != EOF) { - if ((c6 = (*i_getc)(f)) != EOF) { - if (w_iconv_combine(c2, c1, c3, c4, c5, c6)) { - (*i_ungetc)(c6, f); - (*i_ungetc)(c5, f); - (*i_ungetc)(c4, f); - w_iconv_nocombine(c2, c1, c3); - } - } else { - (*i_ungetc)(c5, f); - (*i_ungetc)(c4, f); - w_iconv_nocombine(c2, c1, c3); - } - } else { - (*i_ungetc)(c4, f); - w_iconv_nocombine(c2, c1, c3); - } - } else { - w_iconv_nocombine(c2, c1, c3); - } - } - } - break; - } - break; - case JIS_X_0208: - case JIS_X_0213_1: - if (ms_ucs_map_f && - 0x7F <= c2 && c2 <= 0x92 && - 0x21 <= c1 && c1 <= 0x7E) { - /* CP932 UDC */ - c1 = nkf_char_unicode_new((c2 - 0x7F) * 94 + c1 - 0x21 + 0xE000); - c2 = 0; - } - (*oconv)(c2, c1); /* this is JIS, not SJIS/EUC case */ - break; -#ifdef X0212_ENABLE - case JIS_X_0212: - (*oconv)(PREFIX_EUCG3 | c2, c1); - break; -#endif /* X0212_ENABLE */ - case JIS_X_0213_2: - (*oconv)(PREFIX_EUCG3 | c2, c1); - break; - default: - (*oconv)(input_mode, c1); /* other special case */ - } - - c2 = 0; - c3 = 0; - continue; - /* goto next_word */ - } - -finished: - /* epilogue */ - (*iconv)(EOF, 0, 0); - if (!input_codename) - { - if (is_8bit) { - struct input_code *p = input_code_list; - struct input_code *result = p; - while (p->name){ - if (p->score < result->score) result = p; - ++p; - } - set_input_codename(result->name); -#ifdef CHECK_OPTION - debug(result->name); -#endif - } - } - return 0; -} - -/* - * int options(unsigned char *cp) - * - * return values: - * 0: success - * -1: ArgumentError - */ -static int -options(unsigned char *cp) -{ - nkf_char i, j; - unsigned char *p; - unsigned char *cp_back = NULL; - nkf_encoding *enc; - - if (option_mode==1) - return 0; - while(*cp && *cp++!='-'); - while (*cp || cp_back) { - if(!*cp){ - cp = cp_back; - cp_back = NULL; - continue; - } - p = 0; - switch (*cp++) { - case '-': /* literal options */ - if (!*cp || *cp == SP) { /* ignore the rest of arguments */ - option_mode = 1; - return 0; - } - for (i=0;i<(int)(sizeof(long_option)/sizeof(long_option[0]));i++) { - p = (unsigned char *)long_option[i].name; - for (j=0;*p && *p != '=' && *p == cp[j];p++, j++); - if (*p == cp[j] || cp[j] == SP){ - p = &cp[j] + 1; - break; - } - p = 0; - } - if (p == 0) { -#if !defined(PERL_XS) && !defined(WIN32DLL) - fprintf(stderr, "unknown long option: --%s\n", cp); -#endif - return -1; - } - while(*cp && *cp != SP && cp++); - if (long_option[i].alias[0]){ - cp_back = cp; - cp = (unsigned char *)long_option[i].alias; - }else{ -#ifndef PERL_XS - if (strcmp(long_option[i].name, "help") == 0){ - usage(); - exit(EXIT_SUCCESS); - } -#endif - if (strcmp(long_option[i].name, "ic=") == 0){ - enc = nkf_enc_find((char *)p); - if (!enc) continue; - input_encoding = enc; - continue; - } - if (strcmp(long_option[i].name, "oc=") == 0){ - enc = nkf_enc_find((char *)p); - /* if (enc <= 0) continue; */ - if (!enc) continue; - output_encoding = enc; - continue; - } - if (strcmp(long_option[i].name, "guess=") == 0){ - if (p[0] == '0' || p[0] == '1') { - guess_f = 1; - } else { - guess_f = 2; - } - continue; - } -#ifdef OVERWRITE - if (strcmp(long_option[i].name, "overwrite") == 0){ - file_out_f = TRUE; - overwrite_f = TRUE; - preserve_time_f = TRUE; - continue; - } - if (strcmp(long_option[i].name, "overwrite=") == 0){ - file_out_f = TRUE; - overwrite_f = TRUE; - preserve_time_f = TRUE; - backup_f = TRUE; - backup_suffix = (char *)p; - continue; - } - if (strcmp(long_option[i].name, "in-place") == 0){ - file_out_f = TRUE; - overwrite_f = TRUE; - preserve_time_f = FALSE; - continue; - } - if (strcmp(long_option[i].name, "in-place=") == 0){ - file_out_f = TRUE; - overwrite_f = TRUE; - preserve_time_f = FALSE; - backup_f = TRUE; - backup_suffix = (char *)p; - continue; - } -#endif -#ifdef INPUT_OPTION - if (strcmp(long_option[i].name, "cap-input") == 0){ - cap_f = TRUE; - continue; - } - if (strcmp(long_option[i].name, "url-input") == 0){ - url_f = TRUE; - continue; - } -#endif -#ifdef NUMCHAR_OPTION - if (strcmp(long_option[i].name, "numchar-input") == 0){ - numchar_f = TRUE; - continue; - } -#endif -#ifdef CHECK_OPTION - if (strcmp(long_option[i].name, "no-output") == 0){ - noout_f = TRUE; - continue; - } - if (strcmp(long_option[i].name, "debug") == 0){ - debug_f = TRUE; - continue; - } -#endif - if (strcmp(long_option[i].name, "cp932") == 0){ -#ifdef SHIFTJIS_CP932 - cp51932_f = TRUE; - cp932inv_f = -TRUE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_CP932; -#endif - continue; - } - if (strcmp(long_option[i].name, "no-cp932") == 0){ -#ifdef SHIFTJIS_CP932 - cp51932_f = FALSE; - cp932inv_f = FALSE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_ASCII; -#endif - continue; - } -#ifdef SHIFTJIS_CP932 - if (strcmp(long_option[i].name, "cp932inv") == 0){ - cp932inv_f = -TRUE; - continue; - } -#endif - -#ifdef X0212_ENABLE - if (strcmp(long_option[i].name, "x0212") == 0){ - x0212_f = TRUE; - continue; - } -#endif - -#ifdef EXEC_IO - if (strcmp(long_option[i].name, "exec-in") == 0){ - exec_f = 1; - return 0; - } - if (strcmp(long_option[i].name, "exec-out") == 0){ - exec_f = -1; - return 0; - } -#endif -#if defined(UTF8_OUTPUT_ENABLE) && defined(UTF8_INPUT_ENABLE) - if (strcmp(long_option[i].name, "no-cp932ext") == 0){ - no_cp932ext_f = TRUE; - continue; - } - if (strcmp(long_option[i].name, "no-best-fit-chars") == 0){ - no_best_fit_chars_f = TRUE; - continue; - } - if (strcmp(long_option[i].name, "fb-skip") == 0){ - encode_fallback = NULL; - continue; - } - if (strcmp(long_option[i].name, "fb-html") == 0){ - encode_fallback = encode_fallback_html; - continue; - } - if (strcmp(long_option[i].name, "fb-xml") == 0){ - encode_fallback = encode_fallback_xml; - continue; - } - if (strcmp(long_option[i].name, "fb-java") == 0){ - encode_fallback = encode_fallback_java; - continue; - } - if (strcmp(long_option[i].name, "fb-perl") == 0){ - encode_fallback = encode_fallback_perl; - continue; - } - if (strcmp(long_option[i].name, "fb-subchar") == 0){ - encode_fallback = encode_fallback_subchar; - continue; - } - if (strcmp(long_option[i].name, "fb-subchar=") == 0){ - encode_fallback = encode_fallback_subchar; - unicode_subchar = 0; - if (p[0] != '0'){ - /* decimal number */ - for (i = 0; i < 7 && nkf_isdigit(p[i]); i++){ - unicode_subchar *= 10; - unicode_subchar += hex2bin(p[i]); - } - }else if(p[1] == 'x' || p[1] == 'X'){ - /* hexadecimal number */ - for (i = 2; i < 8 && nkf_isxdigit(p[i]); i++){ - unicode_subchar <<= 4; - unicode_subchar |= hex2bin(p[i]); - } - }else{ - /* octal number */ - for (i = 1; i < 8 && nkf_isoctal(p[i]); i++){ - unicode_subchar *= 8; - unicode_subchar += hex2bin(p[i]); - } - } - w16e_conv(unicode_subchar, &i, &j); - unicode_subchar = i<<8 | j; - continue; - } -#endif -#ifdef UTF8_OUTPUT_ENABLE - if (strcmp(long_option[i].name, "ms-ucs-map") == 0){ - ms_ucs_map_f = UCS_MAP_MS; - continue; - } -#endif -#ifdef UNICODE_NORMALIZATION - if (strcmp(long_option[i].name, "utf8mac-input") == 0){ - nfc_f = TRUE; - continue; - } -#endif - if (strcmp(long_option[i].name, "prefix=") == 0){ - if (nkf_isgraph(p[0])){ - for (i = 1; nkf_isgraph(p[i]); i++){ - prefix_table[p[i]] = p[0]; - } - } - continue; - } -#if !defined(PERL_XS) && !defined(WIN32DLL) - fprintf(stderr, "unsupported long option: --%s\n", long_option[i].name); -#endif - return -1; - } - continue; - case 'b': /* buffered mode */ - unbuf_f = FALSE; - continue; - case 'u': /* non bufferd mode */ - unbuf_f = TRUE; - continue; - case 't': /* transparent mode */ - if (*cp=='1') { - /* alias of -t */ - cp++; - nop_f = TRUE; - } else if (*cp=='2') { - /* - * -t with put/get - * - * nkf -t2MB hoge.bin | nkf -t2mB | diff -s - hoge.bin - * - */ - cp++; - nop_f = 2; - } else - nop_f = TRUE; - continue; - case 'j': /* JIS output */ - case 'n': - output_encoding = nkf_enc_from_index(ISO_2022_JP); - continue; - case 'e': /* AT&T EUC output */ - output_encoding = nkf_enc_from_index(EUCJP_NKF); - continue; - case 's': /* SJIS output */ - output_encoding = nkf_enc_from_index(SHIFT_JIS); - continue; - case 'l': /* ISO8859 Latin-1 support, no conversion */ - iso8859_f = TRUE; /* Only compatible with ISO-2022-JP */ - input_encoding = nkf_enc_from_index(ISO_8859_1); - continue; - case 'i': /* Kanji IN ESC-$-@/B */ - if (*cp=='@'||*cp=='B') - kanji_intro = *cp++; - continue; - case 'o': /* ASCII IN ESC-(-J/B/H */ - /* ESC ( H was used in initial JUNET messages */ - if (*cp=='J'||*cp=='B'||*cp=='H') - ascii_intro = *cp++; - continue; - case 'h': - /* - bit:1 katakana->hiragana - bit:2 hiragana->katakana - */ - if ('9'>= *cp && *cp>='0') - hira_f |= (*cp++ -'0'); - else - hira_f |= 1; - continue; - case 'r': - rot_f = TRUE; - continue; -#if defined(MSDOS) || defined(__OS2__) - case 'T': - binmode_f = FALSE; - continue; -#endif -#ifndef PERL_XS - case 'V': - show_configuration(); - exit(EXIT_SUCCESS); - break; - case 'v': - version(); - exit(EXIT_SUCCESS); - break; -#endif -#ifdef UTF8_OUTPUT_ENABLE - case 'w': /* UTF-{8,16,32} output */ - if (cp[0] == '8') { - cp++; - if (cp[0] == '0'){ - cp++; - output_encoding = nkf_enc_from_index(UTF_8N); - } else { - output_bom_f = TRUE; - output_encoding = nkf_enc_from_index(UTF_8_BOM); - } - } else { - int enc_idx; - if ('1'== cp[0] && '6'==cp[1]) { - cp += 2; - enc_idx = UTF_16; - } else if ('3'== cp[0] && '2'==cp[1]) { - cp += 2; - enc_idx = UTF_32; - } else { - output_encoding = nkf_enc_from_index(UTF_8); - continue; - } - if (cp[0]=='L') { - cp++; - output_endian = ENDIAN_LITTLE; - output_bom_f = TRUE; - } else if (cp[0] == 'B') { - cp++; - output_bom_f = TRUE; - } - if (cp[0] == '0'){ - output_bom_f = FALSE; - cp++; - enc_idx = enc_idx == UTF_16 - ? (output_endian == ENDIAN_LITTLE ? UTF_16LE : UTF_16BE) - : (output_endian == ENDIAN_LITTLE ? UTF_32LE : UTF_32BE); - } else { - enc_idx = enc_idx == UTF_16 - ? (output_endian == ENDIAN_LITTLE ? UTF_16LE_BOM : UTF_16BE_BOM) - : (output_endian == ENDIAN_LITTLE ? UTF_32LE_BOM : UTF_32BE_BOM); - } - output_encoding = nkf_enc_from_index(enc_idx); - } - continue; -#endif -#ifdef UTF8_INPUT_ENABLE - case 'W': /* UTF input */ - if (cp[0] == '8') { - cp++; - input_encoding = nkf_enc_from_index(UTF_8); - }else{ - int enc_idx; - if ('1'== cp[0] && '6'==cp[1]) { - cp += 2; - input_endian = ENDIAN_BIG; - enc_idx = UTF_16; - } else if ('3'== cp[0] && '2'==cp[1]) { - cp += 2; - input_endian = ENDIAN_BIG; - enc_idx = UTF_32; - } else { - input_encoding = nkf_enc_from_index(UTF_8); - continue; - } - if (cp[0]=='L') { - cp++; - input_endian = ENDIAN_LITTLE; - } else if (cp[0] == 'B') { - cp++; - input_endian = ENDIAN_BIG; - } - enc_idx = (enc_idx == UTF_16 - ? (input_endian == ENDIAN_LITTLE ? UTF_16LE : UTF_16BE) - : (input_endian == ENDIAN_LITTLE ? UTF_32LE : UTF_32BE)); - input_encoding = nkf_enc_from_index(enc_idx); - } - continue; -#endif - /* Input code assumption */ - case 'J': /* ISO-2022-JP input */ - input_encoding = nkf_enc_from_index(ISO_2022_JP); - continue; - case 'E': /* EUC-JP input */ - input_encoding = nkf_enc_from_index(EUCJP_NKF); - continue; - case 'S': /* Shift_JIS input */ - input_encoding = nkf_enc_from_index(SHIFT_JIS); - continue; - case 'Z': /* Convert X0208 alphabet to ascii */ - /* alpha_f - bit:0 Convert JIS X 0208 Alphabet to ASCII - bit:1 Convert Kankaku to one space - bit:2 Convert Kankaku to two spaces - bit:3 Convert HTML Entity - bit:4 Convert JIS X 0208 Katakana to JIS X 0201 Katakana - */ - while ('0'<= *cp && *cp <='4') { - alpha_f |= 1 << (*cp++ - '0'); - } - alpha_f |= 1; - continue; - case 'x': /* Convert X0201 kana to X0208 or X0201 Conversion */ - x0201_f = FALSE; /* No X0201->X0208 conversion */ - /* accept X0201 - ESC-(-I in JIS, EUC, MS Kanji - SI/SO in JIS, EUC, MS Kanji - SS2 in EUC, JIS, not in MS Kanji - MS Kanji (0xa0-0xdf) - output X0201 - ESC-(-I in JIS (0x20-0x5f) - SS2 in EUC (0xa0-0xdf) - 0xa0-0xd in MS Kanji (0xa0-0xdf) - */ - continue; - case 'X': /* Convert X0201 kana to X0208 */ - x0201_f = TRUE; - continue; - case 'F': /* prserve new lines */ - fold_preserve_f = TRUE; - case 'f': /* folding -f60 or -f */ - fold_f = TRUE; - fold_len = 0; - while('0'<= *cp && *cp <='9') { /* we don't use atoi here */ - fold_len *= 10; - fold_len += *cp++ - '0'; - } - if (!(0= *cp && *cp>='0') - broken_f |= 1<<(*cp++ -'0'); - else - broken_f |= TRUE; - continue; -#ifndef PERL_XS - case 'O':/* for Output file */ - file_out_f = TRUE; - continue; -#endif - case 'c':/* add cr code */ - eolmode_f = CRLF; - continue; - case 'd':/* delete cr code */ - eolmode_f = LF; - continue; - case 'I': /* ISO-2022-JP output */ - iso2022jp_f = TRUE; - continue; - case 'L': /* line mode */ - if (*cp=='u') { /* unix */ - eolmode_f = LF; cp++; - } else if (*cp=='m') { /* mac */ - eolmode_f = CR; cp++; - } else if (*cp=='w') { /* windows */ - eolmode_f = CRLF; cp++; - } else if (*cp=='0') { /* no conversion */ - eolmode_f = 0; cp++; - } - continue; -#ifndef PERL_XS - case 'g': - if ('2' <= *cp && *cp <= '9') { - guess_f = 2; - cp++; - } else if (*cp == '0' || *cp == '1') { - guess_f = 1; - cp++; - } else { - guess_f = 1; - } - continue; -#endif - case SP: - /* module multiple options in a string are allowed for Perl module */ - while(*cp && *cp++!='-'); - continue; - default: -#if !defined(PERL_XS) && !defined(WIN32DLL) - fprintf(stderr, "unknown option: -%c\n", *(cp-1)); -#endif - /* bogus option but ignored */ - return -1; - } - } - return 0; -} - -#ifdef WIN32DLL -#include "nkf32dll.c" -#elif defined(PERL_XS) -#else /* WIN32DLL */ -int -main(int argc, char **argv) -{ - FILE *fin; - unsigned char *cp; - - char *outfname = NULL; - char *origfname; - -#ifdef EASYWIN /*Easy Win */ - _BufferSize.y = 400;/*Set Scroll Buffer Size*/ -#endif -#ifdef DEFAULT_CODE_LOCALE - setlocale(LC_CTYPE, ""); -#endif - nkf_state_init(); - - for (argc--,argv++; (argc > 0) && **argv == '-'; argc--, argv++) { - cp = (unsigned char *)*argv; - options(cp); -#ifdef EXEC_IO - if (exec_f){ - int fds[2], pid; - if (pipe(fds) < 0 || (pid = fork()) < 0){ - abort(); - } - if (pid == 0){ - if (exec_f > 0){ - close(fds[0]); - dup2(fds[1], 1); - }else{ - close(fds[1]); - dup2(fds[0], 0); - } - execvp(argv[1], &argv[1]); - } - if (exec_f > 0){ - close(fds[1]); - dup2(fds[0], 0); - }else{ - close(fds[0]); - dup2(fds[1], 1); - } - argc = 0; - break; - } -#endif - } - - if (guess_f) { -#ifdef CHECK_OPTION - int debug_f_back = debug_f; -#endif -#ifdef EXEC_IO - int exec_f_back = exec_f; -#endif -#ifdef X0212_ENABLE - int x0212_f_back = x0212_f; -#endif - int x0213_f_back = x0213_f; - int guess_f_back = guess_f; - reinit(); - guess_f = guess_f_back; - mime_f = FALSE; -#ifdef CHECK_OPTION - debug_f = debug_f_back; -#endif -#ifdef EXEC_IO - exec_f = exec_f_back; -#endif - x0212_f = x0212_f_back; - x0213_f = x0213_f_back; - } - - if (binmode_f == TRUE) -#if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__)) - if (freopen("","wb",stdout) == NULL) - return (-1); -#else - setbinmode(stdout); -#endif - - if (unbuf_f) - setbuf(stdout, (char *) NULL); - else - setvbuffer(stdout, (char *) stdobuf, IOBUF_SIZE); - - if (argc == 0) { - if (binmode_f == TRUE) -#if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__)) - if (freopen("","rb",stdin) == NULL) return (-1); -#else - setbinmode(stdin); -#endif - setvbuffer(stdin, (char *) stdibuf, IOBUF_SIZE); - if (nop_f) - noconvert(stdin); - else { - kanji_convert(stdin); - if (guess_f) print_guessed_code(NULL); - } - } else { - int nfiles = argc; - int is_argument_error = FALSE; - while (argc--) { - input_codename = NULL; - input_eol = 0; -#ifdef CHECK_OPTION - iconv_for_check = 0; -#endif - if ((fin = fopen((origfname = *argv++), "r")) == NULL) { - perror(*(argv-1)); - is_argument_error = TRUE; - continue; - } else { -#ifdef OVERWRITE - int fd = 0; - int fd_backup = 0; -#endif - - /* reopen file for stdout */ - if (file_out_f == TRUE) { -#ifdef OVERWRITE - if (overwrite_f){ - outfname = nkf_xmalloc(strlen(origfname) - + strlen(".nkftmpXXXXXX") - + 1); - strcpy(outfname, origfname); -#ifdef MSDOS - { - int i; - for (i = strlen(outfname); i; --i){ - if (outfname[i - 1] == '/' - || outfname[i - 1] == '\\'){ - break; - } - } - outfname[i] = '\0'; - } - strcat(outfname, "ntXXXXXX"); - mktemp(outfname); - fd = open(outfname, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, - S_IREAD | S_IWRITE); -#else - strcat(outfname, ".nkftmpXXXXXX"); - fd = mkstemp(outfname); -#endif - if (fd < 0 - || (fd_backup = dup(fileno(stdout))) < 0 - || dup2(fd, fileno(stdout)) < 0 - ){ - perror(origfname); - return -1; - } - }else -#endif - if(argc == 1) { - outfname = *argv++; - argc--; - } else { - outfname = "nkf.out"; - } - - if(freopen(outfname, "w", stdout) == NULL) { - perror (outfname); - return (-1); - } - if (binmode_f == TRUE) { -#if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__)) - if (freopen("","wb",stdout) == NULL) - return (-1); -#else - setbinmode(stdout); -#endif - } - } - if (binmode_f == TRUE) -#if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__)) - if (freopen("","rb",fin) == NULL) - return (-1); -#else - setbinmode(fin); -#endif - setvbuffer(fin, (char *) stdibuf, IOBUF_SIZE); - if (nop_f) - noconvert(fin); - else { - char *filename = NULL; - kanji_convert(fin); - if (nfiles > 1) filename = origfname; - if (guess_f) print_guessed_code(filename); - } - fclose(fin); -#ifdef OVERWRITE - if (overwrite_f) { - struct stat sb; -#if defined(MSDOS) && !defined(__MINGW32__) && !defined(__WIN32__) && !defined(__WATCOMC__) && !defined(__EMX__) && !defined(__OS2__) && !defined(__DJGPP__) - time_t tb[2]; -#else - struct utimbuf tb; -#endif - - fflush(stdout); - close(fd); - if (dup2(fd_backup, fileno(stdout)) < 0){ - perror("dup2"); - } - if (stat(origfname, &sb)) { - fprintf(stderr, "Can't stat %s\n", origfname); - } - /* $B%Q!<%_%C%7%g%s$rI|85(B */ - if (chmod(outfname, sb.st_mode)) { - fprintf(stderr, "Can't set permission %s\n", outfname); - } - - /* $B%?%$%`%9%?%s%W$rI|85(B */ - if(preserve_time_f){ -#if defined(MSDOS) && !defined(__MINGW32__) && !defined(__WIN32__) && !defined(__WATCOMC__) && !defined(__EMX__) && !defined(__OS2__) && !defined(__DJGPP__) - tb[0] = tb[1] = sb.st_mtime; - if (utime(outfname, tb)) { - fprintf(stderr, "Can't set timestamp %s\n", outfname); - } -#else - tb.actime = sb.st_atime; - tb.modtime = sb.st_mtime; - if (utime(outfname, &tb)) { - fprintf(stderr, "Can't set timestamp %s\n", outfname); - } -#endif - } - if(backup_f){ - char *backup_filename = get_backup_filename(backup_suffix, origfname); -#ifdef MSDOS - unlink(backup_filename); -#endif - if (rename(origfname, backup_filename)) { - perror(backup_filename); - fprintf(stderr, "Can't rename %s to %s\n", - origfname, backup_filename); - } - nkf_xfree(backup_filename); - }else{ -#ifdef MSDOS - if (unlink(origfname)){ - perror(origfname); - } -#endif - } - if (rename(outfname, origfname)) { - perror(origfname); - fprintf(stderr, "Can't rename %s to %s\n", - outfname, origfname); - } - nkf_xfree(outfname); - } -#endif - } - } - if (is_argument_error) - return(-1); - } -#ifdef EASYWIN /*Easy Win */ - if (file_out_f == FALSE) - scanf("%d",&end_check); - else - fclose(stdout); -#else /* for Other OS */ - if (file_out_f == TRUE) - fclose(stdout); -#endif /*Easy Win */ - return (0); -} -#endif /* WIN32DLL */ diff --git a/ext/nkf/nkf-utf8/nkf.h b/ext/nkf/nkf-utf8/nkf.h deleted file mode 100644 index b3a520da54edff..00000000000000 --- a/ext/nkf/nkf-utf8/nkf.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * - * nkf.h - Header file for nkf - * - */ - -#ifndef NKF_H -#define NKF_H - -/* Wrapper of configurations */ - -#ifndef MIME_DECODE_DEFAULT -#define MIME_DECODE_DEFAULT STRICT_MIME -#endif -#ifndef X0201_DEFAULT -#define X0201_DEFAULT TRUE -#endif - -#if defined(DEFAULT_NEWLINE) && DEFAULT_NEWLINE == 0x0D0A -#elif defined(DEFAULT_NEWLINE) && DEFAULT_NEWLINE == 0x0D -#else -#define DEFAULT_NEWLINE 0x0A -#endif -#ifdef HELP_OUTPUT_STDERR -#define HELP_OUTPUT stderr -#else -#define HELP_OUTPUT stdout -#endif - - -/* Compatibility definitions */ - -#ifdef nkf_char -#elif defined(INT_IS_SHORT) -typedef long nkf_char; -#define NKF_INT32_C(n) (n##L) -#else -typedef int nkf_char; -#define NKF_INT32_C(n) (n) -#endif - -#if (defined(__TURBOC__) || defined(_MSC_VER) || defined(LSI_C) || (defined(__WATCOMC__) && defined(__386__) && !defined(__LINUX__)) || defined(__MINGW32__) || defined(__EMX__) || defined(__MSDOS__) || defined(__WINDOWS__) || defined(__DOS__) || defined(__OS2__)) && !defined(MSDOS) -#define MSDOS -#if (defined(__Win32__) || defined(_WIN32)) && !defined(__WIN32__) -#define __WIN32__ -#endif -#endif - -#ifdef PERL_XS -#undef OVERWRITE -#endif - -#ifndef PERL_XS -#include -#endif - -#include -#include - -#if defined(MSDOS) || defined(__OS2__) -#include -#include -#if defined(_MSC_VER) || defined(__WATCOMC__) -#define mktemp _mktemp -#endif -#endif - -#ifdef MSDOS -#ifdef LSI_C -#define setbinmode(fp) fsetbin(fp) -#elif defined(__DJGPP__) -#include -void setbinmode(FILE *fp) -{ - /* we do not use libc's setmode(), which changes COOKED/RAW mode in device. */ - int fd, m; - fd = fileno(fp); - m = (__file_handle_modes[fd] & (~O_TEXT)) | O_BINARY; - __file_handle_set(fd, m); -} -#else /* Microsoft C, Turbo C */ -#define setbinmode(fp) setmode(fileno(fp), O_BINARY) -#endif -#else /* UNIX */ -#define setbinmode(fp) (void)(fp) -#endif - -#ifdef _IOFBF /* SysV and MSDOS, Windows */ -#define setvbuffer(fp, buf, size) setvbuf(fp, buf, _IOFBF, size) -#else /* BSD */ -#define setvbuffer(fp, buf, size) setbuffer(fp, buf, size) -#endif - -/*Borland C++ 4.5 EasyWin*/ -#if defined(__TURBOC__) && defined(_Windows) && !defined(__WIN32__) /*Easy Win */ -#define EASYWIN -#ifndef __WIN16__ -#define __WIN16__ -#endif -#include -#endif - -#ifdef OVERWRITE -/* added by satoru@isoternet.org */ -#if defined(__EMX__) -#include -#endif -#include -#if !defined(MSDOS) || defined(__DJGPP__) /* UNIX, djgpp */ -#include -#if defined(__WATCOMC__) -#include -#else -#include -#endif -#else /* defined(MSDOS) */ -#ifdef __WIN32__ -#ifdef __BORLANDC__ /* BCC32 */ -#include -#else /* !defined(__BORLANDC__) */ -#include -#endif /* (__BORLANDC__) */ -#else /* !defined(__WIN32__) */ -#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__WATCOMC__) || defined(__OS2__) || defined(__EMX__) || defined(__IBMC__) || defined(__IBMCPP__) /* VC++, MinGW, Watcom, emx+gcc, IBM VAC++ */ -#include -#elif defined(__TURBOC__) /* BCC */ -#include -#elif defined(LSI_C) /* LSI C */ -#endif /* (__WIN32__) */ -#endif -#endif -#endif - -#if !defined(DEFAULT_CODE_JIS) && !defined(DEFAULT_CODE_SJIS) && \ - !defined(DEFAULT_CODE_WINDOWS_31J) && !defined(DEFAULT_CODE_EUC) && \ - !defined(DEFAULT_CODE_UTF8) && !defined(DEFAULT_CODE_LOCALE) -#define DEFAULT_CODE_LOCALE -#endif - -#ifdef DEFAULT_CODE_LOCALE - -#if defined(__WIN32__) /* not win32 should be posix */ -# ifndef HAVE_LOCALE_H -# define HAVE_LOCALE_H -# endif -#elif defined(__OS2__) -# undef HAVE_LANGINFO_H /* We do not use kLIBC's langinfo. */ -# ifndef HAVE_LOCALE_H -# define HAVE_LOCALE_H -# endif -#elif defined(MSDOS) -# ifndef HAVE_LOCALE_H -# define HAVE_LOCALE_H -# endif -#elif defined(__BIONIC__) /* bionic doesn't have locale */ -#else -# ifndef HAVE_LANGINFO_H -# define HAVE_LANGINFO_H -# endif -# ifndef HAVE_LOCALE_H -# define HAVE_LOCALE_H -# endif -#endif - -#ifdef HAVE_LANGINFO_H -#include -#endif -#ifdef HAVE_LOCALE_H -#include -#endif - -#endif /* DEFAULT_CODE_LOCALE */ - -#define FALSE 0 -#define TRUE 1 - -#ifndef ARG_UNUSED -#if defined(__GNUC__) -# define ARG_UNUSED __attribute__ ((unused)) -#else -# define ARG_UNUSED -#endif -#endif - -#ifdef WIN32DLL -#include "nkf32.h" -#endif - -#endif /* NKF_H */ diff --git a/ext/nkf/nkf-utf8/utf8tbl.c b/ext/nkf/nkf-utf8/utf8tbl.c deleted file mode 100644 index a31e4e7805dec0..00000000000000 --- a/ext/nkf/nkf-utf8/utf8tbl.c +++ /dev/null @@ -1,14638 +0,0 @@ -/* - * utf8tbl.c - Conversion Table for nkf - * - */ - -#include "config.h" -#include "utf8tbl.h" - -#ifdef UTF8_OUTPUT_ENABLE -static const unsigned short euc_to_utf8_A1[] = { - 0x3000, 0x3001, 0x3002, 0xFF0C, 0xFF0E, 0x30FB, 0xFF1A, - 0xFF1B, 0xFF1F, 0xFF01, 0x309B, 0x309C, 0x00B4, 0xFF40, 0x00A8, - 0xFF3E, 0x203E, 0xFF3F, 0x30FD, 0x30FE, 0x309D, 0x309E, 0x3003, - 0x4EDD, 0x3005, 0x3006, 0x3007, 0x30FC, 0x2014, 0x2010, 0xFF0F, - 0xFF3C, 0x301C, 0x2016, 0xFF5C, 0x2026, 0x2025, 0x2018, 0x2019, - 0x201C, 0x201D, 0xFF08, 0xFF09, 0x3014, 0x3015, 0xFF3B, 0xFF3D, - 0xFF5B, 0xFF5D, 0x3008, 0x3009, 0x300A, 0x300B, 0x300C, 0x300D, - 0x300E, 0x300F, 0x3010, 0x3011, 0xFF0B, 0x2212, 0x00B1, 0x00D7, - 0x00F7, 0xFF1D, 0x2260, 0xFF1C, 0xFF1E, 0x2266, 0x2267, 0x221E, - 0x2234, 0x2642, 0x2640, 0x00B0, 0x2032, 0x2033, 0x2103, 0x00A5, - 0xFF04, 0x00A2, 0x00A3, 0xFF05, 0xFF03, 0xFF06, 0xFF0A, 0xFF20, - 0x00A7, 0x2606, 0x2605, 0x25CB, 0x25CF, 0x25CE, 0x25C7, -}; - -/* Microsoft UCS Mapping Compatible */ -static const unsigned short euc_to_utf8_A1_ms[] = { - 0x3000, 0x3001, 0x3002, 0xFF0C, 0xFF0E, 0x30FB, 0xFF1A, - 0xFF1B, 0xFF1F, 0xFF01, 0x309B, 0x309C, 0x00B4, 0xFF40, 0x00A8, - 0xFF3E, 0xFFE3, 0xFF3F, 0x30FD, 0x30FE, 0x309D, 0x309E, 0x3003, - 0x4EDD, 0x3005, 0x3006, 0x3007, 0x30FC, 0x2015, 0x2010, 0xFF0F, - 0xFF3C, 0xFF5E, 0x2225, 0xFF5C, 0x2026, 0x2025, 0x2018, 0x2019, - 0x201C, 0x201D, 0xFF08, 0xFF09, 0x3014, 0x3015, 0xFF3B, 0xFF3D, - 0xFF5B, 0xFF5D, 0x3008, 0x3009, 0x300A, 0x300B, 0x300C, 0x300D, - 0x300E, 0x300F, 0x3010, 0x3011, 0xFF0B, 0xFF0D, 0x00B1, 0x00D7, - 0x00F7, 0xFF1D, 0x2260, 0xFF1C, 0xFF1E, 0x2266, 0x2267, 0x221E, - 0x2234, 0x2642, 0x2640, 0x00B0, 0x2032, 0x2033, 0x2103, 0xFFE5, - 0xFF04, 0xFFE0, 0xFFE1, 0xFF05, 0xFF03, 0xFF06, 0xFF0A, 0xFF20, - 0x00A7, 0x2606, 0x2605, 0x25CB, 0x25CF, 0x25CE, 0x25C7, -}; -static const unsigned short euc_to_utf8_A2[] = { - 0x25C6, 0x25A1, 0x25A0, 0x25B3, 0x25B2, 0x25BD, 0x25BC, - 0x203B, 0x3012, 0x2192, 0x2190, 0x2191, 0x2193, 0x3013, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2208, 0x220B, 0x2286, 0x2287, 0x2282, 0x2283, - 0x222A, 0x2229, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2227, 0x2228, 0x00AC, 0x21D2, 0x21D4, 0x2200, - 0x2203, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x2220, 0x22A5, 0x2312, 0x2202, - 0x2207, 0x2261, 0x2252, 0x226A, 0x226B, 0x221A, 0x223D, 0x221D, - 0x2235, 0x222B, 0x222C, 0, 0, 0, 0, 0, - 0, 0, 0x212B, 0x2030, 0x266F, 0x266D, 0x266A, 0x2020, - 0x2021, 0x00B6, 0, 0, 0, 0, 0x25EF, -}; - -/* Microsoft UCS Mapping Compatible */ -static const unsigned short euc_to_utf8_A2_ms[] = { - 0x25C6, 0x25A1, 0x25A0, 0x25B3, 0x25B2, 0x25BD, 0x25BC, - 0x203B, 0x3012, 0x2192, 0x2190, 0x2191, 0x2193, 0x3013, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2208, 0x220B, 0x2286, 0x2287, 0x2282, 0x2283, - 0x222A, 0x2229, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2227, 0x2228, 0xFFE2, 0x21D2, 0x21D4, 0x2200, - 0x2203, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x2220, 0x22A5, 0x2312, 0x2202, - 0x2207, 0x2261, 0x2252, 0x226A, 0x226B, 0x221A, 0x223D, 0x221D, - 0x2235, 0x222B, 0x222C, 0, 0, 0, 0, 0, - 0, 0, 0x212B, 0x2030, 0x266F, 0x266D, 0x266A, 0x2020, - 0x2021, 0x00B6, 0, 0, 0, 0, 0x25EF, -}; -static const unsigned short euc_to_utf8_A2_x0213[] = { - 0x25C6, 0x25A1, 0x25A0, 0x25B3, 0x25B2, 0x25BD, 0x25BC, - 0x203B, 0x3012, 0x2192, 0x2190, 0x2191, 0x2193, 0x3013, 0xFF07, - 0xFF02, 0xFF0D, 0xFF5E, 0x3033, 0x3034, 0x3035, 0x303B, 0x303C, - 0x30FF, 0x309F, 0x2208, 0x220B, 0x2286, 0x2287, 0x2282, 0x2283, - 0x222A, 0x2229, 0x2284, 0x2285, 0x228A, 0x228B, 0x2209, 0x2205, - 0x2305, 0x2306, 0x2227, 0x2228, 0x00AC, 0x21D2, 0x21D4, 0x2200, - 0x2203, 0x2295, 0x2296, 0x2297, 0x2225, 0x2226, 0xFF5F, 0xFF60, - 0x3018, 0x3019, 0x3016, 0x3017, 0x2220, 0x22A5, 0x2312, 0x2202, - 0x2207, 0x2261, 0x2252, 0x226A, 0x226B, 0x221A, 0x223D, 0x221D, - 0x2235, 0x222B, 0x222C, 0x2262, 0x2243, 0x2245, 0x2248, 0x2276, - 0x2277, 0x2194, 0x212B, 0x2030, 0x266F, 0x266D, 0x266A, 0x2020, - 0x2021, 0x00B6, 0x266E, 0x266B, 0x266C, 0x2669, 0x25EF, -}; -static const unsigned short euc_to_utf8_A3[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17, - 0xFF18, 0xFF19, 0, 0, 0, 0, 0, 0, - 0, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, - 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, - 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, - 0xFF38, 0xFF39, 0xFF3A, 0, 0, 0, 0, 0, - 0, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, - 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, - 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, - 0xFF58, 0xFF59, 0xFF5A, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_A3_x0213[] = { - 0x25B7, 0x25B6, 0x25C1, 0x25C0, 0x2197, 0x2198, 0x2196, - 0x2199, 0x21C4, 0x21E8, 0x21E6, 0x21E7, 0x21E9, 0x2934, 0x2935, - 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17, - 0xFF18, 0xFF19, 0x29BF, 0x25C9, 0x303D, 0xFE46, 0xFE45, 0x25E6, - 0x2022, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, - 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, - 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, - 0xFF38, 0xFF39, 0xFF3A, 0x2213, 0x2135, 0x210F, 0x33CB, 0x2113, - 0x2127, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, - 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, - 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, - 0xFF58, 0xFF59, 0xFF5A, 0x30A0, 0x2013, 0x29FA, 0x29FB, -}; -static const unsigned short euc_to_utf8_A4[] = { - 0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, - 0x3048, 0x3049, 0x304A, 0x304B, 0x304C, 0x304D, 0x304E, 0x304F, - 0x3050, 0x3051, 0x3052, 0x3053, 0x3054, 0x3055, 0x3056, 0x3057, - 0x3058, 0x3059, 0x305A, 0x305B, 0x305C, 0x305D, 0x305E, 0x305F, - 0x3060, 0x3061, 0x3062, 0x3063, 0x3064, 0x3065, 0x3066, 0x3067, - 0x3068, 0x3069, 0x306A, 0x306B, 0x306C, 0x306D, 0x306E, 0x306F, - 0x3070, 0x3071, 0x3072, 0x3073, 0x3074, 0x3075, 0x3076, 0x3077, - 0x3078, 0x3079, 0x307A, 0x307B, 0x307C, 0x307D, 0x307E, 0x307F, - 0x3080, 0x3081, 0x3082, 0x3083, 0x3084, 0x3085, 0x3086, 0x3087, - 0x3088, 0x3089, 0x308A, 0x308B, 0x308C, 0x308D, 0x308E, 0x308F, - 0x3090, 0x3091, 0x3092, 0x3093, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_A4_x0213[] = { - 0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, - 0x3048, 0x3049, 0x304A, 0x304B, 0x304C, 0x304D, 0x304E, 0x304F, - 0x3050, 0x3051, 0x3052, 0x3053, 0x3054, 0x3055, 0x3056, 0x3057, - 0x3058, 0x3059, 0x305A, 0x305B, 0x305C, 0x305D, 0x305E, 0x305F, - 0x3060, 0x3061, 0x3062, 0x3063, 0x3064, 0x3065, 0x3066, 0x3067, - 0x3068, 0x3069, 0x306A, 0x306B, 0x306C, 0x306D, 0x306E, 0x306F, - 0x3070, 0x3071, 0x3072, 0x3073, 0x3074, 0x3075, 0x3076, 0x3077, - 0x3078, 0x3079, 0x307A, 0x307B, 0x307C, 0x307D, 0x307E, 0x307F, - 0x3080, 0x3081, 0x3082, 0x3083, 0x3084, 0x3085, 0x3086, 0x3087, - 0x3088, 0x3089, 0x308A, 0x308B, 0x308C, 0x308D, 0x308E, 0x308F, - 0x3090, 0x3091, 0x3092, 0x3093, 0x3094, 0x3095, 0x3096, /*0x304B*/ 0x309A, - /*0x304D*/ 0x309A, /*0x304F*/ 0x309A, /*0x3051*/ 0x309A, /*0x3053*/ 0x309A, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_A5[] = { - 0x30A1, 0x30A2, 0x30A3, 0x30A4, 0x30A5, 0x30A6, 0x30A7, - 0x30A8, 0x30A9, 0x30AA, 0x30AB, 0x30AC, 0x30AD, 0x30AE, 0x30AF, - 0x30B0, 0x30B1, 0x30B2, 0x30B3, 0x30B4, 0x30B5, 0x30B6, 0x30B7, - 0x30B8, 0x30B9, 0x30BA, 0x30BB, 0x30BC, 0x30BD, 0x30BE, 0x30BF, - 0x30C0, 0x30C1, 0x30C2, 0x30C3, 0x30C4, 0x30C5, 0x30C6, 0x30C7, - 0x30C8, 0x30C9, 0x30CA, 0x30CB, 0x30CC, 0x30CD, 0x30CE, 0x30CF, - 0x30D0, 0x30D1, 0x30D2, 0x30D3, 0x30D4, 0x30D5, 0x30D6, 0x30D7, - 0x30D8, 0x30D9, 0x30DA, 0x30DB, 0x30DC, 0x30DD, 0x30DE, 0x30DF, - 0x30E0, 0x30E1, 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x30E7, - 0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x30EF, - 0x30F0, 0x30F1, 0x30F2, 0x30F3, 0x30F4, 0x30F5, 0x30F6, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_A5_x0213[] = { - 0x30A1, 0x30A2, 0x30A3, 0x30A4, 0x30A5, 0x30A6, 0x30A7, - 0x30A8, 0x30A9, 0x30AA, 0x30AB, 0x30AC, 0x30AD, 0x30AE, 0x30AF, - 0x30B0, 0x30B1, 0x30B2, 0x30B3, 0x30B4, 0x30B5, 0x30B6, 0x30B7, - 0x30B8, 0x30B9, 0x30BA, 0x30BB, 0x30BC, 0x30BD, 0x30BE, 0x30BF, - 0x30C0, 0x30C1, 0x30C2, 0x30C3, 0x30C4, 0x30C5, 0x30C6, 0x30C7, - 0x30C8, 0x30C9, 0x30CA, 0x30CB, 0x30CC, 0x30CD, 0x30CE, 0x30CF, - 0x30D0, 0x30D1, 0x30D2, 0x30D3, 0x30D4, 0x30D5, 0x30D6, 0x30D7, - 0x30D8, 0x30D9, 0x30DA, 0x30DB, 0x30DC, 0x30DD, 0x30DE, 0x30DF, - 0x30E0, 0x30E1, 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x30E7, - 0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x30EF, - 0x30F0, 0x30F1, 0x30F2, 0x30F3, 0x30F4, 0x30F5, 0x30F6, /*0x30AB*/ 0x309A, - /*0x30AD*/ 0x309A, /*0x30AF*/ 0x309A, /*0x30B1*/ 0x309A, /*0x30B3*/ 0x309A, /*0x30BB*/ 0x309A, /*0x30C4*/ 0x309A, /*0x30C8*/ 0x309A, -}; -static const unsigned short euc_to_utf8_A6[] = { - 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, - 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, - 0x03A0, 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, - 0x03A9, 0, 0, 0, 0, 0, 0, 0, - 0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, - 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, - 0x03C0, 0x03C1, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, - 0x03C9, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short euc_to_utf8_A6_x0213[] = { - 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, - 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, - 0x03A0, 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, - 0x03A9, 0x2664, 0x2660, 0x2662, 0x2666, 0x2661, 0x2665, 0x2667, - 0x2663, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, - 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, - 0x03C0, 0x03C1, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, - 0x03C9, 0x03C2, 0x24F5, 0x24F6, 0x24F7, 0x24F8, 0x24F9, 0x24FA, - 0x24FB, 0x24FC, 0x24FD, 0x24FE, 0x2616, 0x2617, 0x3020, 0x260E, - 0x2600, 0x2601, 0x2602, 0x2603, 0x2668, 0x25B1, 0x31F0, 0x31F1, - 0x31F2, 0x31F3, 0x31F4, 0x31F5, 0x31F6, 0x31F7, 0x31F8, 0x31F9, - /*0x31F7*/ 0x309A, 0x31FA, 0x31FB, 0x31FC, 0x31FD, 0x31FE, 0x31FF, -}; -static const unsigned short euc_to_utf8_A7[] = { - 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0401, - 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, - 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, - 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, - 0x042E, 0x042F, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0451, - 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, - 0x043E, 0x043F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, - 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, - 0x044E, 0x044F, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_A7_x0213[] = { - 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0401, - 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, - 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, - 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, - 0x042E, 0x042F, 0x23BE, 0x23BF, 0x23C0, 0x23C1, 0x23C2, 0x23C3, - 0x23C4, 0x23C5, 0x23C6, 0x23C7, 0x23C8, 0x23C9, 0x23CA, 0x23CB, - 0x23CC, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0451, - 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, - 0x043E, 0x043F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, - 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, - 0x044E, 0x044F, 0x30F7, 0x30F8, 0x30F9, 0x30FA, 0x22DA, 0x22DB, - 0x2153, 0x2154, 0x2155, 0x2713, 0x2318, 0x2423, 0x23CE, -}; -static const unsigned short euc_to_utf8_A8[] = { - 0x2500, 0x2502, 0x250C, 0x2510, 0x2518, 0x2514, 0x251C, - 0x252C, 0x2524, 0x2534, 0x253C, 0x2501, 0x2503, 0x250F, 0x2513, - 0x251B, 0x2517, 0x2523, 0x2533, 0x252B, 0x253B, 0x254B, 0x2520, - 0x252F, 0x2528, 0x2537, 0x253F, 0x251D, 0x2530, 0x2525, 0x2538, - 0x2542, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short euc_to_utf8_A8_x0213[] = { - 0x2500, 0x2502, 0x250C, 0x2510, 0x2518, 0x2514, 0x251C, - 0x252C, 0x2524, 0x2534, 0x253C, 0x2501, 0x2503, 0x250F, 0x2513, - 0x251B, 0x2517, 0x2523, 0x2533, 0x252B, 0x253B, 0x254B, 0x2520, - 0x252F, 0x2528, 0x2537, 0x253F, 0x251D, 0x2530, 0x2525, 0x2538, - 0x2542, 0x3251, 0x3252, 0x3253, 0x3254, 0x3255, 0x3256, 0x3257, - 0x3258, 0x3259, 0x325A, 0x325B, 0x325C, 0x325D, 0x325E, 0x325F, - 0x32B1, 0x32B2, 0x32B3, 0x32B4, 0x32B5, 0x32B6, 0x32B7, 0x32B8, - 0x32B9, 0x32BA, 0x32BB, 0x32BC, 0x32BD, 0x32BE, 0x32BF, 0, - 0, 0, 0, 0, 0, 0, 0, 0x25D0, - 0x25D1, 0x25D2, 0x25D3, 0x203C, 0x2047, 0x2048, 0x2049, 0x01CD, - 0x01CE, 0x01D0, 0x1E3E, 0x1E3F, 0x01F8, 0x01F9, 0x01D1, 0x01D2, - 0x01D4, 0x01D6, 0x01D8, 0x01DA, 0x01DC, 0, 0, -}; -static const unsigned short euc_to_utf8_A9[] = { - 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, - 0x2467, 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, - 0x246F, 0x2470, 0x2471, 0x2472, 0x2473, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x2474, - 0x2475, 0x2476, 0x2477, 0x2478, 0x2479, 0x247A, 0x247B, 0x247C, - 0x247D, 0x247E, 0x247F, 0x2480, 0x2481, 0x2482, 0x2483, 0x2484, - 0x2485, 0x2486, 0x2487, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x2776, 0x2777, 0x2778, - 0x2779, 0x277A, 0x277B, 0x277C, 0x277D, 0x277E, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2488, 0x2489, 0x248A, 0x248B, 0x248C, 0x248D, - 0x248E, 0x248F, 0x2490, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_A9_x0213[] = { - 0x20AC, 0x00A0, 0x00A1, 0x00A4, 0x00A6, 0x00A9, 0x00AA, - 0x00AB, 0x00AD, 0x00AE, 0x00AF, 0x00B2, 0x00B3, 0x00B7, 0x00B8, - 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0, - 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, - 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0, - 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D8, 0x00D9, - 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0, 0x00E1, - 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, - 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1, - 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F8, 0x00F9, 0x00FA, - 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF, 0x0100, 0x012A, 0x016A, - 0x0112, 0x014C, 0x0101, 0x012B, 0x016B, 0x0113, 0x014D, -}; -static const unsigned short euc_to_utf8_AA[] = { - 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, - 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0, 0, 0, - 0, 0, 0, 0, 0, 0x2170, 0x2171, 0x2172, - 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, - 0x217B, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x249C, 0x249D, 0x249E, - 0x249F, 0x24A0, 0x24A1, 0x24A2, 0x24A3, 0x24A4, 0x24A5, 0x24A6, - 0x24A7, 0x24A8, 0x24A9, 0x24AA, 0x24AB, 0x24AC, 0x24AD, 0x24AE, - 0x24AF, 0x24B0, 0x24B1, 0x24B2, 0x24B3, 0x24B4, 0x24B5, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_AA_x0213[] = { - 0x0104, 0x02D8, 0x0141, 0x013D, 0x015A, 0x0160, 0x015E, - 0x0164, 0x0179, 0x017D, 0x017B, 0x0105, 0x02DB, 0x0142, 0x013E, - 0x015B, 0x02C7, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, - 0x017C, 0x0154, 0x0102, 0x0139, 0x0106, 0x010C, 0x0118, 0x011A, - 0x010E, 0x0143, 0x0147, 0x0150, 0x0158, 0x016E, 0x0170, 0x0162, - 0x0155, 0x0103, 0x013A, 0x0107, 0x010D, 0x0119, 0x011B, 0x010F, - 0x0111, 0x0144, 0x0148, 0x0151, 0x0159, 0x016F, 0x0171, 0x0163, - 0x02D9, 0x0108, 0x011C, 0x0124, 0x0134, 0x015C, 0x016C, 0x0109, - 0x011D, 0x0125, 0x0135, 0x015D, 0x016D, 0x0271, 0x028B, 0x027E, - 0x0283, 0x0292, 0x026C, 0x026E, 0x0279, 0x0288, 0x0256, 0x0273, - 0x027D, 0x0282, 0x0290, 0x027B, 0x026D, 0x025F, 0x0272, 0x029D, - 0x028E, 0x0261, 0x014B, 0x0270, 0x0281, 0x0127, 0x0295, -}; -static const unsigned short euc_to_utf8_AB[] = { - 0x339C, 0x339F, 0x339D, 0x33A0, 0x33A4, 0, 0x33A1, - 0x33A5, 0x339E, 0x33A2, 0x338E, 0, 0x338F, 0x33C4, 0x3396, - 0x3397, 0x2113, 0x3398, 0x33B3, 0x33B2, 0x33B1, 0x33B0, 0x2109, - 0x33D4, 0x33CB, 0x3390, 0x3385, 0x3386, 0x3387, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x2116, 0x33CD, 0x2121, 0, -}; -static const unsigned short euc_to_utf8_AB_x0213[] = { - 0x0294, 0x0266, 0x0298, 0x01C2, 0x0253, 0x0257, 0x0284, - 0x0260, 0x0193, 0x0153, 0x0152, 0x0268, 0x0289, 0x0258, 0x0275, - 0x0259, 0x025C, 0x025E, 0x0250, 0x026F, 0x028A, 0x0264, 0x028C, - 0x0254, 0x0251, 0x0252, 0x028D, 0x0265, 0x02A2, 0x02A1, 0x0255, - 0x0291, 0x027A, 0x0267, 0x025A, /*0x00E6*/ 0x0300, 0x01FD, 0x1F70, 0x1F71, - /*0x0254*/ 0x0300, /*0x0254*/ 0x0301, /*0x028C*/ 0x0300, /*0x028C*/ 0x0301, /*0x0259*/ 0x0300, /*0x0259*/ 0x0301, /*0x025A*/ 0x0300, /*0x025A*/ 0x0301, - 0x1F72, 0x1F73, 0x0361, 0x02C8, 0x02CC, 0x02D0, 0x02D1, 0x0306, - 0x203F, 0x030B, /*0*/ 0x0301, 0x0304, /*0*/ 0x0300, 0x030F, 0x030C, 0x0302, - /*0*/ 0x02E5, 0x02E6, 0x02E7, 0x02E8, /*0*/ 0x02E9, /*0x02E9*/ 0x02E5, /*0x02E5*/ 0x02E9, 0x0325, - 0x032C, 0x0339, 0x031C, 0x031F, 0x0320, 0x0308, 0x033D, 0x0329, - 0x032F, 0x02DE, 0x0324, 0x0330, 0x033C, 0x0334, 0x031D, 0x031E, - 0x0318, 0x0319, 0x032A, 0x033A, 0x033B, 0x0303, 0x031A, -}; -static const unsigned short euc_to_utf8_AC[] = { - 0x2664, 0x2667, 0x2661, 0x2662, 0x2660, 0x2663, 0x2665, - 0x2666, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x3020, 0x260E, 0x3004, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x261E, 0x261C, 0x261D, 0x261F, 0x21C6, 0x21C4, 0x21C5, - 0, 0x21E8, 0x21E6, 0x21E7, 0x21E9, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short euc_to_utf8_AC_mac[] = { - 0x2664, 0x2667, 0x2661, 0x2662, 0x2660, 0x2663, 0x2665, - 0x2666, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x3020, 0x260E, 0x3004, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x261E, 0x261C, 0x261D, 0x261F, 0x21C6, 0x21C4, 0x21C5, - 0, 0x21E8, 0x21E6, 0x21E7, 0x21E9, 0x2192, 0x2190, 0x2191, - 0x2193, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short euc_to_utf8_AC_x0213[] = { - 0x2776, 0x2777, 0x2778, 0x2779, 0x277A, 0x277B, 0x277C, - 0x277D, 0x277E, 0x277F, 0x24EB, 0x24EC, 0x24ED, 0x24EE, 0x24EF, - 0x24F0, 0x24F1, 0x24F2, 0x24F3, 0x24F4, 0x2170, 0x2171, 0x2172, - 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, - 0x217B, 0x24D0, 0x24D1, 0x24D2, 0x24D3, 0x24D4, 0x24D5, 0x24D6, - 0x24D7, 0x24D8, 0x24D9, 0x24DA, 0x24DB, 0x24DC, 0x24DD, 0x24DE, - 0x24DF, 0x24E0, 0x24E1, 0x24E2, 0x24E3, 0x24E4, 0x24E5, 0x24E6, - 0x24E7, 0x24E8, 0x24E9, 0x32D0, 0x32D1, 0x32D2, 0x32D3, 0x32D4, - 0x32D5, 0x32D6, 0x32D7, 0x32D8, 0x32D9, 0x32DA, 0x32DB, 0x32DC, - 0x32DD, 0x32DE, 0x32DF, 0x32E0, 0x32E1, 0x32E2, 0x32E3, 0x32FA, - 0x32E9, 0x32E5, 0x32ED, 0x32EC, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x2051, 0x2042, -}; -static const unsigned short euc_to_utf8_AD[] = { - 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, - 0x2467, 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, - 0x246F, 0x2470, 0x2471, 0x2472, 0x2473, 0x2160, 0x2161, 0x2162, - 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0, - 0x3349, 0x3314, 0x3322, 0x334D, 0x3318, 0x3327, 0x3303, 0x3336, - 0x3351, 0x3357, 0x330D, 0x3326, 0x3323, 0x332B, 0x334A, 0x333B, - 0x339C, 0x339D, 0x339E, 0x338E, 0x338F, 0x33C4, 0x33A1, 0, - 0, 0, 0, 0, 0, 0, 0, 0x337B, - 0x301D, 0x301F, 0x2116, 0x33CD, 0x2121, 0x32A4, 0x32A5, 0x32A6, - 0x32A7, 0x32A8, 0x3231, 0x3232, 0x3239, 0x337E, 0x337D, 0x337C, - 0x2252, 0x2261, 0x222B, 0x222E, 0x2211, 0x221A, 0x22A5, 0x2220, - 0x221F, 0x22BF, 0x2235, 0x2229, 0x222A, 0, 0x3299, -}; -static const unsigned short euc_to_utf8_AD_mac[] = { - 0x65E5, 0x6708, 0x706B, 0x6C34, 0x6728, 0x91D1, 0x571F, - 0x796D, 0x795D, 0x81EA, 0x81F3, 0x3239, 0x547C, 0x3231, 0x8CC7, - 0x540D, 0x3232, 0x5B66, 0x8CA1, 0x793E, 0x7279, 0x76E3, 0x4F01, - 0x5354, 0x52B4, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0, - 0x3349, 0x3314, 0x3322, 0x334D, 0x3318, 0x3327, 0x3303, 0x3336, - 0x3351, 0x3357, 0x330D, 0x3326, 0x3323, 0x332B, 0x334A, 0x333B, - 0x339C, 0x339D, 0x339E, 0x338E, 0x338F, 0x33C4, 0x33A1, 0, - 0, 0, 0, 0, 0, 0, 0, 0x337B, - 0x301D, 0x301F, 0x2116, 0x33CD, 0x2121, 0x32A4, 0x32A5, 0x32A6, - 0x32A7, 0x32A8, 0x3231, 0x3232, 0x3239, 0x337E, 0x337D, 0x337C, - 0x2252, 0x5927, 0x5C0F, 0x32A4, 0x32A5, 0x32A6, 0x32A7, 0x32A8, - 0x533B, 0x8CA1, 0x512A, 0x52B4, 0x5370, 0x63A7, 0x79D8, -}; -static const unsigned short euc_to_utf8_AD_x0213[] = { - 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, - 0x2467, 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, - 0x246F, 0x2470, 0x2471, 0x2472, 0x2473, 0x2160, 0x2161, 0x2162, - 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, - 0x3349, 0x3314, 0x3322, 0x334D, 0x3318, 0x3327, 0x3303, 0x3336, - 0x3351, 0x3357, 0x330D, 0x3326, 0x3323, 0x332B, 0x334A, 0x333B, - 0x339C, 0x339D, 0x339E, 0x338E, 0x338F, 0x33C4, 0x33A1, 0x216B, - 0, 0, 0, 0, 0, 0, 0, 0x337B, - 0x301D, 0x301F, 0x2116, 0x33CD, 0x2121, 0x32A4, 0x32A5, 0x32A6, - 0x32A7, 0x32A8, 0x3231, 0x3232, 0x3239, 0x337E, 0x337D, 0x337C, - 0x2252, 0x2261, 0x222B, 0x222E, 0x2211, 0x221A, 0x22A5, 0x2220, - 0x221F, 0x22BF, 0x2235, 0x2229, 0x222A, 0x2756, 0x261E, -}; -static const unsigned short euc_to_utf8_AE[] = { - 0x3349, 0x3322, 0x334D, 0x3314, 0x3316, 0x3305, 0x3333, - 0x334E, 0x3303, 0x3336, 0x3318, 0x3315, 0x3327, 0x3351, 0x334A, - 0x3339, 0x3357, 0x330D, 0x3342, 0x3323, 0x3326, 0x333B, 0x332B, - 0, 0, 0, 0, 0, 0, 0, 0x3300, - 0x331E, 0x332A, 0x3331, 0x3347, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x337E, - 0x337D, 0x337C, 0x337B, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x337F, 0, 0, -}; -static const unsigned short euc_to_utf8_AE_x0213[] = { - 0x4FF1, 0xD840 /*0xDC0B*/, 0x3402, 0x4E28, 0x4E2F, 0x4E30, 0x4E8D, - 0x4EE1, 0x4EFD, 0x4EFF, 0x4F03, 0x4F0B, 0x4F60, 0x4F48, 0x4F49, - 0x4F56, 0x4F5F, 0x4F6A, 0x4F6C, 0x4F7E, 0x4F8A, 0x4F94, 0x4F97, - 0xFA30, 0x4FC9, 0x4FE0, 0x5001, 0x5002, 0x500E, 0x5018, 0x5027, - 0x502E, 0x5040, 0x503B, 0x5041, 0x5094, 0x50CC, 0x50F2, 0x50D0, - 0x50E6, 0xFA31, 0x5106, 0x5103, 0x510B, 0x511E, 0x5135, 0x514A, - 0xFA32, 0x5155, 0x5157, 0x34B5, 0x519D, 0x51C3, 0x51CA, 0x51DE, - 0x51E2, 0x51EE, 0x5201, 0x34DB, 0x5213, 0x5215, 0x5249, 0x5257, - 0x5261, 0x5293, 0x52C8, 0xFA33, 0x52CC, 0x52D0, 0x52D6, 0x52DB, - 0xFA34, 0x52F0, 0x52FB, 0x5300, 0x5307, 0x531C, 0xFA35, 0x5361, - 0x5363, 0x537D, 0x5393, 0x539D, 0x53B2, 0x5412, 0x5427, 0x544D, - 0x549C, 0x546B, 0x5474, 0x547F, 0x5488, 0x5496, 0x54A1, -}; -static const unsigned short euc_to_utf8_AF[] = { - 0x222E, 0x221F, 0x22BF, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x301D, 0x301F, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x3094, 0, 0x30F7, 0x30F8, 0x30F9, 0x30FA, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short euc_to_utf8_AF_x0213[] = { - 0x54A9, 0x54C6, 0x54FF, 0x550E, 0x552B, 0x5535, 0x5550, - 0x555E, 0x5581, 0x5586, 0x558E, 0xFA36, 0x55AD, 0x55CE, 0xFA37, - 0x5608, 0x560E, 0x563B, 0x5649, 0x5676, 0x5666, 0xFA38, 0x566F, - 0x5671, 0x5672, 0x5699, 0x569E, 0x56A9, 0x56AC, 0x56B3, 0x56C9, - 0x56CA, 0x570A, 0xD844 /*0xDE3D*/, 0x5721, 0x572F, 0x5733, 0x5734, 0x5770, - 0x5777, 0x577C, 0x579C, 0xFA0F, 0xD844 /*0xDF1B*/, 0x57B8, 0x57C7, 0x57C8, - 0x57CF, 0x57E4, 0x57ED, 0x57F5, 0x57F6, 0x57FF, 0x5809, 0xFA10, - 0x5861, 0x5864, 0xFA39, 0x587C, 0x5889, 0x589E, 0xFA3A, 0x58A9, - 0xD845 /*0xDC6E*/, 0x58D2, 0x58CE, 0x58D4, 0x58DA, 0x58E0, 0x58E9, 0x590C, - 0x8641, 0x595D, 0x596D, 0x598B, 0x5992, 0x59A4, 0x59C3, 0x59D2, - 0x59DD, 0x5A13, 0x5A23, 0x5A67, 0x5A6D, 0x5A77, 0x5A7E, 0x5A84, - 0x5A9E, 0x5AA7, 0x5AC4, 0xD846 /*0xDCBD*/, 0x5B19, 0x5B25, 0x525D, -}; -static const unsigned short euc_to_utf8_B0[] = { - 0x4E9C, 0x5516, 0x5A03, 0x963F, 0x54C0, 0x611B, 0x6328, - 0x59F6, 0x9022, 0x8475, 0x831C, 0x7A50, 0x60AA, 0x63E1, 0x6E25, - 0x65ED, 0x8466, 0x82A6, 0x9BF5, 0x6893, 0x5727, 0x65A1, 0x6271, - 0x5B9B, 0x59D0, 0x867B, 0x98F4, 0x7D62, 0x7DBE, 0x9B8E, 0x6216, - 0x7C9F, 0x88B7, 0x5B89, 0x5EB5, 0x6309, 0x6697, 0x6848, 0x95C7, - 0x978D, 0x674F, 0x4EE5, 0x4F0A, 0x4F4D, 0x4F9D, 0x5049, 0x56F2, - 0x5937, 0x59D4, 0x5A01, 0x5C09, 0x60DF, 0x610F, 0x6170, 0x6613, - 0x6905, 0x70BA, 0x754F, 0x7570, 0x79FB, 0x7DAD, 0x7DEF, 0x80C3, - 0x840E, 0x8863, 0x8B02, 0x9055, 0x907A, 0x533B, 0x4E95, 0x4EA5, - 0x57DF, 0x80B2, 0x90C1, 0x78EF, 0x4E00, 0x58F1, 0x6EA2, 0x9038, - 0x7A32, 0x8328, 0x828B, 0x9C2F, 0x5141, 0x5370, 0x54BD, 0x54E1, - 0x56E0, 0x59FB, 0x5F15, 0x98F2, 0x6DEB, 0x80E4, 0x852D, -}; -static const unsigned short euc_to_utf8_B1[] = { - 0x9662, 0x9670, 0x96A0, 0x97FB, 0x540B, 0x53F3, 0x5B87, - 0x70CF, 0x7FBD, 0x8FC2, 0x96E8, 0x536F, 0x9D5C, 0x7ABA, 0x4E11, - 0x7893, 0x81FC, 0x6E26, 0x5618, 0x5504, 0x6B1D, 0x851A, 0x9C3B, - 0x59E5, 0x53A9, 0x6D66, 0x74DC, 0x958F, 0x5642, 0x4E91, 0x904B, - 0x96F2, 0x834F, 0x990C, 0x53E1, 0x55B6, 0x5B30, 0x5F71, 0x6620, - 0x66F3, 0x6804, 0x6C38, 0x6CF3, 0x6D29, 0x745B, 0x76C8, 0x7A4E, - 0x9834, 0x82F1, 0x885B, 0x8A60, 0x92ED, 0x6DB2, 0x75AB, 0x76CA, - 0x99C5, 0x60A6, 0x8B01, 0x8D8A, 0x95B2, 0x698E, 0x53AD, 0x5186, - 0x5712, 0x5830, 0x5944, 0x5BB4, 0x5EF6, 0x6028, 0x63A9, 0x63F4, - 0x6CBF, 0x6F14, 0x708E, 0x7114, 0x7159, 0x71D5, 0x733F, 0x7E01, - 0x8276, 0x82D1, 0x8597, 0x9060, 0x925B, 0x9D1B, 0x5869, 0x65BC, - 0x6C5A, 0x7525, 0x51F9, 0x592E, 0x5965, 0x5F80, 0x5FDC, -}; -static const unsigned short euc_to_utf8_B2[] = { - 0x62BC, 0x65FA, 0x6A2A, 0x6B27, 0x6BB4, 0x738B, 0x7FC1, - 0x8956, 0x9D2C, 0x9D0E, 0x9EC4, 0x5CA1, 0x6C96, 0x837B, 0x5104, - 0x5C4B, 0x61B6, 0x81C6, 0x6876, 0x7261, 0x4E59, 0x4FFA, 0x5378, - 0x6069, 0x6E29, 0x7A4F, 0x97F3, 0x4E0B, 0x5316, 0x4EEE, 0x4F55, - 0x4F3D, 0x4FA1, 0x4F73, 0x52A0, 0x53EF, 0x5609, 0x590F, 0x5AC1, - 0x5BB6, 0x5BE1, 0x79D1, 0x6687, 0x679C, 0x67B6, 0x6B4C, 0x6CB3, - 0x706B, 0x73C2, 0x798D, 0x79BE, 0x7A3C, 0x7B87, 0x82B1, 0x82DB, - 0x8304, 0x8377, 0x83EF, 0x83D3, 0x8766, 0x8AB2, 0x5629, 0x8CA8, - 0x8FE6, 0x904E, 0x971E, 0x868A, 0x4FC4, 0x5CE8, 0x6211, 0x7259, - 0x753B, 0x81E5, 0x82BD, 0x86FE, 0x8CC0, 0x96C5, 0x9913, 0x99D5, - 0x4ECB, 0x4F1A, 0x89E3, 0x56DE, 0x584A, 0x58CA, 0x5EFB, 0x5FEB, - 0x602A, 0x6094, 0x6062, 0x61D0, 0x6212, 0x62D0, 0x6539, -}; -static const unsigned short euc_to_utf8_B3[] = { - 0x9B41, 0x6666, 0x68B0, 0x6D77, 0x7070, 0x754C, 0x7686, - 0x7D75, 0x82A5, 0x87F9, 0x958B, 0x968E, 0x8C9D, 0x51F1, 0x52BE, - 0x5916, 0x54B3, 0x5BB3, 0x5D16, 0x6168, 0x6982, 0x6DAF, 0x788D, - 0x84CB, 0x8857, 0x8A72, 0x93A7, 0x9AB8, 0x6D6C, 0x99A8, 0x86D9, - 0x57A3, 0x67FF, 0x86CE, 0x920E, 0x5283, 0x5687, 0x5404, 0x5ED3, - 0x62E1, 0x64B9, 0x683C, 0x6838, 0x6BBB, 0x7372, 0x78BA, 0x7A6B, - 0x899A, 0x89D2, 0x8D6B, 0x8F03, 0x90ED, 0x95A3, 0x9694, 0x9769, - 0x5B66, 0x5CB3, 0x697D, 0x984D, 0x984E, 0x639B, 0x7B20, 0x6A2B, - 0x6A7F, 0x68B6, 0x9C0D, 0x6F5F, 0x5272, 0x559D, 0x6070, 0x62EC, - 0x6D3B, 0x6E07, 0x6ED1, 0x845B, 0x8910, 0x8F44, 0x4E14, 0x9C39, - 0x53F6, 0x691B, 0x6A3A, 0x9784, 0x682A, 0x515C, 0x7AC3, 0x84B2, - 0x91DC, 0x938C, 0x565B, 0x9D28, 0x6822, 0x8305, 0x8431, -}; -static const unsigned short euc_to_utf8_B4[] = { - 0x7CA5, 0x5208, 0x82C5, 0x74E6, 0x4E7E, 0x4F83, 0x51A0, - 0x5BD2, 0x520A, 0x52D8, 0x52E7, 0x5DFB, 0x559A, 0x582A, 0x59E6, - 0x5B8C, 0x5B98, 0x5BDB, 0x5E72, 0x5E79, 0x60A3, 0x611F, 0x6163, - 0x61BE, 0x63DB, 0x6562, 0x67D1, 0x6853, 0x68FA, 0x6B3E, 0x6B53, - 0x6C57, 0x6F22, 0x6F97, 0x6F45, 0x74B0, 0x7518, 0x76E3, 0x770B, - 0x7AFF, 0x7BA1, 0x7C21, 0x7DE9, 0x7F36, 0x7FF0, 0x809D, 0x8266, - 0x839E, 0x89B3, 0x8ACC, 0x8CAB, 0x9084, 0x9451, 0x9593, 0x9591, - 0x95A2, 0x9665, 0x97D3, 0x9928, 0x8218, 0x4E38, 0x542B, 0x5CB8, - 0x5DCC, 0x73A9, 0x764C, 0x773C, 0x5CA9, 0x7FEB, 0x8D0B, 0x96C1, - 0x9811, 0x9854, 0x9858, 0x4F01, 0x4F0E, 0x5371, 0x559C, 0x5668, - 0x57FA, 0x5947, 0x5B09, 0x5BC4, 0x5C90, 0x5E0C, 0x5E7E, 0x5FCC, - 0x63EE, 0x673A, 0x65D7, 0x65E2, 0x671F, 0x68CB, 0x68C4, -}; -static const unsigned short euc_to_utf8_B5[] = { - 0x6A5F, 0x5E30, 0x6BC5, 0x6C17, 0x6C7D, 0x757F, 0x7948, - 0x5B63, 0x7A00, 0x7D00, 0x5FBD, 0x898F, 0x8A18, 0x8CB4, 0x8D77, - 0x8ECC, 0x8F1D, 0x98E2, 0x9A0E, 0x9B3C, 0x4E80, 0x507D, 0x5100, - 0x5993, 0x5B9C, 0x622F, 0x6280, 0x64EC, 0x6B3A, 0x72A0, 0x7591, - 0x7947, 0x7FA9, 0x87FB, 0x8ABC, 0x8B70, 0x63AC, 0x83CA, 0x97A0, - 0x5409, 0x5403, 0x55AB, 0x6854, 0x6A58, 0x8A70, 0x7827, 0x6775, - 0x9ECD, 0x5374, 0x5BA2, 0x811A, 0x8650, 0x9006, 0x4E18, 0x4E45, - 0x4EC7, 0x4F11, 0x53CA, 0x5438, 0x5BAE, 0x5F13, 0x6025, 0x6551, - 0x673D, 0x6C42, 0x6C72, 0x6CE3, 0x7078, 0x7403, 0x7A76, 0x7AAE, - 0x7B08, 0x7D1A, 0x7CFE, 0x7D66, 0x65E7, 0x725B, 0x53BB, 0x5C45, - 0x5DE8, 0x62D2, 0x62E0, 0x6319, 0x6E20, 0x865A, 0x8A31, 0x8DDD, - 0x92F8, 0x6F01, 0x79A6, 0x9B5A, 0x4EA8, 0x4EAB, 0x4EAC, -}; -static const unsigned short euc_to_utf8_B6[] = { - 0x4F9B, 0x4FA0, 0x50D1, 0x5147, 0x7AF6, 0x5171, 0x51F6, - 0x5354, 0x5321, 0x537F, 0x53EB, 0x55AC, 0x5883, 0x5CE1, 0x5F37, - 0x5F4A, 0x602F, 0x6050, 0x606D, 0x631F, 0x6559, 0x6A4B, 0x6CC1, - 0x72C2, 0x72ED, 0x77EF, 0x80F8, 0x8105, 0x8208, 0x854E, 0x90F7, - 0x93E1, 0x97FF, 0x9957, 0x9A5A, 0x4EF0, 0x51DD, 0x5C2D, 0x6681, - 0x696D, 0x5C40, 0x66F2, 0x6975, 0x7389, 0x6850, 0x7C81, 0x50C5, - 0x52E4, 0x5747, 0x5DFE, 0x9326, 0x65A4, 0x6B23, 0x6B3D, 0x7434, - 0x7981, 0x79BD, 0x7B4B, 0x7DCA, 0x82B9, 0x83CC, 0x887F, 0x895F, - 0x8B39, 0x8FD1, 0x91D1, 0x541F, 0x9280, 0x4E5D, 0x5036, 0x53E5, - 0x533A, 0x72D7, 0x7396, 0x77E9, 0x82E6, 0x8EAF, 0x99C6, 0x99C8, - 0x99D2, 0x5177, 0x611A, 0x865E, 0x55B0, 0x7A7A, 0x5076, 0x5BD3, - 0x9047, 0x9685, 0x4E32, 0x6ADB, 0x91E7, 0x5C51, 0x5C48, -}; -static const unsigned short euc_to_utf8_B7[] = { - 0x6398, 0x7A9F, 0x6C93, 0x9774, 0x8F61, 0x7AAA, 0x718A, - 0x9688, 0x7C82, 0x6817, 0x7E70, 0x6851, 0x936C, 0x52F2, 0x541B, - 0x85AB, 0x8A13, 0x7FA4, 0x8ECD, 0x90E1, 0x5366, 0x8888, 0x7941, - 0x4FC2, 0x50BE, 0x5211, 0x5144, 0x5553, 0x572D, 0x73EA, 0x578B, - 0x5951, 0x5F62, 0x5F84, 0x6075, 0x6176, 0x6167, 0x61A9, 0x63B2, - 0x643A, 0x656C, 0x666F, 0x6842, 0x6E13, 0x7566, 0x7A3D, 0x7CFB, - 0x7D4C, 0x7D99, 0x7E4B, 0x7F6B, 0x830E, 0x834A, 0x86CD, 0x8A08, - 0x8A63, 0x8B66, 0x8EFD, 0x981A, 0x9D8F, 0x82B8, 0x8FCE, 0x9BE8, - 0x5287, 0x621F, 0x6483, 0x6FC0, 0x9699, 0x6841, 0x5091, 0x6B20, - 0x6C7A, 0x6F54, 0x7A74, 0x7D50, 0x8840, 0x8A23, 0x6708, 0x4EF6, - 0x5039, 0x5026, 0x5065, 0x517C, 0x5238, 0x5263, 0x55A7, 0x570F, - 0x5805, 0x5ACC, 0x5EFA, 0x61B2, 0x61F8, 0x62F3, 0x6372, -}; -static const unsigned short euc_to_utf8_B8[] = { - 0x691C, 0x6A29, 0x727D, 0x72AC, 0x732E, 0x7814, 0x786F, - 0x7D79, 0x770C, 0x80A9, 0x898B, 0x8B19, 0x8CE2, 0x8ED2, 0x9063, - 0x9375, 0x967A, 0x9855, 0x9A13, 0x9E78, 0x5143, 0x539F, 0x53B3, - 0x5E7B, 0x5F26, 0x6E1B, 0x6E90, 0x7384, 0x73FE, 0x7D43, 0x8237, - 0x8A00, 0x8AFA, 0x9650, 0x4E4E, 0x500B, 0x53E4, 0x547C, 0x56FA, - 0x59D1, 0x5B64, 0x5DF1, 0x5EAB, 0x5F27, 0x6238, 0x6545, 0x67AF, - 0x6E56, 0x72D0, 0x7CCA, 0x88B4, 0x80A1, 0x80E1, 0x83F0, 0x864E, - 0x8A87, 0x8DE8, 0x9237, 0x96C7, 0x9867, 0x9F13, 0x4E94, 0x4E92, - 0x4F0D, 0x5348, 0x5449, 0x543E, 0x5A2F, 0x5F8C, 0x5FA1, 0x609F, - 0x68A7, 0x6A8E, 0x745A, 0x7881, 0x8A9E, 0x8AA4, 0x8B77, 0x9190, - 0x4E5E, 0x9BC9, 0x4EA4, 0x4F7C, 0x4FAF, 0x5019, 0x5016, 0x5149, - 0x516C, 0x529F, 0x52B9, 0x52FE, 0x539A, 0x53E3, 0x5411, -}; -static const unsigned short euc_to_utf8_B9[] = { - 0x540E, 0x5589, 0x5751, 0x57A2, 0x597D, 0x5B54, 0x5B5D, - 0x5B8F, 0x5DE5, 0x5DE7, 0x5DF7, 0x5E78, 0x5E83, 0x5E9A, 0x5EB7, - 0x5F18, 0x6052, 0x614C, 0x6297, 0x62D8, 0x63A7, 0x653B, 0x6602, - 0x6643, 0x66F4, 0x676D, 0x6821, 0x6897, 0x69CB, 0x6C5F, 0x6D2A, - 0x6D69, 0x6E2F, 0x6E9D, 0x7532, 0x7687, 0x786C, 0x7A3F, 0x7CE0, - 0x7D05, 0x7D18, 0x7D5E, 0x7DB1, 0x8015, 0x8003, 0x80AF, 0x80B1, - 0x8154, 0x818F, 0x822A, 0x8352, 0x884C, 0x8861, 0x8B1B, 0x8CA2, - 0x8CFC, 0x90CA, 0x9175, 0x9271, 0x783F, 0x92FC, 0x95A4, 0x964D, - 0x9805, 0x9999, 0x9AD8, 0x9D3B, 0x525B, 0x52AB, 0x53F7, 0x5408, - 0x58D5, 0x62F7, 0x6FE0, 0x8C6A, 0x8F5F, 0x9EB9, 0x514B, 0x523B, - 0x544A, 0x56FD, 0x7A40, 0x9177, 0x9D60, 0x9ED2, 0x7344, 0x6F09, - 0x8170, 0x7511, 0x5FFD, 0x60DA, 0x9AA8, 0x72DB, 0x8FBC, -}; -static const unsigned short euc_to_utf8_BA[] = { - 0x6B64, 0x9803, 0x4ECA, 0x56F0, 0x5764, 0x58BE, 0x5A5A, - 0x6068, 0x61C7, 0x660F, 0x6606, 0x6839, 0x68B1, 0x6DF7, 0x75D5, - 0x7D3A, 0x826E, 0x9B42, 0x4E9B, 0x4F50, 0x53C9, 0x5506, 0x5D6F, - 0x5DE6, 0x5DEE, 0x67FB, 0x6C99, 0x7473, 0x7802, 0x8A50, 0x9396, - 0x88DF, 0x5750, 0x5EA7, 0x632B, 0x50B5, 0x50AC, 0x518D, 0x6700, - 0x54C9, 0x585E, 0x59BB, 0x5BB0, 0x5F69, 0x624D, 0x63A1, 0x683D, - 0x6B73, 0x6E08, 0x707D, 0x91C7, 0x7280, 0x7815, 0x7826, 0x796D, - 0x658E, 0x7D30, 0x83DC, 0x88C1, 0x8F09, 0x969B, 0x5264, 0x5728, - 0x6750, 0x7F6A, 0x8CA1, 0x51B4, 0x5742, 0x962A, 0x583A, 0x698A, - 0x80B4, 0x54B2, 0x5D0E, 0x57FC, 0x7895, 0x9DFA, 0x4F5C, 0x524A, - 0x548B, 0x643E, 0x6628, 0x6714, 0x67F5, 0x7A84, 0x7B56, 0x7D22, - 0x932F, 0x685C, 0x9BAD, 0x7B39, 0x5319, 0x518A, 0x5237, -}; -static const unsigned short euc_to_utf8_BB[] = { - 0x5BDF, 0x62F6, 0x64AE, 0x64E6, 0x672D, 0x6BBA, 0x85A9, - 0x96D1, 0x7690, 0x9BD6, 0x634C, 0x9306, 0x9BAB, 0x76BF, 0x6652, - 0x4E09, 0x5098, 0x53C2, 0x5C71, 0x60E8, 0x6492, 0x6563, 0x685F, - 0x71E6, 0x73CA, 0x7523, 0x7B97, 0x7E82, 0x8695, 0x8B83, 0x8CDB, - 0x9178, 0x9910, 0x65AC, 0x66AB, 0x6B8B, 0x4ED5, 0x4ED4, 0x4F3A, - 0x4F7F, 0x523A, 0x53F8, 0x53F2, 0x55E3, 0x56DB, 0x58EB, 0x59CB, - 0x59C9, 0x59FF, 0x5B50, 0x5C4D, 0x5E02, 0x5E2B, 0x5FD7, 0x601D, - 0x6307, 0x652F, 0x5B5C, 0x65AF, 0x65BD, 0x65E8, 0x679D, 0x6B62, - 0x6B7B, 0x6C0F, 0x7345, 0x7949, 0x79C1, 0x7CF8, 0x7D19, 0x7D2B, - 0x80A2, 0x8102, 0x81F3, 0x8996, 0x8A5E, 0x8A69, 0x8A66, 0x8A8C, - 0x8AEE, 0x8CC7, 0x8CDC, 0x96CC, 0x98FC, 0x6B6F, 0x4E8B, 0x4F3C, - 0x4F8D, 0x5150, 0x5B57, 0x5BFA, 0x6148, 0x6301, 0x6642, -}; -static const unsigned short euc_to_utf8_BC[] = { - 0x6B21, 0x6ECB, 0x6CBB, 0x723E, 0x74BD, 0x75D4, 0x78C1, - 0x793A, 0x800C, 0x8033, 0x81EA, 0x8494, 0x8F9E, 0x6C50, 0x9E7F, - 0x5F0F, 0x8B58, 0x9D2B, 0x7AFA, 0x8EF8, 0x5B8D, 0x96EB, 0x4E03, - 0x53F1, 0x57F7, 0x5931, 0x5AC9, 0x5BA4, 0x6089, 0x6E7F, 0x6F06, - 0x75BE, 0x8CEA, 0x5B9F, 0x8500, 0x7BE0, 0x5072, 0x67F4, 0x829D, - 0x5C61, 0x854A, 0x7E1E, 0x820E, 0x5199, 0x5C04, 0x6368, 0x8D66, - 0x659C, 0x716E, 0x793E, 0x7D17, 0x8005, 0x8B1D, 0x8ECA, 0x906E, - 0x86C7, 0x90AA, 0x501F, 0x52FA, 0x5C3A, 0x6753, 0x707C, 0x7235, - 0x914C, 0x91C8, 0x932B, 0x82E5, 0x5BC2, 0x5F31, 0x60F9, 0x4E3B, - 0x53D6, 0x5B88, 0x624B, 0x6731, 0x6B8A, 0x72E9, 0x73E0, 0x7A2E, - 0x816B, 0x8DA3, 0x9152, 0x9996, 0x5112, 0x53D7, 0x546A, 0x5BFF, - 0x6388, 0x6A39, 0x7DAC, 0x9700, 0x56DA, 0x53CE, 0x5468, -}; -static const unsigned short euc_to_utf8_BD[] = { - 0x5B97, 0x5C31, 0x5DDE, 0x4FEE, 0x6101, 0x62FE, 0x6D32, - 0x79C0, 0x79CB, 0x7D42, 0x7E4D, 0x7FD2, 0x81ED, 0x821F, 0x8490, - 0x8846, 0x8972, 0x8B90, 0x8E74, 0x8F2F, 0x9031, 0x914B, 0x916C, - 0x96C6, 0x919C, 0x4EC0, 0x4F4F, 0x5145, 0x5341, 0x5F93, 0x620E, - 0x67D4, 0x6C41, 0x6E0B, 0x7363, 0x7E26, 0x91CD, 0x9283, 0x53D4, - 0x5919, 0x5BBF, 0x6DD1, 0x795D, 0x7E2E, 0x7C9B, 0x587E, 0x719F, - 0x51FA, 0x8853, 0x8FF0, 0x4FCA, 0x5CFB, 0x6625, 0x77AC, 0x7AE3, - 0x821C, 0x99FF, 0x51C6, 0x5FAA, 0x65EC, 0x696F, 0x6B89, 0x6DF3, - 0x6E96, 0x6F64, 0x76FE, 0x7D14, 0x5DE1, 0x9075, 0x9187, 0x9806, - 0x51E6, 0x521D, 0x6240, 0x6691, 0x66D9, 0x6E1A, 0x5EB6, 0x7DD2, - 0x7F72, 0x66F8, 0x85AF, 0x85F7, 0x8AF8, 0x52A9, 0x53D9, 0x5973, - 0x5E8F, 0x5F90, 0x6055, 0x92E4, 0x9664, 0x50B7, 0x511F, -}; -static const unsigned short euc_to_utf8_BE[] = { - 0x52DD, 0x5320, 0x5347, 0x53EC, 0x54E8, 0x5546, 0x5531, - 0x5617, 0x5968, 0x59BE, 0x5A3C, 0x5BB5, 0x5C06, 0x5C0F, 0x5C11, - 0x5C1A, 0x5E84, 0x5E8A, 0x5EE0, 0x5F70, 0x627F, 0x6284, 0x62DB, - 0x638C, 0x6377, 0x6607, 0x660C, 0x662D, 0x6676, 0x677E, 0x68A2, - 0x6A1F, 0x6A35, 0x6CBC, 0x6D88, 0x6E09, 0x6E58, 0x713C, 0x7126, - 0x7167, 0x75C7, 0x7701, 0x785D, 0x7901, 0x7965, 0x79F0, 0x7AE0, - 0x7B11, 0x7CA7, 0x7D39, 0x8096, 0x83D6, 0x848B, 0x8549, 0x885D, - 0x88F3, 0x8A1F, 0x8A3C, 0x8A54, 0x8A73, 0x8C61, 0x8CDE, 0x91A4, - 0x9266, 0x937E, 0x9418, 0x969C, 0x9798, 0x4E0A, 0x4E08, 0x4E1E, - 0x4E57, 0x5197, 0x5270, 0x57CE, 0x5834, 0x58CC, 0x5B22, 0x5E38, - 0x60C5, 0x64FE, 0x6761, 0x6756, 0x6D44, 0x72B6, 0x7573, 0x7A63, - 0x84B8, 0x8B72, 0x91B8, 0x9320, 0x5631, 0x57F4, 0x98FE, -}; -static const unsigned short euc_to_utf8_BF[] = { - 0x62ED, 0x690D, 0x6B96, 0x71ED, 0x7E54, 0x8077, 0x8272, - 0x89E6, 0x98DF, 0x8755, 0x8FB1, 0x5C3B, 0x4F38, 0x4FE1, 0x4FB5, - 0x5507, 0x5A20, 0x5BDD, 0x5BE9, 0x5FC3, 0x614E, 0x632F, 0x65B0, - 0x664B, 0x68EE, 0x699B, 0x6D78, 0x6DF1, 0x7533, 0x75B9, 0x771F, - 0x795E, 0x79E6, 0x7D33, 0x81E3, 0x82AF, 0x85AA, 0x89AA, 0x8A3A, - 0x8EAB, 0x8F9B, 0x9032, 0x91DD, 0x9707, 0x4EBA, 0x4EC1, 0x5203, - 0x5875, 0x58EC, 0x5C0B, 0x751A, 0x5C3D, 0x814E, 0x8A0A, 0x8FC5, - 0x9663, 0x976D, 0x7B25, 0x8ACF, 0x9808, 0x9162, 0x56F3, 0x53A8, - 0x9017, 0x5439, 0x5782, 0x5E25, 0x63A8, 0x6C34, 0x708A, 0x7761, - 0x7C8B, 0x7FE0, 0x8870, 0x9042, 0x9154, 0x9310, 0x9318, 0x968F, - 0x745E, 0x9AC4, 0x5D07, 0x5D69, 0x6570, 0x67A2, 0x8DA8, 0x96DB, - 0x636E, 0x6749, 0x6919, 0x83C5, 0x9817, 0x96C0, 0x88FE, -}; -static const unsigned short euc_to_utf8_C0[] = { - 0x6F84, 0x647A, 0x5BF8, 0x4E16, 0x702C, 0x755D, 0x662F, - 0x51C4, 0x5236, 0x52E2, 0x59D3, 0x5F81, 0x6027, 0x6210, 0x653F, - 0x6574, 0x661F, 0x6674, 0x68F2, 0x6816, 0x6B63, 0x6E05, 0x7272, - 0x751F, 0x76DB, 0x7CBE, 0x8056, 0x58F0, 0x88FD, 0x897F, 0x8AA0, - 0x8A93, 0x8ACB, 0x901D, 0x9192, 0x9752, 0x9759, 0x6589, 0x7A0E, - 0x8106, 0x96BB, 0x5E2D, 0x60DC, 0x621A, 0x65A5, 0x6614, 0x6790, - 0x77F3, 0x7A4D, 0x7C4D, 0x7E3E, 0x810A, 0x8CAC, 0x8D64, 0x8DE1, - 0x8E5F, 0x78A9, 0x5207, 0x62D9, 0x63A5, 0x6442, 0x6298, 0x8A2D, - 0x7A83, 0x7BC0, 0x8AAC, 0x96EA, 0x7D76, 0x820C, 0x8749, 0x4ED9, - 0x5148, 0x5343, 0x5360, 0x5BA3, 0x5C02, 0x5C16, 0x5DDD, 0x6226, - 0x6247, 0x64B0, 0x6813, 0x6834, 0x6CC9, 0x6D45, 0x6D17, 0x67D3, - 0x6F5C, 0x714E, 0x717D, 0x65CB, 0x7A7F, 0x7BAD, 0x7DDA, -}; -static const unsigned short euc_to_utf8_C1[] = { - 0x7E4A, 0x7FA8, 0x817A, 0x821B, 0x8239, 0x85A6, 0x8A6E, - 0x8CCE, 0x8DF5, 0x9078, 0x9077, 0x92AD, 0x9291, 0x9583, 0x9BAE, - 0x524D, 0x5584, 0x6F38, 0x7136, 0x5168, 0x7985, 0x7E55, 0x81B3, - 0x7CCE, 0x564C, 0x5851, 0x5CA8, 0x63AA, 0x66FE, 0x66FD, 0x695A, - 0x72D9, 0x758F, 0x758E, 0x790E, 0x7956, 0x79DF, 0x7C97, 0x7D20, - 0x7D44, 0x8607, 0x8A34, 0x963B, 0x9061, 0x9F20, 0x50E7, 0x5275, - 0x53CC, 0x53E2, 0x5009, 0x55AA, 0x58EE, 0x594F, 0x723D, 0x5B8B, - 0x5C64, 0x531D, 0x60E3, 0x60F3, 0x635C, 0x6383, 0x633F, 0x63BB, - 0x64CD, 0x65E9, 0x66F9, 0x5DE3, 0x69CD, 0x69FD, 0x6F15, 0x71E5, - 0x4E89, 0x75E9, 0x76F8, 0x7A93, 0x7CDF, 0x7DCF, 0x7D9C, 0x8061, - 0x8349, 0x8358, 0x846C, 0x84BC, 0x85FB, 0x88C5, 0x8D70, 0x9001, - 0x906D, 0x9397, 0x971C, 0x9A12, 0x50CF, 0x5897, 0x618E, -}; -static const unsigned short euc_to_utf8_C2[] = { - 0x81D3, 0x8535, 0x8D08, 0x9020, 0x4FC3, 0x5074, 0x5247, - 0x5373, 0x606F, 0x6349, 0x675F, 0x6E2C, 0x8DB3, 0x901F, 0x4FD7, - 0x5C5E, 0x8CCA, 0x65CF, 0x7D9A, 0x5352, 0x8896, 0x5176, 0x63C3, - 0x5B58, 0x5B6B, 0x5C0A, 0x640D, 0x6751, 0x905C, 0x4ED6, 0x591A, - 0x592A, 0x6C70, 0x8A51, 0x553E, 0x5815, 0x59A5, 0x60F0, 0x6253, - 0x67C1, 0x8235, 0x6955, 0x9640, 0x99C4, 0x9A28, 0x4F53, 0x5806, - 0x5BFE, 0x8010, 0x5CB1, 0x5E2F, 0x5F85, 0x6020, 0x614B, 0x6234, - 0x66FF, 0x6CF0, 0x6EDE, 0x80CE, 0x817F, 0x82D4, 0x888B, 0x8CB8, - 0x9000, 0x902E, 0x968A, 0x9EDB, 0x9BDB, 0x4EE3, 0x53F0, 0x5927, - 0x7B2C, 0x918D, 0x984C, 0x9DF9, 0x6EDD, 0x7027, 0x5353, 0x5544, - 0x5B85, 0x6258, 0x629E, 0x62D3, 0x6CA2, 0x6FEF, 0x7422, 0x8A17, - 0x9438, 0x6FC1, 0x8AFE, 0x8338, 0x51E7, 0x86F8, 0x53EA, -}; -static const unsigned short euc_to_utf8_C3[] = { - 0x53E9, 0x4F46, 0x9054, 0x8FB0, 0x596A, 0x8131, 0x5DFD, - 0x7AEA, 0x8FBF, 0x68DA, 0x8C37, 0x72F8, 0x9C48, 0x6A3D, 0x8AB0, - 0x4E39, 0x5358, 0x5606, 0x5766, 0x62C5, 0x63A2, 0x65E6, 0x6B4E, - 0x6DE1, 0x6E5B, 0x70AD, 0x77ED, 0x7AEF, 0x7BAA, 0x7DBB, 0x803D, - 0x80C6, 0x86CB, 0x8A95, 0x935B, 0x56E3, 0x58C7, 0x5F3E, 0x65AD, - 0x6696, 0x6A80, 0x6BB5, 0x7537, 0x8AC7, 0x5024, 0x77E5, 0x5730, - 0x5F1B, 0x6065, 0x667A, 0x6C60, 0x75F4, 0x7A1A, 0x7F6E, 0x81F4, - 0x8718, 0x9045, 0x99B3, 0x7BC9, 0x755C, 0x7AF9, 0x7B51, 0x84C4, - 0x9010, 0x79E9, 0x7A92, 0x8336, 0x5AE1, 0x7740, 0x4E2D, 0x4EF2, - 0x5B99, 0x5FE0, 0x62BD, 0x663C, 0x67F1, 0x6CE8, 0x866B, 0x8877, - 0x8A3B, 0x914E, 0x92F3, 0x99D0, 0x6A17, 0x7026, 0x732A, 0x82E7, - 0x8457, 0x8CAF, 0x4E01, 0x5146, 0x51CB, 0x558B, 0x5BF5, -}; -static const unsigned short euc_to_utf8_C4[] = { - 0x5E16, 0x5E33, 0x5E81, 0x5F14, 0x5F35, 0x5F6B, 0x5FB4, - 0x61F2, 0x6311, 0x66A2, 0x671D, 0x6F6E, 0x7252, 0x753A, 0x773A, - 0x8074, 0x8139, 0x8178, 0x8776, 0x8ABF, 0x8ADC, 0x8D85, 0x8DF3, - 0x929A, 0x9577, 0x9802, 0x9CE5, 0x52C5, 0x6357, 0x76F4, 0x6715, - 0x6C88, 0x73CD, 0x8CC3, 0x93AE, 0x9673, 0x6D25, 0x589C, 0x690E, - 0x69CC, 0x8FFD, 0x939A, 0x75DB, 0x901A, 0x585A, 0x6802, 0x63B4, - 0x69FB, 0x4F43, 0x6F2C, 0x67D8, 0x8FBB, 0x8526, 0x7DB4, 0x9354, - 0x693F, 0x6F70, 0x576A, 0x58F7, 0x5B2C, 0x7D2C, 0x722A, 0x540A, - 0x91E3, 0x9DB4, 0x4EAD, 0x4F4E, 0x505C, 0x5075, 0x5243, 0x8C9E, - 0x5448, 0x5824, 0x5B9A, 0x5E1D, 0x5E95, 0x5EAD, 0x5EF7, 0x5F1F, - 0x608C, 0x62B5, 0x633A, 0x63D0, 0x68AF, 0x6C40, 0x7887, 0x798E, - 0x7A0B, 0x7DE0, 0x8247, 0x8A02, 0x8AE6, 0x8E44, 0x9013, -}; -static const unsigned short euc_to_utf8_C5[] = { - 0x90B8, 0x912D, 0x91D8, 0x9F0E, 0x6CE5, 0x6458, 0x64E2, - 0x6575, 0x6EF4, 0x7684, 0x7B1B, 0x9069, 0x93D1, 0x6EBA, 0x54F2, - 0x5FB9, 0x64A4, 0x8F4D, 0x8FED, 0x9244, 0x5178, 0x586B, 0x5929, - 0x5C55, 0x5E97, 0x6DFB, 0x7E8F, 0x751C, 0x8CBC, 0x8EE2, 0x985B, - 0x70B9, 0x4F1D, 0x6BBF, 0x6FB1, 0x7530, 0x96FB, 0x514E, 0x5410, - 0x5835, 0x5857, 0x59AC, 0x5C60, 0x5F92, 0x6597, 0x675C, 0x6E21, - 0x767B, 0x83DF, 0x8CED, 0x9014, 0x90FD, 0x934D, 0x7825, 0x783A, - 0x52AA, 0x5EA6, 0x571F, 0x5974, 0x6012, 0x5012, 0x515A, 0x51AC, - 0x51CD, 0x5200, 0x5510, 0x5854, 0x5858, 0x5957, 0x5B95, 0x5CF6, - 0x5D8B, 0x60BC, 0x6295, 0x642D, 0x6771, 0x6843, 0x68BC, 0x68DF, - 0x76D7, 0x6DD8, 0x6E6F, 0x6D9B, 0x706F, 0x71C8, 0x5F53, 0x75D8, - 0x7977, 0x7B49, 0x7B54, 0x7B52, 0x7CD6, 0x7D71, 0x5230, -}; -static const unsigned short euc_to_utf8_C6[] = { - 0x8463, 0x8569, 0x85E4, 0x8A0E, 0x8B04, 0x8C46, 0x8E0F, - 0x9003, 0x900F, 0x9419, 0x9676, 0x982D, 0x9A30, 0x95D8, 0x50CD, - 0x52D5, 0x540C, 0x5802, 0x5C0E, 0x61A7, 0x649E, 0x6D1E, 0x77B3, - 0x7AE5, 0x80F4, 0x8404, 0x9053, 0x9285, 0x5CE0, 0x9D07, 0x533F, - 0x5F97, 0x5FB3, 0x6D9C, 0x7279, 0x7763, 0x79BF, 0x7BE4, 0x6BD2, - 0x72EC, 0x8AAD, 0x6803, 0x6A61, 0x51F8, 0x7A81, 0x6934, 0x5C4A, - 0x9CF6, 0x82EB, 0x5BC5, 0x9149, 0x701E, 0x5678, 0x5C6F, 0x60C7, - 0x6566, 0x6C8C, 0x8C5A, 0x9041, 0x9813, 0x5451, 0x66C7, 0x920D, - 0x5948, 0x90A3, 0x5185, 0x4E4D, 0x51EA, 0x8599, 0x8B0E, 0x7058, - 0x637A, 0x934B, 0x6962, 0x99B4, 0x7E04, 0x7577, 0x5357, 0x6960, - 0x8EDF, 0x96E3, 0x6C5D, 0x4E8C, 0x5C3C, 0x5F10, 0x8FE9, 0x5302, - 0x8CD1, 0x8089, 0x8679, 0x5EFF, 0x65E5, 0x4E73, 0x5165, -}; -static const unsigned short euc_to_utf8_C7[] = { - 0x5982, 0x5C3F, 0x97EE, 0x4EFB, 0x598A, 0x5FCD, 0x8A8D, - 0x6FE1, 0x79B0, 0x7962, 0x5BE7, 0x8471, 0x732B, 0x71B1, 0x5E74, - 0x5FF5, 0x637B, 0x649A, 0x71C3, 0x7C98, 0x4E43, 0x5EFC, 0x4E4B, - 0x57DC, 0x56A2, 0x60A9, 0x6FC3, 0x7D0D, 0x80FD, 0x8133, 0x81BF, - 0x8FB2, 0x8997, 0x86A4, 0x5DF4, 0x628A, 0x64AD, 0x8987, 0x6777, - 0x6CE2, 0x6D3E, 0x7436, 0x7834, 0x5A46, 0x7F75, 0x82AD, 0x99AC, - 0x4FF3, 0x5EC3, 0x62DD, 0x6392, 0x6557, 0x676F, 0x76C3, 0x724C, - 0x80CC, 0x80BA, 0x8F29, 0x914D, 0x500D, 0x57F9, 0x5A92, 0x6885, - 0x6973, 0x7164, 0x72FD, 0x8CB7, 0x58F2, 0x8CE0, 0x966A, 0x9019, - 0x877F, 0x79E4, 0x77E7, 0x8429, 0x4F2F, 0x5265, 0x535A, 0x62CD, - 0x67CF, 0x6CCA, 0x767D, 0x7B94, 0x7C95, 0x8236, 0x8584, 0x8FEB, - 0x66DD, 0x6F20, 0x7206, 0x7E1B, 0x83AB, 0x99C1, 0x9EA6, -}; -static const unsigned short euc_to_utf8_C8[] = { - 0x51FD, 0x7BB1, 0x7872, 0x7BB8, 0x8087, 0x7B48, 0x6AE8, - 0x5E61, 0x808C, 0x7551, 0x7560, 0x516B, 0x9262, 0x6E8C, 0x767A, - 0x9197, 0x9AEA, 0x4F10, 0x7F70, 0x629C, 0x7B4F, 0x95A5, 0x9CE9, - 0x567A, 0x5859, 0x86E4, 0x96BC, 0x4F34, 0x5224, 0x534A, 0x53CD, - 0x53DB, 0x5E06, 0x642C, 0x6591, 0x677F, 0x6C3E, 0x6C4E, 0x7248, - 0x72AF, 0x73ED, 0x7554, 0x7E41, 0x822C, 0x85E9, 0x8CA9, 0x7BC4, - 0x91C6, 0x7169, 0x9812, 0x98EF, 0x633D, 0x6669, 0x756A, 0x76E4, - 0x78D0, 0x8543, 0x86EE, 0x532A, 0x5351, 0x5426, 0x5983, 0x5E87, - 0x5F7C, 0x60B2, 0x6249, 0x6279, 0x62AB, 0x6590, 0x6BD4, 0x6CCC, - 0x75B2, 0x76AE, 0x7891, 0x79D8, 0x7DCB, 0x7F77, 0x80A5, 0x88AB, - 0x8AB9, 0x8CBB, 0x907F, 0x975E, 0x98DB, 0x6A0B, 0x7C38, 0x5099, - 0x5C3E, 0x5FAE, 0x6787, 0x6BD8, 0x7435, 0x7709, 0x7F8E, -}; -static const unsigned short euc_to_utf8_C9[] = { - 0x9F3B, 0x67CA, 0x7A17, 0x5339, 0x758B, 0x9AED, 0x5F66, - 0x819D, 0x83F1, 0x8098, 0x5F3C, 0x5FC5, 0x7562, 0x7B46, 0x903C, - 0x6867, 0x59EB, 0x5A9B, 0x7D10, 0x767E, 0x8B2C, 0x4FF5, 0x5F6A, - 0x6A19, 0x6C37, 0x6F02, 0x74E2, 0x7968, 0x8868, 0x8A55, 0x8C79, - 0x5EDF, 0x63CF, 0x75C5, 0x79D2, 0x82D7, 0x9328, 0x92F2, 0x849C, - 0x86ED, 0x9C2D, 0x54C1, 0x5F6C, 0x658C, 0x6D5C, 0x7015, 0x8CA7, - 0x8CD3, 0x983B, 0x654F, 0x74F6, 0x4E0D, 0x4ED8, 0x57E0, 0x592B, - 0x5A66, 0x5BCC, 0x51A8, 0x5E03, 0x5E9C, 0x6016, 0x6276, 0x6577, - 0x65A7, 0x666E, 0x6D6E, 0x7236, 0x7B26, 0x8150, 0x819A, 0x8299, - 0x8B5C, 0x8CA0, 0x8CE6, 0x8D74, 0x961C, 0x9644, 0x4FAE, 0x64AB, - 0x6B66, 0x821E, 0x8461, 0x856A, 0x90E8, 0x5C01, 0x6953, 0x98A8, - 0x847A, 0x8557, 0x4F0F, 0x526F, 0x5FA9, 0x5E45, 0x670D, -}; -static const unsigned short euc_to_utf8_CA[] = { - 0x798F, 0x8179, 0x8907, 0x8986, 0x6DF5, 0x5F17, 0x6255, - 0x6CB8, 0x4ECF, 0x7269, 0x9B92, 0x5206, 0x543B, 0x5674, 0x58B3, - 0x61A4, 0x626E, 0x711A, 0x596E, 0x7C89, 0x7CDE, 0x7D1B, 0x96F0, - 0x6587, 0x805E, 0x4E19, 0x4F75, 0x5175, 0x5840, 0x5E63, 0x5E73, - 0x5F0A, 0x67C4, 0x4E26, 0x853D, 0x9589, 0x965B, 0x7C73, 0x9801, - 0x50FB, 0x58C1, 0x7656, 0x78A7, 0x5225, 0x77A5, 0x8511, 0x7B86, - 0x504F, 0x5909, 0x7247, 0x7BC7, 0x7DE8, 0x8FBA, 0x8FD4, 0x904D, - 0x4FBF, 0x52C9, 0x5A29, 0x5F01, 0x97AD, 0x4FDD, 0x8217, 0x92EA, - 0x5703, 0x6355, 0x6B69, 0x752B, 0x88DC, 0x8F14, 0x7A42, 0x52DF, - 0x5893, 0x6155, 0x620A, 0x66AE, 0x6BCD, 0x7C3F, 0x83E9, 0x5023, - 0x4FF8, 0x5305, 0x5446, 0x5831, 0x5949, 0x5B9D, 0x5CF0, 0x5CEF, - 0x5D29, 0x5E96, 0x62B1, 0x6367, 0x653E, 0x65B9, 0x670B, -}; -static const unsigned short euc_to_utf8_CB[] = { - 0x6CD5, 0x6CE1, 0x70F9, 0x7832, 0x7E2B, 0x80DE, 0x82B3, - 0x840C, 0x84EC, 0x8702, 0x8912, 0x8A2A, 0x8C4A, 0x90A6, 0x92D2, - 0x98FD, 0x9CF3, 0x9D6C, 0x4E4F, 0x4EA1, 0x508D, 0x5256, 0x574A, - 0x59A8, 0x5E3D, 0x5FD8, 0x5FD9, 0x623F, 0x66B4, 0x671B, 0x67D0, - 0x68D2, 0x5192, 0x7D21, 0x80AA, 0x81A8, 0x8B00, 0x8C8C, 0x8CBF, - 0x927E, 0x9632, 0x5420, 0x982C, 0x5317, 0x50D5, 0x535C, 0x58A8, - 0x64B2, 0x6734, 0x7267, 0x7766, 0x7A46, 0x91E6, 0x52C3, 0x6CA1, - 0x6B86, 0x5800, 0x5E4C, 0x5954, 0x672C, 0x7FFB, 0x51E1, 0x76C6, - 0x6469, 0x78E8, 0x9B54, 0x9EBB, 0x57CB, 0x59B9, 0x6627, 0x679A, - 0x6BCE, 0x54E9, 0x69D9, 0x5E55, 0x819C, 0x6795, 0x9BAA, 0x67FE, - 0x9C52, 0x685D, 0x4EA6, 0x4FE3, 0x53C8, 0x62B9, 0x672B, 0x6CAB, - 0x8FC4, 0x4FAD, 0x7E6D, 0x9EBF, 0x4E07, 0x6162, 0x6E80, -}; -static const unsigned short euc_to_utf8_CC[] = { - 0x6F2B, 0x8513, 0x5473, 0x672A, 0x9B45, 0x5DF3, 0x7B95, - 0x5CAC, 0x5BC6, 0x871C, 0x6E4A, 0x84D1, 0x7A14, 0x8108, 0x5999, - 0x7C8D, 0x6C11, 0x7720, 0x52D9, 0x5922, 0x7121, 0x725F, 0x77DB, - 0x9727, 0x9D61, 0x690B, 0x5A7F, 0x5A18, 0x51A5, 0x540D, 0x547D, - 0x660E, 0x76DF, 0x8FF7, 0x9298, 0x9CF4, 0x59EA, 0x725D, 0x6EC5, - 0x514D, 0x68C9, 0x7DBF, 0x7DEC, 0x9762, 0x9EBA, 0x6478, 0x6A21, - 0x8302, 0x5984, 0x5B5F, 0x6BDB, 0x731B, 0x76F2, 0x7DB2, 0x8017, - 0x8499, 0x5132, 0x6728, 0x9ED9, 0x76EE, 0x6762, 0x52FF, 0x9905, - 0x5C24, 0x623B, 0x7C7E, 0x8CB0, 0x554F, 0x60B6, 0x7D0B, 0x9580, - 0x5301, 0x4E5F, 0x51B6, 0x591C, 0x723A, 0x8036, 0x91CE, 0x5F25, - 0x77E2, 0x5384, 0x5F79, 0x7D04, 0x85AC, 0x8A33, 0x8E8D, 0x9756, - 0x67F3, 0x85AE, 0x9453, 0x6109, 0x6108, 0x6CB9, 0x7652, -}; -static const unsigned short euc_to_utf8_CD[] = { - 0x8AED, 0x8F38, 0x552F, 0x4F51, 0x512A, 0x52C7, 0x53CB, - 0x5BA5, 0x5E7D, 0x60A0, 0x6182, 0x63D6, 0x6709, 0x67DA, 0x6E67, - 0x6D8C, 0x7336, 0x7337, 0x7531, 0x7950, 0x88D5, 0x8A98, 0x904A, - 0x9091, 0x90F5, 0x96C4, 0x878D, 0x5915, 0x4E88, 0x4F59, 0x4E0E, - 0x8A89, 0x8F3F, 0x9810, 0x50AD, 0x5E7C, 0x5996, 0x5BB9, 0x5EB8, - 0x63DA, 0x63FA, 0x64C1, 0x66DC, 0x694A, 0x69D8, 0x6D0B, 0x6EB6, - 0x7194, 0x7528, 0x7AAF, 0x7F8A, 0x8000, 0x8449, 0x84C9, 0x8981, - 0x8B21, 0x8E0A, 0x9065, 0x967D, 0x990A, 0x617E, 0x6291, 0x6B32, - 0x6C83, 0x6D74, 0x7FCC, 0x7FFC, 0x6DC0, 0x7F85, 0x87BA, 0x88F8, - 0x6765, 0x83B1, 0x983C, 0x96F7, 0x6D1B, 0x7D61, 0x843D, 0x916A, - 0x4E71, 0x5375, 0x5D50, 0x6B04, 0x6FEB, 0x85CD, 0x862D, 0x89A7, - 0x5229, 0x540F, 0x5C65, 0x674E, 0x68A8, 0x7406, 0x7483, -}; -static const unsigned short euc_to_utf8_CE[] = { - 0x75E2, 0x88CF, 0x88E1, 0x91CC, 0x96E2, 0x9678, 0x5F8B, - 0x7387, 0x7ACB, 0x844E, 0x63A0, 0x7565, 0x5289, 0x6D41, 0x6E9C, - 0x7409, 0x7559, 0x786B, 0x7C92, 0x9686, 0x7ADC, 0x9F8D, 0x4FB6, - 0x616E, 0x65C5, 0x865C, 0x4E86, 0x4EAE, 0x50DA, 0x4E21, 0x51CC, - 0x5BEE, 0x6599, 0x6881, 0x6DBC, 0x731F, 0x7642, 0x77AD, 0x7A1C, - 0x7CE7, 0x826F, 0x8AD2, 0x907C, 0x91CF, 0x9675, 0x9818, 0x529B, - 0x7DD1, 0x502B, 0x5398, 0x6797, 0x6DCB, 0x71D0, 0x7433, 0x81E8, - 0x8F2A, 0x96A3, 0x9C57, 0x9E9F, 0x7460, 0x5841, 0x6D99, 0x7D2F, - 0x985E, 0x4EE4, 0x4F36, 0x4F8B, 0x51B7, 0x52B1, 0x5DBA, 0x601C, - 0x73B2, 0x793C, 0x82D3, 0x9234, 0x96B7, 0x96F6, 0x970A, 0x9E97, - 0x9F62, 0x66A6, 0x6B74, 0x5217, 0x52A3, 0x70C8, 0x88C2, 0x5EC9, - 0x604B, 0x6190, 0x6F23, 0x7149, 0x7C3E, 0x7DF4, 0x806F, -}; -static const unsigned short euc_to_utf8_CF[] = { - 0x84EE, 0x9023, 0x932C, 0x5442, 0x9B6F, 0x6AD3, 0x7089, - 0x8CC2, 0x8DEF, 0x9732, 0x52B4, 0x5A41, 0x5ECA, 0x5F04, 0x6717, - 0x697C, 0x6994, 0x6D6A, 0x6F0F, 0x7262, 0x72FC, 0x7BED, 0x8001, - 0x807E, 0x874B, 0x90CE, 0x516D, 0x9E93, 0x7984, 0x808B, 0x9332, - 0x8AD6, 0x502D, 0x548C, 0x8A71, 0x6B6A, 0x8CC4, 0x8107, 0x60D1, - 0x67A0, 0x9DF2, 0x4E99, 0x4E98, 0x9C10, 0x8A6B, 0x85C1, 0x8568, - 0x6900, 0x6E7E, 0x7897, 0x8155, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short euc_to_utf8_CF_x0213[] = { - 0x84EE, 0x9023, 0x932C, 0x5442, 0x9B6F, 0x6AD3, 0x7089, - 0x8CC2, 0x8DEF, 0x9732, 0x52B4, 0x5A41, 0x5ECA, 0x5F04, 0x6717, - 0x697C, 0x6994, 0x6D6A, 0x6F0F, 0x7262, 0x72FC, 0x7BED, 0x8001, - 0x807E, 0x874B, 0x90CE, 0x516D, 0x9E93, 0x7984, 0x808B, 0x9332, - 0x8AD6, 0x502D, 0x548C, 0x8A71, 0x6B6A, 0x8CC4, 0x8107, 0x60D1, - 0x67A0, 0x9DF2, 0x4E99, 0x4E98, 0x9C10, 0x8A6B, 0x85C1, 0x8568, - 0x6900, 0x6E7E, 0x7897, 0x8155, 0xD842 /*0xDF9F*/, 0x5B41, 0x5B56, 0x5B7D, - 0x5B93, 0x5BD8, 0x5BEC, 0x5C12, 0x5C1E, 0x5C23, 0x5C2B, 0x378D, - 0x5C62, 0xFA3B, 0xFA3C, 0xD845 /*0xDEB4*/, 0x5C7A, 0x5C8F, 0x5C9F, 0x5CA3, - 0x5CAA, 0x5CBA, 0x5CCB, 0x5CD0, 0x5CD2, 0x5CF4, 0xD847 /*0xDE34*/, 0x37E2, - 0x5D0D, 0x5D27, 0xFA11, 0x5D46, 0x5D47, 0x5D53, 0x5D4A, 0x5D6D, - 0x5D81, 0x5DA0, 0x5DA4, 0x5DA7, 0x5DB8, 0x5DCB, 0x541E, -}; -static const unsigned short euc_to_utf8_D0[] = { - 0x5F0C, 0x4E10, 0x4E15, 0x4E2A, 0x4E31, 0x4E36, 0x4E3C, - 0x4E3F, 0x4E42, 0x4E56, 0x4E58, 0x4E82, 0x4E85, 0x8C6B, 0x4E8A, - 0x8212, 0x5F0D, 0x4E8E, 0x4E9E, 0x4E9F, 0x4EA0, 0x4EA2, 0x4EB0, - 0x4EB3, 0x4EB6, 0x4ECE, 0x4ECD, 0x4EC4, 0x4EC6, 0x4EC2, 0x4ED7, - 0x4EDE, 0x4EED, 0x4EDF, 0x4EF7, 0x4F09, 0x4F5A, 0x4F30, 0x4F5B, - 0x4F5D, 0x4F57, 0x4F47, 0x4F76, 0x4F88, 0x4F8F, 0x4F98, 0x4F7B, - 0x4F69, 0x4F70, 0x4F91, 0x4F6F, 0x4F86, 0x4F96, 0x5118, 0x4FD4, - 0x4FDF, 0x4FCE, 0x4FD8, 0x4FDB, 0x4FD1, 0x4FDA, 0x4FD0, 0x4FE4, - 0x4FE5, 0x501A, 0x5028, 0x5014, 0x502A, 0x5025, 0x5005, 0x4F1C, - 0x4FF6, 0x5021, 0x5029, 0x502C, 0x4FFE, 0x4FEF, 0x5011, 0x5006, - 0x5043, 0x5047, 0x6703, 0x5055, 0x5050, 0x5048, 0x505A, 0x5056, - 0x506C, 0x5078, 0x5080, 0x509A, 0x5085, 0x50B4, 0x50B2, -}; -static const unsigned short euc_to_utf8_D1[] = { - 0x50C9, 0x50CA, 0x50B3, 0x50C2, 0x50D6, 0x50DE, 0x50E5, - 0x50ED, 0x50E3, 0x50EE, 0x50F9, 0x50F5, 0x5109, 0x5101, 0x5102, - 0x5116, 0x5115, 0x5114, 0x511A, 0x5121, 0x513A, 0x5137, 0x513C, - 0x513B, 0x513F, 0x5140, 0x5152, 0x514C, 0x5154, 0x5162, 0x7AF8, - 0x5169, 0x516A, 0x516E, 0x5180, 0x5182, 0x56D8, 0x518C, 0x5189, - 0x518F, 0x5191, 0x5193, 0x5195, 0x5196, 0x51A4, 0x51A6, 0x51A2, - 0x51A9, 0x51AA, 0x51AB, 0x51B3, 0x51B1, 0x51B2, 0x51B0, 0x51B5, - 0x51BD, 0x51C5, 0x51C9, 0x51DB, 0x51E0, 0x8655, 0x51E9, 0x51ED, - 0x51F0, 0x51F5, 0x51FE, 0x5204, 0x520B, 0x5214, 0x520E, 0x5227, - 0x522A, 0x522E, 0x5233, 0x5239, 0x524F, 0x5244, 0x524B, 0x524C, - 0x525E, 0x5254, 0x526A, 0x5274, 0x5269, 0x5273, 0x527F, 0x527D, - 0x528D, 0x5294, 0x5292, 0x5271, 0x5288, 0x5291, 0x8FA8, -}; -static const unsigned short euc_to_utf8_D2[] = { - 0x8FA7, 0x52AC, 0x52AD, 0x52BC, 0x52B5, 0x52C1, 0x52CD, - 0x52D7, 0x52DE, 0x52E3, 0x52E6, 0x98ED, 0x52E0, 0x52F3, 0x52F5, - 0x52F8, 0x52F9, 0x5306, 0x5308, 0x7538, 0x530D, 0x5310, 0x530F, - 0x5315, 0x531A, 0x5323, 0x532F, 0x5331, 0x5333, 0x5338, 0x5340, - 0x5346, 0x5345, 0x4E17, 0x5349, 0x534D, 0x51D6, 0x535E, 0x5369, - 0x536E, 0x5918, 0x537B, 0x5377, 0x5382, 0x5396, 0x53A0, 0x53A6, - 0x53A5, 0x53AE, 0x53B0, 0x53B6, 0x53C3, 0x7C12, 0x96D9, 0x53DF, - 0x66FC, 0x71EE, 0x53EE, 0x53E8, 0x53ED, 0x53FA, 0x5401, 0x543D, - 0x5440, 0x542C, 0x542D, 0x543C, 0x542E, 0x5436, 0x5429, 0x541D, - 0x544E, 0x548F, 0x5475, 0x548E, 0x545F, 0x5471, 0x5477, 0x5470, - 0x5492, 0x547B, 0x5480, 0x5476, 0x5484, 0x5490, 0x5486, 0x54C7, - 0x54A2, 0x54B8, 0x54A5, 0x54AC, 0x54C4, 0x54C8, 0x54A8, -}; -static const unsigned short euc_to_utf8_D3[] = { - 0x54AB, 0x54C2, 0x54A4, 0x54BE, 0x54BC, 0x54D8, 0x54E5, - 0x54E6, 0x550F, 0x5514, 0x54FD, 0x54EE, 0x54ED, 0x54FA, 0x54E2, - 0x5539, 0x5540, 0x5563, 0x554C, 0x552E, 0x555C, 0x5545, 0x5556, - 0x5557, 0x5538, 0x5533, 0x555D, 0x5599, 0x5580, 0x54AF, 0x558A, - 0x559F, 0x557B, 0x557E, 0x5598, 0x559E, 0x55AE, 0x557C, 0x5583, - 0x55A9, 0x5587, 0x55A8, 0x55DA, 0x55C5, 0x55DF, 0x55C4, 0x55DC, - 0x55E4, 0x55D4, 0x5614, 0x55F7, 0x5616, 0x55FE, 0x55FD, 0x561B, - 0x55F9, 0x564E, 0x5650, 0x71DF, 0x5634, 0x5636, 0x5632, 0x5638, - 0x566B, 0x5664, 0x562F, 0x566C, 0x566A, 0x5686, 0x5680, 0x568A, - 0x56A0, 0x5694, 0x568F, 0x56A5, 0x56AE, 0x56B6, 0x56B4, 0x56C2, - 0x56BC, 0x56C1, 0x56C3, 0x56C0, 0x56C8, 0x56CE, 0x56D1, 0x56D3, - 0x56D7, 0x56EE, 0x56F9, 0x5700, 0x56FF, 0x5704, 0x5709, -}; -static const unsigned short euc_to_utf8_D4[] = { - 0x5708, 0x570B, 0x570D, 0x5713, 0x5718, 0x5716, 0x55C7, - 0x571C, 0x5726, 0x5737, 0x5738, 0x574E, 0x573B, 0x5740, 0x574F, - 0x5769, 0x57C0, 0x5788, 0x5761, 0x577F, 0x5789, 0x5793, 0x57A0, - 0x57B3, 0x57A4, 0x57AA, 0x57B0, 0x57C3, 0x57C6, 0x57D4, 0x57D2, - 0x57D3, 0x580A, 0x57D6, 0x57E3, 0x580B, 0x5819, 0x581D, 0x5872, - 0x5821, 0x5862, 0x584B, 0x5870, 0x6BC0, 0x5852, 0x583D, 0x5879, - 0x5885, 0x58B9, 0x589F, 0x58AB, 0x58BA, 0x58DE, 0x58BB, 0x58B8, - 0x58AE, 0x58C5, 0x58D3, 0x58D1, 0x58D7, 0x58D9, 0x58D8, 0x58E5, - 0x58DC, 0x58E4, 0x58DF, 0x58EF, 0x58FA, 0x58F9, 0x58FB, 0x58FC, - 0x58FD, 0x5902, 0x590A, 0x5910, 0x591B, 0x68A6, 0x5925, 0x592C, - 0x592D, 0x5932, 0x5938, 0x593E, 0x7AD2, 0x5955, 0x5950, 0x594E, - 0x595A, 0x5958, 0x5962, 0x5960, 0x5967, 0x596C, 0x5969, -}; -static const unsigned short euc_to_utf8_D5[] = { - 0x5978, 0x5981, 0x599D, 0x4F5E, 0x4FAB, 0x59A3, 0x59B2, - 0x59C6, 0x59E8, 0x59DC, 0x598D, 0x59D9, 0x59DA, 0x5A25, 0x5A1F, - 0x5A11, 0x5A1C, 0x5A09, 0x5A1A, 0x5A40, 0x5A6C, 0x5A49, 0x5A35, - 0x5A36, 0x5A62, 0x5A6A, 0x5A9A, 0x5ABC, 0x5ABE, 0x5ACB, 0x5AC2, - 0x5ABD, 0x5AE3, 0x5AD7, 0x5AE6, 0x5AE9, 0x5AD6, 0x5AFA, 0x5AFB, - 0x5B0C, 0x5B0B, 0x5B16, 0x5B32, 0x5AD0, 0x5B2A, 0x5B36, 0x5B3E, - 0x5B43, 0x5B45, 0x5B40, 0x5B51, 0x5B55, 0x5B5A, 0x5B5B, 0x5B65, - 0x5B69, 0x5B70, 0x5B73, 0x5B75, 0x5B78, 0x6588, 0x5B7A, 0x5B80, - 0x5B83, 0x5BA6, 0x5BB8, 0x5BC3, 0x5BC7, 0x5BC9, 0x5BD4, 0x5BD0, - 0x5BE4, 0x5BE6, 0x5BE2, 0x5BDE, 0x5BE5, 0x5BEB, 0x5BF0, 0x5BF6, - 0x5BF3, 0x5C05, 0x5C07, 0x5C08, 0x5C0D, 0x5C13, 0x5C20, 0x5C22, - 0x5C28, 0x5C38, 0x5C39, 0x5C41, 0x5C46, 0x5C4E, 0x5C53, -}; -static const unsigned short euc_to_utf8_D6[] = { - 0x5C50, 0x5C4F, 0x5B71, 0x5C6C, 0x5C6E, 0x4E62, 0x5C76, - 0x5C79, 0x5C8C, 0x5C91, 0x5C94, 0x599B, 0x5CAB, 0x5CBB, 0x5CB6, - 0x5CBC, 0x5CB7, 0x5CC5, 0x5CBE, 0x5CC7, 0x5CD9, 0x5CE9, 0x5CFD, - 0x5CFA, 0x5CED, 0x5D8C, 0x5CEA, 0x5D0B, 0x5D15, 0x5D17, 0x5D5C, - 0x5D1F, 0x5D1B, 0x5D11, 0x5D14, 0x5D22, 0x5D1A, 0x5D19, 0x5D18, - 0x5D4C, 0x5D52, 0x5D4E, 0x5D4B, 0x5D6C, 0x5D73, 0x5D76, 0x5D87, - 0x5D84, 0x5D82, 0x5DA2, 0x5D9D, 0x5DAC, 0x5DAE, 0x5DBD, 0x5D90, - 0x5DB7, 0x5DBC, 0x5DC9, 0x5DCD, 0x5DD3, 0x5DD2, 0x5DD6, 0x5DDB, - 0x5DEB, 0x5DF2, 0x5DF5, 0x5E0B, 0x5E1A, 0x5E19, 0x5E11, 0x5E1B, - 0x5E36, 0x5E37, 0x5E44, 0x5E43, 0x5E40, 0x5E4E, 0x5E57, 0x5E54, - 0x5E5F, 0x5E62, 0x5E64, 0x5E47, 0x5E75, 0x5E76, 0x5E7A, 0x9EBC, - 0x5E7F, 0x5EA0, 0x5EC1, 0x5EC2, 0x5EC8, 0x5ED0, 0x5ECF, -}; -static const unsigned short euc_to_utf8_D7[] = { - 0x5ED6, 0x5EE3, 0x5EDD, 0x5EDA, 0x5EDB, 0x5EE2, 0x5EE1, - 0x5EE8, 0x5EE9, 0x5EEC, 0x5EF1, 0x5EF3, 0x5EF0, 0x5EF4, 0x5EF8, - 0x5EFE, 0x5F03, 0x5F09, 0x5F5D, 0x5F5C, 0x5F0B, 0x5F11, 0x5F16, - 0x5F29, 0x5F2D, 0x5F38, 0x5F41, 0x5F48, 0x5F4C, 0x5F4E, 0x5F2F, - 0x5F51, 0x5F56, 0x5F57, 0x5F59, 0x5F61, 0x5F6D, 0x5F73, 0x5F77, - 0x5F83, 0x5F82, 0x5F7F, 0x5F8A, 0x5F88, 0x5F91, 0x5F87, 0x5F9E, - 0x5F99, 0x5F98, 0x5FA0, 0x5FA8, 0x5FAD, 0x5FBC, 0x5FD6, 0x5FFB, - 0x5FE4, 0x5FF8, 0x5FF1, 0x5FDD, 0x60B3, 0x5FFF, 0x6021, 0x6060, - 0x6019, 0x6010, 0x6029, 0x600E, 0x6031, 0x601B, 0x6015, 0x602B, - 0x6026, 0x600F, 0x603A, 0x605A, 0x6041, 0x606A, 0x6077, 0x605F, - 0x604A, 0x6046, 0x604D, 0x6063, 0x6043, 0x6064, 0x6042, 0x606C, - 0x606B, 0x6059, 0x6081, 0x608D, 0x60E7, 0x6083, 0x609A, -}; -static const unsigned short euc_to_utf8_D8[] = { - 0x6084, 0x609B, 0x6096, 0x6097, 0x6092, 0x60A7, 0x608B, - 0x60E1, 0x60B8, 0x60E0, 0x60D3, 0x60B4, 0x5FF0, 0x60BD, 0x60C6, - 0x60B5, 0x60D8, 0x614D, 0x6115, 0x6106, 0x60F6, 0x60F7, 0x6100, - 0x60F4, 0x60FA, 0x6103, 0x6121, 0x60FB, 0x60F1, 0x610D, 0x610E, - 0x6147, 0x613E, 0x6128, 0x6127, 0x614A, 0x613F, 0x613C, 0x612C, - 0x6134, 0x613D, 0x6142, 0x6144, 0x6173, 0x6177, 0x6158, 0x6159, - 0x615A, 0x616B, 0x6174, 0x616F, 0x6165, 0x6171, 0x615F, 0x615D, - 0x6153, 0x6175, 0x6199, 0x6196, 0x6187, 0x61AC, 0x6194, 0x619A, - 0x618A, 0x6191, 0x61AB, 0x61AE, 0x61CC, 0x61CA, 0x61C9, 0x61F7, - 0x61C8, 0x61C3, 0x61C6, 0x61BA, 0x61CB, 0x7F79, 0x61CD, 0x61E6, - 0x61E3, 0x61F6, 0x61FA, 0x61F4, 0x61FF, 0x61FD, 0x61FC, 0x61FE, - 0x6200, 0x6208, 0x6209, 0x620D, 0x620C, 0x6214, 0x621B, -}; -static const unsigned short euc_to_utf8_D9[] = { - 0x621E, 0x6221, 0x622A, 0x622E, 0x6230, 0x6232, 0x6233, - 0x6241, 0x624E, 0x625E, 0x6263, 0x625B, 0x6260, 0x6268, 0x627C, - 0x6282, 0x6289, 0x627E, 0x6292, 0x6293, 0x6296, 0x62D4, 0x6283, - 0x6294, 0x62D7, 0x62D1, 0x62BB, 0x62CF, 0x62FF, 0x62C6, 0x64D4, - 0x62C8, 0x62DC, 0x62CC, 0x62CA, 0x62C2, 0x62C7, 0x629B, 0x62C9, - 0x630C, 0x62EE, 0x62F1, 0x6327, 0x6302, 0x6308, 0x62EF, 0x62F5, - 0x6350, 0x633E, 0x634D, 0x641C, 0x634F, 0x6396, 0x638E, 0x6380, - 0x63AB, 0x6376, 0x63A3, 0x638F, 0x6389, 0x639F, 0x63B5, 0x636B, - 0x6369, 0x63BE, 0x63E9, 0x63C0, 0x63C6, 0x63E3, 0x63C9, 0x63D2, - 0x63F6, 0x63C4, 0x6416, 0x6434, 0x6406, 0x6413, 0x6426, 0x6436, - 0x651D, 0x6417, 0x6428, 0x640F, 0x6467, 0x646F, 0x6476, 0x644E, - 0x652A, 0x6495, 0x6493, 0x64A5, 0x64A9, 0x6488, 0x64BC, -}; -static const unsigned short euc_to_utf8_DA[] = { - 0x64DA, 0x64D2, 0x64C5, 0x64C7, 0x64BB, 0x64D8, 0x64C2, - 0x64F1, 0x64E7, 0x8209, 0x64E0, 0x64E1, 0x62AC, 0x64E3, 0x64EF, - 0x652C, 0x64F6, 0x64F4, 0x64F2, 0x64FA, 0x6500, 0x64FD, 0x6518, - 0x651C, 0x6505, 0x6524, 0x6523, 0x652B, 0x6534, 0x6535, 0x6537, - 0x6536, 0x6538, 0x754B, 0x6548, 0x6556, 0x6555, 0x654D, 0x6558, - 0x655E, 0x655D, 0x6572, 0x6578, 0x6582, 0x6583, 0x8B8A, 0x659B, - 0x659F, 0x65AB, 0x65B7, 0x65C3, 0x65C6, 0x65C1, 0x65C4, 0x65CC, - 0x65D2, 0x65DB, 0x65D9, 0x65E0, 0x65E1, 0x65F1, 0x6772, 0x660A, - 0x6603, 0x65FB, 0x6773, 0x6635, 0x6636, 0x6634, 0x661C, 0x664F, - 0x6644, 0x6649, 0x6641, 0x665E, 0x665D, 0x6664, 0x6667, 0x6668, - 0x665F, 0x6662, 0x6670, 0x6683, 0x6688, 0x668E, 0x6689, 0x6684, - 0x6698, 0x669D, 0x66C1, 0x66B9, 0x66C9, 0x66BE, 0x66BC, -}; -static const unsigned short euc_to_utf8_DB[] = { - 0x66C4, 0x66B8, 0x66D6, 0x66DA, 0x66E0, 0x663F, 0x66E6, - 0x66E9, 0x66F0, 0x66F5, 0x66F7, 0x670F, 0x6716, 0x671E, 0x6726, - 0x6727, 0x9738, 0x672E, 0x673F, 0x6736, 0x6741, 0x6738, 0x6737, - 0x6746, 0x675E, 0x6760, 0x6759, 0x6763, 0x6764, 0x6789, 0x6770, - 0x67A9, 0x677C, 0x676A, 0x678C, 0x678B, 0x67A6, 0x67A1, 0x6785, - 0x67B7, 0x67EF, 0x67B4, 0x67EC, 0x67B3, 0x67E9, 0x67B8, 0x67E4, - 0x67DE, 0x67DD, 0x67E2, 0x67EE, 0x67B9, 0x67CE, 0x67C6, 0x67E7, - 0x6A9C, 0x681E, 0x6846, 0x6829, 0x6840, 0x684D, 0x6832, 0x684E, - 0x68B3, 0x682B, 0x6859, 0x6863, 0x6877, 0x687F, 0x689F, 0x688F, - 0x68AD, 0x6894, 0x689D, 0x689B, 0x6883, 0x6AAE, 0x68B9, 0x6874, - 0x68B5, 0x68A0, 0x68BA, 0x690F, 0x688D, 0x687E, 0x6901, 0x68CA, - 0x6908, 0x68D8, 0x6922, 0x6926, 0x68E1, 0x690C, 0x68CD, -}; -static const unsigned short euc_to_utf8_DC[] = { - 0x68D4, 0x68E7, 0x68D5, 0x6936, 0x6912, 0x6904, 0x68D7, - 0x68E3, 0x6925, 0x68F9, 0x68E0, 0x68EF, 0x6928, 0x692A, 0x691A, - 0x6923, 0x6921, 0x68C6, 0x6979, 0x6977, 0x695C, 0x6978, 0x696B, - 0x6954, 0x697E, 0x696E, 0x6939, 0x6974, 0x693D, 0x6959, 0x6930, - 0x6961, 0x695E, 0x695D, 0x6981, 0x696A, 0x69B2, 0x69AE, 0x69D0, - 0x69BF, 0x69C1, 0x69D3, 0x69BE, 0x69CE, 0x5BE8, 0x69CA, 0x69DD, - 0x69BB, 0x69C3, 0x69A7, 0x6A2E, 0x6991, 0x69A0, 0x699C, 0x6995, - 0x69B4, 0x69DE, 0x69E8, 0x6A02, 0x6A1B, 0x69FF, 0x6B0A, 0x69F9, - 0x69F2, 0x69E7, 0x6A05, 0x69B1, 0x6A1E, 0x69ED, 0x6A14, 0x69EB, - 0x6A0A, 0x6A12, 0x6AC1, 0x6A23, 0x6A13, 0x6A44, 0x6A0C, 0x6A72, - 0x6A36, 0x6A78, 0x6A47, 0x6A62, 0x6A59, 0x6A66, 0x6A48, 0x6A38, - 0x6A22, 0x6A90, 0x6A8D, 0x6AA0, 0x6A84, 0x6AA2, 0x6AA3, -}; -static const unsigned short euc_to_utf8_DD[] = { - 0x6A97, 0x8617, 0x6ABB, 0x6AC3, 0x6AC2, 0x6AB8, 0x6AB3, - 0x6AAC, 0x6ADE, 0x6AD1, 0x6ADF, 0x6AAA, 0x6ADA, 0x6AEA, 0x6AFB, - 0x6B05, 0x8616, 0x6AFA, 0x6B12, 0x6B16, 0x9B31, 0x6B1F, 0x6B38, - 0x6B37, 0x76DC, 0x6B39, 0x98EE, 0x6B47, 0x6B43, 0x6B49, 0x6B50, - 0x6B59, 0x6B54, 0x6B5B, 0x6B5F, 0x6B61, 0x6B78, 0x6B79, 0x6B7F, - 0x6B80, 0x6B84, 0x6B83, 0x6B8D, 0x6B98, 0x6B95, 0x6B9E, 0x6BA4, - 0x6BAA, 0x6BAB, 0x6BAF, 0x6BB2, 0x6BB1, 0x6BB3, 0x6BB7, 0x6BBC, - 0x6BC6, 0x6BCB, 0x6BD3, 0x6BDF, 0x6BEC, 0x6BEB, 0x6BF3, 0x6BEF, - 0x9EBE, 0x6C08, 0x6C13, 0x6C14, 0x6C1B, 0x6C24, 0x6C23, 0x6C5E, - 0x6C55, 0x6C62, 0x6C6A, 0x6C82, 0x6C8D, 0x6C9A, 0x6C81, 0x6C9B, - 0x6C7E, 0x6C68, 0x6C73, 0x6C92, 0x6C90, 0x6CC4, 0x6CF1, 0x6CD3, - 0x6CBD, 0x6CD7, 0x6CC5, 0x6CDD, 0x6CAE, 0x6CB1, 0x6CBE, -}; -static const unsigned short euc_to_utf8_DE[] = { - 0x6CBA, 0x6CDB, 0x6CEF, 0x6CD9, 0x6CEA, 0x6D1F, 0x884D, - 0x6D36, 0x6D2B, 0x6D3D, 0x6D38, 0x6D19, 0x6D35, 0x6D33, 0x6D12, - 0x6D0C, 0x6D63, 0x6D93, 0x6D64, 0x6D5A, 0x6D79, 0x6D59, 0x6D8E, - 0x6D95, 0x6FE4, 0x6D85, 0x6DF9, 0x6E15, 0x6E0A, 0x6DB5, 0x6DC7, - 0x6DE6, 0x6DB8, 0x6DC6, 0x6DEC, 0x6DDE, 0x6DCC, 0x6DE8, 0x6DD2, - 0x6DC5, 0x6DFA, 0x6DD9, 0x6DE4, 0x6DD5, 0x6DEA, 0x6DEE, 0x6E2D, - 0x6E6E, 0x6E2E, 0x6E19, 0x6E72, 0x6E5F, 0x6E3E, 0x6E23, 0x6E6B, - 0x6E2B, 0x6E76, 0x6E4D, 0x6E1F, 0x6E43, 0x6E3A, 0x6E4E, 0x6E24, - 0x6EFF, 0x6E1D, 0x6E38, 0x6E82, 0x6EAA, 0x6E98, 0x6EC9, 0x6EB7, - 0x6ED3, 0x6EBD, 0x6EAF, 0x6EC4, 0x6EB2, 0x6ED4, 0x6ED5, 0x6E8F, - 0x6EA5, 0x6EC2, 0x6E9F, 0x6F41, 0x6F11, 0x704C, 0x6EEC, 0x6EF8, - 0x6EFE, 0x6F3F, 0x6EF2, 0x6F31, 0x6EEF, 0x6F32, 0x6ECC, -}; -static const unsigned short euc_to_utf8_DF[] = { - 0x6F3E, 0x6F13, 0x6EF7, 0x6F86, 0x6F7A, 0x6F78, 0x6F81, - 0x6F80, 0x6F6F, 0x6F5B, 0x6FF3, 0x6F6D, 0x6F82, 0x6F7C, 0x6F58, - 0x6F8E, 0x6F91, 0x6FC2, 0x6F66, 0x6FB3, 0x6FA3, 0x6FA1, 0x6FA4, - 0x6FB9, 0x6FC6, 0x6FAA, 0x6FDF, 0x6FD5, 0x6FEC, 0x6FD4, 0x6FD8, - 0x6FF1, 0x6FEE, 0x6FDB, 0x7009, 0x700B, 0x6FFA, 0x7011, 0x7001, - 0x700F, 0x6FFE, 0x701B, 0x701A, 0x6F74, 0x701D, 0x7018, 0x701F, - 0x7030, 0x703E, 0x7032, 0x7051, 0x7063, 0x7099, 0x7092, 0x70AF, - 0x70F1, 0x70AC, 0x70B8, 0x70B3, 0x70AE, 0x70DF, 0x70CB, 0x70DD, - 0x70D9, 0x7109, 0x70FD, 0x711C, 0x7119, 0x7165, 0x7155, 0x7188, - 0x7166, 0x7162, 0x714C, 0x7156, 0x716C, 0x718F, 0x71FB, 0x7184, - 0x7195, 0x71A8, 0x71AC, 0x71D7, 0x71B9, 0x71BE, 0x71D2, 0x71C9, - 0x71D4, 0x71CE, 0x71E0, 0x71EC, 0x71E7, 0x71F5, 0x71FC, -}; -static const unsigned short euc_to_utf8_E0[] = { - 0x71F9, 0x71FF, 0x720D, 0x7210, 0x721B, 0x7228, 0x722D, - 0x722C, 0x7230, 0x7232, 0x723B, 0x723C, 0x723F, 0x7240, 0x7246, - 0x724B, 0x7258, 0x7274, 0x727E, 0x7282, 0x7281, 0x7287, 0x7292, - 0x7296, 0x72A2, 0x72A7, 0x72B9, 0x72B2, 0x72C3, 0x72C6, 0x72C4, - 0x72CE, 0x72D2, 0x72E2, 0x72E0, 0x72E1, 0x72F9, 0x72F7, 0x500F, - 0x7317, 0x730A, 0x731C, 0x7316, 0x731D, 0x7334, 0x732F, 0x7329, - 0x7325, 0x733E, 0x734E, 0x734F, 0x9ED8, 0x7357, 0x736A, 0x7368, - 0x7370, 0x7378, 0x7375, 0x737B, 0x737A, 0x73C8, 0x73B3, 0x73CE, - 0x73BB, 0x73C0, 0x73E5, 0x73EE, 0x73DE, 0x74A2, 0x7405, 0x746F, - 0x7425, 0x73F8, 0x7432, 0x743A, 0x7455, 0x743F, 0x745F, 0x7459, - 0x7441, 0x745C, 0x7469, 0x7470, 0x7463, 0x746A, 0x7476, 0x747E, - 0x748B, 0x749E, 0x74A7, 0x74CA, 0x74CF, 0x74D4, 0x73F1, -}; -static const unsigned short euc_to_utf8_E1[] = { - 0x74E0, 0x74E3, 0x74E7, 0x74E9, 0x74EE, 0x74F2, 0x74F0, - 0x74F1, 0x74F8, 0x74F7, 0x7504, 0x7503, 0x7505, 0x750C, 0x750E, - 0x750D, 0x7515, 0x7513, 0x751E, 0x7526, 0x752C, 0x753C, 0x7544, - 0x754D, 0x754A, 0x7549, 0x755B, 0x7546, 0x755A, 0x7569, 0x7564, - 0x7567, 0x756B, 0x756D, 0x7578, 0x7576, 0x7586, 0x7587, 0x7574, - 0x758A, 0x7589, 0x7582, 0x7594, 0x759A, 0x759D, 0x75A5, 0x75A3, - 0x75C2, 0x75B3, 0x75C3, 0x75B5, 0x75BD, 0x75B8, 0x75BC, 0x75B1, - 0x75CD, 0x75CA, 0x75D2, 0x75D9, 0x75E3, 0x75DE, 0x75FE, 0x75FF, - 0x75FC, 0x7601, 0x75F0, 0x75FA, 0x75F2, 0x75F3, 0x760B, 0x760D, - 0x7609, 0x761F, 0x7627, 0x7620, 0x7621, 0x7622, 0x7624, 0x7634, - 0x7630, 0x763B, 0x7647, 0x7648, 0x7646, 0x765C, 0x7658, 0x7661, - 0x7662, 0x7668, 0x7669, 0x766A, 0x7667, 0x766C, 0x7670, -}; -static const unsigned short euc_to_utf8_E2[] = { - 0x7672, 0x7676, 0x7678, 0x767C, 0x7680, 0x7683, 0x7688, - 0x768B, 0x768E, 0x7696, 0x7693, 0x7699, 0x769A, 0x76B0, 0x76B4, - 0x76B8, 0x76B9, 0x76BA, 0x76C2, 0x76CD, 0x76D6, 0x76D2, 0x76DE, - 0x76E1, 0x76E5, 0x76E7, 0x76EA, 0x862F, 0x76FB, 0x7708, 0x7707, - 0x7704, 0x7729, 0x7724, 0x771E, 0x7725, 0x7726, 0x771B, 0x7737, - 0x7738, 0x7747, 0x775A, 0x7768, 0x776B, 0x775B, 0x7765, 0x777F, - 0x777E, 0x7779, 0x778E, 0x778B, 0x7791, 0x77A0, 0x779E, 0x77B0, - 0x77B6, 0x77B9, 0x77BF, 0x77BC, 0x77BD, 0x77BB, 0x77C7, 0x77CD, - 0x77D7, 0x77DA, 0x77DC, 0x77E3, 0x77EE, 0x77FC, 0x780C, 0x7812, - 0x7926, 0x7820, 0x792A, 0x7845, 0x788E, 0x7874, 0x7886, 0x787C, - 0x789A, 0x788C, 0x78A3, 0x78B5, 0x78AA, 0x78AF, 0x78D1, 0x78C6, - 0x78CB, 0x78D4, 0x78BE, 0x78BC, 0x78C5, 0x78CA, 0x78EC, -}; -static const unsigned short euc_to_utf8_E3[] = { - 0x78E7, 0x78DA, 0x78FD, 0x78F4, 0x7907, 0x7912, 0x7911, - 0x7919, 0x792C, 0x792B, 0x7940, 0x7960, 0x7957, 0x795F, 0x795A, - 0x7955, 0x7953, 0x797A, 0x797F, 0x798A, 0x799D, 0x79A7, 0x9F4B, - 0x79AA, 0x79AE, 0x79B3, 0x79B9, 0x79BA, 0x79C9, 0x79D5, 0x79E7, - 0x79EC, 0x79E1, 0x79E3, 0x7A08, 0x7A0D, 0x7A18, 0x7A19, 0x7A20, - 0x7A1F, 0x7980, 0x7A31, 0x7A3B, 0x7A3E, 0x7A37, 0x7A43, 0x7A57, - 0x7A49, 0x7A61, 0x7A62, 0x7A69, 0x9F9D, 0x7A70, 0x7A79, 0x7A7D, - 0x7A88, 0x7A97, 0x7A95, 0x7A98, 0x7A96, 0x7AA9, 0x7AC8, 0x7AB0, - 0x7AB6, 0x7AC5, 0x7AC4, 0x7ABF, 0x9083, 0x7AC7, 0x7ACA, 0x7ACD, - 0x7ACF, 0x7AD5, 0x7AD3, 0x7AD9, 0x7ADA, 0x7ADD, 0x7AE1, 0x7AE2, - 0x7AE6, 0x7AED, 0x7AF0, 0x7B02, 0x7B0F, 0x7B0A, 0x7B06, 0x7B33, - 0x7B18, 0x7B19, 0x7B1E, 0x7B35, 0x7B28, 0x7B36, 0x7B50, -}; -static const unsigned short euc_to_utf8_E4[] = { - 0x7B7A, 0x7B04, 0x7B4D, 0x7B0B, 0x7B4C, 0x7B45, 0x7B75, - 0x7B65, 0x7B74, 0x7B67, 0x7B70, 0x7B71, 0x7B6C, 0x7B6E, 0x7B9D, - 0x7B98, 0x7B9F, 0x7B8D, 0x7B9C, 0x7B9A, 0x7B8B, 0x7B92, 0x7B8F, - 0x7B5D, 0x7B99, 0x7BCB, 0x7BC1, 0x7BCC, 0x7BCF, 0x7BB4, 0x7BC6, - 0x7BDD, 0x7BE9, 0x7C11, 0x7C14, 0x7BE6, 0x7BE5, 0x7C60, 0x7C00, - 0x7C07, 0x7C13, 0x7BF3, 0x7BF7, 0x7C17, 0x7C0D, 0x7BF6, 0x7C23, - 0x7C27, 0x7C2A, 0x7C1F, 0x7C37, 0x7C2B, 0x7C3D, 0x7C4C, 0x7C43, - 0x7C54, 0x7C4F, 0x7C40, 0x7C50, 0x7C58, 0x7C5F, 0x7C64, 0x7C56, - 0x7C65, 0x7C6C, 0x7C75, 0x7C83, 0x7C90, 0x7CA4, 0x7CAD, 0x7CA2, - 0x7CAB, 0x7CA1, 0x7CA8, 0x7CB3, 0x7CB2, 0x7CB1, 0x7CAE, 0x7CB9, - 0x7CBD, 0x7CC0, 0x7CC5, 0x7CC2, 0x7CD8, 0x7CD2, 0x7CDC, 0x7CE2, - 0x9B3B, 0x7CEF, 0x7CF2, 0x7CF4, 0x7CF6, 0x7CFA, 0x7D06, -}; -static const unsigned short euc_to_utf8_E5[] = { - 0x7D02, 0x7D1C, 0x7D15, 0x7D0A, 0x7D45, 0x7D4B, 0x7D2E, - 0x7D32, 0x7D3F, 0x7D35, 0x7D46, 0x7D73, 0x7D56, 0x7D4E, 0x7D72, - 0x7D68, 0x7D6E, 0x7D4F, 0x7D63, 0x7D93, 0x7D89, 0x7D5B, 0x7D8F, - 0x7D7D, 0x7D9B, 0x7DBA, 0x7DAE, 0x7DA3, 0x7DB5, 0x7DC7, 0x7DBD, - 0x7DAB, 0x7E3D, 0x7DA2, 0x7DAF, 0x7DDC, 0x7DB8, 0x7D9F, 0x7DB0, - 0x7DD8, 0x7DDD, 0x7DE4, 0x7DDE, 0x7DFB, 0x7DF2, 0x7DE1, 0x7E05, - 0x7E0A, 0x7E23, 0x7E21, 0x7E12, 0x7E31, 0x7E1F, 0x7E09, 0x7E0B, - 0x7E22, 0x7E46, 0x7E66, 0x7E3B, 0x7E35, 0x7E39, 0x7E43, 0x7E37, - 0x7E32, 0x7E3A, 0x7E67, 0x7E5D, 0x7E56, 0x7E5E, 0x7E59, 0x7E5A, - 0x7E79, 0x7E6A, 0x7E69, 0x7E7C, 0x7E7B, 0x7E83, 0x7DD5, 0x7E7D, - 0x8FAE, 0x7E7F, 0x7E88, 0x7E89, 0x7E8C, 0x7E92, 0x7E90, 0x7E93, - 0x7E94, 0x7E96, 0x7E8E, 0x7E9B, 0x7E9C, 0x7F38, 0x7F3A, -}; -static const unsigned short euc_to_utf8_E6[] = { - 0x7F45, 0x7F4C, 0x7F4D, 0x7F4E, 0x7F50, 0x7F51, 0x7F55, - 0x7F54, 0x7F58, 0x7F5F, 0x7F60, 0x7F68, 0x7F69, 0x7F67, 0x7F78, - 0x7F82, 0x7F86, 0x7F83, 0x7F88, 0x7F87, 0x7F8C, 0x7F94, 0x7F9E, - 0x7F9D, 0x7F9A, 0x7FA3, 0x7FAF, 0x7FB2, 0x7FB9, 0x7FAE, 0x7FB6, - 0x7FB8, 0x8B71, 0x7FC5, 0x7FC6, 0x7FCA, 0x7FD5, 0x7FD4, 0x7FE1, - 0x7FE6, 0x7FE9, 0x7FF3, 0x7FF9, 0x98DC, 0x8006, 0x8004, 0x800B, - 0x8012, 0x8018, 0x8019, 0x801C, 0x8021, 0x8028, 0x803F, 0x803B, - 0x804A, 0x8046, 0x8052, 0x8058, 0x805A, 0x805F, 0x8062, 0x8068, - 0x8073, 0x8072, 0x8070, 0x8076, 0x8079, 0x807D, 0x807F, 0x8084, - 0x8086, 0x8085, 0x809B, 0x8093, 0x809A, 0x80AD, 0x5190, 0x80AC, - 0x80DB, 0x80E5, 0x80D9, 0x80DD, 0x80C4, 0x80DA, 0x80D6, 0x8109, - 0x80EF, 0x80F1, 0x811B, 0x8129, 0x8123, 0x812F, 0x814B, -}; -static const unsigned short euc_to_utf8_E7[] = { - 0x968B, 0x8146, 0x813E, 0x8153, 0x8151, 0x80FC, 0x8171, - 0x816E, 0x8165, 0x8166, 0x8174, 0x8183, 0x8188, 0x818A, 0x8180, - 0x8182, 0x81A0, 0x8195, 0x81A4, 0x81A3, 0x815F, 0x8193, 0x81A9, - 0x81B0, 0x81B5, 0x81BE, 0x81B8, 0x81BD, 0x81C0, 0x81C2, 0x81BA, - 0x81C9, 0x81CD, 0x81D1, 0x81D9, 0x81D8, 0x81C8, 0x81DA, 0x81DF, - 0x81E0, 0x81E7, 0x81FA, 0x81FB, 0x81FE, 0x8201, 0x8202, 0x8205, - 0x8207, 0x820A, 0x820D, 0x8210, 0x8216, 0x8229, 0x822B, 0x8238, - 0x8233, 0x8240, 0x8259, 0x8258, 0x825D, 0x825A, 0x825F, 0x8264, - 0x8262, 0x8268, 0x826A, 0x826B, 0x822E, 0x8271, 0x8277, 0x8278, - 0x827E, 0x828D, 0x8292, 0x82AB, 0x829F, 0x82BB, 0x82AC, 0x82E1, - 0x82E3, 0x82DF, 0x82D2, 0x82F4, 0x82F3, 0x82FA, 0x8393, 0x8303, - 0x82FB, 0x82F9, 0x82DE, 0x8306, 0x82DC, 0x8309, 0x82D9, -}; -static const unsigned short euc_to_utf8_E8[] = { - 0x8335, 0x8334, 0x8316, 0x8332, 0x8331, 0x8340, 0x8339, - 0x8350, 0x8345, 0x832F, 0x832B, 0x8317, 0x8318, 0x8385, 0x839A, - 0x83AA, 0x839F, 0x83A2, 0x8396, 0x8323, 0x838E, 0x8387, 0x838A, - 0x837C, 0x83B5, 0x8373, 0x8375, 0x83A0, 0x8389, 0x83A8, 0x83F4, - 0x8413, 0x83EB, 0x83CE, 0x83FD, 0x8403, 0x83D8, 0x840B, 0x83C1, - 0x83F7, 0x8407, 0x83E0, 0x83F2, 0x840D, 0x8422, 0x8420, 0x83BD, - 0x8438, 0x8506, 0x83FB, 0x846D, 0x842A, 0x843C, 0x855A, 0x8484, - 0x8477, 0x846B, 0x84AD, 0x846E, 0x8482, 0x8469, 0x8446, 0x842C, - 0x846F, 0x8479, 0x8435, 0x84CA, 0x8462, 0x84B9, 0x84BF, 0x849F, - 0x84D9, 0x84CD, 0x84BB, 0x84DA, 0x84D0, 0x84C1, 0x84C6, 0x84D6, - 0x84A1, 0x8521, 0x84FF, 0x84F4, 0x8517, 0x8518, 0x852C, 0x851F, - 0x8515, 0x8514, 0x84FC, 0x8540, 0x8563, 0x8558, 0x8548, -}; -static const unsigned short euc_to_utf8_E9[] = { - 0x8541, 0x8602, 0x854B, 0x8555, 0x8580, 0x85A4, 0x8588, - 0x8591, 0x858A, 0x85A8, 0x856D, 0x8594, 0x859B, 0x85EA, 0x8587, - 0x859C, 0x8577, 0x857E, 0x8590, 0x85C9, 0x85BA, 0x85CF, 0x85B9, - 0x85D0, 0x85D5, 0x85DD, 0x85E5, 0x85DC, 0x85F9, 0x860A, 0x8613, - 0x860B, 0x85FE, 0x85FA, 0x8606, 0x8622, 0x861A, 0x8630, 0x863F, - 0x864D, 0x4E55, 0x8654, 0x865F, 0x8667, 0x8671, 0x8693, 0x86A3, - 0x86A9, 0x86AA, 0x868B, 0x868C, 0x86B6, 0x86AF, 0x86C4, 0x86C6, - 0x86B0, 0x86C9, 0x8823, 0x86AB, 0x86D4, 0x86DE, 0x86E9, 0x86EC, - 0x86DF, 0x86DB, 0x86EF, 0x8712, 0x8706, 0x8708, 0x8700, 0x8703, - 0x86FB, 0x8711, 0x8709, 0x870D, 0x86F9, 0x870A, 0x8734, 0x873F, - 0x8737, 0x873B, 0x8725, 0x8729, 0x871A, 0x8760, 0x875F, 0x8778, - 0x874C, 0x874E, 0x8774, 0x8757, 0x8768, 0x876E, 0x8759, -}; -static const unsigned short euc_to_utf8_EA[] = { - 0x8753, 0x8763, 0x876A, 0x8805, 0x87A2, 0x879F, 0x8782, - 0x87AF, 0x87CB, 0x87BD, 0x87C0, 0x87D0, 0x96D6, 0x87AB, 0x87C4, - 0x87B3, 0x87C7, 0x87C6, 0x87BB, 0x87EF, 0x87F2, 0x87E0, 0x880F, - 0x880D, 0x87FE, 0x87F6, 0x87F7, 0x880E, 0x87D2, 0x8811, 0x8816, - 0x8815, 0x8822, 0x8821, 0x8831, 0x8836, 0x8839, 0x8827, 0x883B, - 0x8844, 0x8842, 0x8852, 0x8859, 0x885E, 0x8862, 0x886B, 0x8881, - 0x887E, 0x889E, 0x8875, 0x887D, 0x88B5, 0x8872, 0x8882, 0x8897, - 0x8892, 0x88AE, 0x8899, 0x88A2, 0x888D, 0x88A4, 0x88B0, 0x88BF, - 0x88B1, 0x88C3, 0x88C4, 0x88D4, 0x88D8, 0x88D9, 0x88DD, 0x88F9, - 0x8902, 0x88FC, 0x88F4, 0x88E8, 0x88F2, 0x8904, 0x890C, 0x890A, - 0x8913, 0x8943, 0x891E, 0x8925, 0x892A, 0x892B, 0x8941, 0x8944, - 0x893B, 0x8936, 0x8938, 0x894C, 0x891D, 0x8960, 0x895E, -}; -static const unsigned short euc_to_utf8_EB[] = { - 0x8966, 0x8964, 0x896D, 0x896A, 0x896F, 0x8974, 0x8977, - 0x897E, 0x8983, 0x8988, 0x898A, 0x8993, 0x8998, 0x89A1, 0x89A9, - 0x89A6, 0x89AC, 0x89AF, 0x89B2, 0x89BA, 0x89BD, 0x89BF, 0x89C0, - 0x89DA, 0x89DC, 0x89DD, 0x89E7, 0x89F4, 0x89F8, 0x8A03, 0x8A16, - 0x8A10, 0x8A0C, 0x8A1B, 0x8A1D, 0x8A25, 0x8A36, 0x8A41, 0x8A5B, - 0x8A52, 0x8A46, 0x8A48, 0x8A7C, 0x8A6D, 0x8A6C, 0x8A62, 0x8A85, - 0x8A82, 0x8A84, 0x8AA8, 0x8AA1, 0x8A91, 0x8AA5, 0x8AA6, 0x8A9A, - 0x8AA3, 0x8AC4, 0x8ACD, 0x8AC2, 0x8ADA, 0x8AEB, 0x8AF3, 0x8AE7, - 0x8AE4, 0x8AF1, 0x8B14, 0x8AE0, 0x8AE2, 0x8AF7, 0x8ADE, 0x8ADB, - 0x8B0C, 0x8B07, 0x8B1A, 0x8AE1, 0x8B16, 0x8B10, 0x8B17, 0x8B20, - 0x8B33, 0x97AB, 0x8B26, 0x8B2B, 0x8B3E, 0x8B28, 0x8B41, 0x8B4C, - 0x8B4F, 0x8B4E, 0x8B49, 0x8B56, 0x8B5B, 0x8B5A, 0x8B6B, -}; -static const unsigned short euc_to_utf8_EC[] = { - 0x8B5F, 0x8B6C, 0x8B6F, 0x8B74, 0x8B7D, 0x8B80, 0x8B8C, - 0x8B8E, 0x8B92, 0x8B93, 0x8B96, 0x8B99, 0x8B9A, 0x8C3A, 0x8C41, - 0x8C3F, 0x8C48, 0x8C4C, 0x8C4E, 0x8C50, 0x8C55, 0x8C62, 0x8C6C, - 0x8C78, 0x8C7A, 0x8C82, 0x8C89, 0x8C85, 0x8C8A, 0x8C8D, 0x8C8E, - 0x8C94, 0x8C7C, 0x8C98, 0x621D, 0x8CAD, 0x8CAA, 0x8CBD, 0x8CB2, - 0x8CB3, 0x8CAE, 0x8CB6, 0x8CC8, 0x8CC1, 0x8CE4, 0x8CE3, 0x8CDA, - 0x8CFD, 0x8CFA, 0x8CFB, 0x8D04, 0x8D05, 0x8D0A, 0x8D07, 0x8D0F, - 0x8D0D, 0x8D10, 0x9F4E, 0x8D13, 0x8CCD, 0x8D14, 0x8D16, 0x8D67, - 0x8D6D, 0x8D71, 0x8D73, 0x8D81, 0x8D99, 0x8DC2, 0x8DBE, 0x8DBA, - 0x8DCF, 0x8DDA, 0x8DD6, 0x8DCC, 0x8DDB, 0x8DCB, 0x8DEA, 0x8DEB, - 0x8DDF, 0x8DE3, 0x8DFC, 0x8E08, 0x8E09, 0x8DFF, 0x8E1D, 0x8E1E, - 0x8E10, 0x8E1F, 0x8E42, 0x8E35, 0x8E30, 0x8E34, 0x8E4A, -}; -static const unsigned short euc_to_utf8_ED[] = { - 0x8E47, 0x8E49, 0x8E4C, 0x8E50, 0x8E48, 0x8E59, 0x8E64, - 0x8E60, 0x8E2A, 0x8E63, 0x8E55, 0x8E76, 0x8E72, 0x8E7C, 0x8E81, - 0x8E87, 0x8E85, 0x8E84, 0x8E8B, 0x8E8A, 0x8E93, 0x8E91, 0x8E94, - 0x8E99, 0x8EAA, 0x8EA1, 0x8EAC, 0x8EB0, 0x8EC6, 0x8EB1, 0x8EBE, - 0x8EC5, 0x8EC8, 0x8ECB, 0x8EDB, 0x8EE3, 0x8EFC, 0x8EFB, 0x8EEB, - 0x8EFE, 0x8F0A, 0x8F05, 0x8F15, 0x8F12, 0x8F19, 0x8F13, 0x8F1C, - 0x8F1F, 0x8F1B, 0x8F0C, 0x8F26, 0x8F33, 0x8F3B, 0x8F39, 0x8F45, - 0x8F42, 0x8F3E, 0x8F4C, 0x8F49, 0x8F46, 0x8F4E, 0x8F57, 0x8F5C, - 0x8F62, 0x8F63, 0x8F64, 0x8F9C, 0x8F9F, 0x8FA3, 0x8FAD, 0x8FAF, - 0x8FB7, 0x8FDA, 0x8FE5, 0x8FE2, 0x8FEA, 0x8FEF, 0x9087, 0x8FF4, - 0x9005, 0x8FF9, 0x8FFA, 0x9011, 0x9015, 0x9021, 0x900D, 0x901E, - 0x9016, 0x900B, 0x9027, 0x9036, 0x9035, 0x9039, 0x8FF8, -}; -static const unsigned short euc_to_utf8_EE[] = { - 0x904F, 0x9050, 0x9051, 0x9052, 0x900E, 0x9049, 0x903E, - 0x9056, 0x9058, 0x905E, 0x9068, 0x906F, 0x9076, 0x96A8, 0x9072, - 0x9082, 0x907D, 0x9081, 0x9080, 0x908A, 0x9089, 0x908F, 0x90A8, - 0x90AF, 0x90B1, 0x90B5, 0x90E2, 0x90E4, 0x6248, 0x90DB, 0x9102, - 0x9112, 0x9119, 0x9132, 0x9130, 0x914A, 0x9156, 0x9158, 0x9163, - 0x9165, 0x9169, 0x9173, 0x9172, 0x918B, 0x9189, 0x9182, 0x91A2, - 0x91AB, 0x91AF, 0x91AA, 0x91B5, 0x91B4, 0x91BA, 0x91C0, 0x91C1, - 0x91C9, 0x91CB, 0x91D0, 0x91D6, 0x91DF, 0x91E1, 0x91DB, 0x91FC, - 0x91F5, 0x91F6, 0x921E, 0x91FF, 0x9214, 0x922C, 0x9215, 0x9211, - 0x925E, 0x9257, 0x9245, 0x9249, 0x9264, 0x9248, 0x9295, 0x923F, - 0x924B, 0x9250, 0x929C, 0x9296, 0x9293, 0x929B, 0x925A, 0x92CF, - 0x92B9, 0x92B7, 0x92E9, 0x930F, 0x92FA, 0x9344, 0x932E, -}; -static const unsigned short euc_to_utf8_EF[] = { - 0x9319, 0x9322, 0x931A, 0x9323, 0x933A, 0x9335, 0x933B, - 0x935C, 0x9360, 0x937C, 0x936E, 0x9356, 0x93B0, 0x93AC, 0x93AD, - 0x9394, 0x93B9, 0x93D6, 0x93D7, 0x93E8, 0x93E5, 0x93D8, 0x93C3, - 0x93DD, 0x93D0, 0x93C8, 0x93E4, 0x941A, 0x9414, 0x9413, 0x9403, - 0x9407, 0x9410, 0x9436, 0x942B, 0x9435, 0x9421, 0x943A, 0x9441, - 0x9452, 0x9444, 0x945B, 0x9460, 0x9462, 0x945E, 0x946A, 0x9229, - 0x9470, 0x9475, 0x9477, 0x947D, 0x945A, 0x947C, 0x947E, 0x9481, - 0x947F, 0x9582, 0x9587, 0x958A, 0x9594, 0x9596, 0x9598, 0x9599, - 0x95A0, 0x95A8, 0x95A7, 0x95AD, 0x95BC, 0x95BB, 0x95B9, 0x95BE, - 0x95CA, 0x6FF6, 0x95C3, 0x95CD, 0x95CC, 0x95D5, 0x95D4, 0x95D6, - 0x95DC, 0x95E1, 0x95E5, 0x95E2, 0x9621, 0x9628, 0x962E, 0x962F, - 0x9642, 0x964C, 0x964F, 0x964B, 0x9677, 0x965C, 0x965E, -}; -static const unsigned short euc_to_utf8_F0[] = { - 0x965D, 0x965F, 0x9666, 0x9672, 0x966C, 0x968D, 0x9698, - 0x9695, 0x9697, 0x96AA, 0x96A7, 0x96B1, 0x96B2, 0x96B0, 0x96B4, - 0x96B6, 0x96B8, 0x96B9, 0x96CE, 0x96CB, 0x96C9, 0x96CD, 0x894D, - 0x96DC, 0x970D, 0x96D5, 0x96F9, 0x9704, 0x9706, 0x9708, 0x9713, - 0x970E, 0x9711, 0x970F, 0x9716, 0x9719, 0x9724, 0x972A, 0x9730, - 0x9739, 0x973D, 0x973E, 0x9744, 0x9746, 0x9748, 0x9742, 0x9749, - 0x975C, 0x9760, 0x9764, 0x9766, 0x9768, 0x52D2, 0x976B, 0x9771, - 0x9779, 0x9785, 0x977C, 0x9781, 0x977A, 0x9786, 0x978B, 0x978F, - 0x9790, 0x979C, 0x97A8, 0x97A6, 0x97A3, 0x97B3, 0x97B4, 0x97C3, - 0x97C6, 0x97C8, 0x97CB, 0x97DC, 0x97ED, 0x9F4F, 0x97F2, 0x7ADF, - 0x97F6, 0x97F5, 0x980F, 0x980C, 0x9838, 0x9824, 0x9821, 0x9837, - 0x983D, 0x9846, 0x984F, 0x984B, 0x986B, 0x986F, 0x9870, -}; -static const unsigned short euc_to_utf8_F1[] = { - 0x9871, 0x9874, 0x9873, 0x98AA, 0x98AF, 0x98B1, 0x98B6, - 0x98C4, 0x98C3, 0x98C6, 0x98E9, 0x98EB, 0x9903, 0x9909, 0x9912, - 0x9914, 0x9918, 0x9921, 0x991D, 0x991E, 0x9924, 0x9920, 0x992C, - 0x992E, 0x993D, 0x993E, 0x9942, 0x9949, 0x9945, 0x9950, 0x994B, - 0x9951, 0x9952, 0x994C, 0x9955, 0x9997, 0x9998, 0x99A5, 0x99AD, - 0x99AE, 0x99BC, 0x99DF, 0x99DB, 0x99DD, 0x99D8, 0x99D1, 0x99ED, - 0x99EE, 0x99F1, 0x99F2, 0x99FB, 0x99F8, 0x9A01, 0x9A0F, 0x9A05, - 0x99E2, 0x9A19, 0x9A2B, 0x9A37, 0x9A45, 0x9A42, 0x9A40, 0x9A43, - 0x9A3E, 0x9A55, 0x9A4D, 0x9A5B, 0x9A57, 0x9A5F, 0x9A62, 0x9A65, - 0x9A64, 0x9A69, 0x9A6B, 0x9A6A, 0x9AAD, 0x9AB0, 0x9ABC, 0x9AC0, - 0x9ACF, 0x9AD1, 0x9AD3, 0x9AD4, 0x9ADE, 0x9ADF, 0x9AE2, 0x9AE3, - 0x9AE6, 0x9AEF, 0x9AEB, 0x9AEE, 0x9AF4, 0x9AF1, 0x9AF7, -}; -static const unsigned short euc_to_utf8_F2[] = { - 0x9AFB, 0x9B06, 0x9B18, 0x9B1A, 0x9B1F, 0x9B22, 0x9B23, - 0x9B25, 0x9B27, 0x9B28, 0x9B29, 0x9B2A, 0x9B2E, 0x9B2F, 0x9B32, - 0x9B44, 0x9B43, 0x9B4F, 0x9B4D, 0x9B4E, 0x9B51, 0x9B58, 0x9B74, - 0x9B93, 0x9B83, 0x9B91, 0x9B96, 0x9B97, 0x9B9F, 0x9BA0, 0x9BA8, - 0x9BB4, 0x9BC0, 0x9BCA, 0x9BB9, 0x9BC6, 0x9BCF, 0x9BD1, 0x9BD2, - 0x9BE3, 0x9BE2, 0x9BE4, 0x9BD4, 0x9BE1, 0x9C3A, 0x9BF2, 0x9BF1, - 0x9BF0, 0x9C15, 0x9C14, 0x9C09, 0x9C13, 0x9C0C, 0x9C06, 0x9C08, - 0x9C12, 0x9C0A, 0x9C04, 0x9C2E, 0x9C1B, 0x9C25, 0x9C24, 0x9C21, - 0x9C30, 0x9C47, 0x9C32, 0x9C46, 0x9C3E, 0x9C5A, 0x9C60, 0x9C67, - 0x9C76, 0x9C78, 0x9CE7, 0x9CEC, 0x9CF0, 0x9D09, 0x9D08, 0x9CEB, - 0x9D03, 0x9D06, 0x9D2A, 0x9D26, 0x9DAF, 0x9D23, 0x9D1F, 0x9D44, - 0x9D15, 0x9D12, 0x9D41, 0x9D3F, 0x9D3E, 0x9D46, 0x9D48, -}; -static const unsigned short euc_to_utf8_F3[] = { - 0x9D5D, 0x9D5E, 0x9D64, 0x9D51, 0x9D50, 0x9D59, 0x9D72, - 0x9D89, 0x9D87, 0x9DAB, 0x9D6F, 0x9D7A, 0x9D9A, 0x9DA4, 0x9DA9, - 0x9DB2, 0x9DC4, 0x9DC1, 0x9DBB, 0x9DB8, 0x9DBA, 0x9DC6, 0x9DCF, - 0x9DC2, 0x9DD9, 0x9DD3, 0x9DF8, 0x9DE6, 0x9DED, 0x9DEF, 0x9DFD, - 0x9E1A, 0x9E1B, 0x9E1E, 0x9E75, 0x9E79, 0x9E7D, 0x9E81, 0x9E88, - 0x9E8B, 0x9E8C, 0x9E92, 0x9E95, 0x9E91, 0x9E9D, 0x9EA5, 0x9EA9, - 0x9EB8, 0x9EAA, 0x9EAD, 0x9761, 0x9ECC, 0x9ECE, 0x9ECF, 0x9ED0, - 0x9ED4, 0x9EDC, 0x9EDE, 0x9EDD, 0x9EE0, 0x9EE5, 0x9EE8, 0x9EEF, - 0x9EF4, 0x9EF6, 0x9EF7, 0x9EF9, 0x9EFB, 0x9EFC, 0x9EFD, 0x9F07, - 0x9F08, 0x76B7, 0x9F15, 0x9F21, 0x9F2C, 0x9F3E, 0x9F4A, 0x9F52, - 0x9F54, 0x9F63, 0x9F5F, 0x9F60, 0x9F61, 0x9F66, 0x9F67, 0x9F6C, - 0x9F6A, 0x9F77, 0x9F72, 0x9F76, 0x9F95, 0x9F9C, 0x9FA0, -}; -static const unsigned short euc_to_utf8_F4[] = { - 0x582F, 0x69C7, 0x9059, 0x7464, 0x51DC, 0x7199, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short euc_to_utf8_F4_x0213[] = { - 0x582F, 0x69C7, 0x9059, 0x7464, 0x51DC, 0x7199, 0x5653, - 0x5DE2, 0x5E14, 0x5E18, 0x5E58, 0x5E5E, 0x5EBE, 0xF928, 0x5ECB, - 0x5EF9, 0x5F00, 0x5F02, 0x5F07, 0x5F1D, 0x5F23, 0x5F34, 0x5F36, - 0x5F3D, 0x5F40, 0x5F45, 0x5F54, 0x5F58, 0x5F64, 0x5F67, 0x5F7D, - 0x5F89, 0x5F9C, 0x5FA7, 0x5FAF, 0x5FB5, 0x5FB7, 0x5FC9, 0x5FDE, - 0x5FE1, 0x5FE9, 0x600D, 0x6014, 0x6018, 0x6033, 0x6035, 0x6047, - 0xFA3D, 0x609D, 0x609E, 0x60CB, 0x60D4, 0x60D5, 0x60DD, 0x60F8, - 0x611C, 0x612B, 0x6130, 0x6137, 0xFA3E, 0x618D, 0xFA3F, 0x61BC, - 0x61B9, 0xFA40, 0x6222, 0x623E, 0x6243, 0x6256, 0x625A, 0x626F, - 0x6285, 0x62C4, 0x62D6, 0x62FC, 0x630A, 0x6318, 0x6339, 0x6343, - 0x6365, 0x637C, 0x63E5, 0x63ED, 0x63F5, 0x6410, 0x6414, 0x6422, - 0x6479, 0x6451, 0x6460, 0x646D, 0x64CE, 0x64BE, 0x64BF, -}; -static const unsigned short euc_to_utf8_F5[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFE33, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFE31, 0, 0, - 0, 0, 0, 0, 0, 0xFE30, 0, 0, - 0, 0, 0xFE35, 0xFE36, 0xFE39, 0xFE3A, 0, 0, - 0xFE37, 0xFE38, 0xFE3F, 0xFE40, 0xFE3D, 0xFE3E, 0xFE41, 0xFE42, - 0xFE43, 0xFE44, 0xFE3B, 0xFE3C, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short euc_to_utf8_F5_x0213[] = { - 0x64C4, 0x64CA, 0x64D0, 0x64F7, 0x64FB, 0x6522, 0x6529, - 0xFA41, 0x6567, 0x659D, 0xFA42, 0x6600, 0x6609, 0x6615, 0x661E, - 0x663A, 0x6622, 0x6624, 0x662B, 0x6630, 0x6631, 0x6633, 0x66FB, - 0x6648, 0x664C, 0xD84C /*0xDDC4*/, 0x6659, 0x665A, 0x6661, 0x6665, 0x6673, - 0x6677, 0x6678, 0x668D, 0xFA43, 0x66A0, 0x66B2, 0x66BB, 0x66C6, - 0x66C8, 0x3B22, 0x66DB, 0x66E8, 0x66FA, 0x6713, 0xF929, 0x6733, - 0x6766, 0x6747, 0x6748, 0x677B, 0x6781, 0x6793, 0x6798, 0x679B, - 0x67BB, 0x67F9, 0x67C0, 0x67D7, 0x67FC, 0x6801, 0x6852, 0x681D, - 0x682C, 0x6831, 0x685B, 0x6872, 0x6875, 0xFA44, 0x68A3, 0x68A5, - 0x68B2, 0x68C8, 0x68D0, 0x68E8, 0x68ED, 0x68F0, 0x68F1, 0x68FC, - 0x690A, 0x6949, 0xD84D /*0xDDC4*/, 0x6935, 0x6942, 0x6957, 0x6963, 0x6964, - 0x6968, 0x6980, 0xFA14, 0x69A5, 0x69AD, 0x69CF, 0x3BB6, -}; -static const unsigned short euc_to_utf8_F6_x0213[] = { - 0x3BC3, 0x69E2, 0x69E9, 0x69EA, 0x69F5, 0x69F6, 0x6A0F, - 0x6A15, 0xD84D /*0xDF3F*/, 0x6A3B, 0x6A3E, 0x6A45, 0x6A50, 0x6A56, 0x6A5B, - 0x6A6B, 0x6A73, 0xD84D /*0xDF63*/, 0x6A89, 0x6A94, 0x6A9D, 0x6A9E, 0x6AA5, - 0x6AE4, 0x6AE7, 0x3C0F, 0xF91D, 0x6B1B, 0x6B1E, 0x6B2C, 0x6B35, - 0x6B46, 0x6B56, 0x6B60, 0x6B65, 0x6B67, 0x6B77, 0x6B82, 0x6BA9, - 0x6BAD, 0xF970, 0x6BCF, 0x6BD6, 0x6BD7, 0x6BFF, 0x6C05, 0x6C10, - 0x6C33, 0x6C59, 0x6C5C, 0x6CAA, 0x6C74, 0x6C76, 0x6C85, 0x6C86, - 0x6C98, 0x6C9C, 0x6CFB, 0x6CC6, 0x6CD4, 0x6CE0, 0x6CEB, 0x6CEE, - 0xD84F /*0xDCFE*/, 0x6D04, 0x6D0E, 0x6D2E, 0x6D31, 0x6D39, 0x6D3F, 0x6D58, - 0x6D65, 0xFA45, 0x6D82, 0x6D87, 0x6D89, 0x6D94, 0x6DAA, 0x6DAC, - 0x6DBF, 0x6DC4, 0x6DD6, 0x6DDA, 0x6DDB, 0x6DDD, 0x6DFC, 0xFA46, - 0x6E34, 0x6E44, 0x6E5C, 0x6E5E, 0x6EAB, 0x6EB1, 0x6EC1, -}; -static const unsigned short euc_to_utf8_F7_x0213[] = { - 0x6EC7, 0x6ECE, 0x6F10, 0x6F1A, 0xFA47, 0x6F2A, 0x6F2F, - 0x6F33, 0x6F51, 0x6F59, 0x6F5E, 0x6F61, 0x6F62, 0x6F7E, 0x6F88, - 0x6F8C, 0x6F8D, 0x6F94, 0x6FA0, 0x6FA7, 0x6FB6, 0x6FBC, 0x6FC7, - 0x6FCA, 0x6FF9, 0x6FF0, 0x6FF5, 0x7005, 0x7006, 0x7028, 0x704A, - 0x705D, 0x705E, 0x704E, 0x7064, 0x7075, 0x7085, 0x70A4, 0x70AB, - 0x70B7, 0x70D4, 0x70D8, 0x70E4, 0x710F, 0x712B, 0x711E, 0x7120, - 0x712E, 0x7130, 0x7146, 0x7147, 0x7151, 0xFA48, 0x7152, 0x715C, - 0x7160, 0x7168, 0xFA15, 0x7185, 0x7187, 0x7192, 0x71C1, 0x71BA, - 0x71C4, 0x71FE, 0x7200, 0x7215, 0x7255, 0x7256, 0x3E3F, 0x728D, - 0x729B, 0x72BE, 0x72C0, 0x72FB, 0xD851 /*0xDFF1*/, 0x7327, 0x7328, 0xFA16, - 0x7350, 0x7366, 0x737C, 0x7395, 0x739F, 0x73A0, 0x73A2, 0x73A6, - 0x73AB, 0x73C9, 0x73CF, 0x73D6, 0x73D9, 0x73E3, 0x73E9, -}; -static const unsigned short euc_to_utf8_F8_x0213[] = { - 0x7407, 0x740A, 0x741A, 0x741B, 0xFA4A, 0x7426, 0x7428, - 0x742A, 0x742B, 0x742C, 0x742E, 0x742F, 0x7430, 0x7444, 0x7446, - 0x7447, 0x744B, 0x7457, 0x7462, 0x746B, 0x746D, 0x7486, 0x7487, - 0x7489, 0x7498, 0x749C, 0x749F, 0x74A3, 0x7490, 0x74A6, 0x74A8, - 0x74A9, 0x74B5, 0x74BF, 0x74C8, 0x74C9, 0x74DA, 0x74FF, 0x7501, - 0x7517, 0x752F, 0x756F, 0x7579, 0x7592, 0x3F72, 0x75CE, 0x75E4, - 0x7600, 0x7602, 0x7608, 0x7615, 0x7616, 0x7619, 0x761E, 0x762D, - 0x7635, 0x7643, 0x764B, 0x7664, 0x7665, 0x766D, 0x766F, 0x7671, - 0x7681, 0x769B, 0x769D, 0x769E, 0x76A6, 0x76AA, 0x76B6, 0x76C5, - 0x76CC, 0x76CE, 0x76D4, 0x76E6, 0x76F1, 0x76FC, 0x770A, 0x7719, - 0x7734, 0x7736, 0x7746, 0x774D, 0x774E, 0x775C, 0x775F, 0x7762, - 0x777A, 0x7780, 0x7794, 0x77AA, 0x77E0, 0x782D, 0xD855 /*0xDC8E*/, -}; -static const unsigned short euc_to_utf8_F9[] = { - 0x7E8A, 0x891C, 0x9348, 0x9288, 0x84DC, 0x4FC9, 0x70BB, - 0x6631, 0x68C8, 0x92F9, 0x66FB, 0x5F45, 0x4E28, 0x4EE1, 0x4EFC, - 0x4F00, 0x4F03, 0x4F39, 0x4F56, 0x4F92, 0x4F8A, 0x4F9A, 0x4F94, - 0x4FCD, 0x5040, 0x5022, 0x4FFF, 0x501E, 0x5046, 0x5070, 0x5042, - 0x5094, 0x50F4, 0x50D8, 0x514A, 0x5164, 0x519D, 0x51BE, 0x51EC, - 0x5215, 0x529C, 0x52A6, 0x52C0, 0x52DB, 0x5300, 0x5307, 0x5324, - 0x5372, 0x5393, 0x53B2, 0x53DD, 0xFA0E, 0x549C, 0x548A, 0x54A9, - 0x54FF, 0x5586, 0x5759, 0x5765, 0x57AC, 0x57C8, 0x57C7, 0xFA0F, - 0xFA10, 0x589E, 0x58B2, 0x590B, 0x5953, 0x595B, 0x595D, 0x5963, - 0x59A4, 0x59BA, 0x5B56, 0x5BC0, 0x752F, 0x5BD8, 0x5BEC, 0x5C1E, - 0x5CA6, 0x5CBA, 0x5CF5, 0x5D27, 0x5D53, 0xFA11, 0x5D42, 0x5D6D, - 0x5DB8, 0x5DB9, 0x5DD0, 0x5F21, 0x5F34, 0x5F67, 0x5FB7, -}; -static const unsigned short euc_to_utf8_F9_x0213[] = { - 0x7843, 0x784E, 0x784F, 0x7851, 0x7868, 0x786E, 0xFA4B, - 0x78B0, 0xD855 /*0xDD0E*/, 0x78AD, 0x78E4, 0x78F2, 0x7900, 0x78F7, 0x791C, - 0x792E, 0x7931, 0x7934, 0xFA4C, 0xFA4D, 0x7945, 0x7946, 0xFA4E, - 0xFA4F, 0xFA50, 0x795C, 0xFA51, 0xFA19, 0xFA1A, 0x7979, 0xFA52, - 0xFA53, 0xFA1B, 0x7998, 0x79B1, 0x79B8, 0x79C8, 0x79CA, 0xD855 /*0xDF71*/, - 0x79D4, 0x79DE, 0x79EB, 0x79ED, 0x7A03, 0xFA54, 0x7A39, 0x7A5D, - 0x7A6D, 0xFA55, 0x7A85, 0x7AA0, 0xD856 /*0xDDC4*/, 0x7AB3, 0x7ABB, 0x7ACE, - 0x7AEB, 0x7AFD, 0x7B12, 0x7B2D, 0x7B3B, 0x7B47, 0x7B4E, 0x7B60, - 0x7B6D, 0x7B6F, 0x7B72, 0x7B9E, 0xFA56, 0x7BD7, 0x7BD9, 0x7C01, - 0x7C31, 0x7C1E, 0x7C20, 0x7C33, 0x7C36, 0x4264, 0xD857 /*0xDDA1*/, 0x7C59, - 0x7C6D, 0x7C79, 0x7C8F, 0x7C94, 0x7CA0, 0x7CBC, 0x7CD5, 0x7CD9, - 0x7CDD, 0x7D07, 0x7D08, 0x7D13, 0x7D1D, 0x7D23, 0x7D31, -}; -static const unsigned short euc_to_utf8_FA[] = { - 0x5FDE, 0x605D, 0x6085, 0x608A, 0x60DE, 0x60D5, 0x6120, - 0x60F2, 0x6111, 0x6137, 0x6130, 0x6198, 0x6213, 0x62A6, 0x63F5, - 0x6460, 0x649D, 0x64CE, 0x654E, 0x6600, 0x6615, 0x663B, 0x6609, - 0x662E, 0x661E, 0x6624, 0x6665, 0x6657, 0x6659, 0xFA12, 0x6673, - 0x6699, 0x66A0, 0x66B2, 0x66BF, 0x66FA, 0x670E, 0xF929, 0x6766, - 0x67BB, 0x6852, 0x67C0, 0x6801, 0x6844, 0x68CF, 0xFA13, 0x6968, - 0xFA14, 0x6998, 0x69E2, 0x6A30, 0x6A6B, 0x6A46, 0x6A73, 0x6A7E, - 0x6AE2, 0x6AE4, 0x6BD6, 0x6C3F, 0x6C5C, 0x6C86, 0x6C6F, 0x6CDA, - 0x6D04, 0x6D87, 0x6D6F, 0x6D96, 0x6DAC, 0x6DCF, 0x6DF8, 0x6DF2, - 0x6DFC, 0x6E39, 0x6E5C, 0x6E27, 0x6E3C, 0x6EBF, 0x6F88, 0x6FB5, - 0x6FF5, 0x7005, 0x7007, 0x7028, 0x7085, 0x70AB, 0x710F, 0x7104, - 0x715C, 0x7146, 0x7147, 0xFA15, 0x71C1, 0x71FE, 0x72B1, -}; -static const unsigned short euc_to_utf8_FA_x0213[] = { - 0x7D41, 0x7D48, 0x7D53, 0x7D5C, 0x7D7A, 0x7D83, 0x7D8B, - 0x7DA0, 0x7DA6, 0x7DC2, 0x7DCC, 0x7DD6, 0x7DE3, 0xFA57, 0x7E28, - 0x7E08, 0x7E11, 0x7E15, 0xFA59, 0x7E47, 0x7E52, 0x7E61, 0x7E8A, - 0x7E8D, 0x7F47, 0xFA5A, 0x7F91, 0x7F97, 0x7FBF, 0x7FCE, 0x7FDB, - 0x7FDF, 0x7FEC, 0x7FEE, 0x7FFA, 0xFA5B, 0x8014, 0x8026, 0x8035, - 0x8037, 0x803C, 0x80CA, 0x80D7, 0x80E0, 0x80F3, 0x8118, 0x814A, - 0x8160, 0x8167, 0x8168, 0x816D, 0x81BB, 0x81CA, 0x81CF, 0x81D7, - 0xFA5C, 0x4453, 0x445B, 0x8260, 0x8274, 0xD85A /*0xDEFF*/, 0x828E, 0x82A1, - 0x82A3, 0x82A4, 0x82A9, 0x82AE, 0x82B7, 0x82BE, 0x82BF, 0x82C6, - 0x82D5, 0x82FD, 0x82FE, 0x8300, 0x8301, 0x8362, 0x8322, 0x832D, - 0x833A, 0x8343, 0x8347, 0x8351, 0x8355, 0x837D, 0x8386, 0x8392, - 0x8398, 0x83A7, 0x83A9, 0x83BF, 0x83C0, 0x83C7, 0x83CF, -}; -static const unsigned short euc_to_utf8_FB[] = { - 0x72BE, 0x7324, 0xFA16, 0x7377, 0x73BD, 0x73C9, 0x73D6, - 0x73E3, 0x73D2, 0x7407, 0x73F5, 0x7426, 0x742A, 0x7429, 0x742E, - 0x7462, 0x7489, 0x749F, 0x7501, 0x756F, 0x7682, 0x769C, 0x769E, - 0x769B, 0x76A6, 0xFA17, 0x7746, 0x52AF, 0x7821, 0x784E, 0x7864, - 0x787A, 0x7930, 0xFA18, 0xFA19, 0xFA1A, 0x7994, 0xFA1B, 0x799B, - 0x7AD1, 0x7AE7, 0xFA1C, 0x7AEB, 0x7B9E, 0xFA1D, 0x7D48, 0x7D5C, - 0x7DB7, 0x7DA0, 0x7DD6, 0x7E52, 0x7F47, 0x7FA1, 0xFA1E, 0x8301, - 0x8362, 0x837F, 0x83C7, 0x83F6, 0x8448, 0x84B4, 0x8553, 0x8559, - 0x856B, 0xFA1F, 0x85B0, 0xFA20, 0xFA21, 0x8807, 0x88F5, 0x8A12, - 0x8A37, 0x8A79, 0x8AA7, 0x8ABE, 0x8ADF, 0xFA22, 0x8AF6, 0x8B53, - 0x8B7F, 0x8CF0, 0x8CF4, 0x8D12, 0x8D76, 0xFA23, 0x8ECF, 0xFA24, - 0xFA25, 0x9067, 0x90DE, 0xFA26, 0x9115, 0x9127, 0x91DA, -}; -static const unsigned short euc_to_utf8_FB_x0213[] = { - 0x83D1, 0x83E1, 0x83EA, 0x8401, 0x8406, 0x840A, 0xFA5F, - 0x8448, 0x845F, 0x8470, 0x8473, 0x8485, 0x849E, 0x84AF, 0x84B4, - 0x84BA, 0x84C0, 0x84C2, 0xD85B /*0xDE40*/, 0x8532, 0x851E, 0x8523, 0x852F, - 0x8559, 0x8564, 0xFA1F, 0x85AD, 0x857A, 0x858C, 0x858F, 0x85A2, - 0x85B0, 0x85CB, 0x85CE, 0x85ED, 0x8612, 0x85FF, 0x8604, 0x8605, - 0x8610, 0xD85C /*0xDCF4*/, 0x8618, 0x8629, 0x8638, 0x8657, 0x865B, 0xF936, - 0x8662, 0x459D, 0x866C, 0x8675, 0x8698, 0x86B8, 0x86FA, 0x86FC, - 0x86FD, 0x870B, 0x8771, 0x8787, 0x8788, 0x87AC, 0x87AD, 0x87B5, - 0x45EA, 0x87D6, 0x87EC, 0x8806, 0x880A, 0x8810, 0x8814, 0x881F, - 0x8898, 0x88AA, 0x88CA, 0x88CE, 0xD85D /*0xDE84*/, 0x88F5, 0x891C, 0xFA60, - 0x8918, 0x8919, 0x891A, 0x8927, 0x8930, 0x8932, 0x8939, 0x8940, - 0x8994, 0xFA61, 0x89D4, 0x89E5, 0x89F6, 0x8A12, 0x8A15, -}; -static const unsigned short euc_to_utf8_FC[] = { - 0x91D7, 0x91DE, 0x91ED, 0x91EE, 0x91E4, 0x91E5, 0x9206, - 0x9210, 0x920A, 0x923A, 0x9240, 0x923C, 0x924E, 0x9259, 0x9251, - 0x9239, 0x9267, 0x92A7, 0x9277, 0x9278, 0x92E7, 0x92D7, 0x92D9, - 0x92D0, 0xFA27, 0x92D5, 0x92E0, 0x92D3, 0x9325, 0x9321, 0x92FB, - 0xFA28, 0x931E, 0x92FF, 0x931D, 0x9302, 0x9370, 0x9357, 0x93A4, - 0x93C6, 0x93DE, 0x93F8, 0x9431, 0x9445, 0x9448, 0x9592, 0xF9DC, - 0xFA29, 0x969D, 0x96AF, 0x9733, 0x973B, 0x9743, 0x974D, 0x974F, - 0x9751, 0x9755, 0x9857, 0x9865, 0xFA2A, 0xFA2B, 0x9927, 0xFA2C, - 0x999E, 0x9A4E, 0x9AD9, 0x9ADC, 0x9B75, 0x9B72, 0x9B8F, 0x9BB1, - 0x9BBB, 0x9C00, 0x9D70, 0x9D6B, 0xFA2D, 0x9E19, 0x9ED1, 0, - 0, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, - 0x2177, 0x2178, 0x2179, 0xFFE2, 0x00A6, 0xFF07, 0xFF02, -}; - -/* Microsoft UCS Mapping Compatible */ -static const unsigned short euc_to_utf8_FC_ms[] = { - 0x91D7, 0x91DE, 0x91ED, 0x91EE, 0x91E4, 0x91E5, 0x9206, - 0x9210, 0x920A, 0x923A, 0x9240, 0x923C, 0x924E, 0x9259, 0x9251, - 0x9239, 0x9267, 0x92A7, 0x9277, 0x9278, 0x92E7, 0x92D7, 0x92D9, - 0x92D0, 0xFA27, 0x92D5, 0x92E0, 0x92D3, 0x9325, 0x9321, 0x92FB, - 0xFA28, 0x931E, 0x92FF, 0x931D, 0x9302, 0x9370, 0x9357, 0x93A4, - 0x93C6, 0x93DE, 0x93F8, 0x9431, 0x9445, 0x9448, 0x9592, 0xF9DC, - 0xFA29, 0x969D, 0x96AF, 0x9733, 0x973B, 0x9743, 0x974D, 0x974F, - 0x9751, 0x9755, 0x9857, 0x9865, 0xFA2A, 0xFA2B, 0x9927, 0xFA2C, - 0x999E, 0x9A4E, 0x9AD9, 0x9ADC, 0x9B75, 0x9B72, 0x9B8F, 0x9BB1, - 0x9BBB, 0x9C00, 0x9D70, 0x9D6B, 0xFA2D, 0x9E19, 0x9ED1, 0, - 0, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, - 0x2177, 0x2178, 0x2179, 0xFFE2, 0xFFE4, 0xFF07, 0xFF02, -}; -static const unsigned short euc_to_utf8_FC_x0213[] = { - 0x8A22, 0x8A37, 0x8A47, 0x8A4E, 0x8A5D, 0x8A61, 0x8A75, - 0x8A79, 0x8AA7, 0x8AD0, 0x8ADF, 0x8AF4, 0x8AF6, 0xFA22, 0xFA62, - 0xFA63, 0x8B46, 0x8B54, 0x8B59, 0x8B69, 0x8B9D, 0x8C49, 0x8C68, - 0xFA64, 0x8CE1, 0x8CF4, 0x8CF8, 0x8CFE, 0xFA65, 0x8D12, 0x8D1B, - 0x8DAF, 0x8DCE, 0x8DD1, 0x8DD7, 0x8E20, 0x8E23, 0x8E3D, 0x8E70, - 0x8E7B, 0xD860 /*0xDE77*/, 0x8EC0, 0x4844, 0x8EFA, 0x8F1E, 0x8F2D, 0x8F36, - 0x8F54, 0xD860 /*0xDFCD*/, 0x8FA6, 0x8FB5, 0x8FE4, 0x8FE8, 0x8FEE, 0x9008, - 0x902D, 0xFA67, 0x9088, 0x9095, 0x9097, 0x9099, 0x909B, 0x90A2, - 0x90B3, 0x90BE, 0x90C4, 0x90C5, 0x90C7, 0x90D7, 0x90DD, 0x90DE, - 0x90EF, 0x90F4, 0xFA26, 0x9114, 0x9115, 0x9116, 0x9122, 0x9123, - 0x9127, 0x912F, 0x9131, 0x9134, 0x913D, 0x9148, 0x915B, 0x9183, - 0x919E, 0x91AC, 0x91B1, 0x91BC, 0x91D7, 0x91FB, 0x91E4, -}; -static const unsigned short euc_to_utf8_FD_x0213[] = { - 0x91E5, 0x91ED, 0x91F1, 0x9207, 0x9210, 0x9238, 0x9239, - 0x923A, 0x923C, 0x9240, 0x9243, 0x924F, 0x9278, 0x9288, 0x92C2, - 0x92CB, 0x92CC, 0x92D3, 0x92E0, 0x92FF, 0x9304, 0x931F, 0x9321, - 0x9325, 0x9348, 0x9349, 0x934A, 0x9364, 0x9365, 0x936A, 0x9370, - 0x939B, 0x93A3, 0x93BA, 0x93C6, 0x93DE, 0x93DF, 0x9404, 0x93FD, - 0x9433, 0x944A, 0x9463, 0x946B, 0x9471, 0x9472, 0x958E, 0x959F, - 0x95A6, 0x95A9, 0x95AC, 0x95B6, 0x95BD, 0x95CB, 0x95D0, 0x95D3, - 0x49B0, 0x95DA, 0x95DE, 0x9658, 0x9684, 0xF9DC, 0x969D, 0x96A4, - 0x96A5, 0x96D2, 0x96DE, 0xFA68, 0x96E9, 0x96EF, 0x9733, 0x973B, - 0x974D, 0x974E, 0x974F, 0x975A, 0x976E, 0x9773, 0x9795, 0x97AE, - 0x97BA, 0x97C1, 0x97C9, 0x97DE, 0x97DB, 0x97F4, 0xFA69, 0x980A, - 0x981E, 0x982B, 0x9830, 0xFA6A, 0x9852, 0x9853, 0x9856, -}; -static const unsigned short euc_to_utf8_FE_x0213[] = { - 0x9857, 0x9859, 0x985A, 0xF9D0, 0x9865, 0x986C, 0x98BA, - 0x98C8, 0x98E7, 0x9958, 0x999E, 0x9A02, 0x9A03, 0x9A24, 0x9A2D, - 0x9A2E, 0x9A38, 0x9A4A, 0x9A4E, 0x9A52, 0x9AB6, 0x9AC1, 0x9AC3, - 0x9ACE, 0x9AD6, 0x9AF9, 0x9B02, 0x9B08, 0x9B20, 0x4C17, 0x9B2D, - 0x9B5E, 0x9B79, 0x9B66, 0x9B72, 0x9B75, 0x9B84, 0x9B8A, 0x9B8F, - 0x9B9E, 0x9BA7, 0x9BC1, 0x9BCE, 0x9BE5, 0x9BF8, 0x9BFD, 0x9C00, - 0x9C23, 0x9C41, 0x9C4F, 0x9C50, 0x9C53, 0x9C63, 0x9C65, 0x9C77, - 0x9D1D, 0x9D1E, 0x9D43, 0x9D47, 0x9D52, 0x9D63, 0x9D70, 0x9D7C, - 0x9D8A, 0x9D96, 0x9DC0, 0x9DAC, 0x9DBC, 0x9DD7, 0xD868 /*0xDD90*/, 0x9DE7, - 0x9E07, 0x9E15, 0x9E7C, 0x9E9E, 0x9EA4, 0x9EAC, 0x9EAF, 0x9EB4, - 0x9EB5, 0x9EC3, 0x9ED1, 0x9F10, 0x9F39, 0x9F57, 0x9F90, 0x9F94, - 0x9F97, 0x9FA2, 0x59F8, 0x5C5B, 0x5E77, 0x7626, 0x7E6B, -}; - -static const unsigned short euc_to_utf8_8FA1_x0213[] = { - 0xD840 /*0xDC89*/, 0x4E02, 0x4E0F, 0x4E12, 0x4E29, 0x4E2B, 0x4E2E, - 0x4E40, 0x4E47, 0x4E48, 0xD840 /*0xDCA2*/, 0x4E51, 0x3406, 0xD840 /*0xDCA4*/, 0x4E5A, - 0x4E69, 0x4E9D, 0x342C, 0x342E, 0x4EB9, 0x4EBB, 0xD840 /*0xDDA2*/, 0x4EBC, - 0x4EC3, 0x4EC8, 0x4ED0, 0x4EEB, 0x4EDA, 0x4EF1, 0x4EF5, 0x4F00, - 0x4F16, 0x4F64, 0x4F37, 0x4F3E, 0x4F54, 0x4F58, 0xD840 /*0xDE13*/, 0x4F77, - 0x4F78, 0x4F7A, 0x4F7D, 0x4F82, 0x4F85, 0x4F92, 0x4F9A, 0x4FE6, - 0x4FB2, 0x4FBE, 0x4FC5, 0x4FCB, 0x4FCF, 0x4FD2, 0x346A, 0x4FF2, - 0x5000, 0x5010, 0x5013, 0x501C, 0x501E, 0x5022, 0x3468, 0x5042, - 0x5046, 0x504E, 0x5053, 0x5057, 0x5063, 0x5066, 0x506A, 0x5070, - 0x50A3, 0x5088, 0x5092, 0x5093, 0x5095, 0x5096, 0x509C, 0x50AA, - 0xD840 /*0xDF2B*/, 0x50B1, 0x50BA, 0x50BB, 0x50C4, 0x50C7, 0x50F3, 0xD840 /*0xDF81*/, - 0x50CE, 0xD840 /*0xDF71*/, 0x50D4, 0x50D9, 0x50E1, 0x50E9, 0x3492, -}; -static const unsigned short euc_to_utf8_8FA3_x0213[] = { - 0x5108, 0xD840 /*0xDFF9*/, 0x5117, 0x511B, 0xD841 /*0xDC4A*/, 0x5160, 0xD841 /*0xDD09*/, - 0x5173, 0x5183, 0x518B, 0x34BC, 0x5198, 0x51A3, 0x51AD, 0x34C7, - 0x51BC, 0xD841 /*0xDDD6*/, 0xD841 /*0xDE28*/, 0x51F3, 0x51F4, 0x5202, 0x5212, 0x5216, - 0xD841 /*0xDF4F*/, 0x5255, 0x525C, 0x526C, 0x5277, 0x5284, 0x5282, 0xD842 /*0xDC07*/, - 0x5298, 0xD842 /*0xDC3A*/, 0x52A4, 0x52A6, 0x52AF, 0x52BA, 0x52BB, 0x52CA, - 0x351F, 0x52D1, 0xD842 /*0xDCB9*/, 0x52F7, 0x530A, 0x530B, 0x5324, 0x5335, - 0x533E, 0x5342, 0xD842 /*0xDD7C*/, 0xD842 /*0xDD9D*/, 0x5367, 0x536C, 0x537A, 0x53A4, - 0x53B4, 0xD842 /*0xDED3*/, 0x53B7, 0x53C0, 0xD842 /*0xDF1D*/, 0x355D, 0x355E, 0x53D5, - 0x53DA, 0x3563, 0x53F4, 0x53F5, 0x5455, 0x5424, 0x5428, 0x356E, - 0x5443, 0x5462, 0x5466, 0x546C, 0x548A, 0x548D, 0x5495, 0x54A0, - 0x54A6, 0x54AD, 0x54AE, 0x54B7, 0x54BA, 0x54BF, 0x54C3, 0xD843 /*0xDD45*/, - 0x54EC, 0x54EF, 0x54F1, 0x54F3, 0x5500, 0x5501, 0x5509, -}; -static const unsigned short euc_to_utf8_8FA4_x0213[] = { - 0x553C, 0x5541, 0x35A6, 0x5547, 0x554A, 0x35A8, 0x5560, - 0x5561, 0x5564, 0xD843 /*0xDDE1*/, 0x557D, 0x5582, 0x5588, 0x5591, 0x35C5, - 0x55D2, 0xD843 /*0xDE95*/, 0xD843 /*0xDE6D*/, 0x55BF, 0x55C9, 0x55CC, 0x55D1, 0x55DD, - 0x35DA, 0x55E2, 0xD843 /*0xDE64*/, 0x55E9, 0x5628, 0xD843 /*0xDF5F*/, 0x5607, 0x5610, - 0x5630, 0x5637, 0x35F4, 0x563D, 0x563F, 0x5640, 0x5647, 0x565E, - 0x5660, 0x566D, 0x3605, 0x5688, 0x568C, 0x5695, 0x569A, 0x569D, - 0x56A8, 0x56AD, 0x56B2, 0x56C5, 0x56CD, 0x56DF, 0x56E8, 0x56F6, - 0x56F7, 0xD844 /*0xDE01*/, 0x5715, 0x5723, 0xD844 /*0xDE55*/, 0x5729, 0xD844 /*0xDE7B*/, 0x5745, - 0x5746, 0x574C, 0x574D, 0xD844 /*0xDE74*/, 0x5768, 0x576F, 0x5773, 0x5774, - 0x5775, 0x577B, 0xD844 /*0xDEE4*/, 0xD844 /*0xDED7*/, 0x57AC, 0x579A, 0x579D, 0x579E, - 0x57A8, 0x57D7, 0xD844 /*0xDEFD*/, 0x57CC, 0xD844 /*0xDF36*/, 0xD844 /*0xDF44*/, 0x57DE, 0x57E6, - 0x57F0, 0x364A, 0x57F8, 0x57FB, 0x57FD, 0x5804, 0x581E, -}; -static const unsigned short euc_to_utf8_8FA5_x0213[] = { - 0x5820, 0x5827, 0x5832, 0x5839, 0xD844 /*0xDFC4*/, 0x5849, 0x584C, - 0x5867, 0x588A, 0x588B, 0x588D, 0x588F, 0x5890, 0x5894, 0x589D, - 0x58AA, 0x58B1, 0xD845 /*0xDC6D*/, 0x58C3, 0x58CD, 0x58E2, 0x58F3, 0x58F4, - 0x5905, 0x5906, 0x590B, 0x590D, 0x5914, 0x5924, 0xD845 /*0xDDD7*/, 0x3691, - 0x593D, 0x3699, 0x5946, 0x3696, 0xD85B /*0xDC29*/, 0x595B, 0x595F, 0xD845 /*0xDE47*/, - 0x5975, 0x5976, 0x597C, 0x599F, 0x59AE, 0x59BC, 0x59C8, 0x59CD, - 0x59DE, 0x59E3, 0x59E4, 0x59E7, 0x59EE, 0xD845 /*0xDF06*/, 0xD845 /*0xDF42*/, 0x36CF, - 0x5A0C, 0x5A0D, 0x5A17, 0x5A27, 0x5A2D, 0x5A55, 0x5A65, 0x5A7A, - 0x5A8B, 0x5A9C, 0x5A9F, 0x5AA0, 0x5AA2, 0x5AB1, 0x5AB3, 0x5AB5, - 0x5ABA, 0x5ABF, 0x5ADA, 0x5ADC, 0x5AE0, 0x5AE5, 0x5AF0, 0x5AEE, - 0x5AF5, 0x5B00, 0x5B08, 0x5B17, 0x5B34, 0x5B2D, 0x5B4C, 0x5B52, - 0x5B68, 0x5B6F, 0x5B7C, 0x5B7F, 0x5B81, 0x5B84, 0xD846 /*0xDDC3*/, -}; -static const unsigned short euc_to_utf8_8FA8_x0213[] = { - 0x5B96, 0x5BAC, 0x3761, 0x5BC0, 0x3762, 0x5BCE, 0x5BD6, - 0x376C, 0x376B, 0x5BF1, 0x5BFD, 0x3775, 0x5C03, 0x5C29, 0x5C30, - 0xD847 /*0xDC56*/, 0x5C5F, 0x5C63, 0x5C67, 0x5C68, 0x5C69, 0x5C70, 0xD847 /*0xDD2D*/, - 0xD847 /*0xDD45*/, 0x5C7C, 0xD847 /*0xDD78*/, 0xD847 /*0xDD62*/, 0x5C88, 0x5C8A, 0x37C1, 0xD847 /*0xDDA1*/, - 0xD847 /*0xDD9C*/, 0x5CA0, 0x5CA2, 0x5CA6, 0x5CA7, 0xD847 /*0xDD92*/, 0x5CAD, 0x5CB5, - 0xD847 /*0xDDB7*/, 0x5CC9, 0xD847 /*0xDDE0*/, 0xD847 /*0xDE33*/, 0x5D06, 0x5D10, 0x5D2B, 0x5D1D, - 0x5D20, 0x5D24, 0x5D26, 0x5D31, 0x5D39, 0x5D42, 0x37E8, 0x5D61, - 0x5D6A, 0x37F4, 0x5D70, 0xD847 /*0xDF1E*/, 0x37FD, 0x5D88, 0x3800, 0x5D92, - 0x5D94, 0x5D97, 0x5D99, 0x5DB0, 0x5DB2, 0x5DB4, 0xD847 /*0xDF76*/, 0x5DB9, - 0x5DD1, 0x5DD7, 0x5DD8, 0x5DE0, 0xD847 /*0xDFFA*/, 0x5DE4, 0x5DE9, 0x382F, - 0x5E00, 0x3836, 0x5E12, 0x5E15, 0x3840, 0x5E1F, 0x5E2E, 0x5E3E, - 0x5E49, 0x385C, 0x5E56, 0x3861, 0x5E6B, 0x5E6C, 0x5E6D, -}; -static const unsigned short euc_to_utf8_8FAC_x0213[] = { - 0x5E6E, 0xD848 /*0xDD7B*/, 0x5EA5, 0x5EAA, 0x5EAC, 0x5EB9, 0x5EBF, - 0x5EC6, 0x5ED2, 0x5ED9, 0xD848 /*0xDF1E*/, 0x5EFD, 0x5F08, 0x5F0E, 0x5F1C, - 0xD848 /*0xDFAD*/, 0x5F1E, 0x5F47, 0x5F63, 0x5F72, 0x5F7E, 0x5F8F, 0x5FA2, - 0x5FA4, 0x5FB8, 0x5FC4, 0x38FA, 0x5FC7, 0x5FCB, 0x5FD2, 0x5FD3, - 0x5FD4, 0x5FE2, 0x5FEE, 0x5FEF, 0x5FF3, 0x5FFC, 0x3917, 0x6017, - 0x6022, 0x6024, 0x391A, 0x604C, 0x607F, 0x608A, 0x6095, 0x60A8, - 0xD849 /*0xDEF3*/, 0x60B0, 0x60B1, 0x60BE, 0x60C8, 0x60D9, 0x60DB, 0x60EE, - 0x60F2, 0x60F5, 0x6110, 0x6112, 0x6113, 0x6119, 0x611E, 0x613A, - 0x396F, 0x6141, 0x6146, 0x6160, 0x617C, 0xD84A /*0xDC5B*/, 0x6192, 0x6193, - 0x6197, 0x6198, 0x61A5, 0x61A8, 0x61AD, 0xD84A /*0xDCAB*/, 0x61D5, 0x61DD, - 0x61DF, 0x61F5, 0xD84A /*0xDD8F*/, 0x6215, 0x6223, 0x6229, 0x6246, 0x624C, - 0x6251, 0x6252, 0x6261, 0x6264, 0x627B, 0x626D, 0x6273, -}; -static const unsigned short euc_to_utf8_8FAD_x0213[] = { - 0x6299, 0x62A6, 0x62D5, 0xD84A /*0xDEB8*/, 0x62FD, 0x6303, 0x630D, - 0x6310, 0xD84A /*0xDF4F*/, 0xD84A /*0xDF50*/, 0x6332, 0x6335, 0x633B, 0x633C, 0x6341, - 0x6344, 0x634E, 0xD84A /*0xDF46*/, 0x6359, 0xD84B /*0xDC1D*/, 0xD84A /*0xDFA6*/, 0x636C, 0x6384, - 0x6399, 0xD84B /*0xDC24*/, 0x6394, 0x63BD, 0x63F7, 0x63D4, 0x63D5, 0x63DC, - 0x63E0, 0x63EB, 0x63EC, 0x63F2, 0x6409, 0x641E, 0x6425, 0x6429, - 0x642F, 0x645A, 0x645B, 0x645D, 0x6473, 0x647D, 0x6487, 0x6491, - 0x649D, 0x649F, 0x64CB, 0x64CC, 0x64D5, 0x64D7, 0xD84B /*0xDDE1*/, 0x64E4, - 0x64E5, 0x64FF, 0x6504, 0x3A6E, 0x650F, 0x6514, 0x6516, 0x3A73, - 0x651E, 0x6532, 0x6544, 0x6554, 0x656B, 0x657A, 0x6581, 0x6584, - 0x6585, 0x658A, 0x65B2, 0x65B5, 0x65B8, 0x65BF, 0x65C2, 0x65C9, - 0x65D4, 0x3AD6, 0x65F2, 0x65F9, 0x65FC, 0x6604, 0x6608, 0x6621, - 0x662A, 0x6645, 0x6651, 0x664E, 0x3AEA, 0xD84C /*0xDDC3*/, 0x6657, -}; -static const unsigned short euc_to_utf8_8FAE_x0213[] = { - 0x665B, 0x6663, 0xD84C /*0xDDF5*/, 0xD84C /*0xDDB6*/, 0x666A, 0x666B, 0x666C, - 0x666D, 0x667B, 0x6680, 0x6690, 0x6692, 0x6699, 0x3B0E, 0x66AD, - 0x66B1, 0x66B5, 0x3B1A, 0x66BF, 0x3B1C, 0x66EC, 0x3AD7, 0x6701, - 0x6705, 0x6712, 0xD84C /*0xDF72*/, 0x6719, 0xD84C /*0xDFD3*/, 0xD84C /*0xDFD2*/, 0x674C, 0x674D, - 0x6754, 0x675D, 0xD84C /*0xDFD0*/, 0xD84C /*0xDFE4*/, 0xD84C /*0xDFD5*/, 0x6774, 0x6776, 0xD84C /*0xDFDA*/, - 0x6792, 0xD84C /*0xDFDF*/, 0x8363, 0x6810, 0x67B0, 0x67B2, 0x67C3, 0x67C8, - 0x67D2, 0x67D9, 0x67DB, 0x67F0, 0x67F7, 0xD84D /*0xDC4A*/, 0xD84D /*0xDC51*/, 0xD84D /*0xDC4B*/, - 0x6818, 0x681F, 0x682D, 0xD84D /*0xDC65*/, 0x6833, 0x683B, 0x683E, 0x6844, - 0x6845, 0x6849, 0x684C, 0x6855, 0x6857, 0x3B77, 0x686B, 0x686E, - 0x687A, 0x687C, 0x6882, 0x6890, 0x6896, 0x3B6D, 0x6898, 0x6899, - 0x689A, 0x689C, 0x68AA, 0x68AB, 0x68B4, 0x68BB, 0x68FB, 0xD84D /*0xDCE4*/, - 0xD84D /*0xDD5A*/, 0xFA13, 0x68C3, 0x68C5, 0x68CC, 0x68CF, 0x68D6, -}; -static const unsigned short euc_to_utf8_8FAF_x0213[] = { - 0x68D9, 0x68E4, 0x68E5, 0x68EC, 0x68F7, 0x6903, 0x6907, - 0x3B87, 0x3B88, 0xD84D /*0xDD94*/, 0x693B, 0x3B8D, 0x6946, 0x6969, 0x696C, - 0x6972, 0x697A, 0x697F, 0x6992, 0x3BA4, 0x6996, 0x6998, 0x69A6, - 0x69B0, 0x69B7, 0x69BA, 0x69BC, 0x69C0, 0x69D1, 0x69D6, 0xD84D /*0xDE39*/, - 0xD84D /*0xDE47*/, 0x6A30, 0xD84D /*0xDE38*/, 0xD84D /*0xDE3A*/, 0x69E3, 0x69EE, 0x69EF, 0x69F3, - 0x3BCD, 0x69F4, 0x69FE, 0x6A11, 0x6A1A, 0x6A1D, 0xD84D /*0xDF1C*/, 0x6A32, - 0x6A33, 0x6A34, 0x6A3F, 0x6A46, 0x6A49, 0x6A7A, 0x6A4E, 0x6A52, - 0x6A64, 0xD84D /*0xDF0C*/, 0x6A7E, 0x6A83, 0x6A8B, 0x3BF0, 0x6A91, 0x6A9F, - 0x6AA1, 0xD84D /*0xDF64*/, 0x6AAB, 0x6ABD, 0x6AC6, 0x6AD4, 0x6AD0, 0x6ADC, - 0x6ADD, 0xD84D /*0xDFFF*/, 0xD84D /*0xDFE7*/, 0x6AEC, 0x6AF1, 0x6AF2, 0x6AF3, 0x6AFD, - 0xD84E /*0xDC24*/, 0x6B0B, 0x6B0F, 0x6B10, 0x6B11, 0xD84E /*0xDC3D*/, 0x6B17, 0x3C26, - 0x6B2F, 0x6B4A, 0x6B58, 0x6B6C, 0x6B75, 0x6B7A, 0x6B81, -}; -static const unsigned short euc_to_utf8_8FEE_x0213[] = { - 0x6B9B, 0x6BAE, 0xD84E /*0xDE98*/, 0x6BBD, 0x6BBE, 0x6BC7, 0x6BC8, - 0x6BC9, 0x6BDA, 0x6BE6, 0x6BE7, 0x6BEE, 0x6BF1, 0x6C02, 0x6C0A, - 0x6C0E, 0x6C35, 0x6C36, 0x6C3A, 0xD84F /*0xDC7F*/, 0x6C3F, 0x6C4D, 0x6C5B, - 0x6C6D, 0x6C84, 0x6C89, 0x3CC3, 0x6C94, 0x6C95, 0x6C97, 0x6CAD, - 0x6CC2, 0x6CD0, 0x3CD2, 0x6CD6, 0x6CDA, 0x6CDC, 0x6CE9, 0x6CEC, - 0x6CED, 0xD84F /*0xDD00*/, 0x6D00, 0x6D0A, 0x6D24, 0x6D26, 0x6D27, 0x6C67, - 0x6D2F, 0x6D3C, 0x6D5B, 0x6D5E, 0x6D60, 0x6D70, 0x6D80, 0x6D81, - 0x6D8A, 0x6D8D, 0x6D91, 0x6D98, 0xD84F /*0xDD40*/, 0x6E17, 0xD84F /*0xDDFA*/, 0xD84F /*0xDDF9*/, - 0xD84F /*0xDDD3*/, 0x6DAB, 0x6DAE, 0x6DB4, 0x6DC2, 0x6D34, 0x6DC8, 0x6DCE, - 0x6DCF, 0x6DD0, 0x6DDF, 0x6DE9, 0x6DF6, 0x6E36, 0x6E1E, 0x6E22, - 0x6E27, 0x3D11, 0x6E32, 0x6E3C, 0x6E48, 0x6E49, 0x6E4B, 0x6E4C, - 0x6E4F, 0x6E51, 0x6E53, 0x6E54, 0x6E57, 0x6E63, 0x3D1E, -}; -static const unsigned short euc_to_utf8_8FEF_x0213[] = { - 0x6E93, 0x6EA7, 0x6EB4, 0x6EBF, 0x6EC3, 0x6ECA, 0x6ED9, - 0x6F35, 0x6EEB, 0x6EF9, 0x6EFB, 0x6F0A, 0x6F0C, 0x6F18, 0x6F25, - 0x6F36, 0x6F3C, 0xD84F /*0xDF7E*/, 0x6F52, 0x6F57, 0x6F5A, 0x6F60, 0x6F68, - 0x6F98, 0x6F7D, 0x6F90, 0x6F96, 0x6FBE, 0x6F9F, 0x6FA5, 0x6FAF, - 0x3D64, 0x6FB5, 0x6FC8, 0x6FC9, 0x6FDA, 0x6FDE, 0x6FE9, 0xD850 /*0xDC96*/, - 0x6FFC, 0x7000, 0x7007, 0x700A, 0x7023, 0xD850 /*0xDD03*/, 0x7039, 0x703A, - 0x703C, 0x7043, 0x7047, 0x704B, 0x3D9A, 0x7054, 0x7065, 0x7069, - 0x706C, 0x706E, 0x7076, 0x707E, 0x7081, 0x7086, 0x7095, 0x7097, - 0x70BB, 0xD850 /*0xDDC6*/, 0x709F, 0x70B1, 0xD850 /*0xDDFE*/, 0x70EC, 0x70CA, 0x70D1, - 0x70D3, 0x70DC, 0x7103, 0x7104, 0x7106, 0x7107, 0x7108, 0x710C, - 0x3DC0, 0x712F, 0x7131, 0x7150, 0x714A, 0x7153, 0x715E, 0x3DD4, - 0x7196, 0x7180, 0x719B, 0x71A0, 0x71A2, 0x71AE, 0x71AF, -}; -static const unsigned short euc_to_utf8_8FF0_x0213[] = { - 0x71B3, 0xD850 /*0xDFBC*/, 0x71CB, 0x71D3, 0x71D9, 0x71DC, 0x7207, - 0x3E05, 0xFA49, 0x722B, 0x7234, 0x7238, 0x7239, 0x4E2C, 0x7242, - 0x7253, 0x7257, 0x7263, 0xD851 /*0xDE29*/, 0x726E, 0x726F, 0x7278, 0x727F, - 0x728E, 0xD851 /*0xDEA5*/, 0x72AD, 0x72AE, 0x72B0, 0x72B1, 0x72C1, 0x3E60, - 0x72CC, 0x3E66, 0x3E68, 0x72F3, 0x72FA, 0x7307, 0x7312, 0x7318, - 0x7319, 0x3E83, 0x7339, 0x732C, 0x7331, 0x7333, 0x733D, 0x7352, - 0x3E94, 0x736B, 0x736C, 0xD852 /*0xDC96*/, 0x736E, 0x736F, 0x7371, 0x7377, - 0x7381, 0x7385, 0x738A, 0x7394, 0x7398, 0x739C, 0x739E, 0x73A5, - 0x73A8, 0x73B5, 0x73B7, 0x73B9, 0x73BC, 0x73BF, 0x73C5, 0x73CB, - 0x73E1, 0x73E7, 0x73F9, 0x7413, 0x73FA, 0x7401, 0x7424, 0x7431, - 0x7439, 0x7453, 0x7440, 0x7443, 0x744D, 0x7452, 0x745D, 0x7471, - 0x7481, 0x7485, 0x7488, 0xD852 /*0xDE4D*/, 0x7492, 0x7497, 0x7499, -}; -static const unsigned short euc_to_utf8_8FF1_x0213[] = { - 0x74A0, 0x74A1, 0x74A5, 0x74AA, 0x74AB, 0x74B9, 0x74BB, - 0x74BA, 0x74D6, 0x74D8, 0x74DE, 0x74EF, 0x74EB, 0xD852 /*0xDF56*/, 0x74FA, - 0xD852 /*0xDF6F*/, 0x7520, 0x7524, 0x752A, 0x3F57, 0xD853 /*0xDC16*/, 0x753D, 0x753E, - 0x7540, 0x7548, 0x754E, 0x7550, 0x7552, 0x756C, 0x7572, 0x7571, - 0x757A, 0x757D, 0x757E, 0x7581, 0xD853 /*0xDD14*/, 0x758C, 0x3F75, 0x75A2, - 0x3F77, 0x75B0, 0x75B7, 0x75BF, 0x75C0, 0x75C6, 0x75CF, 0x75D3, - 0x75DD, 0x75DF, 0x75E0, 0x75E7, 0x75EC, 0x75EE, 0x75F1, 0x75F9, - 0x7603, 0x7618, 0x7607, 0x760F, 0x3FAE, 0xD853 /*0xDE0E*/, 0x7613, 0x761B, - 0x761C, 0xD853 /*0xDE37*/, 0x7625, 0x7628, 0x763C, 0x7633, 0xD853 /*0xDE6A*/, 0x3FC9, - 0x7641, 0xD853 /*0xDE8B*/, 0x7649, 0x7655, 0x3FD7, 0x766E, 0x7695, 0x769C, - 0x76A1, 0x76A0, 0x76A7, 0x76A8, 0x76AF, 0xD854 /*0xDC4A*/, 0x76C9, 0xD854 /*0xDC55*/, - 0x76E8, 0x76EC, 0xD854 /*0xDD22*/, 0x7717, 0x771A, 0x772D, 0x7735, -}; -static const unsigned short euc_to_utf8_8FF2_x0213[] = { - 0xD854 /*0xDDA9*/, 0x4039, 0xD854 /*0xDDE5*/, 0xD854 /*0xDDCD*/, 0x7758, 0x7760, 0x776A, - 0xD854 /*0xDE1E*/, 0x7772, 0x777C, 0x777D, 0xD854 /*0xDE4C*/, 0x4058, 0x779A, 0x779F, - 0x77A2, 0x77A4, 0x77A9, 0x77DE, 0x77DF, 0x77E4, 0x77E6, 0x77EA, - 0x77EC, 0x4093, 0x77F0, 0x77F4, 0x77FB, 0xD855 /*0xDC2E*/, 0x7805, 0x7806, - 0x7809, 0x780D, 0x7819, 0x7821, 0x782C, 0x7847, 0x7864, 0x786A, - 0xD855 /*0xDCD9*/, 0x788A, 0x7894, 0x78A4, 0x789D, 0x789E, 0x789F, 0x78BB, - 0x78C8, 0x78CC, 0x78CE, 0x78D5, 0x78E0, 0x78E1, 0x78E6, 0x78F9, - 0x78FA, 0x78FB, 0x78FE, 0xD855 /*0xDDA7*/, 0x7910, 0x791B, 0x7930, 0x7925, - 0x793B, 0x794A, 0x7958, 0x795B, 0x4105, 0x7967, 0x7972, 0x7994, - 0x7995, 0x7996, 0x799B, 0x79A1, 0x79A9, 0x79B4, 0x79BB, 0x79C2, - 0x79C7, 0x79CC, 0x79CD, 0x79D6, 0x4148, 0xD855 /*0xDFA9*/, 0xD855 /*0xDFB4*/, 0x414F, - 0x7A0A, 0x7A11, 0x7A15, 0x7A1B, 0x7A1E, 0x4163, 0x7A2D, -}; -static const unsigned short euc_to_utf8_8FF3_x0213[] = { - 0x7A38, 0x7A47, 0x7A4C, 0x7A56, 0x7A59, 0x7A5C, 0x7A5F, - 0x7A60, 0x7A67, 0x7A6A, 0x7A75, 0x7A78, 0x7A82, 0x7A8A, 0x7A90, - 0x7AA3, 0x7AAC, 0xD856 /*0xDDD4*/, 0x41B4, 0x7AB9, 0x7ABC, 0x7ABE, 0x41BF, - 0x7ACC, 0x7AD1, 0x7AE7, 0x7AE8, 0x7AF4, 0xD856 /*0xDEE4*/, 0xD856 /*0xDEE3*/, 0x7B07, - 0xD856 /*0xDEF1*/, 0x7B3D, 0x7B27, 0x7B2A, 0x7B2E, 0x7B2F, 0x7B31, 0x41E6, - 0x41F3, 0x7B7F, 0x7B41, 0x41EE, 0x7B55, 0x7B79, 0x7B64, 0x7B66, - 0x7B69, 0x7B73, 0xD856 /*0xDFB2*/, 0x4207, 0x7B90, 0x7B91, 0x7B9B, 0x420E, - 0x7BAF, 0x7BB5, 0x7BBC, 0x7BC5, 0x7BCA, 0xD857 /*0xDC4B*/, 0xD857 /*0xDC64*/, 0x7BD4, - 0x7BD6, 0x7BDA, 0x7BEA, 0x7BF0, 0x7C03, 0x7C0B, 0x7C0E, 0x7C0F, - 0x7C26, 0x7C45, 0x7C4A, 0x7C51, 0x7C57, 0x7C5E, 0x7C61, 0x7C69, - 0x7C6E, 0x7C6F, 0x7C70, 0xD857 /*0xDE2E*/, 0xD857 /*0xDE56*/, 0xD857 /*0xDE65*/, 0x7CA6, 0xD857 /*0xDE62*/, - 0x7CB6, 0x7CB7, 0x7CBF, 0xD857 /*0xDED8*/, 0x7CC4, 0xD857 /*0xDEC2*/, 0x7CC8, -}; -static const unsigned short euc_to_utf8_8FF4_x0213[] = { - 0x7CCD, 0xD857 /*0xDEE8*/, 0x7CD7, 0xD857 /*0xDF23*/, 0x7CE6, 0x7CEB, 0xD857 /*0xDF5C*/, - 0x7CF5, 0x7D03, 0x7D09, 0x42C6, 0x7D12, 0x7D1E, 0xD857 /*0xDFE0*/, 0xD857 /*0xDFD4*/, - 0x7D3D, 0x7D3E, 0x7D40, 0x7D47, 0xD858 /*0xDC0C*/, 0xD857 /*0xDFFB*/, 0x42D6, 0x7D59, - 0x7D5A, 0x7D6A, 0x7D70, 0x42DD, 0x7D7F, 0xD858 /*0xDC17*/, 0x7D86, 0x7D88, - 0x7D8C, 0x7D97, 0xD858 /*0xDC60*/, 0x7D9D, 0x7DA7, 0x7DAA, 0x7DB6, 0x7DB7, - 0x7DC0, 0x7DD7, 0x7DD9, 0x7DE6, 0x7DF1, 0x7DF9, 0x4302, 0xD858 /*0xDCED*/, - 0xFA58, 0x7E10, 0x7E17, 0x7E1D, 0x7E20, 0x7E27, 0x7E2C, 0x7E45, - 0x7E73, 0x7E75, 0x7E7E, 0x7E86, 0x7E87, 0x432B, 0x7E91, 0x7E98, - 0x7E9A, 0x4343, 0x7F3C, 0x7F3B, 0x7F3E, 0x7F43, 0x7F44, 0x7F4F, - 0x34C1, 0xD858 /*0xDE70*/, 0x7F52, 0xD858 /*0xDE86*/, 0x7F61, 0x7F63, 0x7F64, 0x7F6D, - 0x7F7D, 0x7F7E, 0xD858 /*0xDF4C*/, 0x7F90, 0x517B, 0xD84F /*0xDD0E*/, 0x7F96, 0x7F9C, - 0x7FAD, 0xD859 /*0xDC02*/, 0x7FC3, 0x7FCF, 0x7FE3, 0x7FE5, 0x7FEF, -}; -static const unsigned short euc_to_utf8_8FF5_x0213[] = { - 0x7FF2, 0x8002, 0x800A, 0x8008, 0x800E, 0x8011, 0x8016, - 0x8024, 0x802C, 0x8030, 0x8043, 0x8066, 0x8071, 0x8075, 0x807B, - 0x8099, 0x809C, 0x80A4, 0x80A7, 0x80B8, 0xD859 /*0xDE7E*/, 0x80C5, 0x80D5, - 0x80D8, 0x80E6, 0xD859 /*0xDEB0*/, 0x810D, 0x80F5, 0x80FB, 0x43EE, 0x8135, - 0x8116, 0x811E, 0x43F0, 0x8124, 0x8127, 0x812C, 0xD859 /*0xDF1D*/, 0x813D, - 0x4408, 0x8169, 0x4417, 0x8181, 0x441C, 0x8184, 0x8185, 0x4422, - 0x8198, 0x81B2, 0x81C1, 0x81C3, 0x81D6, 0x81DB, 0xD85A /*0xDCDD*/, 0x81E4, - 0xD85A /*0xDCEA*/, 0x81EC, 0xD85A /*0xDD51*/, 0x81FD, 0x81FF, 0xD85A /*0xDD6F*/, 0x8204, 0xD85A /*0xDDDD*/, - 0x8219, 0x8221, 0x8222, 0xD85A /*0xDE1E*/, 0x8232, 0x8234, 0x823C, 0x8246, - 0x8249, 0x8245, 0xD85A /*0xDE58*/, 0x824B, 0x4476, 0x824F, 0x447A, 0x8257, - 0xD85A /*0xDE8C*/, 0x825C, 0x8263, 0xD85A /*0xDEB7*/, 0xFA5D, 0xFA5E, 0x8279, 0x4491, - 0x827D, 0x827F, 0x8283, 0x828A, 0x8293, 0x82A7, 0x82A8, -}; -static const unsigned short euc_to_utf8_8FF6_x0213[] = { - 0x82B2, 0x82B4, 0x82BA, 0x82BC, 0x82E2, 0x82E8, 0x82F7, - 0x8307, 0x8308, 0x830C, 0x8354, 0x831B, 0x831D, 0x8330, 0x833C, - 0x8344, 0x8357, 0x44BE, 0x837F, 0x44D4, 0x44B3, 0x838D, 0x8394, - 0x8395, 0x839B, 0x839D, 0x83C9, 0x83D0, 0x83D4, 0x83DD, 0x83E5, - 0x83F9, 0x840F, 0x8411, 0x8415, 0xD85B /*0xDC73*/, 0x8417, 0x8439, 0x844A, - 0x844F, 0x8451, 0x8452, 0x8459, 0x845A, 0x845C, 0xD85B /*0xDCDD*/, 0x8465, - 0x8476, 0x8478, 0x847C, 0x8481, 0x450D, 0x84DC, 0x8497, 0x84A6, - 0x84BE, 0x4508, 0x84CE, 0x84CF, 0x84D3, 0xD85B /*0xDE65*/, 0x84E7, 0x84EA, - 0x84EF, 0x84F0, 0x84F1, 0x84FA, 0x84FD, 0x850C, 0x851B, 0x8524, - 0x8525, 0x852B, 0x8534, 0x854F, 0x856F, 0x4525, 0x4543, 0x853E, - 0x8551, 0x8553, 0x855E, 0x8561, 0x8562, 0xD85B /*0xDF94*/, 0x857B, 0x857D, - 0x857F, 0x8581, 0x8586, 0x8593, 0x859D, 0x859F, 0xD85B /*0xDFF8*/, -}; -static const unsigned short euc_to_utf8_8FF7_x0213[] = { - 0xD85B /*0xDFF6*/, 0xD85B /*0xDFF7*/, 0x85B7, 0x85BC, 0x85C7, 0x85CA, 0x85D8, - 0x85D9, 0x85DF, 0x85E1, 0x85E6, 0x85F6, 0x8600, 0x8611, 0x861E, - 0x8621, 0x8624, 0x8627, 0xD85C /*0xDD0D*/, 0x8639, 0x863C, 0xD85C /*0xDD39*/, 0x8640, - 0xFA20, 0x8653, 0x8656, 0x866F, 0x8677, 0x867A, 0x8687, 0x8689, - 0x868D, 0x8691, 0x869C, 0x869D, 0x86A8, 0xFA21, 0x86B1, 0x86B3, - 0x86C1, 0x86C3, 0x86D1, 0x86D5, 0x86D7, 0x86E3, 0x86E6, 0x45B8, - 0x8705, 0x8707, 0x870E, 0x8710, 0x8713, 0x8719, 0x871F, 0x8721, - 0x8723, 0x8731, 0x873A, 0x873E, 0x8740, 0x8743, 0x8751, 0x8758, - 0x8764, 0x8765, 0x8772, 0x877C, 0xD85C /*0xDFDB*/, 0xD85C /*0xDFDA*/, 0x87A7, 0x8789, - 0x878B, 0x8793, 0x87A0, 0xD85C /*0xDFFE*/, 0x45E5, 0x87BE, 0xD85D /*0xDC10*/, 0x87C1, - 0x87CE, 0x87F5, 0x87DF, 0xD85D /*0xDC49*/, 0x87E3, 0x87E5, 0x87E6, 0x87EA, - 0x87EB, 0x87ED, 0x8801, 0x8803, 0x880B, 0x8813, 0x8828, -}; -static const unsigned short euc_to_utf8_8FF8_x0213[] = { - 0x882E, 0x8832, 0x883C, 0x460F, 0x884A, 0x8858, 0x885F, - 0x8864, 0xD85D /*0xDE15*/, 0xD85D /*0xDE14*/, 0x8869, 0xD85D /*0xDE31*/, 0x886F, 0x88A0, 0x88BC, - 0x88BD, 0x88BE, 0x88C0, 0x88D2, 0xD85D /*0xDE93*/, 0x88D1, 0x88D3, 0x88DB, - 0x88F0, 0x88F1, 0x4641, 0x8901, 0xD85D /*0xDF0E*/, 0x8937, 0xD85D /*0xDF23*/, 0x8942, - 0x8945, 0x8949, 0xD85D /*0xDF52*/, 0x4665, 0x8962, 0x8980, 0x8989, 0x8990, - 0x899F, 0x89B0, 0x89B7, 0x89D6, 0x89D8, 0x89EB, 0x46A1, 0x89F1, - 0x89F3, 0x89FD, 0x89FF, 0x46AF, 0x8A11, 0x8A14, 0xD85E /*0xDD85*/, 0x8A21, - 0x8A35, 0x8A3E, 0x8A45, 0x8A4D, 0x8A58, 0x8AAE, 0x8A90, 0x8AB7, - 0x8ABE, 0x8AD7, 0x8AFC, 0xD85E /*0xDE84*/, 0x8B0A, 0x8B05, 0x8B0D, 0x8B1C, - 0x8B1F, 0x8B2D, 0x8B43, 0x470C, 0x8B51, 0x8B5E, 0x8B76, 0x8B7F, - 0x8B81, 0x8B8B, 0x8B94, 0x8B95, 0x8B9C, 0x8B9E, 0x8C39, 0xD85E /*0xDFB3*/, - 0x8C3D, 0xD85E /*0xDFBE*/, 0xD85E /*0xDFC7*/, 0x8C45, 0x8C47, 0x8C4F, 0x8C54, -}; -static const unsigned short euc_to_utf8_8FF9_x0213[] = { - 0x8C57, 0x8C69, 0x8C6D, 0x8C73, 0xD85F /*0xDCB8*/, 0x8C93, 0x8C92, - 0x8C99, 0x4764, 0x8C9B, 0x8CA4, 0x8CD6, 0x8CD5, 0x8CD9, 0xD85F /*0xDDA0*/, - 0x8CF0, 0x8CF1, 0xD85F /*0xDE10*/, 0x8D09, 0x8D0E, 0x8D6C, 0x8D84, 0x8D95, - 0x8DA6, 0xD85F /*0xDFB7*/, 0x8DC6, 0x8DC8, 0x8DD9, 0x8DEC, 0x8E0C, 0x47FD, - 0x8DFD, 0x8E06, 0xD860 /*0xDC8A*/, 0x8E14, 0x8E16, 0x8E21, 0x8E22, 0x8E27, - 0xD860 /*0xDCBB*/, 0x4816, 0x8E36, 0x8E39, 0x8E4B, 0x8E54, 0x8E62, 0x8E6C, - 0x8E6D, 0x8E6F, 0x8E98, 0x8E9E, 0x8EAE, 0x8EB3, 0x8EB5, 0x8EB6, - 0x8EBB, 0xD860 /*0xDE82*/, 0x8ED1, 0x8ED4, 0x484E, 0x8EF9, 0xD860 /*0xDEF3*/, 0x8F00, - 0x8F08, 0x8F17, 0x8F2B, 0x8F40, 0x8F4A, 0x8F58, 0xD861 /*0xDC0C*/, 0x8FA4, - 0x8FB4, 0xFA66, 0x8FB6, 0xD861 /*0xDC55*/, 0x8FC1, 0x8FC6, 0xFA24, 0x8FCA, - 0x8FCD, 0x8FD3, 0x8FD5, 0x8FE0, 0x8FF1, 0x8FF5, 0x8FFB, 0x9002, - 0x900C, 0x9037, 0xD861 /*0xDD6B*/, 0x9043, 0x9044, 0x905D, 0xD861 /*0xDDC8*/, -}; -static const unsigned short euc_to_utf8_8FFA_x0213[] = { - 0xD861 /*0xDDC9*/, 0x9085, 0x908C, 0x9090, 0x961D, 0x90A1, 0x48B5, - 0x90B0, 0x90B6, 0x90C3, 0x90C8, 0xD861 /*0xDED7*/, 0x90DC, 0x90DF, 0xD861 /*0xDEFA*/, - 0x90F6, 0x90F2, 0x9100, 0x90EB, 0x90FE, 0x90FF, 0x9104, 0x9106, - 0x9118, 0x911C, 0x911E, 0x9137, 0x9139, 0x913A, 0x9146, 0x9147, - 0x9157, 0x9159, 0x9161, 0x9164, 0x9174, 0x9179, 0x9185, 0x918E, - 0x91A8, 0x91AE, 0x91B3, 0x91B6, 0x91C3, 0x91C4, 0x91DA, 0xD862 /*0xDD49*/, - 0xD862 /*0xDD46*/, 0x91EC, 0x91EE, 0x9201, 0x920A, 0x9216, 0x9217, 0xD862 /*0xDD6B*/, - 0x9233, 0x9242, 0x9247, 0x924A, 0x924E, 0x9251, 0x9256, 0x9259, - 0x9260, 0x9261, 0x9265, 0x9267, 0x9268, 0xD862 /*0xDD87*/, 0xD862 /*0xDD88*/, 0x927C, - 0x927D, 0x927F, 0x9289, 0x928D, 0x9297, 0x9299, 0x929F, 0x92A7, - 0x92AB, 0xD862 /*0xDDBA*/, 0xD862 /*0xDDBB*/, 0x92B2, 0x92BF, 0x92C0, 0x92C6, 0x92CE, - 0x92D0, 0x92D7, 0x92D9, 0x92E5, 0x92E7, 0x9311, 0xD862 /*0xDE1E*/, -}; -static const unsigned short euc_to_utf8_8FFB_x0213[] = { - 0xD862 /*0xDE29*/, 0x92F7, 0x92F9, 0x92FB, 0x9302, 0x930D, 0x9315, - 0x931D, 0x931E, 0x9327, 0x9329, 0xD862 /*0xDE71*/, 0xD862 /*0xDE43*/, 0x9347, 0x9351, - 0x9357, 0x935A, 0x936B, 0x9371, 0x9373, 0x93A1, 0xD862 /*0xDE99*/, 0xD862 /*0xDECD*/, - 0x9388, 0x938B, 0x938F, 0x939E, 0x93F5, 0xD862 /*0xDEE4*/, 0xD862 /*0xDEDD*/, 0x93F1, - 0x93C1, 0x93C7, 0x93DC, 0x93E2, 0x93E7, 0x9409, 0x940F, 0x9416, - 0x9417, 0x93FB, 0x9432, 0x9434, 0x943B, 0x9445, 0xD862 /*0xDFC1*/, 0xD862 /*0xDFEF*/, - 0x946D, 0x946F, 0x9578, 0x9579, 0x9586, 0x958C, 0x958D, 0xD863 /*0xDD10*/, - 0x95AB, 0x95B4, 0xD863 /*0xDD71*/, 0x95C8, 0xD863 /*0xDDFB*/, 0xD863 /*0xDE1F*/, 0x962C, 0x9633, - 0x9634, 0xD863 /*0xDE36*/, 0x963C, 0x9641, 0x9661, 0xD863 /*0xDE89*/, 0x9682, 0xD863 /*0xDEEB*/, - 0x969A, 0xD863 /*0xDF32*/, 0x49E7, 0x96A9, 0x96AF, 0x96B3, 0x96BA, 0x96BD, - 0x49FA, 0xD863 /*0xDFF8*/, 0x96D8, 0x96DA, 0x96DD, 0x4A04, 0x9714, 0x9723, - 0x4A29, 0x9736, 0x9741, 0x9747, 0x9755, 0x9757, 0x975B, -}; -static const unsigned short euc_to_utf8_8FFC_x0213[] = { - 0x976A, 0xD864 /*0xDEA0*/, 0xD864 /*0xDEB1*/, 0x9796, 0x979A, 0x979E, 0x97A2, - 0x97B1, 0x97B2, 0x97BE, 0x97CC, 0x97D1, 0x97D4, 0x97D8, 0x97D9, - 0x97E1, 0x97F1, 0x9804, 0x980D, 0x980E, 0x9814, 0x9816, 0x4ABC, - 0xD865 /*0xDC90*/, 0x9823, 0x9832, 0x9833, 0x9825, 0x9847, 0x9866, 0x98AB, - 0x98AD, 0x98B0, 0xD865 /*0xDDCF*/, 0x98B7, 0x98B8, 0x98BB, 0x98BC, 0x98BF, - 0x98C2, 0x98C7, 0x98CB, 0x98E0, 0xD865 /*0xDE7F*/, 0x98E1, 0x98E3, 0x98E5, - 0x98EA, 0x98F0, 0x98F1, 0x98F3, 0x9908, 0x4B3B, 0xD865 /*0xDEF0*/, 0x9916, - 0x9917, 0xD865 /*0xDF19*/, 0x991A, 0x991B, 0x991C, 0xD865 /*0xDF50*/, 0x9931, 0x9932, - 0x9933, 0x993A, 0x993B, 0x993C, 0x9940, 0x9941, 0x9946, 0x994D, - 0x994E, 0x995C, 0x995F, 0x9960, 0x99A3, 0x99A6, 0x99B9, 0x99BD, - 0x99BF, 0x99C3, 0x99C9, 0x99D4, 0x99D9, 0x99DE, 0xD866 /*0xDCC6*/, 0x99F0, - 0x99F9, 0x99FC, 0x9A0A, 0x9A11, 0x9A16, 0x9A1A, 0x9A20, -}; -static const unsigned short euc_to_utf8_8FFD_x0213[] = { - 0x9A31, 0x9A36, 0x9A44, 0x9A4C, 0x9A58, 0x4BC2, 0x9AAF, - 0x4BCA, 0x9AB7, 0x4BD2, 0x9AB9, 0xD866 /*0xDE72*/, 0x9AC6, 0x9AD0, 0x9AD2, - 0x9AD5, 0x4BE8, 0x9ADC, 0x9AE0, 0x9AE5, 0x9AE9, 0x9B03, 0x9B0C, - 0x9B10, 0x9B12, 0x9B16, 0x9B1C, 0x9B2B, 0x9B33, 0x9B3D, 0x4C20, - 0x9B4B, 0x9B63, 0x9B65, 0x9B6B, 0x9B6C, 0x9B73, 0x9B76, 0x9B77, - 0x9BA6, 0x9BAC, 0x9BB1, 0xD867 /*0xDDDB*/, 0xD867 /*0xDE3D*/, 0x9BB2, 0x9BB8, 0x9BBE, - 0x9BC7, 0x9BF3, 0x9BD8, 0x9BDD, 0x9BE7, 0x9BEA, 0x9BEB, 0x9BEF, - 0x9BEE, 0xD867 /*0xDE15*/, 0x9BFA, 0xD867 /*0xDE8A*/, 0x9BF7, 0xD867 /*0xDE49*/, 0x9C16, 0x9C18, - 0x9C19, 0x9C1A, 0x9C1D, 0x9C22, 0x9C27, 0x9C29, 0x9C2A, 0xD867 /*0xDEC4*/, - 0x9C31, 0x9C36, 0x9C37, 0x9C45, 0x9C5C, 0xD867 /*0xDEE9*/, 0x9C49, 0x9C4A, - 0xD867 /*0xDEDB*/, 0x9C54, 0x9C58, 0x9C5B, 0x9C5D, 0x9C5F, 0x9C69, 0x9C6A, - 0x9C6B, 0x9C6D, 0x9C6E, 0x9C70, 0x9C72, 0x9C75, 0x9C7A, -}; -static const unsigned short euc_to_utf8_8FFE_x0213[] = { - 0x9CE6, 0x9CF2, 0x9D0B, 0x9D02, 0xD867 /*0xDFCE*/, 0x9D11, 0x9D17, - 0x9D18, 0xD868 /*0xDC2F*/, 0x4CC4, 0xD868 /*0xDC1A*/, 0x9D32, 0x4CD1, 0x9D42, 0x9D4A, - 0x9D5F, 0x9D62, 0xD868 /*0xDCF9*/, 0x9D69, 0x9D6B, 0xD868 /*0xDC82*/, 0x9D73, 0x9D76, - 0x9D77, 0x9D7E, 0x9D84, 0x9D8D, 0x9D99, 0x9DA1, 0x9DBF, 0x9DB5, - 0x9DB9, 0x9DBD, 0x9DC3, 0x9DC7, 0x9DC9, 0x9DD6, 0x9DDA, 0x9DDF, - 0x9DE0, 0x9DE3, 0x9DF4, 0x4D07, 0x9E0A, 0x9E02, 0x9E0D, 0x9E19, - 0x9E1C, 0x9E1D, 0x9E7B, 0xD848 /*0xDE18*/, 0x9E80, 0x9E85, 0x9E9B, 0x9EA8, - 0xD868 /*0xDF8C*/, 0x9EBD, 0xD869 /*0xDC37*/, 0x9EDF, 0x9EE7, 0x9EEE, 0x9EFF, 0x9F02, - 0x4D77, 0x9F03, 0x9F17, 0x9F19, 0x9F2F, 0x9F37, 0x9F3A, 0x9F3D, - 0x9F41, 0x9F45, 0x9F46, 0x9F53, 0x9F55, 0x9F58, 0xD869 /*0xDDF1*/, 0x9F5D, - 0xD869 /*0xDE02*/, 0x9F69, 0xD869 /*0xDE1A*/, 0x9F6D, 0x9F70, 0x9F75, 0xD869 /*0xDEB2*/, 0, - 0, 0, 0, 0, 0, 0, 0, -}; - -#ifdef X0212_ENABLE -static const unsigned short euc_to_utf8_8FA2[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x02D8, - 0x02C7, 0x00B8, 0x02D9, 0x02DD, 0x00AF, 0x02DB, 0x02DA, 0xFF5E, - 0x0384, 0x0385, 0, 0, 0, 0, 0, 0, - 0, 0, 0x00A1, 0xFFE4, 0x00BF, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x00BA, 0x00AA, 0x00A9, 0x00AE, 0x2122, - 0x00A4, 0x2116, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_8FA6[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x0386, 0x0388, 0x0389, 0x038A, 0x03AA, 0, 0x038C, - 0, 0x038E, 0x03AB, 0, 0x038F, 0, 0, 0, - 0, 0x03AC, 0x03AD, 0x03AE, 0x03AF, 0x03CA, 0x0390, 0x03CC, - 0x03C2, 0x03CD, 0x03CB, 0x03B0, 0x03CE, 0, 0, -}; -static const unsigned short euc_to_utf8_8FA7[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, - 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x040E, 0x040F, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, - 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045E, 0x045F, -}; -static const unsigned short euc_to_utf8_8FA9[] = { - 0x00C6, 0x0110, 0, 0x0126, 0, 0x0132, 0, - 0x0141, 0x013F, 0, 0x014A, 0x00D8, 0x0152, 0, 0x0166, - 0x00DE, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x00E6, 0x0111, 0x00F0, 0x0127, 0x0131, 0x0133, 0x0138, - 0x0142, 0x0140, 0x0149, 0x014B, 0x00F8, 0x0153, 0x00DF, 0x0167, - 0x00FE, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short euc_to_utf8_8FAA[] = { - 0x00C1, 0x00C0, 0x00C4, 0x00C2, 0x0102, 0x01CD, 0x0100, - 0x0104, 0x00C5, 0x00C3, 0x0106, 0x0108, 0x010C, 0x00C7, 0x010A, - 0x010E, 0x00C9, 0x00C8, 0x00CB, 0x00CA, 0x011A, 0x0116, 0x0112, - 0x0118, 0, 0x011C, 0x011E, 0x0122, 0x0120, 0x0124, 0x00CD, - 0x00CC, 0x00CF, 0x00CE, 0x01CF, 0x0130, 0x012A, 0x012E, 0x0128, - 0x0134, 0x0136, 0x0139, 0x013D, 0x013B, 0x0143, 0x0147, 0x0145, - 0x00D1, 0x00D3, 0x00D2, 0x00D6, 0x00D4, 0x01D1, 0x0150, 0x014C, - 0x00D5, 0x0154, 0x0158, 0x0156, 0x015A, 0x015C, 0x0160, 0x015E, - 0x0164, 0x0162, 0x00DA, 0x00D9, 0x00DC, 0x00DB, 0x016C, 0x01D3, - 0x0170, 0x016A, 0x0172, 0x016E, 0x0168, 0x01D7, 0x01DB, 0x01D9, - 0x01D5, 0x0174, 0x00DD, 0x0178, 0x0176, 0x0179, 0x017D, 0x017B, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_8FAB[] = { - 0x00E1, 0x00E0, 0x00E4, 0x00E2, 0x0103, 0x01CE, 0x0101, - 0x0105, 0x00E5, 0x00E3, 0x0107, 0x0109, 0x010D, 0x00E7, 0x010B, - 0x010F, 0x00E9, 0x00E8, 0x00EB, 0x00EA, 0x011B, 0x0117, 0x0113, - 0x0119, 0x01F5, 0x011D, 0x011F, 0, 0x0121, 0x0125, 0x00ED, - 0x00EC, 0x00EF, 0x00EE, 0x01D0, 0, 0x012B, 0x012F, 0x0129, - 0x0135, 0x0137, 0x013A, 0x013E, 0x013C, 0x0144, 0x0148, 0x0146, - 0x00F1, 0x00F3, 0x00F2, 0x00F6, 0x00F4, 0x01D2, 0x0151, 0x014D, - 0x00F5, 0x0155, 0x0159, 0x0157, 0x015B, 0x015D, 0x0161, 0x015F, - 0x0165, 0x0163, 0x00FA, 0x00F9, 0x00FC, 0x00FB, 0x016D, 0x01D4, - 0x0171, 0x016B, 0x0173, 0x016F, 0x0169, 0x01D8, 0x01DC, 0x01DA, - 0x01D6, 0x0175, 0x00FD, 0x00FF, 0x0177, 0x017A, 0x017E, 0x017C, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_8FB0[] = { - 0x4E02, 0x4E04, 0x4E05, 0x4E0C, 0x4E12, 0x4E1F, 0x4E23, - 0x4E24, 0x4E28, 0x4E2B, 0x4E2E, 0x4E2F, 0x4E30, 0x4E35, 0x4E40, - 0x4E41, 0x4E44, 0x4E47, 0x4E51, 0x4E5A, 0x4E5C, 0x4E63, 0x4E68, - 0x4E69, 0x4E74, 0x4E75, 0x4E79, 0x4E7F, 0x4E8D, 0x4E96, 0x4E97, - 0x4E9D, 0x4EAF, 0x4EB9, 0x4EC3, 0x4ED0, 0x4EDA, 0x4EDB, 0x4EE0, - 0x4EE1, 0x4EE2, 0x4EE8, 0x4EEF, 0x4EF1, 0x4EF3, 0x4EF5, 0x4EFD, - 0x4EFE, 0x4EFF, 0x4F00, 0x4F02, 0x4F03, 0x4F08, 0x4F0B, 0x4F0C, - 0x4F12, 0x4F15, 0x4F16, 0x4F17, 0x4F19, 0x4F2E, 0x4F31, 0x4F60, - 0x4F33, 0x4F35, 0x4F37, 0x4F39, 0x4F3B, 0x4F3E, 0x4F40, 0x4F42, - 0x4F48, 0x4F49, 0x4F4B, 0x4F4C, 0x4F52, 0x4F54, 0x4F56, 0x4F58, - 0x4F5F, 0x4F63, 0x4F6A, 0x4F6C, 0x4F6E, 0x4F71, 0x4F77, 0x4F78, - 0x4F79, 0x4F7A, 0x4F7D, 0x4F7E, 0x4F81, 0x4F82, 0x4F84, -}; -static const unsigned short euc_to_utf8_8FB1[] = { - 0x4F85, 0x4F89, 0x4F8A, 0x4F8C, 0x4F8E, 0x4F90, 0x4F92, - 0x4F93, 0x4F94, 0x4F97, 0x4F99, 0x4F9A, 0x4F9E, 0x4F9F, 0x4FB2, - 0x4FB7, 0x4FB9, 0x4FBB, 0x4FBC, 0x4FBD, 0x4FBE, 0x4FC0, 0x4FC1, - 0x4FC5, 0x4FC6, 0x4FC8, 0x4FC9, 0x4FCB, 0x4FCC, 0x4FCD, 0x4FCF, - 0x4FD2, 0x4FDC, 0x4FE0, 0x4FE2, 0x4FF0, 0x4FF2, 0x4FFC, 0x4FFD, - 0x4FFF, 0x5000, 0x5001, 0x5004, 0x5007, 0x500A, 0x500C, 0x500E, - 0x5010, 0x5013, 0x5017, 0x5018, 0x501B, 0x501C, 0x501D, 0x501E, - 0x5022, 0x5027, 0x502E, 0x5030, 0x5032, 0x5033, 0x5035, 0x5040, - 0x5041, 0x5042, 0x5045, 0x5046, 0x504A, 0x504C, 0x504E, 0x5051, - 0x5052, 0x5053, 0x5057, 0x5059, 0x505F, 0x5060, 0x5062, 0x5063, - 0x5066, 0x5067, 0x506A, 0x506D, 0x5070, 0x5071, 0x503B, 0x5081, - 0x5083, 0x5084, 0x5086, 0x508A, 0x508E, 0x508F, 0x5090, -}; -static const unsigned short euc_to_utf8_8FB2[] = { - 0x5092, 0x5093, 0x5094, 0x5096, 0x509B, 0x509C, 0x509E, - 0x509F, 0x50A0, 0x50A1, 0x50A2, 0x50AA, 0x50AF, 0x50B0, 0x50B9, - 0x50BA, 0x50BD, 0x50C0, 0x50C3, 0x50C4, 0x50C7, 0x50CC, 0x50CE, - 0x50D0, 0x50D3, 0x50D4, 0x50D8, 0x50DC, 0x50DD, 0x50DF, 0x50E2, - 0x50E4, 0x50E6, 0x50E8, 0x50E9, 0x50EF, 0x50F1, 0x50F6, 0x50FA, - 0x50FE, 0x5103, 0x5106, 0x5107, 0x5108, 0x510B, 0x510C, 0x510D, - 0x510E, 0x50F2, 0x5110, 0x5117, 0x5119, 0x511B, 0x511C, 0x511D, - 0x511E, 0x5123, 0x5127, 0x5128, 0x512C, 0x512D, 0x512F, 0x5131, - 0x5133, 0x5134, 0x5135, 0x5138, 0x5139, 0x5142, 0x514A, 0x514F, - 0x5153, 0x5155, 0x5157, 0x5158, 0x515F, 0x5164, 0x5166, 0x517E, - 0x5183, 0x5184, 0x518B, 0x518E, 0x5198, 0x519D, 0x51A1, 0x51A3, - 0x51AD, 0x51B8, 0x51BA, 0x51BC, 0x51BE, 0x51BF, 0x51C2, -}; -static const unsigned short euc_to_utf8_8FB3[] = { - 0x51C8, 0x51CF, 0x51D1, 0x51D2, 0x51D3, 0x51D5, 0x51D8, - 0x51DE, 0x51E2, 0x51E5, 0x51EE, 0x51F2, 0x51F3, 0x51F4, 0x51F7, - 0x5201, 0x5202, 0x5205, 0x5212, 0x5213, 0x5215, 0x5216, 0x5218, - 0x5222, 0x5228, 0x5231, 0x5232, 0x5235, 0x523C, 0x5245, 0x5249, - 0x5255, 0x5257, 0x5258, 0x525A, 0x525C, 0x525F, 0x5260, 0x5261, - 0x5266, 0x526E, 0x5277, 0x5278, 0x5279, 0x5280, 0x5282, 0x5285, - 0x528A, 0x528C, 0x5293, 0x5295, 0x5296, 0x5297, 0x5298, 0x529A, - 0x529C, 0x52A4, 0x52A5, 0x52A6, 0x52A7, 0x52AF, 0x52B0, 0x52B6, - 0x52B7, 0x52B8, 0x52BA, 0x52BB, 0x52BD, 0x52C0, 0x52C4, 0x52C6, - 0x52C8, 0x52CC, 0x52CF, 0x52D1, 0x52D4, 0x52D6, 0x52DB, 0x52DC, - 0x52E1, 0x52E5, 0x52E8, 0x52E9, 0x52EA, 0x52EC, 0x52F0, 0x52F1, - 0x52F4, 0x52F6, 0x52F7, 0x5300, 0x5303, 0x530A, 0x530B, -}; -static const unsigned short euc_to_utf8_8FB4[] = { - 0x530C, 0x5311, 0x5313, 0x5318, 0x531B, 0x531C, 0x531E, - 0x531F, 0x5325, 0x5327, 0x5328, 0x5329, 0x532B, 0x532C, 0x532D, - 0x5330, 0x5332, 0x5335, 0x533C, 0x533D, 0x533E, 0x5342, 0x534C, - 0x534B, 0x5359, 0x535B, 0x5361, 0x5363, 0x5365, 0x536C, 0x536D, - 0x5372, 0x5379, 0x537E, 0x5383, 0x5387, 0x5388, 0x538E, 0x5393, - 0x5394, 0x5399, 0x539D, 0x53A1, 0x53A4, 0x53AA, 0x53AB, 0x53AF, - 0x53B2, 0x53B4, 0x53B5, 0x53B7, 0x53B8, 0x53BA, 0x53BD, 0x53C0, - 0x53C5, 0x53CF, 0x53D2, 0x53D3, 0x53D5, 0x53DA, 0x53DD, 0x53DE, - 0x53E0, 0x53E6, 0x53E7, 0x53F5, 0x5402, 0x5413, 0x541A, 0x5421, - 0x5427, 0x5428, 0x542A, 0x542F, 0x5431, 0x5434, 0x5435, 0x5443, - 0x5444, 0x5447, 0x544D, 0x544F, 0x545E, 0x5462, 0x5464, 0x5466, - 0x5467, 0x5469, 0x546B, 0x546D, 0x546E, 0x5474, 0x547F, -}; -static const unsigned short euc_to_utf8_8FB5[] = { - 0x5481, 0x5483, 0x5485, 0x5488, 0x5489, 0x548D, 0x5491, - 0x5495, 0x5496, 0x549C, 0x549F, 0x54A1, 0x54A6, 0x54A7, 0x54A9, - 0x54AA, 0x54AD, 0x54AE, 0x54B1, 0x54B7, 0x54B9, 0x54BA, 0x54BB, - 0x54BF, 0x54C6, 0x54CA, 0x54CD, 0x54CE, 0x54E0, 0x54EA, 0x54EC, - 0x54EF, 0x54F6, 0x54FC, 0x54FE, 0x54FF, 0x5500, 0x5501, 0x5505, - 0x5508, 0x5509, 0x550C, 0x550D, 0x550E, 0x5515, 0x552A, 0x552B, - 0x5532, 0x5535, 0x5536, 0x553B, 0x553C, 0x553D, 0x5541, 0x5547, - 0x5549, 0x554A, 0x554D, 0x5550, 0x5551, 0x5558, 0x555A, 0x555B, - 0x555E, 0x5560, 0x5561, 0x5564, 0x5566, 0x557F, 0x5581, 0x5582, - 0x5586, 0x5588, 0x558E, 0x558F, 0x5591, 0x5592, 0x5593, 0x5594, - 0x5597, 0x55A3, 0x55A4, 0x55AD, 0x55B2, 0x55BF, 0x55C1, 0x55C3, - 0x55C6, 0x55C9, 0x55CB, 0x55CC, 0x55CE, 0x55D1, 0x55D2, -}; -static const unsigned short euc_to_utf8_8FB6[] = { - 0x55D3, 0x55D7, 0x55D8, 0x55DB, 0x55DE, 0x55E2, 0x55E9, - 0x55F6, 0x55FF, 0x5605, 0x5608, 0x560A, 0x560D, 0x560E, 0x560F, - 0x5610, 0x5611, 0x5612, 0x5619, 0x562C, 0x5630, 0x5633, 0x5635, - 0x5637, 0x5639, 0x563B, 0x563C, 0x563D, 0x563F, 0x5640, 0x5641, - 0x5643, 0x5644, 0x5646, 0x5649, 0x564B, 0x564D, 0x564F, 0x5654, - 0x565E, 0x5660, 0x5661, 0x5662, 0x5663, 0x5666, 0x5669, 0x566D, - 0x566F, 0x5671, 0x5672, 0x5675, 0x5684, 0x5685, 0x5688, 0x568B, - 0x568C, 0x5695, 0x5699, 0x569A, 0x569D, 0x569E, 0x569F, 0x56A6, - 0x56A7, 0x56A8, 0x56A9, 0x56AB, 0x56AC, 0x56AD, 0x56B1, 0x56B3, - 0x56B7, 0x56BE, 0x56C5, 0x56C9, 0x56CA, 0x56CB, 0x56CF, 0x56D0, - 0x56CC, 0x56CD, 0x56D9, 0x56DC, 0x56DD, 0x56DF, 0x56E1, 0x56E4, - 0x56E5, 0x56E6, 0x56E7, 0x56E8, 0x56F1, 0x56EB, 0x56ED, -}; -static const unsigned short euc_to_utf8_8FB7[] = { - 0x56F6, 0x56F7, 0x5701, 0x5702, 0x5707, 0x570A, 0x570C, - 0x5711, 0x5715, 0x571A, 0x571B, 0x571D, 0x5720, 0x5722, 0x5723, - 0x5724, 0x5725, 0x5729, 0x572A, 0x572C, 0x572E, 0x572F, 0x5733, - 0x5734, 0x573D, 0x573E, 0x573F, 0x5745, 0x5746, 0x574C, 0x574D, - 0x5752, 0x5762, 0x5765, 0x5767, 0x5768, 0x576B, 0x576D, 0x576E, - 0x576F, 0x5770, 0x5771, 0x5773, 0x5774, 0x5775, 0x5777, 0x5779, - 0x577A, 0x577B, 0x577C, 0x577E, 0x5781, 0x5783, 0x578C, 0x5794, - 0x5797, 0x5799, 0x579A, 0x579C, 0x579D, 0x579E, 0x579F, 0x57A1, - 0x5795, 0x57A7, 0x57A8, 0x57A9, 0x57AC, 0x57B8, 0x57BD, 0x57C7, - 0x57C8, 0x57CC, 0x57CF, 0x57D5, 0x57DD, 0x57DE, 0x57E4, 0x57E6, - 0x57E7, 0x57E9, 0x57ED, 0x57F0, 0x57F5, 0x57F6, 0x57F8, 0x57FD, - 0x57FE, 0x57FF, 0x5803, 0x5804, 0x5808, 0x5809, 0x57E1, -}; -static const unsigned short euc_to_utf8_8FB8[] = { - 0x580C, 0x580D, 0x581B, 0x581E, 0x581F, 0x5820, 0x5826, - 0x5827, 0x582D, 0x5832, 0x5839, 0x583F, 0x5849, 0x584C, 0x584D, - 0x584F, 0x5850, 0x5855, 0x585F, 0x5861, 0x5864, 0x5867, 0x5868, - 0x5878, 0x587C, 0x587F, 0x5880, 0x5881, 0x5887, 0x5888, 0x5889, - 0x588A, 0x588C, 0x588D, 0x588F, 0x5890, 0x5894, 0x5896, 0x589D, - 0x58A0, 0x58A1, 0x58A2, 0x58A6, 0x58A9, 0x58B1, 0x58B2, 0x58C4, - 0x58BC, 0x58C2, 0x58C8, 0x58CD, 0x58CE, 0x58D0, 0x58D2, 0x58D4, - 0x58D6, 0x58DA, 0x58DD, 0x58E1, 0x58E2, 0x58E9, 0x58F3, 0x5905, - 0x5906, 0x590B, 0x590C, 0x5912, 0x5913, 0x5914, 0x8641, 0x591D, - 0x5921, 0x5923, 0x5924, 0x5928, 0x592F, 0x5930, 0x5933, 0x5935, - 0x5936, 0x593F, 0x5943, 0x5946, 0x5952, 0x5953, 0x5959, 0x595B, - 0x595D, 0x595E, 0x595F, 0x5961, 0x5963, 0x596B, 0x596D, -}; -static const unsigned short euc_to_utf8_8FB9[] = { - 0x596F, 0x5972, 0x5975, 0x5976, 0x5979, 0x597B, 0x597C, - 0x598B, 0x598C, 0x598E, 0x5992, 0x5995, 0x5997, 0x599F, 0x59A4, - 0x59A7, 0x59AD, 0x59AE, 0x59AF, 0x59B0, 0x59B3, 0x59B7, 0x59BA, - 0x59BC, 0x59C1, 0x59C3, 0x59C4, 0x59C8, 0x59CA, 0x59CD, 0x59D2, - 0x59DD, 0x59DE, 0x59DF, 0x59E3, 0x59E4, 0x59E7, 0x59EE, 0x59EF, - 0x59F1, 0x59F2, 0x59F4, 0x59F7, 0x5A00, 0x5A04, 0x5A0C, 0x5A0D, - 0x5A0E, 0x5A12, 0x5A13, 0x5A1E, 0x5A23, 0x5A24, 0x5A27, 0x5A28, - 0x5A2A, 0x5A2D, 0x5A30, 0x5A44, 0x5A45, 0x5A47, 0x5A48, 0x5A4C, - 0x5A50, 0x5A55, 0x5A5E, 0x5A63, 0x5A65, 0x5A67, 0x5A6D, 0x5A77, - 0x5A7A, 0x5A7B, 0x5A7E, 0x5A8B, 0x5A90, 0x5A93, 0x5A96, 0x5A99, - 0x5A9C, 0x5A9E, 0x5A9F, 0x5AA0, 0x5AA2, 0x5AA7, 0x5AAC, 0x5AB1, - 0x5AB2, 0x5AB3, 0x5AB5, 0x5AB8, 0x5ABA, 0x5ABB, 0x5ABF, -}; -static const unsigned short euc_to_utf8_8FBA[] = { - 0x5AC4, 0x5AC6, 0x5AC8, 0x5ACF, 0x5ADA, 0x5ADC, 0x5AE0, - 0x5AE5, 0x5AEA, 0x5AEE, 0x5AF5, 0x5AF6, 0x5AFD, 0x5B00, 0x5B01, - 0x5B08, 0x5B17, 0x5B34, 0x5B19, 0x5B1B, 0x5B1D, 0x5B21, 0x5B25, - 0x5B2D, 0x5B38, 0x5B41, 0x5B4B, 0x5B4C, 0x5B52, 0x5B56, 0x5B5E, - 0x5B68, 0x5B6E, 0x5B6F, 0x5B7C, 0x5B7D, 0x5B7E, 0x5B7F, 0x5B81, - 0x5B84, 0x5B86, 0x5B8A, 0x5B8E, 0x5B90, 0x5B91, 0x5B93, 0x5B94, - 0x5B96, 0x5BA8, 0x5BA9, 0x5BAC, 0x5BAD, 0x5BAF, 0x5BB1, 0x5BB2, - 0x5BB7, 0x5BBA, 0x5BBC, 0x5BC0, 0x5BC1, 0x5BCD, 0x5BCF, 0x5BD6, - 0x5BD7, 0x5BD8, 0x5BD9, 0x5BDA, 0x5BE0, 0x5BEF, 0x5BF1, 0x5BF4, - 0x5BFD, 0x5C0C, 0x5C17, 0x5C1E, 0x5C1F, 0x5C23, 0x5C26, 0x5C29, - 0x5C2B, 0x5C2C, 0x5C2E, 0x5C30, 0x5C32, 0x5C35, 0x5C36, 0x5C59, - 0x5C5A, 0x5C5C, 0x5C62, 0x5C63, 0x5C67, 0x5C68, 0x5C69, -}; -static const unsigned short euc_to_utf8_8FBB[] = { - 0x5C6D, 0x5C70, 0x5C74, 0x5C75, 0x5C7A, 0x5C7B, 0x5C7C, - 0x5C7D, 0x5C87, 0x5C88, 0x5C8A, 0x5C8F, 0x5C92, 0x5C9D, 0x5C9F, - 0x5CA0, 0x5CA2, 0x5CA3, 0x5CA6, 0x5CAA, 0x5CB2, 0x5CB4, 0x5CB5, - 0x5CBA, 0x5CC9, 0x5CCB, 0x5CD2, 0x5CDD, 0x5CD7, 0x5CEE, 0x5CF1, - 0x5CF2, 0x5CF4, 0x5D01, 0x5D06, 0x5D0D, 0x5D12, 0x5D2B, 0x5D23, - 0x5D24, 0x5D26, 0x5D27, 0x5D31, 0x5D34, 0x5D39, 0x5D3D, 0x5D3F, - 0x5D42, 0x5D43, 0x5D46, 0x5D48, 0x5D55, 0x5D51, 0x5D59, 0x5D4A, - 0x5D5F, 0x5D60, 0x5D61, 0x5D62, 0x5D64, 0x5D6A, 0x5D6D, 0x5D70, - 0x5D79, 0x5D7A, 0x5D7E, 0x5D7F, 0x5D81, 0x5D83, 0x5D88, 0x5D8A, - 0x5D92, 0x5D93, 0x5D94, 0x5D95, 0x5D99, 0x5D9B, 0x5D9F, 0x5DA0, - 0x5DA7, 0x5DAB, 0x5DB0, 0x5DB4, 0x5DB8, 0x5DB9, 0x5DC3, 0x5DC7, - 0x5DCB, 0x5DD0, 0x5DCE, 0x5DD8, 0x5DD9, 0x5DE0, 0x5DE4, -}; -static const unsigned short euc_to_utf8_8FBC[] = { - 0x5DE9, 0x5DF8, 0x5DF9, 0x5E00, 0x5E07, 0x5E0D, 0x5E12, - 0x5E14, 0x5E15, 0x5E18, 0x5E1F, 0x5E20, 0x5E2E, 0x5E28, 0x5E32, - 0x5E35, 0x5E3E, 0x5E4B, 0x5E50, 0x5E49, 0x5E51, 0x5E56, 0x5E58, - 0x5E5B, 0x5E5C, 0x5E5E, 0x5E68, 0x5E6A, 0x5E6B, 0x5E6C, 0x5E6D, - 0x5E6E, 0x5E70, 0x5E80, 0x5E8B, 0x5E8E, 0x5EA2, 0x5EA4, 0x5EA5, - 0x5EA8, 0x5EAA, 0x5EAC, 0x5EB1, 0x5EB3, 0x5EBD, 0x5EBE, 0x5EBF, - 0x5EC6, 0x5ECC, 0x5ECB, 0x5ECE, 0x5ED1, 0x5ED2, 0x5ED4, 0x5ED5, - 0x5EDC, 0x5EDE, 0x5EE5, 0x5EEB, 0x5F02, 0x5F06, 0x5F07, 0x5F08, - 0x5F0E, 0x5F19, 0x5F1C, 0x5F1D, 0x5F21, 0x5F22, 0x5F23, 0x5F24, - 0x5F28, 0x5F2B, 0x5F2C, 0x5F2E, 0x5F30, 0x5F34, 0x5F36, 0x5F3B, - 0x5F3D, 0x5F3F, 0x5F40, 0x5F44, 0x5F45, 0x5F47, 0x5F4D, 0x5F50, - 0x5F54, 0x5F58, 0x5F5B, 0x5F60, 0x5F63, 0x5F64, 0x5F67, -}; -static const unsigned short euc_to_utf8_8FBD[] = { - 0x5F6F, 0x5F72, 0x5F74, 0x5F75, 0x5F78, 0x5F7A, 0x5F7D, - 0x5F7E, 0x5F89, 0x5F8D, 0x5F8F, 0x5F96, 0x5F9C, 0x5F9D, 0x5FA2, - 0x5FA7, 0x5FAB, 0x5FA4, 0x5FAC, 0x5FAF, 0x5FB0, 0x5FB1, 0x5FB8, - 0x5FC4, 0x5FC7, 0x5FC8, 0x5FC9, 0x5FCB, 0x5FD0, 0x5FD1, 0x5FD2, - 0x5FD3, 0x5FD4, 0x5FDE, 0x5FE1, 0x5FE2, 0x5FE8, 0x5FE9, 0x5FEA, - 0x5FEC, 0x5FED, 0x5FEE, 0x5FEF, 0x5FF2, 0x5FF3, 0x5FF6, 0x5FFA, - 0x5FFC, 0x6007, 0x600A, 0x600D, 0x6013, 0x6014, 0x6017, 0x6018, - 0x601A, 0x601F, 0x6024, 0x602D, 0x6033, 0x6035, 0x6040, 0x6047, - 0x6048, 0x6049, 0x604C, 0x6051, 0x6054, 0x6056, 0x6057, 0x605D, - 0x6061, 0x6067, 0x6071, 0x607E, 0x607F, 0x6082, 0x6086, 0x6088, - 0x608A, 0x608E, 0x6091, 0x6093, 0x6095, 0x6098, 0x609D, 0x609E, - 0x60A2, 0x60A4, 0x60A5, 0x60A8, 0x60B0, 0x60B1, 0x60B7, -}; -static const unsigned short euc_to_utf8_8FBE[] = { - 0x60BB, 0x60BE, 0x60C2, 0x60C4, 0x60C8, 0x60C9, 0x60CA, - 0x60CB, 0x60CE, 0x60CF, 0x60D4, 0x60D5, 0x60D9, 0x60DB, 0x60DD, - 0x60DE, 0x60E2, 0x60E5, 0x60F2, 0x60F5, 0x60F8, 0x60FC, 0x60FD, - 0x6102, 0x6107, 0x610A, 0x610C, 0x6110, 0x6111, 0x6112, 0x6113, - 0x6114, 0x6116, 0x6117, 0x6119, 0x611C, 0x611E, 0x6122, 0x612A, - 0x612B, 0x6130, 0x6131, 0x6135, 0x6136, 0x6137, 0x6139, 0x6141, - 0x6145, 0x6146, 0x6149, 0x615E, 0x6160, 0x616C, 0x6172, 0x6178, - 0x617B, 0x617C, 0x617F, 0x6180, 0x6181, 0x6183, 0x6184, 0x618B, - 0x618D, 0x6192, 0x6193, 0x6197, 0x6198, 0x619C, 0x619D, 0x619F, - 0x61A0, 0x61A5, 0x61A8, 0x61AA, 0x61AD, 0x61B8, 0x61B9, 0x61BC, - 0x61C0, 0x61C1, 0x61C2, 0x61CE, 0x61CF, 0x61D5, 0x61DC, 0x61DD, - 0x61DE, 0x61DF, 0x61E1, 0x61E2, 0x61E7, 0x61E9, 0x61E5, -}; -static const unsigned short euc_to_utf8_8FBF[] = { - 0x61EC, 0x61ED, 0x61EF, 0x6201, 0x6203, 0x6204, 0x6207, - 0x6213, 0x6215, 0x621C, 0x6220, 0x6222, 0x6223, 0x6227, 0x6229, - 0x622B, 0x6239, 0x623D, 0x6242, 0x6243, 0x6244, 0x6246, 0x624C, - 0x6250, 0x6251, 0x6252, 0x6254, 0x6256, 0x625A, 0x625C, 0x6264, - 0x626D, 0x626F, 0x6273, 0x627A, 0x627D, 0x628D, 0x628E, 0x628F, - 0x6290, 0x62A6, 0x62A8, 0x62B3, 0x62B6, 0x62B7, 0x62BA, 0x62BE, - 0x62BF, 0x62C4, 0x62CE, 0x62D5, 0x62D6, 0x62DA, 0x62EA, 0x62F2, - 0x62F4, 0x62FC, 0x62FD, 0x6303, 0x6304, 0x630A, 0x630B, 0x630D, - 0x6310, 0x6313, 0x6316, 0x6318, 0x6329, 0x632A, 0x632D, 0x6335, - 0x6336, 0x6339, 0x633C, 0x6341, 0x6342, 0x6343, 0x6344, 0x6346, - 0x634A, 0x634B, 0x634E, 0x6352, 0x6353, 0x6354, 0x6358, 0x635B, - 0x6365, 0x6366, 0x636C, 0x636D, 0x6371, 0x6374, 0x6375, -}; -static const unsigned short euc_to_utf8_8FC0[] = { - 0x6378, 0x637C, 0x637D, 0x637F, 0x6382, 0x6384, 0x6387, - 0x638A, 0x6390, 0x6394, 0x6395, 0x6399, 0x639A, 0x639E, 0x63A4, - 0x63A6, 0x63AD, 0x63AE, 0x63AF, 0x63BD, 0x63C1, 0x63C5, 0x63C8, - 0x63CE, 0x63D1, 0x63D3, 0x63D4, 0x63D5, 0x63DC, 0x63E0, 0x63E5, - 0x63EA, 0x63EC, 0x63F2, 0x63F3, 0x63F5, 0x63F8, 0x63F9, 0x6409, - 0x640A, 0x6410, 0x6412, 0x6414, 0x6418, 0x641E, 0x6420, 0x6422, - 0x6424, 0x6425, 0x6429, 0x642A, 0x642F, 0x6430, 0x6435, 0x643D, - 0x643F, 0x644B, 0x644F, 0x6451, 0x6452, 0x6453, 0x6454, 0x645A, - 0x645B, 0x645C, 0x645D, 0x645F, 0x6460, 0x6461, 0x6463, 0x646D, - 0x6473, 0x6474, 0x647B, 0x647D, 0x6485, 0x6487, 0x648F, 0x6490, - 0x6491, 0x6498, 0x6499, 0x649B, 0x649D, 0x649F, 0x64A1, 0x64A3, - 0x64A6, 0x64A8, 0x64AC, 0x64B3, 0x64BD, 0x64BE, 0x64BF, -}; -static const unsigned short euc_to_utf8_8FC1[] = { - 0x64C4, 0x64C9, 0x64CA, 0x64CB, 0x64CC, 0x64CE, 0x64D0, - 0x64D1, 0x64D5, 0x64D7, 0x64E4, 0x64E5, 0x64E9, 0x64EA, 0x64ED, - 0x64F0, 0x64F5, 0x64F7, 0x64FB, 0x64FF, 0x6501, 0x6504, 0x6508, - 0x6509, 0x650A, 0x650F, 0x6513, 0x6514, 0x6516, 0x6519, 0x651B, - 0x651E, 0x651F, 0x6522, 0x6526, 0x6529, 0x652E, 0x6531, 0x653A, - 0x653C, 0x653D, 0x6543, 0x6547, 0x6549, 0x6550, 0x6552, 0x6554, - 0x655F, 0x6560, 0x6567, 0x656B, 0x657A, 0x657D, 0x6581, 0x6585, - 0x658A, 0x6592, 0x6595, 0x6598, 0x659D, 0x65A0, 0x65A3, 0x65A6, - 0x65AE, 0x65B2, 0x65B3, 0x65B4, 0x65BF, 0x65C2, 0x65C8, 0x65C9, - 0x65CE, 0x65D0, 0x65D4, 0x65D6, 0x65D8, 0x65DF, 0x65F0, 0x65F2, - 0x65F4, 0x65F5, 0x65F9, 0x65FE, 0x65FF, 0x6600, 0x6604, 0x6608, - 0x6609, 0x660D, 0x6611, 0x6612, 0x6615, 0x6616, 0x661D, -}; -static const unsigned short euc_to_utf8_8FC2[] = { - 0x661E, 0x6621, 0x6622, 0x6623, 0x6624, 0x6626, 0x6629, - 0x662A, 0x662B, 0x662C, 0x662E, 0x6630, 0x6631, 0x6633, 0x6639, - 0x6637, 0x6640, 0x6645, 0x6646, 0x664A, 0x664C, 0x6651, 0x664E, - 0x6657, 0x6658, 0x6659, 0x665B, 0x665C, 0x6660, 0x6661, 0x66FB, - 0x666A, 0x666B, 0x666C, 0x667E, 0x6673, 0x6675, 0x667F, 0x6677, - 0x6678, 0x6679, 0x667B, 0x6680, 0x667C, 0x668B, 0x668C, 0x668D, - 0x6690, 0x6692, 0x6699, 0x669A, 0x669B, 0x669C, 0x669F, 0x66A0, - 0x66A4, 0x66AD, 0x66B1, 0x66B2, 0x66B5, 0x66BB, 0x66BF, 0x66C0, - 0x66C2, 0x66C3, 0x66C8, 0x66CC, 0x66CE, 0x66CF, 0x66D4, 0x66DB, - 0x66DF, 0x66E8, 0x66EB, 0x66EC, 0x66EE, 0x66FA, 0x6705, 0x6707, - 0x670E, 0x6713, 0x6719, 0x671C, 0x6720, 0x6722, 0x6733, 0x673E, - 0x6745, 0x6747, 0x6748, 0x674C, 0x6754, 0x6755, 0x675D, -}; -static const unsigned short euc_to_utf8_8FC3[] = { - 0x6766, 0x676C, 0x676E, 0x6774, 0x6776, 0x677B, 0x6781, - 0x6784, 0x678E, 0x678F, 0x6791, 0x6793, 0x6796, 0x6798, 0x6799, - 0x679B, 0x67B0, 0x67B1, 0x67B2, 0x67B5, 0x67BB, 0x67BC, 0x67BD, - 0x67F9, 0x67C0, 0x67C2, 0x67C3, 0x67C5, 0x67C8, 0x67C9, 0x67D2, - 0x67D7, 0x67D9, 0x67DC, 0x67E1, 0x67E6, 0x67F0, 0x67F2, 0x67F6, - 0x67F7, 0x6852, 0x6814, 0x6819, 0x681D, 0x681F, 0x6828, 0x6827, - 0x682C, 0x682D, 0x682F, 0x6830, 0x6831, 0x6833, 0x683B, 0x683F, - 0x6844, 0x6845, 0x684A, 0x684C, 0x6855, 0x6857, 0x6858, 0x685B, - 0x686B, 0x686E, 0x686F, 0x6870, 0x6871, 0x6872, 0x6875, 0x6879, - 0x687A, 0x687B, 0x687C, 0x6882, 0x6884, 0x6886, 0x6888, 0x6896, - 0x6898, 0x689A, 0x689C, 0x68A1, 0x68A3, 0x68A5, 0x68A9, 0x68AA, - 0x68AE, 0x68B2, 0x68BB, 0x68C5, 0x68C8, 0x68CC, 0x68CF, -}; -static const unsigned short euc_to_utf8_8FC4[] = { - 0x68D0, 0x68D1, 0x68D3, 0x68D6, 0x68D9, 0x68DC, 0x68DD, - 0x68E5, 0x68E8, 0x68EA, 0x68EB, 0x68EC, 0x68ED, 0x68F0, 0x68F1, - 0x68F5, 0x68F6, 0x68FB, 0x68FC, 0x68FD, 0x6906, 0x6909, 0x690A, - 0x6910, 0x6911, 0x6913, 0x6916, 0x6917, 0x6931, 0x6933, 0x6935, - 0x6938, 0x693B, 0x6942, 0x6945, 0x6949, 0x694E, 0x6957, 0x695B, - 0x6963, 0x6964, 0x6965, 0x6966, 0x6968, 0x6969, 0x696C, 0x6970, - 0x6971, 0x6972, 0x697A, 0x697B, 0x697F, 0x6980, 0x698D, 0x6992, - 0x6996, 0x6998, 0x69A1, 0x69A5, 0x69A6, 0x69A8, 0x69AB, 0x69AD, - 0x69AF, 0x69B7, 0x69B8, 0x69BA, 0x69BC, 0x69C5, 0x69C8, 0x69D1, - 0x69D6, 0x69D7, 0x69E2, 0x69E5, 0x69EE, 0x69EF, 0x69F1, 0x69F3, - 0x69F5, 0x69FE, 0x6A00, 0x6A01, 0x6A03, 0x6A0F, 0x6A11, 0x6A15, - 0x6A1A, 0x6A1D, 0x6A20, 0x6A24, 0x6A28, 0x6A30, 0x6A32, -}; -static const unsigned short euc_to_utf8_8FC5[] = { - 0x6A34, 0x6A37, 0x6A3B, 0x6A3E, 0x6A3F, 0x6A45, 0x6A46, - 0x6A49, 0x6A4A, 0x6A4E, 0x6A50, 0x6A51, 0x6A52, 0x6A55, 0x6A56, - 0x6A5B, 0x6A64, 0x6A67, 0x6A6A, 0x6A71, 0x6A73, 0x6A7E, 0x6A81, - 0x6A83, 0x6A86, 0x6A87, 0x6A89, 0x6A8B, 0x6A91, 0x6A9B, 0x6A9D, - 0x6A9E, 0x6A9F, 0x6AA5, 0x6AAB, 0x6AAF, 0x6AB0, 0x6AB1, 0x6AB4, - 0x6ABD, 0x6ABE, 0x6ABF, 0x6AC6, 0x6AC9, 0x6AC8, 0x6ACC, 0x6AD0, - 0x6AD4, 0x6AD5, 0x6AD6, 0x6ADC, 0x6ADD, 0x6AE4, 0x6AE7, 0x6AEC, - 0x6AF0, 0x6AF1, 0x6AF2, 0x6AFC, 0x6AFD, 0x6B02, 0x6B03, 0x6B06, - 0x6B07, 0x6B09, 0x6B0F, 0x6B10, 0x6B11, 0x6B17, 0x6B1B, 0x6B1E, - 0x6B24, 0x6B28, 0x6B2B, 0x6B2C, 0x6B2F, 0x6B35, 0x6B36, 0x6B3B, - 0x6B3F, 0x6B46, 0x6B4A, 0x6B4D, 0x6B52, 0x6B56, 0x6B58, 0x6B5D, - 0x6B60, 0x6B67, 0x6B6B, 0x6B6E, 0x6B70, 0x6B75, 0x6B7D, -}; -static const unsigned short euc_to_utf8_8FC6[] = { - 0x6B7E, 0x6B82, 0x6B85, 0x6B97, 0x6B9B, 0x6B9F, 0x6BA0, - 0x6BA2, 0x6BA3, 0x6BA8, 0x6BA9, 0x6BAC, 0x6BAD, 0x6BAE, 0x6BB0, - 0x6BB8, 0x6BB9, 0x6BBD, 0x6BBE, 0x6BC3, 0x6BC4, 0x6BC9, 0x6BCC, - 0x6BD6, 0x6BDA, 0x6BE1, 0x6BE3, 0x6BE6, 0x6BE7, 0x6BEE, 0x6BF1, - 0x6BF7, 0x6BF9, 0x6BFF, 0x6C02, 0x6C04, 0x6C05, 0x6C09, 0x6C0D, - 0x6C0E, 0x6C10, 0x6C12, 0x6C19, 0x6C1F, 0x6C26, 0x6C27, 0x6C28, - 0x6C2C, 0x6C2E, 0x6C33, 0x6C35, 0x6C36, 0x6C3A, 0x6C3B, 0x6C3F, - 0x6C4A, 0x6C4B, 0x6C4D, 0x6C4F, 0x6C52, 0x6C54, 0x6C59, 0x6C5B, - 0x6C5C, 0x6C6B, 0x6C6D, 0x6C6F, 0x6C74, 0x6C76, 0x6C78, 0x6C79, - 0x6C7B, 0x6C85, 0x6C86, 0x6C87, 0x6C89, 0x6C94, 0x6C95, 0x6C97, - 0x6C98, 0x6C9C, 0x6C9F, 0x6CB0, 0x6CB2, 0x6CB4, 0x6CC2, 0x6CC6, - 0x6CCD, 0x6CCF, 0x6CD0, 0x6CD1, 0x6CD2, 0x6CD4, 0x6CD6, -}; -static const unsigned short euc_to_utf8_8FC7[] = { - 0x6CDA, 0x6CDC, 0x6CE0, 0x6CE7, 0x6CE9, 0x6CEB, 0x6CEC, - 0x6CEE, 0x6CF2, 0x6CF4, 0x6D04, 0x6D07, 0x6D0A, 0x6D0E, 0x6D0F, - 0x6D11, 0x6D13, 0x6D1A, 0x6D26, 0x6D27, 0x6D28, 0x6C67, 0x6D2E, - 0x6D2F, 0x6D31, 0x6D39, 0x6D3C, 0x6D3F, 0x6D57, 0x6D5E, 0x6D5F, - 0x6D61, 0x6D65, 0x6D67, 0x6D6F, 0x6D70, 0x6D7C, 0x6D82, 0x6D87, - 0x6D91, 0x6D92, 0x6D94, 0x6D96, 0x6D97, 0x6D98, 0x6DAA, 0x6DAC, - 0x6DB4, 0x6DB7, 0x6DB9, 0x6DBD, 0x6DBF, 0x6DC4, 0x6DC8, 0x6DCA, - 0x6DCE, 0x6DCF, 0x6DD6, 0x6DDB, 0x6DDD, 0x6DDF, 0x6DE0, 0x6DE2, - 0x6DE5, 0x6DE9, 0x6DEF, 0x6DF0, 0x6DF4, 0x6DF6, 0x6DFC, 0x6E00, - 0x6E04, 0x6E1E, 0x6E22, 0x6E27, 0x6E32, 0x6E36, 0x6E39, 0x6E3B, - 0x6E3C, 0x6E44, 0x6E45, 0x6E48, 0x6E49, 0x6E4B, 0x6E4F, 0x6E51, - 0x6E52, 0x6E53, 0x6E54, 0x6E57, 0x6E5C, 0x6E5D, 0x6E5E, -}; -static const unsigned short euc_to_utf8_8FC8[] = { - 0x6E62, 0x6E63, 0x6E68, 0x6E73, 0x6E7B, 0x6E7D, 0x6E8D, - 0x6E93, 0x6E99, 0x6EA0, 0x6EA7, 0x6EAD, 0x6EAE, 0x6EB1, 0x6EB3, - 0x6EBB, 0x6EBF, 0x6EC0, 0x6EC1, 0x6EC3, 0x6EC7, 0x6EC8, 0x6ECA, - 0x6ECD, 0x6ECE, 0x6ECF, 0x6EEB, 0x6EED, 0x6EEE, 0x6EF9, 0x6EFB, - 0x6EFD, 0x6F04, 0x6F08, 0x6F0A, 0x6F0C, 0x6F0D, 0x6F16, 0x6F18, - 0x6F1A, 0x6F1B, 0x6F26, 0x6F29, 0x6F2A, 0x6F2F, 0x6F30, 0x6F33, - 0x6F36, 0x6F3B, 0x6F3C, 0x6F2D, 0x6F4F, 0x6F51, 0x6F52, 0x6F53, - 0x6F57, 0x6F59, 0x6F5A, 0x6F5D, 0x6F5E, 0x6F61, 0x6F62, 0x6F68, - 0x6F6C, 0x6F7D, 0x6F7E, 0x6F83, 0x6F87, 0x6F88, 0x6F8B, 0x6F8C, - 0x6F8D, 0x6F90, 0x6F92, 0x6F93, 0x6F94, 0x6F96, 0x6F9A, 0x6F9F, - 0x6FA0, 0x6FA5, 0x6FA6, 0x6FA7, 0x6FA8, 0x6FAE, 0x6FAF, 0x6FB0, - 0x6FB5, 0x6FB6, 0x6FBC, 0x6FC5, 0x6FC7, 0x6FC8, 0x6FCA, -}; -static const unsigned short euc_to_utf8_8FC9[] = { - 0x6FDA, 0x6FDE, 0x6FE8, 0x6FE9, 0x6FF0, 0x6FF5, 0x6FF9, - 0x6FFC, 0x6FFD, 0x7000, 0x7005, 0x7006, 0x7007, 0x700D, 0x7017, - 0x7020, 0x7023, 0x702F, 0x7034, 0x7037, 0x7039, 0x703C, 0x7043, - 0x7044, 0x7048, 0x7049, 0x704A, 0x704B, 0x7054, 0x7055, 0x705D, - 0x705E, 0x704E, 0x7064, 0x7065, 0x706C, 0x706E, 0x7075, 0x7076, - 0x707E, 0x7081, 0x7085, 0x7086, 0x7094, 0x7095, 0x7096, 0x7097, - 0x7098, 0x709B, 0x70A4, 0x70AB, 0x70B0, 0x70B1, 0x70B4, 0x70B7, - 0x70CA, 0x70D1, 0x70D3, 0x70D4, 0x70D5, 0x70D6, 0x70D8, 0x70DC, - 0x70E4, 0x70FA, 0x7103, 0x7104, 0x7105, 0x7106, 0x7107, 0x710B, - 0x710C, 0x710F, 0x711E, 0x7120, 0x712B, 0x712D, 0x712F, 0x7130, - 0x7131, 0x7138, 0x7141, 0x7145, 0x7146, 0x7147, 0x714A, 0x714B, - 0x7150, 0x7152, 0x7157, 0x715A, 0x715C, 0x715E, 0x7160, -}; -static const unsigned short euc_to_utf8_8FCA[] = { - 0x7168, 0x7179, 0x7180, 0x7185, 0x7187, 0x718C, 0x7192, - 0x719A, 0x719B, 0x71A0, 0x71A2, 0x71AF, 0x71B0, 0x71B2, 0x71B3, - 0x71BA, 0x71BF, 0x71C0, 0x71C1, 0x71C4, 0x71CB, 0x71CC, 0x71D3, - 0x71D6, 0x71D9, 0x71DA, 0x71DC, 0x71F8, 0x71FE, 0x7200, 0x7207, - 0x7208, 0x7209, 0x7213, 0x7217, 0x721A, 0x721D, 0x721F, 0x7224, - 0x722B, 0x722F, 0x7234, 0x7238, 0x7239, 0x7241, 0x7242, 0x7243, - 0x7245, 0x724E, 0x724F, 0x7250, 0x7253, 0x7255, 0x7256, 0x725A, - 0x725C, 0x725E, 0x7260, 0x7263, 0x7268, 0x726B, 0x726E, 0x726F, - 0x7271, 0x7277, 0x7278, 0x727B, 0x727C, 0x727F, 0x7284, 0x7289, - 0x728D, 0x728E, 0x7293, 0x729B, 0x72A8, 0x72AD, 0x72AE, 0x72B1, - 0x72B4, 0x72BE, 0x72C1, 0x72C7, 0x72C9, 0x72CC, 0x72D5, 0x72D6, - 0x72D8, 0x72DF, 0x72E5, 0x72F3, 0x72F4, 0x72FA, 0x72FB, -}; -static const unsigned short euc_to_utf8_8FCB[] = { - 0x72FE, 0x7302, 0x7304, 0x7305, 0x7307, 0x730B, 0x730D, - 0x7312, 0x7313, 0x7318, 0x7319, 0x731E, 0x7322, 0x7324, 0x7327, - 0x7328, 0x732C, 0x7331, 0x7332, 0x7335, 0x733A, 0x733B, 0x733D, - 0x7343, 0x734D, 0x7350, 0x7352, 0x7356, 0x7358, 0x735D, 0x735E, - 0x735F, 0x7360, 0x7366, 0x7367, 0x7369, 0x736B, 0x736C, 0x736E, - 0x736F, 0x7371, 0x7377, 0x7379, 0x737C, 0x7380, 0x7381, 0x7383, - 0x7385, 0x7386, 0x738E, 0x7390, 0x7393, 0x7395, 0x7397, 0x7398, - 0x739C, 0x739E, 0x739F, 0x73A0, 0x73A2, 0x73A5, 0x73A6, 0x73AA, - 0x73AB, 0x73AD, 0x73B5, 0x73B7, 0x73B9, 0x73BC, 0x73BD, 0x73BF, - 0x73C5, 0x73C6, 0x73C9, 0x73CB, 0x73CC, 0x73CF, 0x73D2, 0x73D3, - 0x73D6, 0x73D9, 0x73DD, 0x73E1, 0x73E3, 0x73E6, 0x73E7, 0x73E9, - 0x73F4, 0x73F5, 0x73F7, 0x73F9, 0x73FA, 0x73FB, 0x73FD, -}; -static const unsigned short euc_to_utf8_8FCC[] = { - 0x73FF, 0x7400, 0x7401, 0x7404, 0x7407, 0x740A, 0x7411, - 0x741A, 0x741B, 0x7424, 0x7426, 0x7428, 0x7429, 0x742A, 0x742B, - 0x742C, 0x742D, 0x742E, 0x742F, 0x7430, 0x7431, 0x7439, 0x7440, - 0x7443, 0x7444, 0x7446, 0x7447, 0x744B, 0x744D, 0x7451, 0x7452, - 0x7457, 0x745D, 0x7462, 0x7466, 0x7467, 0x7468, 0x746B, 0x746D, - 0x746E, 0x7471, 0x7472, 0x7480, 0x7481, 0x7485, 0x7486, 0x7487, - 0x7489, 0x748F, 0x7490, 0x7491, 0x7492, 0x7498, 0x7499, 0x749A, - 0x749C, 0x749F, 0x74A0, 0x74A1, 0x74A3, 0x74A6, 0x74A8, 0x74A9, - 0x74AA, 0x74AB, 0x74AE, 0x74AF, 0x74B1, 0x74B2, 0x74B5, 0x74B9, - 0x74BB, 0x74BF, 0x74C8, 0x74C9, 0x74CC, 0x74D0, 0x74D3, 0x74D8, - 0x74DA, 0x74DB, 0x74DE, 0x74DF, 0x74E4, 0x74E8, 0x74EA, 0x74EB, - 0x74EF, 0x74F4, 0x74FA, 0x74FB, 0x74FC, 0x74FF, 0x7506, -}; -static const unsigned short euc_to_utf8_8FCD[] = { - 0x7512, 0x7516, 0x7517, 0x7520, 0x7521, 0x7524, 0x7527, - 0x7529, 0x752A, 0x752F, 0x7536, 0x7539, 0x753D, 0x753E, 0x753F, - 0x7540, 0x7543, 0x7547, 0x7548, 0x754E, 0x7550, 0x7552, 0x7557, - 0x755E, 0x755F, 0x7561, 0x756F, 0x7571, 0x7579, 0x757A, 0x757B, - 0x757C, 0x757D, 0x757E, 0x7581, 0x7585, 0x7590, 0x7592, 0x7593, - 0x7595, 0x7599, 0x759C, 0x75A2, 0x75A4, 0x75B4, 0x75BA, 0x75BF, - 0x75C0, 0x75C1, 0x75C4, 0x75C6, 0x75CC, 0x75CE, 0x75CF, 0x75D7, - 0x75DC, 0x75DF, 0x75E0, 0x75E1, 0x75E4, 0x75E7, 0x75EC, 0x75EE, - 0x75EF, 0x75F1, 0x75F9, 0x7600, 0x7602, 0x7603, 0x7604, 0x7607, - 0x7608, 0x760A, 0x760C, 0x760F, 0x7612, 0x7613, 0x7615, 0x7616, - 0x7619, 0x761B, 0x761C, 0x761D, 0x761E, 0x7623, 0x7625, 0x7626, - 0x7629, 0x762D, 0x7632, 0x7633, 0x7635, 0x7638, 0x7639, -}; -static const unsigned short euc_to_utf8_8FCE[] = { - 0x763A, 0x763C, 0x764A, 0x7640, 0x7641, 0x7643, 0x7644, - 0x7645, 0x7649, 0x764B, 0x7655, 0x7659, 0x765F, 0x7664, 0x7665, - 0x766D, 0x766E, 0x766F, 0x7671, 0x7674, 0x7681, 0x7685, 0x768C, - 0x768D, 0x7695, 0x769B, 0x769C, 0x769D, 0x769F, 0x76A0, 0x76A2, - 0x76A3, 0x76A4, 0x76A5, 0x76A6, 0x76A7, 0x76A8, 0x76AA, 0x76AD, - 0x76BD, 0x76C1, 0x76C5, 0x76C9, 0x76CB, 0x76CC, 0x76CE, 0x76D4, - 0x76D9, 0x76E0, 0x76E6, 0x76E8, 0x76EC, 0x76F0, 0x76F1, 0x76F6, - 0x76F9, 0x76FC, 0x7700, 0x7706, 0x770A, 0x770E, 0x7712, 0x7714, - 0x7715, 0x7717, 0x7719, 0x771A, 0x771C, 0x7722, 0x7728, 0x772D, - 0x772E, 0x772F, 0x7734, 0x7735, 0x7736, 0x7739, 0x773D, 0x773E, - 0x7742, 0x7745, 0x7746, 0x774A, 0x774D, 0x774E, 0x774F, 0x7752, - 0x7756, 0x7757, 0x775C, 0x775E, 0x775F, 0x7760, 0x7762, -}; -static const unsigned short euc_to_utf8_8FCF[] = { - 0x7764, 0x7767, 0x776A, 0x776C, 0x7770, 0x7772, 0x7773, - 0x7774, 0x777A, 0x777D, 0x7780, 0x7784, 0x778C, 0x778D, 0x7794, - 0x7795, 0x7796, 0x779A, 0x779F, 0x77A2, 0x77A7, 0x77AA, 0x77AE, - 0x77AF, 0x77B1, 0x77B5, 0x77BE, 0x77C3, 0x77C9, 0x77D1, 0x77D2, - 0x77D5, 0x77D9, 0x77DE, 0x77DF, 0x77E0, 0x77E4, 0x77E6, 0x77EA, - 0x77EC, 0x77F0, 0x77F1, 0x77F4, 0x77F8, 0x77FB, 0x7805, 0x7806, - 0x7809, 0x780D, 0x780E, 0x7811, 0x781D, 0x7821, 0x7822, 0x7823, - 0x782D, 0x782E, 0x7830, 0x7835, 0x7837, 0x7843, 0x7844, 0x7847, - 0x7848, 0x784C, 0x784E, 0x7852, 0x785C, 0x785E, 0x7860, 0x7861, - 0x7863, 0x7864, 0x7868, 0x786A, 0x786E, 0x787A, 0x787E, 0x788A, - 0x788F, 0x7894, 0x7898, 0x78A1, 0x789D, 0x789E, 0x789F, 0x78A4, - 0x78A8, 0x78AC, 0x78AD, 0x78B0, 0x78B1, 0x78B2, 0x78B3, -}; -static const unsigned short euc_to_utf8_8FD0[] = { - 0x78BB, 0x78BD, 0x78BF, 0x78C7, 0x78C8, 0x78C9, 0x78CC, - 0x78CE, 0x78D2, 0x78D3, 0x78D5, 0x78D6, 0x78E4, 0x78DB, 0x78DF, - 0x78E0, 0x78E1, 0x78E6, 0x78EA, 0x78F2, 0x78F3, 0x7900, 0x78F6, - 0x78F7, 0x78FA, 0x78FB, 0x78FF, 0x7906, 0x790C, 0x7910, 0x791A, - 0x791C, 0x791E, 0x791F, 0x7920, 0x7925, 0x7927, 0x7929, 0x792D, - 0x7931, 0x7934, 0x7935, 0x793B, 0x793D, 0x793F, 0x7944, 0x7945, - 0x7946, 0x794A, 0x794B, 0x794F, 0x7951, 0x7954, 0x7958, 0x795B, - 0x795C, 0x7967, 0x7969, 0x796B, 0x7972, 0x7979, 0x797B, 0x797C, - 0x797E, 0x798B, 0x798C, 0x7991, 0x7993, 0x7994, 0x7995, 0x7996, - 0x7998, 0x799B, 0x799C, 0x79A1, 0x79A8, 0x79A9, 0x79AB, 0x79AF, - 0x79B1, 0x79B4, 0x79B8, 0x79BB, 0x79C2, 0x79C4, 0x79C7, 0x79C8, - 0x79CA, 0x79CF, 0x79D4, 0x79D6, 0x79DA, 0x79DD, 0x79DE, -}; -static const unsigned short euc_to_utf8_8FD1[] = { - 0x79E0, 0x79E2, 0x79E5, 0x79EA, 0x79EB, 0x79ED, 0x79F1, - 0x79F8, 0x79FC, 0x7A02, 0x7A03, 0x7A07, 0x7A09, 0x7A0A, 0x7A0C, - 0x7A11, 0x7A15, 0x7A1B, 0x7A1E, 0x7A21, 0x7A27, 0x7A2B, 0x7A2D, - 0x7A2F, 0x7A30, 0x7A34, 0x7A35, 0x7A38, 0x7A39, 0x7A3A, 0x7A44, - 0x7A45, 0x7A47, 0x7A48, 0x7A4C, 0x7A55, 0x7A56, 0x7A59, 0x7A5C, - 0x7A5D, 0x7A5F, 0x7A60, 0x7A65, 0x7A67, 0x7A6A, 0x7A6D, 0x7A75, - 0x7A78, 0x7A7E, 0x7A80, 0x7A82, 0x7A85, 0x7A86, 0x7A8A, 0x7A8B, - 0x7A90, 0x7A91, 0x7A94, 0x7A9E, 0x7AA0, 0x7AA3, 0x7AAC, 0x7AB3, - 0x7AB5, 0x7AB9, 0x7ABB, 0x7ABC, 0x7AC6, 0x7AC9, 0x7ACC, 0x7ACE, - 0x7AD1, 0x7ADB, 0x7AE8, 0x7AE9, 0x7AEB, 0x7AEC, 0x7AF1, 0x7AF4, - 0x7AFB, 0x7AFD, 0x7AFE, 0x7B07, 0x7B14, 0x7B1F, 0x7B23, 0x7B27, - 0x7B29, 0x7B2A, 0x7B2B, 0x7B2D, 0x7B2E, 0x7B2F, 0x7B30, -}; -static const unsigned short euc_to_utf8_8FD2[] = { - 0x7B31, 0x7B34, 0x7B3D, 0x7B3F, 0x7B40, 0x7B41, 0x7B47, - 0x7B4E, 0x7B55, 0x7B60, 0x7B64, 0x7B66, 0x7B69, 0x7B6A, 0x7B6D, - 0x7B6F, 0x7B72, 0x7B73, 0x7B77, 0x7B84, 0x7B89, 0x7B8E, 0x7B90, - 0x7B91, 0x7B96, 0x7B9B, 0x7B9E, 0x7BA0, 0x7BA5, 0x7BAC, 0x7BAF, - 0x7BB0, 0x7BB2, 0x7BB5, 0x7BB6, 0x7BBA, 0x7BBB, 0x7BBC, 0x7BBD, - 0x7BC2, 0x7BC5, 0x7BC8, 0x7BCA, 0x7BD4, 0x7BD6, 0x7BD7, 0x7BD9, - 0x7BDA, 0x7BDB, 0x7BE8, 0x7BEA, 0x7BF2, 0x7BF4, 0x7BF5, 0x7BF8, - 0x7BF9, 0x7BFA, 0x7BFC, 0x7BFE, 0x7C01, 0x7C02, 0x7C03, 0x7C04, - 0x7C06, 0x7C09, 0x7C0B, 0x7C0C, 0x7C0E, 0x7C0F, 0x7C19, 0x7C1B, - 0x7C20, 0x7C25, 0x7C26, 0x7C28, 0x7C2C, 0x7C31, 0x7C33, 0x7C34, - 0x7C36, 0x7C39, 0x7C3A, 0x7C46, 0x7C4A, 0x7C55, 0x7C51, 0x7C52, - 0x7C53, 0x7C59, 0x7C5A, 0x7C5B, 0x7C5C, 0x7C5D, 0x7C5E, -}; -static const unsigned short euc_to_utf8_8FD3[] = { - 0x7C61, 0x7C63, 0x7C67, 0x7C69, 0x7C6D, 0x7C6E, 0x7C70, - 0x7C72, 0x7C79, 0x7C7C, 0x7C7D, 0x7C86, 0x7C87, 0x7C8F, 0x7C94, - 0x7C9E, 0x7CA0, 0x7CA6, 0x7CB0, 0x7CB6, 0x7CB7, 0x7CBA, 0x7CBB, - 0x7CBC, 0x7CBF, 0x7CC4, 0x7CC7, 0x7CC8, 0x7CC9, 0x7CCD, 0x7CCF, - 0x7CD3, 0x7CD4, 0x7CD5, 0x7CD7, 0x7CD9, 0x7CDA, 0x7CDD, 0x7CE6, - 0x7CE9, 0x7CEB, 0x7CF5, 0x7D03, 0x7D07, 0x7D08, 0x7D09, 0x7D0F, - 0x7D11, 0x7D12, 0x7D13, 0x7D16, 0x7D1D, 0x7D1E, 0x7D23, 0x7D26, - 0x7D2A, 0x7D2D, 0x7D31, 0x7D3C, 0x7D3D, 0x7D3E, 0x7D40, 0x7D41, - 0x7D47, 0x7D48, 0x7D4D, 0x7D51, 0x7D53, 0x7D57, 0x7D59, 0x7D5A, - 0x7D5C, 0x7D5D, 0x7D65, 0x7D67, 0x7D6A, 0x7D70, 0x7D78, 0x7D7A, - 0x7D7B, 0x7D7F, 0x7D81, 0x7D82, 0x7D83, 0x7D85, 0x7D86, 0x7D88, - 0x7D8B, 0x7D8C, 0x7D8D, 0x7D91, 0x7D96, 0x7D97, 0x7D9D, -}; -static const unsigned short euc_to_utf8_8FD4[] = { - 0x7D9E, 0x7DA6, 0x7DA7, 0x7DAA, 0x7DB3, 0x7DB6, 0x7DB7, - 0x7DB9, 0x7DC2, 0x7DC3, 0x7DC4, 0x7DC5, 0x7DC6, 0x7DCC, 0x7DCD, - 0x7DCE, 0x7DD7, 0x7DD9, 0x7E00, 0x7DE2, 0x7DE5, 0x7DE6, 0x7DEA, - 0x7DEB, 0x7DED, 0x7DF1, 0x7DF5, 0x7DF6, 0x7DF9, 0x7DFA, 0x7E08, - 0x7E10, 0x7E11, 0x7E15, 0x7E17, 0x7E1C, 0x7E1D, 0x7E20, 0x7E27, - 0x7E28, 0x7E2C, 0x7E2D, 0x7E2F, 0x7E33, 0x7E36, 0x7E3F, 0x7E44, - 0x7E45, 0x7E47, 0x7E4E, 0x7E50, 0x7E52, 0x7E58, 0x7E5F, 0x7E61, - 0x7E62, 0x7E65, 0x7E6B, 0x7E6E, 0x7E6F, 0x7E73, 0x7E78, 0x7E7E, - 0x7E81, 0x7E86, 0x7E87, 0x7E8A, 0x7E8D, 0x7E91, 0x7E95, 0x7E98, - 0x7E9A, 0x7E9D, 0x7E9E, 0x7F3C, 0x7F3B, 0x7F3D, 0x7F3E, 0x7F3F, - 0x7F43, 0x7F44, 0x7F47, 0x7F4F, 0x7F52, 0x7F53, 0x7F5B, 0x7F5C, - 0x7F5D, 0x7F61, 0x7F63, 0x7F64, 0x7F65, 0x7F66, 0x7F6D, -}; -static const unsigned short euc_to_utf8_8FD5[] = { - 0x7F71, 0x7F7D, 0x7F7E, 0x7F7F, 0x7F80, 0x7F8B, 0x7F8D, - 0x7F8F, 0x7F90, 0x7F91, 0x7F96, 0x7F97, 0x7F9C, 0x7FA1, 0x7FA2, - 0x7FA6, 0x7FAA, 0x7FAD, 0x7FB4, 0x7FBC, 0x7FBF, 0x7FC0, 0x7FC3, - 0x7FC8, 0x7FCE, 0x7FCF, 0x7FDB, 0x7FDF, 0x7FE3, 0x7FE5, 0x7FE8, - 0x7FEC, 0x7FEE, 0x7FEF, 0x7FF2, 0x7FFA, 0x7FFD, 0x7FFE, 0x7FFF, - 0x8007, 0x8008, 0x800A, 0x800D, 0x800E, 0x800F, 0x8011, 0x8013, - 0x8014, 0x8016, 0x801D, 0x801E, 0x801F, 0x8020, 0x8024, 0x8026, - 0x802C, 0x802E, 0x8030, 0x8034, 0x8035, 0x8037, 0x8039, 0x803A, - 0x803C, 0x803E, 0x8040, 0x8044, 0x8060, 0x8064, 0x8066, 0x806D, - 0x8071, 0x8075, 0x8081, 0x8088, 0x808E, 0x809C, 0x809E, 0x80A6, - 0x80A7, 0x80AB, 0x80B8, 0x80B9, 0x80C8, 0x80CD, 0x80CF, 0x80D2, - 0x80D4, 0x80D5, 0x80D7, 0x80D8, 0x80E0, 0x80ED, 0x80EE, -}; -static const unsigned short euc_to_utf8_8FD6[] = { - 0x80F0, 0x80F2, 0x80F3, 0x80F6, 0x80F9, 0x80FA, 0x80FE, - 0x8103, 0x810B, 0x8116, 0x8117, 0x8118, 0x811C, 0x811E, 0x8120, - 0x8124, 0x8127, 0x812C, 0x8130, 0x8135, 0x813A, 0x813C, 0x8145, - 0x8147, 0x814A, 0x814C, 0x8152, 0x8157, 0x8160, 0x8161, 0x8167, - 0x8168, 0x8169, 0x816D, 0x816F, 0x8177, 0x8181, 0x8190, 0x8184, - 0x8185, 0x8186, 0x818B, 0x818E, 0x8196, 0x8198, 0x819B, 0x819E, - 0x81A2, 0x81AE, 0x81B2, 0x81B4, 0x81BB, 0x81CB, 0x81C3, 0x81C5, - 0x81CA, 0x81CE, 0x81CF, 0x81D5, 0x81D7, 0x81DB, 0x81DD, 0x81DE, - 0x81E1, 0x81E4, 0x81EB, 0x81EC, 0x81F0, 0x81F1, 0x81F2, 0x81F5, - 0x81F6, 0x81F8, 0x81F9, 0x81FD, 0x81FF, 0x8200, 0x8203, 0x820F, - 0x8213, 0x8214, 0x8219, 0x821A, 0x821D, 0x8221, 0x8222, 0x8228, - 0x8232, 0x8234, 0x823A, 0x8243, 0x8244, 0x8245, 0x8246, -}; -static const unsigned short euc_to_utf8_8FD7[] = { - 0x824B, 0x824E, 0x824F, 0x8251, 0x8256, 0x825C, 0x8260, - 0x8263, 0x8267, 0x826D, 0x8274, 0x827B, 0x827D, 0x827F, 0x8280, - 0x8281, 0x8283, 0x8284, 0x8287, 0x8289, 0x828A, 0x828E, 0x8291, - 0x8294, 0x8296, 0x8298, 0x829A, 0x829B, 0x82A0, 0x82A1, 0x82A3, - 0x82A4, 0x82A7, 0x82A8, 0x82A9, 0x82AA, 0x82AE, 0x82B0, 0x82B2, - 0x82B4, 0x82B7, 0x82BA, 0x82BC, 0x82BE, 0x82BF, 0x82C6, 0x82D0, - 0x82D5, 0x82DA, 0x82E0, 0x82E2, 0x82E4, 0x82E8, 0x82EA, 0x82ED, - 0x82EF, 0x82F6, 0x82F7, 0x82FD, 0x82FE, 0x8300, 0x8301, 0x8307, - 0x8308, 0x830A, 0x830B, 0x8354, 0x831B, 0x831D, 0x831E, 0x831F, - 0x8321, 0x8322, 0x832C, 0x832D, 0x832E, 0x8330, 0x8333, 0x8337, - 0x833A, 0x833C, 0x833D, 0x8342, 0x8343, 0x8344, 0x8347, 0x834D, - 0x834E, 0x8351, 0x8355, 0x8356, 0x8357, 0x8370, 0x8378, -}; -static const unsigned short euc_to_utf8_8FD8[] = { - 0x837D, 0x837F, 0x8380, 0x8382, 0x8384, 0x8386, 0x838D, - 0x8392, 0x8394, 0x8395, 0x8398, 0x8399, 0x839B, 0x839C, 0x839D, - 0x83A6, 0x83A7, 0x83A9, 0x83AC, 0x83BE, 0x83BF, 0x83C0, 0x83C7, - 0x83C9, 0x83CF, 0x83D0, 0x83D1, 0x83D4, 0x83DD, 0x8353, 0x83E8, - 0x83EA, 0x83F6, 0x83F8, 0x83F9, 0x83FC, 0x8401, 0x8406, 0x840A, - 0x840F, 0x8411, 0x8415, 0x8419, 0x83AD, 0x842F, 0x8439, 0x8445, - 0x8447, 0x8448, 0x844A, 0x844D, 0x844F, 0x8451, 0x8452, 0x8456, - 0x8458, 0x8459, 0x845A, 0x845C, 0x8460, 0x8464, 0x8465, 0x8467, - 0x846A, 0x8470, 0x8473, 0x8474, 0x8476, 0x8478, 0x847C, 0x847D, - 0x8481, 0x8485, 0x8492, 0x8493, 0x8495, 0x849E, 0x84A6, 0x84A8, - 0x84A9, 0x84AA, 0x84AF, 0x84B1, 0x84B4, 0x84BA, 0x84BD, 0x84BE, - 0x84C0, 0x84C2, 0x84C7, 0x84C8, 0x84CC, 0x84CF, 0x84D3, -}; -static const unsigned short euc_to_utf8_8FD9[] = { - 0x84DC, 0x84E7, 0x84EA, 0x84EF, 0x84F0, 0x84F1, 0x84F2, - 0x84F7, 0x8532, 0x84FA, 0x84FB, 0x84FD, 0x8502, 0x8503, 0x8507, - 0x850C, 0x850E, 0x8510, 0x851C, 0x851E, 0x8522, 0x8523, 0x8524, - 0x8525, 0x8527, 0x852A, 0x852B, 0x852F, 0x8533, 0x8534, 0x8536, - 0x853F, 0x8546, 0x854F, 0x8550, 0x8551, 0x8552, 0x8553, 0x8556, - 0x8559, 0x855C, 0x855D, 0x855E, 0x855F, 0x8560, 0x8561, 0x8562, - 0x8564, 0x856B, 0x856F, 0x8579, 0x857A, 0x857B, 0x857D, 0x857F, - 0x8581, 0x8585, 0x8586, 0x8589, 0x858B, 0x858C, 0x858F, 0x8593, - 0x8598, 0x859D, 0x859F, 0x85A0, 0x85A2, 0x85A5, 0x85A7, 0x85B4, - 0x85B6, 0x85B7, 0x85B8, 0x85BC, 0x85BD, 0x85BE, 0x85BF, 0x85C2, - 0x85C7, 0x85CA, 0x85CB, 0x85CE, 0x85AD, 0x85D8, 0x85DA, 0x85DF, - 0x85E0, 0x85E6, 0x85E8, 0x85ED, 0x85F3, 0x85F6, 0x85FC, -}; -static const unsigned short euc_to_utf8_8FDA[] = { - 0x85FF, 0x8600, 0x8604, 0x8605, 0x860D, 0x860E, 0x8610, - 0x8611, 0x8612, 0x8618, 0x8619, 0x861B, 0x861E, 0x8621, 0x8627, - 0x8629, 0x8636, 0x8638, 0x863A, 0x863C, 0x863D, 0x8640, 0x8642, - 0x8646, 0x8652, 0x8653, 0x8656, 0x8657, 0x8658, 0x8659, 0x865D, - 0x8660, 0x8661, 0x8662, 0x8663, 0x8664, 0x8669, 0x866C, 0x866F, - 0x8675, 0x8676, 0x8677, 0x867A, 0x868D, 0x8691, 0x8696, 0x8698, - 0x869A, 0x869C, 0x86A1, 0x86A6, 0x86A7, 0x86A8, 0x86AD, 0x86B1, - 0x86B3, 0x86B4, 0x86B5, 0x86B7, 0x86B8, 0x86B9, 0x86BF, 0x86C0, - 0x86C1, 0x86C3, 0x86C5, 0x86D1, 0x86D2, 0x86D5, 0x86D7, 0x86DA, - 0x86DC, 0x86E0, 0x86E3, 0x86E5, 0x86E7, 0x8688, 0x86FA, 0x86FC, - 0x86FD, 0x8704, 0x8705, 0x8707, 0x870B, 0x870E, 0x870F, 0x8710, - 0x8713, 0x8714, 0x8719, 0x871E, 0x871F, 0x8721, 0x8723, -}; -static const unsigned short euc_to_utf8_8FDB[] = { - 0x8728, 0x872E, 0x872F, 0x8731, 0x8732, 0x8739, 0x873A, - 0x873C, 0x873D, 0x873E, 0x8740, 0x8743, 0x8745, 0x874D, 0x8758, - 0x875D, 0x8761, 0x8764, 0x8765, 0x876F, 0x8771, 0x8772, 0x877B, - 0x8783, 0x8784, 0x8785, 0x8786, 0x8787, 0x8788, 0x8789, 0x878B, - 0x878C, 0x8790, 0x8793, 0x8795, 0x8797, 0x8798, 0x8799, 0x879E, - 0x87A0, 0x87A3, 0x87A7, 0x87AC, 0x87AD, 0x87AE, 0x87B1, 0x87B5, - 0x87BE, 0x87BF, 0x87C1, 0x87C8, 0x87C9, 0x87CA, 0x87CE, 0x87D5, - 0x87D6, 0x87D9, 0x87DA, 0x87DC, 0x87DF, 0x87E2, 0x87E3, 0x87E4, - 0x87EA, 0x87EB, 0x87ED, 0x87F1, 0x87F3, 0x87F8, 0x87FA, 0x87FF, - 0x8801, 0x8803, 0x8806, 0x8809, 0x880A, 0x880B, 0x8810, 0x8819, - 0x8812, 0x8813, 0x8814, 0x8818, 0x881A, 0x881B, 0x881C, 0x881E, - 0x881F, 0x8828, 0x882D, 0x882E, 0x8830, 0x8832, 0x8835, -}; -static const unsigned short euc_to_utf8_8FDC[] = { - 0x883A, 0x883C, 0x8841, 0x8843, 0x8845, 0x8848, 0x8849, - 0x884A, 0x884B, 0x884E, 0x8851, 0x8855, 0x8856, 0x8858, 0x885A, - 0x885C, 0x885F, 0x8860, 0x8864, 0x8869, 0x8871, 0x8879, 0x887B, - 0x8880, 0x8898, 0x889A, 0x889B, 0x889C, 0x889F, 0x88A0, 0x88A8, - 0x88AA, 0x88BA, 0x88BD, 0x88BE, 0x88C0, 0x88CA, 0x88CB, 0x88CC, - 0x88CD, 0x88CE, 0x88D1, 0x88D2, 0x88D3, 0x88DB, 0x88DE, 0x88E7, - 0x88EF, 0x88F0, 0x88F1, 0x88F5, 0x88F7, 0x8901, 0x8906, 0x890D, - 0x890E, 0x890F, 0x8915, 0x8916, 0x8918, 0x8919, 0x891A, 0x891C, - 0x8920, 0x8926, 0x8927, 0x8928, 0x8930, 0x8931, 0x8932, 0x8935, - 0x8939, 0x893A, 0x893E, 0x8940, 0x8942, 0x8945, 0x8946, 0x8949, - 0x894F, 0x8952, 0x8957, 0x895A, 0x895B, 0x895C, 0x8961, 0x8962, - 0x8963, 0x896B, 0x896E, 0x8970, 0x8973, 0x8975, 0x897A, -}; -static const unsigned short euc_to_utf8_8FDD[] = { - 0x897B, 0x897C, 0x897D, 0x8989, 0x898D, 0x8990, 0x8994, - 0x8995, 0x899B, 0x899C, 0x899F, 0x89A0, 0x89A5, 0x89B0, 0x89B4, - 0x89B5, 0x89B6, 0x89B7, 0x89BC, 0x89D4, 0x89D5, 0x89D6, 0x89D7, - 0x89D8, 0x89E5, 0x89E9, 0x89EB, 0x89ED, 0x89F1, 0x89F3, 0x89F6, - 0x89F9, 0x89FD, 0x89FF, 0x8A04, 0x8A05, 0x8A07, 0x8A0F, 0x8A11, - 0x8A12, 0x8A14, 0x8A15, 0x8A1E, 0x8A20, 0x8A22, 0x8A24, 0x8A26, - 0x8A2B, 0x8A2C, 0x8A2F, 0x8A35, 0x8A37, 0x8A3D, 0x8A3E, 0x8A40, - 0x8A43, 0x8A45, 0x8A47, 0x8A49, 0x8A4D, 0x8A4E, 0x8A53, 0x8A56, - 0x8A57, 0x8A58, 0x8A5C, 0x8A5D, 0x8A61, 0x8A65, 0x8A67, 0x8A75, - 0x8A76, 0x8A77, 0x8A79, 0x8A7A, 0x8A7B, 0x8A7E, 0x8A7F, 0x8A80, - 0x8A83, 0x8A86, 0x8A8B, 0x8A8F, 0x8A90, 0x8A92, 0x8A96, 0x8A97, - 0x8A99, 0x8A9F, 0x8AA7, 0x8AA9, 0x8AAE, 0x8AAF, 0x8AB3, -}; -static const unsigned short euc_to_utf8_8FDE[] = { - 0x8AB6, 0x8AB7, 0x8ABB, 0x8ABE, 0x8AC3, 0x8AC6, 0x8AC8, - 0x8AC9, 0x8ACA, 0x8AD1, 0x8AD3, 0x8AD4, 0x8AD5, 0x8AD7, 0x8ADD, - 0x8ADF, 0x8AEC, 0x8AF0, 0x8AF4, 0x8AF5, 0x8AF6, 0x8AFC, 0x8AFF, - 0x8B05, 0x8B06, 0x8B0B, 0x8B11, 0x8B1C, 0x8B1E, 0x8B1F, 0x8B0A, - 0x8B2D, 0x8B30, 0x8B37, 0x8B3C, 0x8B42, 0x8B43, 0x8B44, 0x8B45, - 0x8B46, 0x8B48, 0x8B52, 0x8B53, 0x8B54, 0x8B59, 0x8B4D, 0x8B5E, - 0x8B63, 0x8B6D, 0x8B76, 0x8B78, 0x8B79, 0x8B7C, 0x8B7E, 0x8B81, - 0x8B84, 0x8B85, 0x8B8B, 0x8B8D, 0x8B8F, 0x8B94, 0x8B95, 0x8B9C, - 0x8B9E, 0x8B9F, 0x8C38, 0x8C39, 0x8C3D, 0x8C3E, 0x8C45, 0x8C47, - 0x8C49, 0x8C4B, 0x8C4F, 0x8C51, 0x8C53, 0x8C54, 0x8C57, 0x8C58, - 0x8C5B, 0x8C5D, 0x8C59, 0x8C63, 0x8C64, 0x8C66, 0x8C68, 0x8C69, - 0x8C6D, 0x8C73, 0x8C75, 0x8C76, 0x8C7B, 0x8C7E, 0x8C86, -}; -static const unsigned short euc_to_utf8_8FDF[] = { - 0x8C87, 0x8C8B, 0x8C90, 0x8C92, 0x8C93, 0x8C99, 0x8C9B, - 0x8C9C, 0x8CA4, 0x8CB9, 0x8CBA, 0x8CC5, 0x8CC6, 0x8CC9, 0x8CCB, - 0x8CCF, 0x8CD6, 0x8CD5, 0x8CD9, 0x8CDD, 0x8CE1, 0x8CE8, 0x8CEC, - 0x8CEF, 0x8CF0, 0x8CF2, 0x8CF5, 0x8CF7, 0x8CF8, 0x8CFE, 0x8CFF, - 0x8D01, 0x8D03, 0x8D09, 0x8D12, 0x8D17, 0x8D1B, 0x8D65, 0x8D69, - 0x8D6C, 0x8D6E, 0x8D7F, 0x8D82, 0x8D84, 0x8D88, 0x8D8D, 0x8D90, - 0x8D91, 0x8D95, 0x8D9E, 0x8D9F, 0x8DA0, 0x8DA6, 0x8DAB, 0x8DAC, - 0x8DAF, 0x8DB2, 0x8DB5, 0x8DB7, 0x8DB9, 0x8DBB, 0x8DC0, 0x8DC5, - 0x8DC6, 0x8DC7, 0x8DC8, 0x8DCA, 0x8DCE, 0x8DD1, 0x8DD4, 0x8DD5, - 0x8DD7, 0x8DD9, 0x8DE4, 0x8DE5, 0x8DE7, 0x8DEC, 0x8DF0, 0x8DBC, - 0x8DF1, 0x8DF2, 0x8DF4, 0x8DFD, 0x8E01, 0x8E04, 0x8E05, 0x8E06, - 0x8E0B, 0x8E11, 0x8E14, 0x8E16, 0x8E20, 0x8E21, 0x8E22, -}; -static const unsigned short euc_to_utf8_8FE0[] = { - 0x8E23, 0x8E26, 0x8E27, 0x8E31, 0x8E33, 0x8E36, 0x8E37, - 0x8E38, 0x8E39, 0x8E3D, 0x8E40, 0x8E41, 0x8E4B, 0x8E4D, 0x8E4E, - 0x8E4F, 0x8E54, 0x8E5B, 0x8E5C, 0x8E5D, 0x8E5E, 0x8E61, 0x8E62, - 0x8E69, 0x8E6C, 0x8E6D, 0x8E6F, 0x8E70, 0x8E71, 0x8E79, 0x8E7A, - 0x8E7B, 0x8E82, 0x8E83, 0x8E89, 0x8E90, 0x8E92, 0x8E95, 0x8E9A, - 0x8E9B, 0x8E9D, 0x8E9E, 0x8EA2, 0x8EA7, 0x8EA9, 0x8EAD, 0x8EAE, - 0x8EB3, 0x8EB5, 0x8EBA, 0x8EBB, 0x8EC0, 0x8EC1, 0x8EC3, 0x8EC4, - 0x8EC7, 0x8ECF, 0x8ED1, 0x8ED4, 0x8EDC, 0x8EE8, 0x8EEE, 0x8EF0, - 0x8EF1, 0x8EF7, 0x8EF9, 0x8EFA, 0x8EED, 0x8F00, 0x8F02, 0x8F07, - 0x8F08, 0x8F0F, 0x8F10, 0x8F16, 0x8F17, 0x8F18, 0x8F1E, 0x8F20, - 0x8F21, 0x8F23, 0x8F25, 0x8F27, 0x8F28, 0x8F2C, 0x8F2D, 0x8F2E, - 0x8F34, 0x8F35, 0x8F36, 0x8F37, 0x8F3A, 0x8F40, 0x8F41, -}; -static const unsigned short euc_to_utf8_8FE1[] = { - 0x8F43, 0x8F47, 0x8F4F, 0x8F51, 0x8F52, 0x8F53, 0x8F54, - 0x8F55, 0x8F58, 0x8F5D, 0x8F5E, 0x8F65, 0x8F9D, 0x8FA0, 0x8FA1, - 0x8FA4, 0x8FA5, 0x8FA6, 0x8FB5, 0x8FB6, 0x8FB8, 0x8FBE, 0x8FC0, - 0x8FC1, 0x8FC6, 0x8FCA, 0x8FCB, 0x8FCD, 0x8FD0, 0x8FD2, 0x8FD3, - 0x8FD5, 0x8FE0, 0x8FE3, 0x8FE4, 0x8FE8, 0x8FEE, 0x8FF1, 0x8FF5, - 0x8FF6, 0x8FFB, 0x8FFE, 0x9002, 0x9004, 0x9008, 0x900C, 0x9018, - 0x901B, 0x9028, 0x9029, 0x902F, 0x902A, 0x902C, 0x902D, 0x9033, - 0x9034, 0x9037, 0x903F, 0x9043, 0x9044, 0x904C, 0x905B, 0x905D, - 0x9062, 0x9066, 0x9067, 0x906C, 0x9070, 0x9074, 0x9079, 0x9085, - 0x9088, 0x908B, 0x908C, 0x908E, 0x9090, 0x9095, 0x9097, 0x9098, - 0x9099, 0x909B, 0x90A0, 0x90A1, 0x90A2, 0x90A5, 0x90B0, 0x90B2, - 0x90B3, 0x90B4, 0x90B6, 0x90BD, 0x90CC, 0x90BE, 0x90C3, -}; -static const unsigned short euc_to_utf8_8FE2[] = { - 0x90C4, 0x90C5, 0x90C7, 0x90C8, 0x90D5, 0x90D7, 0x90D8, - 0x90D9, 0x90DC, 0x90DD, 0x90DF, 0x90E5, 0x90D2, 0x90F6, 0x90EB, - 0x90EF, 0x90F0, 0x90F4, 0x90FE, 0x90FF, 0x9100, 0x9104, 0x9105, - 0x9106, 0x9108, 0x910D, 0x9110, 0x9114, 0x9116, 0x9117, 0x9118, - 0x911A, 0x911C, 0x911E, 0x9120, 0x9125, 0x9122, 0x9123, 0x9127, - 0x9129, 0x912E, 0x912F, 0x9131, 0x9134, 0x9136, 0x9137, 0x9139, - 0x913A, 0x913C, 0x913D, 0x9143, 0x9147, 0x9148, 0x914F, 0x9153, - 0x9157, 0x9159, 0x915A, 0x915B, 0x9161, 0x9164, 0x9167, 0x916D, - 0x9174, 0x9179, 0x917A, 0x917B, 0x9181, 0x9183, 0x9185, 0x9186, - 0x918A, 0x918E, 0x9191, 0x9193, 0x9194, 0x9195, 0x9198, 0x919E, - 0x91A1, 0x91A6, 0x91A8, 0x91AC, 0x91AD, 0x91AE, 0x91B0, 0x91B1, - 0x91B2, 0x91B3, 0x91B6, 0x91BB, 0x91BC, 0x91BD, 0x91BF, -}; -static const unsigned short euc_to_utf8_8FE3[] = { - 0x91C2, 0x91C3, 0x91C5, 0x91D3, 0x91D4, 0x91D7, 0x91D9, - 0x91DA, 0x91DE, 0x91E4, 0x91E5, 0x91E9, 0x91EA, 0x91EC, 0x91ED, - 0x91EE, 0x91EF, 0x91F0, 0x91F1, 0x91F7, 0x91F9, 0x91FB, 0x91FD, - 0x9200, 0x9201, 0x9204, 0x9205, 0x9206, 0x9207, 0x9209, 0x920A, - 0x920C, 0x9210, 0x9212, 0x9213, 0x9216, 0x9218, 0x921C, 0x921D, - 0x9223, 0x9224, 0x9225, 0x9226, 0x9228, 0x922E, 0x922F, 0x9230, - 0x9233, 0x9235, 0x9236, 0x9238, 0x9239, 0x923A, 0x923C, 0x923E, - 0x9240, 0x9242, 0x9243, 0x9246, 0x9247, 0x924A, 0x924D, 0x924E, - 0x924F, 0x9251, 0x9258, 0x9259, 0x925C, 0x925D, 0x9260, 0x9261, - 0x9265, 0x9267, 0x9268, 0x9269, 0x926E, 0x926F, 0x9270, 0x9275, - 0x9276, 0x9277, 0x9278, 0x9279, 0x927B, 0x927C, 0x927D, 0x927F, - 0x9288, 0x9289, 0x928A, 0x928D, 0x928E, 0x9292, 0x9297, -}; -static const unsigned short euc_to_utf8_8FE4[] = { - 0x9299, 0x929F, 0x92A0, 0x92A4, 0x92A5, 0x92A7, 0x92A8, - 0x92AB, 0x92AF, 0x92B2, 0x92B6, 0x92B8, 0x92BA, 0x92BB, 0x92BC, - 0x92BD, 0x92BF, 0x92C0, 0x92C1, 0x92C2, 0x92C3, 0x92C5, 0x92C6, - 0x92C7, 0x92C8, 0x92CB, 0x92CC, 0x92CD, 0x92CE, 0x92D0, 0x92D3, - 0x92D5, 0x92D7, 0x92D8, 0x92D9, 0x92DC, 0x92DD, 0x92DF, 0x92E0, - 0x92E1, 0x92E3, 0x92E5, 0x92E7, 0x92E8, 0x92EC, 0x92EE, 0x92F0, - 0x92F9, 0x92FB, 0x92FF, 0x9300, 0x9302, 0x9308, 0x930D, 0x9311, - 0x9314, 0x9315, 0x931C, 0x931D, 0x931E, 0x931F, 0x9321, 0x9324, - 0x9325, 0x9327, 0x9329, 0x932A, 0x9333, 0x9334, 0x9336, 0x9337, - 0x9347, 0x9348, 0x9349, 0x9350, 0x9351, 0x9352, 0x9355, 0x9357, - 0x9358, 0x935A, 0x935E, 0x9364, 0x9365, 0x9367, 0x9369, 0x936A, - 0x936D, 0x936F, 0x9370, 0x9371, 0x9373, 0x9374, 0x9376, -}; -static const unsigned short euc_to_utf8_8FE5[] = { - 0x937A, 0x937D, 0x937F, 0x9380, 0x9381, 0x9382, 0x9388, - 0x938A, 0x938B, 0x938D, 0x938F, 0x9392, 0x9395, 0x9398, 0x939B, - 0x939E, 0x93A1, 0x93A3, 0x93A4, 0x93A6, 0x93A8, 0x93AB, 0x93B4, - 0x93B5, 0x93B6, 0x93BA, 0x93A9, 0x93C1, 0x93C4, 0x93C5, 0x93C6, - 0x93C7, 0x93C9, 0x93CA, 0x93CB, 0x93CC, 0x93CD, 0x93D3, 0x93D9, - 0x93DC, 0x93DE, 0x93DF, 0x93E2, 0x93E6, 0x93E7, 0x93F9, 0x93F7, - 0x93F8, 0x93FA, 0x93FB, 0x93FD, 0x9401, 0x9402, 0x9404, 0x9408, - 0x9409, 0x940D, 0x940E, 0x940F, 0x9415, 0x9416, 0x9417, 0x941F, - 0x942E, 0x942F, 0x9431, 0x9432, 0x9433, 0x9434, 0x943B, 0x943F, - 0x943D, 0x9443, 0x9445, 0x9448, 0x944A, 0x944C, 0x9455, 0x9459, - 0x945C, 0x945F, 0x9461, 0x9463, 0x9468, 0x946B, 0x946D, 0x946E, - 0x946F, 0x9471, 0x9472, 0x9484, 0x9483, 0x9578, 0x9579, -}; -static const unsigned short euc_to_utf8_8FE6[] = { - 0x957E, 0x9584, 0x9588, 0x958C, 0x958D, 0x958E, 0x959D, - 0x959E, 0x959F, 0x95A1, 0x95A6, 0x95A9, 0x95AB, 0x95AC, 0x95B4, - 0x95B6, 0x95BA, 0x95BD, 0x95BF, 0x95C6, 0x95C8, 0x95C9, 0x95CB, - 0x95D0, 0x95D1, 0x95D2, 0x95D3, 0x95D9, 0x95DA, 0x95DD, 0x95DE, - 0x95DF, 0x95E0, 0x95E4, 0x95E6, 0x961D, 0x961E, 0x9622, 0x9624, - 0x9625, 0x9626, 0x962C, 0x9631, 0x9633, 0x9637, 0x9638, 0x9639, - 0x963A, 0x963C, 0x963D, 0x9641, 0x9652, 0x9654, 0x9656, 0x9657, - 0x9658, 0x9661, 0x966E, 0x9674, 0x967B, 0x967C, 0x967E, 0x967F, - 0x9681, 0x9682, 0x9683, 0x9684, 0x9689, 0x9691, 0x9696, 0x969A, - 0x969D, 0x969F, 0x96A4, 0x96A5, 0x96A6, 0x96A9, 0x96AE, 0x96AF, - 0x96B3, 0x96BA, 0x96CA, 0x96D2, 0x5DB2, 0x96D8, 0x96DA, 0x96DD, - 0x96DE, 0x96DF, 0x96E9, 0x96EF, 0x96F1, 0x96FA, 0x9702, -}; -static const unsigned short euc_to_utf8_8FE7[] = { - 0x9703, 0x9705, 0x9709, 0x971A, 0x971B, 0x971D, 0x9721, - 0x9722, 0x9723, 0x9728, 0x9731, 0x9733, 0x9741, 0x9743, 0x974A, - 0x974E, 0x974F, 0x9755, 0x9757, 0x9758, 0x975A, 0x975B, 0x9763, - 0x9767, 0x976A, 0x976E, 0x9773, 0x9776, 0x9777, 0x9778, 0x977B, - 0x977D, 0x977F, 0x9780, 0x9789, 0x9795, 0x9796, 0x9797, 0x9799, - 0x979A, 0x979E, 0x979F, 0x97A2, 0x97AC, 0x97AE, 0x97B1, 0x97B2, - 0x97B5, 0x97B6, 0x97B8, 0x97B9, 0x97BA, 0x97BC, 0x97BE, 0x97BF, - 0x97C1, 0x97C4, 0x97C5, 0x97C7, 0x97C9, 0x97CA, 0x97CC, 0x97CD, - 0x97CE, 0x97D0, 0x97D1, 0x97D4, 0x97D7, 0x97D8, 0x97D9, 0x97DD, - 0x97DE, 0x97E0, 0x97DB, 0x97E1, 0x97E4, 0x97EF, 0x97F1, 0x97F4, - 0x97F7, 0x97F8, 0x97FA, 0x9807, 0x980A, 0x9819, 0x980D, 0x980E, - 0x9814, 0x9816, 0x981C, 0x981E, 0x9820, 0x9823, 0x9826, -}; -static const unsigned short euc_to_utf8_8FE8[] = { - 0x982B, 0x982E, 0x982F, 0x9830, 0x9832, 0x9833, 0x9835, - 0x9825, 0x983E, 0x9844, 0x9847, 0x984A, 0x9851, 0x9852, 0x9853, - 0x9856, 0x9857, 0x9859, 0x985A, 0x9862, 0x9863, 0x9865, 0x9866, - 0x986A, 0x986C, 0x98AB, 0x98AD, 0x98AE, 0x98B0, 0x98B4, 0x98B7, - 0x98B8, 0x98BA, 0x98BB, 0x98BF, 0x98C2, 0x98C5, 0x98C8, 0x98CC, - 0x98E1, 0x98E3, 0x98E5, 0x98E6, 0x98E7, 0x98EA, 0x98F3, 0x98F6, - 0x9902, 0x9907, 0x9908, 0x9911, 0x9915, 0x9916, 0x9917, 0x991A, - 0x991B, 0x991C, 0x991F, 0x9922, 0x9926, 0x9927, 0x992B, 0x9931, - 0x9932, 0x9933, 0x9934, 0x9935, 0x9939, 0x993A, 0x993B, 0x993C, - 0x9940, 0x9941, 0x9946, 0x9947, 0x9948, 0x994D, 0x994E, 0x9954, - 0x9958, 0x9959, 0x995B, 0x995C, 0x995E, 0x995F, 0x9960, 0x999B, - 0x999D, 0x999F, 0x99A6, 0x99B0, 0x99B1, 0x99B2, 0x99B5, -}; -static const unsigned short euc_to_utf8_8FE9[] = { - 0x99B9, 0x99BA, 0x99BD, 0x99BF, 0x99C3, 0x99C9, 0x99D3, - 0x99D4, 0x99D9, 0x99DA, 0x99DC, 0x99DE, 0x99E7, 0x99EA, 0x99EB, - 0x99EC, 0x99F0, 0x99F4, 0x99F5, 0x99F9, 0x99FD, 0x99FE, 0x9A02, - 0x9A03, 0x9A04, 0x9A0B, 0x9A0C, 0x9A10, 0x9A11, 0x9A16, 0x9A1E, - 0x9A20, 0x9A22, 0x9A23, 0x9A24, 0x9A27, 0x9A2D, 0x9A2E, 0x9A33, - 0x9A35, 0x9A36, 0x9A38, 0x9A47, 0x9A41, 0x9A44, 0x9A4A, 0x9A4B, - 0x9A4C, 0x9A4E, 0x9A51, 0x9A54, 0x9A56, 0x9A5D, 0x9AAA, 0x9AAC, - 0x9AAE, 0x9AAF, 0x9AB2, 0x9AB4, 0x9AB5, 0x9AB6, 0x9AB9, 0x9ABB, - 0x9ABE, 0x9ABF, 0x9AC1, 0x9AC3, 0x9AC6, 0x9AC8, 0x9ACE, 0x9AD0, - 0x9AD2, 0x9AD5, 0x9AD6, 0x9AD7, 0x9ADB, 0x9ADC, 0x9AE0, 0x9AE4, - 0x9AE5, 0x9AE7, 0x9AE9, 0x9AEC, 0x9AF2, 0x9AF3, 0x9AF5, 0x9AF9, - 0x9AFA, 0x9AFD, 0x9AFF, 0x9B00, 0x9B01, 0x9B02, 0x9B03, -}; -static const unsigned short euc_to_utf8_8FEA[] = { - 0x9B04, 0x9B05, 0x9B08, 0x9B09, 0x9B0B, 0x9B0C, 0x9B0D, - 0x9B0E, 0x9B10, 0x9B12, 0x9B16, 0x9B19, 0x9B1B, 0x9B1C, 0x9B20, - 0x9B26, 0x9B2B, 0x9B2D, 0x9B33, 0x9B34, 0x9B35, 0x9B37, 0x9B39, - 0x9B3A, 0x9B3D, 0x9B48, 0x9B4B, 0x9B4C, 0x9B55, 0x9B56, 0x9B57, - 0x9B5B, 0x9B5E, 0x9B61, 0x9B63, 0x9B65, 0x9B66, 0x9B68, 0x9B6A, - 0x9B6B, 0x9B6C, 0x9B6D, 0x9B6E, 0x9B73, 0x9B75, 0x9B77, 0x9B78, - 0x9B79, 0x9B7F, 0x9B80, 0x9B84, 0x9B85, 0x9B86, 0x9B87, 0x9B89, - 0x9B8A, 0x9B8B, 0x9B8D, 0x9B8F, 0x9B90, 0x9B94, 0x9B9A, 0x9B9D, - 0x9B9E, 0x9BA6, 0x9BA7, 0x9BA9, 0x9BAC, 0x9BB0, 0x9BB1, 0x9BB2, - 0x9BB7, 0x9BB8, 0x9BBB, 0x9BBC, 0x9BBE, 0x9BBF, 0x9BC1, 0x9BC7, - 0x9BC8, 0x9BCE, 0x9BD0, 0x9BD7, 0x9BD8, 0x9BDD, 0x9BDF, 0x9BE5, - 0x9BE7, 0x9BEA, 0x9BEB, 0x9BEF, 0x9BF3, 0x9BF7, 0x9BF8, -}; -static const unsigned short euc_to_utf8_8FEB[] = { - 0x9BF9, 0x9BFA, 0x9BFD, 0x9BFF, 0x9C00, 0x9C02, 0x9C0B, - 0x9C0F, 0x9C11, 0x9C16, 0x9C18, 0x9C19, 0x9C1A, 0x9C1C, 0x9C1E, - 0x9C22, 0x9C23, 0x9C26, 0x9C27, 0x9C28, 0x9C29, 0x9C2A, 0x9C31, - 0x9C35, 0x9C36, 0x9C37, 0x9C3D, 0x9C41, 0x9C43, 0x9C44, 0x9C45, - 0x9C49, 0x9C4A, 0x9C4E, 0x9C4F, 0x9C50, 0x9C53, 0x9C54, 0x9C56, - 0x9C58, 0x9C5B, 0x9C5D, 0x9C5E, 0x9C5F, 0x9C63, 0x9C69, 0x9C6A, - 0x9C5C, 0x9C6B, 0x9C68, 0x9C6E, 0x9C70, 0x9C72, 0x9C75, 0x9C77, - 0x9C7B, 0x9CE6, 0x9CF2, 0x9CF7, 0x9CF9, 0x9D0B, 0x9D02, 0x9D11, - 0x9D17, 0x9D18, 0x9D1C, 0x9D1D, 0x9D1E, 0x9D2F, 0x9D30, 0x9D32, - 0x9D33, 0x9D34, 0x9D3A, 0x9D3C, 0x9D45, 0x9D3D, 0x9D42, 0x9D43, - 0x9D47, 0x9D4A, 0x9D53, 0x9D54, 0x9D5F, 0x9D63, 0x9D62, 0x9D65, - 0x9D69, 0x9D6A, 0x9D6B, 0x9D70, 0x9D76, 0x9D77, 0x9D7B, -}; -static const unsigned short euc_to_utf8_8FEC[] = { - 0x9D7C, 0x9D7E, 0x9D83, 0x9D84, 0x9D86, 0x9D8A, 0x9D8D, - 0x9D8E, 0x9D92, 0x9D93, 0x9D95, 0x9D96, 0x9D97, 0x9D98, 0x9DA1, - 0x9DAA, 0x9DAC, 0x9DAE, 0x9DB1, 0x9DB5, 0x9DB9, 0x9DBC, 0x9DBF, - 0x9DC3, 0x9DC7, 0x9DC9, 0x9DCA, 0x9DD4, 0x9DD5, 0x9DD6, 0x9DD7, - 0x9DDA, 0x9DDE, 0x9DDF, 0x9DE0, 0x9DE5, 0x9DE7, 0x9DE9, 0x9DEB, - 0x9DEE, 0x9DF0, 0x9DF3, 0x9DF4, 0x9DFE, 0x9E0A, 0x9E02, 0x9E07, - 0x9E0E, 0x9E10, 0x9E11, 0x9E12, 0x9E15, 0x9E16, 0x9E19, 0x9E1C, - 0x9E1D, 0x9E7A, 0x9E7B, 0x9E7C, 0x9E80, 0x9E82, 0x9E83, 0x9E84, - 0x9E85, 0x9E87, 0x9E8E, 0x9E8F, 0x9E96, 0x9E98, 0x9E9B, 0x9E9E, - 0x9EA4, 0x9EA8, 0x9EAC, 0x9EAE, 0x9EAF, 0x9EB0, 0x9EB3, 0x9EB4, - 0x9EB5, 0x9EC6, 0x9EC8, 0x9ECB, 0x9ED5, 0x9EDF, 0x9EE4, 0x9EE7, - 0x9EEC, 0x9EED, 0x9EEE, 0x9EF0, 0x9EF1, 0x9EF2, 0x9EF5, -}; -static const unsigned short euc_to_utf8_8FED[] = { - 0x9EF8, 0x9EFF, 0x9F02, 0x9F03, 0x9F09, 0x9F0F, 0x9F10, - 0x9F11, 0x9F12, 0x9F14, 0x9F16, 0x9F17, 0x9F19, 0x9F1A, 0x9F1B, - 0x9F1F, 0x9F22, 0x9F26, 0x9F2A, 0x9F2B, 0x9F2F, 0x9F31, 0x9F32, - 0x9F34, 0x9F37, 0x9F39, 0x9F3A, 0x9F3C, 0x9F3D, 0x9F3F, 0x9F41, - 0x9F43, 0x9F44, 0x9F45, 0x9F46, 0x9F47, 0x9F53, 0x9F55, 0x9F56, - 0x9F57, 0x9F58, 0x9F5A, 0x9F5D, 0x9F5E, 0x9F68, 0x9F69, 0x9F6D, - 0x9F6E, 0x9F6F, 0x9F70, 0x9F71, 0x9F73, 0x9F75, 0x9F7A, 0x9F7D, - 0x9F8F, 0x9F90, 0x9F91, 0x9F92, 0x9F94, 0x9F96, 0x9F97, 0x9F9E, - 0x9FA1, 0x9FA2, 0x9FA3, 0x9FA5, 0, 0, 0, 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 unsigned short euc_to_utf8_8FF3[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, - 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x2160, 0x2161, -}; -static const unsigned short euc_to_utf8_8FF4[] = { - 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, - 0x2169, 0xff07, 0xff02, 0x3231, 0x2116, 0x2121, 0x70bb, 0x4efc, - 0x50f4, 0x51ec, 0x5307, 0x5324, 0xfa0e, 0x548a, 0x5759, 0xfa0f, - 0xfa10, 0x589e, 0x5bec, 0x5cf5, 0x5d53, 0xfa11, 0x5fb7, 0x6085, - 0x6120, 0x654e, 0x663b, 0x6665, 0xfa12, 0xf929, 0x6801, 0xfa13, - 0xfa14, 0x6a6b, 0x6ae2, 0x6df8, 0x6df2, 0x7028, 0xfa15, 0xfa16, - 0x7501, 0x7682, 0x769e, 0xfa17, 0x7930, 0xfa18, 0xfa19, 0xfa1a, - 0xfa1b, 0x7ae7, 0xfa1c, 0xfa1d, 0x7da0, 0x7dd6, 0xfa1e, 0x8362, - 0xfa1f, 0x85b0, 0xfa20, 0xfa21, 0x8807, 0xfa22, 0x8b7f, 0x8cf4, - 0x8d76, 0xfa23, 0xfa24, 0xfa25, 0x90de, 0xfa26, 0x9115, 0xfa27, - 0xfa28, 0x9592, 0xf9dc, 0xfa29, 0x973b, 0x974d, 0x9751, 0xfa2a, - 0xfa2b, 0xfa2c, 0x999e, 0x9ad9, 0x9b72, 0xfa2d, 0x9ed1, -}; -#endif /* X0212_ENABLE */ - -const unsigned short euc_to_utf8_1byte[] = { - 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67, - 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F, - 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77, - 0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F, - 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87, - 0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F, - 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97, - 0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x00A9, 0x2122, -}; -const unsigned short *const euc_to_utf8_2bytes[] = { - euc_to_utf8_A1, euc_to_utf8_A2, euc_to_utf8_A3, - euc_to_utf8_A4, euc_to_utf8_A5, euc_to_utf8_A6, euc_to_utf8_A7, - euc_to_utf8_A8, euc_to_utf8_A9, euc_to_utf8_AA, euc_to_utf8_AB, - euc_to_utf8_AC, euc_to_utf8_AD, euc_to_utf8_AE, euc_to_utf8_AF, - euc_to_utf8_B0, euc_to_utf8_B1, euc_to_utf8_B2, euc_to_utf8_B3, - euc_to_utf8_B4, euc_to_utf8_B5, euc_to_utf8_B6, euc_to_utf8_B7, - euc_to_utf8_B8, euc_to_utf8_B9, euc_to_utf8_BA, euc_to_utf8_BB, - euc_to_utf8_BC, euc_to_utf8_BD, euc_to_utf8_BE, euc_to_utf8_BF, - euc_to_utf8_C0, euc_to_utf8_C1, euc_to_utf8_C2, euc_to_utf8_C3, - euc_to_utf8_C4, euc_to_utf8_C5, euc_to_utf8_C6, euc_to_utf8_C7, - euc_to_utf8_C8, euc_to_utf8_C9, euc_to_utf8_CA, euc_to_utf8_CB, - euc_to_utf8_CC, euc_to_utf8_CD, euc_to_utf8_CE, euc_to_utf8_CF, - euc_to_utf8_D0, euc_to_utf8_D1, euc_to_utf8_D2, euc_to_utf8_D3, - euc_to_utf8_D4, euc_to_utf8_D5, euc_to_utf8_D6, euc_to_utf8_D7, - euc_to_utf8_D8, euc_to_utf8_D9, euc_to_utf8_DA, euc_to_utf8_DB, - euc_to_utf8_DC, euc_to_utf8_DD, euc_to_utf8_DE, euc_to_utf8_DF, - euc_to_utf8_E0, euc_to_utf8_E1, euc_to_utf8_E2, euc_to_utf8_E3, - euc_to_utf8_E4, euc_to_utf8_E5, euc_to_utf8_E6, euc_to_utf8_E7, - euc_to_utf8_E8, euc_to_utf8_E9, euc_to_utf8_EA, euc_to_utf8_EB, - euc_to_utf8_EC, euc_to_utf8_ED, euc_to_utf8_EE, euc_to_utf8_EF, - euc_to_utf8_F0, euc_to_utf8_F1, euc_to_utf8_F2, euc_to_utf8_F3, - euc_to_utf8_F4, euc_to_utf8_F5, 0, 0, - 0, euc_to_utf8_F9, euc_to_utf8_FA, euc_to_utf8_FB, - euc_to_utf8_FC, 0, 0, -}; -/* Microsoft UCS Mapping Compatible */ -const unsigned short *const euc_to_utf8_2bytes_ms[] = { - euc_to_utf8_A1_ms, euc_to_utf8_A2_ms, euc_to_utf8_A3, - euc_to_utf8_A4, euc_to_utf8_A5, euc_to_utf8_A6, euc_to_utf8_A7, - euc_to_utf8_A8, euc_to_utf8_A9, euc_to_utf8_AA, euc_to_utf8_AB, - euc_to_utf8_AC, euc_to_utf8_AD, euc_to_utf8_AE, euc_to_utf8_AF, - euc_to_utf8_B0, euc_to_utf8_B1, euc_to_utf8_B2, euc_to_utf8_B3, - euc_to_utf8_B4, euc_to_utf8_B5, euc_to_utf8_B6, euc_to_utf8_B7, - euc_to_utf8_B8, euc_to_utf8_B9, euc_to_utf8_BA, euc_to_utf8_BB, - euc_to_utf8_BC, euc_to_utf8_BD, euc_to_utf8_BE, euc_to_utf8_BF, - euc_to_utf8_C0, euc_to_utf8_C1, euc_to_utf8_C2, euc_to_utf8_C3, - euc_to_utf8_C4, euc_to_utf8_C5, euc_to_utf8_C6, euc_to_utf8_C7, - euc_to_utf8_C8, euc_to_utf8_C9, euc_to_utf8_CA, euc_to_utf8_CB, - euc_to_utf8_CC, euc_to_utf8_CD, euc_to_utf8_CE, euc_to_utf8_CF, - euc_to_utf8_D0, euc_to_utf8_D1, euc_to_utf8_D2, euc_to_utf8_D3, - euc_to_utf8_D4, euc_to_utf8_D5, euc_to_utf8_D6, euc_to_utf8_D7, - euc_to_utf8_D8, euc_to_utf8_D9, euc_to_utf8_DA, euc_to_utf8_DB, - euc_to_utf8_DC, euc_to_utf8_DD, euc_to_utf8_DE, euc_to_utf8_DF, - euc_to_utf8_E0, euc_to_utf8_E1, euc_to_utf8_E2, euc_to_utf8_E3, - euc_to_utf8_E4, euc_to_utf8_E5, euc_to_utf8_E6, euc_to_utf8_E7, - euc_to_utf8_E8, euc_to_utf8_E9, euc_to_utf8_EA, euc_to_utf8_EB, - euc_to_utf8_EC, euc_to_utf8_ED, euc_to_utf8_EE, euc_to_utf8_EF, - euc_to_utf8_F0, euc_to_utf8_F1, euc_to_utf8_F2, euc_to_utf8_F3, - euc_to_utf8_F4, euc_to_utf8_F5, 0, 0, - 0, euc_to_utf8_F9, euc_to_utf8_FA, euc_to_utf8_FB, - euc_to_utf8_FC_ms, 0, 0, -}; -/* CP10001 */ -const unsigned short *const euc_to_utf8_2bytes_mac[] = { - euc_to_utf8_A1_ms, euc_to_utf8_A2_ms, euc_to_utf8_A3, - euc_to_utf8_A4, euc_to_utf8_A5, euc_to_utf8_A6, euc_to_utf8_A7, - euc_to_utf8_A8, euc_to_utf8_A9, euc_to_utf8_AA, euc_to_utf8_AB, - euc_to_utf8_AC_mac, euc_to_utf8_AD_mac, euc_to_utf8_AE, euc_to_utf8_AF, - euc_to_utf8_B0, euc_to_utf8_B1, euc_to_utf8_B2, euc_to_utf8_B3, - euc_to_utf8_B4, euc_to_utf8_B5, euc_to_utf8_B6, euc_to_utf8_B7, - euc_to_utf8_B8, euc_to_utf8_B9, euc_to_utf8_BA, euc_to_utf8_BB, - euc_to_utf8_BC, euc_to_utf8_BD, euc_to_utf8_BE, euc_to_utf8_BF, - euc_to_utf8_C0, euc_to_utf8_C1, euc_to_utf8_C2, euc_to_utf8_C3, - euc_to_utf8_C4, euc_to_utf8_C5, euc_to_utf8_C6, euc_to_utf8_C7, - euc_to_utf8_C8, euc_to_utf8_C9, euc_to_utf8_CA, euc_to_utf8_CB, - euc_to_utf8_CC, euc_to_utf8_CD, euc_to_utf8_CE, euc_to_utf8_CF, - euc_to_utf8_D0, euc_to_utf8_D1, euc_to_utf8_D2, euc_to_utf8_D3, - euc_to_utf8_D4, euc_to_utf8_D5, euc_to_utf8_D6, euc_to_utf8_D7, - euc_to_utf8_D8, euc_to_utf8_D9, euc_to_utf8_DA, euc_to_utf8_DB, - euc_to_utf8_DC, euc_to_utf8_DD, euc_to_utf8_DE, euc_to_utf8_DF, - euc_to_utf8_E0, euc_to_utf8_E1, euc_to_utf8_E2, euc_to_utf8_E3, - euc_to_utf8_E4, euc_to_utf8_E5, euc_to_utf8_E6, euc_to_utf8_E7, - euc_to_utf8_E8, euc_to_utf8_E9, euc_to_utf8_EA, euc_to_utf8_EB, - euc_to_utf8_EC, euc_to_utf8_ED, euc_to_utf8_EE, euc_to_utf8_EF, - euc_to_utf8_F0, euc_to_utf8_F1, euc_to_utf8_F2, euc_to_utf8_F3, - euc_to_utf8_F4, euc_to_utf8_F5, 0, 0, - 0, euc_to_utf8_F9, euc_to_utf8_FA, euc_to_utf8_FB, - euc_to_utf8_FC_ms, 0, 0, -}; -const unsigned short *const euc_to_utf8_2bytes_x0213[] = { - euc_to_utf8_A1, euc_to_utf8_A2_x0213, euc_to_utf8_A3_x0213, - euc_to_utf8_A4_x0213, euc_to_utf8_A5_x0213, euc_to_utf8_A6_x0213, euc_to_utf8_A7_x0213, - euc_to_utf8_A8_x0213, euc_to_utf8_A9_x0213, euc_to_utf8_AA_x0213, euc_to_utf8_AB_x0213, - euc_to_utf8_AC_x0213, euc_to_utf8_AD_x0213, euc_to_utf8_AE_x0213, euc_to_utf8_AF_x0213, - euc_to_utf8_B0, euc_to_utf8_B1, euc_to_utf8_B2, euc_to_utf8_B3, - euc_to_utf8_B4, euc_to_utf8_B5, euc_to_utf8_B6, euc_to_utf8_B7, - euc_to_utf8_B8, euc_to_utf8_B9, euc_to_utf8_BA, euc_to_utf8_BB, - euc_to_utf8_BC, euc_to_utf8_BD, euc_to_utf8_BE, euc_to_utf8_BF, - euc_to_utf8_C0, euc_to_utf8_C1, euc_to_utf8_C2, euc_to_utf8_C3, - euc_to_utf8_C4, euc_to_utf8_C5, euc_to_utf8_C6, euc_to_utf8_C7, - euc_to_utf8_C8, euc_to_utf8_C9, euc_to_utf8_CA, euc_to_utf8_CB, - euc_to_utf8_CC, euc_to_utf8_CD, euc_to_utf8_CE, euc_to_utf8_CF_x0213, - euc_to_utf8_D0, euc_to_utf8_D1, euc_to_utf8_D2, euc_to_utf8_D3, - euc_to_utf8_D4, euc_to_utf8_D5, euc_to_utf8_D6, euc_to_utf8_D7, - euc_to_utf8_D8, euc_to_utf8_D9, euc_to_utf8_DA, euc_to_utf8_DB, - euc_to_utf8_DC, euc_to_utf8_DD, euc_to_utf8_DE, euc_to_utf8_DF, - euc_to_utf8_E0, euc_to_utf8_E1, euc_to_utf8_E2, euc_to_utf8_E3, - euc_to_utf8_E4, euc_to_utf8_E5, euc_to_utf8_E6, euc_to_utf8_E7, - euc_to_utf8_E8, euc_to_utf8_E9, euc_to_utf8_EA, euc_to_utf8_EB, - euc_to_utf8_EC, euc_to_utf8_ED, euc_to_utf8_EE, euc_to_utf8_EF, - euc_to_utf8_F0, euc_to_utf8_F1, euc_to_utf8_F2, euc_to_utf8_F3, - euc_to_utf8_F4_x0213, euc_to_utf8_F5_x0213, euc_to_utf8_F6_x0213, euc_to_utf8_F7_x0213, - euc_to_utf8_F8_x0213, euc_to_utf8_F9_x0213, euc_to_utf8_FA_x0213, euc_to_utf8_FB_x0213, - euc_to_utf8_FC_x0213, euc_to_utf8_FD_x0213, euc_to_utf8_FE_x0213, -}; - -#ifdef X0212_ENABLE -const unsigned short *const x0212_to_utf8_2bytes[] = { - 0, euc_to_utf8_8FA2, 0, - 0, 0, euc_to_utf8_8FA6, euc_to_utf8_8FA7, - 0, euc_to_utf8_8FA9, euc_to_utf8_8FAA, euc_to_utf8_8FAB, - 0, 0, 0, 0, - euc_to_utf8_8FB0, euc_to_utf8_8FB1, euc_to_utf8_8FB2, euc_to_utf8_8FB3, - euc_to_utf8_8FB4, euc_to_utf8_8FB5, euc_to_utf8_8FB6, euc_to_utf8_8FB7, - euc_to_utf8_8FB8, euc_to_utf8_8FB9, euc_to_utf8_8FBA, euc_to_utf8_8FBB, - euc_to_utf8_8FBC, euc_to_utf8_8FBD, euc_to_utf8_8FBE, euc_to_utf8_8FBF, - euc_to_utf8_8FC0, euc_to_utf8_8FC1, euc_to_utf8_8FC2, euc_to_utf8_8FC3, - euc_to_utf8_8FC4, euc_to_utf8_8FC5, euc_to_utf8_8FC6, euc_to_utf8_8FC7, - euc_to_utf8_8FC8, euc_to_utf8_8FC9, euc_to_utf8_8FCA, euc_to_utf8_8FCB, - euc_to_utf8_8FCC, euc_to_utf8_8FCD, euc_to_utf8_8FCE, euc_to_utf8_8FCF, - euc_to_utf8_8FD0, euc_to_utf8_8FD1, euc_to_utf8_8FD2, euc_to_utf8_8FD3, - euc_to_utf8_8FD4, euc_to_utf8_8FD5, euc_to_utf8_8FD6, euc_to_utf8_8FD7, - euc_to_utf8_8FD8, euc_to_utf8_8FD9, euc_to_utf8_8FDA, euc_to_utf8_8FDB, - euc_to_utf8_8FDC, euc_to_utf8_8FDD, euc_to_utf8_8FDE, euc_to_utf8_8FDF, - euc_to_utf8_8FE0, euc_to_utf8_8FE1, euc_to_utf8_8FE2, euc_to_utf8_8FE3, - euc_to_utf8_8FE4, euc_to_utf8_8FE5, euc_to_utf8_8FE6, euc_to_utf8_8FE7, - euc_to_utf8_8FE8, euc_to_utf8_8FE9, euc_to_utf8_8FEA, euc_to_utf8_8FEB, - euc_to_utf8_8FEC, euc_to_utf8_8FED, 0, 0, - 0, 0, 0, euc_to_utf8_8FF3, - euc_to_utf8_8FF4, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0,}; - -const unsigned short *const x0212_to_utf8_2bytes_x0213[] = { - euc_to_utf8_8FA1_x0213, euc_to_utf8_8FA2, euc_to_utf8_8FA3_x0213, - euc_to_utf8_8FA4_x0213, euc_to_utf8_8FA5_x0213, euc_to_utf8_8FA6, euc_to_utf8_8FA7, - euc_to_utf8_8FA8_x0213, euc_to_utf8_8FA9, euc_to_utf8_8FAA, euc_to_utf8_8FAB, - euc_to_utf8_8FAC_x0213, euc_to_utf8_8FAD_x0213, euc_to_utf8_8FAE_x0213, euc_to_utf8_8FAF_x0213, - euc_to_utf8_8FB0, euc_to_utf8_8FB1, euc_to_utf8_8FB2, euc_to_utf8_8FB3, - euc_to_utf8_8FB4, euc_to_utf8_8FB5, euc_to_utf8_8FB6, euc_to_utf8_8FB7, - euc_to_utf8_8FB8, euc_to_utf8_8FB9, euc_to_utf8_8FBA, euc_to_utf8_8FBB, - euc_to_utf8_8FBC, euc_to_utf8_8FBD, euc_to_utf8_8FBE, euc_to_utf8_8FBF, - euc_to_utf8_8FC0, euc_to_utf8_8FC1, euc_to_utf8_8FC2, euc_to_utf8_8FC3, - euc_to_utf8_8FC4, euc_to_utf8_8FC5, euc_to_utf8_8FC6, euc_to_utf8_8FC7, - euc_to_utf8_8FC8, euc_to_utf8_8FC9, euc_to_utf8_8FCA, euc_to_utf8_8FCB, - euc_to_utf8_8FCC, euc_to_utf8_8FCD, euc_to_utf8_8FCE, euc_to_utf8_8FCF, - euc_to_utf8_8FD0, euc_to_utf8_8FD1, euc_to_utf8_8FD2, euc_to_utf8_8FD3, - euc_to_utf8_8FD4, euc_to_utf8_8FD5, euc_to_utf8_8FD6, euc_to_utf8_8FD7, - euc_to_utf8_8FD8, euc_to_utf8_8FD9, euc_to_utf8_8FDA, euc_to_utf8_8FDB, - euc_to_utf8_8FDC, euc_to_utf8_8FDD, euc_to_utf8_8FDE, euc_to_utf8_8FDF, - euc_to_utf8_8FE0, euc_to_utf8_8FE1, euc_to_utf8_8FE2, euc_to_utf8_8FE3, - euc_to_utf8_8FE4, euc_to_utf8_8FE5, euc_to_utf8_8FE6, euc_to_utf8_8FE7, - euc_to_utf8_8FE8, euc_to_utf8_8FE9, euc_to_utf8_8FEA, euc_to_utf8_8FEB, - euc_to_utf8_8FEC, euc_to_utf8_8FED, euc_to_utf8_8FEE_x0213, euc_to_utf8_8FEF_x0213, - euc_to_utf8_8FF0_x0213, euc_to_utf8_8FF1_x0213, euc_to_utf8_8FF2_x0213, euc_to_utf8_8FF3_x0213, - euc_to_utf8_8FF4_x0213, euc_to_utf8_8FF5_x0213, euc_to_utf8_8FF6_x0213, euc_to_utf8_8FF7_x0213, - euc_to_utf8_8FF8_x0213, euc_to_utf8_8FF9_x0213, euc_to_utf8_8FFA_x0213, euc_to_utf8_8FFB_x0213, - euc_to_utf8_8FFC_x0213, euc_to_utf8_8FFD_x0213, euc_to_utf8_8FFE_x0213,}; -#endif /* X0212_ENABLE */ - -const unsigned short x0213_combining_chars[sizeof_x0213_combining_chars] = { - 0x309A, 0x0300, 0x0301, 0x02E5, 0x02E9, -}; -const unsigned short x0213_combining_table[sizeof_x0213_combining_table][3] = { - {0x2477, 0x304B, 0x309A}, - {0x2478, 0x304D, 0x309A}, - {0x2479, 0x304F, 0x309A}, - {0x247A, 0x3051, 0x309A}, - {0x247B, 0x3053, 0x309A}, - {0x2577, 0x30AB, 0x309A}, - {0x2578, 0x30AD, 0x309A}, - {0x2579, 0x30AF, 0x309A}, - {0x257A, 0x30B1, 0x309A}, - {0x257B, 0x30B3, 0x309A}, - {0x257C, 0x30BB, 0x309A}, - {0x257D, 0x30C4, 0x309A}, - {0x257E, 0x30C8, 0x309A}, - {0x2678, 0x31F7, 0x309A}, - {0x2B44, 0x00E6, 0x0300}, - {0x2B48, 0x0254, 0x0300}, - {0x2B49, 0x0254, 0x0301}, - {0x2B4A, 0x028C, 0x0300}, - {0x2B4B, 0x028C, 0x0301}, - {0x2B4C, 0x0259, 0x0300}, - {0x2B4D, 0x0259, 0x0301}, - {0x2B4E, 0x025A, 0x0300}, - {0x2B4F, 0x025A, 0x0301}, - {0x2B65, 0x02E9, 0x02E5}, - {0x2B66, 0x02E5, 0x02E9}, -}; -const unsigned short x0213_1_surrogate_table[sizeof_x0213_1_surrogate_table][3] = { - {0x2E22, 0xD840, 0xDC0B}, - {0x2F42, 0xD844, 0xDE3D}, - {0x2F4C, 0xD844, 0xDF1B}, - {0x2F60, 0xD845, 0xDC6E}, - {0x2F7B, 0xD846, 0xDCBD}, - {0x4F54, 0xD842, 0xDF9F}, - {0x4F63, 0xD845, 0xDEB4}, - {0x4F6E, 0xD847, 0xDE34}, - {0x753A, 0xD84C, 0xDDC4}, - {0x7572, 0xD84D, 0xDDC4}, - {0x7629, 0xD84D, 0xDF3F}, - {0x7632, 0xD84D, 0xDF63}, - {0x7660, 0xD84F, 0xDCFE}, - {0x776C, 0xD851, 0xDFF1}, - {0x787E, 0xD855, 0xDC8E}, - {0x7929, 0xD855, 0xDD0E}, - {0x7947, 0xD855, 0xDF71}, - {0x7954, 0xD856, 0xDDC4}, - {0x796E, 0xD857, 0xDDA1}, - {0x7A5D, 0xD85A, 0xDEFF}, - {0x7B33, 0xD85B, 0xDE40}, - {0x7B49, 0xD85C, 0xDCF4}, - {0x7B6C, 0xD85D, 0xDE84}, - {0x7C49, 0xD860, 0xDE77}, - {0x7C51, 0xD860, 0xDFCD}, - {0x7E66, 0xD868, 0xDD90}, -}; -const unsigned short x0213_2_surrogate_table[sizeof_x0213_2_surrogate_table][3] = { - {0x2121, 0xD840, 0xDC89}, - {0x212B, 0xD840, 0xDCA2}, - {0x212E, 0xD840, 0xDCA4}, - {0x2136, 0xD840, 0xDDA2}, - {0x2146, 0xD840, 0xDE13}, - {0x2170, 0xD840, 0xDF2B}, - {0x2177, 0xD840, 0xDF81}, - {0x2179, 0xD840, 0xDF71}, - {0x2322, 0xD840, 0xDFF9}, - {0x2325, 0xD841, 0xDC4A}, - {0x2327, 0xD841, 0xDD09}, - {0x2331, 0xD841, 0xDDD6}, - {0x2332, 0xD841, 0xDE28}, - {0x2338, 0xD841, 0xDF4F}, - {0x233F, 0xD842, 0xDC07}, - {0x2341, 0xD842, 0xDC3A}, - {0x234A, 0xD842, 0xDCB9}, - {0x2352, 0xD842, 0xDD7C}, - {0x2353, 0xD842, 0xDD9D}, - {0x2359, 0xD842, 0xDED3}, - {0x235C, 0xD842, 0xDF1D}, - {0x2377, 0xD843, 0xDD45}, - {0x242A, 0xD843, 0xDDE1}, - {0x2431, 0xD843, 0xDE95}, - {0x2432, 0xD843, 0xDE6D}, - {0x243A, 0xD843, 0xDE64}, - {0x243D, 0xD843, 0xDF5F}, - {0x2459, 0xD844, 0xDE01}, - {0x245C, 0xD844, 0xDE55}, - {0x245E, 0xD844, 0xDE7B}, - {0x2463, 0xD844, 0xDE74}, - {0x246A, 0xD844, 0xDEE4}, - {0x246B, 0xD844, 0xDED7}, - {0x2472, 0xD844, 0xDEFD}, - {0x2474, 0xD844, 0xDF36}, - {0x2475, 0xD844, 0xDF44}, - {0x2525, 0xD844, 0xDFC4}, - {0x2532, 0xD845, 0xDC6D}, - {0x253E, 0xD845, 0xDDD7}, - {0x2544, 0xD85B, 0xDC29}, - {0x2547, 0xD845, 0xDE47}, - {0x2555, 0xD845, 0xDF06}, - {0x2556, 0xD845, 0xDF42}, - {0x257E, 0xD846, 0xDDC3}, - {0x2830, 0xD847, 0xDC56}, - {0x2837, 0xD847, 0xDD2D}, - {0x2838, 0xD847, 0xDD45}, - {0x283A, 0xD847, 0xDD78}, - {0x283B, 0xD847, 0xDD62}, - {0x283F, 0xD847, 0xDDA1}, - {0x2840, 0xD847, 0xDD9C}, - {0x2845, 0xD847, 0xDD92}, - {0x2848, 0xD847, 0xDDB7}, - {0x284A, 0xD847, 0xDDE0}, - {0x284B, 0xD847, 0xDE33}, - {0x285B, 0xD847, 0xDF1E}, - {0x2866, 0xD847, 0xDF76}, - {0x286C, 0xD847, 0xDFFA}, - {0x2C22, 0xD848, 0xDD7B}, - {0x2C2B, 0xD848, 0xDF1E}, - {0x2C30, 0xD848, 0xDFAD}, - {0x2C50, 0xD849, 0xDEF3}, - {0x2C65, 0xD84A, 0xDC5B}, - {0x2C6D, 0xD84A, 0xDCAB}, - {0x2C72, 0xD84A, 0xDD8F}, - {0x2D24, 0xD84A, 0xDEB8}, - {0x2D29, 0xD84A, 0xDF4F}, - {0x2D2A, 0xD84A, 0xDF50}, - {0x2D32, 0xD84A, 0xDF46}, - {0x2D34, 0xD84B, 0xDC1D}, - {0x2D35, 0xD84A, 0xDFA6}, - {0x2D39, 0xD84B, 0xDC24}, - {0x2D56, 0xD84B, 0xDDE1}, - {0x2D7D, 0xD84C, 0xDDC3}, - {0x2E23, 0xD84C, 0xDDF5}, - {0x2E24, 0xD84C, 0xDDB6}, - {0x2E3A, 0xD84C, 0xDF72}, - {0x2E3C, 0xD84C, 0xDFD3}, - {0x2E3D, 0xD84C, 0xDFD2}, - {0x2E42, 0xD84C, 0xDFD0}, - {0x2E43, 0xD84C, 0xDFE4}, - {0x2E44, 0xD84C, 0xDFD5}, - {0x2E47, 0xD84C, 0xDFDA}, - {0x2E49, 0xD84C, 0xDFDF}, - {0x2E55, 0xD84D, 0xDC4A}, - {0x2E56, 0xD84D, 0xDC51}, - {0x2E57, 0xD84D, 0xDC4B}, - {0x2E5B, 0xD84D, 0xDC65}, - {0x2E77, 0xD84D, 0xDCE4}, - {0x2E78, 0xD84D, 0xDD5A}, - {0x2F2A, 0xD84D, 0xDD94}, - {0x2F3F, 0xD84D, 0xDE39}, - {0x2F40, 0xD84D, 0xDE47}, - {0x2F42, 0xD84D, 0xDE38}, - {0x2F43, 0xD84D, 0xDE3A}, - {0x2F4E, 0xD84D, 0xDF1C}, - {0x2F59, 0xD84D, 0xDF0C}, - {0x2F61, 0xD84D, 0xDF64}, - {0x2F69, 0xD84D, 0xDFFF}, - {0x2F6A, 0xD84D, 0xDFE7}, - {0x2F70, 0xD84E, 0xDC24}, - {0x2F75, 0xD84E, 0xDC3D}, - {0x6E23, 0xD84E, 0xDE98}, - {0x6E34, 0xD84F, 0xDC7F}, - {0x6E49, 0xD84F, 0xDD00}, - {0x6E5C, 0xD84F, 0xDD40}, - {0x6E5E, 0xD84F, 0xDDFA}, - {0x6E5F, 0xD84F, 0xDDF9}, - {0x6E60, 0xD84F, 0xDDD3}, - {0x6F32, 0xD84F, 0xDF7E}, - {0x6F47, 0xD850, 0xDC96}, - {0x6F4D, 0xD850, 0xDD03}, - {0x6F61, 0xD850, 0xDDC6}, - {0x6F64, 0xD850, 0xDDFE}, - {0x7022, 0xD850, 0xDFBC}, - {0x7033, 0xD851, 0xDE29}, - {0x7039, 0xD851, 0xDEA5}, - {0x7053, 0xD852, 0xDC96}, - {0x707B, 0xD852, 0xDE4D}, - {0x712E, 0xD852, 0xDF56}, - {0x7130, 0xD852, 0xDF6F}, - {0x7135, 0xD853, 0xDC16}, - {0x7144, 0xD853, 0xDD14}, - {0x715D, 0xD853, 0xDE0E}, - {0x7161, 0xD853, 0xDE37}, - {0x7166, 0xD853, 0xDE6A}, - {0x7169, 0xD853, 0xDE8B}, - {0x7175, 0xD854, 0xDC4A}, - {0x7177, 0xD854, 0xDC55}, - {0x717A, 0xD854, 0xDD22}, - {0x7221, 0xD854, 0xDDA9}, - {0x7223, 0xD854, 0xDDE5}, - {0x7224, 0xD854, 0xDDCD}, - {0x7228, 0xD854, 0xDE1E}, - {0x722C, 0xD854, 0xDE4C}, - {0x723D, 0xD855, 0xDC2E}, - {0x7248, 0xD855, 0xDCD9}, - {0x725B, 0xD855, 0xDDA7}, - {0x7275, 0xD855, 0xDFA9}, - {0x7276, 0xD855, 0xDFB4}, - {0x7332, 0xD856, 0xDDD4}, - {0x733D, 0xD856, 0xDEE4}, - {0x733E, 0xD856, 0xDEE3}, - {0x7340, 0xD856, 0xDEF1}, - {0x7352, 0xD856, 0xDFB2}, - {0x735D, 0xD857, 0xDC4B}, - {0x735E, 0xD857, 0xDC64}, - {0x7373, 0xD857, 0xDE2E}, - {0x7374, 0xD857, 0xDE56}, - {0x7375, 0xD857, 0xDE65}, - {0x7377, 0xD857, 0xDE62}, - {0x737B, 0xD857, 0xDED8}, - {0x737D, 0xD857, 0xDEC2}, - {0x7422, 0xD857, 0xDEE8}, - {0x7424, 0xD857, 0xDF23}, - {0x7427, 0xD857, 0xDF5C}, - {0x742E, 0xD857, 0xDFE0}, - {0x742F, 0xD857, 0xDFD4}, - {0x7434, 0xD858, 0xDC0C}, - {0x7435, 0xD857, 0xDFFB}, - {0x743D, 0xD858, 0xDC17}, - {0x7442, 0xD858, 0xDC60}, - {0x744F, 0xD858, 0xDCED}, - {0x7469, 0xD858, 0xDE70}, - {0x746B, 0xD858, 0xDE86}, - {0x7472, 0xD858, 0xDF4C}, - {0x7475, 0xD84F, 0xDD0E}, - {0x7479, 0xD859, 0xDC02}, - {0x7535, 0xD859, 0xDE7E}, - {0x753A, 0xD859, 0xDEB0}, - {0x7546, 0xD859, 0xDF1D}, - {0x7556, 0xD85A, 0xDCDD}, - {0x7558, 0xD85A, 0xDCEA}, - {0x755A, 0xD85A, 0xDD51}, - {0x755D, 0xD85A, 0xDD6F}, - {0x755F, 0xD85A, 0xDDDD}, - {0x7563, 0xD85A, 0xDE1E}, - {0x756A, 0xD85A, 0xDE58}, - {0x7570, 0xD85A, 0xDE8C}, - {0x7573, 0xD85A, 0xDEB7}, - {0x7644, 0xD85B, 0xDC73}, - {0x764E, 0xD85B, 0xDCDD}, - {0x765D, 0xD85B, 0xDE65}, - {0x7675, 0xD85B, 0xDF94}, - {0x767E, 0xD85B, 0xDFF8}, - {0x7721, 0xD85B, 0xDFF6}, - {0x7722, 0xD85B, 0xDFF7}, - {0x7733, 0xD85C, 0xDD0D}, - {0x7736, 0xD85C, 0xDD39}, - {0x7764, 0xD85C, 0xDFDB}, - {0x7765, 0xD85C, 0xDFDA}, - {0x776B, 0xD85C, 0xDFFE}, - {0x776E, 0xD85D, 0xDC10}, - {0x7773, 0xD85D, 0xDC49}, - {0x7829, 0xD85D, 0xDE15}, - {0x782A, 0xD85D, 0xDE14}, - {0x782C, 0xD85D, 0xDE31}, - {0x7834, 0xD85D, 0xDE93}, - {0x783C, 0xD85D, 0xDF0E}, - {0x783E, 0xD85D, 0xDF23}, - {0x7842, 0xD85D, 0xDF52}, - {0x7856, 0xD85E, 0xDD85}, - {0x7863, 0xD85E, 0xDE84}, - {0x7877, 0xD85E, 0xDFB3}, - {0x7879, 0xD85E, 0xDFBE}, - {0x787A, 0xD85E, 0xDFC7}, - {0x7925, 0xD85F, 0xDCB8}, - {0x792F, 0xD85F, 0xDDA0}, - {0x7932, 0xD85F, 0xDE10}, - {0x7939, 0xD85F, 0xDFB7}, - {0x7942, 0xD860, 0xDC8A}, - {0x7948, 0xD860, 0xDCBB}, - {0x7959, 0xD860, 0xDE82}, - {0x795E, 0xD860, 0xDEF3}, - {0x7966, 0xD861, 0xDC0C}, - {0x796B, 0xD861, 0xDC55}, - {0x797A, 0xD861, 0xDD6B}, - {0x797E, 0xD861, 0xDDC8}, - {0x7A21, 0xD861, 0xDDC9}, - {0x7A2C, 0xD861, 0xDED7}, - {0x7A2F, 0xD861, 0xDEFA}, - {0x7A4F, 0xD862, 0xDD49}, - {0x7A50, 0xD862, 0xDD46}, - {0x7A57, 0xD862, 0xDD6B}, - {0x7A65, 0xD862, 0xDD87}, - {0x7A66, 0xD862, 0xDD88}, - {0x7A71, 0xD862, 0xDDBA}, - {0x7A72, 0xD862, 0xDDBB}, - {0x7A7E, 0xD862, 0xDE1E}, - {0x7B21, 0xD862, 0xDE29}, - {0x7B2C, 0xD862, 0xDE71}, - {0x7B2D, 0xD862, 0xDE43}, - {0x7B36, 0xD862, 0xDE99}, - {0x7B37, 0xD862, 0xDECD}, - {0x7B3D, 0xD862, 0xDEE4}, - {0x7B3E, 0xD862, 0xDEDD}, - {0x7B4E, 0xD862, 0xDFC1}, - {0x7B4F, 0xD862, 0xDFEF}, - {0x7B57, 0xD863, 0xDD10}, - {0x7B5A, 0xD863, 0xDD71}, - {0x7B5C, 0xD863, 0xDDFB}, - {0x7B5D, 0xD863, 0xDE1F}, - {0x7B61, 0xD863, 0xDE36}, - {0x7B65, 0xD863, 0xDE89}, - {0x7B67, 0xD863, 0xDEEB}, - {0x7B69, 0xD863, 0xDF32}, - {0x7B71, 0xD863, 0xDFF8}, - {0x7C22, 0xD864, 0xDEA0}, - {0x7C23, 0xD864, 0xDEB1}, - {0x7C38, 0xD865, 0xDC90}, - {0x7C42, 0xD865, 0xDDCF}, - {0x7C4C, 0xD865, 0xDE7F}, - {0x7C56, 0xD865, 0xDEF0}, - {0x7C59, 0xD865, 0xDF19}, - {0x7C5D, 0xD865, 0xDF50}, - {0x7C76, 0xD866, 0xDCC6}, - {0x7D2C, 0xD866, 0xDE72}, - {0x7D4B, 0xD867, 0xDDDB}, - {0x7D4C, 0xD867, 0xDE3D}, - {0x7D59, 0xD867, 0xDE15}, - {0x7D5B, 0xD867, 0xDE8A}, - {0x7D5D, 0xD867, 0xDE49}, - {0x7D67, 0xD867, 0xDEC4}, - {0x7D6D, 0xD867, 0xDEE9}, - {0x7D70, 0xD867, 0xDEDB}, - {0x7E25, 0xD867, 0xDFCE}, - {0x7E29, 0xD868, 0xDC2F}, - {0x7E2B, 0xD868, 0xDC1A}, - {0x7E32, 0xD868, 0xDCF9}, - {0x7E35, 0xD868, 0xDC82}, - {0x7E53, 0xD848, 0xDE18}, - {0x7E58, 0xD868, 0xDF8C}, - {0x7E5A, 0xD869, 0xDC37}, - {0x7E6E, 0xD869, 0xDDF1}, - {0x7E70, 0xD869, 0xDE02}, - {0x7E72, 0xD869, 0xDE1A}, - {0x7E76, 0xD869, 0xDEB2}, -}; -#endif /* UTF8_OUTPUT_ENABLE */ - -#ifdef UTF8_INPUT_ENABLE -static const unsigned short utf8_to_euc_C2[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xA242, 0x2171, 0x2172, 0xA270, 0x216F, 0xA243, 0x2178, - 0x212F, 0xA26D, 0xA26C, 0, 0x224C, 0, 0xA26E, 0xA234, - 0x216B, 0x215E, 0, 0, 0x212D, 0, 0x2279, 0, - 0xA231, 0, 0xA26B, 0, 0, 0, 0, 0xA244, -}; -static const unsigned short utf8_to_euc_C2_ms[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xA242, 0x2171, 0x2172, 0xA270, 0x5C, 0xA243, 0x2178, - 0x212F, 0xA26D, 0xA26C, 0, 0x224C, 0, 0xA26E, 0xA234, - 0x216B, 0x215E, 0, 0, 0x212D, 0, 0x2279, 0, - 0xA231, 0, 0xA26B, 0, 0, 0, 0, 0xA244, -}; -static const unsigned short utf8_to_euc_C2_mac[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x00A0, 0xA242, 0x2171, 0x2172, 0xA270, 0x5C, 0xA243, 0x2178, - 0x212F, 0x00FD, 0xA26C, 0, 0x224C, 0, 0xA26E, 0xA234, - 0x216B, 0x215E, 0, 0, 0x212D, 0, 0x2279, 0, - 0xA231, 0, 0xA26B, 0, 0, 0, 0, 0xA244, -}; -static const unsigned short utf8_to_euc_C2_932[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x21, 0x2171, 0x2172, 0, 0x5C, 0x7C, 0x2178, - 0x212F, 0x63, 0x61, 0x2263, 0x224C, 0x2D, 0x52, 0x2131, - 0x216B, 0x215E, 0x32, 0x33, 0x212D, 0x264C, 0x2279, 0x2126, - 0x2124, 0x31, 0x6F, 0x2264, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_C2_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2922, 0x2923, 0x2171, 0x2172, 0x2924, 0x216F, 0x2925, 0x2178, - 0x212F, 0x2926, 0x2927, 0x2928, 0x224C, 0x2929, 0x292A, 0x292B, - 0x216B, 0x215E, 0x292C, 0x292D, 0x212D, 0, 0x2279, 0x292E, - 0x292F, 0x2930, 0x2931, 0x2932, 0x2933, 0x2934, 0x2935, 0x2936, -}; -static const unsigned short utf8_to_euc_C3[] = { - 0xAA22, 0xAA21, 0xAA24, 0xAA2A, 0xAA23, 0xAA29, 0xA921, 0xAA2E, - 0xAA32, 0xAA31, 0xAA34, 0xAA33, 0xAA40, 0xAA3F, 0xAA42, 0xAA41, - 0, 0xAA50, 0xAA52, 0xAA51, 0xAA54, 0xAA58, 0xAA53, 0x215F, - 0xA92C, 0xAA63, 0xAA62, 0xAA65, 0xAA64, 0xAA72, 0xA930, 0xA94E, - 0xAB22, 0xAB21, 0xAB24, 0xAB2A, 0xAB23, 0xAB29, 0xA941, 0xAB2E, - 0xAB32, 0xAB31, 0xAB34, 0xAB33, 0xAB40, 0xAB3F, 0xAB42, 0xAB41, - 0xA943, 0xAB50, 0xAB52, 0xAB51, 0xAB54, 0xAB58, 0xAB53, 0x2160, - 0xA94C, 0xAB63, 0xAB62, 0xAB65, 0xAB64, 0xAB72, 0xA950, 0xAB73, -}; -static const unsigned short utf8_to_euc_C3_932[] = { - 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x43, - 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, - 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x215F, - 0x4F, 0x55, 0x55, 0x55, 0x55, 0x59, 0x54, 0x73, - 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x63, - 0x65, 0x65, 0x65, 0x65, 0x69, 0x69, 0x69, 0x69, - 0x64, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x2160, - 0x6F, 0x75, 0x75, 0x75, 0x75, 0x79, 0x74, 0x79, -}; -static const unsigned short utf8_to_euc_C3_x0213[] = { - 0x2937, 0x2938, 0x2939, 0x293A, 0x293B, 0x293C, 0x293D, 0x293E, - 0x293F, 0x2940, 0x2941, 0x2942, 0x2943, 0x2944, 0x2945, 0x2946, - 0x2947, 0x2948, 0x2949, 0x294A, 0x294B, 0x294C, 0x294D, 0x215F, - 0x294E, 0x294F, 0x2950, 0x2951, 0x2952, 0x2953, 0x2954, 0x2955, - 0x2956, 0x2957, 0x2958, 0x2959, 0x295A, 0x295B, 0x295C, 0x295D, - 0x295E, 0x295F, 0x2960, 0x2961, 0x2962, 0x2963, 0x2964, 0x2965, - 0x2966, 0x2967, 0x2968, 0x2969, 0x296A, 0x296B, 0x296C, 0x2160, - 0x296D, 0x296E, 0x296F, 0x2970, 0x2971, 0x2972, 0x2973, 0x2974, -}; -static const unsigned short utf8_to_euc_C4[] = { - 0xAA27, 0xAB27, 0xAA25, 0xAB25, 0xAA28, 0xAB28, 0xAA2B, 0xAB2B, - 0xAA2C, 0xAB2C, 0xAA2F, 0xAB2F, 0xAA2D, 0xAB2D, 0xAA30, 0xAB30, - 0xA922, 0xA942, 0xAA37, 0xAB37, 0, 0, 0xAA36, 0xAB36, - 0xAA38, 0xAB38, 0xAA35, 0xAB35, 0xAA3A, 0xAB3A, 0xAA3B, 0xAB3B, - 0xAA3D, 0xAB3D, 0xAA3C, 0, 0xAA3E, 0xAB3E, 0xA924, 0xA944, - 0xAA47, 0xAB47, 0xAA45, 0xAB45, 0, 0, 0xAA46, 0xAB46, - 0xAA44, 0xA945, 0xA926, 0xA946, 0xAA48, 0xAB48, 0xAA49, 0xAB49, - 0xA947, 0xAA4A, 0xAB4A, 0xAA4C, 0xAB4C, 0xAA4B, 0xAB4B, 0xA929, -}; -static const unsigned short utf8_to_euc_C4_x0213[] = { - 0x2975, 0x297A, 0x2A3A, 0x2A49, 0x2A21, 0x2A2C, 0x2A3C, 0x2A4B, - 0x2A59, 0x2A5F, 0xAA2F, 0xAB2F, 0x2A3D, 0x2A4C, 0x2A40, 0x2A4F, - 0xA922, 0x2A50, 0x2978, 0x297D, 0, 0, 0xAA36, 0xAB36, - 0x2A3E, 0x2A4D, 0x2A3F, 0x2A4E, 0x2A5A, 0x2A60, 0xAA3B, 0xAB3B, - 0xAA3D, 0xAB3D, 0xAA3C, 0, 0x2A5B, 0x2A61, 0xA924, 0x2A7D, - 0xAA47, 0xAB47, 0x2976, 0x297B, 0, 0, 0xAA46, 0xAB46, - 0xAA44, 0xA945, 0xA926, 0xA946, 0x2A5C, 0x2A62, 0xAA49, 0xAB49, - 0xA947, 0x2A3B, 0x2A4A, 0xAA4C, 0xAB4C, 0x2A24, 0x2A2F, 0xA929, -}; -static const unsigned short utf8_to_euc_C5[] = { - 0xA949, 0xA928, 0xA948, 0xAA4D, 0xAB4D, 0xAA4F, 0xAB4F, 0xAA4E, - 0xAB4E, 0xA94A, 0xA92B, 0xA94B, 0xAA57, 0xAB57, 0, 0, - 0xAA56, 0xAB56, 0xA92D, 0xA94D, 0xAA59, 0xAB59, 0xAA5B, 0xAB5B, - 0xAA5A, 0xAB5A, 0xAA5C, 0xAB5C, 0xAA5D, 0xAB5D, 0xAA5F, 0xAB5F, - 0xAA5E, 0xAB5E, 0xAA61, 0xAB61, 0xAA60, 0xAB60, 0xA92F, 0xA94F, - 0xAA6C, 0xAB6C, 0xAA69, 0xAB69, 0xAA66, 0xAB66, 0xAA6B, 0xAB6B, - 0xAA68, 0xAB68, 0xAA6A, 0xAB6A, 0xAA71, 0xAB71, 0xAA74, 0xAB74, - 0xAA73, 0xAA75, 0xAB75, 0xAA77, 0xAB77, 0xAA76, 0xAB76, 0, -}; -static const unsigned short utf8_to_euc_C5_x0213[] = { - 0xA949, 0x2A23, 0x2A2E, 0x2A41, 0x2A51, 0xAA4F, 0xAB4F, 0x2A42, - 0x2A52, 0xA94A, 0xA92B, 0x2A7A, 0x2979, 0x297E, 0, 0, - 0x2A43, 0x2A53, 0x2B2B, 0x2B2A, 0x2A39, 0x2A48, 0xAA5B, 0xAB5B, - 0x2A44, 0x2A54, 0x2A25, 0x2A30, 0x2A5D, 0x2A63, 0x2A27, 0x2A33, - 0x2A26, 0x2A32, 0x2A47, 0x2A57, 0x2A28, 0x2A34, 0xA92F, 0xA94F, - 0xAA6C, 0xAB6C, 0x2977, 0x297C, 0x2A5E, 0x2A64, 0x2A45, 0x2A55, - 0x2A46, 0x2A56, 0xAA6A, 0xAB6A, 0xAA71, 0xAB71, 0xAA74, 0xAB74, - 0xAA73, 0x2A29, 0x2A35, 0x2A2B, 0x2A38, 0x2A2A, 0x2A37, 0, -}; -static const unsigned short utf8_to_euc_C6_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x2B29, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_C7[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xAA26, 0xAB26, 0xAA43, - 0xAB43, 0xAA55, 0xAB55, 0xAA67, 0xAB67, 0xAA70, 0xAB70, 0xAA6D, - 0xAB6D, 0xAA6F, 0xAB6F, 0xAA6E, 0xAB6E, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xAB39, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_C7_x0213[] = { - 0, 0, 0x2B24, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x286F, 0x2870, 0xAA43, - 0x2871, 0x2876, 0x2877, 0xAA67, 0x2878, 0xAA70, 0x2879, 0xAA6D, - 0x287A, 0xAA6F, 0x287B, 0xAA6E, 0x287C, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xAB39, 0, 0, - 0x2874, 0x2875, 0, 0, 0, 0x2B45, 0, 0, -}; -static const unsigned short utf8_to_euc_C9_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2B33, 0x2B39, 0x2B3A, 0x2B25, 0x2B38, 0x2B3F, 0x2A6E, 0x2B26, - 0x2B2E, 0x2B30, 0x2B43, 0, 0x2B31, 0, 0x2B32, 0x2A75, - 0x2B28, 0x2A79, 0, 0, 0x2B36, 0x2B3C, 0x2B22, 0x2B42, - 0x2B2C, 0, 0, 0, 0x2A6A, 0x2A74, 0x2A6B, 0x2B34, - 0x2A7B, 0x2A65, 0x2A76, 0x2A6F, 0, 0x2B2F, 0, 0, - 0, 0x2A6C, 0x2B41, 0x2A73, 0, 0x2A70, 0x2A67, 0, -}; -static const unsigned short utf8_to_euc_CA_x0213[] = { - 0, 0x2A7C, 0x2A71, 0x2A68, 0x2B27, 0, 0, 0, - 0x2A6D, 0x2B2D, 0x2B35, 0x2A66, 0x2B37, 0x2B3B, 0x2A78, 0, - 0x2A72, 0x2B40, 0x2A69, 0, 0x2B21, 0x2A7E, 0, 0, - 0x2B23, 0, 0, 0, 0, 0x2A77, 0, 0, - 0, 0x2B3E, 0x2B3D, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_CB[] = { - 0, 0, 0, 0, 0, 0, 0, 0xA230, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xA22F, 0xA232, 0xA236, 0xA235, 0, 0xA233, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_CB_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0x2A31, - 0x2B53, 0, 0, 0, 0x2B54, 0, 0, 0, - 0x2B55, 0x2B56, 0, 0, 0, 0, 0, 0, - 0x2A22, 0x2A58, 0xA236, 0x2A2D, 0, 0x2A36, 0x2B71, 0, - 0, 0, 0, 0, 0, 0x2B60, 0x2B61, 0x2B62, - 0x2B63, 0x2B64, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_CC_x0213[] = { - 0x2B5C, 0x2B5A, 0x2B5F, 0x2B7D, 0x2B5B, 0, 0x2B57, 0, - 0x2B6D, 0, 0, 0x2B59, 0x2B5E, 0, 0, 0x2B5D, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2B78, 0x2B79, 0x2B7E, 0, 0x2B6A, 0x2B76, 0x2B77, 0x2B6B, - 0x2B6C, 0, 0, 0, 0x2B72, 0x2B67, 0, 0, - 0, 0x2B6F, 0x2B7A, 0, 0x2B68, 0, 0, 0x2B70, - 0x2B73, 0, 0, 0, 0x2B75, 0, 0, 0, - 0, 0x2B69, 0x2B7B, 0x2B7C, 0x2B74, 0x2B6E, 0, 0, -}; -static const unsigned short utf8_to_euc_CD_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x2B52, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_CE[] = { - 0, 0, 0, 0, 0xA238, 0xA239, 0xA661, 0, - 0xA662, 0xA663, 0xA664, 0, 0xA667, 0, 0xA669, 0xA66C, - 0xA676, 0x2621, 0x2622, 0x2623, 0x2624, 0x2625, 0x2626, 0x2627, - 0x2628, 0x2629, 0x262A, 0x262B, 0x262C, 0x262D, 0x262E, 0x262F, - 0x2630, 0x2631, 0, 0x2632, 0x2633, 0x2634, 0x2635, 0x2636, - 0x2637, 0x2638, 0xA665, 0xA66A, 0xA671, 0xA672, 0xA673, 0xA674, - 0xA67B, 0x2641, 0x2642, 0x2643, 0x2644, 0x2645, 0x2646, 0x2647, - 0x2648, 0x2649, 0x264A, 0x264B, 0x264C, 0x264D, 0x264E, 0x264F, -}; -static const unsigned short utf8_to_euc_CF[] = { - 0x2650, 0x2651, 0xA678, 0x2652, 0x2653, 0x2654, 0x2655, 0x2656, - 0x2657, 0x2658, 0xA675, 0xA67A, 0xA677, 0xA679, 0xA67C, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_CF_x0213[] = { - 0x2650, 0x2651, 0x2659, 0x2652, 0x2653, 0x2654, 0x2655, 0x2656, - 0x2657, 0x2658, 0xA675, 0xA67A, 0xA677, 0xA679, 0xA67C, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_D0[] = { - 0, 0x2727, 0xA742, 0xA743, 0xA744, 0xA745, 0xA746, 0xA747, - 0xA748, 0xA749, 0xA74A, 0xA74B, 0xA74C, 0, 0xA74D, 0xA74E, - 0x2721, 0x2722, 0x2723, 0x2724, 0x2725, 0x2726, 0x2728, 0x2729, - 0x272A, 0x272B, 0x272C, 0x272D, 0x272E, 0x272F, 0x2730, 0x2731, - 0x2732, 0x2733, 0x2734, 0x2735, 0x2736, 0x2737, 0x2738, 0x2739, - 0x273A, 0x273B, 0x273C, 0x273D, 0x273E, 0x273F, 0x2740, 0x2741, - 0x2751, 0x2752, 0x2753, 0x2754, 0x2755, 0x2756, 0x2758, 0x2759, - 0x275A, 0x275B, 0x275C, 0x275D, 0x275E, 0x275F, 0x2760, 0x2761, -}; -static const unsigned short utf8_to_euc_D1[] = { - 0x2762, 0x2763, 0x2764, 0x2765, 0x2766, 0x2767, 0x2768, 0x2769, - 0x276A, 0x276B, 0x276C, 0x276D, 0x276E, 0x276F, 0x2770, 0x2771, - 0, 0x2757, 0xA772, 0xA773, 0xA774, 0xA775, 0xA776, 0xA777, - 0xA778, 0xA779, 0xA77A, 0xA77B, 0xA77C, 0, 0xA77D, 0xA77E, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E1B8_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x2872, 0x2873, -}; -static const unsigned short utf8_to_euc_E1BD_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2B46, 0x2B47, 0x2B50, 0x2B51, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E280[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x213E, 0, 0, 0, 0x213D, 0x213D, 0x2142, 0, - 0x2146, 0x2147, 0, 0, 0x2148, 0x2149, 0, 0, - 0x2277, 0x2278, 0, 0, 0, 0x2145, 0x2144, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2273, 0, 0x216C, 0x216D, 0, 0, 0, 0, - 0, 0, 0, 0x2228, 0, 0, 0x2131, 0, -}; -static const unsigned short utf8_to_euc_E280_ms[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x213E, 0, 0, 0, 0x213D, 0x213D, 0x2142, 0, - 0x2146, 0x2147, 0, 0, 0x2148, 0x2149, 0, 0, - 0x2277, 0x2278, 0, 0, 0, 0x2145, 0x2144, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2273, 0, 0x216C, 0x216D, 0, 0, 0, 0, - 0, 0, 0, 0x2228, 0, 0, 0x7E, 0, -}; -static const unsigned short utf8_to_euc_E280_932[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x213E, 0, 0, 0, 0, 0x213D, 0, 0, - 0x2146, 0x2147, 0, 0, 0x2148, 0x2149, 0, 0, - 0x2277, 0x2278, 0, 0, 0, 0x2145, 0x2144, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2273, 0, 0x216C, 0x216D, 0, 0, 0, 0, - 0, 0, 0, 0x2228, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E280_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x213E, 0, 0, 0x237C, 0x213D, 0x213D, 0x2142, 0, - 0x2146, 0x2147, 0, 0, 0x2148, 0x2149, 0, 0, - 0x2277, 0x2278, 0x2340, 0, 0, 0x2145, 0x2144, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2273, 0, 0x216C, 0x216D, 0, 0, 0, 0, - 0, 0, 0, 0x2228, 0x286B, 0, 0x2131, 0x2B58, -}; -static const unsigned short utf8_to_euc_E281_x0213[] = { - 0, 0, 0x2C7E, 0, 0, 0, 0, 0x286C, - 0x286D, 0x286E, 0, 0, 0, 0, 0, 0, - 0, 0x2C7D, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E282_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x2921, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E284[] = { - 0, 0, 0, 0x216E, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x2D62, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x2D64, 0xA26F, 0, 0, 0, 0, 0, - 0, 0, 0, 0x2272, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E284_mac[] = { - 0, 0, 0, 0x216E, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x2B7B, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x2B7D, 0x00FE, 0, 0, 0, 0, 0, - 0, 0, 0, 0x2272, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E284_x0213[] = { - 0, 0, 0, 0x216E, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x235D, - 0, 0, 0, 0x235F, 0, 0, 0x2D62, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x2D64, 0xA26F, 0, 0, 0, 0, 0x2360, - 0, 0, 0, 0x2272, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x235C, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E285[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2D35, 0x2D36, 0x2D37, 0x2D38, 0x2D39, 0x2D3A, 0x2D3B, 0x2D3C, - 0x2D3D, 0x2D3E, 0, 0, 0, 0, 0, 0, - 0xF373, 0xF374, 0xF375, 0xF376, 0xF377, 0xF378, 0xF379, 0xF37A, - 0xF37B, 0xF37C, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E285_mac[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2A21, 0x2A22, 0x2A23, 0x2A24, 0x2A25, 0x2A26, 0x2A27, 0x2A28, - 0x2A29, 0x2A2A, 0, 0, 0, 0, 0, 0, - 0x2A35, 0x2A36, 0x2A37, 0x2A38, 0x2A39, 0x2A3A, 0x2A3B, 0x2A3C, - 0x2A3D, 0x2A3E, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E285_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x2778, 0x2779, 0x277A, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2D35, 0x2D36, 0x2D37, 0x2D38, 0x2D39, 0x2D3A, 0x2D3B, 0x2D3C, - 0x2D3D, 0x2D3E, 0x2D3F, 0x2D57, 0, 0, 0, 0, - 0x2C35, 0x2C36, 0x2C37, 0x2C38, 0x2C39, 0x2C3A, 0x2C3B, 0x2C3C, - 0x2C3D, 0x2C3E, 0x2C3F, 0x2C40, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E286[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x222B, 0x222C, 0x222A, 0x222D, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E286_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x222B, 0x222C, 0x222A, 0x222D, 0x2271, 0, 0x2327, 0x2325, - 0x2326, 0x2328, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E287[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x224D, 0, 0x224E, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E287_x0213[] = { - 0, 0, 0, 0, 0x2329, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x224D, 0, 0x224E, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x232B, 0x232C, - 0x232A, 0x232D, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E288[] = { - 0x224F, 0, 0x225F, 0x2250, 0, 0, 0, 0x2260, - 0x223A, 0, 0, 0x223B, 0, 0, 0, 0, - 0, 0x2D74, 0x215D, 0, 0, 0, 0, 0, - 0, 0, 0x2265, 0, 0, 0x2267, 0x2167, 0x2D78, - 0x225C, 0, 0, 0, 0, 0x2142, 0, 0x224A, - 0x224B, 0x2241, 0x2240, 0x2269, 0x226A, 0, 0x2D73, 0, - 0, 0, 0, 0, 0x2168, 0x2268, 0, 0, - 0, 0, 0, 0, 0, 0x2266, 0, 0, -}; -static const unsigned short utf8_to_euc_E288_932[] = { - 0x224F, 0, 0x225F, 0x2250, 0, 0, 0, 0x2260, - 0x223A, 0, 0, 0x223B, 0, 0, 0, 0, - 0, 0x2D74, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2265, 0, 0, 0x2267, 0x2167, 0x2D78, - 0x225C, 0, 0, 0, 0, 0x2142, 0, 0x224A, - 0x224B, 0x2241, 0x2240, 0x2269, 0x226A, 0, 0x2D73, 0, - 0, 0, 0, 0, 0x2168, 0x2268, 0, 0, - 0, 0, 0, 0, 0, 0x2266, 0, 0, -}; -static const unsigned short utf8_to_euc_E288_mac[] = { - 0x224F, 0, 0x225F, 0x2250, 0, 0, 0, 0x2260, - 0x223A, 0, 0, 0x223B, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2265, 0, 0, 0x2267, 0x2167, 0x2F22, - 0x225C, 0, 0, 0, 0, 0x2142, 0, 0x224A, - 0x224B, 0x2241, 0x2240, 0x2269, 0x226A, 0, 0x2F21, 0, - 0, 0, 0, 0, 0x2168, 0x2268, 0, 0, - 0, 0, 0, 0, 0, 0x2266, 0, 0, -}; -static const unsigned short utf8_to_euc_E288_x0213[] = { - 0x224F, 0, 0x225F, 0x2250, 0, 0x2247, 0, 0x2260, - 0x223A, 0x2246, 0, 0x223B, 0, 0, 0, 0, - 0, 0x2D74, 0x215D, 0x235B, 0, 0, 0, 0, - 0, 0, 0x2265, 0, 0, 0x2267, 0x2167, 0x2D78, - 0x225C, 0, 0, 0, 0, 0x2254, 0x2255, 0x224A, - 0x224B, 0x2241, 0x2240, 0x2269, 0x226A, 0, 0x2D73, 0, - 0, 0, 0, 0, 0x2168, 0x2268, 0, 0, - 0, 0, 0, 0, 0, 0x2266, 0, 0, -}; -static const unsigned short utf8_to_euc_E289[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2262, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2162, 0x2261, 0, 0, 0, 0, 0x2165, 0x2166, - 0, 0, 0x2263, 0x2264, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E289_x0213[] = { - 0, 0, 0, 0x226C, 0, 0x226D, 0, 0, - 0x226E, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2262, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2162, 0x2261, 0x226B, 0, 0, 0, 0x2165, 0x2166, - 0, 0, 0x2263, 0x2264, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x226F, 0x2270, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E28A[] = { - 0, 0, 0x223E, 0x223F, 0, 0, 0x223C, 0x223D, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x225D, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x2D79, -}; -static const unsigned short utf8_to_euc_E28A_mac[] = { - 0, 0, 0x223E, 0x223F, 0, 0, 0x223C, 0x223D, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x225D, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x2F23, -}; -static const unsigned short utf8_to_euc_E28A_x0213[] = { - 0, 0, 0x223E, 0x223F, 0x2242, 0x2243, 0x223C, 0x223D, - 0, 0, 0x2244, 0x2245, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x2251, 0x2252, 0x2253, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x225D, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x2D79, -}; -static const unsigned short utf8_to_euc_E28B_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2776, 0x2777, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E28C[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x225E, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E28C_x0213[] = { - 0, 0, 0, 0, 0, 0x2248, 0x2249, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x225E, 0, 0, 0, 0, 0, - 0x277C, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E28E_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x2742, 0x2743, -}; -static const unsigned short utf8_to_euc_E28F_x0213[] = { - 0x2744, 0x2745, 0x2746, 0x2747, 0x2748, 0x2749, 0x274A, 0x274B, - 0x274C, 0x274D, 0x274E, 0x274F, 0x2750, 0, 0x277E, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E290_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x277D, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E291[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2D21, 0x2D22, 0x2D23, 0x2D24, 0x2D25, 0x2D26, 0x2D27, 0x2D28, - 0x2D29, 0x2D2A, 0x2D2B, 0x2D2C, 0x2D2D, 0x2D2E, 0x2D2F, 0x2D30, - 0x2D31, 0x2D32, 0x2D33, 0x2D34, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E291_mac[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2921, 0x2922, 0x2923, 0x2924, 0x2925, 0x2926, 0x2927, 0x2928, - 0x2929, 0x292A, 0x292B, 0x292C, 0x292D, 0x292E, 0x292F, 0x2930, - 0x2931, 0x2932, 0x2933, 0x2934, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E293_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2C41, 0x2C42, 0x2C43, 0x2C44, 0x2C45, 0x2C46, 0x2C47, 0x2C48, - 0x2C49, 0x2C4A, 0x2C4B, 0x2C4C, 0x2C4D, 0x2C4E, 0x2C4F, 0x2C50, - 0x2C51, 0x2C52, 0x2C53, 0x2C54, 0x2C55, 0x2C56, 0x2C57, 0x2C58, - 0x2C59, 0x2C5A, 0, 0x2C2B, 0x2C2C, 0x2C2D, 0x2C2E, 0x2C2F, - 0x2C30, 0x2C31, 0x2C32, 0x2C33, 0x2C34, 0x265A, 0x265B, 0x265C, - 0x265D, 0x265E, 0x265F, 0x2660, 0x2661, 0x2662, 0x2663, 0, -}; -static const unsigned short utf8_to_euc_E294[] = { - 0x2821, 0x282C, 0x2822, 0x282D, 0, 0, 0, 0, - 0, 0, 0, 0, 0x2823, 0, 0, 0x282E, - 0x2824, 0, 0, 0x282F, 0x2826, 0, 0, 0x2831, - 0x2825, 0, 0, 0x2830, 0x2827, 0x283C, 0, 0, - 0x2837, 0, 0, 0x2832, 0x2829, 0x283E, 0, 0, - 0x2839, 0, 0, 0x2834, 0x2828, 0, 0, 0x2838, - 0x283D, 0, 0, 0x2833, 0x282A, 0, 0, 0x283A, - 0x283F, 0, 0, 0x2835, 0x282B, 0, 0, 0x283B, -}; -static const unsigned short utf8_to_euc_E295[] = { - 0, 0, 0x2840, 0, 0, 0, 0, 0, - 0, 0, 0, 0x2836, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E296[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2223, 0x2222, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2225, 0x2224, 0, 0, 0, 0, - 0, 0, 0, 0, 0x2227, 0x2226, 0, 0, -}; -static const unsigned short utf8_to_euc_E296_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2223, 0x2222, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x266D, 0x2225, 0x2224, 0, 0, 0x2322, 0x2321, - 0, 0, 0, 0, 0x2227, 0x2226, 0, 0, -}; -static const unsigned short utf8_to_euc_E297[] = { - 0, 0, 0, 0, 0, 0, 0x2221, 0x217E, - 0, 0, 0, 0x217B, 0, 0, 0x217D, 0x217C, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x227E, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E297_x0213[] = { - 0x2324, 0x2323, 0, 0, 0, 0, 0x2221, 0x217E, - 0, 0x233B, 0, 0x217B, 0, 0, 0x217D, 0x217C, - 0x2867, 0x2868, 0x2869, 0x286A, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x233F, 0, - 0, 0, 0, 0, 0, 0, 0, 0x227E, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E298[] = { - 0, 0, 0, 0, 0, 0x217A, 0x2179, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E298_x0213[] = { - 0x2668, 0x2669, 0x266A, 0x266B, 0, 0x217A, 0x2179, 0, - 0, 0, 0, 0, 0, 0, 0x2667, 0, - 0, 0, 0, 0, 0, 0, 0x2664, 0x2665, - 0, 0, 0, 0, 0, 0, 0x2D7E, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E299[] = { - 0x216A, 0, 0x2169, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2276, 0, 0, 0x2275, 0, 0x2274, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E299_x0213[] = { - 0x216A, 0, 0x2169, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x263A, 0x263D, 0x263B, 0x2640, 0x2639, 0x263E, 0x263C, 0x263F, - 0x266C, 0x227D, 0x2276, 0x227B, 0x227C, 0x2275, 0x227A, 0x2274, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E29C_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x277B, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E29D_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x2D7D, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x2C21, 0x2C22, - 0x2C23, 0x2C24, 0x2C25, 0x2C26, 0x2C27, 0x2C28, 0x2C29, 0x2C2A, -}; -static const unsigned short utf8_to_euc_E2A4_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x232E, 0x232F, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E2A6_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x233A, -}; -static const unsigned short utf8_to_euc_E2A7_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x237D, 0x237E, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E380[] = { - 0x2121, 0x2122, 0x2123, 0x2137, 0, 0x2139, 0x213A, 0x213B, - 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, - 0x215A, 0x215B, 0x2229, 0x222E, 0x214C, 0x214D, 0, 0, - 0, 0, 0, 0, 0x2141, 0x2D60, 0, 0x2D61, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E380_932[] = { - 0x2121, 0x2122, 0x2123, 0x2137, 0, 0x2139, 0x213A, 0x213B, - 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, - 0x215A, 0x215B, 0x2229, 0x222E, 0x214C, 0x214D, 0, 0, - 0, 0, 0, 0, 0, 0x2D60, 0, 0x2D61, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E380_x0213[] = { - 0x2121, 0x2122, 0x2123, 0x2137, 0, 0x2139, 0x213A, 0x213B, - 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, - 0x215A, 0x215B, 0x2229, 0x222E, 0x214C, 0x214D, 0x225A, 0x225B, - 0x2258, 0x2259, 0, 0, 0x2141, 0x2D60, 0, 0x2D61, - 0x2666, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x2233, 0x2234, 0x2235, 0, 0, - 0, 0, 0, 0x2236, 0x2237, 0x233C, 0, 0, -}; -static const unsigned short utf8_to_euc_E381[] = { - 0, 0x2421, 0x2422, 0x2423, 0x2424, 0x2425, 0x2426, 0x2427, - 0x2428, 0x2429, 0x242A, 0x242B, 0x242C, 0x242D, 0x242E, 0x242F, - 0x2430, 0x2431, 0x2432, 0x2433, 0x2434, 0x2435, 0x2436, 0x2437, - 0x2438, 0x2439, 0x243A, 0x243B, 0x243C, 0x243D, 0x243E, 0x243F, - 0x2440, 0x2441, 0x2442, 0x2443, 0x2444, 0x2445, 0x2446, 0x2447, - 0x2448, 0x2449, 0x244A, 0x244B, 0x244C, 0x244D, 0x244E, 0x244F, - 0x2450, 0x2451, 0x2452, 0x2453, 0x2454, 0x2455, 0x2456, 0x2457, - 0x2458, 0x2459, 0x245A, 0x245B, 0x245C, 0x245D, 0x245E, 0x245F, -}; -static const unsigned short utf8_to_euc_E382[] = { - 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, - 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, 0x246F, - 0x2470, 0x2471, 0x2472, 0x2473, 0, 0, 0, 0, - 0, 0, 0, 0x212B, 0x212C, 0x2135, 0x2136, 0, - 0, 0x2521, 0x2522, 0x2523, 0x2524, 0x2525, 0x2526, 0x2527, - 0x2528, 0x2529, 0x252A, 0x252B, 0x252C, 0x252D, 0x252E, 0x252F, - 0x2530, 0x2531, 0x2532, 0x2533, 0x2534, 0x2535, 0x2536, 0x2537, - 0x2538, 0x2539, 0x253A, 0x253B, 0x253C, 0x253D, 0x253E, 0x253F, -}; -static const unsigned short utf8_to_euc_E382_932[] = { - 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, - 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, 0x246F, - 0x2470, 0x2471, 0x2472, 0x2473, 0x2574, 0, 0, 0, - 0, 0, 0, 0x212B, 0x212C, 0x2135, 0x2136, 0, - 0, 0x2521, 0x2522, 0x2523, 0x2524, 0x2525, 0x2526, 0x2527, - 0x2528, 0x2529, 0x252A, 0x252B, 0x252C, 0x252D, 0x252E, 0x252F, - 0x2530, 0x2531, 0x2532, 0x2533, 0x2534, 0x2535, 0x2536, 0x2537, - 0x2538, 0x2539, 0x253A, 0x253B, 0x253C, 0x253D, 0x253E, 0x253F, -}; -static const unsigned short utf8_to_euc_E382_x0213[] = { - 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, - 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, 0x246F, - 0x2470, 0x2471, 0x2472, 0x2473, 0x2474, 0x2475, 0x2476, 0, - 0, 0, 0, 0x212B, 0x212C, 0x2135, 0x2136, 0x2239, - 0x237B, 0x2521, 0x2522, 0x2523, 0x2524, 0x2525, 0x2526, 0x2527, - 0x2528, 0x2529, 0x252A, 0x252B, 0x252C, 0x252D, 0x252E, 0x252F, - 0x2530, 0x2531, 0x2532, 0x2533, 0x2534, 0x2535, 0x2536, 0x2537, - 0x2538, 0x2539, 0x253A, 0x253B, 0x253C, 0x253D, 0x253E, 0x253F, -}; -static const unsigned short utf8_to_euc_E383[] = { - 0x2540, 0x2541, 0x2542, 0x2543, 0x2544, 0x2545, 0x2546, 0x2547, - 0x2548, 0x2549, 0x254A, 0x254B, 0x254C, 0x254D, 0x254E, 0x254F, - 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555, 0x2556, 0x2557, - 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E, 0x255F, - 0x2560, 0x2561, 0x2562, 0x2563, 0x2564, 0x2565, 0x2566, 0x2567, - 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0x256D, 0x256E, 0x256F, - 0x2570, 0x2571, 0x2572, 0x2573, 0x2574, 0x2575, 0x2576, 0, - 0, 0, 0, 0x2126, 0x213C, 0x2133, 0x2134, 0, -}; -static const unsigned short utf8_to_euc_E383_x0213[] = { - 0x2540, 0x2541, 0x2542, 0x2543, 0x2544, 0x2545, 0x2546, 0x2547, - 0x2548, 0x2549, 0x254A, 0x254B, 0x254C, 0x254D, 0x254E, 0x254F, - 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555, 0x2556, 0x2557, - 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E, 0x255F, - 0x2560, 0x2561, 0x2562, 0x2563, 0x2564, 0x2565, 0x2566, 0x2567, - 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0x256D, 0x256E, 0x256F, - 0x2570, 0x2571, 0x2572, 0x2573, 0x2574, 0x2575, 0x2576, 0x2772, - 0x2773, 0x2774, 0x2775, 0x2126, 0x213C, 0x2133, 0x2134, 0x2238, -}; -static const unsigned short utf8_to_euc_E387_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x266E, 0x266F, 0x2670, 0x2671, 0x2672, 0x2673, 0x2674, 0x2675, - 0x2676, 0x2677, 0x2679, 0x267A, 0x267B, 0x267C, 0x267D, 0x267E, -}; -static const unsigned short utf8_to_euc_E388[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x2D6A, 0x2D6B, 0, 0, 0, 0, 0, - 0, 0x2D6C, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E388_mac[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x2D2E, 0x2D31, 0, 0, 0, 0, 0, - 0, 0x2D2C, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E389_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x2841, 0x2842, 0x2843, 0x2844, 0x2845, 0x2846, 0x2847, - 0x2848, 0x2849, 0x284A, 0x284B, 0x284C, 0x284D, 0x284E, 0x284F, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E38A[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x2D65, 0x2D66, 0x2D67, 0x2D68, - 0x2D69, 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 unsigned short utf8_to_euc_E38A_mac[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x2D73, 0x2D74, 0x2D75, 0x2D76, - 0x2D77, 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 unsigned short utf8_to_euc_E38A_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x2D65, 0x2D66, 0x2D67, 0x2D68, - 0x2D69, 0, 0, 0, 0, 0, 0, 0, - 0, 0x2850, 0x2851, 0x2852, 0x2853, 0x2854, 0x2855, 0x2856, - 0x2857, 0x2858, 0x2859, 0x285A, 0x285B, 0x285C, 0x285D, 0x285E, -}; -static const unsigned short utf8_to_euc_E38B_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2C5B, 0x2C5C, 0x2C5D, 0x2C5E, 0x2C5F, 0x2C60, 0x2C61, 0x2C62, - 0x2C63, 0x2C64, 0x2C65, 0x2C66, 0x2C67, 0x2C68, 0x2C69, 0x2C6A, - 0x2C6B, 0x2C6C, 0x2C6D, 0x2C6E, 0, 0x2C71, 0, 0, - 0, 0x2C70, 0, 0, 0x2C73, 0x2C72, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2C6F, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E38C[] = { - 0, 0, 0, 0x2D46, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x2D4A, 0, 0, - 0, 0, 0, 0, 0x2D41, 0, 0, 0, - 0x2D44, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2D42, 0x2D4C, 0, 0, 0x2D4B, 0x2D45, - 0, 0, 0, 0x2D4D, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x2D47, 0, - 0, 0, 0, 0x2D4F, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E38C_mac[] = { - 0, 0, 0, 0x2E29, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x2E32, 0, 0, - 0, 0, 0, 0, 0x2E24, 0, 0, 0, - 0x2E2B, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2E22, 0x2E34, 0, 0, 0x2E35, 0x2E2D, - 0, 0, 0, 0x2E37, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x2E2A, 0, - 0, 0, 0, 0x2E36, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E38D[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x2D40, 0x2D4E, 0, 0, 0x2D43, 0, 0, - 0, 0x2D48, 0, 0, 0, 0, 0, 0x2D49, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x2D5F, 0x2D6F, 0x2D6E, 0x2D6D, 0, -}; -static const unsigned short utf8_to_euc_E38D_mac[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x2E21, 0x2E2F, 0, 0, 0x2E23, 0, 0, - 0, 0x2E2E, 0, 0, 0, 0, 0, 0x2E31, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x2E6A, 0x2E69, 0x2E68, 0x2E67, 0, -}; -static const unsigned short utf8_to_euc_E38E[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x2D53, 0x2D54, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x2D50, 0x2D51, 0x2D52, 0, - 0, 0x2D56, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E38E_mac[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x2B2B, 0x2B2D, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x2B21, 0x2B23, 0x2B29, 0, - 0, 0x2B27, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E38F[] = { - 0, 0, 0, 0, 0x2D55, 0, 0, 0, - 0, 0, 0, 0, 0, 0x2D63, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E38F_mac[] = { - 0, 0, 0, 0, 0x2B2E, 0, 0, 0, - 0, 0, 0, 0, 0, 0x2B7C, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E38F_x0213[] = { - 0, 0, 0, 0, 0x2D55, 0, 0, 0, - 0, 0, 0, 0x235E, 0, 0x2D63, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E390_x0213[] = { - 0, 0, 0x2E23, 0, 0, 0, 0xA12D, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xA132, 0, 0xA133, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E391_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xA15E, 0, 0xA156, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E392_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xA17E, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x2E53, 0, 0, - 0, 0, 0, 0, 0xA32B, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E393_x0213[] = { - 0, 0xF468, 0, 0, 0, 0, 0, 0xA32F, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x2E5B, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E394_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xA348, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E395_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xA35D, 0xA35E, 0, - 0, 0, 0, 0xA361, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xA367, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E396_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xA423, 0, - 0xA426, 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 unsigned short utf8_to_euc_E397_x0213[] = { - 0, 0, 0, 0, 0, 0xA42F, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xA438, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xA442, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E398_x0213[] = { - 0, 0, 0, 0, 0, 0xA44A, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E399_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xA479, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E39A_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xA53F, 0, 0, 0, 0, 0xA543, 0, - 0, 0xA541, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E39B_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xA557, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E39D_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xA823, 0xA825, 0, 0, 0, 0, 0, - 0, 0, 0, 0xA829, 0xA828, 0, 0, 0, - 0, 0, 0, 0, 0, 0xA82C, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E39E_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x4F5F, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E39F_x0213[] = { - 0, 0xA83E, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x4F6F, 0, 0, 0, 0, 0, - 0xA856, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xA859, 0, 0, 0, - 0, 0, 0, 0, 0, 0xA85C, 0, 0, -}; -static const unsigned short utf8_to_euc_E3A0_x0213[] = { - 0xA85E, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xA86F, - 0, 0, 0, 0, 0, 0, 0xA871, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3A1_x0213[] = { - 0xA874, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xA879, 0, 0, 0, - 0, 0xA87B, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E3A3_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xAC3B, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3A4_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xAC46, - 0, 0, 0xAC4A, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E3A5_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xAC60, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3A9_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xAD5B, 0, - 0, 0, 0, 0xAD5F, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3AB_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xAD71, 0xAE36, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xAD7C, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3AC_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xAE2E, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xAE32, 0, 0xAE34, 0, 0, 0, - 0, 0, 0x7549, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E3AD_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xAE6D, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xAE65, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3AE_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0xAF28, - 0xAF29, 0, 0, 0, 0, 0xAF2C, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xAF34, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x757E, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3AF_x0213[] = { - 0, 0, 0, 0x7621, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xAF48, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xAF5D, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3B0_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x763A, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xAF77, 0, - 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 unsigned short utf8_to_euc_E3B3_x0213[] = { - 0, 0, 0, 0xEE3B, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xEE42, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E3B4_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xEE71, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xEE7E, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E3B5_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xEF40, 0, 0, 0, - 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 unsigned short utf8_to_euc_E3B6_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xEF54, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E3B7_x0213[] = { - 0xEF70, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xEF77, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E3B8_x0213[] = { - 0, 0, 0, 0, 0, 0xF028, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x7766, -}; -static const unsigned short utf8_to_euc_E3B9_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xF03F, 0, 0, 0, 0, 0, 0xF041, 0, - 0xF042, 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 unsigned short utf8_to_euc_E3BA_x0213[] = { - 0, 0, 0, 0xF049, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xF050, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E3BD_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xF134, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x784D, 0, 0, 0xF146, 0, 0xF148, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3BE_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xF15C, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3BF_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xF167, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xF16C, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E480_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xF222, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E481_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xF22D, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E482_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xF239, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E484_x0213[] = { - 0, 0, 0, 0, 0, 0xF264, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E485_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0xF274, 0, 0, 0, 0, 0, 0, 0xF277, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xF27D, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E486_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xF333, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xF337, -}; -static const unsigned short utf8_to_euc_E487_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xF347, 0, - 0, 0, 0, 0, 0, 0, 0xF34B, 0, - 0, 0, 0, 0xF348, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E488_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0xF353, - 0, 0, 0, 0, 0, 0, 0xF357, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E489_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x796D, 0, 0, 0, - 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 unsigned short utf8_to_euc_E48B_x0213[] = { - 0, 0, 0, 0, 0, 0, 0xF42B, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xF436, 0, - 0, 0, 0, 0, 0, 0xF43B, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E48C_x0213[] = { - 0, 0, 0xF44E, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xF45D, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E48D_x0213[] = { - 0, 0, 0, 0xF461, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E48F_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xF53E, 0, - 0xF542, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E490_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0xF548, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xF54A, - 0, 0, 0, 0, 0xF54C, 0, 0, 0, - 0, 0, 0xF54F, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E491_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x7A59, 0, 0, 0, 0, - 0, 0, 0, 0x7A5A, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xF56C, 0, - 0, 0, 0xF56E, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E492_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xF577, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xF635, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xF632, 0, -}; -static const unsigned short utf8_to_euc_E493_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xF634, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E494_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0xF659, 0, 0, 0, 0, 0xF654, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xF66D, 0, 0, - 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 unsigned short utf8_to_euc_E495_x0213[] = { - 0, 0, 0, 0xF66E, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E496_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x7B51, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xF74F, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E497_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xF76C, 0, 0, - 0, 0, 0x7B60, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E498_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xF824, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E499_x0213[] = { - 0, 0xF83A, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xF843, 0, 0, - 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 unsigned short utf8_to_euc_E49A_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xF84E, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xF853, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E49C_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xF86B, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E49D_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xF929, 0, 0, 0, - 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 unsigned short utf8_to_euc_E49F_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xF93F, 0, 0, -}; -static const unsigned short utf8_to_euc_E4A0_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xF949, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E4A1_x0213[] = { - 0, 0, 0, 0, 0x7C4B, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xF95C, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E4A2_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFA27, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E4A6_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x7D58, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E4A7_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xFB6A, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFB70, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E4A8_x0213[] = { - 0, 0, 0, 0, 0xFB75, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFB78, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E4AA_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFC37, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E4AC_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFC55, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E4AF_x0213[] = { - 0, 0, 0xFD26, 0, 0, 0, 0, 0, - 0, 0, 0xFD28, 0, 0, 0, 0, 0, - 0, 0, 0xFD2A, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFD31, 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 unsigned short utf8_to_euc_E4B0_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x7E3E, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFD3F, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E4B3_x0213[] = { - 0, 0, 0, 0, 0xFE2A, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFE2D, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E4B4_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0xFE4B, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E4B5_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xFE60, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E4B8[] = { - 0x306C, 0x437A, 0xB021, 0x3C37, 0xB022, 0xB023, 0, 0x4B7C, - 0x3E66, 0x3B30, 0x3E65, 0x323C, 0xB024, 0x4954, 0x4D3F, 0, - 0x5022, 0x312F, 0xB025, 0, 0x336E, 0x5023, 0x4024, 0x5242, - 0x3556, 0x4A3A, 0, 0, 0, 0, 0x3E67, 0xB026, - 0, 0x4E3E, 0, 0xB027, 0xB028, 0, 0x4A42, 0, - 0xB029, 0, 0x5024, 0xB02A, 0, 0x4366, 0xB02B, 0xB02C, - 0xB02D, 0x5025, 0x367A, 0, 0, 0xB02E, 0x5026, 0, - 0x345D, 0x4330, 0, 0x3C67, 0x5027, 0, 0, 0x5028, -}; -static const unsigned short utf8_to_euc_E4B8_x0213[] = { - 0x306C, 0x437A, 0xA122, 0x3C37, 0xB022, 0xB023, 0, 0x4B7C, - 0x3E66, 0x3B30, 0x3E65, 0x323C, 0xB024, 0x4954, 0x4D3F, 0xA123, - 0x5022, 0x312F, 0xA124, 0, 0x336E, 0x5023, 0x4024, 0x5242, - 0x3556, 0x4A3A, 0, 0, 0, 0, 0x3E67, 0xB026, - 0, 0x4E3E, 0, 0xB027, 0xB028, 0, 0x4A42, 0, - 0x2E24, 0xA125, 0x5024, 0xA126, 0xF02E, 0x4366, 0xA127, 0x2E25, - 0x2E26, 0x5025, 0x367A, 0, 0, 0xB02E, 0x5026, 0, - 0x345D, 0x4330, 0, 0x3C67, 0x5027, 0, 0, 0x5028, -}; -static const unsigned short utf8_to_euc_E4B9[] = { - 0xB02F, 0xB030, 0x5029, 0x4735, 0xB031, 0x3557, 0, 0xB032, - 0, 0, 0, 0x4737, 0, 0x4663, 0x3843, 0x4B33, - 0, 0xB033, 0, 0, 0, 0x6949, 0x502A, 0x3E68, - 0x502B, 0x3235, 0xB034, 0, 0xB035, 0x3665, 0x3870, 0x4C69, - 0, 0, 0x5626, 0xB036, 0, 0, 0, 0, - 0xB037, 0xB038, 0, 0, 0, 0, 0, 0, - 0, 0x4D70, 0, 0x467D, 0xB039, 0xB03A, 0, 0, - 0, 0xB03B, 0, 0, 0, 0, 0x3425, 0xB03C, -}; -static const unsigned short utf8_to_euc_E4B9_x0213[] = { - 0xA128, 0xB030, 0x5029, 0x4735, 0xB031, 0x3557, 0, 0xA129, - 0xA12A, 0, 0, 0x4737, 0, 0x4663, 0x3843, 0x4B33, - 0, 0xA12C, 0, 0, 0, 0x6949, 0x502A, 0x3E68, - 0x502B, 0x3235, 0xA12F, 0, 0xB035, 0x3665, 0x3870, 0x4C69, - 0, 0, 0x5626, 0xB036, 0, 0, 0, 0, - 0xB037, 0xA130, 0, 0, 0, 0, 0, 0, - 0, 0x4D70, 0, 0x467D, 0xB039, 0xB03A, 0, 0, - 0, 0xB03B, 0, 0, 0, 0, 0x3425, 0xB03C, -}; -static const unsigned short utf8_to_euc_E4BA[] = { - 0x3535, 0, 0x502C, 0, 0, 0x502D, 0x4E3B, 0, - 0x4D3D, 0x4168, 0x502F, 0x3B76, 0x4673, 0xB03D, 0x5032, 0, - 0, 0x313E, 0x385F, 0, 0x385E, 0x3066, 0xB03E, 0xB03F, - 0x4F4B, 0x4F4A, 0, 0x3A33, 0x3021, 0xB040, 0x5033, 0x5034, - 0x5035, 0x4B34, 0x5036, 0, 0x3872, 0x3067, 0x4B72, 0, - 0x357C, 0, 0, 0x357D, 0x357E, 0x4462, 0x4E3C, 0xB041, - 0x5037, 0, 0, 0x5038, 0, 0, 0x5039, 0, - 0, 0xB042, 0x3F4D, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E4BA_x0213[] = { - 0x3535, 0, 0x502C, 0, 0, 0x502D, 0x4E3B, 0, - 0x4D3D, 0x4168, 0x502F, 0x3B76, 0x4673, 0x2E27, 0x5032, 0, - 0, 0x313E, 0x385F, 0, 0x385E, 0x3066, 0xB03E, 0xB03F, - 0x4F4B, 0x4F4A, 0, 0x3A33, 0x3021, 0xA131, 0x5033, 0x5034, - 0x5035, 0x4B34, 0x5036, 0, 0x3872, 0x3067, 0x4B72, 0, - 0x357C, 0, 0, 0x357D, 0x357E, 0x4462, 0x4E3C, 0xB041, - 0x5037, 0, 0, 0x5038, 0, 0, 0x5039, 0, - 0, 0xA134, 0x3F4D, 0xA135, 0xA137, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E4BB[] = { - 0x3D3A, 0x3F4E, 0x503E, 0xB043, 0x503C, 0, 0x503D, 0x3558, - 0, 0, 0x3A23, 0x3270, 0, 0x503B, 0x503A, 0x4A29, - 0xB044, 0, 0, 0, 0x3B46, 0x3B45, 0x423E, 0x503F, - 0x4955, 0x4067, 0xB045, 0xB046, 0, 0x2138, 0x5040, 0x5042, - 0xB047, 0xB048, 0xB049, 0x4265, 0x4E61, 0x304A, 0, 0, - 0xB04A, 0, 0, 0, 0, 0x5041, 0x323E, 0xB04B, - 0x3644, 0xB04C, 0x4367, 0xB04D, 0, 0xB04E, 0x376F, 0x5043, - 0, 0, 0, 0x4724, 0xF42F, 0xB04F, 0xB050, 0xB051, -}; -static const unsigned short utf8_to_euc_E4BB_x0213[] = { - 0x3D3A, 0x3F4E, 0x503E, 0xA138, 0x503C, 0, 0x503D, 0x3558, - 0xA139, 0, 0x3A23, 0x3270, 0, 0x503B, 0x503A, 0x4A29, - 0xA13A, 0, 0, 0, 0x3B46, 0x3B45, 0x423E, 0x503F, - 0x4955, 0x4067, 0xA13C, 0xB046, 0, 0x2138, 0x5040, 0x5042, - 0xB047, 0x2E28, 0xB049, 0x4265, 0x4E61, 0x304A, 0, 0, - 0xB04A, 0, 0, 0xA13B, 0, 0x5041, 0x323E, 0xB04B, - 0x3644, 0xA13D, 0x4367, 0xB04D, 0, 0xA13E, 0x376F, 0x5043, - 0, 0, 0, 0x4724, 0, 0x2E29, 0xB050, 0x2E2A, -}; -static const unsigned short utf8_to_euc_E4BC[] = { - 0xB052, 0x346B, 0xB053, 0xB054, 0, 0, 0, 0, - 0xB055, 0x5044, 0x304B, 0xB056, 0xB057, 0x3860, 0x346C, 0x497A, - 0x4832, 0x3559, 0xB058, 0, 0, 0xB059, 0xB05A, 0xB05B, - 0, 0xB05C, 0x3271, 0, 0x5067, 0x4541, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xB05D, 0x476C, - 0x5046, 0xB05E, 0, 0xB060, 0x483C, 0xB061, 0x4E62, 0xB062, - 0x3F2D, 0xB063, 0x3B47, 0xB064, 0x3B77, 0x3240, 0xB065, 0, -}; -static const unsigned short utf8_to_euc_E4BC_x0213[] = { - 0xA13F, 0x346B, 0xB053, 0x2E2B, 0, 0, 0, 0, - 0xB055, 0x5044, 0x304B, 0x2E2C, 0xB057, 0x3860, 0x346C, 0x497A, - 0x4832, 0x3559, 0xB058, 0, 0, 0xB059, 0xA140, 0xB05B, - 0, 0xB05C, 0x3271, 0, 0x5067, 0x4541, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xB05D, 0x476C, - 0x5046, 0xB05E, 0, 0xB060, 0x483C, 0xB061, 0x4E62, 0xA142, - 0x3F2D, 0, 0x3B47, 0xB064, 0x3B77, 0x3240, 0xA143, 0, -}; -static const unsigned short utf8_to_euc_E4BD[] = { - 0xB066, 0, 0xB067, 0x4451, 0, 0, 0x4322, 0x504A, - 0xB068, 0xB069, 0, 0xB06A, 0xB06B, 0x304C, 0x4463, 0x3D3B, - 0x3A34, 0x4D24, 0xB06C, 0x424E, 0xB06D, 0x323F, 0xB06E, 0x5049, - 0xB06F, 0x4D3E, 0x5045, 0x5047, 0x3A6E, 0x5048, 0x5524, 0xB070, - 0xB05F, 0, 0, 0xB071, 0, 0, 0, 0, - 0, 0x5050, 0xB072, 0, 0xB073, 0, 0xB074, 0x5053, - 0x5051, 0xB075, 0, 0x3242, 0, 0x4A3B, 0x504B, 0xB076, - 0xB077, 0xB078, 0xB079, 0x504F, 0x3873, 0xB07A, 0xB07B, 0x3B48, -}; -static const unsigned short utf8_to_euc_E4BD_x0213[] = { - 0xB066, 0, 0xB067, 0x4451, 0, 0, 0x4322, 0x504A, - 0x2E2E, 0x2E2F, 0, 0xB06A, 0xB06B, 0x304C, 0x4463, 0x3D3B, - 0x3A34, 0x4D24, 0xB06C, 0x424E, 0xA144, 0x323F, 0x2E30, 0x5049, - 0xA145, 0x4D3E, 0x5045, 0x5047, 0x3A6E, 0x5048, 0x5524, 0x2E31, - 0x2E2D, 0, 0, 0xB071, 0xA141, 0, 0, 0, - 0, 0x5050, 0x2E32, 0, 0x2E33, 0, 0xB074, 0x5053, - 0x5051, 0xB075, 0, 0x3242, 0, 0x4A3B, 0x504B, 0xA147, - 0xA148, 0xB078, 0xA149, 0x504F, 0x3873, 0xA14A, 0x2E34, 0x3B48, -}; -static const unsigned short utf8_to_euc_E4BE[] = { - 0, 0xB07C, 0xB07D, 0x3426, 0xB07E, 0xB121, 0x5054, 0, - 0x504C, 0xB122, 0xB123, 0x4E63, 0xB124, 0x3B78, 0xB125, 0x504D, - 0xB126, 0x5052, 0xB127, 0xB128, 0xB129, 0, 0x5055, 0xB12A, - 0x504E, 0xB12B, 0xB12C, 0x3621, 0, 0x304D, 0xB12D, 0xB12E, - 0x3622, 0x3241, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x5525, 0, 0x4B79, 0x496E, 0x3874, - 0, 0, 0xB12F, 0, 0, 0x3F2F, 0x4E37, 0xB130, - 0, 0xB131, 0, 0xB132, 0xB133, 0xB134, 0xB135, 0x4A58, -}; -static const unsigned short utf8_to_euc_E4BE_x0213[] = { - 0, 0xB07C, 0xA14B, 0x3426, 0xB07E, 0xA14C, 0x5054, 0, - 0x504C, 0xB122, 0x2E35, 0x4E63, 0xB124, 0x3B78, 0xB125, 0x504D, - 0xB126, 0x5052, 0xA14D, 0xB128, 0x2E36, 0, 0x5055, 0x2E37, - 0x504E, 0xB12B, 0xA14E, 0x3621, 0, 0x304D, 0xB12D, 0xB12E, - 0x3622, 0x3241, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x5525, 0, 0x4B79, 0x496E, 0x3874, - 0, 0, 0xA150, 0, 0, 0x3F2F, 0x4E37, 0xB130, - 0, 0xB131, 0, 0xB132, 0xB133, 0xB134, 0xA151, 0x4A58, -}; -static const unsigned short utf8_to_euc_E4BF[] = { - 0xB136, 0xB137, 0x3738, 0x4225, 0x3264, 0xB138, 0xB139, 0, - 0xB13A, 0xB13B, 0x3D53, 0xB13C, 0xB13D, 0xB13E, 0x5059, 0xB13F, - 0x505E, 0x505C, 0xB140, 0, 0x5057, 0, 0, 0x422F, - 0x505A, 0, 0x505D, 0x505B, 0xB141, 0x4A5D, 0, 0x5058, - 0xB142, 0x3F2E, 0xB143, 0x4B73, 0x505F, 0x5060, 0, 0, - 0, 0, 0, 0, 0, 0, 0x3D24, 0x506D, - 0xB144, 0, 0xB145, 0x4750, 0, 0x4936, 0x5068, 0, - 0x4A70, 0, 0x3236, 0, 0xB146, 0xB147, 0x506C, 0xB148, -}; -static const unsigned short utf8_to_euc_E4BF_x0213[] = { - 0xB136, 0xB137, 0x3738, 0x4225, 0x3264, 0xA152, 0xB139, 0, - 0xB13A, 0x2E39, 0x3D53, 0xA153, 0xB13D, 0, 0x5059, 0xA154, - 0x505E, 0x505C, 0xA155, 0, 0x5057, 0, 0, 0x422F, - 0x505A, 0, 0x505D, 0x505B, 0xB141, 0x4A5D, 0, 0x5058, - 0x2E3A, 0x3F2E, 0xB143, 0x4B73, 0x505F, 0x5060, 0xA14F, 0, - 0, 0, 0, 0, 0, 0, 0x3D24, 0x506D, - 0xB144, 0x2E21, 0xA157, 0x4750, 0, 0x4936, 0x5068, 0, - 0x4A70, 0, 0x3236, 0, 0xB146, 0xB147, 0x506C, 0, -}; -static const unsigned short utf8_to_euc_E580[] = { - 0xB149, 0xB14A, 0, 0, 0xB14B, 0x5066, 0x506F, 0xB14C, - 0, 0x4152, 0xB14D, 0x3844, 0xB14E, 0x475C, 0xB14F, 0x6047, - 0xB150, 0x506E, 0x455D, 0xB151, 0x5063, 0, 0x3876, 0xB152, - 0xB153, 0x3875, 0x5061, 0xB154, 0xB155, 0xB156, 0xB157, 0x3C5A, - 0, 0x5069, 0xB158, 0x4A6F, 0x434D, 0x5065, 0x3771, 0xB159, - 0x5062, 0x506A, 0x5064, 0x4E51, 0x506B, 0x4F41, 0xB15A, 0, - 0xB15B, 0, 0xB15C, 0xB15D, 0, 0xB15E, 0x3666, 0, - 0, 0x3770, 0, 0xB176, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E580_x0213[] = { - 0xA158, 0x2E3B, 0x2E3C, 0, 0xB14B, 0x5066, 0x506F, 0xB14C, - 0, 0x4152, 0xB14D, 0x3844, 0xB14E, 0x475C, 0x2E3D, 0x6047, - 0xA159, 0x506E, 0x455D, 0xA15A, 0x5063, 0, 0x3876, 0xB152, - 0x2E3E, 0x3875, 0x5061, 0xB154, 0xA15B, 0xB156, 0xA15C, 0x3C5A, - 0, 0x5069, 0xA15D, 0x4A6F, 0x434D, 0x5065, 0x3771, 0x2E3F, - 0x5062, 0x506A, 0x5064, 0x4E51, 0x506B, 0x4F41, 0x2E40, 0, - 0xB15B, 0, 0xB15C, 0xB15D, 0, 0xB15E, 0x3666, 0, - 0, 0x3770, 0, 0x2E42, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E581[] = { - 0xB15F, 0xB160, 0xB161, 0x5070, 0, 0xB162, 0xB163, 0x5071, - 0x5075, 0x304E, 0xB164, 0, 0xB165, 0, 0xB166, 0x4A50, - 0x5074, 0xB167, 0xB168, 0xB169, 0, 0x5073, 0x5077, 0xB16A, - 0, 0xB16B, 0x5076, 0, 0x4464, 0, 0, 0xB16C, - 0xB16D, 0, 0xB16E, 0xB16F, 0, 0x3772, 0xB170, 0xB171, - 0, 0, 0xB172, 0, 0x5078, 0xB173, 0, 0, - 0xB174, 0xB175, 0x3C45, 0, 0x4226, 0x4465, 0x3676, 0, - 0x5079, 0, 0, 0, 0, 0x3536, 0, 0, -}; -static const unsigned short utf8_to_euc_E581_x0213[] = { - 0x2E41, 0x2E43, 0xA15F, 0x5070, 0, 0xB162, 0xA160, 0x5071, - 0x5075, 0x304E, 0xB164, 0, 0xB165, 0, 0xA161, 0x4A50, - 0x5074, 0xB167, 0xB168, 0xA162, 0, 0x5073, 0x5077, 0xA163, - 0, 0xB16B, 0x5076, 0, 0x4464, 0, 0, 0xB16C, - 0xB16D, 0, 0xB16E, 0xA164, 0, 0x3772, 0xA165, 0xB171, - 0, 0, 0xA166, 0, 0x5078, 0xB173, 0, 0, - 0xA167, 0xB175, 0x3C45, 0, 0x4226, 0x4465, 0x3676, 0, - 0x5079, 0, 0, 0, 0, 0x3536, 0, 0, -}; -static const unsigned short utf8_to_euc_E582[] = { - 0x507A, 0xB177, 0, 0xB178, 0xB179, 0x507C, 0xB17A, 0, - 0, 0, 0xB17B, 0, 0, 0x4B35, 0xB17C, 0xB17D, - 0xB17E, 0x3766, 0xB221, 0xB222, 0xB223, 0, 0xB224, 0, - 0x3B31, 0x4877, 0x507B, 0xB225, 0xB226, 0, 0xB227, 0xB228, - 0xB229, 0xB22A, 0xB22B, 0, 0, 0, 0, 0, - 0, 0, 0xB22C, 0, 0x3A45, 0x4D43, 0, 0xB22D, - 0xB22E, 0, 0x507E, 0x5123, 0x507D, 0x3A44, 0, 0x3D7D, - 0, 0xB22F, 0xB230, 0, 0, 0xB231, 0x3739, 0, -}; -static const unsigned short utf8_to_euc_E582_x0213[] = { - 0x507A, 0xB177, 0, 0xB178, 0xB179, 0x507C, 0xB17A, 0, - 0xA169, 0, 0xB17B, 0, 0, 0x4B35, 0xB17C, 0xB17D, - 0xB17E, 0x3766, 0xA16A, 0xA16B, 0x2E44, 0xA16C, 0xA16D, 0, - 0x3B31, 0x4877, 0x507B, 0xB225, 0xA16E, 0, 0xB227, 0xB228, - 0xB229, 0xB22A, 0xB22B, 0xA168, 0, 0, 0, 0, - 0, 0, 0xA16F, 0, 0x3A45, 0x4D43, 0, 0xB22D, - 0xB22E, 0xA171, 0x507E, 0x5123, 0x507D, 0x3A44, 0, 0x3D7D, - 0, 0xB22F, 0xA172, 0xA173, 0, 0xB231, 0x3739, 0, -}; -static const unsigned short utf8_to_euc_E583[] = { - 0xB232, 0, 0x5124, 0xB233, 0xB234, 0x364F, 0, 0xB235, - 0, 0x5121, 0x5122, 0, 0xB236, 0x462F, 0xB237, 0x417C, - 0xB238, 0x3623, 0, 0xB239, 0xB23A, 0x4B4D, 0x5125, 0, - 0xB23B, 0, 0x4E3D, 0, 0xB23C, 0xB23D, 0x5126, 0xB23E, - 0, 0, 0xB23F, 0x5129, 0xB240, 0x5127, 0xB241, 0x414E, - 0xB242, 0xB243, 0, 0, 0, 0x5128, 0x512A, 0xB244, - 0, 0xB245, 0xB251, 0, 0xF430, 0x512C, 0xB246, 0, - 0, 0x512B, 0xB247, 0x4A48, 0, 0, 0xB248, 0, -}; -static const unsigned short utf8_to_euc_E583_x0213[] = { - 0xB232, 0, 0x5124, 0xB233, 0xA174, 0x364F, 0, 0xA175, - 0, 0x5121, 0x5122, 0, 0x2E45, 0x462F, 0xA178, 0x417C, - 0x2E47, 0x3623, 0, 0xB239, 0xA17A, 0x4B4D, 0x5125, 0, - 0, 0xA17B, 0x4E3D, 0, 0xB23C, 0xB23D, 0x5126, 0xB23E, - 0, 0xA17C, 0xB23F, 0x5129, 0xB240, 0x5127, 0x2E48, 0x414E, - 0xB242, 0xA17D, 0, 0, 0, 0x5128, 0x512A, 0xB244, - 0, 0xB245, 0x2E46, 0xA176, 0, 0x512C, 0xB246, 0, - 0, 0x512B, 0xB247, 0x4A48, 0, 0, 0xB248, 0, -}; -static const unsigned short utf8_to_euc_E584[] = { - 0x3537, 0x512E, 0x512F, 0xB249, 0x322F, 0, 0xB24A, 0xB24B, - 0xB24C, 0x512D, 0, 0xB24D, 0xB24E, 0xB24F, 0xB250, 0, - 0xB252, 0, 0x3C74, 0, 0x5132, 0x5131, 0x5130, 0xB253, - 0x5056, 0xB254, 0x5133, 0xB255, 0xB256, 0xB257, 0xB258, 0x3D7E, - 0, 0x5134, 0, 0xB259, 0, 0, 0, 0xB25A, - 0xB25B, 0, 0x4D25, 0, 0xB25C, 0xB25D, 0, 0xB25E, - 0, 0xB25F, 0x4C59, 0xB260, 0xB261, 0xB262, 0, 0x5136, - 0xB263, 0xB264, 0x5135, 0x5138, 0x5137, 0, 0, 0x5139, -}; -static const unsigned short utf8_to_euc_E584_x0213[] = { - 0x3537, 0x512E, 0x512F, 0x2E4B, 0x322F, 0, 0x2E4A, 0xB24B, - 0xA321, 0x512D, 0, 0x2E4C, 0xB24E, 0xB24F, 0xB250, 0, - 0xB252, 0, 0x3C74, 0, 0x5132, 0x5131, 0x5130, 0xA323, - 0x5056, 0xB254, 0x5133, 0xA324, 0xB256, 0xB257, 0x2E4D, 0x3D7E, - 0, 0x5134, 0, 0xB259, 0, 0, 0, 0xB25A, - 0xB25B, 0, 0x4D25, 0, 0xB25C, 0xB25D, 0, 0xB25E, - 0, 0xB25F, 0x4C59, 0xB260, 0xB261, 0x2E4E, 0, 0x5136, - 0xB263, 0xB264, 0x5135, 0x5138, 0x5137, 0, 0, 0x5139, -}; -static const unsigned short utf8_to_euc_E585[] = { - 0x513A, 0x3074, 0xB265, 0x3835, 0x373B, 0x3D3C, 0x437B, 0x3624, - 0x4068, 0x3877, 0xB266, 0x396E, 0x513C, 0x4C48, 0x4546, 0xB267, - 0x3B79, 0, 0x513B, 0xB268, 0x513D, 0xB269, 0, 0xB26A, - 0xB26B, 0, 0x455E, 0, 0x3375, 0, 0, 0xB26C, - 0, 0, 0x513E, 0, 0xB26D, 0x467E, 0xB26E, 0, - 0x4134, 0x5140, 0x5141, 0x482C, 0x3878, 0x4F3B, 0x5142, 0, - 0, 0x3626, 0, 0, 0, 0x4A3C, 0x4236, 0x3671, - 0x4535, 0, 0, 0, 0x3773, 0, 0xB26F, 0, -}; -static const unsigned short utf8_to_euc_E585_x0213[] = { - 0x513A, 0x3074, 0xB265, 0x3835, 0x373B, 0x3D3C, 0x437B, 0x3624, - 0x4068, 0x3877, 0x2E4F, 0x396E, 0x513C, 0x4C48, 0x4546, 0xB267, - 0x3B79, 0, 0x513B, 0xB268, 0x513D, 0x2E51, 0, 0x2E52, - 0xB26B, 0, 0x455E, 0, 0x3375, 0, 0, 0xB26C, - 0xA326, 0, 0x513E, 0, 0, 0x467E, 0xB26E, 0, - 0x4134, 0x5140, 0x5141, 0x482C, 0x3878, 0x4F3B, 0x5142, 0, - 0, 0x3626, 0, 0xA328, 0, 0x4A3C, 0x4236, 0x3671, - 0x4535, 0, 0, 0xF474, 0x3773, 0, 0xB26F, 0, -}; -static const unsigned short utf8_to_euc_E586[] = { - 0x5143, 0, 0x5144, 0xB270, 0xB271, 0x4662, 0x315F, 0, - 0, 0x5147, 0x3A7D, 0xB272, 0x5146, 0x3A46, 0xB273, 0x5148, - 0x666E, 0x5149, 0x4B41, 0x514A, 0, 0x514B, 0x514C, 0x3E69, - 0xB274, 0x3C4C, 0, 0, 0, 0xB275, 0, 0, - 0x3427, 0xB276, 0x514F, 0xB277, 0x514D, 0x4C3D, 0x514E, 0, - 0x495A, 0x5150, 0x5151, 0x5152, 0x455F, 0xB278, 0, 0, - 0x5156, 0x5154, 0x5155, 0x5153, 0x3A63, 0x5157, 0x4C6A, 0x4E64, - 0xB279, 0, 0xB27A, 0, 0xB27B, 0x5158, 0xB27C, 0xB27D, -}; -static const unsigned short utf8_to_euc_E586_x0213[] = { - 0x5143, 0, 0x5144, 0xA329, 0xB271, 0x4662, 0x315F, 0, - 0, 0x5147, 0x3A7D, 0xA32A, 0x5146, 0x3A46, 0xB273, 0x5148, - 0x666E, 0x5149, 0x4B41, 0x514A, 0, 0x514B, 0x514C, 0x3E69, - 0xA32C, 0x3C4C, 0, 0, 0, 0x2E54, 0, 0, - 0x3427, 0xB276, 0x514F, 0xA32D, 0x514D, 0x4C3D, 0x514E, 0, - 0x495A, 0x5150, 0x5151, 0x5152, 0x455F, 0xA32E, 0, 0, - 0x5156, 0x5154, 0x5155, 0x5153, 0x3A63, 0x5157, 0x4C6A, 0x4E64, - 0xB279, 0, 0xB27A, 0, 0xA330, 0x5158, 0, 0xB27D, -}; -static const unsigned short utf8_to_euc_E587[] = { - 0, 0, 0xB27E, 0, 0x4028, 0x5159, 0x3D5A, 0, - 0xB321, 0x515A, 0, 0x437C, 0x4E3F, 0x4560, 0, 0xB322, - 0, 0xB323, 0xB324, 0xB325, 0, 0xB326, 0x5245, 0, - 0xB327, 0, 0, 0x515B, 0x7425, 0x3645, 0xB328, 0, - 0x515C, 0x4B5E, 0xB329, 0, 0, 0xB32A, 0x3D68, 0x427C, - 0, 0x515E, 0x4664, 0, 0xF431, 0x515F, 0xB32B, 0, - 0x5160, 0x332E, 0xB32C, 0xB32D, 0xB32E, 0x5161, 0x3627, 0xB32F, - 0x464C, 0x317A, 0x3D50, 0, 0, 0x4821, 0x5162, 0, -}; -static const unsigned short utf8_to_euc_E587_x0213[] = { - 0, 0, 0xB27E, 0x2E55, 0x4028, 0x5159, 0x3D5A, 0, - 0xB321, 0x515A, 0x2E56, 0x437C, 0x4E3F, 0x4560, 0, 0xB322, - 0, 0xB323, 0xB324, 0xB325, 0, 0xB326, 0x5245, 0, - 0xB327, 0, 0, 0x515B, 0x7425, 0x3645, 0x2E57, 0, - 0x515C, 0x4B5E, 0x2E58, 0, 0, 0xB32A, 0x3D68, 0x427C, - 0, 0x515E, 0x4664, 0, 0, 0x515F, 0x2E59, 0, - 0x5160, 0x332E, 0xB32C, 0xA333, 0xA334, 0x5161, 0x3627, 0xB32F, - 0x464C, 0x317A, 0x3D50, 0, 0, 0x4821, 0x5162, 0, -}; -static const unsigned short utf8_to_euc_E588[] = { - 0x4561, 0xB330, 0xB331, 0x3F4F, 0x5163, 0xB332, 0x4A2C, 0x405A, - 0x3422, 0, 0x3429, 0x5164, 0, 0, 0x5166, 0, - 0, 0x373A, 0xB333, 0xB334, 0x5165, 0xB335, 0xB336, 0x4E73, - 0xB337, 0, 0, 0, 0, 0x3D69, 0, 0, - 0, 0, 0xB338, 0, 0x483D, 0x4A4C, 0, 0x5167, - 0xB339, 0x4D78, 0x5168, 0, 0, 0, 0x5169, 0, - 0x457E, 0xB33A, 0xB33B, 0x516A, 0, 0xB33C, 0x4029, 0x3A7E, - 0x3774, 0x516B, 0x3B49, 0x396F, 0xB33D, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E588_x0213[] = { - 0x4561, 0x2E5A, 0xA335, 0x3F4F, 0x5163, 0xB332, 0x4A2C, 0x405A, - 0x3422, 0, 0x3429, 0x5164, 0, 0, 0x5166, 0, - 0, 0x373A, 0xA336, 0x2E5C, 0x5165, 0x2E5D, 0xA337, 0x4E73, - 0xB337, 0, 0, 0, 0, 0x3D69, 0, 0, - 0, 0, 0xB338, 0, 0x483D, 0x4A4C, 0, 0x5167, - 0xB339, 0x4D78, 0x5168, 0, 0, 0, 0x5169, 0, - 0x457E, 0xB33A, 0xB33B, 0x516A, 0, 0xB33C, 0x4029, 0x3A7E, - 0x3774, 0x516B, 0x3B49, 0x396F, 0xB33D, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E589[] = { - 0, 0, 0, 0x4466, 0x516D, 0xB33E, 0, 0x4227, - 0, 0xB33F, 0x3A6F, 0x516E, 0x516F, 0x4130, 0, 0x516C, - 0, 0, 0, 0, 0x5171, 0xB340, 0x4B36, 0xB341, - 0xB342, 0, 0xB343, 0x3964, 0xB344, 0, 0x5170, 0xB345, - 0xB346, 0xB347, 0, 0x3775, 0x3A5E, 0x476D, 0xB348, 0, - 0, 0x5174, 0x5172, 0, 0, 0, 0xB349, 0x497B, - 0x3E6A, 0x517B, 0x3364, 0x5175, 0x5173, 0x414F, 0, 0xB34A, - 0xB34B, 0xB34C, 0, 0, 0, 0x5177, 0, 0x5176, -}; -static const unsigned short utf8_to_euc_E589_x0213[] = { - 0, 0, 0, 0x4466, 0x516D, 0xB33E, 0, 0x4227, - 0, 0x2E5E, 0x3A6F, 0x516E, 0x516F, 0x4130, 0, 0x516C, - 0, 0, 0, 0, 0x5171, 0xA339, 0x4B36, 0x2E5F, - 0xB342, 0, 0xB343, 0x3964, 0xA33A, 0x2F7E, 0x5170, 0xB345, - 0xB346, 0x2E60, 0, 0x3775, 0x3A5E, 0x476D, 0xB348, 0, - 0, 0x5174, 0x5172, 0, 0xA33B, 0, 0xB349, 0x497B, - 0x3E6A, 0x517B, 0x3364, 0x5175, 0x5173, 0x414F, 0, 0xA33C, - 0xB34B, 0xB34C, 0, 0, 0, 0x5177, 0, 0x5176, -}; -static const unsigned short utf8_to_euc_E58A[] = { - 0xB34D, 0, 0xB34E, 0x3344, 0, 0xB34F, 0, 0x3760, - 0x517C, 0x4E2D, 0xB350, 0, 0xB351, 0x5178, 0, 0, - 0, 0x517D, 0x517A, 0xB352, 0x5179, 0xB353, 0xB354, 0xB355, - 0xB356, 0, 0xB357, 0x4E4F, 0xB358, 0, 0, 0x3879, - 0x3243, 0, 0, 0x4E74, 0xB359, 0xB35A, 0xB35B, 0xB35C, - 0, 0x3D75, 0x4558, 0x3965, 0x5222, 0x5223, 0, 0xB35D, - 0xB35E, 0x4E65, 0, 0, 0x4F2B, 0x5225, 0xB35F, 0xB360, - 0xB361, 0x387A, 0xB362, 0xB363, 0x5224, 0xB364, 0x332F, 0, -}; -static const unsigned short utf8_to_euc_E58A_x0213[] = { - 0xB34D, 0, 0xA33E, 0x3344, 0xA33D, 0xB34F, 0, 0x3760, - 0x517C, 0x4E2D, 0xB350, 0, 0xB351, 0x5178, 0, 0, - 0, 0x517D, 0x517A, 0x2E61, 0x5179, 0xB353, 0xB354, 0xB355, - 0xA340, 0, 0xB357, 0x4E4F, 0, 0, 0, 0x3879, - 0x3243, 0, 0, 0x4E74, 0xA342, 0xB35A, 0xA343, 0xB35C, - 0, 0x3D75, 0x4558, 0x3965, 0x5222, 0x5223, 0, 0xA344, - 0xB35E, 0x4E65, 0, 0, 0x4F2B, 0x5225, 0xB35F, 0xB360, - 0xB361, 0x387A, 0xA345, 0xA346, 0x5224, 0xB364, 0x332F, 0, -}; -static const unsigned short utf8_to_euc_E58B[] = { - 0xB365, 0x5226, 0, 0x4B56, 0xB366, 0x443C, 0xB367, 0x4D26, - 0xB368, 0x4A59, 0, 0, 0xB369, 0x5227, 0, 0xB36A, - 0, 0xB36B, 0x7055, 0, 0xB36C, 0x4630, 0xB36D, 0x5228, - 0x342A, 0x4C33, 0, 0xB36E, 0xB36F, 0x3E21, 0x5229, 0x4A67, - 0x522D, 0xB370, 0x402A, 0x522A, 0x3650, 0xB371, 0x522B, 0x342B, - 0xB372, 0xB373, 0xB374, 0, 0xB375, 0, 0, 0, - 0xB376, 0xB377, 0x372E, 0x522E, 0xB378, 0x522F, 0xB379, 0xB37A, - 0x5230, 0x5231, 0x3C5B, 0, 0, 0, 0x387B, 0x4C5E, -}; -static const unsigned short utf8_to_euc_E58B_x0213[] = { - 0, 0x5226, 0, 0x4B56, 0xB366, 0x443C, 0xB367, 0x4D26, - 0x2E62, 0x4A59, 0xA347, 0, 0x2E64, 0x5227, 0, 0xB36A, - 0x2E65, 0xA349, 0x7055, 0, 0xB36C, 0x4630, 0x2E66, 0x5228, - 0x342A, 0x4C33, 0, 0x2E67, 0xB36F, 0x3E21, 0x5229, 0x4A67, - 0x522D, 0xB370, 0x402A, 0x522A, 0x3650, 0xB371, 0x522B, 0x342B, - 0xB372, 0xB373, 0xB374, 0, 0xB375, 0, 0, 0, - 0x2E69, 0xB377, 0x372E, 0x522E, 0xB378, 0x522F, 0xB379, 0xA34B, - 0x5230, 0x5231, 0x3C5B, 0x2E6A, 0, 0, 0x387B, 0x4C5E, -}; -static const unsigned short utf8_to_euc_E58C[] = { - 0xB37B, 0x4C68, 0x4677, 0xB37C, 0, 0x4A71, 0x5232, 0xF432, - 0x5233, 0, 0xB37D, 0xB37E, 0xB421, 0x5235, 0, 0x5237, - 0x5236, 0xB422, 0, 0xB423, 0, 0x5238, 0x323D, 0x4B4C, - 0xB424, 0x3A7C, 0x5239, 0xB425, 0xB426, 0x4159, 0xB427, 0xB428, - 0x3E22, 0x3629, 0, 0x523A, 0xF433, 0xB429, 0, 0xB42A, - 0xB42B, 0xB42C, 0x485B, 0xB42D, 0xB42E, 0xB42F, 0, 0x523B, - 0xB430, 0x523C, 0xB431, 0x523D, 0, 0xB432, 0, 0, - 0x523E, 0x4924, 0x3668, 0x3065, 0xB433, 0xB434, 0xB435, 0x463F, -}; -static const unsigned short utf8_to_euc_E58C_x0213[] = { - 0x2E6B, 0x4C68, 0x4677, 0xB37C, 0, 0x4A71, 0x5232, 0x2E6C, - 0x5233, 0, 0xA34C, 0xA34D, 0xB421, 0x5235, 0, 0x5237, - 0x5236, 0xB422, 0, 0xB423, 0, 0x5238, 0x323D, 0x4B4C, - 0xB424, 0x3A7C, 0x5239, 0xB425, 0x2E6D, 0x4159, 0xB427, 0xB428, - 0x3E22, 0x3629, 0, 0x523A, 0xA34E, 0xB429, 0, 0xB42A, - 0xB42B, 0xB42C, 0x485B, 0xB42D, 0xB42E, 0xB42F, 0, 0x523B, - 0xB430, 0x523C, 0xB431, 0x523D, 0, 0xA34F, 0, 0, - 0x523E, 0x4924, 0x3668, 0x3065, 0xB433, 0xB434, 0xA350, 0x463F, -}; -static const unsigned short utf8_to_euc_E58D[] = { - 0x523F, 0x3D3D, 0xB436, 0x4069, 0, 0x5241, 0x5240, 0x3E23, - 0x3861, 0x5243, 0x483E, 0xB438, 0xB437, 0x5244, 0, 0, - 0, 0x485C, 0x4234, 0x426E, 0x3628, 0, 0, 0x466E, - 0x4331, 0xB439, 0x476E, 0xB43A, 0x4B4E, 0, 0x5246, 0, - 0x406A, 0xB43B, 0, 0xB43C, 0, 0xB43D, 0x3735, 0, - 0, 0x5247, 0, 0, 0xB43E, 0xB43F, 0x5248, 0x312C, - 0x3075, 0x346D, 0xB440, 0x4228, 0x3551, 0x4D71, 0, 0x524B, - 0x3237, 0xB441, 0, 0x524A, 0, 0, 0xB442, 0x362A, -}; -static const unsigned short utf8_to_euc_E58D_x0213[] = { - 0x523F, 0x3D3D, 0xA351, 0x4069, 0, 0x5241, 0x5240, 0x3E23, - 0x3861, 0x5243, 0x483E, 0xB438, 0xB437, 0x5244, 0, 0, - 0, 0x485C, 0x4234, 0x426E, 0x3628, 0, 0, 0x466E, - 0x4331, 0xB439, 0x476E, 0xB43A, 0x4B4E, 0, 0x5246, 0, - 0x406A, 0x2E6F, 0, 0x2E70, 0, 0xB43D, 0x3735, 0xA354, - 0, 0x5247, 0, 0, 0xA355, 0xB43F, 0x5248, 0x312C, - 0x3075, 0x346D, 0, 0x4228, 0x3551, 0x4D71, 0, 0x524B, - 0x3237, 0xB441, 0xA356, 0x524A, 0, 0x2E71, 0xB442, 0x362A, -}; -static const unsigned short utf8_to_euc_E58E[] = { - 0, 0, 0x524C, 0xB443, 0x4C71, 0, 0, 0xB444, - 0xB445, 0, 0, 0, 0, 0, 0xB446, 0, - 0, 0, 0, 0xB447, 0xB448, 0, 0x524D, 0, - 0x4E52, 0xB449, 0x387C, 0, 0, 0xB44A, 0, 0x3836, - 0x524E, 0xB44B, 0, 0, 0xB44C, 0x5250, 0x524F, 0, - 0x3F5F, 0x3139, 0xB44D, 0xB44E, 0, 0x315E, 0x5251, 0xB44F, - 0x5252, 0, 0xB450, 0x3837, 0xB451, 0xB452, 0x5253, 0xB453, - 0xB454, 0, 0xB455, 0x356E, 0, 0xB456, 0, 0, -}; -static const unsigned short utf8_to_euc_E58E_x0213[] = { - 0, 0, 0x524C, 0xB443, 0x4C71, 0, 0, 0xB444, - 0xB445, 0, 0, 0, 0, 0, 0xB446, 0, - 0, 0, 0, 0x2E72, 0xB448, 0, 0x524D, 0, - 0x4E52, 0xB449, 0x387C, 0, 0, 0x2E73, 0, 0x3836, - 0x524E, 0xB44B, 0, 0, 0xA357, 0x5250, 0x524F, 0, - 0x3F5F, 0x3139, 0xB44D, 0xB44E, 0, 0x315E, 0x5251, 0xB44F, - 0x5252, 0, 0x2E74, 0x3837, 0xA358, 0xB452, 0x5253, 0xA35A, - 0xB454, 0, 0xB455, 0x356E, 0, 0xB456, 0, 0, -}; -static const unsigned short utf8_to_euc_E58F[] = { - 0xB457, 0, 0x3B32, 0x5254, 0, 0xB458, 0, 0, - 0x4B74, 0x3A35, 0x355A, 0x4D27, 0x4150, 0x483F, 0x3C7D, 0xB459, - 0, 0, 0xB45A, 0xB45B, 0x3D47, 0xB45C, 0x3C68, 0x3C75, - 0, 0x3D76, 0xB45D, 0x4840, 0, 0xB45E, 0xB45F, 0x5257, - 0xB460, 0x3143, 0x4151, 0x387D, 0x3845, 0x3667, 0xB461, 0xB462, - 0x525B, 0x4321, 0x427E, 0x362B, 0x3E24, 0x525C, 0x525A, 0x3244, - 0x4266, 0x3C38, 0x3B4B, 0x3126, 0, 0xB463, 0x3370, 0x3966, - 0x3B4A, 0, 0x525D, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E58F_x0213[] = { - 0xA35B, 0, 0x3B32, 0x5254, 0, 0xB458, 0, 0, - 0x4B74, 0x3A35, 0x355A, 0x4D27, 0x4150, 0x483F, 0x3C7D, 0xB459, - 0, 0, 0xB45A, 0xB45B, 0x3D47, 0xA35F, 0x3C68, 0x3C75, - 0, 0x3D76, 0xA360, 0x4840, 0, 0, 0xB45F, 0x5257, - 0xB460, 0x3143, 0x4151, 0x387D, 0x3845, 0x3667, 0xB461, 0xB462, - 0x525B, 0x4321, 0x427E, 0x362B, 0x3E24, 0x525C, 0x525A, 0x3244, - 0x4266, 0x3C38, 0x3B4B, 0x3126, 0xA362, 0xA363, 0x3370, 0x3966, - 0x3B4A, 0, 0x525D, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E590[] = { - 0, 0x525E, 0xB464, 0x3549, 0x3346, 0, 0, 0, - 0x3967, 0x3548, 0x445F, 0x3125, 0x4631, 0x4C3E, 0x3921, 0x4D79, - 0x4547, 0x387E, 0, 0xB465, 0, 0, 0, 0, - 0, 0, 0xB466, 0x372F, 0, 0x5267, 0, 0x3663, - 0x4B4A, 0xB467, 0, 0, 0, 0, 0x485D, 0xB468, - 0xB469, 0x5266, 0xB46A, 0x345E, 0x5261, 0x5262, 0x5264, 0xB46B, - 0, 0xB46C, 0, 0, 0xB46D, 0xB46E, 0x5265, 0, - 0x355B, 0x3F61, 0, 0x4A2D, 0x5263, 0x525F, 0x3863, 0, -}; -static const unsigned short utf8_to_euc_E590_x0213[] = { - 0, 0x525E, 0xB464, 0x3549, 0x3346, 0, 0, 0, - 0x3967, 0x3548, 0x445F, 0x3125, 0x4631, 0x4C3E, 0x3921, 0x4D79, - 0x4547, 0x387E, 0x2E75, 0xB465, 0, 0, 0, 0, - 0, 0, 0xB466, 0x372F, 0, 0x5267, 0x4F7E, 0x3663, - 0x4B4A, 0xB467, 0, 0, 0xA365, 0, 0x485D, 0x2E76, - 0xA366, 0x5266, 0xB46A, 0x345E, 0x5261, 0x5262, 0x5264, 0xB46B, - 0, 0xB46C, 0, 0, 0xB46D, 0xB46E, 0x5265, 0, - 0x355B, 0x3F61, 0, 0x4A2D, 0x5263, 0x525F, 0x3863, 0, -}; -static const unsigned short utf8_to_euc_E591[] = { - 0x5260, 0, 0x4F24, 0xB46F, 0xB470, 0, 0x4A72, 0xB471, - 0x4468, 0x3862, 0x3970, 0, 0, 0xB472, 0x5268, 0xB473, - 0, 0x465D, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xB474, 0x526C, - 0, 0, 0xB475, 0, 0xB476, 0, 0xB477, 0xB478, - 0x3C7E, 0xB479, 0x3C76, 0xB47A, 0, 0xB47B, 0xB47C, 0, - 0x526F, 0x526D, 0, 0x4C23, 0xB47D, 0x526A, 0x5273, 0x526E, - 0, 0, 0, 0x5271, 0x3846, 0x4C3F, 0, 0xB47E, -}; -static const unsigned short utf8_to_euc_E591_x0213[] = { - 0x5260, 0, 0x4F24, 0xA368, 0xB470, 0, 0x4A72, 0xB471, - 0x4468, 0x3862, 0x3970, 0, 0, 0x2E77, 0x5268, 0xB473, - 0, 0x465D, 0, 0, 0, 0xA364, 0, 0, - 0, 0, 0, 0, 0, 0, 0xB474, 0x526C, - 0, 0, 0xA369, 0, 0xB476, 0, 0xA36A, 0xB478, - 0x3C7E, 0xB479, 0x3C76, 0x2E79, 0xA36B, 0xB47B, 0xB47C, 0, - 0x526F, 0x526D, 0, 0x4C23, 0x2E7A, 0x526A, 0x5273, 0x526E, - 0, 0, 0, 0x5271, 0x3846, 0x4C3F, 0, 0x2E7B, -}; -static const unsigned short utf8_to_euc_E592[] = { - 0x5272, 0xB521, 0, 0xB522, 0x5274, 0xB523, 0x5276, 0, - 0xB524, 0xB525, 0xF435, 0x3A70, 0x4F42, 0xB526, 0x526B, 0x5269, - 0x5275, 0xB527, 0x5270, 0, 0, 0xB528, 0xB529, 0, - 0, 0, 0, 0, 0xB52A, 0, 0, 0xB52B, - 0, 0xB52C, 0x5278, 0, 0x5323, 0x527A, 0xB52D, 0xB52E, - 0x527E, 0xB52F, 0xB530, 0x5321, 0x527B, 0xB531, 0xB532, 0x533E, - 0, 0xB533, 0x3A69, 0x3331, 0, 0, 0, 0xB534, - 0x5279, 0xB535, 0xB536, 0xB537, 0x5325, 0x3076, 0x5324, 0xB538, -}; -static const unsigned short utf8_to_euc_E592_x0213[] = { - 0x5272, 0xB521, 0, 0xB522, 0x5274, 0xB523, 0x5276, 0, - 0x2E7C, 0xB525, 0xA36C, 0x3A70, 0x4F42, 0xA36D, 0x526B, 0x5269, - 0x5275, 0xB527, 0x5270, 0, 0, 0xA36E, 0x2E7D, 0, - 0, 0, 0, 0, 0x2E78, 0, 0, 0xB52B, - 0xA36F, 0x2E7E, 0x5278, 0, 0x5323, 0x527A, 0xA370, 0xB52E, - 0x527E, 0x2F21, 0xB530, 0x5321, 0x527B, 0xA371, 0xA372, 0x533E, - 0, 0xB533, 0x3A69, 0x3331, 0, 0, 0, 0xA373, - 0x5279, 0xB535, 0xA374, 0xB537, 0x5325, 0x3076, 0x5324, 0xA375, -}; -static const unsigned short utf8_to_euc_E593[] = { - 0x3025, 0x494A, 0x5322, 0, 0x527C, 0, 0xB539, 0x5277, - 0x527D, 0x3A48, 0xB53A, 0, 0, 0xB53B, 0xB53C, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x5326, 0, 0, 0, 0, 0, 0, 0, - 0xB53D, 0x3077, 0x532F, 0, 0, 0x5327, 0x5328, 0, - 0x3E25, 0x4B69, 0xB53E, 0, 0xB53F, 0x532D, 0x532C, 0xB540, - 0, 0, 0x452F, 0, 0, 0, 0xB541, 0, - 0, 0, 0x532E, 0, 0xB542, 0x532B, 0xB543, 0xB544, -}; -static const unsigned short utf8_to_euc_E593_x0213[] = { - 0x3025, 0x494A, 0x5322, 0xA376, 0x527C, 0, 0x2F22, 0x5277, - 0x527D, 0x3A48, 0xB53A, 0, 0, 0xB53B, 0xB53C, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x5326, 0, 0, 0, 0, 0, 0, 0, - 0xB53D, 0x3077, 0x532F, 0, 0, 0x5327, 0x5328, 0, - 0x3E25, 0x4B69, 0xB53E, 0, 0xA378, 0x532D, 0x532C, 0xA379, - 0, 0xA37A, 0x452F, 0xA37B, 0, 0, 0xB541, 0, - 0, 0, 0x532E, 0, 0xB542, 0x532B, 0xB543, 0x2F23, -}; -static const unsigned short utf8_to_euc_E594[] = { - 0xB545, 0xB546, 0, 0, 0x3134, 0xB547, 0x3A36, 0x3F30, - 0xB548, 0xB549, 0, 0, 0xB54A, 0xB54B, 0xB54C, 0x5329, - 0x4562, 0, 0, 0, 0x532A, 0xB54D, 0x3022, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xB54E, 0xB54F, 0, 0, 0x5334, 0x4D23, - 0, 0x3E27, 0xB550, 0x533A, 0, 0xB551, 0xB552, 0, - 0x5339, 0x5330, 0, 0xB553, 0xB554, 0xB555, 0x4243, 0, -}; -static const unsigned short utf8_to_euc_E594_x0213[] = { - 0xA37C, 0xA37D, 0, 0, 0x3134, 0xB547, 0x3A36, 0x3F30, - 0xB548, 0xA37E, 0, 0, 0xB54A, 0xB54B, 0x2F24, 0x5329, - 0x4562, 0, 0, 0, 0x532A, 0xB54D, 0x3022, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xB54E, 0x2F25, 0, 0, 0x5334, 0x4D23, - 0, 0x3E27, 0xB550, 0x533A, 0, 0x2F26, 0xB552, 0, - 0x5339, 0x5330, 0, 0xB553, 0xA421, 0xB555, 0x4243, 0, -}; -static const unsigned short utf8_to_euc_E595[] = { - 0x5331, 0xB556, 0, 0, 0x426F, 0x5336, 0x3E26, 0xB557, - 0, 0xB558, 0xB559, 0, 0x5333, 0xB55A, 0, 0x4C64, - 0xB55B, 0xB55C, 0, 0x373C, 0, 0, 0x5337, 0x5338, - 0xB55D, 0, 0xB55E, 0xB55F, 0x5335, 0x533B, 0xB560, 0, - 0xB561, 0xB562, 0, 0x5332, 0xB563, 0, 0xB564, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x5341, 0x5346, 0, 0x5342, 0xB565, -}; -static const unsigned short utf8_to_euc_E595_x0213[] = { - 0x5331, 0xA422, 0, 0, 0x426F, 0x5336, 0x3E26, 0xA424, - 0, 0xB558, 0xA425, 0, 0x5333, 0xB55A, 0, 0x4C64, - 0x2F27, 0xB55C, 0, 0x373C, 0, 0, 0x5337, 0x5338, - 0xB55D, 0, 0xB55E, 0xB55F, 0x5335, 0x533B, 0x2F28, 0, - 0xA427, 0xA428, 0, 0x5332, 0xA429, 0, 0xB564, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x5341, 0x5346, 0xA42B, 0x5342, 0xB565, -}; -static const unsigned short utf8_to_euc_E596[] = { - 0x533D, 0xB566, 0xB567, 0x5347, 0x4131, 0, 0xB568, 0x5349, - 0xB569, 0x3922, 0x533F, 0x437D, 0, 0, 0xB56A, 0xB56B, - 0, 0xB56C, 0xB56D, 0xB56E, 0xB56F, 0, 0, 0xB570, - 0x5343, 0x533C, 0x342D, 0, 0x346E, 0x3365, 0x5344, 0x5340, - 0, 0, 0, 0xB571, 0xB572, 0, 0, 0x3776, - 0x534A, 0x5348, 0x4153, 0x354A, 0x362C, 0xB573, 0x5345, 0, - 0x3674, 0, 0xB574, 0, 0, 0, 0x3144, 0, - 0, 0, 0, 0, 0, 0, 0, 0xB575, -}; -static const unsigned short utf8_to_euc_E596_x0213[] = { - 0x533D, 0x2F29, 0xA42C, 0x5347, 0x4131, 0, 0x2F2A, 0x5349, - 0xA42D, 0x3922, 0x533F, 0x437D, 0, 0, 0x2F2B, 0xB56B, - 0, 0xA42E, 0xB56D, 0xB56E, 0xB56F, 0, 0, 0xB570, - 0x5343, 0x533C, 0x342D, 0, 0x346E, 0x3365, 0x5344, 0x5340, - 0, 0, 0, 0xB571, 0xB572, 0, 0, 0x3776, - 0x534A, 0x5348, 0x4153, 0x354A, 0x362C, 0x2F2D, 0x5345, 0, - 0x3674, 0, 0xB574, 0, 0, 0, 0x3144, 0, - 0, 0, 0, 0, 0, 0, 0, 0xA433, -}; -static const unsigned short utf8_to_euc_E597[] = { - 0, 0xB576, 0, 0xB577, 0x534E, 0x534C, 0xB578, 0x5427, - 0, 0xB579, 0, 0xB57A, 0xB57B, 0, 0xB57C, 0, - 0, 0xB57D, 0xB57E, 0xB621, 0x5351, 0, 0, 0xB622, - 0xB623, 0, 0x534B, 0xB624, 0x534F, 0, 0xB625, 0x534D, - 0, 0, 0xB626, 0x3B4C, 0x5350, 0, 0, 0, - 0, 0xB627, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xB628, 0x5353, - 0, 0x5358, 0, 0, 0, 0x5356, 0x5355, 0xB629, -}; -static const unsigned short utf8_to_euc_E597_x0213[] = { - 0, 0xB576, 0, 0xB577, 0x534E, 0x534C, 0xB578, 0x5427, - 0, 0xA434, 0, 0xB57A, 0xA435, 0, 0x2F2E, 0, - 0, 0xA436, 0xA430, 0xB621, 0x5351, 0, 0, 0xB622, - 0xB623, 0, 0x534B, 0xB624, 0x534F, 0xA437, 0xB625, 0x534D, - 0, 0, 0xA439, 0x3B4C, 0x5350, 0, 0, 0, - 0, 0xA43B, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xB628, 0x5353, - 0, 0x5358, 0, 0, 0, 0x5356, 0x5355, 0xB629, -}; -static const unsigned short utf8_to_euc_E598[] = { - 0, 0, 0, 0, 0, 0xB62A, 0x4332, 0, - 0xB62B, 0x3245, 0xB62C, 0, 0, 0xB62D, 0xB62E, 0xB62F, - 0xB630, 0xB631, 0xB632, 0, 0x5352, 0, 0x5354, 0x3E28, - 0x3133, 0xB633, 0, 0x5357, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x325E, 0, 0, 0xB634, 0, 0, 0x5362, - 0xB635, 0x3E7C, 0x535E, 0xB636, 0x535C, 0xB637, 0x535D, 0xB638, - 0x535F, 0xB639, 0, 0xB63A, 0xB63B, 0xB63C, 0, 0xB63D, -}; -static const unsigned short utf8_to_euc_E598_x0213[] = { - 0, 0, 0, 0, 0, 0xB62A, 0x4332, 0xA43E, - 0x2F30, 0x3245, 0xB62C, 0, 0, 0xB62D, 0x2F31, 0xB62F, - 0xA43F, 0xB631, 0xB632, 0, 0x5352, 0, 0x5354, 0x3E28, - 0x3133, 0xB633, 0, 0x5357, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xA43C, 0x325E, 0, 0, 0xB634, 0, 0, 0x5362, - 0xA440, 0x3E7C, 0x535E, 0xB636, 0x535C, 0xB637, 0x535D, 0xA441, - 0x535F, 0xB639, 0, 0x2F32, 0xB63B, 0xA443, 0, 0xA444, -}; -static const unsigned short utf8_to_euc_E599[] = { - 0xB63E, 0xB63F, 0x313D, 0xB640, 0xB641, 0, 0xB642, 0, - 0, 0xB643, 0, 0xB644, 0x4139, 0xB645, 0x5359, 0xB646, - 0x535A, 0, 0, 0, 0xB647, 0, 0, 0, - 0, 0, 0, 0x337A, 0, 0, 0xB648, 0, - 0xB649, 0xB64A, 0xB64B, 0xB64C, 0x5361, 0, 0xB64D, 0, - 0x346F, 0xB64E, 0x5364, 0x5360, 0x5363, 0xB64F, 0, 0xB650, - 0, 0xB651, 0xB652, 0, 0x4A2E, 0xB653, 0, 0, - 0x4655, 0, 0x4838, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E599_x0213[] = { - 0xA445, 0xB63F, 0x313D, 0xB640, 0xB641, 0, 0xB642, 0xA446, - 0, 0x2F33, 0, 0xB644, 0x4139, 0xB645, 0x5359, 0xB646, - 0x535A, 0, 0, 0x7427, 0xB647, 0, 0, 0, - 0, 0, 0, 0x337A, 0, 0, 0xA447, 0, - 0xA448, 0xB64A, 0xB64B, 0xB64C, 0x5361, 0, 0x2F35, 0, - 0x346F, 0xB64E, 0x5364, 0x5360, 0x5363, 0xA449, 0, 0x2F37, - 0, 0x2F38, 0x2F39, 0, 0x4A2E, 0xB653, 0x2F34, 0, - 0x4655, 0, 0x4838, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E59A[] = { - 0x5366, 0, 0, 0, 0xB654, 0xB655, 0x5365, 0x3345, - 0xB656, 0, 0x5367, 0xB657, 0xB658, 0, 0, 0x536A, - 0, 0, 0, 0, 0x5369, 0xB659, 0, 0, - 0, 0xB65A, 0xB65B, 0, 0, 0xB65C, 0xB65D, 0xB65E, - 0x5368, 0, 0x4739, 0, 0, 0x536B, 0xB65F, 0xB660, - 0xB661, 0xB662, 0, 0xB663, 0xB664, 0xB665, 0x536C, 0, - 0, 0xB666, 0, 0xB667, 0x536E, 0, 0x536D, 0xB668, - 0, 0, 0, 0, 0x5370, 0, 0xB669, 0, -}; -static const unsigned short utf8_to_euc_E59A_x0213[] = { - 0x5366, 0, 0, 0, 0xB654, 0xB655, 0x5365, 0x3345, - 0xA44B, 0, 0x5367, 0xB657, 0xA44C, 0, 0, 0x536A, - 0, 0, 0, 0, 0x5369, 0xA44D, 0, 0, - 0, 0x2F3A, 0xA44E, 0, 0, 0xA44F, 0x2F3B, 0xB65E, - 0x5368, 0, 0x4739, 0, 0, 0x536B, 0xB65F, 0xB660, - 0xA450, 0x2F3C, 0, 0xB663, 0x2F3D, 0xA451, 0x536C, 0, - 0, 0xB666, 0xA452, 0x2F3E, 0x536E, 0, 0x536D, 0xB668, - 0, 0, 0, 0, 0x5370, 0, 0xB669, 0, -}; -static const unsigned short utf8_to_euc_E59B[] = { - 0x5373, 0x5371, 0x536F, 0x5372, 0, 0xB66A, 0, 0, - 0x5374, 0xB66B, 0xB66C, 0xB66D, 0xB670, 0xB671, 0x5375, 0xB66E, - 0xB66F, 0x5376, 0, 0x5377, 0, 0, 0, 0x5378, - 0x5145, 0xB672, 0x3C7C, 0x3B4D, 0xB673, 0xB674, 0x3273, 0xB675, - 0x3078, 0xB676, 0, 0x4344, 0xB677, 0xB678, 0xB679, 0xB67A, - 0xB67B, 0, 0, 0xB67D, 0, 0xB67E, 0x5379, 0, - 0x3A24, 0xB67C, 0x304F, 0x3F5E, 0, 0, 0xB721, 0xB722, - 0, 0x537A, 0x3847, 0, 0, 0x3971, 0, 0x537C, -}; -static const unsigned short utf8_to_euc_E59B_x0213[] = { - 0x5373, 0x5371, 0x536F, 0x5372, 0, 0xA453, 0, 0, - 0x5374, 0x2F3F, 0x2F40, 0xB66D, 0xB670, 0xA454, 0x5375, 0xB66E, - 0xB66F, 0x5376, 0, 0x5377, 0, 0, 0, 0x5378, - 0x5145, 0xB672, 0x3C7C, 0x3B4D, 0xB673, 0xB674, 0x3273, 0xA455, - 0x3078, 0xB676, 0, 0x4344, 0xB677, 0xB678, 0xB679, 0xB67A, - 0xA456, 0, 0, 0xB67D, 0, 0xB67E, 0x5379, 0, - 0x3A24, 0xB67C, 0x304F, 0x3F5E, 0, 0, 0xA457, 0xA458, - 0, 0x537A, 0x3847, 0, 0, 0x3971, 0, 0x537C, -}; -static const unsigned short utf8_to_euc_E59C[] = { - 0x537B, 0xB723, 0xB724, 0x4A60, 0x537D, 0, 0, 0xB725, - 0x5421, 0x537E, 0xB726, 0x5422, 0xB727, 0x5423, 0, 0x3777, - 0, 0xB728, 0x3160, 0x5424, 0, 0xB729, 0x5426, 0, - 0x5425, 0, 0xB72A, 0xB72B, 0x5428, 0xB72C, 0, 0x455A, - 0xB72D, 0, 0xB72E, 0xB72F, 0xB730, 0xB731, 0x5429, 0x3035, - 0x3A5F, 0xB732, 0xB733, 0, 0xB734, 0x373D, 0xB735, 0xB736, - 0x434F, 0, 0, 0xB737, 0xB738, 0, 0, 0x542A, - 0x542B, 0, 0, 0x542D, 0, 0xB739, 0xB73A, 0xB73B, -}; -static const unsigned short utf8_to_euc_E59C_x0213[] = { - 0x537B, 0xB723, 0xB724, 0x4A60, 0x537D, 0, 0, 0xB725, - 0x5421, 0x537E, 0x2F41, 0x5422, 0xB727, 0x5423, 0, 0x3777, - 0, 0xB728, 0x3160, 0x5424, 0, 0xA45A, 0x5426, 0, - 0x5425, 0, 0xB72A, 0xB72B, 0x5428, 0xB72C, 0, 0x455A, - 0xB72D, 0x2F43, 0xB72E, 0xA45B, 0xB730, 0xB731, 0x5429, 0x3035, - 0x3A5F, 0xA45D, 0xB733, 0, 0xB734, 0x373D, 0xB735, 0x2F44, - 0x434F, 0, 0, 0x2F45, 0x2F46, 0, 0, 0x542A, - 0x542B, 0, 0, 0x542D, 0, 0xB739, 0xB73A, 0xB73B, -}; -static const unsigned short utf8_to_euc_E59D[] = { - 0x542E, 0, 0x3A64, 0, 0, 0xB73C, 0xB73D, 0x3651, - 0, 0, 0x4B37, 0, 0xB73E, 0xB73F, 0x542C, 0x542F, - 0x3A41, 0x3923, 0xB740, 0, 0, 0, 0, 0, - 0, 0xF436, 0, 0, 0, 0, 0, 0, - 0, 0x5433, 0xB741, 0, 0x3A25, 0xB742, 0x4333, 0xB743, - 0xB744, 0x5430, 0x445A, 0xB745, 0, 0xB746, 0xB747, 0xB748, - 0xB749, 0xB74A, 0, 0xB74B, 0xB74C, 0xB74D, 0, 0xB74E, - 0, 0xB74F, 0xB750, 0xB751, 0xB752, 0, 0xB753, 0x5434, -}; -static const unsigned short utf8_to_euc_E59D_x0213[] = { - 0x542E, 0, 0x3A64, 0, 0, 0xA45F, 0xA460, 0x3651, - 0, 0, 0x4B37, 0, 0xA461, 0xA462, 0x542C, 0x542F, - 0x3A41, 0x3923, 0xB740, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x5433, 0xB741, 0, 0x3A25, 0, 0x4333, 0xB743, - 0xA464, 0x5430, 0x445A, 0xB745, 0, 0xB746, 0xB747, 0xA465, - 0x2F47, 0xB74A, 0, 0xA466, 0xA467, 0xA468, 0, 0x2F48, - 0, 0xB74F, 0xB750, 0xA469, 0x2F49, 0, 0xB753, 0x5434, -}; -static const unsigned short utf8_to_euc_E59E[] = { - 0, 0xB754, 0x3F62, 0xB755, 0, 0, 0, 0, - 0x5432, 0x5435, 0, 0x373F, 0xB756, 0, 0, 0, - 0, 0, 0, 0x5436, 0xB757, 0xB760, 0, 0xB758, - 0, 0xB759, 0xB75A, 0, 0xB75B, 0xB75C, 0xB75D, 0xB75E, - 0x5437, 0xB75F, 0x3924, 0x3340, 0x5439, 0, 0, 0xB761, - 0xB762, 0xB763, 0x543A, 0, 0xB764, 0, 0, 0, - 0x543B, 0, 0, 0x5438, 0, 0, 0, 0, - 0xB765, 0, 0, 0, 0, 0xB766, 0, 0, -}; -static const unsigned short utf8_to_euc_E59E_x0213[] = { - 0, 0xB754, 0x3F62, 0xB755, 0, 0, 0, 0, - 0x5432, 0x5435, 0, 0x373F, 0xB756, 0, 0, 0, - 0, 0, 0, 0x5436, 0xB757, 0xB760, 0, 0xB758, - 0, 0xB759, 0xA46D, 0, 0x2F4A, 0xA46E, 0xA46F, 0xB75E, - 0x5437, 0xB75F, 0x3924, 0x3340, 0x5439, 0, 0, 0xB761, - 0xA470, 0xB763, 0x543A, 0, 0xA46C, 0, 0, 0, - 0x543B, 0, 0, 0x5438, 0, 0, 0, 0, - 0x2F4D, 0, 0, 0, 0, 0xB766, 0, 0, -}; -static const unsigned short utf8_to_euc_E59F[] = { - 0x5431, 0, 0, 0x543C, 0, 0, 0x543D, 0xB767, - 0xB768, 0, 0, 0x4B64, 0xB769, 0, 0x3E6B, 0xB76A, - 0, 0, 0x543F, 0x5440, 0x543E, 0xB76B, 0x5442, 0, - 0, 0, 0, 0, 0x4738, 0xB76C, 0xB76D, 0x3068, - 0x4956, 0xB77E, 0, 0x5443, 0xB76E, 0, 0xB76F, 0xB770, - 0, 0xB771, 0, 0, 0, 0xB772, 0, 0, - 0xB773, 0, 0, 0, 0x3E7D, 0xB774, 0xB775, 0x3C39, - 0xB776, 0x475D, 0x3470, 0, 0x3A6B, 0xB777, 0xB778, 0xB779, -}; -static const unsigned short utf8_to_euc_E59F_x0213[] = { - 0x5431, 0, 0, 0x543C, 0, 0, 0x543D, 0x2F4E, - 0x2F4F, 0, 0, 0x4B64, 0xA473, 0, 0x3E6B, 0x2F50, - 0, 0, 0x543F, 0x5440, 0x543E, 0xB76B, 0x5442, 0xA471, - 0, 0, 0, 0, 0x4738, 0xB76C, 0xA476, 0x3068, - 0x4956, 0xB77E, 0, 0x5443, 0x2F51, 0, 0xA477, 0xB770, - 0, 0xB771, 0, 0, 0, 0x2F52, 0, 0, - 0xA478, 0, 0, 0, 0x3E7D, 0x2F53, 0x2F54, 0x3C39, - 0xA47A, 0x475D, 0x3470, 0xA47B, 0x3A6B, 0xA47C, 0xB778, 0x2F55, -}; -static const unsigned short utf8_to_euc_E5A0[] = { - 0x4B59, 0, 0x4632, 0xB77A, 0xB77B, 0x3778, 0x424F, 0, - 0xB77C, 0xB77D, 0x5441, 0x5444, 0xB821, 0xB822, 0, 0, - 0, 0, 0, 0, 0, 0x4244, 0, 0, - 0, 0x5445, 0, 0xB823, 0, 0x5446, 0xB824, 0xB825, - 0xB826, 0x5448, 0, 0, 0x4469, 0, 0xB827, 0xB828, - 0, 0, 0x342E, 0, 0, 0xB829, 0, 0x7421, - 0x3161, 0x4A73, 0xB82A, 0, 0x3E6C, 0x4548, 0, 0, - 0, 0xB82B, 0x3A66, 0, 0, 0x544E, 0, 0xB82C, -}; -static const unsigned short utf8_to_euc_E5A0_x0213[] = { - 0x4B59, 0, 0x4632, 0xB77A, 0xA47D, 0x3778, 0x424F, 0, - 0xB77C, 0x2F56, 0x5441, 0x5444, 0xB821, 0xB822, 0, 0, - 0, 0, 0, 0, 0, 0x4244, 0, 0, - 0, 0x5445, 0, 0xB823, 0, 0x5446, 0xA47E, 0xB825, - 0xA521, 0x5448, 0, 0, 0x4469, 0, 0xB827, 0xA522, - 0, 0, 0x342E, 0, 0, 0xB829, 0, 0x7421, - 0x3161, 0x4A73, 0xA523, 0, 0x3E6C, 0x4548, 0, 0, - 0, 0xA524, 0x3A66, 0, 0, 0x544E, 0, 0xB82C, -}; -static const unsigned short utf8_to_euc_E5A1[] = { - 0x4A3D, 0x4E5D, 0, 0, 0, 0, 0, 0, - 0, 0xB82D, 0x3274, 0x544A, 0xB82E, 0xB82F, 0, 0xB830, - 0xB831, 0x413A, 0x544D, 0, 0x4563, 0xB832, 0, 0x4549, - 0x4564, 0x4839, 0x444D, 0, 0, 0, 0x3A49, 0xB833, - 0, 0xB834, 0x5449, 0, 0xB835, 0, 0, 0xB836, - 0xB837, 0x3176, 0, 0x4536, 0, 0, 0, 0, - 0x544B, 0, 0x5447, 0, 0, 0x3F50, 0, 0, - 0xB838, 0x544F, 0, 0, 0xB839, 0, 0x3D4E, 0xB83A, -}; -static const unsigned short utf8_to_euc_E5A1_x0213[] = { - 0x4A3D, 0x4E5D, 0, 0, 0, 0, 0, 0, - 0, 0xA526, 0x3274, 0x544A, 0xA527, 0xB82F, 0, 0xB830, - 0xB831, 0x413A, 0x544D, 0, 0x4563, 0xB832, 0, 0x4549, - 0x4564, 0x4839, 0x444D, 0, 0, 0, 0x3A49, 0xB833, - 0, 0x2F58, 0x5449, 0, 0x2F59, 0, 0, 0xA528, - 0xB837, 0x3176, 0, 0x4536, 0, 0, 0, 0, - 0x544B, 0, 0x5447, 0, 0, 0x3F50, 0, 0, - 0xB838, 0x544F, 0, 0, 0x2F5B, 0, 0x3D4E, 0xB83A, -}; -static const unsigned short utf8_to_euc_E5A2[] = { - 0xB83B, 0xB83C, 0, 0x362D, 0, 0x5450, 0, 0xB83D, - 0xB83E, 0xB83F, 0xB840, 0, 0xB841, 0xB842, 0, 0xB843, - 0xB844, 0, 0, 0x4A68, 0xB845, 0, 0xB846, 0x417D, - 0, 0, 0, 0, 0x4446, 0xB847, 0xF439, 0x5452, - 0xB848, 0xB849, 0xB84A, 0, 0, 0, 0xB84B, 0, - 0x4B4F, 0xB84C, 0, 0x5453, 0, 0, 0x5458, 0, - 0, 0xB84D, 0xB84E, 0x4A2F, 0, 0, 0, 0, - 0x5457, 0x5451, 0x5454, 0x5456, 0xB850, 0, 0x3A26, 0, -}; -static const unsigned short utf8_to_euc_E5A2_x0213[] = { - 0xB83B, 0xB83C, 0, 0x362D, 0, 0x5450, 0, 0xB83D, - 0xB83E, 0x2F5C, 0xA529, 0xA52A, 0xB841, 0xA52B, 0, 0xA52C, - 0xA52D, 0, 0, 0x4A68, 0xA52E, 0, 0xB846, 0x417D, - 0, 0, 0, 0, 0x4446, 0xA52F, 0x2F5D, 0x5452, - 0xB848, 0xB849, 0xB84A, 0, 0, 0, 0xB84B, 0, - 0x4B4F, 0x2F5F, 0xA530, 0x5453, 0, 0, 0x5458, 0, - 0, 0xA531, 0, 0x4A2F, 0, 0, 0, 0, - 0x5457, 0x5451, 0x5454, 0x5456, 0xB850, 0, 0x3A26, 0, -}; -static const unsigned short utf8_to_euc_E5A3[] = { - 0, 0x4A49, 0xB851, 0, 0xB84F, 0x5459, 0, 0x4345, - 0xB852, 0, 0x3275, 0, 0x3E6D, 0xB853, 0xB854, 0, - 0xB855, 0x545B, 0xB856, 0x545A, 0xB857, 0x3968, 0xB858, 0x545C, - 0x545E, 0x545D, 0xB859, 0, 0x5460, 0xB85A, 0x5455, 0x5462, - 0, 0xB85B, 0xB85C, 0, 0x5461, 0x545F, 0, 0, - 0, 0xB85D, 0, 0x3B4E, 0x3F51, 0, 0x4154, 0x5463, - 0x403C, 0x306D, 0x4764, 0xB85E, 0, 0, 0, 0x445B, - 0, 0x5465, 0x5464, 0x5466, 0x5467, 0x5468, 0, 0, -}; -static const unsigned short utf8_to_euc_E5A3_x0213[] = { - 0, 0x4A49, 0xB851, 0xA533, 0xB84F, 0x5459, 0, 0x4345, - 0xB852, 0, 0x3275, 0, 0x3E6D, 0xA534, 0x2F62, 0, - 0xB855, 0x545B, 0x2F61, 0x545A, 0x2F63, 0x3968, 0xB858, 0x545C, - 0x545E, 0x545D, 0x2F64, 0, 0x5460, 0xB85A, 0x5455, 0x5462, - 0x2F65, 0xB85B, 0xA535, 0, 0x5461, 0x545F, 0, 0, - 0, 0x2F66, 0, 0x3B4E, 0x3F51, 0, 0x4154, 0x5463, - 0x403C, 0x306D, 0x4764, 0xA536, 0xA537, 0, 0, 0x445B, - 0, 0x5465, 0x5464, 0x5466, 0x5467, 0x5468, 0, 0, -}; -static const unsigned short utf8_to_euc_E5A4[] = { - 0, 0, 0x5469, 0, 0, 0xB85F, 0xB860, 0, - 0, 0x4A51, 0x546A, 0xB861, 0xB862, 0, 0, 0x3246, - 0x546B, 0, 0xB863, 0xB864, 0xB865, 0x4D3C, 0x3330, 0, - 0x5249, 0x3D48, 0x423F, 0x546C, 0x4C6B, 0xB867, 0, 0, - 0, 0xB868, 0x4C34, 0xB869, 0xB86A, 0x546E, 0, 0x4267, - 0xB86B, 0x4537, 0x4240, 0x4957, 0x546F, 0x5470, 0x317B, 0xB86C, - 0xB86D, 0x3C3A, 0x5471, 0xB86E, 0, 0xB86F, 0xB870, 0x3050, - 0x5472, 0, 0, 0, 0, 0, 0x5473, 0xB871, -}; -static const unsigned short utf8_to_euc_E5A4_x0213[] = { - 0, 0, 0x5469, 0, 0, 0xA538, 0xA539, 0, - 0, 0x4A51, 0x546A, 0xA53A, 0x2F67, 0xA53B, 0, 0x3246, - 0x546B, 0, 0xB863, 0xB864, 0xA53C, 0x4D3C, 0x3330, 0, - 0x5249, 0x3D48, 0x423F, 0x546C, 0x4C6B, 0xB867, 0, 0, - 0, 0xB868, 0x4C34, 0xB869, 0xA53D, 0x546E, 0, 0x4267, - 0xB86B, 0x4537, 0x4240, 0x4957, 0x546F, 0x5470, 0x317B, 0xB86C, - 0xB86D, 0x3C3A, 0x5471, 0xB86E, 0, 0xB86F, 0xB870, 0x3050, - 0x5472, 0, 0, 0, 0, 0xA540, 0x5473, 0xB871, -}; -static const unsigned short utf8_to_euc_E5A5[] = { - 0, 0, 0, 0xB872, 0x3162, 0, 0xB873, 0x3471, - 0x4660, 0x4A74, 0, 0, 0, 0, 0x5477, 0x4155, - 0x5476, 0x3740, 0xB874, 0xB875, 0x4B5B, 0x5475, 0, 0x4565, - 0x5479, 0xB876, 0x5478, 0xB877, 0, 0xB878, 0xB879, 0xB87A, - 0x547B, 0xB87B, 0x547A, 0xB87C, 0, 0x317C, 0, 0x547C, - 0x3E29, 0x547E, 0x4325, 0xB87D, 0x547D, 0xB87E, 0x4A33, 0xB921, - 0, 0, 0xB922, 0x3D77, 0x455B, 0xB923, 0xB924, 0, - 0x5521, 0xB925, 0, 0xB926, 0xB927, 0x3925, 0, 0, -}; -static const unsigned short utf8_to_euc_E5A5_x0213[] = { - 0, 0, 0, 0xB872, 0x3162, 0, 0xA542, 0x3471, - 0x4660, 0x4A74, 0, 0, 0, 0, 0x5477, 0x4155, - 0x5476, 0x3740, 0xB874, 0, 0x4B5B, 0x5475, 0, 0x4565, - 0x5479, 0xB876, 0x5478, 0xA545, 0, 0x2F69, 0xB879, 0xA546, - 0x547B, 0xB87B, 0x547A, 0, 0, 0x317C, 0, 0x547C, - 0x3E29, 0x547E, 0x4325, 0xB87D, 0x547D, 0x2F6A, 0x4A33, 0xB921, - 0, 0, 0xB922, 0x3D77, 0x455B, 0xA548, 0xA549, 0, - 0x5521, 0xB925, 0, 0xB926, 0xA54A, 0x3925, 0, 0, -}; -static const unsigned short utf8_to_euc_E5A6[] = { - 0, 0x5522, 0x4721, 0x485E, 0x4C51, 0, 0, 0, - 0, 0, 0x4725, 0xB928, 0xB929, 0x552B, 0xB92A, 0, - 0, 0, 0xB92B, 0x3538, 0, 0xB92C, 0x4D45, 0xB92D, - 0, 0x4C2F, 0, 0x562C, 0, 0x5523, 0, 0xB92E, - 0, 0, 0, 0x5526, 0xB92F, 0x4245, 0, 0xB930, - 0x4B38, 0, 0, 0, 0x454A, 0xB931, 0xB932, 0xB933, - 0xB934, 0, 0x5527, 0xB935, 0, 0, 0, 0xB936, - 0, 0x4B65, 0xB937, 0x3A4A, 0xB938, 0, 0x3E2A, 0, -}; -static const unsigned short utf8_to_euc_E5A6_x0213[] = { - 0, 0x5522, 0x4721, 0x485E, 0x4C51, 0, 0, 0, - 0, 0, 0x4725, 0x2F6B, 0xB929, 0x552B, 0xB92A, 0, - 0, 0, 0x2F6C, 0x3538, 0, 0xB92C, 0x4D45, 0xB92D, - 0, 0x4C2F, 0, 0x562C, 0, 0x5523, 0, 0xA54B, - 0, 0, 0, 0x5526, 0x2F6D, 0x4245, 0, 0xB930, - 0x4B38, 0, 0, 0, 0x454A, 0xB931, 0xA54C, 0xB933, - 0xB934, 0, 0x5527, 0xB935, 0, 0, 0, 0xB936, - 0, 0x4B65, 0, 0x3A4A, 0xA54D, 0, 0x3E2A, 0, -}; -static const unsigned short utf8_to_euc_E5A7[] = { - 0, 0xB939, 0, 0xB93A, 0xB93B, 0, 0x5528, 0, - 0xB93C, 0x3B50, 0xB93D, 0x3B4F, 0, 0xB93E, 0, 0, - 0x3039, 0x3848, 0xB93F, 0x402B, 0x3051, 0, 0, 0, - 0, 0x552C, 0x552D, 0, 0x552A, 0xB940, 0xB941, 0xB942, - 0, 0, 0, 0xB943, 0xB944, 0x3138, 0x342F, 0xB945, - 0x5529, 0, 0x4C45, 0x4931, 0, 0, 0xB946, 0xB947, - 0, 0xB948, 0xB949, 0, 0xB94A, 0, 0x3028, 0xB94B, - 0, 0, 0, 0x3079, 0, 0, 0, 0x3B51, -}; -static const unsigned short utf8_to_euc_E5A7_x0213[] = { - 0, 0xB939, 0, 0x2F6E, 0xB93B, 0, 0x5528, 0, - 0xA54E, 0x3B50, 0xB93D, 0x3B4F, 0, 0xA54F, 0, 0, - 0x3039, 0x3848, 0x2F6F, 0x402B, 0x3051, 0, 0, 0, - 0, 0x552C, 0x552D, 0, 0x552A, 0x2F70, 0xA550, 0xB942, - 0, 0, 0, 0xA551, 0xA552, 0x3138, 0x342F, 0xA553, - 0x5529, 0, 0x4C45, 0x4931, 0, 0, 0xA554, 0xB947, - 0, 0xB948, 0xB949, 0, 0xB94A, 0, 0x3028, 0xB94B, - 0x7E7A, 0, 0, 0x3079, 0, 0, 0, 0x3B51, -}; -static const unsigned short utf8_to_euc_E5A8[] = { - 0xB94C, 0x3052, 0, 0x3023, 0xB94D, 0, 0, 0, - 0, 0x5532, 0, 0, 0xB94E, 0xB94F, 0xB950, 0, - 0, 0x5530, 0xB951, 0xB952, 0, 0, 0, 0, - 0x4C3C, 0, 0x5533, 0, 0x5531, 0, 0xB953, 0x552F, - 0x3F31, 0, 0, 0xB954, 0xB955, 0x552E, 0, 0xB956, - 0xB957, 0x4A5A, 0xB958, 0, 0, 0xB959, 0, 0x3864, - 0xB95A, 0, 0, 0, 0, 0x5537, 0x5538, 0, - 0, 0, 0, 0, 0x3E2B, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E5A8_x0213[] = { - 0xB94C, 0x3052, 0, 0x3023, 0xB94D, 0, 0, 0, - 0, 0x5532, 0, 0, 0xA558, 0xA559, 0xB950, 0, - 0, 0x5530, 0xB951, 0x2F71, 0, 0, 0, 0xA55A, - 0x4C3C, 0, 0x5533, 0, 0x5531, 0, 0xB953, 0x552F, - 0x3F31, 0, 0, 0x2F72, 0xB955, 0x552E, 0, 0xA55B, - 0xB957, 0x4A5A, 0xB958, 0, 0, 0xA55C, 0, 0x3864, - 0xB95A, 0, 0, 0, 0, 0x5537, 0x5538, 0, - 0, 0, 0, 0, 0x3E2B, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E5A9[] = { - 0x5534, 0x4F2C, 0, 0, 0xB95B, 0xB95C, 0x474C, 0xB95D, - 0xB95E, 0x5536, 0, 0, 0xB95F, 0, 0, 0, - 0xB960, 0, 0, 0, 0, 0xB961, 0, 0, - 0, 0, 0x3A27, 0, 0, 0, 0xB962, 0, - 0, 0, 0x5539, 0xB963, 0, 0xB964, 0x4958, 0xB965, - 0, 0, 0x553A, 0, 0x5535, 0xB966, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xB967, - 0, 0, 0xB968, 0xB969, 0, 0, 0xB96A, 0x4C3B, -}; -static const unsigned short utf8_to_euc_E5A9_x0213[] = { - 0x5534, 0x4F2C, 0, 0, 0xB95B, 0xB95C, 0x474C, 0xB95D, - 0xB95E, 0x5536, 0, 0, 0xB95F, 0, 0, 0, - 0xB960, 0, 0, 0, 0, 0xA55D, 0, 0, - 0, 0, 0x3A27, 0, 0, 0, 0xB962, 0, - 0, 0, 0x5539, 0xB963, 0, 0xA55E, 0x4958, 0x2F73, - 0, 0, 0x553A, 0, 0x5535, 0x2F74, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x2F75, - 0, 0, 0xA55F, 0xB969, 0, 0, 0x2F76, 0x4C3B, -}; -static const unsigned short utf8_to_euc_E5AA[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xB96B, 0, 0, 0, 0, - 0xB96C, 0, 0x475E, 0xB96D, 0, 0, 0xB96E, 0, - 0, 0xB96F, 0x553B, 0x4932, 0xB970, 0, 0xB971, 0xB972, - 0xB973, 0, 0xB974, 0, 0, 0, 0, 0xB975, - 0, 0, 0, 0, 0xB976, 0, 0, 0, - 0, 0xB977, 0xB978, 0xB979, 0, 0xB97A, 0, 0, - 0xB97B, 0, 0xB97C, 0xB97D, 0x553C, 0x5540, 0x553D, 0xB97E, -}; -static const unsigned short utf8_to_euc_E5AA_x0213[] = { - 0, 0, 0, 0, 0x2F77, 0, 0, 0, - 0, 0, 0, 0xA560, 0, 0, 0, 0, - 0xB96C, 0, 0x475E, 0xB96D, 0, 0, 0xB96E, 0, - 0, 0xB96F, 0x553B, 0x4932, 0xA561, 0, 0x2F78, 0xA562, - 0xA563, 0, 0xA564, 0, 0, 0, 0, 0x2F79, - 0, 0, 0, 0, 0xB976, 0, 0, 0, - 0, 0xA565, 0xB978, 0xA566, 0, 0xA567, 0, 0, - 0xB97B, 0, 0xA568, 0xB97D, 0x553C, 0x5540, 0x553D, 0xA569, -}; -static const unsigned short utf8_to_euc_E5AB[] = { - 0, 0x3247, 0x553F, 0, 0xBA21, 0, 0xBA22, 0, - 0xBA23, 0x3C3B, 0, 0x553E, 0x3779, 0, 0, 0xBA24, - 0x554C, 0, 0, 0, 0, 0, 0x5545, 0x5542, - 0, 0, 0xBA25, 0, 0xBA26, 0, 0, 0, - 0xBA27, 0x4364, 0, 0x5541, 0, 0xBA28, 0x5543, 0, - 0, 0x5544, 0xBA29, 0, 0, 0, 0xBA2A, 0, - 0, 0, 0, 0, 0, 0xBA2B, 0xBA2C, 0, - 0, 0, 0x5546, 0x5547, 0, 0xBA2D, 0, 0, -}; -static const unsigned short utf8_to_euc_E5AB_x0213[] = { - 0, 0x3247, 0x553F, 0, 0x2F7A, 0, 0xBA22, 0, - 0xBA23, 0x3C3B, 0, 0x553E, 0x3779, 0, 0, 0xBA24, - 0x554C, 0, 0, 0, 0, 0, 0x5545, 0x5542, - 0, 0, 0xA56A, 0, 0xA56B, 0, 0, 0, - 0xA56C, 0x4364, 0, 0x5541, 0, 0xA56D, 0x5543, 0, - 0, 0x5544, 0xBA29, 0, 0, 0, 0xA56F, 0, - 0xA56E, 0, 0, 0, 0, 0xA570, 0xBA2C, 0, - 0, 0, 0x5546, 0x5547, 0, 0xBA2D, 0, 0, -}; -static const unsigned short utf8_to_euc_E5AC[] = { - 0xBA2E, 0xBA2F, 0, 0, 0, 0, 0, 0, - 0xBA30, 0x3472, 0, 0x5549, 0x5548, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x554A, 0xBA31, - 0, 0xBA33, 0, 0xBA34, 0, 0xBA35, 0, 0, - 0, 0xBA36, 0x3E6E, 0, 0, 0xBA37, 0, 0, - 0, 0, 0x554D, 0, 0x445C, 0xBA38, 0, 0, - 0x3145, 0, 0x554B, 0, 0xBA32, 0, 0x554E, 0, - 0xBA39, 0, 0, 0, 0, 0, 0x554F, 0, -}; -static const unsigned short utf8_to_euc_E5AC_x0213[] = { - 0xA571, 0xBA2F, 0, 0, 0, 0, 0, 0, - 0xA572, 0x3472, 0, 0x5549, 0x5548, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x554A, 0xA573, - 0, 0x2F7C, 0, 0xBA34, 0, 0xBA35, 0, 0, - 0, 0xBA36, 0x3E6E, 0, 0, 0x2F7D, 0, 0, - 0, 0, 0x554D, 0, 0x445C, 0xA575, 0, 0, - 0x3145, 0, 0x554B, 0, 0xA574, 0, 0x554E, 0, - 0xBA39, 0, 0, 0, 0, 0, 0x554F, 0, -}; -static const unsigned short utf8_to_euc_E5AD[] = { - 0x5552, 0xBA3A, 0, 0x5550, 0, 0x5551, 0, 0, - 0, 0, 0, 0xBA3B, 0xBA3C, 0, 0, 0, - 0x3B52, 0x5553, 0xBA3D, 0, 0x3926, 0x5554, 0xBA3E, 0x3B7A, - 0x4238, 0, 0x5555, 0x5556, 0x3B5A, 0x3927, 0xBA3F, 0x4C52, - 0, 0, 0, 0x3528, 0x3849, 0x5557, 0x3358, 0, - 0xBA40, 0x5558, 0, 0x4239, 0, 0, 0xBA41, 0xBA42, - 0x5559, 0x5623, 0, 0x555A, 0, 0x555B, 0, 0, - 0x555C, 0, 0x555E, 0, 0xBA43, 0xBA44, 0xBA45, 0xBA46, -}; -static const unsigned short utf8_to_euc_E5AD_x0213[] = { - 0x5552, 0x4F55, 0, 0x5550, 0, 0x5551, 0, 0, - 0, 0, 0, 0xBA3B, 0xA576, 0, 0, 0, - 0x3B52, 0x5553, 0xA577, 0, 0x3926, 0x5554, 0x4F56, 0x3B7A, - 0x4238, 0, 0x5555, 0x5556, 0x3B5A, 0x3927, 0xBA3F, 0x4C52, - 0, 0, 0, 0x3528, 0x3849, 0x5557, 0x3358, 0, - 0xA578, 0x5558, 0, 0x4239, 0, 0, 0xBA41, 0xA579, - 0x5559, 0x5623, 0, 0x555A, 0, 0x555B, 0, 0, - 0x555C, 0, 0x555E, 0, 0xA57A, 0x4F57, 0xBA45, 0xA57B, -}; -static const unsigned short utf8_to_euc_E5AE[] = { - 0x555F, 0xBA47, 0, 0x5560, 0xBA48, 0x4270, 0xBA49, 0x3127, - 0x3C69, 0x3042, 0xBA4A, 0x4157, 0x3430, 0x3C35, 0xBA4B, 0x3928, - 0xBA4C, 0xBA4D, 0, 0xBA4E, 0xBA4F, 0x4566, 0xBA50, 0x3D21, - 0x3431, 0x4368, 0x446A, 0x3038, 0x3539, 0x4A75, 0, 0x3C42, - 0, 0, 0x3552, 0x406B, 0x3C3C, 0x4D28, 0x5561, 0, - 0xBA51, 0xBA52, 0, 0, 0xBA53, 0xBA54, 0x355C, 0xBA55, - 0x3A4B, 0xBA56, 0xBA57, 0x3332, 0x3163, 0x3E2C, 0x3248, 0xBA58, - 0x5562, 0x4D46, 0xBA59, 0, 0xBA5A, 0, 0, 0x3D49, -}; -static const unsigned short utf8_to_euc_E5AE_x0213[] = { - 0x555F, 0xA57C, 0, 0x5560, 0xA57D, 0x4270, 0xBA49, 0x3127, - 0x3C69, 0x3042, 0xBA4A, 0x4157, 0x3430, 0x3C35, 0xBA4B, 0x3928, - 0xBA4C, 0xBA4D, 0, 0x4F58, 0xBA4F, 0x4566, 0xA821, 0x3D21, - 0x3431, 0x4368, 0x446A, 0x3038, 0x3539, 0x4A75, 0, 0x3C42, - 0, 0, 0x3552, 0x406B, 0x3C3C, 0x4D28, 0x5561, 0, - 0xBA51, 0xBA52, 0, 0, 0xA822, 0xBA54, 0x355C, 0xBA55, - 0x3A4B, 0xBA56, 0xBA57, 0x3332, 0x3163, 0x3E2C, 0x3248, 0xBA58, - 0x5562, 0x4D46, 0xBA59, 0, 0xBA5A, 0, 0, 0x3D49, -}; -static const unsigned short utf8_to_euc_E5AF[] = { - 0xBA5B, 0xBA5C, 0x3C64, 0x5563, 0x3473, 0x4652, 0x4C29, 0x5564, - 0, 0x5565, 0, 0, 0x4959, 0xBA5D, 0, 0xBA5E, - 0x5567, 0, 0x3428, 0x3677, 0x5566, 0, 0xBA5F, 0xBA60, - 0xBA61, 0xBA62, 0xBA63, 0x3432, 0, 0x3F32, 0x556B, 0x3B21, - 0xBA64, 0x3249, 0x556A, 0, 0x5568, 0x556C, 0x5569, 0x472B, - 0x5C4D, 0x3F33, 0, 0x556D, 0xF43A, 0, 0x4E40, 0xBA65, - 0x556E, 0xBA66, 0, 0x5570, 0xBA67, 0x437E, 0x556F, 0, - 0x4023, 0, 0x3B7B, 0, 0, 0xBA68, 0x4250, 0x3C77, -}; -static const unsigned short utf8_to_euc_E5AF_x0213[] = { - 0xA824, 0xBA5C, 0x3C64, 0x5563, 0x3473, 0x4652, 0x4C29, 0x5564, - 0, 0x5565, 0, 0, 0x4959, 0xBA5D, 0xA826, 0xBA5E, - 0x5567, 0, 0x3428, 0x3677, 0x5566, 0, 0xA827, 0xBA60, - 0x4F59, 0xBA62, 0xBA63, 0x3432, 0, 0x3F32, 0x556B, 0x3B21, - 0xBA64, 0x3249, 0x556A, 0, 0x5568, 0x556C, 0x5569, 0x472B, - 0x5C4D, 0x3F33, 0, 0x556D, 0x4F5A, 0, 0x4E40, 0xBA65, - 0x556E, 0xA82A, 0, 0x5570, 0xBA67, 0x437E, 0x556F, 0, - 0x4023, 0, 0x3B7B, 0, 0, 0xA82B, 0x4250, 0x3C77, -}; -static const unsigned short utf8_to_euc_E5B0[] = { - 0, 0x4975, 0x406C, 0, 0x3C4D, 0x5571, 0x3E2D, 0x5572, - 0x5573, 0x3053, 0x423A, 0x3F52, 0xBA69, 0x5574, 0x4633, 0x3E2E, - 0, 0x3E2F, 0, 0x5575, 0, 0, 0x406D, 0xBA6A, - 0, 0, 0x3E30, 0, 0, 0, 0xBA6B, 0xBA6C, - 0x5576, 0, 0x5577, 0xBA6D, 0x4C60, 0, 0xBA6E, 0, - 0x5578, 0xBA6F, 0, 0xBA70, 0xBA71, 0x3646, 0xBA72, 0, - 0xBA73, 0x3D22, 0xBA74, 0, 0, 0xBA75, 0xBA76, 0, - 0x5579, 0x557A, 0x3C5C, 0x3F2C, 0x4674, 0x3F54, 0x4878, 0x4722, -}; -static const unsigned short utf8_to_euc_E5B0_x0213[] = { - 0, 0x4975, 0x406C, 0xA82D, 0x3C4D, 0x5571, 0x3E2D, 0x5572, - 0x5573, 0x3053, 0x423A, 0x3F52, 0xBA69, 0x5574, 0x4633, 0x3E2E, - 0, 0x3E2F, 0x4F5B, 0x5575, 0, 0, 0x406D, 0xBA6A, - 0, 0, 0x3E30, 0, 0, 0, 0x4F5C, 0xBA6C, - 0x5576, 0, 0x5577, 0x4F5D, 0x4C60, 0, 0xBA6E, 0, - 0x5578, 0xA82E, 0, 0x4F5E, 0xBA71, 0x3646, 0xBA72, 0, - 0xA82F, 0x3D22, 0xBA74, 0, 0, 0xBA75, 0xBA76, 0, - 0x5579, 0x557A, 0x3C5C, 0x3F2C, 0x4674, 0x3F54, 0x4878, 0x4722, -}; -static const unsigned short utf8_to_euc_E5B1[] = { - 0x3649, 0x557B, 0, 0, 0, 0x356F, 0x557C, 0, - 0x367E, 0, 0x464F, 0x3230, 0, 0x3B53, 0x557D, 0x5622, - 0x5621, 0x367D, 0, 0x557E, 0, 0x4538, 0, 0, - 0, 0xBA77, 0xBA78, 0, 0xBA79, 0, 0x4230, 0, - 0x454B, 0x3C48, 0xBA7A, 0xBA7B, 0x4158, 0x4D7A, 0, 0xBA7C, - 0xBA7D, 0xBA7E, 0, 0, 0x5624, 0xBB21, 0x5625, 0x4656, - 0xBB22, 0x3B33, 0, 0, 0xBB23, 0xBB24, 0x5627, 0, - 0, 0x5628, 0xBB25, 0xBB26, 0xBB27, 0xBB28, 0, 0, -}; -static const unsigned short utf8_to_euc_E5B1_x0213[] = { - 0x3649, 0x557B, 0, 0, 0, 0x356F, 0x557C, 0, - 0x367E, 0, 0x464F, 0x3230, 0, 0x3B53, 0x557D, 0x5622, - 0x5621, 0x367D, 0, 0x557E, 0, 0x4538, 0, 0, - 0, 0xBA77, 0xBA78, 0x7E7B, 0xBA79, 0, 0x4230, 0xA831, - 0x454B, 0x3C48, 0x4F60, 0xA832, 0x4158, 0x4D7A, 0, 0xA833, - 0xA834, 0xA835, 0, 0, 0x5624, 0xBB21, 0x5625, 0x4656, - 0xA836, 0x3B33, 0, 0, 0xBB23, 0xBB24, 0x5627, 0, - 0, 0x5628, 0x4F64, 0xBB26, 0xA839, 0xBB28, 0, 0, -}; -static const unsigned short utf8_to_euc_E5B2[] = { - 0, 0, 0, 0, 0, 0, 0, 0xBB29, - 0xBB2A, 0, 0xBB2B, 0, 0x5629, 0, 0, 0xBB2C, - 0x3474, 0x562A, 0xBB2D, 0, 0x562B, 0, 0, 0, - 0, 0, 0, 0, 0, 0xBB2E, 0, 0xBB2F, - 0xBB30, 0x322C, 0xBB31, 0xBB32, 0, 0, 0xBB33, 0, - 0x413B, 0x3464, 0xBB34, 0x562D, 0x4C28, 0, 0, 0, - 0, 0x4252, 0xBB35, 0x3359, 0xBB36, 0xBB37, 0x562F, 0x5631, - 0x345F, 0, 0xBB38, 0x562E, 0x5630, 0, 0x5633, 0, -}; -static const unsigned short utf8_to_euc_E5B2_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0xBB29, - 0xA83C, 0, 0xA83D, 0, 0x5629, 0, 0, 0x4F65, - 0x3474, 0x562A, 0xBB2D, 0, 0x562B, 0, 0, 0, - 0, 0, 0, 0, 0, 0xBB2E, 0, 0x4F66, - 0xA841, 0x322C, 0xA842, 0x4F67, 0, 0, 0xA843, 0xA844, - 0x413B, 0x3464, 0x4F68, 0x562D, 0x4C28, 0xA846, 0, 0, - 0, 0x4252, 0xBB35, 0x3359, 0xBB36, 0xA847, 0x562F, 0x5631, - 0x345F, 0, 0x4F69, 0x562E, 0x5630, 0, 0x5633, 0, -}; -static const unsigned short utf8_to_euc_E5B3[] = { - 0, 0, 0, 0, 0, 0x5632, 0, 0x5634, - 0, 0xBB39, 0, 0xBB3A, 0, 0, 0, 0, - 0, 0, 0xBB3B, 0, 0, 0, 0, 0xBB3D, - 0, 0x5635, 0, 0, 0, 0xBB3C, 0, 0, - 0x463D, 0x362E, 0, 0, 0, 0, 0, 0, - 0x3265, 0x5636, 0x563B, 0, 0, 0x5639, 0xBB3E, 0x4A77, - 0x4A76, 0xBB3F, 0xBB40, 0, 0xBB41, 0xF43B, 0x4567, 0, - 0, 0, 0x5638, 0x3D54, 0, 0x5637, 0, 0, -}; -static const unsigned short utf8_to_euc_E5B3_x0213[] = { - 0, 0, 0, 0, 0, 0x5632, 0, 0x5634, - 0, 0xA849, 0, 0x4F6A, 0, 0, 0, 0, - 0x4F6B, 0, 0x4F6C, 0, 0, 0, 0, 0xBB3D, - 0, 0x5635, 0, 0, 0, 0xBB3C, 0, 0, - 0x463D, 0x362E, 0, 0, 0, 0, 0, 0, - 0x3265, 0x5636, 0x563B, 0, 0, 0x5639, 0xBB3E, 0x4A77, - 0x4A76, 0xBB3F, 0xBB40, 0, 0x4F6D, 0, 0x4567, 0, - 0, 0, 0x5638, 0x3D54, 0, 0x5637, 0, 0, -}; -static const unsigned short utf8_to_euc_E5B4[] = { - 0, 0xBB42, 0, 0, 0, 0, 0xBB43, 0x3F72, - 0, 0, 0, 0x563C, 0, 0xBB44, 0x3A6A, 0, - 0, 0x5642, 0xBB45, 0, 0x5643, 0x563D, 0x3333, 0x563E, - 0x5647, 0x5646, 0x5645, 0x5641, 0, 0, 0, 0x5640, - 0, 0, 0x5644, 0xBB47, 0xBB48, 0, 0xBB49, 0xBB4A, - 0, 0x4A78, 0, 0xBB46, 0, 0, 0, 0, - 0, 0xBB4B, 0, 0, 0xBB4C, 0, 0, 0, - 0, 0xBB4D, 0, 0, 0, 0xBB4E, 0, 0xBB4F, -}; -static const unsigned short utf8_to_euc_E5B4_x0213[] = { - 0, 0xBB42, 0, 0, 0, 0, 0xA84C, 0x3F72, - 0, 0, 0, 0x563C, 0, 0x4F70, 0x3A6A, 0, - 0xA84D, 0x5642, 0xBB45, 0, 0x5643, 0x563D, 0x3333, 0x563E, - 0x5647, 0x5646, 0x5645, 0x5641, 0, 0xA84F, 0, 0x5640, - 0xA850, 0, 0x5644, 0xBB47, 0xA851, 0, 0xA852, 0x4F71, - 0, 0x4A78, 0, 0xA84E, 0, 0, 0, 0, - 0, 0xA853, 0, 0, 0xBB4C, 0, 0, 0, - 0, 0xA854, 0, 0, 0, 0xBB4E, 0, 0xBB4F, -}; -static const unsigned short utf8_to_euc_E5B5[] = { - 0, 0, 0xBB50, 0xBB51, 0, 0, 0xBB52, 0, - 0xBB53, 0, 0xBB57, 0x564B, 0x5648, 0, 0x564A, 0, - 0x4D72, 0xBB55, 0x5649, 0xF43C, 0, 0xBB54, 0, 0, - 0, 0xBB56, 0, 0, 0x563F, 0, 0, 0xBB58, - 0xBB59, 0xBB5A, 0xBB5B, 0, 0xBB5C, 0, 0, 0, - 0, 0x3F73, 0xBB5D, 0, 0x564C, 0xBB5E, 0, 0x3A37, - 0xBB5F, 0, 0, 0x564D, 0, 0, 0x564E, 0, - 0, 0xBB60, 0xBB61, 0, 0, 0, 0xBB62, 0xBB63, -}; -static const unsigned short utf8_to_euc_E5B5_x0213[] = { - 0, 0, 0xA855, 0xBB51, 0, 0, 0x4F73, 0x4F74, - 0xBB53, 0, 0x4F76, 0x564B, 0x5648, 0, 0x564A, 0, - 0x4D72, 0xBB55, 0x5649, 0x4F75, 0, 0xBB54, 0, 0, - 0, 0xBB56, 0, 0, 0x563F, 0, 0, 0xBB58, - 0xBB59, 0xA857, 0xBB5B, 0, 0xBB5C, 0, 0, 0, - 0, 0x3F73, 0xA858, 0, 0x564C, 0x4F77, 0, 0x3A37, - 0xA85A, 0, 0, 0x564D, 0, 0, 0x564E, 0, - 0, 0xBB60, 0xBB61, 0, 0, 0, 0xBB62, 0xBB63, -}; -static const unsigned short utf8_to_euc_E5B6[] = { - 0, 0xBB64, 0x5651, 0xBB65, 0x5650, 0, 0, 0x564F, - 0xBB66, 0, 0xBB67, 0x4568, 0x563A, 0, 0, 0, - 0x5657, 0, 0xBB68, 0xBB69, 0xBB6A, 0xBB6B, 0, 0, - 0, 0xBB6C, 0, 0xBB6D, 0, 0x5653, 0, 0xBB6E, - 0xBB6F, 0, 0x5652, 0, 0, 0, 0, 0xBB70, - 0, 0, 0, 0xBB71, 0x5654, 0, 0x5655, 0, - 0xBB72, 0, 0xE674, 0, 0xBB73, 0, 0, 0x5658, - 0xBB74, 0xBB75, 0x4E66, 0, 0x5659, 0x5656, 0, 0, -}; -static const unsigned short utf8_to_euc_E5B6_x0213[] = { - 0, 0x4F78, 0x5651, 0xBB65, 0x5650, 0, 0, 0x564F, - 0xA85D, 0, 0xBB67, 0x4568, 0x563A, 0, 0, 0, - 0x5657, 0, 0xA85F, 0xBB69, 0xA860, 0xBB6B, 0, 0xA861, - 0, 0xA862, 0, 0xBB6D, 0, 0x5653, 0, 0xBB6E, - 0x4F79, 0, 0x5652, 0, 0x4F7A, 0, 0, 0x4F7B, - 0, 0, 0, 0xBB71, 0x5654, 0, 0x5655, 0, - 0xA863, 0, 0xA864, 0, 0xA865, 0, 0, 0x5658, - 0x4F7C, 0xA867, 0x4E66, 0, 0x5659, 0x5656, 0, 0, -}; -static const unsigned short utf8_to_euc_E5B7[] = { - 0, 0, 0, 0xBB76, 0, 0, 0, 0xBB77, - 0, 0x565A, 0, 0xBB78, 0x3460, 0x565B, 0xBB7A, 0, - 0xBB79, 0, 0x565D, 0x565C, 0, 0, 0x565E, 0, - 0xBB7B, 0xBB7C, 0, 0x565F, 0, 0x406E, 0x3D23, 0, - 0xBB7D, 0x3D64, 0, 0x4163, 0xBB7E, 0x3929, 0x3A38, 0x392A, - 0x3570, 0xBC21, 0, 0x5660, 0, 0, 0x3A39, 0, - 0, 0x384A, 0x5661, 0x4C26, 0x4743, 0x5662, 0, 0x392B, - 0xBC22, 0xBC23, 0, 0x342C, 0, 0x4327, 0x3652, 0, -}; -static const unsigned short utf8_to_euc_E5B7_x0213[] = { - 0, 0, 0, 0xBB76, 0, 0, 0, 0xBB77, - 0, 0x565A, 0, 0x4F7D, 0x3460, 0x565B, 0xBB7A, 0, - 0, 0xA868, 0x565D, 0x565C, 0, 0, 0x565E, 0xA869, - 0xA86A, 0xBB7C, 0, 0x565F, 0, 0x406E, 0x3D23, 0, - 0xA86B, 0x3D64, 0x7428, 0x4163, 0xA86D, 0x3929, 0x3A38, 0x392A, - 0x3570, 0xA86E, 0, 0x5660, 0, 0, 0x3A39, 0, - 0, 0x384A, 0x5661, 0x4C26, 0x4743, 0x5662, 0, 0x392B, - 0xBC22, 0xBC23, 0, 0x342C, 0, 0x4327, 0x3652, 0, -}; -static const unsigned short utf8_to_euc_E5B8[] = { - 0xBC24, 0, 0x3B54, 0x495B, 0, 0, 0x4841, 0xBC25, - 0, 0, 0, 0x5663, 0x3475, 0xBC26, 0, 0, - 0, 0x5666, 0xBC27, 0, 0xBC28, 0xBC29, 0x4421, 0, - 0xBC2A, 0x5665, 0x5664, 0x5667, 0, 0x446B, 0, 0xBC2B, - 0xBC2C, 0, 0, 0, 0, 0x3F63, 0, 0, - 0xBC2E, 0, 0, 0x3B55, 0, 0x404A, 0xBC2D, 0x4253, - 0x3522, 0, 0xBC2F, 0x4422, 0, 0xBC30, 0x5668, 0x5669, - 0x3E6F, 0, 0, 0, 0, 0x4B39, 0xBC31, 0, -}; -static const unsigned short utf8_to_euc_E5B8_x0213[] = { - 0xA870, 0, 0x3B54, 0x495B, 0, 0, 0x4841, 0xBC25, - 0, 0, 0, 0x5663, 0x3475, 0xBC26, 0, 0, - 0, 0x5666, 0xA872, 0, 0x7429, 0xA873, 0x4421, 0, - 0x742A, 0x5665, 0x5664, 0x5667, 0, 0x446B, 0, 0xA875, - 0xBC2C, 0, 0, 0, 0, 0x3F63, 0, 0, - 0xBC2E, 0, 0, 0x3B55, 0, 0x404A, 0xA876, 0x4253, - 0x3522, 0, 0xBC2F, 0x4422, 0, 0xBC30, 0x5668, 0x5669, - 0x3E6F, 0, 0, 0, 0, 0x4B39, 0xA877, 0, -}; -static const unsigned short utf8_to_euc_E5B9[] = { - 0x566C, 0, 0, 0x566B, 0x566A, 0x497D, 0, 0x5673, - 0, 0xBC34, 0, 0xBC32, 0x4B5A, 0, 0x566D, 0, - 0xBC33, 0xBC35, 0, 0, 0x566F, 0x4B6B, 0xBC36, 0x566E, - 0xBC37, 0, 0, 0xBC38, 0xBC39, 0, 0xBC3A, 0x5670, - 0, 0x4828, 0x5671, 0x4A3E, 0x5672, 0, 0, 0, - 0xBC3B, 0, 0xBC3C, 0xBC3D, 0xBC3E, 0xBC3F, 0xBC40, 0, - 0xBC41, 0, 0x3433, 0x4A3F, 0x472F, 0x5674, 0x5675, 0, - 0x392C, 0x3434, 0x5676, 0x3838, 0x4D44, 0x4D29, 0x3476, 0x5678, -}; -static const unsigned short utf8_to_euc_E5B9_x0213[] = { - 0x566C, 0, 0, 0x566B, 0x566A, 0x497D, 0, 0x5673, - 0, 0xA878, 0, 0xBC32, 0x4B5A, 0, 0x566D, 0, - 0xBC33, 0xBC35, 0, 0, 0x566F, 0x4B6B, 0xA87A, 0x566E, - 0x742B, 0, 0, 0xBC38, 0xBC39, 0, 0x742C, 0x5670, - 0, 0x4828, 0x5671, 0x4A3E, 0x5672, 0, 0, 0, - 0xBC3B, 0, 0xBC3C, 0xA87C, 0xA87D, 0xA87E, 0xAC21, 0, - 0xBC41, 0, 0x3433, 0x4A3F, 0x472F, 0x5674, 0x5675, 0x7E7C, - 0x392C, 0x3434, 0x5676, 0x3838, 0x4D44, 0x4D29, 0x3476, 0x5678, -}; -static const unsigned short utf8_to_euc_E5BA[] = { - 0xBC42, 0x4423, 0, 0x392D, 0x3E31, 0, 0, 0x485F, - 0, 0, 0x3E32, 0xBC43, 0, 0, 0xBC44, 0x3D78, - 0, 0, 0, 0, 0, 0x446C, 0x4A79, 0x4539, - 0, 0, 0x392E, 0, 0x495C, 0, 0, 0, - 0x5679, 0, 0xBC45, 0, 0xBC46, 0xBC47, 0x4559, 0x3A42, - 0xBC48, 0, 0xBC49, 0x384B, 0xBC4A, 0x446D, 0, 0, - 0, 0xBC4B, 0, 0xBC4C, 0, 0x3043, 0x3D6E, 0x392F, - 0x4D47, 0, 0, 0, 0, 0xBC4D, 0xBC4E, 0xBC4F, -}; -static const unsigned short utf8_to_euc_E5BA_x0213[] = { - 0xBC42, 0x4423, 0, 0x392D, 0x3E31, 0, 0, 0x485F, - 0, 0, 0x3E32, 0xBC43, 0, 0, 0xBC44, 0x3D78, - 0, 0, 0, 0, 0, 0x446C, 0x4A79, 0x4539, - 0, 0, 0x392E, 0, 0x495C, 0, 0, 0, - 0x5679, 0, 0xBC45, 0, 0xBC46, 0xAC23, 0x4559, 0x3A42, - 0xBC48, 0, 0xAC24, 0x384B, 0xAC25, 0x446D, 0, 0, - 0, 0xBC4B, 0, 0xBC4C, 0, 0x3043, 0x3D6E, 0x392F, - 0x4D47, 0xAC26, 0, 0, 0, 0xBC4D, 0x742D, 0xAC27, -}; -static const unsigned short utf8_to_euc_E5BB[] = { - 0, 0x567A, 0x567B, 0x4751, 0, 0, 0xBC50, 0, - 0x567C, 0x4E77, 0x4F2D, 0xBC52, 0xBC51, 0, 0xBC53, 0x567E, - 0x567D, 0xBC54, 0xBC55, 0x3347, 0xBC56, 0xBC57, 0x5721, 0, - 0, 0, 0x5724, 0x5725, 0xBC58, 0x5723, 0xBC59, 0x4940, - 0x3E33, 0x5727, 0x5726, 0x5722, 0, 0xBC5A, 0, 0, - 0x5728, 0x5729, 0, 0xBC5B, 0x572A, 0, 0, 0, - 0x572D, 0x572B, 0, 0x572C, 0x572E, 0, 0x3164, 0x446E, - 0x572F, 0, 0x377A, 0x3276, 0x4736, 0, 0x5730, 0x467B, -}; -static const unsigned short utf8_to_euc_E5BB_x0213[] = { - 0, 0x567A, 0x567B, 0x4751, 0, 0, 0xAC28, 0, - 0x567C, 0x4E77, 0x4F2D, 0x742F, 0xBC51, 0, 0xBC53, 0x567E, - 0x567D, 0xBC54, 0xAC29, 0x3347, 0xBC56, 0xBC57, 0x5721, 0, - 0, 0xAC2A, 0x5724, 0x5725, 0xBC58, 0x5723, 0xBC59, 0x4940, - 0x3E33, 0x5727, 0x5726, 0x5722, 0, 0xBC5A, 0, 0, - 0x5728, 0x5729, 0, 0xBC5B, 0x572A, 0, 0, 0, - 0x572D, 0x572B, 0, 0x572C, 0x572E, 0, 0x3164, 0x446E, - 0x572F, 0x7430, 0x377A, 0x3276, 0x4736, 0xAC2C, 0x5730, 0x467B, -}; -static const unsigned short utf8_to_euc_E5BC[] = { - 0, 0x4A5B, 0xBC5C, 0x5731, 0x4F2E, 0, 0xBC5D, 0xBC5E, - 0xBC5F, 0x5732, 0x4A40, 0x5735, 0x5021, 0x5031, 0xBC60, 0x3C30, - 0x4675, 0x5736, 0, 0x355D, 0x4424, 0x307A, 0x5737, 0x4A26, - 0x3930, 0xBC61, 0, 0x4350, 0xBC62, 0xBC63, 0, 0x446F, - 0, 0xBC64, 0xBC65, 0xBC66, 0xBC67, 0x4C6F, 0x3839, 0x384C, - 0xBC68, 0x5738, 0, 0xBC69, 0xBC6A, 0x5739, 0xBC6B, 0x573F, - 0xBC6C, 0x3C65, 0, 0, 0xBC6D, 0x4425, 0xBC6E, 0x362F, - 0x573A, 0, 0, 0xBC6F, 0x492B, 0xBC70, 0x4346, 0xBC71, -}; -static const unsigned short utf8_to_euc_E5BC_x0213[] = { - 0x7431, 0x4A5B, 0x7432, 0x5731, 0x4F2E, 0, 0xBC5D, 0x7433, - 0xAC2D, 0x5732, 0x4A40, 0x5735, 0x5021, 0x5031, 0xAC2E, 0x3C30, - 0x4675, 0x5736, 0, 0x355D, 0x4424, 0x307A, 0x5737, 0x4A26, - 0x3930, 0xBC61, 0, 0x4350, 0xAC2F, 0x7434, 0xAC31, 0x446F, - 0, 0, 0xBC65, 0x7435, 0xBC67, 0x4C6F, 0x3839, 0x384C, - 0xBC68, 0x5738, 0, 0xBC69, 0xBC6A, 0x5739, 0xBC6B, 0x573F, - 0xBC6C, 0x3C65, 0, 0, 0x7436, 0x4425, 0x7437, 0x362F, - 0x573A, 0, 0, 0xBC6F, 0x492B, 0x7438, 0x4346, 0xBC71, -}; -static const unsigned short utf8_to_euc_E5BD[] = { - 0xBC72, 0x573B, 0, 0, 0xBC73, 0xBC74, 0, 0xBC75, - 0x573C, 0, 0x3630, 0, 0x573D, 0xBC76, 0x573E, 0, - 0xBC77, 0x5740, 0, 0x4576, 0xBC78, 0, 0x5741, 0x5742, - 0xBC79, 0x5743, 0, 0xBC7A, 0x5734, 0x5733, 0, 0, - 0xBC7B, 0x5744, 0x3741, 0xBC7C, 0xBC7D, 0, 0x4927, 0xBC7E, - 0, 0x3A4C, 0x4937, 0x4426, 0x494B, 0x5745, 0, 0xBD21, - 0x3E34, 0x3146, 0xBD22, 0x5746, 0xBD23, 0xBD24, 0, 0x5747, - 0xBD25, 0x4C72, 0xBD26, 0, 0x4860, 0xBD27, 0xBD28, 0x574A, -}; -static const unsigned short utf8_to_euc_E5BD_x0213[] = { - 0x7439, 0x573B, 0, 0, 0xBC73, 0x743A, 0, 0xAC32, - 0x573C, 0, 0x3630, 0, 0x573D, 0xBC76, 0x573E, 0, - 0xBC77, 0x5740, 0, 0x4576, 0x743B, 0, 0x5741, 0x5742, - 0x743C, 0x5743, 0, 0xBC7A, 0x5734, 0x5733, 0, 0, - 0xBC7B, 0x5744, 0x3741, 0xAC33, 0x743D, 0, 0x4927, 0x743E, - 0, 0x3A4C, 0x4937, 0x4426, 0x494B, 0x5745, 0, 0xBD21, - 0x3E34, 0x3146, 0xAC34, 0x5746, 0xBD23, 0xBD24, 0, 0x5747, - 0xBD25, 0x4C72, 0xBD26, 0, 0x4860, 0x743F, 0xAC35, 0x574A, -}; -static const unsigned short utf8_to_euc_E5BE[] = { - 0x317D, 0x402C, 0x5749, 0x5748, 0x3742, 0x4254, 0, 0x574E, - 0x574C, 0xBD29, 0x574B, 0x4E27, 0x3865, 0xBD2A, 0, 0xBD2B, - 0x3D79, 0x574D, 0x454C, 0x3D3E, 0, 0, 0xBD2C, 0x4640, - 0x5751, 0x5750, 0, 0, 0xBD2D, 0xBD2E, 0x574F, 0, - 0x5752, 0x3866, 0xBD2F, 0, 0xBD32, 0, 0, 0xBD30, - 0x5753, 0x497C, 0x3D5B, 0xBD31, 0xBD33, 0x5754, 0x4879, 0xBD34, - 0xBD35, 0xBD36, 0, 0x4641, 0x4427, 0, 0, 0xF43E, - 0xBD37, 0x4530, 0, 0, 0x5755, 0x352B, 0, 0, -}; -static const unsigned short utf8_to_euc_E5BE_x0213[] = { - 0x317D, 0x402C, 0x5749, 0x5748, 0x3742, 0x4254, 0, 0x574E, - 0x574C, 0x7440, 0x574B, 0x4E27, 0x3865, 0xBD2A, 0, 0xAC36, - 0x3D79, 0x574D, 0x454C, 0x3D3E, 0, 0, 0xBD2C, 0x4640, - 0x5751, 0x5750, 0, 0, 0x7441, 0xBD2E, 0x574F, 0, - 0x5752, 0x3866, 0xAC37, 0, 0xAC38, 0, 0, 0x7442, - 0x5753, 0x497C, 0x3D5B, 0xBD31, 0xBD33, 0x5754, 0x4879, 0x7443, - 0xBD35, 0xBD36, 0, 0x4641, 0x4427, 0x7444, 0, 0x7445, - 0xAC39, 0x4530, 0, 0, 0x5755, 0x352B, 0, 0, -}; -static const unsigned short utf8_to_euc_E5BF[] = { - 0, 0, 0, 0x3F34, 0xBD38, 0x492C, 0, 0xBD39, - 0xBD3A, 0xBD3B, 0, 0xBD3C, 0x3477, 0x4726, 0, 0, - 0xBD3D, 0xBD3E, 0xBD3F, 0xBD40, 0xBD41, 0, 0x5756, 0x3B56, - 0x4B3A, 0x4B3B, 0, 0, 0x317E, 0x575B, 0xBD42, 0, - 0x4369, 0xBD43, 0xBD44, 0, 0x5758, 0, 0, 0, - 0xBD45, 0xBD46, 0xBD47, 0x3277, 0xBD48, 0xBD49, 0xBD4A, 0xBD4B, - 0x582D, 0x575A, 0xBD4C, 0xBD4D, 0, 0x4730, 0xBD4E, 0, - 0x5759, 0, 0xBD4F, 0x5757, 0xBD50, 0x397A, 0, 0x575D, -}; -static const unsigned short utf8_to_euc_E5BF_x0213[] = { - 0, 0, 0, 0x3F34, 0xAC3A, 0x492C, 0, 0xAC3C, - 0xBD3A, 0x7446, 0, 0xAC3D, 0x3477, 0x4726, 0, 0, - 0xBD3D, 0xBD3E, 0xAC3E, 0xAC3F, 0xAC40, 0, 0x5756, 0x3B56, - 0x4B3A, 0x4B3B, 0, 0, 0x317E, 0x575B, 0x7447, 0, - 0x4369, 0x7448, 0xAC41, 0, 0x5758, 0, 0, 0, - 0xBD45, 0x7449, 0xBD47, 0x3277, 0xBD48, 0xBD49, 0xAC42, 0xAC43, - 0x582D, 0x575A, 0xBD4C, 0xAC44, 0, 0x4730, 0xBD4E, 0, - 0x5759, 0, 0xBD4F, 0x5757, 0xAC45, 0x397A, 0, 0x575D, -}; -static const unsigned short utf8_to_euc_E680[] = { - 0, 0, 0, 0, 0, 0, 0, 0xBD51, - 0, 0, 0xBD52, 0, 0, 0xBD53, 0x5763, 0x5769, - 0x5761, 0, 0x455C, 0xBD54, 0xBD55, 0x5766, 0x495D, 0xBD56, - 0xBD57, 0x5760, 0xBD58, 0x5765, 0x4E67, 0x3B57, 0, 0xBD59, - 0x4255, 0x575E, 0, 0, 0xBD5A, 0x355E, 0x5768, 0x402D, - 0x3165, 0x5762, 0x3278, 0x5767, 0, 0xBD5B, 0, 0x3631, - 0, 0x5764, 0, 0xBD5C, 0, 0xBD5D, 0, 0, - 0, 0, 0x576A, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E680_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0xBD51, - 0, 0, 0xBD52, 0, 0, 0x744A, 0x5763, 0x5769, - 0x5761, 0, 0x455C, 0xBD54, 0x744B, 0x5766, 0x495D, 0xAC47, - 0x744C, 0x5760, 0xBD58, 0x5765, 0x4E67, 0x3B57, 0, 0xBD59, - 0x4255, 0x575E, 0xAC48, 0, 0xAC49, 0x355E, 0x5768, 0x402D, - 0x3165, 0x5762, 0x3278, 0x5767, 0, 0xBD5B, 0, 0x3631, - 0, 0x5764, 0, 0x744D, 0, 0x744E, 0, 0, - 0, 0, 0x576A, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E681[] = { - 0xBD5E, 0x576C, 0x5776, 0x5774, 0, 0, 0x5771, 0xBD5F, - 0xBD60, 0xBD61, 0x5770, 0x4E78, 0xBD62, 0x5772, 0, 0, - 0x3632, 0xBD63, 0x3931, 0, 0xBD64, 0x3D7A, 0xBD65, 0xBD66, - 0, 0x5779, 0x576B, 0, 0, 0xBD67, 0, 0x576F, - 0x575F, 0xBD68, 0x327A, 0x5773, 0x5775, 0x4351, 0, 0xBD69, - 0x3A28, 0x3238, 0x576D, 0x5778, 0x5777, 0x3633, 0, 0x4229, - 0x3366, 0xBD6A, 0, 0, 0, 0x3743, 0, 0x576E, - 0, 0, 0, 0, 0, 0, 0xBD6B, 0xBD6C, -}; -static const unsigned short utf8_to_euc_E681_x0213[] = { - 0xBD5E, 0x576C, 0x5776, 0x5774, 0, 0, 0x5771, 0x744F, - 0xBD60, 0xBD61, 0x5770, 0x4E78, 0xAC4B, 0x5772, 0, 0, - 0x3632, 0xBD63, 0x3931, 0, 0xBD64, 0x3D7A, 0xBD65, 0xBD66, - 0, 0x5779, 0x576B, 0, 0, 0, 0, 0x576F, - 0x575F, 0xBD68, 0x327A, 0x5773, 0x5775, 0x4351, 0, 0xBD69, - 0x3A28, 0x3238, 0x576D, 0x5778, 0x5777, 0x3633, 0, 0x4229, - 0x3366, 0xBD6A, 0, 0, 0, 0x3743, 0, 0x576E, - 0, 0, 0, 0, 0, 0, 0xBD6B, 0xAC4C, -}; -static const unsigned short utf8_to_euc_E682[] = { - 0, 0x577A, 0xBD6D, 0x577D, 0x5821, 0xF43F, 0xBD6E, 0, - 0xBD6F, 0x3C3D, 0xBD70, 0x5827, 0x4470, 0x577B, 0xBD71, 0, - 0, 0xBD72, 0x5825, 0xBD73, 0x3279, 0xBD74, 0x5823, 0x5824, - 0xBD75, 0, 0x577E, 0x5822, 0, 0xBD76, 0xBD77, 0x3867, - 0x4D2A, 0, 0xBD78, 0x3435, 0xBD79, 0xBD7A, 0x3159, 0x5826, - 0xBD7B, 0x473A, 0x302D, 0, 0, 0, 0, 0, - 0xBD7C, 0xBD7D, 0x4861, 0x575C, 0x582C, 0x5830, 0x4C65, 0xBD7E, - 0x5829, 0, 0, 0xBE21, 0x4569, 0x582E, 0xBE22, 0, -}; -static const unsigned short utf8_to_euc_E682_x0213[] = { - 0, 0x577A, 0xBD6D, 0x577D, 0x5821, 0, 0xBD6E, 0, - 0xBD6F, 0x3C3D, 0xAC4D, 0x5827, 0x4470, 0x577B, 0xBD71, 0, - 0, 0xBD72, 0x5825, 0xBD73, 0x3279, 0xAC4E, 0x5823, 0x5824, - 0xBD75, 0, 0x577E, 0x5822, 0, 0x7451, 0x7452, 0x3867, - 0x4D2A, 0, 0xBD78, 0x3435, 0xBD79, 0xBD7A, 0x3159, 0x5826, - 0xAC4F, 0x473A, 0x302D, 0, 0, 0, 0, 0, - 0xAC51, 0xAC52, 0x4861, 0x575C, 0x582C, 0x5830, 0x4C65, 0xBD7E, - 0x5829, 0, 0, 0xBE21, 0x4569, 0x582E, 0xAC53, 0, -}; -static const unsigned short utf8_to_euc_E683[] = { - 0, 0, 0xBE23, 0, 0xBE24, 0x3E70, 0x582F, 0x4657, - 0xBE25, 0xBE26, 0xBE27, 0xBE28, 0, 0, 0xBE29, 0xBE2A, - 0, 0x4F47, 0, 0x582B, 0xBE2B, 0xBE2C, 0, 0, - 0x5831, 0xBE2D, 0x397B, 0xBE2E, 0x404B, 0xBE2F, 0xBE30, 0x3054, - 0x582A, 0x5828, 0xBE31, 0x415A, 0, 0xBE32, 0, 0x577C, - 0x3B34, 0, 0, 0, 0, 0, 0, 0, - 0x4246, 0x583D, 0xBE33, 0x415B, 0x5838, 0xBE34, 0x5835, 0x5836, - 0xBE35, 0x3C66, 0x5839, 0x583C, 0xBE36, 0xBE37, 0, 0, -}; -static const unsigned short utf8_to_euc_E683_x0213[] = { - 0, 0, 0xBE23, 0, 0xBE24, 0x3E70, 0x582F, 0x4657, - 0xAC54, 0xBE26, 0xBE27, 0x7453, 0, 0, 0xBE29, 0xBE2A, - 0, 0x4F47, 0, 0x582B, 0x7454, 0x7455, 0, 0, - 0x5831, 0xAC55, 0x397B, 0xAC56, 0x404B, 0x7456, 0, 0x3054, - 0x582A, 0x5828, 0xBE31, 0x415A, 0, 0xBE32, 0, 0x577C, - 0x3B34, 0, 0, 0, 0, 0, 0xAC57, 0, - 0x4246, 0x583D, 0xAC58, 0x415B, 0x5838, 0xAC59, 0x5835, 0x5836, - 0x7457, 0x3C66, 0x5839, 0x583C, 0xBE36, 0xBE37, 0, 0, -}; -static const unsigned short utf8_to_euc_E684[] = { - 0x5837, 0x3D25, 0xBE38, 0x583A, 0, 0, 0x5834, 0xBE39, - 0x4C7C, 0x4C7B, 0xBE3A, 0, 0xBE3B, 0x583E, 0x583F, 0x3055, - 0xBE3C, 0xBE3D, 0xBE3E, 0xBE3F, 0xBE40, 0x5833, 0xBE41, 0xBE42, - 0, 0xBE43, 0x3672, 0x3026, 0xBE44, 0, 0xBE45, 0x3436, - 0xF440, 0x583B, 0xBE46, 0, 0, 0, 0, 0x5843, - 0x5842, 0, 0xBE47, 0xBE48, 0x5847, 0, 0, 0, - 0xBE49, 0xBE4A, 0, 0, 0x5848, 0xBE4B, 0xBE4C, 0xBE4D, - 0, 0xBE4E, 0, 0, 0x5846, 0x5849, 0x5841, 0x5845, -}; -static const unsigned short utf8_to_euc_E684_x0213[] = { - 0x5837, 0x3D25, 0xBE38, 0x583A, 0, 0, 0x5834, 0xBE39, - 0x4C7C, 0x4C7B, 0xBE3A, 0, 0xBE3B, 0x583E, 0x583F, 0x3055, - 0xAC5A, 0, 0xAC5B, 0xAC5C, 0xBE40, 0x5833, 0xBE41, 0xBE42, - 0, 0xAC5D, 0x3672, 0x3026, 0x7458, 0, 0xAC5E, 0x3436, - 0, 0x583B, 0xBE46, 0, 0, 0, 0, 0x5843, - 0x5842, 0, 0xBE47, 0x7459, 0x5847, 0, 0, 0, - 0x745A, 0xBE4A, 0, 0, 0x5848, 0xBE4B, 0xBE4C, 0x745B, - 0, 0xBE4E, 0xAC5F, 0, 0x5846, 0x5849, 0x5841, 0x5845, -}; -static const unsigned short utf8_to_euc_E685[] = { - 0, 0xBE4F, 0x584A, 0, 0x584B, 0xBE50, 0xBE51, 0x5840, - 0x3B7C, 0xBE52, 0x5844, 0x4256, 0x3932, 0x5832, 0x3F35, 0, - 0, 0, 0, 0x5858, 0, 0x4A69, 0, 0, - 0x584E, 0x584F, 0x5850, 0, 0, 0x5857, 0xBE53, 0x5856, - 0xBE54, 0, 0x4B7D, 0x3437, 0, 0x5854, 0, 0x3745, - 0x3334, 0, 0, 0x5851, 0xBE55, 0, 0x4E38, 0x5853, - 0x3056, 0x5855, 0xBE56, 0x584C, 0x5852, 0x5859, 0x3744, 0x584D, - 0xBE57, 0, 0, 0xBE58, 0xBE59, 0, 0x4D5D, 0xBE5A, -}; -static const unsigned short utf8_to_euc_E685_x0213[] = { - 0, 0xAC61, 0x584A, 0, 0x584B, 0xBE50, 0xAC62, 0x5840, - 0x3B7C, 0xBE52, 0x5844, 0x4256, 0x3932, 0x5832, 0x3F35, 0, - 0, 0, 0, 0x5858, 0, 0x4A69, 0, 0, - 0x584E, 0x584F, 0x5850, 0, 0, 0x5857, 0xBE53, 0x5856, - 0xAC63, 0, 0x4B7D, 0x3437, 0, 0x5854, 0, 0x3745, - 0x3334, 0, 0, 0x5851, 0xBE55, 0, 0x4E38, 0x5853, - 0x3056, 0x5855, 0xBE56, 0x584C, 0x5852, 0x5859, 0x3744, 0x584D, - 0xBE57, 0, 0, 0xBE58, 0xAC64, 0, 0x4D5D, 0xBE5A, -}; -static const unsigned short utf8_to_euc_E686[] = { - 0xBE5B, 0xBE5C, 0x4D2B, 0xBE5D, 0xBE5E, 0, 0, 0x585C, - 0, 0, 0x5860, 0xBE5F, 0, 0xBE60, 0x417E, 0, - 0x4E79, 0x5861, 0xBE61, 0xBE62, 0x585E, 0, 0x585B, 0xBE63, - 0xBE64, 0x585A, 0x585F, 0, 0xBE65, 0xBE66, 0, 0xBE67, - 0xBE68, 0, 0, 0, 0x4A30, 0xBE69, 0, 0x4634, - 0xBE6A, 0x3746, 0xBE6B, 0x5862, 0x585D, 0xBE6C, 0x5863, 0, - 0, 0, 0x377B, 0, 0, 0, 0x3231, 0, - 0xBE6D, 0xBE6E, 0x586B, 0, 0xBE6F, 0, 0x3438, 0, -}; -static const unsigned short utf8_to_euc_E686_x0213[] = { - 0xBE5B, 0xBE5C, 0x4D2B, 0xBE5D, 0xBE5E, 0, 0, 0x585C, - 0, 0, 0x5860, 0xBE5F, 0, 0x745D, 0x417E, 0, - 0x4E79, 0x5861, 0xAC66, 0xAC67, 0x585E, 0, 0x585B, 0xAC68, - 0xAC69, 0x585A, 0x585F, 0, 0xBE65, 0xBE66, 0, 0xBE67, - 0xBE68, 0, 0, 0, 0x4A30, 0xAC6A, 0, 0x4634, - 0xAC6B, 0x3746, 0xBE6B, 0x5862, 0x585D, 0xAC6C, 0x5863, 0, - 0, 0, 0x377B, 0, 0, 0, 0x3231, 0, - 0xBE6D, 0x7460, 0x586B, 0, 0x745F, 0, 0x3438, 0, -}; -static const unsigned short utf8_to_euc_E687[] = { - 0xBE70, 0xBE71, 0xBE72, 0x5869, 0, 0, 0x586A, 0x3A29, - 0x5868, 0x5866, 0x5865, 0x586C, 0x5864, 0x586E, 0xBE73, 0xBE74, - 0x327B, 0, 0, 0, 0, 0xBE75, 0, 0, - 0, 0, 0, 0, 0xBE76, 0xBE77, 0xBE78, 0xBE79, - 0, 0xBE7A, 0xBE7B, 0x5870, 0, 0xBE7E, 0x586F, 0xBE7C, - 0, 0xBE7D, 0, 0, 0xBF21, 0xBF22, 0, 0xBF23, - 0, 0, 0x4428, 0, 0x5873, 0, 0x5871, 0x5867, - 0x377C, 0, 0x5872, 0, 0x5876, 0x5875, 0x5877, 0x5874, -}; -static const unsigned short utf8_to_euc_E687_x0213[] = { - 0xBE70, 0xBE71, 0xBE72, 0x5869, 0, 0, 0x586A, 0x3A29, - 0x5868, 0x5866, 0x5865, 0x586C, 0x5864, 0x586E, 0xBE73, 0xBE74, - 0x327B, 0, 0, 0, 0, 0xAC6E, 0, 0, - 0, 0, 0, 0, 0xBE76, 0xAC6F, 0xBE78, 0xAC70, - 0, 0xBE7A, 0xBE7B, 0x5870, 0, 0xBE7E, 0x586F, 0xBE7C, - 0, 0xBE7D, 0, 0, 0xBF21, 0xBF22, 0, 0xBF23, - 0, 0, 0x4428, 0, 0x5873, 0xAC71, 0x5871, 0x5867, - 0x377C, 0, 0x5872, 0, 0x5876, 0x5875, 0x5877, 0x5874, -}; -static const unsigned short utf8_to_euc_E688[] = { - 0x5878, 0xBF24, 0, 0xBF25, 0xBF26, 0, 0, 0xBF27, - 0x5879, 0x587A, 0x4A6A, 0, 0x587C, 0x587B, 0x3D3F, 0, - 0x402E, 0x3266, 0x327C, 0xBF28, 0x587D, 0xBF29, 0x303F, 0, - 0, 0, 0x404C, 0x587E, 0xBF2A, 0x6C43, 0x5921, 0x3761, - 0xBF2B, 0x5922, 0xBF2C, 0xBF2D, 0, 0, 0x406F, 0xBF2E, - 0, 0xBF2F, 0x5923, 0xBF30, 0, 0, 0x5924, 0x353A, - 0x5925, 0, 0x5926, 0x5927, 0x4257, 0, 0, 0, - 0x384D, 0xBF31, 0, 0x4C61, 0, 0xBF32, 0, 0x4B3C, -}; -static const unsigned short utf8_to_euc_E688_x0213[] = { - 0x5878, 0xBF24, 0, 0xBF25, 0xBF26, 0, 0, 0xBF27, - 0x5879, 0x587A, 0x4A6A, 0, 0x587C, 0x587B, 0x3D3F, 0, - 0x402E, 0x3266, 0x327C, 0, 0x587D, 0xAC73, 0x303F, 0, - 0, 0, 0x404C, 0x587E, 0xBF2A, 0x6C43, 0x5921, 0x3761, - 0xBF2B, 0x5922, 0x7462, 0xAC74, 0, 0, 0x406F, 0xBF2E, - 0, 0xAC75, 0x5923, 0xBF30, 0, 0, 0x5924, 0x353A, - 0x5925, 0, 0x5926, 0x5927, 0x4257, 0, 0, 0, - 0x384D, 0xBF31, 0, 0x4C61, 0, 0xBF32, 0x7463, 0x4B3C, -}; -static const unsigned short utf8_to_euc_E689[] = { - 0x3D6A, 0x5928, 0xBF33, 0xBF34, 0xBF35, 0, 0xBF36, 0x4070, - 0x6E3D, 0x4862, 0, 0x3C6A, 0xBF37, 0x3A4D, 0x5929, 0, - 0xBF38, 0xBF39, 0xBF3A, 0x4247, 0xBF3B, 0x4A27, 0xBF3C, 0, - 0x4271, 0, 0xBF3D, 0x592C, 0xBF3E, 0, 0x592A, 0, - 0x592D, 0, 0, 0x592B, 0xBF3F, 0, 0, 0, - 0x592E, 0, 0, 0, 0, 0xBF40, 0x4A31, 0xBF41, - 0, 0x3037, 0, 0xBF42, 0, 0, 0x495E, 0, - 0, 0x4863, 0xBF43, 0, 0x592F, 0xBF44, 0x5932, 0x3E35, -}; -static const unsigned short utf8_to_euc_E689_x0213[] = { - 0x3D6A, 0x5928, 0xBF33, 0x7464, 0xBF35, 0, 0xAC76, 0x4070, - 0x6E3D, 0x4862, 0, 0x3C6A, 0xAC77, 0x3A4D, 0x5929, 0, - 0xBF38, 0xAC78, 0xAC79, 0x4247, 0xBF3B, 0x4A27, 0x7465, 0, - 0x4271, 0, 0x7466, 0x592C, 0xBF3E, 0, 0x592A, 0, - 0x592D, 0xAC7A, 0, 0x592B, 0xAC7B, 0, 0, 0, - 0x592E, 0, 0, 0, 0, 0xAC7D, 0x4A31, 0x7467, - 0, 0x3037, 0, 0xAC7E, 0, 0, 0x495E, 0, - 0, 0x4863, 0xBF43, 0xAC7C, 0x592F, 0xBF44, 0x5932, 0x3E35, -}; -static const unsigned short utf8_to_euc_E68A[] = { - 0x353B, 0, 0x5930, 0x5937, 0x3E36, 0, 0, 0, - 0, 0x5931, 0x4744, 0, 0, 0xBF45, 0xBF46, 0xBF47, - 0xBF48, 0x4D5E, 0x5933, 0x5934, 0x5938, 0x456A, 0x5935, 0x3933, - 0x405E, 0, 0, 0x5946, 0x4834, 0, 0x4272, 0, - 0, 0, 0, 0, 0, 0, 0xBF49, 0, - 0xBF4A, 0, 0, 0x4864, 0x5A2D, 0, 0, 0, - 0, 0x4A7A, 0, 0xBF4B, 0, 0x4471, 0xBF4C, 0xBF4D, - 0, 0x4B75, 0xBF4E, 0x593B, 0x3221, 0x436A, 0xBF4F, 0xBF50, -}; -static const unsigned short utf8_to_euc_E68A_x0213[] = { - 0x353B, 0, 0x5930, 0x5937, 0x3E36, 0x7468, 0, 0, - 0, 0x5931, 0x4744, 0, 0, 0xBF45, 0xBF46, 0xBF47, - 0xBF48, 0x4D5E, 0x5933, 0x5934, 0x5938, 0x456A, 0x5935, 0x3933, - 0x405E, 0xAD21, 0, 0x5946, 0x4834, 0, 0x4272, 0, - 0, 0, 0, 0, 0, 0, 0xAD22, 0, - 0xBF4A, 0, 0, 0x4864, 0x5A2D, 0, 0, 0, - 0, 0x4A7A, 0, 0xBF4B, 0, 0x4471, 0xBF4C, 0xBF4D, - 0, 0x4B75, 0xBF4E, 0x593B, 0x3221, 0x436A, 0xBF4F, 0xBF50, -}; -static const unsigned short utf8_to_euc_E68B[] = { - 0, 0, 0x5944, 0, 0xBF51, 0x4334, 0x593E, 0x5945, - 0x5940, 0x5947, 0x5943, 0, 0x5942, 0x476F, 0xBF52, 0x593C, - 0x327D, 0x593A, 0x3571, 0x4273, 0x5936, 0xBF53, 0xBF54, 0x5939, - 0x3934, 0x405B, 0xBF55, 0x3E37, 0x5941, 0x4752, 0, 0, - 0x3572, 0x3348, 0, 0, 0, 0, 0, 0, - 0, 0, 0xBF56, 0, 0x3367, 0x3F21, 0x5949, 0x594E, - 0, 0x594A, 0xBF57, 0x377D, 0xBF58, 0x594F, 0x3B22, 0x3969, - 0, 0, 0, 0, 0xBF59, 0xBF5A, 0x3D26, 0x593D, -}; -static const unsigned short utf8_to_euc_E68B_x0213[] = { - 0, 0, 0x5944, 0, 0x7469, 0x4334, 0x593E, 0x5945, - 0x5940, 0x5947, 0x5943, 0, 0x5942, 0x476F, 0xBF52, 0x593C, - 0x327D, 0x593A, 0x3571, 0x4273, 0x5936, 0xAD23, 0x746A, 0x5939, - 0x3934, 0x405B, 0xBF55, 0x3E37, 0x5941, 0x4752, 0, 0, - 0x3572, 0x3348, 0, 0, 0, 0, 0, 0, - 0, 0, 0xBF56, 0, 0x3367, 0x3F21, 0x5949, 0x594E, - 0, 0x594A, 0xBF57, 0x377D, 0xBF58, 0x594F, 0x3B22, 0x3969, - 0, 0, 0, 0, 0x746B, 0xAD25, 0x3D26, 0x593D, -}; -static const unsigned short utf8_to_euc_E68C[] = { - 0, 0x3B7D, 0x594C, 0xBF5B, 0xBF5C, 0, 0, 0x3B58, - 0x594D, 0x3044, 0xBF5D, 0xBF5E, 0x5948, 0xBF5F, 0, 0, - 0xBF60, 0x4429, 0, 0xBF61, 0, 0, 0xBF62, 0, - 0xBF63, 0x3573, 0, 0, 0, 0, 0, 0x3634, - 0, 0, 0, 0, 0, 0, 0, 0x594B, - 0x3027, 0xBF64, 0xBF65, 0x3A43, 0, 0xBF66, 0, 0x3F36, - 0, 0, 0, 0, 0, 0xBF67, 0xBF68, 0, - 0, 0xBF69, 0x4472, 0, 0xBF6A, 0x4854, 0x5951, 0x415E, -}; -static const unsigned short utf8_to_euc_E68C_x0213[] = { - 0, 0x3B7D, 0x594C, 0xAD26, 0xBF5C, 0, 0, 0x3B58, - 0x594D, 0x3044, 0x746C, 0xBF5E, 0x5948, 0xAD27, 0, 0, - 0xAD28, 0x4429, 0, 0xBF61, 0, 0, 0xBF62, 0, - 0x746D, 0x3573, 0, 0, 0, 0, 0, 0x3634, - 0, 0, 0, 0, 0, 0, 0, 0x594B, - 0x3027, 0xBF64, 0xBF65, 0x3A43, 0, 0xBF66, 0, 0x3F36, - 0, 0, 0xAD2B, 0, 0, 0xAD2C, 0xBF68, 0, - 0, 0x746E, 0x4472, 0xAD2D, 0xAD2E, 0x4854, 0x5951, 0x415E, -}; -static const unsigned short utf8_to_euc_E68D[] = { - 0, 0xBF6B, 0xBF6C, 0xBF6D, 0xBF6E, 0, 0xBF6F, 0, - 0, 0x422A, 0xBF70, 0xBF71, 0x3B2B, 0x5952, 0xBF72, 0x5954, - 0x5950, 0, 0xBF73, 0xBF74, 0xBF75, 0x4A61, 0, 0x443D, - 0xBF76, 0, 0, 0xBF77, 0x415C, 0, 0, 0, - 0, 0, 0, 0, 0, 0xBF78, 0xBF79, 0x4A7B, - 0x3C4E, 0x5960, 0, 0x595F, 0xBF7A, 0xBF7B, 0x3F78, 0, - 0, 0xBF7C, 0x377E, 0, 0xBF7D, 0xBF7E, 0x5959, 0x3E39, - 0xC021, 0, 0x4668, 0x4731, 0xC022, 0xC023, 0, 0xC024, -}; -static const unsigned short utf8_to_euc_E68D_x0213[] = { - 0, 0xAD2F, 0xBF6C, 0x746F, 0xAD30, 0, 0xBF6F, 0, - 0, 0x422A, 0xBF70, 0xBF71, 0x3B2B, 0x5952, 0xAD31, 0x5954, - 0x5950, 0, 0xBF73, 0xBF74, 0xBF75, 0x4A61, 0, 0x443D, - 0xBF76, 0xAD33, 0, 0xBF77, 0x415C, 0, 0, 0, - 0, 0, 0, 0, 0, 0x7470, 0xBF79, 0x4A7B, - 0x3C4E, 0x5960, 0, 0x595F, 0xAD36, 0xBF7B, 0x3F78, 0, - 0, 0xBF7C, 0x377E, 0, 0xBF7D, 0xBF7E, 0x5959, 0x3E39, - 0xC021, 0, 0x4668, 0x4731, 0x7471, 0xC023, 0, 0xC024, -}; -static const unsigned short utf8_to_euc_E68E[] = { - 0x5957, 0, 0xC025, 0x415D, 0xC026, 0, 0, 0xC027, - 0x3C78, 0x595C, 0xC028, 0, 0x3E38, 0, 0x5956, 0x595B, - 0xC029, 0, 0x4753, 0, 0xC02A, 0xC02B, 0x5955, 0, - 0x3721, 0xC02C, 0xC02D, 0x335D, 0, 0, 0xC02E, 0x595D, - 0x4E2B, 0x3A4E, 0x4335, 0x595A, 0xC02F, 0x405C, 0xC030, 0x3935, - 0x3F64, 0x3166, 0x413C, 0x5958, 0x3545, 0xC031, 0xC032, 0xC033, - 0, 0, 0x3747, 0, 0x444F, 0x595E, 0, 0, - 0, 0, 0, 0x415F, 0, 0xC034, 0x5961, 0, -}; -static const unsigned short utf8_to_euc_E68E_x0213[] = { - 0x5957, 0, 0xC025, 0x415D, 0xAD37, 0, 0, 0xC027, - 0x3C78, 0x595C, 0xC028, 0, 0x3E38, 0, 0x5956, 0x595B, - 0xC029, 0, 0x4753, 0, 0xAD3A, 0xC02B, 0x5955, 0, - 0x3721, 0xAD38, 0xC02D, 0x335D, 0, 0, 0xC02E, 0x595D, - 0x4E2B, 0x3A4E, 0x4335, 0x595A, 0xC02F, 0x405C, 0xC030, 0x3935, - 0x3F64, 0x3166, 0x413C, 0x5958, 0x3545, 0xC031, 0xC032, 0xC033, - 0, 0, 0x3747, 0, 0x444F, 0x595E, 0, 0, - 0, 0, 0, 0x415F, 0, 0xAD3B, 0x5961, 0, -}; -static const unsigned short utf8_to_euc_E68F[] = { - 0x5963, 0xC035, 0, 0x4237, 0x5969, 0xC036, 0x5964, 0, - 0xC037, 0x5966, 0, 0, 0, 0, 0xC038, 0x4941, - 0x4473, 0xC039, 0x5967, 0xC03A, 0xC03B, 0xC03C, 0x4D2C, 0, - 0, 0, 0x4D48, 0x3439, 0xC03D, 0, 0, 0, - 0xC03E, 0x302E, 0, 0x5965, 0, 0xC03F, 0, 0, - 0, 0x5962, 0xC040, 0, 0xC041, 0, 0x3478, 0, - 0, 0, 0xC042, 0xC043, 0x3167, 0xC044, 0x5968, 0, - 0xC045, 0xC046, 0x4D49, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E68F_x0213[] = { - 0x5963, 0xC035, 0, 0x4237, 0x5969, 0xC036, 0x5964, 0, - 0xC037, 0x5966, 0, 0, 0, 0, 0xC038, 0x4941, - 0x4473, 0xC039, 0x5967, 0xC03A, 0xAD3D, 0xAD3E, 0x4D2C, 0, - 0, 0, 0x4D48, 0x3439, 0xAD3F, 0, 0, 0, - 0xAD40, 0x302E, 0, 0x5965, 0, 0x7472, 0, 0, - 0, 0x5962, 0xC040, 0xAD41, 0xAD42, 0x7473, 0x3478, 0, - 0, 0, 0xAD43, 0xC043, 0x3167, 0x7474, 0x5968, 0xAD3C, - 0xC045, 0xC046, 0x4D49, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E690[] = { - 0, 0, 0, 0, 0, 0, 0x596C, 0, - 0, 0xC047, 0xC048, 0, 0, 0x423B, 0, 0x5973, - 0xC049, 0, 0xC04A, 0x596D, 0xC04B, 0, 0x596A, 0x5971, - 0xC04C, 0, 0, 0, 0x5953, 0, 0xC04D, 0, - 0xC04E, 0, 0xC04F, 0, 0xC050, 0xC051, 0x596E, 0, - 0x5972, 0xC052, 0xC053, 0, 0x4842, 0x456B, 0, 0xC054, - 0xC055, 0, 0, 0, 0x596B, 0xC056, 0x596F, 0, - 0, 0, 0x3748, 0, 0, 0xC057, 0x3A71, 0xC058, -}; -static const unsigned short utf8_to_euc_E690_x0213[] = { - 0, 0, 0, 0, 0, 0, 0x596C, 0, - 0, 0xAD44, 0xC048, 0, 0, 0x423B, 0, 0x5973, - 0x7475, 0, 0xC04A, 0x596D, 0x7476, 0, 0x596A, 0x5971, - 0xC04C, 0, 0, 0, 0x5953, 0, 0xAD45, 0, - 0xC04E, 0, 0x7477, 0, 0xC050, 0xAD46, 0x596E, 0, - 0x5972, 0xAD47, 0xC053, 0, 0x4842, 0x456B, 0, 0xAD48, - 0xC055, 0, 0, 0, 0x596B, 0xC056, 0x596F, 0, - 0, 0, 0x3748, 0, 0, 0xC057, 0x3A71, 0xC058, -}; -static const unsigned short utf8_to_euc_E691[] = { - 0, 0, 0x405D, 0, 0, 0, 0, 0, - 0, 0, 0, 0xC059, 0, 0, 0x5977, 0xC05A, - 0, 0xC05B, 0xC05C, 0xC05D, 0xC05E, 0, 0, 0, - 0x4526, 0, 0xC05F, 0xC060, 0xC061, 0xC062, 0, 0xC063, - 0xC064, 0xC065, 0, 0xC066, 0, 0, 0, 0x5974, - 0, 0x4B60, 0, 0, 0, 0xC067, 0, 0x5975, - 0, 0, 0, 0xC068, 0xC069, 0, 0x5976, 0, - 0x4C4E, 0, 0x4022, 0xC06A, 0, 0xC06B, 0, 0, -}; -static const unsigned short utf8_to_euc_E691_x0213[] = { - 0, 0, 0x405D, 0, 0, 0, 0, 0, - 0, 0, 0, 0xC059, 0, 0, 0x5977, 0xC05A, - 0, 0x7479, 0xC05C, 0xC05D, 0xC05E, 0, 0, 0, - 0x4526, 0, 0xAD49, 0xAD4A, 0xC061, 0xAD4B, 0, 0xC063, - 0x747A, 0xC065, 0, 0xC066, 0, 0, 0, 0x5974, - 0, 0x4B60, 0, 0, 0, 0x747B, 0, 0x5975, - 0, 0, 0, 0xAD4C, 0xC069, 0, 0x5976, 0, - 0x4C4E, 0x7478, 0x4022, 0xC06A, 0, 0xAD4D, 0, 0, -}; -static const unsigned short utf8_to_euc_E692[] = { - 0, 0, 0, 0x3762, 0, 0xC06C, 0, 0xC06D, - 0x597D, 0, 0, 0, 0, 0, 0, 0xC06E, - 0xC06F, 0xC070, 0x3B35, 0x597A, 0, 0x5979, 0, 0, - 0xC071, 0xC072, 0x4732, 0xC073, 0, 0xC074, 0x4635, 0xC075, - 0, 0xC076, 0, 0xC077, 0x4531, 0x597B, 0xC078, 0, - 0xC079, 0x597C, 0, 0x496F, 0xC07A, 0x4745, 0x3B23, 0, - 0x4071, 0, 0x4B50, 0xC07B, 0, 0, 0, 0, - 0, 0x3349, 0, 0x5A25, 0x597E, 0xC07C, 0xC07D, 0xC07E, -}; -static const unsigned short utf8_to_euc_E692_x0213[] = { - 0, 0, 0, 0x3762, 0, 0xC06C, 0, 0xAD4E, - 0x597D, 0, 0, 0, 0, 0, 0, 0xC06E, - 0xC06F, 0xAD4F, 0x3B35, 0x597A, 0, 0x5979, 0, 0, - 0xC071, 0xC072, 0x4732, 0xC073, 0, 0xAD50, 0x4635, 0xAD51, - 0, 0xC076, 0, 0xC077, 0x4531, 0x597B, 0xC078, 0, - 0xC079, 0x597C, 0, 0x496F, 0xC07A, 0x4745, 0x3B23, 0, - 0x4071, 0, 0x4B50, 0xC07B, 0, 0, 0, 0, - 0, 0x3349, 0, 0x5A25, 0x597E, 0xC07C, 0x747D, 0x747E, -}; -static const unsigned short utf8_to_euc_E693[] = { - 0, 0x4D4A, 0x5A27, 0, 0xC121, 0x5A23, 0, 0x5A24, - 0, 0xC122, 0xC123, 0xC124, 0xC125, 0x4160, 0xC126, 0, - 0xC127, 0xC128, 0x5A22, 0, 0x593F, 0xC129, 0, 0xC12A, - 0x5A26, 0, 0x5A21, 0, 0, 0, 0, 0, - 0x5A2B, 0x5A2C, 0x4527, 0x5A2E, 0xC12B, 0xC12C, 0x3B24, 0x5A29, - 0, 0xC12D, 0xC12E, 0, 0x353C, 0xC12F, 0, 0x5A2F, - 0xC130, 0x5A28, 0x5A33, 0, 0x5A32, 0xC131, 0x5A31, 0xC132, - 0, 0, 0x5A34, 0xC133, 0, 0x5A36, 0x3E71, 0xC134, -}; -static const unsigned short utf8_to_euc_E693_x0213[] = { - 0, 0x4D4A, 0x5A27, 0, 0x7521, 0x5A23, 0, 0x5A24, - 0, 0xC122, 0x7522, 0xAD52, 0xAD53, 0x4160, 0x747C, 0, - 0x7523, 0xC128, 0x5A22, 0, 0x593F, 0xAD54, 0, 0xAD55, - 0x5A26, 0, 0x5A21, 0, 0, 0, 0, 0, - 0x5A2B, 0x5A2C, 0x4527, 0x5A2E, 0xAD57, 0xAD58, 0x3B24, 0x5A29, - 0, 0xC12D, 0xC12E, 0, 0x353C, 0xC12F, 0, 0x5A2F, - 0xC130, 0x5A28, 0x5A33, 0, 0x5A32, 0xC131, 0x5A31, 0x7524, - 0, 0, 0x5A34, 0x7525, 0, 0x5A36, 0x3E71, 0xAD59, -}; -static const unsigned short utf8_to_euc_E694[] = { - 0x5A35, 0xC135, 0, 0, 0xC136, 0x5A39, 0, 0, - 0xC137, 0xC138, 0xC139, 0, 0, 0, 0, 0xC13A, - 0, 0, 0, 0xC13B, 0xC13C, 0, 0xC13D, 0, - 0x5A37, 0xC13E, 0, 0xC13F, 0x5A38, 0x5970, 0xC140, 0xC141, - 0, 0, 0xC142, 0x5A3B, 0x5A3A, 0, 0xC143, 0, - 0, 0xC144, 0x5978, 0x5A3C, 0x5A30, 0, 0xC145, 0x3B59, - 0, 0xC146, 0, 0, 0x5A3D, 0x5A3E, 0x5A40, 0x5A3F, - 0x5A41, 0x327E, 0xC147, 0x3936, 0xC148, 0xC149, 0x4A7C, 0x402F, -}; -static const unsigned short utf8_to_euc_E694_x0213[] = { - 0x5A35, 0xC135, 0, 0, 0xAD5A, 0x5A39, 0, 0, - 0xC137, 0xC138, 0xC139, 0, 0, 0, 0, 0xAD5C, - 0, 0, 0, 0xC13B, 0xAD5D, 0, 0xAD5E, 0, - 0x5A37, 0xC13E, 0, 0xC13F, 0x5A38, 0x5970, 0xAD60, 0xC141, - 0, 0, 0x7526, 0x5A3B, 0x5A3A, 0, 0xC143, 0, - 0, 0x7527, 0x5978, 0x5A3C, 0x5A30, 0, 0xC145, 0x3B59, - 0, 0xC146, 0xAD61, 0, 0x5A3D, 0x5A3E, 0x5A40, 0x5A3F, - 0x5A41, 0x327E, 0xC147, 0x3936, 0xC148, 0xC149, 0x4A7C, 0x402F, -}; -static const unsigned short utf8_to_euc_E695[] = { - 0, 0, 0, 0xC14A, 0, 0x384E, 0, 0xC14B, - 0x5A43, 0xC14C, 0, 0, 0, 0x5A46, 0xF441, 0x4952, - 0xC14D, 0x355F, 0xC14E, 0, 0xC14F, 0x5A45, 0x5A44, 0x4754, - 0x5A47, 0x3635, 0, 0, 0, 0x5A49, 0x5A48, 0xC150, - 0xC151, 0, 0x343A, 0x3B36, 0, 0, 0x4658, 0xC152, - 0, 0, 0, 0xC153, 0x3749, 0, 0, 0, - 0x3F74, 0, 0x5A4A, 0, 0x4030, 0x4528, 0, 0x495F, - 0x5A4B, 0, 0xC154, 0, 0, 0xC155, 0, 0, -}; -static const unsigned short utf8_to_euc_E695_x0213[] = { - 0, 0, 0, 0xC14A, 0xAD62, 0x384E, 0, 0xC14B, - 0x5A43, 0xC14C, 0, 0, 0, 0x5A46, 0, 0x4952, - 0xC14D, 0x355F, 0xC14E, 0, 0xAD63, 0x5A45, 0x5A44, 0x4754, - 0x5A47, 0x3635, 0, 0, 0, 0x5A49, 0x5A48, 0xC150, - 0xC151, 0, 0x343A, 0x3B36, 0, 0, 0x4658, 0x7529, - 0, 0, 0, 0xAD64, 0x3749, 0, 0, 0, - 0x3F74, 0, 0x5A4A, 0, 0x4030, 0x4528, 0, 0x495F, - 0x5A4B, 0, 0xAD65, 0, 0, 0xC155, 0, 0, -}; -static const unsigned short utf8_to_euc_E696[] = { - 0, 0xC156, 0x5A4C, 0x5A4D, 0, 0xC157, 0, 0x4A38, - 0x555D, 0x4046, 0xC158, 0, 0x494C, 0, 0x3A58, 0, - 0x4865, 0x4843, 0xC159, 0, 0, 0xC15A, 0, 0x454D, - 0xC15B, 0x4E41, 0, 0x5A4F, 0x3C50, 0xC15C, 0, 0x5A50, - 0xC15D, 0x3036, 0, 0xC15E, 0x3654, 0x404D, 0xC15F, 0x4960, - 0, 0, 0, 0x5A51, 0x3B42, 0x4347, 0xC160, 0x3B5B, - 0x3F37, 0, 0xC161, 0xC162, 0xC163, 0, 0, 0x5A52, - 0, 0x4A7D, 0, 0, 0x3177, 0x3B5C, 0, 0xC164, -}; -static const unsigned short utf8_to_euc_E696_x0213[] = { - 0, 0xAD66, 0x5A4C, 0x5A4D, 0xAD67, 0xAD68, 0, 0x4A38, - 0x555D, 0x4046, 0xAD69, 0, 0x494C, 0, 0x3A58, 0, - 0x4865, 0x4843, 0xC159, 0, 0, 0xC15A, 0, 0x454D, - 0xC15B, 0x4E41, 0, 0x5A4F, 0x3C50, 0x752A, 0, 0x5A50, - 0xC15D, 0x3036, 0, 0xC15E, 0x3654, 0x404D, 0xC15F, 0x4960, - 0, 0, 0, 0x5A51, 0x3B42, 0x4347, 0xC160, 0x3B5B, - 0x3F37, 0, 0xAD6A, 0xC162, 0xC163, 0xAD6B, 0, 0x5A52, - 0xAD6C, 0x4A7D, 0, 0, 0x3177, 0x3B5C, 0, 0xAD6D, -}; -static const unsigned short utf8_to_euc_E697[] = { - 0, 0x5A55, 0xC165, 0x5A53, 0x5A56, 0x4E39, 0x5A54, 0, - 0xC166, 0xC167, 0, 0x407B, 0x5A57, 0, 0xC168, 0x4232, - 0xC169, 0, 0x5A58, 0, 0xC16A, 0, 0xC16B, 0x347A, - 0xC16C, 0x5A5A, 0, 0x5A59, 0, 0, 0, 0xC16D, - 0x5A5B, 0x5A5C, 0x347B, 0, 0, 0x467C, 0x4336, 0x356C, - 0x3B5D, 0x4161, 0, 0, 0x3D5C, 0x3030, 0, 0, - 0xC16E, 0x5A5D, 0xC16F, 0, 0xC170, 0xC171, 0, 0, - 0, 0xC172, 0x3222, 0x5A61, 0, 0, 0xC173, 0xC174, -}; -static const unsigned short utf8_to_euc_E697_x0213[] = { - 0, 0x5A55, 0xAD6E, 0x5A53, 0x5A56, 0x4E39, 0x5A54, 0, - 0xC166, 0xAD6F, 0, 0x407B, 0x5A57, 0, 0xC168, 0x4232, - 0xC169, 0, 0x5A58, 0, 0xAD70, 0, 0xC16B, 0x347A, - 0xC16C, 0x5A5A, 0, 0x5A59, 0, 0, 0, 0xC16D, - 0x5A5B, 0x5A5C, 0x347B, 0, 0, 0x467C, 0x4336, 0x356C, - 0x3B5D, 0x4161, 0, 0, 0x3D5C, 0x3030, 0, 0, - 0xC16E, 0x5A5D, 0xAD72, 0, 0xC170, 0xC171, 0, 0, - 0, 0xAD73, 0x3222, 0x5A61, 0xAD74, 0, 0xC173, 0xC174, -}; -static const unsigned short utf8_to_euc_E698[] = { - 0xC175, 0, 0x3937, 0x5A60, 0xC176, 0, 0x3A2B, 0x3E3A, - 0xC177, 0xC178, 0x5A5F, 0, 0x3E3B, 0xC179, 0x4C40, 0x3A2A, - 0, 0xC17A, 0xC17B, 0x3057, 0x404E, 0xC17C, 0xC17D, 0, - 0, 0, 0, 0, 0x5A66, 0xC17E, 0xC221, 0x4031, - 0x3147, 0xC222, 0xC223, 0xC224, 0xC225, 0x3D55, 0xC226, 0x4B66, - 0x3A72, 0xC227, 0xC228, 0xC229, 0xC22A, 0x3E3C, 0xC22B, 0x4027, - 0xC22C, 0xC22D, 0, 0xC22E, 0x5A65, 0x5A63, 0x5A64, 0xC230, - 0, 0xC22F, 0, 0xF442, 0x436B, 0, 0, 0x5B26, -}; -static const unsigned short utf8_to_euc_E698_x0213[] = { - 0x752C, 0, 0x3937, 0x5A60, 0xAD75, 0, 0x3A2B, 0x3E3A, - 0xAD76, 0x752D, 0x5A5F, 0, 0x3E3B, 0xC179, 0x4C40, 0x3A2A, - 0, 0xC17A, 0xC17B, 0x3057, 0x404E, 0x752E, 0xC17D, 0, - 0, 0, 0, 0, 0x5A66, 0xC17E, 0x752F, 0x4031, - 0x3147, 0xAD77, 0x7531, 0xC224, 0x7532, 0x3D55, 0xC226, 0x4B66, - 0x3A72, 0xC227, 0xAD78, 0x7533, 0xC22A, 0x3E3C, 0, 0x4027, - 0x7534, 0x7535, 0, 0x7536, 0x5A65, 0x5A63, 0x5A64, 0xC230, - 0, 0xC22F, 0x7530, 0, 0x436B, 0, 0, 0x5B26, -}; -static const unsigned short utf8_to_euc_E699[] = { - 0xC231, 0x5A6A, 0x3B7E, 0x3938, 0x5A68, 0xC232, 0xC233, 0, - 0, 0x5A69, 0xC234, 0x3F38, 0xC235, 0, 0xC237, 0x5A67, - 0, 0xC236, 0x3B2F, 0, 0, 0, 0, 0xC238, - 0xC239, 0xC23A, 0, 0xC23B, 0xC23C, 0x5A6C, 0x5A6B, 0x5A70, - 0xC23D, 0xC23E, 0x5A71, 0, 0x5A6D, 0xF443, 0x3322, 0x5A6E, - 0x5A6F, 0x4855, 0xC240, 0xC241, 0xC242, 0, 0x4961, 0x374A, - 0x5A72, 0, 0, 0xC244, 0x4032, 0xC245, 0x3E3D, 0xC247, - 0xC248, 0xC249, 0x4352, 0xC24A, 0xC24C, 0, 0xC243, 0xC246, -}; -static const unsigned short utf8_to_euc_E699_x0213[] = { - 0xC231, 0x5A6A, 0x3B7E, 0x3938, 0x5A68, 0xAD79, 0xC233, 0, - 0x7538, 0x5A69, 0xC234, 0x3F38, 0x7539, 0, 0xAD7B, 0x5A67, - 0, 0xAD7A, 0x3B2F, 0, 0, 0, 0, 0xAD7E, - 0xC239, 0x753B, 0x753C, 0xAE21, 0xC23C, 0x5A6C, 0x5A6B, 0x5A70, - 0xC23D, 0x753D, 0x5A71, 0xAE22, 0x5A6D, 0x753E, 0x3322, 0x5A6E, - 0x5A6F, 0x4855, 0xAE25, 0xAE26, 0xAE27, 0xAE28, 0x4961, 0x374A, - 0x5A72, 0, 0, 0x753F, 0x4032, 0xC245, 0x3E3D, 0x7540, - 0x7541, 0xC249, 0x4352, 0xAE29, 0xC24C, 0, 0xC243, 0xC246, -}; -static const unsigned short utf8_to_euc_E69A[] = { - 0xC24B, 0x3647, 0, 0x5A73, 0x5A77, 0, 0, 0x324B, - 0x5A74, 0x5A76, 0, 0xC24D, 0xC24E, 0xC24F, 0x5A75, 0, - 0xC250, 0x3D6B, 0xC251, 0, 0, 0, 0x4348, 0x3045, - 0x5A78, 0xC252, 0xC253, 0xC254, 0xC255, 0x5A79, 0, 0xC256, - 0xC257, 0, 0x442A, 0, 0xC258, 0, 0x4E71, 0, - 0, 0, 0, 0x3B43, 0, 0xC259, 0x4A6B, 0, - 0, 0xC25A, 0xC25B, 0, 0x4B3D, 0xC25C, 0, 0, - 0x5B22, 0x5A7B, 0, 0xC25D, 0x5A7E, 0, 0x5A7D, 0xC25E, -}; -static const unsigned short utf8_to_euc_E69A_x0213[] = { - 0xAE2A, 0x3647, 0, 0x5A73, 0x5A77, 0, 0, 0x324B, - 0x5A74, 0x5A76, 0, 0xC24D, 0xC24E, 0x7542, 0x5A75, 0, - 0xAE2B, 0x3D6B, 0xAE2C, 0, 0, 0, 0x4348, 0x3045, - 0x5A78, 0xAE2D, 0xC253, 0xC254, 0xC255, 0x5A79, 0, 0xC256, - 0x7544, 0, 0x442A, 0, 0xC258, 0, 0x4E71, 0, - 0, 0, 0, 0x3B43, 0, 0xAE2F, 0x4A6B, 0, - 0, 0xAE30, 0x7545, 0, 0x4B3D, 0xAE31, 0, 0, - 0x5B22, 0x5A7B, 0, 0x7546, 0x5A7E, 0, 0x5A7D, 0xAE33, -}; -static const unsigned short utf8_to_euc_E69B[] = { - 0xC25F, 0x5A7A, 0xC260, 0xC261, 0x5B21, 0, 0, 0x465E, - 0xC262, 0x5A7C, 0, 0, 0xC263, 0, 0xC264, 0xC265, - 0, 0, 0, 0, 0xC266, 0, 0x5B23, 0, - 0, 0x3D6C, 0x5B24, 0xC267, 0x4D4B, 0x4778, 0, 0xC268, - 0x5B25, 0, 0, 0, 0, 0, 0x5B27, 0, - 0xC269, 0x5B28, 0, 0xC26A, 0xC26B, 0, 0xC26C, 0, - 0x5B29, 0, 0x364A, 0x3148, 0x3939, 0x5B2A, 0, 0x5B2B, - 0x3D71, 0x4162, 0xC26D, 0xC23F, 0x5258, 0x413E, 0x413D, 0x4258, -}; -static const unsigned short utf8_to_euc_E69B_x0213[] = { - 0xC25F, 0x5A7A, 0xC260, 0xC261, 0x5B21, 0, 0x7547, 0x465E, - 0x7548, 0x5A7C, 0, 0, 0xC263, 0, 0xC264, 0xC265, - 0, 0, 0, 0, 0xC266, 0, 0x5B23, 0, - 0, 0x3D6C, 0x5B24, 0x754A, 0x4D4B, 0x4778, 0, 0xC268, - 0x5B25, 0, 0, 0, 0, 0, 0x5B27, 0, - 0x754B, 0x5B28, 0, 0xC26A, 0xAE35, 0, 0xC26C, 0, - 0x5B29, 0, 0x364A, 0x3148, 0x3939, 0x5B2A, 0, 0x5B2B, - 0x3D71, 0x4162, 0x754C, 0x7537, 0x5258, 0x413E, 0x413D, 0x4258, -}; -static const unsigned short utf8_to_euc_E69C[] = { - 0x3A47, 0, 0, 0x5072, 0, 0xC26E, 0, 0xC26F, - 0x376E, 0x4D2D, 0, 0x4A7E, 0, 0x497E, 0xC270, 0x5B2C, - 0, 0, 0, 0xC271, 0x3A73, 0x443F, 0x5B2D, 0x4F2F, - 0, 0xC272, 0, 0x4B3E, 0xC273, 0x442B, 0x5B2E, 0x347C, - 0xC274, 0, 0xC275, 0, 0, 0, 0x5B2F, 0x5B30, - 0x4C5A, 0, 0x4C24, 0x4B76, 0x4B5C, 0x3B25, 0x5B32, 0, - 0, 0x3C6B, 0, 0xC276, 0x4B51, 0, 0x5B34, 0x5B37, - 0x5B36, 0, 0x3479, 0, 0, 0x3560, 0xC277, 0x5B33, -}; -static const unsigned short utf8_to_euc_E69C_x0213[] = { - 0x3A47, 0xAE37, 0, 0x5072, 0, 0xAE38, 0, 0xC26F, - 0x376E, 0x4D2D, 0, 0x4A7E, 0, 0x497E, 0, 0x5B2C, - 0, 0, 0xAE39, 0x754D, 0x3A73, 0x443F, 0x5B2D, 0x4F2F, - 0, 0xAE3B, 0, 0x4B3E, 0xC273, 0x442B, 0x5B2E, 0x347C, - 0xC274, 0, 0xC275, 0, 0, 0, 0x5B2F, 0x5B30, - 0x4C5A, 0, 0x4C24, 0x4B76, 0x4B5C, 0x3B25, 0x5B32, 0, - 0, 0x3C6B, 0, 0x754F, 0x4B51, 0, 0x5B34, 0x5B37, - 0x5B36, 0, 0x3479, 0, 0, 0x3560, 0xC277, 0x5B33, -}; -static const unsigned short utf8_to_euc_E69D[] = { - 0, 0x5B35, 0, 0, 0, 0xC278, 0x5B38, 0xC279, - 0xC27A, 0x3F79, 0, 0, 0xC27B, 0, 0x4D7B, 0x3049, - 0x3A60, 0x423C, 0, 0x3C5D, 0xC27C, 0xC27D, 0x3E73, 0, - 0, 0x5B3B, 0, 0, 0x454E, 0xC27E, 0x5B39, 0x422B, - 0x5B3A, 0x3E72, 0x4C5D, 0x5B3C, 0x5B3D, 0x4D68, 0xC321, 0, - 0, 0, 0x5B42, 0, 0xC322, 0x393A, 0xC323, 0x4755, - 0x5B3F, 0x456C, 0x5A5E, 0x5A62, 0xC324, 0x354F, 0xC325, 0x4747, - 0, 0, 0, 0xC326, 0x5B41, 0, 0x3E3E, 0x4844, -}; -static const unsigned short utf8_to_euc_E69D_x0213[] = { - 0, 0x5B35, 0, 0, 0, 0xC278, 0x5B38, 0x7551, - 0x7552, 0x3F79, 0, 0, 0xAE3E, 0xAE3F, 0x4D7B, 0x3049, - 0x3A60, 0x423C, 0, 0x3C5D, 0xAE40, 0xC27D, 0x3E73, 0, - 0, 0x5B3B, 0, 0, 0x454E, 0xAE41, 0x5B39, 0x422B, - 0x5B3A, 0x3E72, 0x4C5D, 0x5B3C, 0x5B3D, 0x4D68, 0x7550, 0, - 0, 0, 0x5B42, 0, 0xC322, 0x393A, 0xC323, 0x4755, - 0x5B3F, 0x456C, 0x5A5E, 0x5A62, 0xAE45, 0x354F, 0xAE46, 0x4747, - 0, 0, 0, 0x7553, 0x5B41, 0, 0x3E3E, 0x4844, -}; -static const unsigned short utf8_to_euc_E69E[] = { - 0, 0xC327, 0, 0, 0xC328, 0x5B47, 0, 0x487A, - 0, 0x5B3E, 0, 0x5B44, 0x5B43, 0, 0xC329, 0xC32A, - 0x404F, 0xC32B, 0, 0xC32C, 0, 0x4B6D, 0xC32D, 0x4E53, - 0xC32E, 0xC32F, 0x4B67, 0xC330, 0x324C, 0x3B5E, 0, 0, - 0x4F48, 0x5B46, 0x3F75, 0, 0, 0, 0x5B45, 0, - 0, 0x5B40, 0, 0, 0, 0, 0, 0x384F, - 0xC331, 0xC332, 0xC333, 0x5B4C, 0x5B4A, 0xC334, 0x324D, 0x5B48, - 0x5B4E, 0x5B54, 0, 0xC335, 0xC336, 0xC337, 0, 0, -}; -static const unsigned short utf8_to_euc_E69E_x0213[] = { - 0, 0x7554, 0, 0, 0xC328, 0x5B47, 0, 0x487A, - 0, 0x5B3E, 0, 0x5B44, 0x5B43, 0, 0xC329, 0xC32A, - 0x404F, 0xC32B, 0xAE48, 0x7555, 0, 0x4B6D, 0xC32D, 0x4E53, - 0x7556, 0xC32F, 0x4B67, 0x7557, 0x324C, 0x3B5E, 0, 0, - 0x4F48, 0x5B46, 0x3F75, 0, 0, 0, 0x5B45, 0, - 0, 0x5B40, 0, 0, 0, 0, 0, 0x384F, - 0xAE4C, 0xC332, 0xAE4D, 0x5B4C, 0x5B4A, 0xC334, 0x324D, 0x5B48, - 0x5B4E, 0x5B54, 0, 0x7558, 0xC336, 0xC337, 0, 0, -}; -static const unsigned short utf8_to_euc_E69F[] = { - 0xC339, 0x4248, 0xC33A, 0xC33B, 0x4A41, 0xC33C, 0x5B56, 0, - 0xC33D, 0xC33E, 0x4922, 0, 0, 0, 0x5B55, 0x4770, - 0x4B3F, 0x343B, 0xC33F, 0x4077, 0x3D40, 0, 0, 0xC340, - 0x4453, 0xC341, 0x4D2E, 0, 0xC342, 0x5B51, 0x5B50, 0, - 0, 0xC343, 0x5B52, 0, 0x5B4F, 0, 0xC344, 0x5B57, - 0, 0x5B4D, 0, 0, 0x5B4B, 0, 0x5B53, 0x5B49, - 0xC345, 0x436C, 0xC346, 0x4C78, 0x3C46, 0x3A74, 0xC347, 0xC348, - 0, 0xC338, 0, 0x3A3A, 0, 0, 0x4B6F, 0x3341, -}; -static const unsigned short utf8_to_euc_E69F_x0213[] = { - 0x755A, 0x4248, 0xC33A, 0xAE4E, 0x4A41, 0xC33C, 0x5B56, 0, - 0xAE4F, 0xC33E, 0x4922, 0, 0, 0, 0x5B55, 0x4770, - 0x4B3F, 0x343B, 0xAE50, 0x4077, 0x3D40, 0, 0, 0x755B, - 0x4453, 0xAE51, 0x4D2E, 0xAE52, 0xC342, 0x5B51, 0x5B50, 0, - 0, 0xC343, 0x5B52, 0, 0x5B4F, 0, 0xC344, 0x5B57, - 0, 0x5B4D, 0, 0, 0x5B4B, 0, 0x5B53, 0x5B49, - 0xAE53, 0x436C, 0xC346, 0x4C78, 0x3C46, 0x3A74, 0xC347, 0xAE54, - 0, 0x7559, 0, 0x3A3A, 0x755C, 0, 0x4B6F, 0x3341, -}; -static const unsigned short utf8_to_euc_E6A0[] = { - 0, 0xF446, 0x444E, 0x464A, 0x3149, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x4072, 0xC34A, 0, 0x4034, 0x372A, - 0, 0xC34B, 0, 0, 0, 0xC34C, 0x5B59, 0xC34D, - 0, 0x393B, 0x337C, 0, 0, 0, 0, 0xC34F, - 0xC34E, 0x5B5B, 0x3374, 0x5B61, 0xC350, 0xC351, 0, 0xC352, - 0xC353, 0xC354, 0x5B5E, 0xC355, 0x4073, 0, 0, 0, - 0x334B, 0x3A2C, 0, 0xC356, 0x334A, 0x3A4F, 0, 0xC357, -}; -static const unsigned short utf8_to_euc_E6A0_x0213[] = { - 0, 0x755D, 0x444E, 0x464A, 0x3149, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xAE4B, 0, 0, 0x4072, 0xC34A, 0, 0x4034, 0x372A, - 0xAE58, 0xC34B, 0, 0, 0, 0x755F, 0x5B59, 0xAE59, - 0, 0x393B, 0x337C, 0, 0, 0, 0, 0xC34F, - 0xC34E, 0x5B5B, 0x3374, 0x5B61, 0x7560, 0xAE5A, 0, 0xC352, - 0xC353, 0x7561, 0x5B5E, 0xAE5C, 0x4073, 0, 0, 0, - 0x334B, 0x3A2C, 0, 0xAE5D, 0x334A, 0x3A4F, 0xAE5E, 0xC357, -}; -static const unsigned short utf8_to_euc_E6A1[] = { - 0x5B5C, 0x3765, 0x374B, 0x456D, 0xC358, 0xC359, 0x5B5A, 0, - 0x3046, 0, 0xC35A, 0, 0xC35B, 0x5B5D, 0x5B5F, 0, - 0x364D, 0x372C, 0xC349, 0x343C, 0x354B, 0xC35C, 0, 0xC35D, - 0xC35E, 0x5B62, 0, 0xC35F, 0x3A79, 0x4B71, 0, 0x3B37, - 0, 0, 0, 0x5B63, 0, 0, 0, 0x4930, - 0, 0, 0, 0xC360, 0, 0, 0xC361, 0xC362, - 0xC363, 0xC364, 0xC365, 0, 0x5B6F, 0xC366, 0x3233, 0x5B64, - 0, 0xC367, 0xC368, 0xC369, 0xC36A, 0, 0x5B75, 0x5B65, -}; -static const unsigned short utf8_to_euc_E6A1_x0213[] = { - 0x5B5C, 0x3765, 0x374B, 0x456D, 0xAE5F, 0xAE60, 0x5B5A, 0, - 0x3046, 0xAE61, 0xC35A, 0, 0xAE62, 0x5B5D, 0x5B5F, 0, - 0x364D, 0x372C, 0x755E, 0x343C, 0x354B, 0xAE63, 0, 0xAE64, - 0xC35E, 0x5B62, 0, 0x7562, 0x3A79, 0x4B71, 0, 0x3B37, - 0, 0, 0, 0x5B63, 0, 0, 0, 0x4930, - 0, 0, 0, 0xAE66, 0, 0, 0xAE67, 0xC362, - 0xC363, 0xC364, 0x7563, 0, 0x5B6F, 0x7564, 0x3233, 0x5B64, - 0, 0xC367, 0xAE68, 0xC369, 0xAE69, 0, 0x5B75, 0x5B65, -}; -static const unsigned short utf8_to_euc_E6A2[] = { - 0, 0x4E42, 0xC36B, 0x5B6C, 0xC36C, 0x475F, 0xC36D, 0, - 0xC36E, 0, 0, 0, 0, 0x5B74, 0, 0x5B67, - 0, 0, 0, 0x3034, 0x5B69, 0, 0xC36F, 0x393C, - 0xC370, 0, 0xC371, 0x5B6B, 0xC372, 0x5B6A, 0, 0x5B66, - 0x5B71, 0xC373, 0x3E3F, 0xC374, 0, 0xC375, 0x546D, 0x3868, - 0x4D7C, 0xC376, 0xC377, 0, 0, 0x5B68, 0xC378, 0x4474, - 0x3323, 0x3A2D, 0xC379, 0x5B60, 0, 0x5B70, 0x3361, 0, - 0, 0x5B6E, 0x5B72, 0xC37A, 0x456E, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E6A2_x0213[] = { - 0, 0x4E42, 0xAE6A, 0x5B6C, 0xC36C, 0x475F, 0xC36D, 0, - 0xC36E, 0, 0, 0, 0, 0x5B74, 0, 0x5B67, - 0xAE6B, 0, 0, 0x3034, 0x5B69, 0, 0xAE6C, 0x393C, - 0xAE6E, 0xAE6F, 0xAE70, 0x5B6B, 0xAE71, 0x5B6A, 0, 0x5B66, - 0x5B71, 0xC373, 0x3E3F, 0x7566, 0, 0x7567, 0x546D, 0x3868, - 0x4D7C, 0xC376, 0xAE72, 0xAE73, 0, 0x5B68, 0xC378, 0x4474, - 0x3323, 0x3A2D, 0x7568, 0x5B60, 0xAE74, 0x5B70, 0x3361, 0, - 0, 0x5B6E, 0x5B72, 0xAE75, 0x456E, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E6A3[] = { - 0, 0, 0, 0, 0x347E, 0xC37B, 0x5C32, 0, - 0xC37C, 0x4C49, 0x5B77, 0x347D, 0xC37D, 0x5B7E, 0, 0xC37E, - 0xC421, 0xC422, 0x4B40, 0xC423, 0x5C21, 0x5C23, 0xC424, 0x5C27, - 0x5B79, 0xC425, 0x432A, 0, 0xC426, 0xC427, 0, 0x456F, - 0x5C2B, 0x5B7C, 0, 0x5C28, 0, 0xC428, 0, 0x5C22, - 0xC429, 0, 0xC42A, 0xC42B, 0xC42C, 0xC42D, 0x3F39, 0x5C2C, - 0xC42E, 0xC42F, 0x4033, 0, 0, 0xC430, 0xC431, 0, - 0, 0x5C2A, 0x343D, 0xC432, 0xC433, 0xC434, 0, 0, -}; -static const unsigned short utf8_to_euc_E6A3_x0213[] = { - 0, 0, 0, 0xAE7A, 0x347E, 0xAE7B, 0x5C32, 0, - 0x7569, 0x4C49, 0x5B77, 0x347D, 0xAE7C, 0x5B7E, 0, 0xAE7D, - 0x756A, 0xC422, 0x4B40, 0xC423, 0x5C21, 0x5C23, 0xAE7E, 0x5C27, - 0x5B79, 0xAF21, 0x432A, 0, 0xC426, 0xC427, 0, 0x456F, - 0x5C2B, 0x5B7C, 0, 0x5C28, 0xAF22, 0xAF23, 0, 0x5C22, - 0x756B, 0, 0xC42A, 0xC42B, 0xAF24, 0x756C, 0x3F39, 0x5C2C, - 0x756D, 0x756E, 0x4033, 0, 0, 0xC430, 0xC431, 0xAF25, - 0, 0x5C2A, 0x343D, 0xAE76, 0x756F, 0xC434, 0, 0, -}; -static const unsigned short utf8_to_euc_E6A4[] = { - 0x4F50, 0x5B76, 0, 0, 0x5C26, 0x3058, 0xC435, 0, - 0x5B78, 0xC436, 0xC437, 0x4C3A, 0x5B7D, 0x3F22, 0x4447, 0x5B73, - 0xC438, 0xC439, 0x5C25, 0xC43A, 0, 0, 0xC43B, 0xC43C, - 0, 0x3F7A, 0x5C2F, 0x3371, 0x3821, 0, 0, 0, - 0, 0x5C31, 0x5B7A, 0x5C30, 0, 0x5C29, 0x5B7B, 0, - 0x5C2D, 0, 0x5C2E, 0, 0, 0, 0, 0, - 0x5C3F, 0xC43D, 0, 0xC43E, 0x464E, 0xC43F, 0x5C24, 0, - 0xC440, 0x5C3B, 0, 0xC441, 0, 0x5C3D, 0, 0x4458, -}; -static const unsigned short utf8_to_euc_E6A4_x0213[] = { - 0x4F50, 0x5B76, 0, 0xAF26, 0x5C26, 0x3058, 0xC435, 0xAF27, - 0x5B78, 0xC436, 0x7570, 0x4C3A, 0x5B7D, 0x3F22, 0x4447, 0x5B73, - 0xC438, 0xC439, 0x5C25, 0xC43A, 0, 0, 0xC43B, 0xC43C, - 0, 0x3F7A, 0x5C2F, 0x3371, 0x3821, 0, 0, 0, - 0, 0x5C31, 0x5B7A, 0x5C30, 0, 0x5C29, 0x5B7B, 0, - 0x5C2D, 0, 0x5C2E, 0, 0, 0, 0, 0, - 0x5C3F, 0xC43D, 0, 0xC43E, 0x464E, 0x7573, 0x5C24, 0, - 0xC440, 0x5C3B, 0, 0xAF2B, 0, 0x5C3D, 0, 0x4458, -}; -static const unsigned short utf8_to_euc_E6A5[] = { - 0, 0, 0xC442, 0, 0, 0xC443, 0, 0, - 0, 0xC444, 0x4D4C, 0, 0, 0, 0xC445, 0, - 0, 0, 0, 0x4976, 0x5C38, 0x424A, 0, 0xC446, - 0, 0x5C3E, 0x413F, 0xC447, 0x5C35, 0x5C42, 0x5C41, 0, - 0x466F, 0x5C40, 0x466A, 0xC448, 0xC449, 0xC44A, 0xC44B, 0, - 0xC44C, 0xC44D, 0x5C44, 0x5C37, 0xC44E, 0x3648, 0x5C3A, 0x3D5D, - 0xC44F, 0xC450, 0xC451, 0x4760, 0x5C3C, 0x364B, 0, 0x5C34, - 0x5C36, 0x5C33, 0xC452, 0xC453, 0x4F30, 0x335A, 0x5C39, 0xC454, -}; -static const unsigned short utf8_to_euc_E6A5_x0213[] = { - 0, 0, 0x7574, 0, 0, 0xC443, 0xAF2D, 0, - 0, 0x7571, 0x4D4C, 0, 0, 0, 0xC445, 0, - 0, 0, 0, 0x4976, 0x5C38, 0x424A, 0, 0x7575, - 0, 0x5C3E, 0x413F, 0xC447, 0x5C35, 0x5C42, 0x5C41, 0, - 0x466F, 0x5C40, 0x466A, 0x7576, 0x7577, 0xC44A, 0xC44B, 0, - 0x7578, 0xAF2E, 0x5C44, 0x5C37, 0xAF2F, 0x3648, 0x5C3A, 0x3D5D, - 0xC44F, 0xC450, 0xAF30, 0x4760, 0x5C3C, 0x364B, 0, 0x5C34, - 0x5C36, 0x5C33, 0xAF31, 0xC453, 0x4F30, 0x335A, 0x5C39, 0xAF32, -}; -static const unsigned short utf8_to_euc_E6A6[] = { - 0xC455, 0x5C43, 0x3335, 0, 0, 0, 0, 0, - 0, 0, 0x3A67, 0, 0, 0xC456, 0x315D, 0, - 0, 0x5C54, 0xC457, 0, 0x4F31, 0x5C57, 0xC458, 0, - 0xC459, 0, 0, 0x3F3A, 0x5C56, 0, 0, 0, - 0x5C55, 0xC45A, 0, 0, 0, 0xC45B, 0xC45C, 0x5C52, - 0xC45D, 0, 0, 0xC45E, 0, 0xC45F, 0x5C46, 0xC460, - 0, 0x5C63, 0x5C45, 0, 0x5C58, 0, 0, 0xC461, - 0xC462, 0, 0xC463, 0x5C50, 0xC464, 0, 0x5C4B, 0x5C48, -}; -static const unsigned short utf8_to_euc_E6A6_x0213[] = { - 0x7579, 0x5C43, 0x3335, 0, 0, 0, 0, 0, - 0, 0, 0x3A67, 0, 0, 0xC456, 0x315D, 0, - 0, 0x5C54, 0xAF33, 0, 0x4F31, 0x5C57, 0xAF35, 0, - 0xAF36, 0, 0, 0x3F3A, 0x5C56, 0, 0, 0, - 0x5C55, 0xC45A, 0, 0, 0, 0x757B, 0xAF37, 0x5C52, - 0xC45D, 0, 0, 0xC45E, 0, 0x757C, 0x5C46, 0xC460, - 0xAF38, 0x5C63, 0x5C45, 0, 0x5C58, 0, 0, 0xAF39, - 0xC462, 0, 0xAF3A, 0x5C50, 0xAF3B, 0, 0x5C4B, 0x5C48, -}; -static const unsigned short utf8_to_euc_E6A7[] = { - 0, 0x5C49, 0, 0x5C51, 0, 0xC465, 0, 0x7422, - 0xC466, 0, 0x5C4E, 0x393D, 0x4448, 0x4164, 0x5C4C, 0, - 0x5C47, 0xC467, 0, 0x5C4A, 0, 0, 0xC468, 0xC469, - 0x4D4D, 0x4B6A, 0, 0, 0, 0x5C4F, 0x5C59, 0, - 0, 0, 0xC46A, 0, 0, 0xC46B, 0, 0x5C61, - 0x5C5A, 0, 0, 0x5C67, 0, 0x5C65, 0xC46C, 0xC46D, - 0, 0xC46E, 0x5C60, 0xC46F, 0, 0xC470, 0, 0, - 0, 0x5C5F, 0, 0x4450, 0, 0x4165, 0xC471, 0x5C5D, -}; -static const unsigned short utf8_to_euc_E6A7_x0213[] = { - 0xAF3C, 0x5C49, 0, 0x5C51, 0, 0xC465, 0, 0x7422, - 0xC466, 0, 0x5C4E, 0x393D, 0x4448, 0x4164, 0x5C4C, 0x757D, - 0x5C47, 0xAF3D, 0, 0x5C4A, 0, 0, 0xAF3E, 0xC469, - 0x4D4D, 0x4B6A, 0, 0, 0, 0x5C4F, 0x5C59, 0, - 0, 0, 0x7622, 0xAF44, 0, 0xC46B, 0, 0x5C61, - 0x5C5A, 0x7623, 0x7624, 0x5C67, 0, 0x5C65, 0xAF45, 0xAF46, - 0, 0xC46E, 0x5C60, 0xAF47, 0xAF49, 0x7625, 0x7626, 0, - 0, 0x5C5F, 0, 0x4450, 0, 0x4165, 0xAF4A, 0x5C5D, -}; -static const unsigned short utf8_to_euc_E6A8[] = { - 0xC472, 0xC473, 0x5C5B, 0xC474, 0, 0x5C62, 0, 0, - 0, 0, 0x5C68, 0x4875, 0x5C6E, 0, 0, 0xC475, - 0, 0xC476, 0x5C69, 0x5C6C, 0x5C66, 0xC477, 0, 0x4374, - 0, 0x4938, 0xC478, 0x5C5C, 0, 0xC479, 0x5C64, 0x3E40, - 0xC47A, 0x4C4F, 0x5C78, 0x5C6B, 0xC47B, 0, 0, 0, - 0xC47C, 0x3822, 0x3223, 0x335F, 0, 0, 0x5C53, 0, - 0xC47D, 0, 0xC47E, 0, 0xC521, 0x3E41, 0x5C70, 0xC522, - 0x5C77, 0x3C79, 0x3372, 0xC523, 0, 0x432E, 0xC524, 0xC525, -}; -static const unsigned short utf8_to_euc_E6A8_x0213[] = { - 0xC472, 0xC473, 0x5C5B, 0xC474, 0, 0x5C62, 0, 0, - 0, 0, 0x5C68, 0x4875, 0x5C6E, 0, 0, 0x7627, - 0, 0xAF4B, 0x5C69, 0x5C6C, 0x5C66, 0x7628, 0, 0x4374, - 0, 0x4938, 0xAF4C, 0x5C5C, 0, 0xAF4D, 0x5C64, 0x3E40, - 0xC47A, 0x4C4F, 0x5C78, 0x5C6B, 0xC47B, 0, 0, 0, - 0xC47C, 0x3822, 0x3223, 0x335F, 0, 0, 0x5C53, 0, - 0xAF41, 0, 0xAF4F, 0xAF50, 0xAF51, 0x3E41, 0x5C70, 0xC522, - 0x5C77, 0x3C79, 0x3372, 0x762A, 0, 0x432E, 0x762B, 0xAF52, -}; -static const unsigned short utf8_to_euc_E6A9[] = { - 0, 0, 0, 0, 0x5C6D, 0xC526, 0xC527, 0x5C72, - 0x5C76, 0xC528, 0xC529, 0x3636, 0, 0, 0xC52A, 0, - 0xC52B, 0xC52C, 0xC52D, 0, 0, 0xC52E, 0xC52F, 0, - 0x354C, 0x5C74, 0, 0xC530, 0, 0, 0, 0x3521, - 0, 0x464B, 0x5C73, 0, 0xC531, 0, 0x5C75, 0xC532, - 0, 0, 0xC533, 0xF449, 0, 0, 0, 0, - 0, 0xC534, 0x5C6F, 0xC535, 0, 0, 0, 0, - 0x5C71, 0, 0, 0, 0, 0, 0xC536, 0x3360, -}; -static const unsigned short utf8_to_euc_E6A9_x0213[] = { - 0, 0, 0, 0, 0x5C6D, 0x762C, 0xAF53, 0x5C72, - 0x5C76, 0xAF54, 0xC529, 0x3636, 0, 0, 0xAF56, 0, - 0x762D, 0xC52C, 0xAF57, 0, 0, 0xC52E, 0x762E, 0, - 0x354C, 0x5C74, 0, 0x762F, 0, 0, 0, 0x3521, - 0, 0x464B, 0x5C73, 0, 0xAF58, 0, 0x5C75, 0xC532, - 0, 0, 0xC533, 0x7630, 0, 0, 0, 0, - 0, 0xC534, 0x5C6F, 0x7631, 0, 0, 0, 0, - 0x5C71, 0, 0xAF55, 0, 0, 0, 0xAF5A, 0x3360, -}; -static const unsigned short utf8_to_euc_E6AA[] = { - 0x4349, 0xC537, 0, 0xC538, 0x5C7C, 0, 0xC539, 0xC53A, - 0, 0xC53B, 0, 0xC53C, 0, 0x5C7A, 0x3869, 0, - 0x5C79, 0xC53D, 0, 0, 0, 0, 0, 0x5D21, - 0, 0, 0, 0xC53E, 0x5B58, 0xC53F, 0xC540, 0xC541, - 0x5C7B, 0, 0x5C7D, 0x5C7E, 0, 0xC542, 0, 0, - 0, 0, 0x5D2C, 0xC543, 0x5D28, 0, 0x5B6D, 0xC544, - 0xC545, 0xC546, 0, 0x5D27, 0xC547, 0, 0, 0, - 0x5D26, 0, 0, 0x5D23, 0, 0xC548, 0xC549, 0xC54A, -}; -static const unsigned short utf8_to_euc_E6AA_x0213[] = { - 0x4349, 0xC537, 0, 0xAF5B, 0x5C7C, 0, 0xC539, 0xC53A, - 0, 0x7633, 0, 0xAF5C, 0, 0x5C7A, 0x3869, 0, - 0x5C79, 0xAF5E, 0, 0, 0x7634, 0, 0, 0x5D21, - 0, 0, 0, 0xC53E, 0x5B58, 0x7635, 0x7636, 0xAF5F, - 0x5C7B, 0xAF60, 0x5C7D, 0x5C7E, 0, 0x7637, 0, 0, - 0, 0, 0x5D2C, 0xAF62, 0x5D28, 0, 0x5B6D, 0xC544, - 0xC545, 0xC546, 0, 0x5D27, 0xC547, 0, 0, 0, - 0x5D26, 0, 0, 0x5D23, 0, 0xAF63, 0xC549, 0xC54A, -}; -static const unsigned short utf8_to_euc_E6AB[] = { - 0, 0x5C6A, 0x5D25, 0x5D24, 0, 0, 0xC54B, 0, - 0xC54D, 0xC54C, 0, 0, 0xC54E, 0, 0, 0, - 0xC54F, 0x5D2A, 0, 0x4F26, 0xC550, 0xC551, 0xC552, 0, - 0, 0, 0x5D2D, 0x367B, 0xC553, 0xC554, 0x5D29, 0x5D2B, - 0, 0, 0xF44A, 0, 0xC555, 0, 0, 0xC556, - 0x4827, 0, 0x5D2E, 0, 0xC557, 0, 0, 0, - 0xC558, 0xC559, 0xC55A, 0, 0, 0, 0, 0, - 0, 0, 0x5D32, 0x5D2F, 0xC55B, 0xC55C, 0, 0, -}; -static const unsigned short utf8_to_euc_E6AB_x0213[] = { - 0, 0x5C6A, 0x5D25, 0x5D24, 0, 0, 0xAF64, 0, - 0xC54D, 0xC54C, 0, 0, 0xC54E, 0, 0, 0, - 0xAF66, 0x5D2A, 0, 0x4F26, 0xAF65, 0xC551, 0xC552, 0, - 0, 0, 0x5D2D, 0x367B, 0xAF67, 0xAF68, 0x5D29, 0x5D2B, - 0, 0, 0, 0, 0x7638, 0, 0, 0x7639, - 0x4827, 0, 0x5D2E, 0, 0xAF6B, 0, 0, 0, - 0xC558, 0xAF6C, 0xAF6D, 0xAF6E, 0, 0, 0, 0, - 0, 0, 0x5D32, 0x5D2F, 0xC55B, 0xAF6F, 0, 0, -}; -static const unsigned short utf8_to_euc_E6AC[] = { - 0, 0, 0xC55D, 0xC55E, 0x4D73, 0x5D30, 0xC55F, 0xC560, - 0, 0xC561, 0x5C5E, 0, 0, 0, 0, 0xC562, - 0xC563, 0xC564, 0x5D33, 0, 0, 0, 0x5D34, 0xC565, - 0, 0, 0, 0xC566, 0, 0x3135, 0xC567, 0x5D36, - 0x3767, 0x3C21, 0, 0x3655, 0xC568, 0, 0, 0x3224, - 0xC569, 0, 0, 0xC56A, 0xC56B, 0, 0, 0xC56C, - 0, 0, 0x4D5F, 0, 0, 0xC56D, 0xC56E, 0x5D38, - 0x5D37, 0x5D3A, 0x353D, 0xC56F, 0, 0x3656, 0x343E, 0xC570, -}; -static const unsigned short utf8_to_euc_E6AC_x0213[] = { - 0, 0, 0xC55D, 0xC55E, 0x4D73, 0x5D30, 0xC55F, 0xC560, - 0, 0xC561, 0x5C5E, 0xAF71, 0, 0, 0, 0xAF72, - 0xAF73, 0xAF74, 0x5D33, 0, 0, 0, 0x5D34, 0xAF76, - 0, 0, 0, 0x763C, 0, 0x3135, 0x763D, 0x5D36, - 0x3767, 0x3C21, 0, 0x3655, 0xC568, 0, 0, 0x3224, - 0xC569, 0, 0, 0xC56A, 0x763E, 0, 0, 0xAF78, - 0, 0, 0x4D5F, 0, 0, 0x763F, 0xC56E, 0x5D38, - 0x5D37, 0x5D3A, 0x353D, 0xC56F, 0, 0x3656, 0x343E, 0xC570, -}; -static const unsigned short utf8_to_euc_E6AD[] = { - 0, 0, 0, 0x5D3D, 0, 0, 0xC571, 0x5D3C, - 0, 0x5D3E, 0xC572, 0, 0x324E, 0xC573, 0x4337, 0, - 0x5D3F, 0, 0xC574, 0x343F, 0x5D41, 0, 0xC575, 0, - 0xC576, 0x5D40, 0, 0x5D42, 0, 0xC577, 0, 0x5D43, - 0xC578, 0x5D44, 0x3B5F, 0x4035, 0x3A21, 0, 0x4970, 0xC579, - 0, 0x4A62, 0x4F44, 0xC57A, 0, 0, 0xC57B, 0x3B75, - 0xC57C, 0, 0, 0x3A50, 0x4E72, 0xC57D, 0, 0, - 0x5D45, 0x5D46, 0, 0x3B60, 0, 0xC57E, 0xC621, 0x5D47, -}; -static const unsigned short utf8_to_euc_E6AD_x0213[] = { - 0, 0, 0, 0x5D3D, 0, 0, 0x7640, 0x5D3C, - 0, 0x5D3E, 0xAF79, 0, 0x324E, 0xC573, 0x4337, 0, - 0x5D3F, 0, 0xC574, 0x343F, 0x5D41, 0, 0x7641, 0, - 0xAF7A, 0x5D40, 0, 0x5D42, 0, 0xC577, 0, 0x5D43, - 0x7642, 0x5D44, 0x3B5F, 0x4035, 0x3A21, 0x7643, 0x4970, 0x7644, - 0, 0x4A62, 0x4F44, 0xC57A, 0xAF7B, 0, 0xC57B, 0x3B75, - 0xC57C, 0, 0, 0x3A50, 0x4E72, 0xAF7C, 0, 0x7645, - 0x5D45, 0x5D46, 0xAF7D, 0x3B60, 0, 0xC57E, 0xC621, 0x5D47, -}; -static const unsigned short utf8_to_euc_E6AE[] = { - 0x5D48, 0, 0xC622, 0x5D4A, 0x5D49, 0xC623, 0x4B58, 0, - 0, 0x3D5E, 0x3C6C, 0x3B44, 0, 0x5D4B, 0, 0, - 0, 0, 0, 0, 0, 0x5D4D, 0x3F23, 0xC624, - 0x5D4C, 0, 0, 0xC625, 0, 0, 0x5D4E, 0xC626, - 0xC627, 0, 0xC628, 0xC629, 0x5D4F, 0, 0, 0, - 0xC62A, 0xC62B, 0x5D50, 0x5D51, 0xC62C, 0xC62D, 0xC62E, 0x5D52, - 0xC62F, 0x5D54, 0x5D53, 0x5D55, 0x3225, 0x434A, 0, 0x5D56, - 0xC630, 0xC631, 0x3B26, 0x334C, 0x5D57, 0xC632, 0xC633, 0x4542, -}; -static const unsigned short utf8_to_euc_E6AE_x0213[] = { - 0x5D48, 0xAF7E, 0x7646, 0x5D4A, 0x5D49, 0xC623, 0x4B58, 0, - 0, 0x3D5E, 0x3C6C, 0x3B44, 0, 0x5D4B, 0, 0, - 0, 0, 0, 0, 0, 0x5D4D, 0x3F23, 0xC624, - 0x5D4C, 0, 0, 0xEE21, 0, 0, 0x5D4E, 0xC626, - 0xC627, 0, 0xC628, 0xC629, 0x5D4F, 0, 0, 0, - 0xC62A, 0x7647, 0x5D50, 0x5D51, 0xC62C, 0x7648, 0xEE22, 0x5D52, - 0xC62F, 0x5D54, 0x5D53, 0x5D55, 0x3225, 0x434A, 0, 0x5D56, - 0xC630, 0xC631, 0x3B26, 0x334C, 0x5D57, 0xEE24, 0xEE25, 0x4542, -}; -static const unsigned short utf8_to_euc_E6AF[] = { - 0x544C, 0, 0, 0xC634, 0xC635, 0x3523, 0x5D58, 0, - 0, 0xC636, 0, 0x5D59, 0xC637, 0x4A6C, 0x4B68, 0, - 0, 0, 0x4647, 0x5D5A, 0x4866, 0, 0xC638, 0, - 0x487B, 0, 0xC639, 0x4C53, 0, 0, 0, 0x5D5B, - 0, 0xC63A, 0, 0xC63B, 0, 0, 0xC63C, 0xC63D, - 0, 0, 0, 0x5D5D, 0x5D5C, 0, 0xC63E, 0x5D5F, - 0, 0xC63F, 0, 0x5D5E, 0, 0, 0, 0xC640, - 0, 0xC641, 0, 0, 0, 0, 0, 0xC642, -}; -static const unsigned short utf8_to_euc_E6AF_x0213[] = { - 0x544C, 0, 0, 0xC634, 0xC635, 0x3523, 0x5D58, 0xEE26, - 0xEE27, 0xEE28, 0, 0x5D59, 0xC637, 0x4A6C, 0x4B68, 0x764A, - 0, 0, 0x4647, 0x5D5A, 0x4866, 0, 0x764B, 0x764C, - 0x487B, 0, 0xEE29, 0x4C53, 0, 0, 0, 0x5D5B, - 0, 0xC63A, 0, 0xC63B, 0, 0, 0xEE2A, 0xEE2B, - 0, 0, 0, 0x5D5D, 0x5D5C, 0, 0xEE2C, 0x5D5F, - 0, 0xEE2D, 0, 0x5D5E, 0, 0, 0, 0xC640, - 0, 0xC641, 0, 0, 0, 0, 0, 0x764D, -}; -static const unsigned short utf8_to_euc_E6B0[] = { - 0, 0, 0xC643, 0, 0xC644, 0xC645, 0, 0, - 0x5D61, 0xC646, 0, 0, 0, 0xC647, 0xC648, 0x3B61, - 0xC649, 0x4C31, 0xC64A, 0x5D62, 0x5D63, 0, 0, 0x3524, - 0, 0xC64B, 0, 0x5D64, 0, 0, 0, 0xC64C, - 0, 0, 0, 0x5D66, 0x5D65, 0, 0xC64D, 0xC64E, - 0xC64F, 0, 0, 0, 0xC650, 0, 0xC651, 0, - 0, 0, 0, 0xC652, 0x3F65, 0xC653, 0xC654, 0x4939, - 0x314A, 0, 0xC655, 0xC656, 0, 0, 0x4845, 0xC657, -}; -static const unsigned short utf8_to_euc_E6B0_x0213[] = { - 0, 0, 0xEE2E, 0, 0xC644, 0x764E, 0, 0, - 0x5D61, 0xC646, 0xEE2F, 0, 0, 0xC647, 0xEE30, 0x3B61, - 0x764F, 0x4C31, 0xC64A, 0x5D62, 0x5D63, 0, 0, 0x3524, - 0, 0xC64B, 0, 0x5D64, 0, 0, 0, 0xC64C, - 0, 0, 0, 0x5D66, 0x5D65, 0, 0xC64D, 0xC64E, - 0xC64F, 0, 0, 0, 0xC650, 0, 0xC651, 0, - 0, 0, 0, 0x7650, 0x3F65, 0xEE31, 0xEE32, 0x4939, - 0x314A, 0, 0xEE33, 0xC656, 0, 0, 0x4845, 0xEE35, -}; -static const unsigned short utf8_to_euc_E6B1[] = { - 0x4475, 0x3D41, 0x3561, 0, 0, 0, 0, 0, - 0, 0, 0xC658, 0xC659, 0, 0xC65A, 0x4846, 0xC65B, - 0x3C2E, 0, 0xC65C, 0, 0xC65D, 0x5D68, 0, 0x3440, - 0, 0xC65E, 0x3178, 0xC65F, 0xC660, 0x4672, 0x5D67, 0x393E, - 0x4353, 0, 0x5D69, 0, 0, 0, 0, 0xC736, - 0x5D71, 0, 0x5D6A, 0xC661, 0, 0xC662, 0, 0xC663, - 0x4241, 0, 0x3562, 0x5D72, 0xC664, 0, 0xC665, 0, - 0xC666, 0xC667, 0x3768, 0xC668, 0, 0x3525, 0x5D70, 0, -}; -static const unsigned short utf8_to_euc_E6B1_x0213[] = { - 0x4475, 0x3D41, 0x3561, 0, 0, 0, 0, 0, - 0, 0, 0xC658, 0xC659, 0, 0xEE36, 0x4846, 0xC65B, - 0x3C2E, 0, 0xC65C, 0, 0xC65D, 0x5D68, 0, 0x3440, - 0, 0x7651, 0x3178, 0xEE37, 0x7652, 0x4672, 0x5D67, 0x393E, - 0x4353, 0, 0x5D69, 0, 0, 0, 0, 0xEE4F, - 0x5D71, 0, 0x5D6A, 0xC661, 0, 0xEE38, 0, 0, - 0x4241, 0, 0x3562, 0x5D72, 0x7654, 0, 0x7655, 0, - 0xC666, 0xC667, 0x3768, 0xC668, 0, 0x3525, 0x5D70, 0, -}; -static const unsigned short utf8_to_euc_E6B2[] = { - 0, 0x5D6E, 0x5D6B, 0x4D60, 0, 0xC669, 0xC66A, 0xC66B, - 0x4440, 0xC66C, 0, 0, 0x4659, 0x5D6C, 0, 0, - 0x5D74, 0, 0x5D73, 0x3723, 0xC66D, 0xC66E, 0x322D, 0xC66F, - 0xC670, 0x3A3B, 0x5D6D, 0x5D6F, 0xC671, 0, 0, 0xC672, - 0, 0x4B57, 0x4274, 0, 0, 0, 0, 0, - 0, 0, 0, 0x4B77, 0, 0, 0x5D7C, 0, - 0xC673, 0x5D7D, 0xC674, 0x324F, 0xC675, 0, 0, 0, - 0x4A28, 0x4C7D, 0x5E21, 0x3C23, 0x3E42, 0x5D78, 0x5D7E, 0x3168, -}; -static const unsigned short utf8_to_euc_E6B2_x0213[] = { - 0, 0x5D6E, 0x5D6B, 0x4D60, 0xEE39, 0x7656, 0x7657, 0xC66B, - 0x4440, 0xEE3A, 0, 0, 0x4659, 0x5D6C, 0, 0, - 0x5D74, 0, 0x5D73, 0x3723, 0xEE3C, 0xEE3D, 0x322D, 0xEE3E, - 0x7658, 0x3A3B, 0x5D6D, 0x5D6F, 0x7659, 0, 0, 0xC672, - 0, 0x4B57, 0x4274, 0, 0, 0, 0, 0, - 0, 0, 0x7653, 0x4B77, 0, 0xEE3F, 0x5D7C, 0, - 0xC673, 0x5D7D, 0xC674, 0x324F, 0xC675, 0, 0, 0, - 0x4A28, 0x4C7D, 0x5E21, 0x3C23, 0x3E42, 0x5D78, 0x5D7E, 0x3168, -}; -static const unsigned short utf8_to_euc_E6B3[] = { - 0, 0x3637, 0xC676, 0, 0x5D75, 0x5D7A, 0xC677, 0, - 0, 0x4074, 0x4771, 0, 0x4867, 0xC678, 0, 0xC679, - 0xC67A, 0xC67B, 0xC67C, 0x5D77, 0xC67D, 0x4B21, 0xC67E, 0x5D79, - 0, 0x5E24, 0xC721, 0x5E22, 0xC722, 0x5D7B, 0, 0, - 0xC723, 0x4B22, 0x4748, 0x3563, 0, 0x4525, 0, 0xC724, - 0x436D, 0xC725, 0x5E25, 0xC726, 0xC727, 0, 0xC728, 0x5E23, - 0x4259, 0x5D76, 0xC729, 0x314B, 0xC72A, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E6B3_x0213[] = { - 0, 0x3637, 0xEE40, 0, 0x5D75, 0x5D7A, 0x765B, 0, - 0, 0x4074, 0x4771, 0, 0x4867, 0xC678, 0, 0xC679, - 0xEE41, 0xC67B, 0xC67C, 0x5D77, 0x765C, 0x4B21, 0xEE43, 0x5D79, - 0, 0x5E24, 0xEE44, 0x5E22, 0xEE45, 0x5D7B, 0, 0, - 0x765D, 0x4B22, 0x4748, 0x3563, 0, 0x4525, 0, 0xC724, - 0x436D, 0xEE46, 0x5E25, 0x765E, 0xEE47, 0xEE48, 0x765F, 0x5E23, - 0x4259, 0x5D76, 0xC729, 0x314B, 0xC72A, 0, 0, 0, - 0, 0, 0, 0x765A, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E6B4[] = { - 0, 0, 0, 0, 0xC72B, 0, 0, 0xC72C, - 0, 0, 0xC72D, 0x4D4E, 0x5E30, 0, 0xC72E, 0xC72F, - 0, 0xC730, 0x5E2F, 0xC731, 0, 0, 0, 0x4076, - 0, 0x5E2C, 0xC732, 0x4D6C, 0, 0, 0x4636, 0x5E26, - 0, 0, 0, 0, 0, 0x4445, 0xC733, 0xC734, - 0xC735, 0x314C, 0x393F, 0x5E29, 0, 0, 0xC737, 0xC738, - 0, 0xC739, 0x3D27, 0x5E2E, 0, 0x5E2D, 0x5E28, 0, - 0x5E2B, 0xC73A, 0, 0x3368, 0xC73B, 0x5E2A, 0x4749, 0xC73C, -}; -static const unsigned short utf8_to_euc_E6B4_x0213[] = { - 0xEE4A, 0, 0, 0, 0x7661, 0, 0, 0xC72C, - 0, 0, 0xEE4B, 0x4D4E, 0x5E30, 0, 0x7662, 0xC72F, - 0, 0xC730, 0x5E2F, 0xC731, 0, 0, 0, 0x4076, - 0, 0x5E2C, 0xC732, 0x4D6C, 0, 0, 0x4636, 0x5E26, - 0, 0, 0, 0, 0xEE4C, 0x4445, 0xEE4D, 0xEE4E, - 0xC735, 0x314C, 0x393F, 0x5E29, 0, 0, 0x7663, 0xEE50, - 0, 0x7664, 0x3D27, 0x5E2E, 0xEE65, 0x5E2D, 0x5E28, 0, - 0x5E2B, 0x7665, 0, 0x3368, 0xEE51, 0x5E2A, 0x4749, 0x7666, -}; -static const unsigned short utf8_to_euc_E6B5[] = { - 0, 0x4E2E, 0, 0, 0x3E74, 0x4075, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xC73D, - 0, 0x5E36, 0x5E34, 0, 0x494D, 0, 0xC73E, 0xC73F, - 0, 0xC740, 0, 0x5E31, 0x5E33, 0xC741, 0x313A, 0xC742, - 0, 0x3940, 0x4F32, 0, 0x333D, 0, 0x4962, 0xC743, - 0xC744, 0, 0, 0, 0x4D61, 0, 0, 0x3324, - 0x3F3B, 0x5E35, 0, 0, 0xC745, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E6B5_x0213[] = { - 0, 0x4E2E, 0, 0, 0x3E74, 0x4075, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xC73D, - 0x7667, 0x5E36, 0x5E34, 0xEE52, 0x494D, 0, 0xEE53, 0xC73F, - 0xEE54, 0xC740, 0, 0x5E31, 0x5E33, 0x7668, 0x313A, 0xC742, - 0, 0x3940, 0x4F32, 0, 0x333D, 0, 0x4962, 0, - 0xEE55, 0, 0, 0, 0x4D61, 0, 0, 0x3324, - 0x3F3B, 0x5E35, 0, 0, 0xC745, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E6B6[] = { - 0, 0, 0xC746, 0, 0, 0x5E3A, 0, 0xC747, - 0x3E43, 0, 0, 0, 0x4D30, 0, 0x5E37, 0, - 0, 0xC748, 0xC749, 0x5E32, 0xC74A, 0x5E38, 0xC74B, 0xC74C, - 0xC74D, 0x4E5E, 0, 0x4573, 0x4642, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xC74E, 0, 0xC74F, 0, 0, 0x3336, - 0, 0, 0x3155, 0, 0xC750, 0x5E3E, 0, 0xC751, - 0x5E41, 0xC752, 0, 0, 0x4E43, 0xC753, 0, 0xC754, -}; -static const unsigned short utf8_to_euc_E6B6_x0213[] = { - 0xEE56, 0xEE57, 0x766A, 0, 0, 0x5E3A, 0, 0x766B, - 0x3E43, 0x766C, 0xEE58, 0, 0x4D30, 0xEE59, 0x5E37, 0, - 0, 0xEE5A, 0xC749, 0x5E32, 0x766D, 0x5E38, 0, 0xC74C, - 0xEE5B, 0x4E5E, 0, 0x4573, 0x4642, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x766E, 0xEE61, 0x766F, 0, 0xEE62, 0x3336, - 0, 0, 0x3155, 0, 0xEE63, 0x5E3E, 0, 0xC751, - 0x5E41, 0xC752, 0, 0, 0x4E43, 0xC753, 0, 0x7670, -}; -static const unsigned short utf8_to_euc_E6B7[] = { - 0x4D64, 0, 0, 0, 0xC755, 0x5E48, 0x5E42, 0x5E3F, - 0xC756, 0, 0xC757, 0x4E54, 0x5E45, 0, 0xC758, 0xC759, - 0, 0x3D4A, 0x5E47, 0, 0, 0x5E4C, 0xC75A, 0, - 0x4571, 0x5E4A, 0, 0xC75B, 0, 0xC75C, 0x5E44, 0xC75D, - 0xC75E, 0x4338, 0xC75F, 0, 0x5E4B, 0xC760, 0x5E40, 0, - 0x5E46, 0xC761, 0x5E4D, 0x307C, 0x5E43, 0, 0x5E4E, 0xC762, - 0xC763, 0x3F3C, 0xF44C, 0x3D5F, 0xC764, 0x4A25, 0xC765, 0x3A2E, - 0xF44B, 0x5E3B, 0x5E49, 0x453A, 0xC766, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E6B7_x0213[] = { - 0x4D64, 0, 0xEE64, 0, 0x7671, 0x5E48, 0x5E42, 0x5E3F, - 0xEE66, 0, 0xC757, 0x4E54, 0x5E45, 0, 0xEE67, 0xEE68, - 0xEE69, 0x3D4A, 0x5E47, 0, 0, 0x5E4C, 0x7672, 0, - 0x4571, 0x5E4A, 0x7673, 0x7674, 0, 0x7675, 0x5E44, 0xEE6A, - 0xC75E, 0x4338, 0xC75F, 0, 0x5E4B, 0xC760, 0x5E40, 0, - 0x5E46, 0xEE6B, 0x5E4D, 0x307C, 0x5E43, 0, 0x5E4E, 0xC762, - 0xC763, 0x3F3C, 0, 0x3D5F, 0xC764, 0x4A25, 0xEE6C, 0x3A2E, - 0, 0x5E3B, 0x5E49, 0x453A, 0x7676, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E6B8[] = { - 0xC767, 0, 0, 0, 0xC768, 0x4036, 0, 0x3369, - 0x3A51, 0x3E44, 0x5E3D, 0x3D42, 0, 0, 0, 0, - 0, 0, 0, 0x374C, 0, 0x5E3C, 0, 0, - 0, 0x5E52, 0x3D6D, 0x383A, 0, 0x5E61, 0xC769, 0x5E5B, - 0x3574, 0x454F, 0xC76A, 0x5E56, 0x5E5F, 0x302F, 0x3132, 0xC76B, - 0, 0x3239, 0, 0x5E58, 0x422C, 0x5E4F, 0x5E51, 0x3941, - 0, 0, 0xC76C, 0, 0, 0, 0xC76D, 0, - 0x5E62, 0xC76E, 0x5E5D, 0xC76F, 0xC770, 0, 0x5E55, 0, -}; -static const unsigned short utf8_to_euc_E6B8_x0213[] = { - 0xC767, 0, 0, 0, 0xC768, 0x4036, 0, 0x3369, - 0x3A51, 0x3E44, 0x5E3D, 0x3D42, 0, 0, 0, 0, - 0, 0, 0, 0x374C, 0, 0x5E3C, 0, 0xEE5D, - 0, 0x5E52, 0x3D6D, 0x383A, 0, 0x5E61, 0xEE6E, 0x5E5B, - 0x3574, 0x454F, 0xEE6F, 0x5E56, 0x5E5F, 0x302F, 0x3132, 0xEE70, - 0, 0x3239, 0, 0x5E58, 0x422C, 0x5E4F, 0x5E51, 0x3941, - 0, 0, 0xEE72, 0, 0x7678, 0, 0xEE6D, 0, - 0x5E62, 0, 0x5E5D, 0xC76F, 0xEE73, 0, 0x5E55, 0, -}; -static const unsigned short utf8_to_euc_E6B9[] = { - 0, 0, 0, 0x5E5C, 0xC771, 0xC772, 0, 0, - 0xC773, 0xC774, 0x4C2B, 0xC775, 0, 0x5E5A, 0x5E5E, 0xC776, - 0, 0xC777, 0xC778, 0xC779, 0xC77A, 0, 0x3850, 0xC77B, - 0x3E45, 0, 0, 0x4339, 0xC77C, 0xC77D, 0xC77E, 0x5E54, - 0, 0, 0xC821, 0xC822, 0, 0, 0, 0x4D2F, - 0xC823, 0, 0, 0x5E57, 0, 0, 0x5E50, 0x4572, - 0, 0, 0x5E53, 0xC824, 0, 0, 0x5E59, 0, - 0, 0, 0, 0xC825, 0, 0xC826, 0x4F51, 0x3C3E, -}; -static const unsigned short utf8_to_euc_E6B9_x0213[] = { - 0, 0, 0, 0x5E5C, 0x7679, 0xC772, 0, 0, - 0xEE74, 0xEE75, 0x4C2B, 0xEE76, 0xEE77, 0x5E5A, 0x5E5E, 0xEE78, - 0, 0xEE79, 0xC778, 0xEE7A, 0xEE7B, 0, 0x3850, 0xEE7C, - 0x3E45, 0, 0, 0x4339, 0x767A, 0xC77D, 0x767B, 0x5E54, - 0, 0, 0xC821, 0xEE7D, 0, 0, 0, 0x4D2F, - 0xC823, 0, 0, 0x5E57, 0, 0, 0x5E50, 0x4572, - 0, 0, 0x5E53, 0xC824, 0, 0, 0x5E59, 0, - 0, 0, 0, 0xC825, 0, 0xC826, 0x4F51, 0x3C3E, -}; -static const unsigned short utf8_to_euc_E6BA[] = { - 0x4B7E, 0, 0x5E63, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x482E, 0xC827, 0, 0x5E6F, - 0x383B, 0, 0, 0xC828, 0, 0, 0x3D60, 0, - 0x5E65, 0xC829, 0, 0, 0x4E2F, 0x3942, 0, 0x5E72, - 0xC82A, 0, 0x306E, 0, 0, 0x5E70, 0, 0xC82B, - 0, 0, 0x5E64, 0, 0, 0xC82C, 0xC82D, 0x5E6A, - 0, 0xC82E, 0x5E6C, 0xC82F, 0, 0, 0x4D4F, 0x5E67, - 0, 0, 0x452E, 0xC830, 0, 0x5E69, 0, 0xC831, -}; -static const unsigned short utf8_to_euc_E6BA_x0213[] = { - 0x4B7E, 0, 0x5E63, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x482E, 0xC827, 0, 0x5E6F, - 0x383B, 0, 0, 0xEF21, 0, 0, 0x3D60, 0, - 0x5E65, 0xC829, 0, 0, 0x4E2F, 0x3942, 0, 0x5E72, - 0xC82A, 0, 0x306E, 0, 0, 0x5E70, 0, 0xEF22, - 0, 0, 0x5E64, 0x767C, 0, 0xC82C, 0xC82D, 0x5E6A, - 0, 0x767D, 0x5E6C, 0xC82F, 0xEF23, 0, 0x4D4F, 0x5E67, - 0, 0, 0x452E, 0xC830, 0, 0x5E69, 0, 0xEF24, -}; -static const unsigned short utf8_to_euc_E6BB[] = { - 0xC832, 0xC833, 0x5E71, 0xC834, 0x5E6B, 0x4C47, 0, 0xC835, - 0xC836, 0x5E66, 0xC837, 0x3C22, 0x5E7E, 0xC838, 0xC839, 0xC83A, - 0, 0x336A, 0, 0x5E68, 0x5E6D, 0x5E6E, 0, 0, - 0, 0, 0, 0, 0, 0x426C, 0x425A, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xC83B, 0x5E76, 0xC83C, 0xC83D, 0x5E7C, - 0, 0, 0x5E7A, 0, 0x4529, 0, 0, 0x5F23, - 0x5E77, 0xC83E, 0, 0xC83F, 0, 0xC840, 0x5E78, 0x5E60, -}; -static const unsigned short utf8_to_euc_E6BB_x0213[] = { - 0xC832, 0x767E, 0x5E71, 0xEF25, 0x5E6B, 0x4C47, 0, 0x7721, - 0xC836, 0x5E66, 0xEF26, 0x3C22, 0x5E7E, 0xC838, 0x7722, 0xC83A, - 0, 0x336A, 0, 0x5E68, 0x5E6D, 0x5E6E, 0, 0, - 0, 0xEF27, 0, 0, 0, 0x426C, 0x425A, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xEF29, 0x5E76, 0xC83C, 0xC83D, 0x5E7C, - 0, 0, 0x5E7A, 0, 0x4529, 0, 0, 0x5F23, - 0x5E77, 0xEF2A, 0, 0xEF2B, 0, 0xC840, 0x5E78, 0x5E60, -}; -static const unsigned short utf8_to_euc_E6BC[] = { - 0, 0x3579, 0x493A, 0, 0xC841, 0, 0x3C3F, 0, - 0xC842, 0x3977, 0xC843, 0, 0xC844, 0xC845, 0, 0x4F33, - 0, 0x5E74, 0, 0x5F22, 0x3169, 0x4166, 0xC846, 0, - 0xC847, 0, 0xC848, 0xC849, 0, 0, 0, 0, - 0x4779, 0, 0x3441, 0x4E7A, 0, 0, 0xC84A, 0, - 0, 0xC84B, 0xC84C, 0x4C21, 0x4452, 0xC853, 0, 0xC84D, - 0xC84E, 0x5E7B, 0x5E7D, 0xC84F, 0, 0, 0xC850, 0, - 0x4132, 0, 0, 0xC851, 0xC852, 0, 0x5F21, 0x5E79, -}; -static const unsigned short utf8_to_euc_E6BC_x0213[] = { - 0, 0x3579, 0x493A, 0, 0xC841, 0, 0x3C3F, 0, - 0xC842, 0x3977, 0xEF2C, 0, 0xEF2D, 0xC845, 0, 0x4F33, - 0x7723, 0x5E74, 0, 0x5F22, 0x3169, 0x4166, 0xC846, 0, - 0xEF2E, 0, 0x7724, 0xC849, 0, 0, 0, 0, - 0x4779, 0, 0x3441, 0x4E7A, 0, 0xEF2F, 0xC84A, 0, - 0, 0xC84B, 0x7726, 0x4C21, 0x4452, 0xC853, 0, 0x7727, - 0xC84E, 0x5E7B, 0x5E7D, 0x7728, 0, 0xEF28, 0xEF30, 0, - 0x4132, 0, 0, 0xC851, 0xEF31, 0, 0x5F21, 0x5E79, -}; -static const unsigned short utf8_to_euc_E6BD[] = { - 0, 0x5E73, 0, 0, 0, 0x3443, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xC854, - 0, 0xC855, 0xC856, 0xC857, 0x3769, 0, 0, 0xC858, - 0x5F2F, 0xC859, 0xC85A, 0x5F2A, 0x4078, 0xC85B, 0xC85C, 0x3363, - 0, 0xC85D, 0xC85E, 0, 0x3D61, 0, 0x5F33, 0, - 0xC85F, 0, 0, 0, 0xC860, 0x5F2C, 0x442C, 0x5F29, - 0x4459, 0, 0, 0, 0x5F4C, 0, 0, 0, - 0x5F26, 0, 0x5F25, 0, 0x5F2E, 0xC861, 0xC862, 0, -}; -static const unsigned short utf8_to_euc_E6BD_x0213[] = { - 0, 0x5E73, 0, 0, 0, 0x3443, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xC854, - 0, 0x7729, 0xEF33, 0xC857, 0x3769, 0, 0, 0xEF34, - 0x5F2F, 0x772A, 0xEF35, 0x5F2A, 0x4078, 0xC85B, 0x772B, 0x3363, - 0xEF36, 0x772C, 0x772D, 0, 0x3D61, 0, 0x5F33, 0, - 0xEF37, 0, 0, 0, 0xC860, 0x5F2C, 0x442C, 0x5F29, - 0x4459, 0, 0, 0, 0x5F4C, 0, 0, 0, - 0x5F26, 0, 0x5F25, 0, 0x5F2E, 0xEF39, 0x772E, 0, -}; -static const unsigned short utf8_to_euc_E6BE[] = { - 0x5F28, 0x5F27, 0x5F2D, 0xC863, 0x4021, 0, 0x5F24, 0xC864, - 0xC865, 0, 0, 0xC866, 0xC867, 0xC868, 0x5F30, 0, - 0xC869, 0x5F31, 0xC86A, 0xC86B, 0xC86C, 0, 0xC86D, 0x3442, - 0, 0, 0xC86E, 0, 0, 0, 0, 0xC86F, - 0xC870, 0x5F36, 0, 0x5F35, 0x5F37, 0xC871, 0xC872, 0xC873, - 0xC874, 0, 0x5F3A, 0, 0, 0, 0xC875, 0xC876, - 0xC877, 0x4543, 0, 0x5F34, 0, 0xC878, 0xC879, 0, - 0, 0x5F38, 0, 0, 0xC87A, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E6BE_x0213[] = { - 0x5F28, 0x5F27, 0x5F2D, 0xC863, 0x4021, 0, 0x5F24, 0xC864, - 0x772F, 0, 0, 0xC866, 0x7730, 0x7731, 0x5F30, 0, - 0xEF3A, 0x5F31, 0xC86A, 0xC86B, 0x7732, 0, 0xEF3B, 0x3442, - 0xEF38, 0, 0xC86E, 0, 0, 0, 0, 0xEF3D, - 0x7733, 0x5F36, 0, 0x5F35, 0x5F37, 0xEF3E, 0xC872, 0x7734, - 0xC874, 0, 0x5F3A, 0, 0, 0, 0xC875, 0xEF3F, - 0xC877, 0x4543, 0, 0x5F34, 0, 0xEF41, 0x7735, 0, - 0, 0x5F38, 0, 0, 0x7736, 0, 0xEF3C, 0, -}; -static const unsigned short utf8_to_euc_E6BF[] = { - 0x3763, 0x4279, 0x5F32, 0x473B, 0, 0xC87B, 0x5F39, 0xC87C, - 0xC87D, 0, 0xC87E, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x5F3E, 0x5F3C, 0, 0, - 0x5F3F, 0, 0xC921, 0x5F42, 0, 0, 0xC922, 0x5F3B, - 0x396A, 0x4728, 0, 0, 0x5E39, 0, 0, 0, - 0xC923, 0xC924, 0, 0x4D74, 0x5F3D, 0, 0x5F41, 0x4275, - 0xC925, 0x5F40, 0, 0x5F2B, 0, 0xC926, 0x6F69, 0, - 0, 0xC927, 0x5F45, 0, 0xC928, 0xC929, 0x5F49, 0, -}; -static const unsigned short utf8_to_euc_E6BF_x0213[] = { - 0x3763, 0x4279, 0x5F32, 0x473B, 0, 0xC87B, 0x5F39, 0x7737, - 0xEF42, 0xEF43, 0x7738, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x5F3E, 0x5F3C, 0, 0, - 0x5F3F, 0, 0xEF44, 0x5F42, 0, 0, 0xEF45, 0x5F3B, - 0x396A, 0x4728, 0, 0, 0x5E39, 0, 0, 0, - 0xC923, 0xEF46, 0, 0x4D74, 0x5F3D, 0, 0x5F41, 0x4275, - 0x773A, 0x5F40, 0, 0x5F2B, 0, 0x773B, 0x6F69, 0, - 0, 0x7739, 0x5F45, 0, 0xEF48, 0xC929, 0x5F49, 0, -}; -static const unsigned short utf8_to_euc_E780[] = { - 0xC92A, 0x5F47, 0, 0, 0, 0xC92B, 0xC92C, 0xC92D, - 0, 0x5F43, 0, 0x5F44, 0, 0xC92E, 0, 0x5F48, - 0, 0x5F46, 0, 0, 0, 0x494E, 0, 0xC92F, - 0x5F4E, 0, 0x5F4B, 0x5F4A, 0, 0x5F4D, 0x4654, 0x5F4F, - 0xC930, 0, 0, 0xC931, 0, 0, 0x4375, 0x426D, - 0xF44D, 0, 0, 0, 0x4025, 0, 0, 0xC932, - 0x5F50, 0, 0x5F52, 0, 0xC933, 0, 0, 0xC934, - 0, 0xC935, 0, 0, 0xC936, 0, 0x5F51, 0, -}; -static const unsigned short utf8_to_euc_E780_x0213[] = { - 0xEF49, 0x5F47, 0, 0, 0, 0x773C, 0x773D, 0xEF4A, - 0, 0x5F43, 0xEF4B, 0x5F44, 0, 0xC92E, 0, 0x5F48, - 0, 0x5F46, 0, 0, 0, 0x494E, 0, 0xC92F, - 0x5F4E, 0, 0x5F4B, 0x5F4A, 0, 0x5F4D, 0x4654, 0x5F4F, - 0xC930, 0, 0, 0xEF4C, 0, 0, 0x4375, 0x426D, - 0x773E, 0, 0, 0, 0x4025, 0, 0, 0xC932, - 0x5F50, 0, 0x5F52, 0, 0xC933, 0, 0, 0xC934, - 0, 0xEF4E, 0xEF4F, 0, 0xEF50, 0, 0x5F51, 0, -}; -static const unsigned short utf8_to_euc_E781[] = { - 0, 0, 0, 0xC937, 0xC938, 0, 0, 0, - 0xC939, 0xC93A, 0xC93B, 0xC93C, 0x5E75, 0, 0xC941, 0, - 0, 0x5F53, 0, 0, 0xC93D, 0xC93E, 0, 0, - 0x4667, 0, 0, 0, 0, 0xC93F, 0xC940, 0, - 0, 0, 0, 0x5F54, 0xC942, 0xC943, 0, 0, - 0, 0, 0, 0x3250, 0xC944, 0, 0xC945, 0x4574, - 0x3325, 0, 0, 0, 0, 0xC946, 0xC947, 0, - 0x3564, 0, 0, 0, 0x3C5E, 0x3A52, 0xC948, 0, -}; -static const unsigned short utf8_to_euc_E781_x0213[] = { - 0, 0, 0, 0xEF51, 0xC938, 0, 0, 0xEF52, - 0xC939, 0xC93A, 0x773F, 0xEF53, 0x5E75, 0, 0x7742, 0, - 0, 0x5F53, 0, 0, 0xEF55, 0xC93E, 0, 0, - 0x4667, 0, 0, 0, 0, 0x7740, 0x7741, 0, - 0, 0, 0, 0x5F54, 0x7743, 0xEF56, 0, 0, - 0, 0xEF57, 0, 0x3250, 0xEF58, 0, 0xEF59, 0x4574, - 0x3325, 0, 0, 0, 0, 0x7744, 0xEF5A, 0, - 0x3564, 0, 0, 0, 0x3C5E, 0x3A52, 0xEF5B, 0, -}; -static const unsigned short utf8_to_euc_E782[] = { - 0, 0xC949, 0, 0, 0, 0xC94A, 0xC94B, 0, - 0, 0x4F27, 0x3F66, 0, 0, 0, 0x316A, 0, - 0, 0, 0x5F56, 0, 0xC94C, 0xC94D, 0xC94E, 0xC94F, - 0xC950, 0x5F55, 0, 0xC951, 0, 0, 0, 0, - 0, 0, 0, 0, 0xC952, 0, 0, 0, - 0, 0, 0, 0xC953, 0x5F59, 0x433A, 0x5F5C, 0x5F57, - 0xC954, 0xC955, 0, 0x5F5B, 0xC956, 0, 0, 0xC957, - 0x5F5A, 0x4540, 0x3059, 0xF42E, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E782_x0213[] = { - 0, 0xEF5C, 0, 0, 0, 0x7745, 0xEF5D, 0, - 0, 0x4F27, 0x3F66, 0, 0, 0, 0x316A, 0, - 0, 0, 0x5F56, 0, 0xC94C, 0xEF5E, 0xC94E, 0xEF5F, - 0xC950, 0x5F55, 0, 0xC951, 0, 0, 0, 0xEF62, - 0, 0, 0, 0, 0x7746, 0, 0, 0, - 0, 0, 0, 0x7747, 0x5F59, 0x433A, 0x5F5C, 0x5F57, - 0xC954, 0xEF63, 0, 0x5F5B, 0xC956, 0, 0, 0x7748, - 0x5F5A, 0x4540, 0x3059, 0xEF60, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E783[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0x4E75, 0, 0xC958, 0x5F5E, 0, 0, 0, 0x3128, - 0, 0xC959, 0, 0xC95A, 0xC95B, 0xC95C, 0xC95D, 0, - 0xC95E, 0x5F60, 0, 0, 0xC95F, 0x5F5F, 0, 0x5F5D, - 0, 0, 0, 0, 0xC960, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x5F58, 0, 0, 0, 0, 0, 0, - 0, 0x4B23, 0xC961, 0, 0, 0x5F62, 0, 0, -}; -static const unsigned short utf8_to_euc_E783_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0x4E75, 0, 0xEF66, 0x5F5E, 0, 0, 0, 0x3128, - 0, 0xEF67, 0, 0xEF68, 0x7749, 0xC95C, 0xC95D, 0, - 0x774A, 0x5F60, 0, 0, 0xEF69, 0x5F5F, 0, 0x5F5D, - 0, 0, 0, 0, 0x774B, 0, 0, 0, - 0, 0, 0, 0, 0xEF65, 0, 0, 0, - 0, 0x5F58, 0, 0, 0, 0, 0, 0, - 0, 0x4B23, 0xC961, 0, 0, 0x5F62, 0, 0, -}; -static const unsigned short utf8_to_euc_E784[] = { - 0, 0, 0, 0xC962, 0xC963, 0xC964, 0xC965, 0xC966, - 0, 0x5F61, 0, 0xC967, 0xC968, 0, 0, 0xC969, - 0, 0, 0, 0, 0x316B, 0, 0, 0, - 0, 0x5F64, 0x4A32, 0, 0x5F63, 0, 0xC96A, 0, - 0xC96B, 0x4C35, 0, 0, 0, 0, 0x3E47, 0, - 0, 0, 0, 0xC96C, 0, 0xC96D, 0, 0xC96E, - 0xC96F, 0xC970, 0, 0, 0, 0, 0x4133, 0, - 0xC971, 0, 0, 0, 0x3E46, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E784_x0213[] = { - 0, 0, 0, 0xEF6A, 0xEF6B, 0xC964, 0xEF6C, 0xEF6D, - 0xEF6E, 0x5F61, 0, 0xC967, 0xEF6F, 0, 0, 0x774C, - 0, 0, 0, 0, 0x316B, 0, 0, 0, - 0, 0x5F64, 0x4A32, 0, 0x5F63, 0, 0x774E, 0, - 0x774F, 0x4C35, 0, 0, 0, 0, 0x3E47, 0, - 0, 0, 0, 0x774D, 0, 0xC96D, 0x7750, 0xEF71, - 0x7751, 0xEF72, 0, 0, 0, 0, 0x4133, 0, - 0xC971, 0, 0, 0, 0x3E46, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E785[] = { - 0, 0xC972, 0, 0, 0, 0xC973, 0xC974, 0xC975, - 0, 0x4E7B, 0xC976, 0xC977, 0x5F6A, 0, 0x4079, 0, - 0xC978, 0, 0xC979, 0, 0, 0x5F66, 0x5F6B, 0xC97A, - 0, 0x316C, 0xC97B, 0, 0xC97C, 0, 0xC97D, 0, - 0xC97E, 0, 0x5F69, 0, 0x4761, 0x5F65, 0x5F68, 0x3E48, - 0xCA21, 0x4851, 0, 0, 0x5F6C, 0, 0x3C51, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xCA22, 0, 0, 0, 0x407A, 0, 0, -}; -static const unsigned short utf8_to_euc_E785_x0213[] = { - 0, 0xC972, 0, 0, 0, 0xC973, 0x7752, 0x7753, - 0, 0x4E7B, 0xEF74, 0xC977, 0x5F6A, 0, 0x4079, 0, - 0xEF73, 0x7754, 0x7756, 0xEF75, 0, 0x5F66, 0x5F6B, 0xC97A, - 0, 0x316C, 0xC97B, 0, 0x7757, 0, 0xEF76, 0, - 0x7758, 0, 0x5F69, 0, 0x4761, 0x5F65, 0x5F68, 0x3E48, - 0x7759, 0x4851, 0, 0, 0x5F6C, 0, 0x3C51, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xCA22, 0, 0, 0, 0x407A, 0, 0, -}; -static const unsigned short utf8_to_euc_E786[] = { - 0xCA23, 0, 0, 0, 0x5F6F, 0xCA24, 0, 0xCA25, - 0x5F67, 0, 0x3727, 0, 0xCA26, 0, 0, 0x5F6D, - 0, 0, 0xCA27, 0, 0x4D50, 0x5F70, 0, 0, - 0, 0x7426, 0xCA28, 0xCA29, 0, 0, 0, 0x3D4F, - 0xCA2A, 0, 0xCA2B, 0, 0, 0, 0, 0, - 0x5F71, 0, 0, 0, 0x5F72, 0, 0, 0xCA2C, - 0xCA2D, 0x472E, 0xCA2E, 0xCA2F, 0, 0, 0, 0, - 0, 0x5F74, 0xCA30, 0, 0, 0, 0x5F75, 0xCA31, -}; -static const unsigned short utf8_to_euc_E786_x0213[] = { - 0xEF79, 0, 0, 0, 0x5F6F, 0x775B, 0, 0x775C, - 0x5F67, 0, 0x3727, 0, 0xCA26, 0, 0, 0x5F6D, - 0, 0, 0x775D, 0, 0x4D50, 0x5F70, 0xEF78, 0, - 0, 0x7426, 0xCA28, 0xEF7A, 0, 0, 0, 0x3D4F, - 0xEF7B, 0, 0xEF7C, 0, 0, 0, 0, 0, - 0x5F71, 0, 0, 0, 0x5F72, 0, 0xEF7D, 0xEF7E, - 0xCA2D, 0x472E, 0xCA2E, 0xF021, 0, 0, 0, 0, - 0, 0x5F74, 0x775F, 0, 0, 0, 0x5F75, 0xCA31, -}; -static const unsigned short utf8_to_euc_E787[] = { - 0xCA32, 0xCA33, 0, 0x4733, 0xCA34, 0, 0, 0, - 0x4575, 0x5F77, 0, 0xCA35, 0xCA36, 0, 0x5F79, 0, - 0x4E55, 0, 0x5F76, 0xCA37, 0x5F78, 0x316D, 0xCA38, 0x5F73, - 0, 0xCA39, 0xCA3A, 0, 0xCA3B, 0, 0, 0x535B, - 0x5F7A, 0, 0, 0, 0, 0x4167, 0x3B38, 0x5F7C, - 0, 0, 0, 0, 0x5F7B, 0x3F24, 0x5259, 0, - 0, 0, 0, 0, 0, 0x5F7D, 0, 0, - 0xCA3C, 0x6021, 0, 0x5F6E, 0x5F7E, 0, 0xCA3D, 0x6022, -}; -static const unsigned short utf8_to_euc_E787_x0213[] = { - 0xCA32, 0x775E, 0, 0x4733, 0x7760, 0, 0, 0, - 0x4575, 0x5F77, 0, 0xF023, 0xCA36, 0, 0x5F79, 0, - 0x4E55, 0, 0x5F76, 0xF024, 0x5F78, 0x316D, 0xCA38, 0x5F73, - 0, 0xF025, 0xCA3A, 0, 0xF026, 0, 0, 0x535B, - 0x5F7A, 0, 0, 0, 0, 0x4167, 0x3B38, 0x5F7C, - 0, 0, 0, 0, 0x5F7B, 0x3F24, 0x5259, 0, - 0, 0, 0, 0, 0, 0x5F7D, 0, 0, - 0xCA3C, 0x6021, 0, 0x5F6E, 0x5F7E, 0, 0x7761, 0x6022, -}; -static const unsigned short utf8_to_euc_E788[] = { - 0xCA3E, 0, 0, 0, 0, 0, 0x477A, 0xCA3F, - 0xCA40, 0xCA41, 0, 0, 0, 0x6023, 0, 0, - 0x6024, 0, 0, 0xCA42, 0, 0, 0, 0xCA43, - 0, 0, 0xCA44, 0x6025, 0, 0xCA45, 0, 0xCA46, - 0, 0, 0, 0, 0xCA47, 0, 0, 0, - 0x6026, 0, 0x445E, 0xCA48, 0x6028, 0x6027, 0, 0xCA49, - 0x6029, 0, 0x602A, 0, 0xCA4A, 0x3C5F, 0x4963, 0, - 0xCA4B, 0xCA4C, 0x4C6C, 0x602B, 0x602C, 0x4156, 0x3C24, 0x602D, -}; -static const unsigned short utf8_to_euc_E788_x0213[] = { - 0x7762, 0, 0, 0, 0, 0, 0x477A, 0xF027, - 0xCA40, 0xCA41, 0, 0, 0, 0x6023, 0, 0, - 0x6024, 0, 0, 0xCA42, 0, 0x7763, 0, 0xCA43, - 0, 0, 0xCA44, 0x6025, 0, 0xCA45, 0, 0xCA46, - 0, 0, 0, 0, 0xCA47, 0, 0, 0, - 0x6026, 0, 0x445E, 0xF02A, 0x6028, 0x6027, 0, 0xCA49, - 0x6029, 0, 0x602A, 0, 0xF02B, 0x3C5F, 0x4963, 0, - 0xF02C, 0xF02D, 0x4C6C, 0x602B, 0x602C, 0x4156, 0x3C24, 0x602D, -}; -static const unsigned short utf8_to_euc_E789[] = { - 0x602E, 0xCA4D, 0xCA4E, 0xCA4F, 0, 0xCA50, 0x602F, 0x4A52, - 0x4847, 0, 0, 0x6030, 0x4757, 0, 0xCA51, 0xCA52, - 0xCA53, 0, 0x442D, 0xCA54, 0, 0xCA55, 0xCA56, 0, - 0x6031, 0x3267, 0xCA57, 0x356D, 0xCA58, 0x4C46, 0xCA59, 0x4C36, - 0xCA5A, 0x3234, 0x4F34, 0xCA5B, 0, 0, 0, 0x4B52, - 0xCA5C, 0x4A2A, 0, 0xCA5D, 0, 0, 0xCA5E, 0xCA5F, - 0, 0xCA60, 0x4037, 0, 0x6032, 0, 0, 0xCA61, - 0xCA62, 0x4643, 0, 0xCA63, 0xCA64, 0x3823, 0x6033, 0xCA65, -}; -static const unsigned short utf8_to_euc_E789_x0213[] = { - 0x602E, 0xCA4D, 0xF02F, 0xCA4F, 0, 0xCA50, 0x602F, 0x4A52, - 0x4847, 0, 0, 0x6030, 0x4757, 0, 0xCA51, 0xCA52, - 0xCA53, 0, 0x442D, 0xF030, 0, 0x7764, 0x7765, 0xF031, - 0x6031, 0x3267, 0xCA57, 0x356D, 0xCA58, 0x4C46, 0xCA59, 0x4C36, - 0xCA5A, 0x3234, 0x4F34, 0xF032, 0, 0, 0, 0x4B52, - 0xCA5C, 0x4A2A, 0, 0xCA5D, 0, 0, 0xF034, 0xF035, - 0, 0xCA60, 0x4037, 0, 0x6032, 0, 0, 0xCA61, - 0xF036, 0x4643, 0, 0xCA63, 0xCA64, 0x3823, 0x6033, 0xF037, -}; -static const unsigned short utf8_to_euc_E78A[] = { - 0x3A54, 0x6035, 0x6034, 0, 0xCA66, 0, 0, 0x6036, - 0, 0xCA67, 0, 0, 0, 0xCA68, 0xCA69, 0, - 0, 0, 0x6037, 0xCA6A, 0, 0, 0x6038, 0, - 0, 0, 0, 0xCA6B, 0, 0, 0, 0, - 0x353E, 0, 0x6039, 0, 0, 0, 0, 0x603A, - 0xCA6C, 0, 0, 0, 0x3824, 0xCA6D, 0xCA6E, 0x4848, - 0, 0xCA6F, 0x603C, 0, 0xCA70, 0, 0x3E75, 0, - 0, 0x603B, 0, 0, 0, 0, 0xCA71, 0, -}; -static const unsigned short utf8_to_euc_E78A_x0213[] = { - 0x3A54, 0x6035, 0x6034, 0, 0xCA66, 0, 0, 0x6036, - 0, 0xCA67, 0, 0, 0, 0x7767, 0xF038, 0, - 0, 0, 0x6037, 0xCA6A, 0, 0, 0x6038, 0, - 0, 0, 0, 0x7768, 0, 0, 0, 0, - 0x353E, 0, 0x6039, 0, 0, 0, 0, 0x603A, - 0xCA6C, 0, 0, 0, 0x3824, 0xF03A, 0xF03B, 0x4848, - 0xF03C, 0xF03D, 0x603C, 0, 0xCA70, 0, 0x3E75, 0, - 0, 0x603B, 0, 0, 0, 0, 0x7769, 0, -}; -static const unsigned short utf8_to_euc_E78B[] = { - 0, 0xCA72, 0x3638, 0x603D, 0x603F, 0, 0x603E, 0xCA73, - 0, 0xCA74, 0, 0, 0xCA75, 0, 0x6040, 0, - 0x3851, 0, 0x6041, 0, 0, 0xCA76, 0xCA77, 0x3669, - 0xCA78, 0x4140, 0, 0x397D, 0, 0, 0, 0xCA79, - 0x6043, 0x6044, 0x6042, 0, 0, 0xCA7A, 0, 0, - 0, 0x3C6D, 0, 0, 0x4648, 0x3639, 0, 0, - 0, 0, 0, 0xCA7B, 0xCA7C, 0, 0, 0x6046, - 0x432C, 0x6045, 0xCA7D, 0xCA7E, 0x4F35, 0x4762, 0xCB21, 0, -}; -static const unsigned short utf8_to_euc_E78B_x0213[] = { - 0x776A, 0xF03E, 0x3638, 0x603D, 0x603F, 0, 0x603E, 0xCA73, - 0, 0xCA74, 0, 0, 0xF040, 0, 0x6040, 0, - 0x3851, 0, 0x6041, 0, 0, 0xCA76, 0xCA77, 0x3669, - 0xCA78, 0x4140, 0, 0x397D, 0, 0, 0, 0xCA79, - 0x6043, 0x6044, 0x6042, 0, 0, 0xCA7A, 0, 0, - 0, 0x3C6D, 0, 0, 0x4648, 0x3639, 0, 0, - 0, 0, 0, 0xF043, 0xCA7C, 0, 0, 0x6046, - 0x432C, 0x6045, 0xF044, 0x776B, 0x4F35, 0x4762, 0xCB21, 0, -}; -static const unsigned short utf8_to_euc_E78C[] = { - 0, 0, 0xCB22, 0, 0xCB23, 0xCB24, 0, 0xCB25, - 0, 0, 0x6049, 0xCB26, 0, 0xCB27, 0, 0, - 0, 0, 0xCB28, 0xCB29, 0, 0, 0x604B, 0x6048, - 0xCB2A, 0xCB2B, 0, 0x4C54, 0x604A, 0x604C, 0xCB2C, 0x4E44, - 0, 0, 0xCB2D, 0, 0xCB2E, 0x6050, 0, 0xCB2F, - 0xCB30, 0x604F, 0x4376, 0x472D, 0xCB31, 0, 0x3825, 0x604E, - 0, 0xCB32, 0xCB33, 0, 0x604D, 0xCB34, 0x4D31, 0x4D32, - 0, 0, 0xCB35, 0xCB36, 0, 0xCB37, 0x6051, 0x316E, -}; -static const unsigned short utf8_to_euc_E78C_x0213[] = { - 0, 0, 0xCB22, 0, 0xCB23, 0xCB24, 0, 0xF045, - 0, 0, 0x6049, 0xCB26, 0, 0xCB27, 0, 0, - 0, 0, 0xF046, 0xCB29, 0, 0, 0x604B, 0x6048, - 0xF047, 0xF048, 0, 0x4C54, 0x604A, 0x604C, 0xCB2C, 0x4E44, - 0, 0, 0xCB2D, 0, 0, 0x6050, 0, 0x776D, - 0x776E, 0x604F, 0x4376, 0x472D, 0xF04B, 0, 0x3825, 0x604E, - 0, 0xF04C, 0xCB33, 0xF04D, 0x604D, 0xCB34, 0x4D31, 0x4D32, - 0, 0xF04A, 0xCB35, 0xCB36, 0, 0xF04E, 0x6051, 0x316E, -}; -static const unsigned short utf8_to_euc_E78D[] = { - 0, 0, 0, 0xCB38, 0x3976, 0x3B62, 0, 0, - 0, 0, 0, 0, 0, 0xCB39, 0x6052, 0x6053, - 0xCB3A, 0, 0xCB3B, 0, 0, 0, 0xCB3C, 0x6055, - 0xCB3D, 0, 0, 0, 0, 0xCB3E, 0xCB3F, 0xCB40, - 0xCB41, 0, 0, 0x3D43, 0, 0, 0xCB42, 0xCB43, - 0x6057, 0xCB44, 0x6056, 0xCB45, 0xCB46, 0, 0xCB47, 0xCB48, - 0x6058, 0xCB49, 0x334D, 0, 0, 0x605A, 0, 0xCB4A, - 0x6059, 0xCB4B, 0x605C, 0x605B, 0xCB4C, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E78D_x0213[] = { - 0, 0, 0, 0xCB38, 0x3976, 0x3B62, 0, 0, - 0, 0, 0, 0, 0, 0xCB39, 0x6052, 0x6053, - 0x7770, 0, 0xF04F, 0, 0, 0, 0xCB3C, 0x6055, - 0xCB3D, 0, 0, 0, 0, 0xCB3E, 0xCB3F, 0xCB40, - 0xCB41, 0, 0, 0x3D43, 0, 0, 0x7771, 0xCB43, - 0x6057, 0xCB44, 0x6056, 0xF051, 0xF052, 0, 0xF054, 0xF055, - 0x6058, 0xF056, 0x334D, 0, 0, 0x605A, 0, 0xF057, - 0x6059, 0xCB4B, 0x605C, 0x605B, 0x7772, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E78E[] = { - 0xCB4D, 0xCB4E, 0, 0xCB4F, 0x383C, 0xCB50, 0xCB51, 0x4E28, - 0, 0x364C, 0, 0x3226, 0, 0, 0xCB52, 0, - 0xCB53, 0, 0, 0xCB54, 0, 0xCB55, 0x366A, 0xCB56, - 0xCB57, 0, 0, 0, 0xCB58, 0, 0xCB59, 0xCB5A, - 0xCB5B, 0, 0xCB5C, 0, 0, 0xCB5D, 0xCB5E, 0, - 0, 0x3461, 0xCB5F, 0xCB60, 0, 0xCB61, 0, 0, - 0, 0, 0x4E68, 0x605E, 0, 0xCB62, 0, 0xCB63, - 0, 0xCB64, 0, 0x6060, 0xCB65, 0xCB66, 0, 0xCB67, -}; -static const unsigned short utf8_to_euc_E78E_x0213[] = { - 0xCB4D, 0xF058, 0, 0xCB4F, 0x383C, 0xF059, 0xCB51, 0x4E28, - 0, 0x364C, 0xF05A, 0x3226, 0, 0, 0xCB52, 0, - 0xCB53, 0, 0, 0xCB54, 0xF05B, 0x7773, 0x366A, 0xCB56, - 0xF05C, 0, 0, 0, 0xF05D, 0, 0xF05E, 0x7774, - 0x7775, 0, 0x7776, 0, 0, 0xF05F, 0x7777, 0, - 0xF060, 0x3461, 0xCB5F, 0x7778, 0, 0xCB61, 0, 0, - 0, 0, 0x4E68, 0x605E, 0, 0xF061, 0, 0xF062, - 0, 0xF063, 0, 0x6060, 0xF064, 0, 0, 0xF065, -}; -static const unsigned short utf8_to_euc_E78F[] = { - 0x6061, 0, 0x3251, 0, 0, 0xCB68, 0xCB69, 0, - 0x605D, 0xCB6A, 0x3B39, 0xCB6B, 0xCB6C, 0x4441, 0x605F, 0xCB6D, - 0, 0, 0xCB6E, 0xCB6F, 0, 0, 0xCB70, 0, - 0, 0xCB71, 0, 0, 0, 0xCB72, 0x6064, 0, - 0x3C6E, 0xCB73, 0, 0xCB74, 0, 0x6062, 0xCB75, 0xCB76, - 0, 0xCB77, 0x373E, 0, 0, 0x4849, 0x6063, 0, - 0, 0x607E, 0, 0, 0xCB78, 0xCB79, 0, 0xCB7A, - 0x6069, 0xCB7B, 0xCB7C, 0xCB7D, 0, 0xCB7E, 0x383D, 0xCC21, -}; -static const unsigned short utf8_to_euc_E78F_x0213[] = { - 0x6061, 0, 0x3251, 0, 0, 0xF066, 0xCB69, 0, - 0x605D, 0x7779, 0x3B39, 0xF067, 0xCB6C, 0x4441, 0x605F, 0x777A, - 0, 0, 0, 0xCB6F, 0, 0, 0x777B, 0, - 0, 0x777C, 0, 0, 0, 0xCB72, 0x6064, 0, - 0x3C6E, 0xF068, 0, 0x777D, 0, 0x6062, 0xCB75, 0xF069, - 0, 0x777E, 0x373E, 0, 0, 0x4849, 0x6063, 0, - 0, 0x607E, 0, 0, 0xCB78, 0, 0, 0xCB7A, - 0x6069, 0xF06A, 0xF06C, 0xCB7D, 0, 0xCB7E, 0x383D, 0xCC21, -}; -static const unsigned short utf8_to_euc_E790[] = { - 0xCC22, 0xCC23, 0, 0x3565, 0xCC24, 0x6066, 0x4D7D, 0xCC25, - 0, 0x4E30, 0xCC26, 0, 0, 0, 0, 0, - 0, 0xCC27, 0, 0, 0, 0, 0, 0, - 0, 0, 0xCC28, 0xCC29, 0, 0, 0, 0, - 0, 0, 0x4276, 0, 0xCC2A, 0x6068, 0xCC2B, 0, - 0xCC2C, 0xCC2D, 0xCC2E, 0xCC2F, 0xCC30, 0xCC31, 0xCC32, 0xCC33, - 0xCC34, 0xCC35, 0x606A, 0x4E56, 0x3657, 0x487C, 0x474A, 0, - 0, 0xCC36, 0x606B, 0, 0, 0, 0, 0x606D, -}; -static const unsigned short utf8_to_euc_E790_x0213[] = { - 0xCC22, 0xF06D, 0, 0x3565, 0xCC24, 0x6066, 0x4D7D, 0x7821, - 0, 0x4E30, 0x7822, 0, 0, 0, 0, 0, - 0, 0xCC27, 0, 0xF06B, 0, 0, 0, 0, - 0, 0, 0x7823, 0x7824, 0, 0, 0, 0, - 0, 0, 0x4276, 0, 0xF06E, 0x6068, 0x7826, 0, - 0x7827, 0, 0x7828, 0x7829, 0x782A, 0xCC31, 0x782B, 0x782C, - 0x782D, 0xF06F, 0x606A, 0x4E56, 0x3657, 0x487C, 0x474A, 0, - 0, 0xF070, 0x606B, 0, 0, 0, 0, 0x606D, -}; -static const unsigned short utf8_to_euc_E791[] = { - 0xCC37, 0x6070, 0, 0xCC38, 0xCC39, 0, 0xCC3A, 0xCC3B, - 0, 0, 0, 0xCC3C, 0, 0xCC3D, 0, 0, - 0, 0xCC3E, 0xCC3F, 0, 0, 0x606C, 0, 0xCC40, - 0, 0x606F, 0x386A, 0x314D, 0x6071, 0xCC41, 0x3F70, 0x606E, - 0x4E5C, 0, 0xCC42, 0x6074, 0x7424, 0, 0xCC43, 0xCC44, - 0xCC45, 0x6072, 0x6075, 0xCC46, 0, 0xCC47, 0xCC48, 0x6067, - 0x6073, 0xCC49, 0xCC4A, 0x3A3C, 0, 0, 0x6076, 0, - 0, 0, 0, 0, 0, 0, 0x6077, 0, -}; -static const unsigned short utf8_to_euc_E791_x0213[] = { - 0xF072, 0x6070, 0, 0xF073, 0x782E, 0, 0x782F, 0x7830, - 0, 0, 0, 0x7831, 0, 0xF074, 0, 0, - 0, 0xCC3E, 0xF075, 0xF071, 0, 0x606C, 0, 0x7832, - 0, 0x606F, 0x386A, 0x314D, 0x6071, 0xF076, 0x3F70, 0x606E, - 0x4E5C, 0, 0x7833, 0x6074, 0x7424, 0, 0xCC43, 0xCC44, - 0xCC45, 0x6072, 0x6075, 0x7834, 0, 0x7835, 0xCC48, 0x6067, - 0x6073, 0xF077, 0xCC4A, 0x3A3C, 0, 0, 0x6076, 0, - 0, 0, 0, 0, 0, 0, 0x6077, 0, -}; -static const unsigned short utf8_to_euc_E792[] = { - 0xCC4B, 0xCC4C, 0, 0x4D7E, 0, 0xCC4D, 0xCC4E, 0xCC4F, - 0, 0xCC50, 0, 0x6078, 0, 0, 0, 0xCC51, - 0xCC52, 0xCC53, 0xCC54, 0, 0, 0, 0, 0, - 0xCC55, 0xCC56, 0xCC57, 0, 0xCC58, 0, 0x6079, 0xCC59, - 0xCC5A, 0xCC5B, 0x6065, 0xCC5C, 0, 0, 0xCC5D, 0x607A, - 0xCC5E, 0xCC5F, 0xCC60, 0xCC61, 0, 0, 0xCC62, 0xCC63, - 0x3444, 0xCC64, 0xCC65, 0, 0, 0xCC66, 0, 0, - 0, 0xCC67, 0, 0xCC68, 0, 0x3C25, 0, 0xCC69, -}; -static const unsigned short utf8_to_euc_E792_x0213[] = { - 0xCC4B, 0xF078, 0, 0x4D7E, 0, 0xF079, 0x7836, 0x7837, - 0xF07A, 0x7838, 0, 0x6078, 0, 0, 0, 0xCC51, - 0x783D, 0xCC53, 0xF07C, 0, 0, 0, 0, 0xF07D, - 0x7839, 0xF07E, 0xCC57, 0, 0x783A, 0, 0x6079, 0x783B, - 0xF121, 0xF122, 0x6065, 0x783C, 0, 0xF123, 0x783E, 0x607A, - 0x783F, 0x7840, 0xF124, 0xF125, 0, 0, 0xCC62, 0xCC63, - 0x3444, 0xCC64, 0xCC65, 0, 0, 0x7841, 0, 0, - 0, 0xF126, 0xF128, 0xF127, 0, 0x3C25, 0, 0x7842, -}; -static const unsigned short utf8_to_euc_E793[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0xCC6A, 0xCC6B, 0x607B, 0, 0xCC6C, 0, 0, 0x607C, - 0xCC6D, 0, 0, 0xCC6E, 0x607D, 0, 0, 0, - 0xCC6F, 0, 0xCC70, 0xCC71, 0x313B, 0, 0xCC72, 0xCC73, - 0x6121, 0, 0x493B, 0x6122, 0xCC74, 0, 0x3424, 0x6123, - 0xCC75, 0x6124, 0xCC76, 0xCC77, 0, 0, 0x6125, 0xCC78, - 0x6127, 0x6128, 0x6126, 0, 0xCC79, 0, 0x4953, 0x612A, - 0x6129, 0, 0xCC7A, 0xCC7B, 0xCC7C, 0, 0, 0xCC7D, -}; -static const unsigned short utf8_to_euc_E793_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0x7843, 0x7844, 0x607B, 0, 0xCC6C, 0, 0, 0x607C, - 0xCC6D, 0, 0, 0xCC6E, 0x607D, 0, 0xF129, 0, - 0xF12A, 0, 0x7845, 0xCC71, 0x313B, 0, 0xF12B, 0xCC73, - 0x6121, 0, 0x493B, 0x6122, 0xCC74, 0, 0x3424, 0x6123, - 0xCC75, 0x6124, 0xCC76, 0xF12D, 0, 0, 0x6125, 0xF12C, - 0x6127, 0x6128, 0x6126, 0, 0xCC79, 0, 0x4953, 0x612A, - 0x6129, 0, 0xF12F, 0xCC7B, 0xCC7C, 0, 0, 0x7846, -}; -static const unsigned short utf8_to_euc_E794[] = { - 0, 0xF450, 0, 0x612C, 0x612B, 0x612D, 0xCC7E, 0, - 0, 0, 0, 0, 0x612E, 0x6130, 0x612F, 0, - 0, 0x3979, 0xCD21, 0x6132, 0, 0x6131, 0xCD22, 0xCD23, - 0x3445, 0, 0x3F53, 0, 0x453C, 0, 0x6133, 0x4038, - 0xCD24, 0xCD25, 0, 0x3B3A, 0xCD26, 0x3179, 0x6134, 0xCD27, - 0x4D51, 0xCD28, 0xCD29, 0x4A63, 0x6135, 0, 0, 0xCD2A, - 0x4544, 0x4D33, 0x3943, 0x3F3D, 0, 0, 0xCD2B, 0x434B, - 0x5234, 0xCD2C, 0x442E, 0x3268, 0x6136, 0xCD2D, 0xCD2E, 0xCD2F, -}; -static const unsigned short utf8_to_euc_E794_x0213[] = { - 0, 0x7847, 0, 0x612C, 0x612B, 0x612D, 0xCC7E, 0, - 0, 0, 0, 0, 0x612E, 0x6130, 0x612F, 0, - 0, 0x3979, 0xCD21, 0x6132, 0, 0x6131, 0xCD22, 0x7848, - 0x3445, 0, 0x3F53, 0, 0x453C, 0, 0x6133, 0x4038, - 0xF131, 0xCD25, 0, 0x3B3A, 0xF132, 0x3179, 0x6134, 0xCD27, - 0x4D51, 0xCD28, 0xF133, 0x4A63, 0x6135, 0, 0, 0x7849, - 0x4544, 0x4D33, 0x3943, 0x3F3D, 0, 0, 0xCD2B, 0x434B, - 0x5234, 0xCD2C, 0x442E, 0x3268, 0x6136, 0xF136, 0xF137, 0xCD2F, -}; -static const unsigned short utf8_to_euc_E795[] = { - 0xCD30, 0, 0, 0xCD31, 0x6137, 0, 0x613C, 0xCD32, - 0xCD33, 0x613A, 0x6139, 0x5A42, 0x3326, 0x6138, 0xCD34, 0x305A, - 0xCD35, 0x482A, 0xCD36, 0, 0x484A, 0, 0, 0xCD37, - 0, 0x4E31, 0x613D, 0x613B, 0x435C, 0x4026, 0xCD38, 0xCD39, - 0x482B, 0xCD3A, 0x492D, 0, 0x613F, 0x4E2C, 0x374D, 0x6140, - 0, 0x613E, 0x4856, 0x6141, 0, 0x6142, 0, 0xCD3B, - 0x305B, 0xCD3C, 0, 0x3E76, 0x6147, 0, 0x6144, 0x466D, - 0x6143, 0xCD3D, 0xCD3E, 0xCD3F, 0xCD40, 0xCD41, 0xCD42, 0x3526, -}; -static const unsigned short utf8_to_euc_E795_x0213[] = { - 0xF138, 0, 0, 0xCD31, 0x6137, 0, 0x613C, 0xCD32, - 0xF139, 0x613A, 0x6139, 0x5A42, 0x3326, 0x6138, 0xF13A, 0x305A, - 0xF13B, 0x482A, 0xF13C, 0, 0x484A, 0, 0, 0xCD37, - 0, 0x4E31, 0x613D, 0x613B, 0x435C, 0x4026, 0xCD38, 0xCD39, - 0x482B, 0xCD3A, 0x492D, 0, 0x613F, 0x4E2C, 0x374D, 0x6140, - 0, 0x613E, 0x4856, 0x6141, 0xF13D, 0x6142, 0, 0x784A, - 0x305B, 0xF13F, 0xF13E, 0x3E76, 0x6147, 0, 0x6144, 0x466D, - 0x6143, 0x784B, 0xF140, 0xCD3F, 0xCD40, 0xF141, 0xF142, 0x3526, -}; -static const unsigned short utf8_to_euc_E796[] = { - 0, 0xCD43, 0x614A, 0, 0, 0xCD44, 0x6145, 0x6146, - 0, 0x6149, 0x6148, 0x4925, 0, 0, 0x4142, 0x4141, - 0xCD45, 0x353F, 0xCD46, 0xCD47, 0x614B, 0xCD48, 0, 0, - 0, 0xCD49, 0x614C, 0, 0xCD4A, 0x614D, 0, 0, - 0, 0, 0xCD4B, 0x614F, 0xCD4C, 0x614E, 0, 0, - 0, 0, 0, 0x3156, 0, 0, 0, 0, - 0, 0x6157, 0x4868, 0x6151, 0xCD4D, 0x6153, 0, 0, - 0x6155, 0x3F3E, 0xCD4E, 0, 0x6156, 0x6154, 0x3C40, 0xCD4F, -}; -static const unsigned short utf8_to_euc_E796_x0213[] = { - 0, 0xF143, 0x614A, 0, 0, 0xCD44, 0x6145, 0x6146, - 0, 0x6149, 0x6148, 0x4925, 0xF145, 0, 0x4142, 0x4141, - 0xCD45, 0x353F, 0x784C, 0xCD47, 0x614B, 0xCD48, 0, 0, - 0, 0xCD49, 0x614C, 0, 0xCD4A, 0x614D, 0, 0, - 0, 0, 0xF147, 0x614F, 0xCD4C, 0x614E, 0, 0, - 0, 0, 0, 0x3156, 0, 0, 0, 0, - 0xF149, 0x6157, 0x4868, 0x6151, 0xCD4D, 0x6153, 0, 0xF14A, - 0x6155, 0x3F3E, 0xCD4E, 0, 0x6156, 0x6154, 0x3C40, 0xF14B, -}; -static const unsigned short utf8_to_euc_E797[] = { - 0xCD50, 0xCD51, 0x6150, 0x6152, 0xCD52, 0x4942, 0xCD53, 0x3E49, - 0, 0, 0x6159, 0, 0xCD54, 0x6158, 0xCD55, 0xCD56, - 0, 0, 0x615A, 0, 0x3C26, 0x3A2F, 0, 0xCD57, - 0x4577, 0x615B, 0, 0x444B, 0xCD58, 0, 0x615D, 0xCD59, - 0xCD5A, 0xCD5B, 0x4E21, 0x615C, 0xCD5C, 0, 0, 0xCD5D, - 0, 0x4169, 0, 0, 0xCD5E, 0, 0xCD5F, 0xCD60, - 0x6162, 0xCD61, 0x6164, 0x6165, 0x4354, 0, 0, 0, - 0, 0xCD62, 0x6163, 0, 0x6160, 0, 0x615E, 0x615F, -}; -static const unsigned short utf8_to_euc_E797_x0213[] = { - 0xF14C, 0xCD51, 0x6150, 0x6152, 0xCD52, 0x4942, 0xF14D, 0x3E49, - 0, 0, 0x6159, 0, 0xCD54, 0x6158, 0x784E, 0xF14E, - 0, 0, 0x615A, 0xF14F, 0x3C26, 0x3A2F, 0, 0xCD57, - 0x4577, 0x615B, 0, 0x444B, 0xCD58, 0xF150, 0x615D, 0xF151, - 0xF152, 0xCD5B, 0x4E21, 0x615C, 0x784F, 0, 0, 0xF153, - 0, 0x4169, 0, 0, 0xF154, 0, 0xF155, 0xCD60, - 0x6162, 0xF156, 0x6164, 0x6165, 0x4354, 0, 0, 0, - 0, 0xF157, 0x6163, 0, 0x6160, 0, 0x615E, 0x615F, -}; -static const unsigned short utf8_to_euc_E798[] = { - 0xCD63, 0x6161, 0xCD64, 0xCD65, 0xCD66, 0, 0, 0xCD67, - 0xCD68, 0x6168, 0xCD69, 0x6166, 0xCD6A, 0x6167, 0, 0xCD6B, - 0, 0, 0xCD6C, 0xCD6D, 0, 0xCD6E, 0xCD6F, 0, - 0, 0xCD70, 0, 0xCD71, 0xCD72, 0xCD73, 0xCD74, 0x6169, - 0x616B, 0x616C, 0x616D, 0xCD75, 0x616E, 0xCD76, 0xCD77, 0x616A, - 0, 0xCD78, 0, 0, 0, 0xCD79, 0, 0, - 0x6170, 0, 0xCD7A, 0xCD7B, 0x616F, 0xCD7C, 0, 0, - 0xCD7D, 0xCD7E, 0xCE21, 0x6171, 0xCE22, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E798_x0213[] = { - 0x7850, 0x6161, 0x7851, 0xF158, 0xCD66, 0, 0, 0xF15A, - 0x7852, 0x6168, 0xCD69, 0x6166, 0xCD6A, 0x6167, 0, 0xF15B, - 0, 0, 0xCD6C, 0xF15E, 0, 0x7853, 0x7854, 0, - 0xF159, 0x7855, 0, 0xF15F, 0xF160, 0xCD73, 0x7856, 0x6169, - 0x616B, 0x616C, 0x616D, 0xCD75, 0x616E, 0xF162, 0x7E7D, 0x616A, - 0xF163, 0xCD78, 0, 0, 0, 0x7857, 0, 0, - 0x6170, 0, 0xCD7A, 0xF165, 0x616F, 0x7858, 0, 0, - 0xCD7D, 0xCD7E, 0xCE21, 0x6171, 0xF164, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E799[] = { - 0xCE24, 0xCE25, 0x4E45, 0xCE26, 0xCE27, 0xCE28, 0x6174, 0x6172, - 0x6173, 0xCE29, 0xCE23, 0xCE2A, 0x3462, 0, 0, 0, - 0, 0, 0x4C7E, 0, 0, 0xCE2B, 0x4A4A, 0, - 0x6176, 0xCE2C, 0, 0, 0x6175, 0, 0, 0xCE2D, - 0, 0x6177, 0x6178, 0, 0xCE2E, 0xCE2F, 0, 0x617C, - 0x6179, 0x617A, 0x617B, 0, 0x617D, 0xCE30, 0xCE31, 0xCE32, - 0x617E, 0xCE33, 0x6221, 0, 0xCE34, 0, 0x6222, 0, - 0x6223, 0, 0x482F, 0x4550, 0x6224, 0x4772, 0x4934, 0, -}; -static const unsigned short utf8_to_euc_E799_x0213[] = { - 0xCE24, 0xF168, 0x4E45, 0x7859, 0xCE27, 0xCE28, 0x6174, 0x6172, - 0x6173, 0xF16A, 0xCE23, 0x785A, 0x3462, 0, 0, 0, - 0, 0, 0x4C7E, 0, 0, 0xF16B, 0x4A4A, 0, - 0x6176, 0xCE2C, 0, 0, 0x6175, 0, 0, 0xCE2D, - 0, 0x6177, 0x6178, 0, 0x785B, 0x785C, 0, 0x617C, - 0x6179, 0x617A, 0x617B, 0, 0x617D, 0x785D, 0xF16D, 0x785E, - 0x617E, 0x785F, 0x6221, 0, 0xCE34, 0, 0x6222, 0, - 0x6223, 0, 0x482F, 0x4550, 0x6224, 0x4772, 0x4934, 0, -}; -static const unsigned short utf8_to_euc_E79A[] = { - 0x6225, 0xCE35, 0xF451, 0x6226, 0x452A, 0xCE36, 0x3327, 0x3944, - 0x6227, 0, 0, 0x6228, 0xCE37, 0xCE38, 0x6229, 0, - 0x3B29, 0, 0, 0x622B, 0, 0xCE39, 0x622A, 0, - 0, 0x622C, 0x622D, 0xCE3A, 0xCE3B, 0xCE3C, 0xF452, 0xCE3D, - 0xCE3E, 0, 0xCE3F, 0xCE40, 0xCE41, 0xCE42, 0xCE43, 0xCE44, - 0xCE45, 0, 0xCE46, 0, 0, 0xCE47, 0x4869, 0, - 0x622E, 0, 0, 0, 0x622F, 0, 0, 0x7369, - 0x6230, 0x6231, 0x6232, 0, 0, 0xCE48, 0, 0x3B2E, -}; -static const unsigned short utf8_to_euc_E79A_x0213[] = { - 0x6225, 0x7860, 0, 0x6226, 0x452A, 0xCE36, 0x3327, 0x3944, - 0x6227, 0, 0, 0x6228, 0xCE37, 0xCE38, 0x6229, 0, - 0x3B29, 0, 0, 0x622B, 0, 0xF16E, 0x622A, 0, - 0, 0x622C, 0x622D, 0x7861, 0xF16F, 0x7862, 0x7863, 0xCE3D, - 0xF171, 0xF170, 0xCE3F, 0xCE40, 0xCE41, 0xCE42, 0x7864, 0xF172, - 0xF173, 0, 0x7865, 0, 0, 0xCE47, 0x4869, 0xF174, - 0x622E, 0, 0, 0, 0x622F, 0, 0x7866, 0x7369, - 0x6230, 0x6231, 0x6232, 0, 0, 0xCE48, 0, 0x3B2E, -}; -static const unsigned short utf8_to_euc_E79B[] = { - 0, 0xCE49, 0x6233, 0x4756, 0, 0xCE4A, 0x4B5F, 0, - 0x314E, 0xCE4B, 0x3157, 0xCE4C, 0xCE4D, 0x6234, 0xCE4E, 0, - 0, 0, 0x6236, 0, 0xCE4F, 0, 0x6235, 0x4570, - 0, 0xCE50, 0, 0x4039, 0x5D39, 0, 0x6237, 0x4C41, - 0xCE51, 0x6238, 0, 0x3446, 0x4857, 0x6239, 0xCE52, 0x623A, - 0xCE53, 0, 0x623B, 0, 0xCE54, 0, 0x4C5C, 0, - 0xCE55, 0xCE56, 0x4C55, 0, 0x443E, 0, 0xCE57, 0, - 0x416A, 0xCE58, 0, 0x623D, 0xCE59, 0, 0x3D62, 0, -}; -static const unsigned short utf8_to_euc_E79B_x0213[] = { - 0, 0xCE49, 0x6233, 0x4756, 0, 0x7867, 0x4B5F, 0, - 0x314E, 0xF176, 0x3157, 0xCE4C, 0x7868, 0x6234, 0x7869, 0, - 0, 0, 0x6236, 0, 0x786A, 0, 0x6235, 0x4570, - 0, 0xCE50, 0, 0x4039, 0x5D39, 0, 0x6237, 0x4C41, - 0xCE51, 0x6238, 0, 0x3446, 0x4857, 0x6239, 0x786B, 0x623A, - 0xF178, 0, 0x623B, 0, 0xF179, 0, 0x4C5C, 0, - 0xCE55, 0x786C, 0x4C55, 0, 0x443E, 0, 0xCE57, 0, - 0x416A, 0xCE58, 0, 0x623D, 0x786D, 0, 0x3D62, 0, -}; -static const unsigned short utf8_to_euc_E79C[] = { - 0xCE5A, 0x3E4A, 0, 0, 0x6240, 0, 0xCE5B, 0x623F, - 0x623E, 0x487D, 0xCE5C, 0x3447, 0x3829, 0, 0xCE5D, 0, - 0, 0, 0xCE5E, 0, 0xCE5F, 0xCE60, 0, 0xCE61, - 0, 0xCE62, 0xCE63, 0x6246, 0xCE64, 0, 0x6243, 0x3F3F, - 0x4C32, 0, 0xCE65, 0, 0x6242, 0x6244, 0x6245, 0, - 0xCE66, 0x6241, 0, 0, 0, 0xCE67, 0xCE68, 0xCE69, - 0, 0, 0, 0, 0xCE6A, 0xCE6B, 0xCE6C, 0x6247, - 0x6248, 0xCE6D, 0x442F, 0, 0x3463, 0xCE6E, 0xCE6F, 0, -}; -static const unsigned short utf8_to_euc_E79C_x0213[] = { - 0xCE5A, 0x3E4A, 0, 0, 0x6240, 0, 0xCE5B, 0x623F, - 0x623E, 0x487D, 0x786E, 0x3447, 0x3829, 0, 0xCE5D, 0, - 0, 0, 0xCE5E, 0, 0xCE5F, 0xCE60, 0, 0xF17B, - 0, 0x786F, 0xF17C, 0x6246, 0xCE64, 0, 0x6243, 0x3F3F, - 0x4C32, 0, 0xCE65, 0, 0x6242, 0x6244, 0x6245, 0, - 0xCE66, 0x6241, 0, 0, 0, 0xF17D, 0xCE68, 0xCE69, - 0, 0, 0, 0, 0x7870, 0xF17E, 0x7871, 0x6247, - 0x6248, 0xCE6D, 0x442F, 0, 0x3463, 0xCE6E, 0xCE6F, 0, -}; -static const unsigned short utf8_to_euc_E79D[] = { - 0x4365, 0, 0xCE70, 0, 0, 0xCE71, 0xCE72, 0x6249, - 0, 0, 0xCE73, 0, 0, 0xCE74, 0xCE75, 0xCE76, - 0, 0, 0xCE77, 0, 0, 0, 0xCE78, 0xCE79, - 0, 0, 0x624A, 0x624D, 0xCE7A, 0, 0xCE7B, 0xCE7C, - 0xCE7D, 0x3F67, 0xCE7E, 0x4644, 0xCF21, 0x624E, 0x4B53, 0xCF22, - 0x624B, 0, 0xCF23, 0x624C, 0xCF24, 0, 0, 0, - 0xCF25, 0, 0xCF26, 0xCF27, 0xCF28, 0, 0, 0, - 0, 0x6251, 0xCF29, 0, 0, 0xCF2A, 0x6250, 0x624F, -}; -static const unsigned short utf8_to_euc_E79D_x0213[] = { - 0x4365, 0, 0xCE70, 0, 0, 0xCE71, 0x7872, 0x6249, - 0, 0, 0xCE73, 0, 0, 0x7873, 0x7874, 0xCE76, - 0, 0, 0xCE77, 0, 0, 0, 0xCE78, 0xCE79, - 0xF225, 0, 0x624A, 0x624D, 0x7875, 0, 0xCE7B, 0x7876, - 0xF226, 0x3F67, 0x7877, 0x4644, 0xCF21, 0x624E, 0x4B53, 0xCF22, - 0x624B, 0, 0xF227, 0x624C, 0xCF24, 0, 0, 0, - 0xCF25, 0, 0xF229, 0xCF27, 0xCF28, 0, 0, 0, - 0, 0x6251, 0x7878, 0, 0xF22A, 0xF22B, 0x6250, 0x624F, -}; -static const unsigned short utf8_to_euc_E79E[] = { - 0xCF2B, 0, 0, 0, 0xCF2C, 0, 0, 0, - 0, 0, 0, 0x6253, 0xCF2D, 0xCF2E, 0x6252, 0, - 0, 0x6254, 0, 0, 0xCF2F, 0xCF30, 0xCF31, 0, - 0, 0, 0xCF32, 0, 0, 0, 0x6256, 0xCF33, - 0x6255, 0, 0xCF34, 0, 0, 0x4A4D, 0, 0xCF35, - 0, 0, 0xCF36, 0, 0x3D56, 0x4E46, 0xCF37, 0xCF38, - 0x6257, 0xCF39, 0, 0x4637, 0, 0xCF3A, 0x6258, 0, - 0, 0x6259, 0, 0x625D, 0x625B, 0x625C, 0xCF3B, 0x625A, -}; -static const unsigned short utf8_to_euc_E79E_x0213[] = { - 0x7879, 0, 0, 0, 0xCF2C, 0, 0, 0, - 0, 0, 0, 0x6253, 0xCF2D, 0xCF2E, 0x6252, 0, - 0, 0x6254, 0, 0, 0x787A, 0xCF30, 0xCF31, 0, - 0, 0, 0xF22E, 0, 0, 0, 0x6256, 0xF22F, - 0x6255, 0, 0xF230, 0, 0xF231, 0x4A4D, 0, 0xCF35, - 0, 0xF232, 0x787B, 0, 0x3D56, 0x4E46, 0xCF37, 0xCF38, - 0x6257, 0xCF39, 0, 0x4637, 0, 0xCF3A, 0x6258, 0, - 0, 0x6259, 0, 0x625D, 0x625B, 0x625C, 0xCF3B, 0x625A, -}; -static const unsigned short utf8_to_euc_E79F[] = { - 0, 0, 0, 0xCF3C, 0, 0, 0, 0x625E, - 0, 0xCF3D, 0, 0, 0, 0x625F, 0, 0, - 0, 0xCF3E, 0xCF3F, 0, 0, 0xCF40, 0, 0x6260, - 0, 0xCF41, 0x6261, 0x4C37, 0x6262, 0, 0xCF42, 0xCF43, - 0xCF44, 0, 0x4C70, 0x6263, 0xCF45, 0x434E, 0xCF46, 0x476A, - 0, 0x366B, 0xCF47, 0, 0xCF48, 0x433B, 0x6264, 0x363A, - 0xCF49, 0xCF4A, 0, 0x4050, 0xCF4B, 0, 0, 0, - 0xCF4C, 0, 0, 0xCF4D, 0x6265, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E79F_x0213[] = { - 0, 0, 0, 0xCF3C, 0, 0, 0, 0x625E, - 0, 0xCF3D, 0, 0, 0, 0x625F, 0, 0, - 0, 0xCF3E, 0xCF3F, 0, 0, 0xCF40, 0, 0x6260, - 0, 0xCF41, 0x6261, 0x4C37, 0x6262, 0, 0xF233, 0xF234, - 0x787C, 0, 0x4C70, 0x6263, 0xF235, 0x434E, 0xF236, 0x476A, - 0, 0x366B, 0xF237, 0, 0xF238, 0x433B, 0x6264, 0x363A, - 0xF23A, 0xCF4A, 0, 0x4050, 0xF23B, 0, 0, 0, - 0xCF4C, 0, 0, 0xF23C, 0x6265, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E7A0[] = { - 0, 0, 0x3A3D, 0, 0, 0xCF4E, 0xCF4F, 0, - 0, 0xCF50, 0, 0, 0x6266, 0xCF51, 0xCF52, 0, - 0, 0xCF53, 0x6267, 0, 0x3826, 0x3A55, 0, 0, - 0, 0, 0, 0, 0, 0xCF54, 0, 0, - 0x6269, 0xCF55, 0xCF56, 0xCF57, 0, 0x4556, 0x3A56, 0x354E, - 0, 0, 0, 0, 0, 0xCF58, 0xCF59, 0, - 0xCF5A, 0, 0x4B24, 0, 0x474B, 0xCF5B, 0, 0xCF5C, - 0, 0, 0x4557, 0, 0, 0, 0, 0x395C, -}; -static const unsigned short utf8_to_euc_E7A0_x0213[] = { - 0, 0, 0x3A3D, 0, 0, 0xF23E, 0xF23F, 0, - 0, 0xF240, 0, 0, 0x6266, 0xF241, 0xCF52, 0, - 0, 0xCF53, 0x6267, 0, 0x3826, 0x3A55, 0, 0, - 0, 0xF242, 0, 0, 0, 0xCF54, 0, 0, - 0x6269, 0xF243, 0xCF56, 0xCF57, 0, 0x4556, 0x3A56, 0x354E, - 0, 0, 0, 0, 0xF244, 0x787D, 0xCF59, 0, - 0xCF5A, 0, 0x4B24, 0, 0x474B, 0xCF5B, 0, 0xCF5C, - 0, 0, 0x4557, 0, 0, 0, 0, 0x395C, -}; -static const unsigned short utf8_to_euc_E7A1[] = { - 0, 0, 0, 0xCF5D, 0xCF5E, 0x626B, 0, 0xCF5F, - 0xCF60, 0, 0, 0, 0xCF61, 0, 0xCF62, 0, - 0, 0, 0xCF63, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xCF64, 0x3E4B, 0xCF65, 0, - 0xCF66, 0xCF67, 0, 0xCF68, 0xCF69, 0, 0, 0, - 0xCF6A, 0, 0xCF6B, 0x4E32, 0x3945, 0, 0xCF6C, 0x3827, - 0, 0, 0x4823, 0, 0x626D, 0, 0, 0, - 0, 0, 0xCF6D, 0, 0x626F, 0, 0xCF6E, 0, -}; -static const unsigned short utf8_to_euc_E7A1_x0213[] = { - 0, 0, 0, 0x7921, 0xCF5E, 0x626B, 0, 0xF245, - 0xCF60, 0, 0, 0, 0xCF61, 0, 0x7922, 0x7923, - 0, 0x7924, 0xCF63, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xCF64, 0x3E4B, 0xCF65, 0, - 0xCF66, 0xCF67, 0, 0xCF68, 0xF246, 0, 0, 0, - 0x7925, 0, 0xF247, 0x4E32, 0x3945, 0, 0x7926, 0x3827, - 0, 0, 0x4823, 0, 0x626D, 0, 0, 0, - 0, 0, 0, 0, 0x626F, 0, 0xCF6E, 0, -}; -static const unsigned short utf8_to_euc_E7A2[] = { - 0, 0x386B, 0, 0, 0, 0, 0x626E, 0x4476, - 0, 0, 0xCF6F, 0, 0x6271, 0x3337, 0x626C, 0xCF70, - 0, 0x486A, 0, 0x3130, 0xCF71, 0x3A6C, 0, 0x4F52, - 0xCF72, 0, 0x6270, 0, 0, 0xCF74, 0xCF75, 0xCF76, - 0, 0xCF73, 0, 0x6272, 0xCF77, 0, 0, 0x4A4B, - 0xCF78, 0x4059, 0x6274, 0, 0xCF79, 0xCF7A, 0, 0x6275, - 0xCF7B, 0xCF7C, 0xCF7D, 0xCF7E, 0, 0x6273, 0, 0, - 0, 0, 0x334E, 0xD021, 0x627B, 0xD022, 0x627A, 0xD023, -}; -static const unsigned short utf8_to_euc_E7A2_x0213[] = { - 0, 0x386B, 0, 0, 0, 0, 0x626E, 0x4476, - 0, 0, 0xF249, 0, 0x6271, 0x3337, 0x626C, 0xCF70, - 0, 0x486A, 0, 0x3130, 0xF24A, 0x3A6C, 0, 0x4F52, - 0xCF72, 0, 0x6270, 0, 0, 0xF24C, 0xF24D, 0xF24E, - 0, 0xCF73, 0, 0x6272, 0xF24B, 0, 0, 0x4A4B, - 0xCF78, 0x4059, 0x6274, 0, 0xCF79, 0x792A, 0, 0x6275, - 0x7928, 0xCF7C, 0xCF7D, 0xCF7E, 0, 0x6273, 0, 0, - 0, 0, 0x334E, 0xF24F, 0x627B, 0xD022, 0x627A, 0xD023, -}; -static const unsigned short utf8_to_euc_E7A3[] = { - 0, 0x3C27, 0, 0, 0, 0x627C, 0x6277, 0xD024, - 0xD025, 0xD026, 0x627D, 0x6278, 0xD027, 0, 0xD028, 0, - 0x4858, 0x6276, 0xD029, 0xD02A, 0x6279, 0xD02B, 0xD02C, 0, - 0, 0, 0x6322, 0xD02E, 0, 0, 0, 0xD02F, - 0xD030, 0xD031, 0, 0, 0xD02D, 0, 0xD032, 0x6321, - 0x4B61, 0, 0xD033, 0, 0x627E, 0, 0, 0x306B, - 0, 0, 0xD034, 0xD035, 0x6324, 0, 0xD037, 0xD038, - 0, 0, 0xD039, 0xD03A, 0, 0x6323, 0, 0xD03B, -}; -static const unsigned short utf8_to_euc_E7A3_x0213[] = { - 0, 0x3C27, 0, 0, 0, 0x627C, 0x6277, 0xD024, - 0xF250, 0xD026, 0x627D, 0x6278, 0xF251, 0, 0xF252, 0, - 0x4858, 0x6276, 0xD029, 0xD02A, 0x6279, 0xF253, 0xD02C, 0, - 0, 0, 0x6322, 0xD02E, 0, 0, 0, 0xD02F, - 0xF254, 0xF255, 0, 0, 0x792B, 0, 0xF256, 0x6321, - 0x4B61, 0, 0xD033, 0, 0x627E, 0, 0, 0x306B, - 0, 0, 0x792C, 0xD035, 0x6324, 0, 0xD037, 0x792E, - 0, 0xF257, 0xF258, 0xF259, 0, 0x6323, 0xF25A, 0xD03B, -}; -static const unsigned short utf8_to_euc_E7A4[] = { - 0xD036, 0x3E4C, 0, 0, 0, 0, 0xD03C, 0x6325, - 0, 0, 0, 0, 0xD03D, 0, 0x4143, 0, - 0xD03E, 0x6327, 0x6326, 0, 0, 0, 0, 0, - 0, 0x6328, 0xD03F, 0, 0xD040, 0, 0xD041, 0xD042, - 0xD043, 0, 0, 0, 0, 0xD044, 0x6268, 0xD045, - 0, 0xD046, 0x626A, 0x632A, 0x6329, 0xD047, 0, 0, - 0xF454, 0xD048, 0, 0, 0xD049, 0xD04A, 0, 0, - 0, 0, 0x3C28, 0xD04B, 0x4E69, 0xD04C, 0x3C52, 0xD04D, -}; -static const unsigned short utf8_to_euc_E7A4_x0213[] = { - 0x792D, 0x3E4C, 0, 0, 0, 0, 0xD03C, 0x6325, - 0, 0, 0, 0, 0xD03D, 0, 0x4143, 0, - 0xF25C, 0x6327, 0x6326, 0, 0, 0, 0, 0, - 0, 0x6328, 0xD03F, 0xF25D, 0x792F, 0, 0xD041, 0xD042, - 0xD043, 0, 0, 0, 0, 0xF25F, 0x6268, 0xD045, - 0, 0xD046, 0x626A, 0x632A, 0x6329, 0xD047, 0x7930, 0, - 0xF25E, 0x7931, 0, 0, 0x7932, 0xD04A, 0, 0, - 0, 0, 0x3C28, 0xF260, 0x4E69, 0xD04C, 0x3C52, 0xD04D, -}; -static const unsigned short utf8_to_euc_E7A5[] = { - 0x632B, 0x3737, 0, 0, 0xD04E, 0xD04F, 0xD050, 0x3540, - 0x3527, 0x3B63, 0xD051, 0xD052, 0, 0, 0, 0xD053, - 0x4D34, 0xD054, 0, 0x6331, 0xD055, 0x6330, 0x4144, 0x632D, - 0xD056, 0, 0x632F, 0xD057, 0xD058, 0x3D4B, 0x3F40, 0x632E, - 0x632C, 0, 0x472A, 0, 0, 0x3E4D, 0, 0xD059, - 0x493C, 0xD05A, 0, 0xD05B, 0, 0x3A57, 0, 0, - 0, 0, 0xD05C, 0, 0, 0, 0, 0x4578, - 0, 0xD05D, 0x6332, 0xD05E, 0xD05F, 0, 0xD060, 0x6333, -}; -static const unsigned short utf8_to_euc_E7A5_x0213[] = { - 0x632B, 0x3737, 0, 0, 0xD04E, 0x7935, 0x7936, 0x3540, - 0x3527, 0x3B63, 0xF261, 0xD052, 0, 0, 0, 0xD053, - 0x4D34, 0xD054, 0, 0x6331, 0xD055, 0x6330, 0x4144, 0x632D, - 0xF262, 0, 0x632F, 0xF263, 0x793A, 0x3D4B, 0x3F40, 0x632E, - 0x632C, 0, 0x472A, 0, 0, 0x3E4D, 0, 0xF265, - 0x493C, 0xD05A, 0, 0xD05B, 0, 0x3A57, 0, 0, - 0, 0, 0xF266, 0, 0, 0, 0, 0x4578, - 0, 0x793E, 0x6332, 0xD05E, 0xD05F, 0, 0xD060, 0x6333, -}; -static const unsigned short utf8_to_euc_E7A6[] = { - 0x6349, 0x3658, 0, 0, 0x4F3D, 0x4135, 0, 0, - 0, 0, 0x6334, 0xD061, 0xD062, 0x3252, 0x4477, 0x4A21, - 0, 0xD063, 0, 0xD064, 0xD065, 0xD066, 0xD067, 0, - 0xD068, 0, 0, 0xD069, 0xD06A, 0x6335, 0, 0, - 0, 0xD06B, 0, 0, 0, 0, 0x357A, 0x6336, - 0xD06C, 0xD06D, 0x6338, 0xD06E, 0, 0, 0x6339, 0xD06F, - 0x4729, 0xD070, 0, 0x633A, 0xD071, 0, 0, 0, - 0xD072, 0x633B, 0x633C, 0xD073, 0, 0x3659, 0x3253, 0x4645, -}; -static const unsigned short utf8_to_euc_E7A6_x0213[] = { - 0x6349, 0x3658, 0, 0, 0x4F3D, 0x4135, 0, 0, - 0, 0, 0x6334, 0xD061, 0xD062, 0x3252, 0x4477, 0x4A21, - 0, 0xD063, 0, 0xD064, 0xF267, 0xF268, 0xF269, 0, - 0x7942, 0, 0, 0xF26A, 0xD06A, 0x6335, 0, 0, - 0, 0xF26B, 0, 0, 0, 0, 0x357A, 0x6336, - 0xD06C, 0xF26C, 0x6338, 0xD06E, 0, 0, 0x6339, 0xD06F, - 0x4729, 0x7943, 0, 0x633A, 0xF26D, 0, 0, 0, - 0x7944, 0x633B, 0x633C, 0xF26E, 0, 0x3659, 0x3253, 0x4645, -}; -static const unsigned short utf8_to_euc_E7A7[] = { - 0x3D28, 0x3B64, 0xD074, 0, 0xD075, 0, 0, 0xD076, - 0xD077, 0x633D, 0xD078, 0x3D29, 0, 0, 0, 0xD079, - 0, 0x324A, 0x4943, 0, 0xD07A, 0x633E, 0xD07B, 0, - 0x486B, 0, 0xD07C, 0, 0, 0xD07D, 0xD07E, 0x4145, - 0xD121, 0x6341, 0xD122, 0x6342, 0x4769, 0xD123, 0x3F41, 0x633F, - 0, 0x4361, 0xD124, 0xD125, 0x6340, 0xD126, 0, 0, - 0x3E4E, 0xD127, 0, 0, 0, 0, 0, 0, - 0xD128, 0, 0, 0x305C, 0xD129, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E7A7_x0213[] = { - 0x3D28, 0x3B64, 0xF26F, 0, 0xD075, 0, 0, 0xF270, - 0x7945, 0x633D, 0x7946, 0x3D29, 0xF271, 0xF272, 0, 0xD079, - 0, 0x324A, 0x4943, 0, 0x7948, 0x633E, 0xF273, 0, - 0x486B, 0, 0xD07C, 0, 0, 0xD07D, 0x7949, 0x4145, - 0xD121, 0x6341, 0xD122, 0x6342, 0x4769, 0xD123, 0x3F41, 0x633F, - 0, 0x4361, 0xD124, 0x794A, 0x6340, 0x794B, 0, 0, - 0x3E4E, 0xD127, 0, 0, 0, 0, 0, 0, - 0xD128, 0, 0, 0x305C, 0xD129, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E7A8[] = { - 0x3529, 0, 0xD12A, 0xD12B, 0, 0, 0, 0xD12C, - 0x6343, 0xD12D, 0xD12E, 0x4478, 0xD12F, 0x6344, 0x4047, 0, - 0, 0xD130, 0, 0, 0x4C2D, 0xD131, 0, 0x4923, - 0x6345, 0x6346, 0x4355, 0xD132, 0x4E47, 0, 0xD133, 0x6348, - 0x6347, 0xD134, 0, 0, 0, 0, 0, 0xD135, - 0, 0, 0, 0xD136, 0, 0xD137, 0x3C6F, 0xD138, - 0xD139, 0x634A, 0x3070, 0, 0xD13A, 0xD13B, 0, 0x634D, - 0xD13C, 0xD13D, 0xD13E, 0x634B, 0x3254, 0x374E, 0x634C, 0x3946, -}; -static const unsigned short utf8_to_euc_E7A8_x0213[] = { - 0x3529, 0, 0xD12A, 0x794C, 0, 0, 0, 0xD12C, - 0x6343, 0xD12D, 0xF278, 0x4478, 0xD12F, 0x6344, 0x4047, 0, - 0, 0xF279, 0, 0, 0x4C2D, 0xF27A, 0, 0x4923, - 0x6345, 0x6346, 0x4355, 0xF27B, 0x4E47, 0, 0xF27C, 0x6348, - 0x6347, 0xD134, 0, 0, 0, 0, 0, 0xD135, - 0, 0, 0, 0xD136, 0, 0xF27E, 0x3C6F, 0xD138, - 0xD139, 0x634A, 0x3070, 0, 0xD13A, 0xD13B, 0, 0x634D, - 0xF321, 0x794E, 0xD13E, 0x634B, 0x3254, 0x374E, 0x634C, 0x3946, -}; -static const unsigned short utf8_to_euc_E7A9[] = { - 0x3972, 0, 0x4A66, 0x634E, 0xD13F, 0xD140, 0x4B54, 0xD141, - 0xD142, 0x6350, 0, 0, 0xD143, 0x4051, 0x314F, 0x323A, - 0x302C, 0, 0, 0, 0, 0xD144, 0xD145, 0x634F, - 0, 0xD146, 0, 0, 0xD147, 0xD148, 0, 0xD149, - 0xD14A, 0x6351, 0x6352, 0x3E77, 0, 0xD14B, 0, 0xD14C, - 0, 0x6353, 0xD14D, 0x334F, 0, 0xD14E, 0, 0, - 0x6355, 0, 0, 0, 0x376A, 0xD14F, 0x3566, 0, - 0xD150, 0x6356, 0x3675, 0, 0, 0x6357, 0xD151, 0x407C, -}; -static const unsigned short utf8_to_euc_E7A9_x0213[] = { - 0x3972, 0, 0x4A66, 0x634E, 0xD13F, 0xD140, 0x4B54, 0xF322, - 0xD142, 0x6350, 0, 0, 0xF323, 0x4051, 0x314F, 0x323A, - 0x302C, 0, 0, 0, 0, 0xD144, 0xF324, 0x634F, - 0, 0xF325, 0, 0, 0xF326, 0x794F, 0, 0xF327, - 0xF328, 0x6351, 0x6352, 0x3E77, 0, 0xD14B, 0, 0xF329, - 0, 0x6353, 0xF32A, 0x334F, 0, 0x7950, 0, 0, - 0x6355, 0, 0, 0, 0x376A, 0xF32B, 0x3566, 0, - 0xF32C, 0x6356, 0x3675, 0, 0, 0x6357, 0xD151, 0x407C, -}; -static const unsigned short utf8_to_euc_E7AA[] = { - 0xD152, 0x464D, 0xD153, 0x4060, 0x3A75, 0xD154, 0xD155, 0, - 0x6358, 0, 0xD156, 0xD157, 0, 0, 0, 0, - 0xD158, 0xD159, 0x4362, 0x416B, 0xD15A, 0x635A, 0x635C, 0x6359, - 0x635B, 0, 0, 0, 0, 0, 0xD15B, 0x3722, - 0xD15C, 0, 0, 0xD15D, 0, 0, 0, 0, - 0, 0x635D, 0x3726, 0, 0xD15E, 0, 0x3567, 0x4D52, - 0x635F, 0, 0, 0xD15F, 0, 0xD160, 0x6360, 0, - 0, 0xD161, 0x312E, 0xD162, 0xD163, 0, 0, 0x6363, -}; -static const unsigned short utf8_to_euc_E7AA_x0213[] = { - 0xD152, 0x464D, 0xF32D, 0x4060, 0x3A75, 0x7952, 0xD155, 0, - 0x6358, 0, 0xF32E, 0xD157, 0, 0, 0, 0, - 0xF32F, 0xD159, 0x4362, 0x416B, 0xD15A, 0x635A, 0x635C, 0x6359, - 0x635B, 0, 0, 0, 0, 0, 0xD15B, 0x3722, - 0x7953, 0, 0, 0xF330, 0, 0, 0, 0, - 0, 0x635D, 0x3726, 0, 0xF331, 0, 0x3567, 0x4D52, - 0x635F, 0, 0, 0x7955, 0, 0xD160, 0x6360, 0, - 0, 0xF334, 0x312E, 0x7956, 0xF335, 0, 0xF336, 0x6363, -}; -static const unsigned short utf8_to_euc_E7AB[] = { - 0, 0, 0, 0x3376, 0x6362, 0x6361, 0xD164, 0x6365, - 0x635E, 0xD165, 0x6366, 0x4E29, 0xD166, 0x6367, 0xD167, 0x6368, - 0, 0xD168, 0x5474, 0x636A, 0, 0x6369, 0, 0, - 0, 0x636B, 0x636C, 0xD169, 0x4E35, 0x636D, 0, 0x706F, - 0x3E4F, 0x636E, 0x636F, 0x3D57, 0, 0x4638, 0x6370, 0xF459, - 0xD16A, 0xD16B, 0x4328, 0xD16C, 0xD16D, 0x6371, 0, 0x433C, - 0x6372, 0xD16E, 0, 0, 0xD16F, 0, 0x3625, 0, - 0x513F, 0x435D, 0x3C33, 0xD170, 0, 0xD171, 0xD172, 0x3448, -}; -static const unsigned short utf8_to_euc_E7AB_x0213[] = { - 0, 0, 0, 0x3376, 0x6362, 0x6361, 0xD164, 0x6365, - 0x635E, 0xD165, 0x6366, 0x4E29, 0xF338, 0x6367, 0x7957, 0x6368, - 0, 0xF339, 0x5474, 0x636A, 0, 0x6369, 0, 0, - 0, 0x636B, 0x636C, 0xD169, 0x4E35, 0x636D, 0, 0x706F, - 0x3E4F, 0x636E, 0x636F, 0x3D57, 0, 0x4638, 0x6370, 0xF33A, - 0xF33B, 0xD16B, 0x4328, 0x7958, 0xD16D, 0x6371, 0, 0x433C, - 0x6372, 0xD16E, 0, 0, 0xF33C, 0, 0x3625, 0, - 0x513F, 0x435D, 0x3C33, 0xD170, 0, 0x7959, 0xD172, 0x3448, -}; -static const unsigned short utf8_to_euc_E7AC[] = { - 0, 0, 0x6373, 0, 0x6422, 0, 0x6376, 0xD173, - 0x3568, 0, 0x6375, 0x6424, 0, 0, 0, 0x6374, - 0, 0x3E50, 0, 0, 0xD174, 0, 0, 0, - 0x6378, 0x6379, 0, 0x452B, 0, 0, 0x637A, 0xD175, - 0x335E, 0, 0, 0xD176, 0, 0x3F5A, 0x4964, 0xD177, - 0x637C, 0xD178, 0xD179, 0xD17A, 0x4268, 0xD17B, 0xD17C, 0xD17D, - 0xD17E, 0xD221, 0, 0x6377, 0xD222, 0x637B, 0x637D, 0, - 0, 0x3A7B, 0, 0, 0, 0xD223, 0, 0xD224, -}; -static const unsigned short utf8_to_euc_E7AC_x0213[] = { - 0, 0, 0x6373, 0, 0x6422, 0, 0x6376, 0xF33F, - 0x3568, 0, 0x6375, 0x6424, 0, 0, 0, 0x6374, - 0, 0x3E50, 0x795A, 0, 0xD174, 0, 0, 0, - 0x6378, 0x6379, 0, 0x452B, 0, 0, 0x637A, 0xD175, - 0x335E, 0, 0, 0xD176, 0, 0x3F5A, 0x4964, 0xF342, - 0x637C, 0xD178, 0xF343, 0xD17A, 0x4268, 0x795B, 0xF344, 0xF345, - 0xD17E, 0xF346, 0, 0x6377, 0xD222, 0x637B, 0x637D, 0, - 0, 0x3A7B, 0, 0x795C, 0, 0xF341, 0, 0xD224, -}; -static const unsigned short utf8_to_euc_E7AD[] = { - 0xD225, 0xD226, 0, 0, 0, 0x6426, 0x492E, 0xD227, - 0x4826, 0x4579, 0, 0x365A, 0x6425, 0x6423, 0xD228, 0x4835, - 0x637E, 0x435E, 0x457B, 0, 0x457A, 0xD229, 0x3A76, 0, - 0, 0, 0, 0, 0, 0x6438, 0, 0, - 0xD22A, 0, 0, 0, 0xD22B, 0x6428, 0xD22C, 0x642A, - 0, 0xD22D, 0xD22E, 0, 0x642D, 0xD22F, 0x642E, 0xD230, - 0x642B, 0x642C, 0xD231, 0xD232, 0x6429, 0x6427, 0, 0xD233, - 0, 0, 0x6421, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E7AD_x0213[] = { - 0xD225, 0xF34A, 0, 0, 0, 0x6426, 0x492E, 0x795D, - 0x4826, 0x4579, 0, 0x365A, 0x6425, 0x6423, 0x795E, 0x4835, - 0x637E, 0x435E, 0x457B, 0, 0x457A, 0xF34C, 0x3A76, 0, - 0, 0, 0, 0, 0, 0x6438, 0, 0, - 0x795F, 0, 0, 0, 0xF34E, 0x6428, 0xF34F, 0x642A, - 0, 0xF350, 0xD22E, 0, 0x642D, 0x7960, 0x642E, 0x7961, - 0x642B, 0x642C, 0x7962, 0xF351, 0x6429, 0x6427, 0, 0xD233, - 0, 0xF34D, 0x6421, 0, 0, 0, 0, 0xF349, -}; -static const unsigned short utf8_to_euc_E7AE[] = { - 0, 0, 0, 0, 0xD234, 0, 0x4A4F, 0x3255, - 0, 0xD235, 0, 0x6435, 0, 0x6432, 0xD236, 0x6437, - 0xD237, 0xD238, 0x6436, 0, 0x4773, 0x4C27, 0xD239, 0x3B3B, - 0x6430, 0x6439, 0x6434, 0xD23A, 0x6433, 0x642F, 0xD23B, 0x6431, - 0xD23C, 0x3449, 0, 0, 0, 0xD23D, 0, 0, - 0, 0, 0x433D, 0, 0xD23E, 0x407D, 0, 0xD23F, - 0xD240, 0x4822, 0xD241, 0, 0x643E, 0xD242, 0xD243, 0, - 0x4824, 0, 0xD244, 0xD245, 0xD246, 0xD247, 0, 0, -}; -static const unsigned short utf8_to_euc_E7AE_x0213[] = { - 0, 0, 0, 0, 0xD234, 0, 0x4A4F, 0x3255, - 0, 0xD235, 0, 0x6435, 0, 0x6432, 0xD236, 0x6437, - 0xF354, 0xF355, 0x6436, 0, 0x4773, 0x4C27, 0xD239, 0x3B3B, - 0x6430, 0x6439, 0x6434, 0xF356, 0x6433, 0x642F, 0x7963, 0x6431, - 0xD23C, 0x3449, 0, 0, 0, 0xD23D, 0, 0, - 0, 0, 0x433D, 0, 0xD23E, 0x407D, 0, 0xF358, - 0xD240, 0x4822, 0xD241, 0, 0x643E, 0xF359, 0xD243, 0, - 0x4824, 0, 0xD244, 0xD245, 0xF35A, 0xD247, 0, 0, -}; -static const unsigned short utf8_to_euc_E7AF[] = { - 0x4061, 0x643B, 0xD248, 0, 0x484F, 0xD249, 0x643F, 0x4A53, - 0xD24A, 0x435B, 0xD24B, 0x643A, 0x643C, 0, 0, 0x643D, - 0, 0, 0, 0, 0xD24C, 0, 0xD24D, 0xD24E, - 0, 0xD24F, 0xD250, 0xD251, 0, 0x6440, 0, 0, - 0x3C44, 0, 0, 0, 0x4646, 0x6445, 0x6444, 0, - 0xD252, 0x6441, 0xD253, 0, 0, 0x4F36, 0, 0, - 0, 0, 0xD254, 0x644A, 0xD255, 0xD256, 0x644E, 0x644B, - 0xD257, 0xD258, 0xD259, 0, 0xD25A, 0, 0xD25B, 0, -}; -static const unsigned short utf8_to_euc_E7AF_x0213[] = { - 0x4061, 0x643B, 0xD248, 0, 0x484F, 0xF35B, 0x643F, 0x4A53, - 0xD24A, 0x435B, 0xF35C, 0x643A, 0x643C, 0, 0, 0x643D, - 0, 0, 0, 0, 0xF35F, 0, 0xF360, 0x7965, - 0, 0x7966, 0xF361, 0xD251, 0, 0x6440, 0, 0, - 0x3C44, 0, 0, 0, 0x4646, 0x6445, 0x6444, 0, - 0xD252, 0x6441, 0xF362, 0, 0, 0x4F36, 0, 0, - 0xF363, 0, 0xD254, 0x644A, 0xD255, 0xD256, 0x644E, 0x644B, - 0xD257, 0xD258, 0xD259, 0, 0xD25A, 0, 0xD25B, 0, -}; -static const unsigned short utf8_to_euc_E7B0[] = { - 0x6447, 0xD25C, 0xD25D, 0xD25E, 0xD25F, 0, 0xD260, 0x6448, - 0, 0xD261, 0, 0xD262, 0xD263, 0x644D, 0xD264, 0xD265, - 0, 0x6442, 0x5255, 0x6449, 0x6443, 0, 0, 0x644C, - 0, 0xD266, 0, 0xD267, 0, 0, 0, 0x6452, - 0xD268, 0x344A, 0, 0x644F, 0, 0xD269, 0xD26A, 0x6450, - 0xD26B, 0, 0x6451, 0x6454, 0xD26C, 0, 0, 0, - 0, 0xD26D, 0, 0xD26E, 0xD26F, 0, 0xD270, 0x6453, - 0x4876, 0xD271, 0xD272, 0, 0, 0x6455, 0x4E7C, 0x4A6D, -}; -static const unsigned short utf8_to_euc_E7B0_x0213[] = { - 0x6447, 0x7967, 0xD25D, 0xF364, 0xD25F, 0, 0xD260, 0x6448, - 0, 0xD261, 0, 0xF365, 0xD263, 0x644D, 0xF366, 0xF367, - 0, 0x6442, 0x5255, 0x6449, 0x6443, 0, 0, 0x644C, - 0, 0xD266, 0, 0xD267, 0, 0, 0x7969, 0x6452, - 0x796A, 0x344A, 0, 0x644F, 0, 0xD269, 0xF368, 0x6450, - 0xD26B, 0, 0x6451, 0x6454, 0xD26C, 0, 0, 0, - 0, 0x7968, 0, 0x796B, 0xD26F, 0, 0x796C, 0x6453, - 0x4876, 0xD271, 0xD272, 0, 0, 0x6455, 0x4E7C, 0x4A6D, -}; -static const unsigned short utf8_to_euc_E7B1[] = { - 0x645A, 0, 0, 0x6457, 0, 0, 0xD273, 0, - 0, 0, 0xD274, 0, 0x6456, 0x4052, 0, 0x6459, - 0x645B, 0xD276, 0xD277, 0xD278, 0x6458, 0xD275, 0x645F, 0, - 0x645C, 0xD279, 0xD27A, 0xD27B, 0xD27C, 0xD27D, 0xD27E, 0x645D, - 0x6446, 0xD321, 0, 0xD322, 0x645E, 0x6460, 0, 0xD323, - 0, 0xD324, 0, 0, 0x6461, 0xD325, 0xD326, 0, - 0xD327, 0, 0xD328, 0x4A46, 0, 0x6462, 0, 0, - 0, 0xD329, 0, 0, 0xD32A, 0xD32B, 0x4C62, 0, -}; -static const unsigned short utf8_to_euc_E7B1_x0213[] = { - 0x645A, 0, 0, 0x6457, 0, 0xF369, 0xD273, 0, - 0, 0, 0xF36A, 0, 0x6456, 0x4052, 0, 0x6459, - 0x645B, 0xF36B, 0xD277, 0xD278, 0x6458, 0xD275, 0x645F, 0xF36C, - 0x645C, 0x796F, 0xD27A, 0xD27B, 0xD27C, 0xD27D, 0xF36D, 0x645D, - 0x6446, 0xF36E, 0, 0xD322, 0x645E, 0x6460, 0, 0xD323, - 0, 0xF36F, 0, 0, 0x6461, 0x7970, 0xF370, 0xF371, - 0xF372, 0, 0xD328, 0x4A46, 0, 0x6462, 0, 0, - 0, 0x7971, 0, 0, 0xD32A, 0xD32B, 0x4C62, 0, -}; -static const unsigned short utf8_to_euc_E7B2[] = { - 0, 0x364E, 0x3729, 0x6463, 0, 0, 0xD32C, 0xD32D, - 0, 0x4A34, 0, 0x3F68, 0, 0x4C30, 0, 0xD32E, - 0x6464, 0, 0x4E33, 0, 0xD32F, 0x4774, 0, 0x4146, - 0x4734, 0, 0, 0x3D4D, 0, 0, 0xD330, 0x3040, - 0xD331, 0x6469, 0x6467, 0, 0x6465, 0x3421, 0xD332, 0x3E51, - 0x646A, 0, 0, 0x6468, 0, 0x6466, 0x646E, 0, - 0xD333, 0x646D, 0x646C, 0x646B, 0, 0, 0xD334, 0xD335, - 0, 0x646F, 0xD336, 0xD337, 0xD338, 0x6470, 0x403A, 0xD339, -}; -static const unsigned short utf8_to_euc_E7B2_x0213[] = { - 0, 0x364E, 0x3729, 0x6463, 0, 0, 0xD32C, 0xD32D, - 0, 0x4A34, 0, 0x3F68, 0, 0x4C30, 0, 0x7972, - 0x6464, 0, 0x4E33, 0, 0x7973, 0x4774, 0, 0x4146, - 0x4734, 0, 0, 0x3D4D, 0, 0, 0xD330, 0x3040, - 0x7974, 0x6469, 0x6467, 0, 0x6465, 0x3421, 0xF376, 0x3E51, - 0x646A, 0, 0, 0x6468, 0, 0x6466, 0x646E, 0, - 0xD333, 0x646D, 0x646C, 0x646B, 0, 0, 0xF378, 0xF379, - 0, 0x646F, 0xD336, 0xD337, 0x7975, 0x6470, 0x403A, 0xF37A, -}; -static const unsigned short utf8_to_euc_E7B3[] = { - 0x6471, 0, 0x6473, 0, 0xD33A, 0x6472, 0, 0xD33B, - 0xD33C, 0xD33D, 0x3852, 0, 0, 0xD33E, 0x4138, 0xD33F, - 0, 0, 0x6475, 0xD340, 0xD341, 0xD342, 0x457C, 0xD343, - 0x6474, 0xD344, 0xD345, 0, 0x6476, 0xD346, 0x4A35, 0x416C, - 0x3947, 0, 0x6477, 0, 0, 0, 0xD347, 0x4E48, - 0, 0xD348, 0, 0xD349, 0, 0, 0, 0x6479, - 0, 0, 0x647A, 0, 0x647B, 0xD34A, 0x647C, 0, - 0x3B65, 0, 0x647D, 0x374F, 0, 0, 0x356A, 0, -}; -static const unsigned short utf8_to_euc_E7B3_x0213[] = { - 0x6471, 0, 0x6473, 0, 0xF37C, 0x6472, 0, 0xD33B, - 0xF37E, 0xD33D, 0x3852, 0, 0, 0xF421, 0x4138, 0xD33F, - 0, 0, 0x6475, 0xD340, 0xD341, 0x7976, 0x457C, 0xF423, - 0x6474, 0x7977, 0xD345, 0, 0x6476, 0x7978, 0x4A35, 0x416C, - 0x3947, 0, 0x6477, 0, 0, 0, 0xF425, 0x4E48, - 0, 0xD348, 0, 0xF426, 0, 0, 0, 0x6479, - 0, 0, 0x647A, 0, 0x647B, 0xF428, 0x647C, 0, - 0x3B65, 0, 0x647D, 0x374F, 0, 0, 0x356A, 0, -}; -static const unsigned short utf8_to_euc_E7B4[] = { - 0x352A, 0, 0x6521, 0xD34B, 0x4C73, 0x3948, 0x647E, 0xD34C, - 0xD34D, 0xD34E, 0x6524, 0x4C66, 0, 0x473C, 0, 0xD34F, - 0x4933, 0xD350, 0xD351, 0xD352, 0x3D63, 0x6523, 0xD353, 0x3C53, - 0x3949, 0x3B66, 0x3569, 0x4A36, 0x6522, 0xD354, 0xD355, 0, - 0x4147, 0x4B42, 0x3A77, 0xD356, 0, 0, 0xD357, 0, - 0, 0, 0xD358, 0x3B67, 0x445D, 0xD359, 0x6527, 0x4E5F, - 0x3A59, 0xD35A, 0x6528, 0x3F42, 0, 0x652A, 0, 0, - 0, 0x3E52, 0x3A30, 0, 0xD35B, 0xD35C, 0xD35D, 0x6529, -}; -static const unsigned short utf8_to_euc_E7B4_x0213[] = { - 0x352A, 0, 0x6521, 0xF429, 0x4C73, 0x3948, 0x647E, 0x7979, - 0x797A, 0xF42A, 0x6524, 0x4C66, 0, 0x473C, 0, 0xD34F, - 0x4933, 0xD350, 0xF42C, 0x797B, 0x3D63, 0x6523, 0xD353, 0x3C53, - 0x3949, 0x3B66, 0x3569, 0x4A36, 0x6522, 0x797C, 0xF42D, 0, - 0x4147, 0x4B42, 0x3A77, 0x797D, 0, 0, 0xD357, 0, - 0, 0, 0xD358, 0x3B67, 0x445D, 0xD359, 0x6527, 0x4E5F, - 0x3A59, 0x797E, 0x6528, 0x3F42, 0, 0x652A, 0, 0, - 0, 0x3E52, 0x3A30, 0, 0xD35B, 0xF430, 0xF431, 0x6529, -}; -static const unsigned short utf8_to_euc_E7B5[] = { - 0xD35E, 0xD35F, 0x3D2A, 0x383E, 0x4148, 0x6525, 0x652B, 0xD360, - 0xD361, 0, 0, 0x6526, 0x3750, 0xD362, 0x652E, 0x6532, - 0x376B, 0xD363, 0, 0xD364, 0, 0, 0x652D, 0xD365, - 0, 0xD366, 0xD367, 0x6536, 0xD368, 0xD369, 0x394A, 0, - 0, 0x4D6D, 0x303C, 0x6533, 0, 0xD36A, 0x356B, 0xD36B, - 0x6530, 0, 0xD36C, 0, 0, 0, 0x6531, 0, - 0xD36D, 0x457D, 0x652F, 0x652C, 0, 0x3328, 0x4064, 0, - 0xD36E, 0x3828, 0xD36F, 0xD370, 0, 0x6538, 0, 0xD371, -}; -static const unsigned short utf8_to_euc_E7B5_x0213[] = { - 0xF432, 0x7A21, 0x3D2A, 0x383E, 0x4148, 0x6525, 0x652B, 0xF433, - 0x7A22, 0, 0, 0x6526, 0x3750, 0xD362, 0x652E, 0x6532, - 0x376B, 0xD363, 0, 0x7A23, 0, 0, 0x652D, 0xD365, - 0, 0xF437, 0xF438, 0x6536, 0x7A24, 0xD369, 0x394A, 0, - 0, 0x4D6D, 0x303C, 0x6533, 0, 0xD36A, 0x356B, 0xD36B, - 0x6530, 0, 0xF439, 0, 0, 0, 0x6531, 0, - 0xF43A, 0x457D, 0x652F, 0x652C, 0, 0x3328, 0x4064, 0, - 0xD36E, 0x3828, 0x7A25, 0xD370, 0, 0x6538, 0, 0xF43C, -}; -static const unsigned short utf8_to_euc_E7B6[] = { - 0, 0xD372, 0xD373, 0xD374, 0, 0xD375, 0xD376, 0, - 0xD377, 0x6535, 0, 0xD378, 0xD379, 0xD37A, 0, 0x6537, - 0, 0xD37B, 0, 0x6534, 0, 0, 0xD37C, 0xD37D, - 0, 0x3751, 0x4233, 0x6539, 0x416E, 0xD37E, 0xD421, 0x6546, - 0xF45C, 0, 0x6542, 0x653C, 0, 0, 0xD422, 0xD423, - 0, 0, 0xD424, 0x6540, 0x3C7A, 0x305D, 0x653B, 0x6543, - 0x6547, 0x394B, 0x4C56, 0xD425, 0x4456, 0x653D, 0xD426, 0xD427, - 0x6545, 0xD428, 0x653A, 0x433E, 0, 0x653F, 0x303D, 0x4C4A, -}; -static const unsigned short utf8_to_euc_E7B6_x0213[] = { - 0, 0xD372, 0xD373, 0x7A26, 0, 0xD375, 0xF43E, 0, - 0xF43F, 0x6535, 0, 0x7A27, 0xF440, 0xD37A, 0, 0x6537, - 0, 0xD37B, 0, 0x6534, 0, 0, 0xD37C, 0xF441, - 0, 0x3751, 0x4233, 0x6539, 0x416E, 0xF443, 0xD421, 0x6546, - 0x7A28, 0, 0x6542, 0x653C, 0, 0, 0x7A29, 0xF444, - 0, 0, 0xF445, 0x6540, 0x3C7A, 0x305D, 0x653B, 0x6543, - 0x6547, 0x394B, 0x4C56, 0xD425, 0x4456, 0x653D, 0xF446, 0xF447, - 0x6545, 0xD428, 0x653A, 0x433E, 0, 0x653F, 0x303D, 0x4C4A, -}; -static const unsigned short utf8_to_euc_E7B7[] = { - 0, 0, 0xD429, 0xD42A, 0xD42B, 0xD42C, 0xD42D, 0x653E, - 0, 0, 0x365B, 0x486C, 0xD42E, 0xD42F, 0xD430, 0x416D, - 0, 0x4E50, 0x3D6F, 0, 0, 0x656E, 0xF45D, 0xD431, - 0x6548, 0xD432, 0x407E, 0, 0x6544, 0x6549, 0x654B, 0, - 0x4479, 0x654E, 0xD434, 0, 0x654A, 0xD435, 0xD436, 0, - 0x4A54, 0x344B, 0xD437, 0xD438, 0x4C4B, 0xD439, 0, 0x305E, - 0, 0xD43A, 0x654D, 0, 0x4E7D, 0xD43B, 0xD43C, 0, - 0, 0xD43D, 0xD43E, 0x654C, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E7B7_x0213[] = { - 0xF448, 0, 0x7A2A, 0xD42A, 0xD42B, 0xD42C, 0xD42D, 0x653E, - 0, 0, 0x365B, 0x486C, 0x7A2B, 0xD42F, 0xD430, 0x416D, - 0, 0x4E50, 0x3D6F, 0, 0, 0x656E, 0x7A2C, 0xF449, - 0x6548, 0xF44A, 0x407E, 0, 0x6544, 0x6549, 0x654B, 0, - 0x4479, 0x654E, 0xD434, 0x7A2D, 0x654A, 0xD435, 0xF44B, 0, - 0x4A54, 0x344B, 0xD437, 0xD438, 0x4C4B, 0xD439, 0, 0x305E, - 0, 0xF44C, 0x654D, 0, 0x4E7D, 0xD43B, 0xD43C, 0, - 0, 0xF44D, 0xD43E, 0x654C, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E7B8[] = { - 0xD433, 0x316F, 0, 0, 0x466C, 0x654F, 0, 0, - 0xD43F, 0x6556, 0x6550, 0x6557, 0, 0, 0, 0, - 0xD440, 0xD441, 0x6553, 0, 0, 0xD442, 0, 0xD443, - 0, 0, 0, 0x477B, 0xD444, 0xD445, 0x3C4A, 0x6555, - 0xD446, 0x6552, 0x6558, 0x6551, 0, 0, 0x3D44, 0xD447, - 0xD448, 0, 0, 0x4B25, 0xD449, 0xD44A, 0x3D4C, 0xD44B, - 0, 0x6554, 0x6560, 0xD44C, 0, 0x655C, 0xD44D, 0x655F, - 0, 0x655D, 0x6561, 0x655B, 0, 0x6541, 0x4053, 0xD44E, -}; -static const unsigned short utf8_to_euc_E7B8_x0213[] = { - 0xD433, 0x316F, 0, 0, 0x466C, 0x654F, 0, 0, - 0x7A30, 0x6556, 0x6550, 0x6557, 0, 0, 0, 0, - 0xF451, 0x7A31, 0x6553, 0, 0, 0x7A32, 0, 0xF452, - 0, 0, 0, 0x477B, 0xD444, 0xF453, 0x3C4A, 0x6555, - 0xF454, 0x6552, 0x6558, 0x6551, 0, 0, 0x3D44, 0xF455, - 0x7A2F, 0, 0, 0x4B25, 0xF456, 0xD44A, 0x3D4C, 0xD44B, - 0, 0x6554, 0x6560, 0xD44C, 0, 0x655C, 0xD44D, 0x655F, - 0, 0x655D, 0x6561, 0x655B, 0, 0x6541, 0x4053, 0xD44E, -}; -static const unsigned short utf8_to_euc_E7B9[] = { - 0, 0x484B, 0, 0x655E, 0xD44F, 0xD450, 0x6559, 0xD451, - 0, 0, 0x4121, 0x3752, 0, 0x3D2B, 0xD452, 0, - 0xD453, 0, 0xD454, 0, 0x3F25, 0x4136, 0x6564, 0, - 0xD455, 0x6566, 0x6567, 0, 0, 0x6563, 0x6565, 0xD456, - 0, 0xD457, 0xD458, 0, 0, 0xD459, 0x655A, 0x6562, - 0, 0x656A, 0x6569, 0xD45A, 0, 0x4B7A, 0xD45B, 0xD45C, - 0x372B, 0, 0, 0xD45D, 0, 0, 0, 0, - 0xD45E, 0x6568, 0, 0x656C, 0x656B, 0x656F, 0xD45F, 0x6571, -}; -static const unsigned short utf8_to_euc_E7B9_x0213[] = { - 0, 0x484B, 0, 0x655E, 0xD44F, 0xF457, 0x6559, 0x7A34, - 0, 0, 0x4121, 0x3752, 0, 0x3D2B, 0xD452, 0, - 0xD453, 0, 0x7A35, 0, 0x3F25, 0x4136, 0x6564, 0, - 0xD455, 0x6566, 0x6567, 0, 0, 0x6563, 0x6565, 0xD456, - 0, 0x7A36, 0xD458, 0, 0, 0xD459, 0x655A, 0x6562, - 0, 0x656A, 0x6569, 0x7E7E, 0, 0x4B7A, 0xD45B, 0xD45C, - 0x372B, 0, 0, 0xF458, 0, 0xF459, 0, 0, - 0xD45E, 0x6568, 0, 0x656C, 0x656B, 0x656F, 0xF45A, 0x6571, -}; -static const unsigned short utf8_to_euc_E7BA[] = { - 0, 0xD460, 0x3B3C, 0x656D, 0, 0, 0xD461, 0xD462, - 0x6572, 0x6573, 0xD463, 0, 0x6574, 0xD464, 0x657A, 0x453B, - 0x6576, 0xD465, 0x6575, 0x6577, 0x6578, 0xD466, 0x6579, 0, - 0xD467, 0, 0xD468, 0x657B, 0x657C, 0xD469, 0xD46A, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E7BA_x0213[] = { - 0, 0xD460, 0x3B3C, 0x656D, 0, 0, 0xF45B, 0xF45C, - 0x6572, 0x6573, 0x7A37, 0, 0x6574, 0x7A38, 0x657A, 0x453B, - 0x6576, 0xF45E, 0x6575, 0x6577, 0x6578, 0xD466, 0x6579, 0, - 0xF45F, 0, 0xF460, 0x657B, 0x657C, 0xD469, 0xD46A, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E7BC[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x344C, 0, - 0x657D, 0, 0x657E, 0xD46C, 0xD46B, 0xD46D, 0xD46E, 0xD46F, -}; -static const unsigned short utf8_to_euc_E7BC_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x344C, 0, - 0x657D, 0, 0x657E, 0xF463, 0xF462, 0xD46D, 0xF464, 0xD46F, -}; -static const unsigned short utf8_to_euc_E7BD[] = { - 0, 0, 0, 0xD470, 0xD471, 0x6621, 0, 0xD472, - 0, 0, 0, 0, 0x6622, 0x6623, 0x6624, 0xD473, - 0x6625, 0x6626, 0xD474, 0xD475, 0x6628, 0x6627, 0, 0, - 0x6629, 0, 0, 0xD476, 0xD477, 0xD478, 0, 0x662A, - 0x662B, 0xD479, 0, 0xD47A, 0xD47B, 0xD47C, 0xD47D, 0x662E, - 0x662C, 0x662D, 0x3A61, 0x3753, 0, 0xD47E, 0x4356, 0, - 0x4833, 0xD521, 0x3D70, 0, 0, 0x474D, 0, 0x486D, - 0x662F, 0x586D, 0, 0, 0, 0xD522, 0xD523, 0xD524, -}; -static const unsigned short utf8_to_euc_E7BD_x0213[] = { - 0, 0, 0, 0xF465, 0xF466, 0x6621, 0, 0x7A39, - 0, 0, 0, 0, 0x6622, 0x6623, 0x6624, 0xF467, - 0x6625, 0x6626, 0xF46A, 0xD475, 0x6628, 0x6627, 0, 0, - 0x6629, 0, 0, 0xD476, 0xD477, 0xD478, 0, 0x662A, - 0x662B, 0xF46C, 0, 0xF46D, 0xF46E, 0xD47C, 0xD47D, 0x662E, - 0x662C, 0x662D, 0x3A61, 0x3753, 0, 0xF46F, 0x4356, 0, - 0x4833, 0xD521, 0x3D70, 0, 0, 0x474D, 0, 0x486D, - 0x662F, 0x586D, 0, 0, 0, 0xF470, 0xF471, 0xD524, -}; -static const unsigned short utf8_to_euc_E7BE[] = { - 0xD525, 0, 0x6630, 0x6632, 0, 0x4D65, 0x6631, 0x6634, - 0x6633, 0, 0x4D53, 0xD526, 0x6635, 0xD527, 0x487E, 0xD528, - 0xD529, 0xD52A, 0, 0, 0x6636, 0, 0xD52B, 0xD52C, - 0, 0, 0x6639, 0, 0xD52D, 0x6638, 0x6637, 0, - 0, 0xD52E, 0xD52F, 0x663A, 0x3732, 0, 0xD530, 0, - 0x4122, 0x3541, 0xD531, 0, 0, 0xD532, 0x663E, 0x663B, - 0, 0, 0x663C, 0, 0xD533, 0, 0x663F, 0, - 0x6640, 0x663D, 0, 0, 0xD534, 0x3129, 0, 0xD535, -}; -static const unsigned short utf8_to_euc_E7BE_x0213[] = { - 0xD525, 0, 0x6630, 0x6632, 0, 0x4D65, 0x6631, 0x6634, - 0x6633, 0, 0x4D53, 0xD526, 0x6635, 0xD527, 0x487E, 0xD528, - 0xF473, 0x7A3B, 0, 0, 0x6636, 0, 0xF476, 0x7A3C, - 0, 0, 0x6639, 0, 0xF477, 0x6638, 0x6637, 0, - 0, 0, 0xD52F, 0x663A, 0x3732, 0, 0xD530, 0, - 0x4122, 0x3541, 0xD531, 0, 0, 0xF478, 0x663E, 0x663B, - 0, 0, 0x663C, 0, 0xD533, 0, 0x663F, 0, - 0x6640, 0x663D, 0, 0, 0xD534, 0x3129, 0, 0x7A3D, -}; -static const unsigned short utf8_to_euc_E7BF[] = { - 0xD536, 0x3227, 0, 0xD537, 0, 0x6642, 0x6643, 0, - 0xD538, 0, 0x6644, 0, 0x4D62, 0, 0xD539, 0xD53A, - 0, 0, 0x3D2C, 0, 0x6646, 0x6645, 0, 0, - 0, 0, 0, 0xD53B, 0, 0, 0, 0xD53C, - 0x3F69, 0x6647, 0, 0xD53D, 0, 0xD53E, 0x6648, 0, - 0xD53F, 0x6649, 0, 0x3465, 0xD540, 0, 0xD541, 0xD542, - 0x344D, 0, 0xD543, 0x664A, 0, 0, 0, 0, - 0, 0x664B, 0xD544, 0x4B5D, 0x4D63, 0xD545, 0xD546, 0xD547, -}; -static const unsigned short utf8_to_euc_E7BF_x0213[] = { - 0xD536, 0x3227, 0, 0xF47A, 0, 0x6642, 0x6643, 0, - 0xD538, 0, 0x6644, 0, 0x4D62, 0, 0x7A3E, 0xF47B, - 0, 0, 0x3D2C, 0, 0x6646, 0x6645, 0, 0, - 0, 0, 0, 0x7A3F, 0, 0, 0, 0x7A40, - 0x3F69, 0x6647, 0, 0xF47C, 0, 0xF47D, 0x6648, 0, - 0xD53F, 0x6649, 0, 0x3465, 0x7A41, 0, 0x7A42, 0xF47E, - 0x344D, 0, 0xF521, 0x664A, 0, 0, 0, 0, - 0, 0x664B, 0x7A43, 0x4B5D, 0x4D63, 0xD545, 0xD546, 0xD547, -}; -static const unsigned short utf8_to_euc_E880[] = { - 0x4D54, 0x4F37, 0, 0x394D, 0x664E, 0x3C54, 0x664D, 0xD548, - 0xD549, 0, 0xD54A, 0x664F, 0x3C29, 0xD54B, 0xD54C, 0xD54D, - 0x4251, 0xD54E, 0x6650, 0xD54F, 0xD550, 0x394C, 0xD551, 0x4C57, - 0x6651, 0x6652, 0, 0, 0x6653, 0xD552, 0xD553, 0xD554, - 0xD555, 0x6654, 0, 0, 0xD556, 0, 0xD557, 0, - 0x6655, 0, 0, 0, 0xD558, 0, 0xD559, 0, - 0xD55A, 0, 0, 0x3C2A, 0xD55B, 0xD55C, 0x4C6D, 0xD55D, - 0, 0xD55E, 0xD55F, 0x6657, 0xD560, 0x433F, 0xD561, 0x6656, -}; -static const unsigned short utf8_to_euc_E880_x0213[] = { - 0x4D54, 0x4F37, 0xF522, 0x394D, 0x664E, 0x3C54, 0x664D, 0xD548, - 0xF524, 0, 0xF523, 0x664F, 0x3C29, 0xD54B, 0xF525, 0xD54D, - 0x4251, 0xF526, 0x6650, 0xD54F, 0x7A45, 0x394C, 0xF527, 0x4C57, - 0x6651, 0x6652, 0, 0, 0x6653, 0xD552, 0xD553, 0xD554, - 0xD555, 0x6654, 0, 0, 0xF528, 0, 0x7A46, 0, - 0x6655, 0, 0, 0, 0xF529, 0, 0xD559, 0, - 0xF52A, 0, 0, 0x3C2A, 0xD55B, 0x7A47, 0x4C6D, 0x7A48, - 0, 0xD55E, 0xD55F, 0x6657, 0x7A49, 0x433F, 0xD561, 0x6656, -}; -static const unsigned short utf8_to_euc_E881[] = { - 0xD562, 0, 0, 0, 0xD563, 0, 0x6659, 0, - 0, 0, 0x6658, 0, 0, 0, 0, 0, - 0, 0, 0x665A, 0, 0, 0, 0x403B, 0, - 0x665B, 0, 0x665C, 0, 0, 0, 0x4A39, 0x665D, - 0xD564, 0x416F, 0x665E, 0, 0xD565, 0, 0xD566, 0, - 0x665F, 0, 0, 0, 0, 0xD567, 0, 0x4E7E, - 0x6662, 0xD568, 0x6661, 0x6660, 0x4430, 0xD569, 0x6663, 0x3F26, - 0, 0x6664, 0, 0, 0, 0x6665, 0x4F38, 0x6666, -}; -static const unsigned short utf8_to_euc_E881_x0213[] = { - 0xD562, 0, 0, 0xF52B, 0xD563, 0, 0x6659, 0, - 0, 0, 0x6658, 0, 0, 0, 0, 0, - 0, 0, 0x665A, 0, 0, 0, 0x403B, 0, - 0x665B, 0, 0x665C, 0, 0, 0, 0x4A39, 0x665D, - 0xD564, 0x416F, 0x665E, 0, 0xD565, 0, 0xF52C, 0, - 0x665F, 0, 0, 0, 0, 0xD567, 0, 0x4E7E, - 0x6662, 0xF52D, 0x6661, 0x6660, 0x4430, 0xF52E, 0x6663, 0x3F26, - 0, 0x6664, 0, 0xF52F, 0, 0x6665, 0x4F38, 0x6666, -}; -static const unsigned short utf8_to_euc_E882[] = { - 0, 0xD56A, 0, 0, 0x6667, 0x6669, 0x6668, 0x4825, - 0xD56B, 0x4679, 0, 0x4F3E, 0x4829, 0, 0xD56C, 0, - 0, 0, 0, 0x666B, 0, 0, 0x3E53, 0, - 0x492A, 0, 0x666C, 0x666A, 0xD56D, 0x344E, 0xD56E, 0, - 0, 0x3854, 0x3B68, 0, 0, 0x486E, 0xD56F, 0xD570, - 0, 0x382A, 0x4B43, 0xD571, 0x666F, 0x666D, 0, 0x394E, - 0, 0x394F, 0x3069, 0, 0x3A68, 0, 0, 0, - 0xD572, 0xD573, 0x4759, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E882_x0213[] = { - 0, 0xD56A, 0, 0, 0x6667, 0x6669, 0x6668, 0x4825, - 0xD56B, 0x4679, 0, 0x4F3E, 0x4829, 0, 0xD56C, 0, - 0, 0, 0, 0x666B, 0, 0, 0x3E53, 0, - 0x492A, 0xF530, 0x666C, 0x666A, 0xF531, 0x344E, 0xD56E, 0, - 0, 0x3854, 0x3B68, 0, 0xF532, 0x486E, 0xD56F, 0xF533, - 0, 0x382A, 0x4B43, 0xD571, 0x666F, 0x666D, 0, 0x394E, - 0, 0x394F, 0x3069, 0, 0x3A68, 0, 0, 0, - 0xF534, 0xD573, 0x4759, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E883[] = { - 0, 0, 0, 0x305F, 0x6674, 0, 0x4340, 0, - 0xD574, 0, 0, 0, 0x4758, 0xD575, 0x425B, 0xD576, - 0, 0, 0xD577, 0, 0xD578, 0xD579, 0x6676, 0xD57A, - 0xD57B, 0x6672, 0x6675, 0x6670, 0, 0x6673, 0x4B26, 0, - 0xD57C, 0x3855, 0, 0, 0x307D, 0x6671, 0, 0, - 0, 0, 0, 0, 0, 0xD57D, 0xD57E, 0x6678, - 0xD621, 0x6679, 0xD622, 0xD623, 0x4639, 0, 0xD624, 0, - 0x363B, 0xD625, 0xD626, 0, 0x6726, 0x473D, 0xD627, 0, -}; -static const unsigned short utf8_to_euc_E883_x0213[] = { - 0, 0, 0, 0x305F, 0x6674, 0xF536, 0x4340, 0, - 0xD574, 0, 0x7A4A, 0, 0x4758, 0xD575, 0x425B, 0xD576, - 0, 0, 0xD577, 0, 0xD578, 0xF537, 0x6676, 0x7A4B, - 0xF538, 0x6672, 0x6675, 0x6670, 0, 0x6673, 0x4B26, 0, - 0x7A4C, 0x3855, 0, 0, 0x307D, 0x6671, 0xF539, 0, - 0, 0, 0, 0, 0, 0xD57D, 0xD57E, 0x6678, - 0xD621, 0x6679, 0xD622, 0x7A4D, 0x4639, 0xF53C, 0xD624, 0, - 0x363B, 0xD625, 0xD626, 0xF53D, 0x6726, 0x473D, 0xD627, 0, -}; -static const unsigned short utf8_to_euc_E884[] = { - 0, 0, 0x3B69, 0xD628, 0, 0x363C, 0x4048, 0x4F46, - 0x4C2E, 0x6677, 0x4054, 0xD629, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xD62A, 0xD62B, - 0xD62C, 0, 0x3553, 0x667A, 0xD62D, 0, 0xD62E, 0, - 0xD62F, 0, 0, 0x667C, 0xD630, 0, 0, 0xD631, - 0, 0x667B, 0, 0, 0xD632, 0, 0, 0x667D, - 0xD633, 0x4326, 0, 0x473E, 0, 0xD634, 0, 0, - 0, 0x4431, 0xD635, 0, 0xD636, 0, 0x6723, 0, -}; -static const unsigned short utf8_to_euc_E884_x0213[] = { - 0, 0, 0x3B69, 0xD628, 0, 0x363C, 0x4048, 0x4F46, - 0x4C2E, 0x6677, 0x4054, 0xD629, 0, 0xF53B, 0, 0, - 0, 0, 0, 0, 0, 0, 0xF540, 0xD62B, - 0x7A4E, 0, 0x3553, 0x667A, 0xD62D, 0, 0xF541, 0, - 0xD62F, 0, 0, 0x667C, 0xF543, 0, 0, 0xF544, - 0, 0x667B, 0, 0, 0xF545, 0, 0, 0x667D, - 0xD633, 0x4326, 0, 0x473E, 0, 0xF53F, 0, 0, - 0, 0x4431, 0xD635, 0, 0xD636, 0xF547, 0x6723, 0, -}; -static const unsigned short utf8_to_euc_E885[] = { - 0, 0, 0, 0, 0, 0xD637, 0x6722, 0xD638, - 0, 0, 0xD639, 0x667E, 0xD63A, 0, 0x3F55, 0, - 0x4965, 0x6725, 0xD63B, 0x6724, 0x3950, 0x4F53, 0, 0xD63C, - 0, 0, 0, 0, 0, 0, 0, 0x6735, - 0xD63D, 0xD63E, 0, 0, 0, 0x6729, 0x672A, 0xD63F, - 0xD640, 0xD641, 0, 0x3C70, 0, 0xD642, 0x6728, 0xD643, - 0x3978, 0x6727, 0, 0, 0x672B, 0, 0, 0xD644, - 0x4432, 0x4A22, 0x4123, 0, 0, 0, 0, 0x425C, -}; -static const unsigned short utf8_to_euc_E885_x0213[] = { - 0, 0, 0, 0, 0, 0xD637, 0x6722, 0xD638, - 0, 0, 0x7A4F, 0x667E, 0xD63A, 0, 0x3F55, 0, - 0x4965, 0x6725, 0xD63B, 0x6724, 0x3950, 0x4F53, 0, 0xD63C, - 0, 0, 0, 0, 0, 0, 0, 0x6735, - 0x7A50, 0xD63E, 0, 0, 0, 0x6729, 0x672A, 0x7A51, - 0x7A52, 0xF549, 0, 0x3C70, 0, 0x7A53, 0x6728, 0xD643, - 0x3978, 0x6727, 0, 0, 0x672B, 0, 0, 0xD644, - 0x4432, 0x4A22, 0x4123, 0, 0, 0, 0, 0x425C, -}; -static const unsigned short utf8_to_euc_E886[] = { - 0x672F, 0xD645, 0x6730, 0x672C, 0xD647, 0xD648, 0xD649, 0, - 0x672D, 0, 0x672E, 0xD64A, 0, 0, 0xD64B, 0x3951, - 0xD646, 0, 0, 0x6736, 0, 0x6732, 0xD64C, 0, - 0xD64D, 0, 0x4966, 0xD64E, 0x4B6C, 0x4928, 0xD64F, 0, - 0x6731, 0, 0xD650, 0x6734, 0x6733, 0, 0, 0, - 0x4B44, 0x6737, 0, 0, 0, 0, 0xD651, 0, - 0x6738, 0, 0xD652, 0x4137, 0xD653, 0x6739, 0, 0, - 0x673B, 0, 0x673F, 0xD654, 0, 0x673C, 0x673A, 0x473F, -}; -static const unsigned short utf8_to_euc_E886_x0213[] = { - 0x672F, 0xF54B, 0x6730, 0x672C, 0xF54D, 0xF54E, 0xD649, 0, - 0x672D, 0, 0x672E, 0xD64A, 0, 0, 0xD64B, 0x3951, - 0xD646, 0, 0, 0x6736, 0, 0x6732, 0xD64C, 0, - 0xF550, 0, 0x4966, 0xD64E, 0x4B6C, 0x4928, 0xD64F, 0, - 0x6731, 0, 0xD650, 0x6734, 0x6733, 0, 0, 0, - 0x4B44, 0x6737, 0, 0, 0, 0, 0xD651, 0, - 0x6738, 0, 0xF551, 0x4137, 0xD653, 0x6739, 0, 0, - 0x673B, 0, 0x673F, 0x7A54, 0, 0x673C, 0x673A, 0x473F, -}; -static const unsigned short utf8_to_euc_E887[] = { - 0x673D, 0, 0x673E, 0xD656, 0, 0xD657, 0x3232, 0, - 0x6745, 0x6740, 0xD658, 0xD655, 0, 0x6741, 0xD659, 0xD65A, - 0, 0x6742, 0, 0x4221, 0, 0xD65B, 0, 0xD65C, - 0x6744, 0x6743, 0x6746, 0xD65D, 0, 0xD65E, 0xD65F, 0x6747, - 0x6748, 0xD660, 0, 0x3F43, 0xD661, 0x3269, 0, 0x6749, - 0x4E57, 0, 0x3C2B, 0xD662, 0xD663, 0x3D2D, 0, 0, - 0xD664, 0xD665, 0xD666, 0x3B6A, 0x4357, 0xD667, 0xD668, 0, - 0xD669, 0xD66A, 0x674A, 0x674B, 0x3131, 0xD66B, 0x674C, 0xD66C, -}; -static const unsigned short utf8_to_euc_E887_x0213[] = { - 0x673D, 0xF552, 0x673E, 0xF553, 0, 0xD657, 0x3232, 0, - 0x6745, 0x6740, 0x7A55, 0xD655, 0, 0x6741, 0xD659, 0x7A56, - 0, 0x6742, 0, 0x4221, 0, 0xD65B, 0xF554, 0x7A57, - 0x6744, 0x6743, 0x6746, 0xF555, 0, 0xD65E, 0xD65F, 0x6747, - 0x6748, 0xD660, 0, 0x3F43, 0xF557, 0x3269, 0, 0x6749, - 0x4E57, 0, 0x3C2B, 0xD662, 0xF559, 0x3D2D, 0, 0, - 0xD664, 0xD665, 0xD666, 0x3B6A, 0x4357, 0xD667, 0xD668, 0, - 0xD669, 0xD66A, 0x674A, 0x674B, 0x3131, 0xF55B, 0x674C, 0xF55C, -}; -static const unsigned short utf8_to_euc_E888[] = { - 0xD66D, 0x674D, 0x674E, 0xD66E, 0, 0x674F, 0, 0x6750, - 0x363D, 0x5A2A, 0x6751, 0, 0x4065, 0x6752, 0x3C4B, 0xD66F, - 0x6753, 0, 0x5030, 0xD670, 0xD671, 0, 0x6754, 0x4A5E, - 0x345C, 0xD672, 0xD673, 0x4124, 0x3D58, 0xD674, 0x4971, 0x3D2E, - 0, 0xD675, 0xD676, 0, 0, 0, 0, 0, - 0xD677, 0x6755, 0x3952, 0x6756, 0x484C, 0, 0x6764, 0, - 0, 0, 0xD678, 0x6758, 0xD679, 0x4249, 0x4775, 0x383F, - 0x6757, 0x4125, 0xD67A, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E888_x0213[] = { - 0xD66D, 0x674D, 0x674E, 0xD66E, 0xF55E, 0x674F, 0, 0x6750, - 0x363D, 0x5A2A, 0x6751, 0, 0x4065, 0x6752, 0x3C4B, 0xD66F, - 0x6753, 0, 0x5030, 0xD670, 0xD671, 0, 0x6754, 0x4A5E, - 0x345C, 0xF560, 0xD673, 0x4124, 0x3D58, 0xD674, 0x4971, 0x3D2E, - 0, 0xF561, 0xF562, 0, 0, 0, 0, 0, - 0xD677, 0x6755, 0x3952, 0x6756, 0x484C, 0, 0x6764, 0, - 0, 0, 0xF564, 0x6758, 0xF565, 0x4249, 0x4775, 0x383F, - 0x6757, 0x4125, 0xD67A, 0, 0xF566, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E889[] = { - 0x6759, 0, 0, 0xD67B, 0xD67C, 0xD67D, 0xD67E, 0x447A, - 0, 0, 0, 0xD721, 0, 0, 0xD722, 0xD723, - 0, 0xD724, 0, 0, 0, 0, 0xD725, 0, - 0x675B, 0x675A, 0x675D, 0, 0xD726, 0x675C, 0, 0x675E, - 0xD727, 0, 0x6760, 0xD728, 0x675F, 0, 0x344F, 0xD729, - 0x6761, 0, 0x6762, 0x6763, 0, 0xD72A, 0x3A31, 0x4E49, - 0, 0x6765, 0x3F27, 0, 0xD72B, 0, 0x3170, 0x6766, - 0x6767, 0, 0, 0xD72C, 0, 0xD72D, 0x6768, 0xD72E, -}; -static const unsigned short utf8_to_euc_E889_x0213[] = { - 0x6759, 0, 0, 0xD67B, 0xD67C, 0xF569, 0xF567, 0x447A, - 0, 0xF568, 0, 0xF56B, 0, 0, 0xD722, 0xF56D, - 0, 0xD724, 0, 0, 0, 0, 0xD725, 0xF56F, - 0x675B, 0x675A, 0x675D, 0, 0xF571, 0x675C, 0, 0x675E, - 0x7A5B, 0, 0x6760, 0xF572, 0x675F, 0, 0x344F, 0xD729, - 0x6761, 0, 0x6762, 0x6763, 0, 0xD72A, 0x3A31, 0x4E49, - 0, 0x6765, 0x3F27, 0, 0x7A5C, 0, 0x3170, 0x6766, - 0x6767, 0xF576, 0, 0xD72C, 0, 0xF578, 0x6768, 0xF579, -}; -static const unsigned short utf8_to_euc_E88A[] = { - 0xD72F, 0xD730, 0, 0xD731, 0xD732, 0, 0, 0xD733, - 0, 0xD734, 0xD735, 0x3072, 0, 0x6769, 0xD736, 0, - 0, 0xD737, 0x676A, 0, 0xD738, 0, 0xD739, 0, - 0xD73A, 0x4967, 0xD73B, 0xD73C, 0, 0x3C47, 0, 0x676C, - 0xD73D, 0xD73E, 0, 0xD73F, 0xD740, 0x3329, 0x3032, 0xD741, - 0xD742, 0xD743, 0xD744, 0x676B, 0x676E, 0x474E, 0xD745, 0x3F44, - 0xD746, 0x3256, 0xD747, 0x4B27, 0xD748, 0, 0, 0xD749, - 0x375D, 0x365C, 0xD74A, 0x676D, 0xD74B, 0x326A, 0xD74C, 0xD74D, -}; -static const unsigned short utf8_to_euc_E88A_x0213[] = { - 0xD72F, 0xD730, 0, 0xF57A, 0xD732, 0, 0, 0xD733, - 0, 0xD734, 0xF57B, 0x3072, 0, 0x6769, 0x7A5E, 0, - 0, 0xD737, 0x676A, 0xF57C, 0xD738, 0, 0xD739, 0, - 0xD73A, 0x4967, 0xD73B, 0xD73C, 0, 0x3C47, 0, 0x676C, - 0xD73D, 0x7A5F, 0, 0x7A60, 0x7A61, 0x3329, 0x3032, 0xF57D, - 0xF57E, 0x7A62, 0xD744, 0x676B, 0x676E, 0x474E, 0x7A63, 0x3F44, - 0xD746, 0x3256, 0xF621, 0x4B27, 0xF622, 0, 0, 0x7A64, - 0x375D, 0x365C, 0xF623, 0x676D, 0xF624, 0x326A, 0x7A65, 0x7A66, -}; -static const unsigned short utf8_to_euc_E88B[] = { - 0, 0, 0, 0, 0, 0x3423, 0xD74E, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xD74F, 0x3171, 0x6772, 0x4E6A, 0x425D, 0xD750, 0, 0x4944, - 0, 0x677E, 0xD751, 0x3257, 0x677C, 0, 0x677A, 0x6771, - 0xD752, 0x676F, 0xD753, 0x6770, 0xD754, 0x3C63, 0x366C, 0x4377, - 0xD755, 0, 0xD756, 0x4651, 0, 0xD757, 0, 0xD758, - 0, 0x3151, 0, 0x6774, 0x6773, 0, 0xD759, 0xD75A, - 0, 0x6779, 0x6775, 0x6778, 0, 0xD75B, 0xD75C, 0, -}; -static const unsigned short utf8_to_euc_E88B_x0213[] = { - 0, 0, 0, 0, 0, 0x3423, 0x7A67, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xD74F, 0x3171, 0x6772, 0x4E6A, 0x425D, 0x7A68, 0, 0x4944, - 0, 0x677E, 0xD751, 0x3257, 0x677C, 0, 0x677A, 0x6771, - 0xD752, 0x676F, 0xF625, 0x6770, 0xD754, 0x3C63, 0x366C, 0x4377, - 0xF626, 0, 0xD756, 0x4651, 0, 0xD757, 0, 0xD758, - 0, 0x3151, 0, 0x6774, 0x6773, 0, 0xD759, 0xF627, - 0, 0x6779, 0x6775, 0x6778, 0, 0x7A69, 0x7A6A, 0, -}; -static const unsigned short utf8_to_euc_E88C[] = { - 0xD75D, 0xD75E, 0x4C50, 0x6777, 0x3258, 0x337D, 0x677B, 0xD75F, - 0xD760, 0x677D, 0xD761, 0xD762, 0, 0, 0x3754, 0, - 0, 0, 0, 0, 0, 0, 0x6823, 0x682C, - 0x682D, 0, 0, 0xD764, 0x302B, 0xD765, 0xD766, 0xD767, - 0, 0xD768, 0xD769, 0x6834, 0, 0, 0, 0, - 0x3071, 0, 0, 0x682B, 0xD76A, 0xD76B, 0xD76C, 0x682A, - 0xD76D, 0x6825, 0x6824, 0xD76E, 0x6822, 0x6821, 0x4363, 0xD76F, - 0x427B, 0x6827, 0xD770, 0, 0xD771, 0xD772, 0, 0, -}; -static const unsigned short utf8_to_euc_E88C_x0213[] = { - 0x7A6B, 0x7A6C, 0x4C50, 0x6777, 0x3258, 0x337D, 0x677B, 0xF628, - 0xF629, 0x677D, 0xD761, 0xD762, 0xF62A, 0, 0x3754, 0, - 0, 0, 0, 0, 0, 0, 0x6823, 0x682C, - 0x682D, 0, 0, 0xF62C, 0x302B, 0xF62D, 0xD766, 0xD767, - 0, 0xD768, 0x7A6E, 0x6834, 0, 0, 0, 0, - 0x3071, 0, 0, 0x682B, 0xD76A, 0x7A6F, 0xD76C, 0x682A, - 0xF62E, 0x6825, 0x6824, 0xD76E, 0x6822, 0x6821, 0x4363, 0xD76F, - 0x427B, 0x6827, 0x7A70, 0, 0xF62F, 0xD772, 0, 0, -}; -static const unsigned short utf8_to_euc_E88D[] = { - 0x6826, 0, 0xD773, 0xD774, 0xD775, 0x6829, 0, 0xD776, - 0, 0x4170, 0x3755, 0, 0, 0xD777, 0xD778, 0x3141, - 0x6828, 0xD779, 0x3953, 0xD83E, 0xD763, 0xD77A, 0xD77B, 0xD77C, - 0x4171, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xF45F, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xD77D, 0, 0, 0x683A, 0, 0x683B, 0, 0x3259, - 0xD77E, 0, 0, 0x322E, 0x6838, 0xD821, 0, 0xD822, -}; -static const unsigned short utf8_to_euc_E88D_x0213[] = { - 0x6826, 0, 0xD773, 0x7A71, 0xF630, 0x6829, 0, 0x7A72, - 0, 0x4170, 0x3755, 0, 0, 0xD777, 0xD778, 0x3141, - 0x6828, 0x7A73, 0x3953, 0xD83E, 0xF62B, 0x7A74, 0xD77B, 0xF631, - 0x4171, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x7A6D, 0xAE4A, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xD77D, 0, 0, 0x683A, 0, 0x683B, 0, 0x3259, - 0xD77E, 0, 0, 0x322E, 0x6838, 0x7A75, 0, 0xF633, -}; -static const unsigned short utf8_to_euc_E88E[] = { - 0xD823, 0, 0xD824, 0, 0xD825, 0x682E, 0xD826, 0x6836, - 0, 0x683D, 0x6837, 0, 0, 0xD827, 0x6835, 0, - 0, 0, 0xD828, 0x6776, 0xD829, 0xD82A, 0x6833, 0, - 0xD82B, 0xD82C, 0x682F, 0xD82D, 0xD82E, 0xD82F, 0x3450, 0x6831, - 0x683C, 0, 0x6832, 0, 0, 0, 0xD830, 0xD831, - 0x683E, 0xD832, 0x6830, 0x477C, 0xD833, 0xD84C, 0, 0, - 0, 0x4D69, 0, 0, 0, 0x6839, 0, 0, - 0, 0, 0, 0, 0, 0x684F, 0xD834, 0xD835, -}; -static const unsigned short utf8_to_euc_E88E_x0213[] = { - 0xD823, 0, 0xD824, 0, 0xD825, 0x682E, 0x7A76, 0x6836, - 0, 0x683D, 0x6837, 0, 0, 0xF636, 0x6835, 0, - 0, 0, 0x7A77, 0x6776, 0xF637, 0xF638, 0x6833, 0, - 0x7A78, 0xD82C, 0x682F, 0xF639, 0xD82E, 0xF63A, 0x3450, 0x6831, - 0x683C, 0, 0x6832, 0, 0, 0, 0xD830, 0x7A79, - 0x683E, 0x7A7A, 0x6830, 0x477C, 0xD833, 0xD84C, 0, 0, - 0, 0x4D69, 0, 0, 0, 0x6839, 0, 0, - 0, 0, 0, 0, 0, 0x684F, 0xD834, 0x7A7B, -}; -static const unsigned short utf8_to_euc_E88F[] = { - 0xD836, 0x6847, 0, 0, 0, 0x3F7B, 0, 0xD837, - 0, 0xD838, 0x3546, 0, 0x365D, 0, 0x6842, 0xD839, - 0xD83A, 0xD83B, 0, 0x325B, 0xD83C, 0, 0x3E54, 0, - 0x6845, 0, 0, 0, 0x3A5A, 0xD83D, 0, 0x4551, - 0x684A, 0, 0, 0, 0, 0, 0, 0, - 0xD83F, 0x4A6E, 0xD840, 0x6841, 0, 0, 0, 0x325A, - 0x3856, 0x4929, 0x684B, 0, 0x683F, 0, 0xD841, 0x6848, - 0xD842, 0xD843, 0, 0x6852, 0xD844, 0x6843, 0, 0, -}; -static const unsigned short utf8_to_euc_E88F_x0213[] = { - 0x7A7C, 0x6847, 0, 0, 0, 0x3F7B, 0, 0x7A7D, - 0, 0xF63B, 0x3546, 0, 0x365D, 0, 0x6842, 0x7A7E, - 0xF63C, 0x7B21, 0, 0x325B, 0xF63D, 0, 0x3E54, 0, - 0x6845, 0, 0, 0, 0x3A5A, 0xF63E, 0, 0x4551, - 0x684A, 0x7B22, 0, 0, 0, 0xF63F, 0, 0, - 0xD83F, 0x4A6E, 0x7B23, 0x6841, 0, 0, 0, 0x325A, - 0x3856, 0x4929, 0x684B, 0, 0x683F, 0, 0, 0x6848, - 0xD842, 0xF640, 0, 0x6852, 0xD844, 0x6843, 0, 0, -}; -static const unsigned short utf8_to_euc_E890[] = { - 0, 0xD845, 0, 0x6844, 0x463A, 0, 0xD846, 0x6849, - 0, 0, 0xD847, 0x6846, 0x4B28, 0x684C, 0x3060, 0xD848, - 0, 0xD849, 0, 0x6840, 0, 0xD84A, 0, 0, - 0, 0xD84B, 0, 0, 0, 0, 0, 0, - 0x684E, 0, 0x684D, 0, 0, 0, 0, 0, - 0, 0x476B, 0x6854, 0, 0x685F, 0, 0, 0xD84D, - 0, 0x337E, 0, 0, 0, 0x6862, 0, 0, - 0x6850, 0xD84E, 0, 0, 0x6855, 0x4D6E, 0, 0, -}; -static const unsigned short utf8_to_euc_E890_x0213[] = { - 0, 0x7B24, 0, 0x6844, 0x463A, 0, 0x7B25, 0x6849, - 0, 0, 0x7B26, 0x6846, 0x4B28, 0x684C, 0x3060, 0xF641, - 0, 0xF642, 0, 0x6840, 0, 0xF643, 0, 0xF645, - 0, 0xD84B, 0, 0, 0, 0, 0, 0, - 0x684E, 0, 0x684D, 0, 0, 0, 0, 0, - 0, 0x476B, 0x6854, 0, 0x685F, 0, 0, 0xD84D, - 0, 0x337E, 0, 0, 0, 0x6862, 0, 0, - 0x6850, 0xF646, 0, 0, 0x6855, 0x4D6E, 0, 0, -}; -static const unsigned short utf8_to_euc_E891[] = { - 0, 0, 0, 0, 0, 0xD84F, 0x685E, 0xD850, - 0xD851, 0x4D55, 0xD852, 0, 0, 0xD853, 0x4E2A, 0xD854, - 0, 0xD855, 0xD856, 0, 0, 0, 0xD857, 0x4378, - 0xD858, 0xD859, 0xD85A, 0x336B, 0xD85B, 0, 0, 0, - 0xD85C, 0x4972, 0x6864, 0x4621, 0xD85D, 0xD85E, 0x3031, 0xD85F, - 0, 0x685D, 0xD860, 0x6859, 0x4172, 0x6853, 0x685B, 0x6860, - 0xD861, 0x472C, 0, 0xD862, 0xD863, 0x302A, 0xD864, 0x6858, - 0xD865, 0x6861, 0x4978, 0, 0xD866, 0xD867, 0, 0, -}; -static const unsigned short utf8_to_euc_E891_x0213[] = { - 0, 0, 0, 0, 0, 0xD84F, 0x685E, 0xD850, - 0x7B28, 0x4D55, 0xF647, 0, 0, 0xD853, 0x4E2A, 0xF648, - 0, 0xF649, 0xF64A, 0, 0, 0, 0xD857, 0x4378, - 0xD858, 0xF64B, 0xF64C, 0x336B, 0xF64D, 0, 0, 0x7B29, - 0xD85C, 0x4972, 0x6864, 0x4621, 0xD85D, 0xF64F, 0x3031, 0xD85F, - 0, 0x685D, 0xD860, 0x6859, 0x4172, 0x6853, 0x685B, 0x6860, - 0x7B2A, 0x472C, 0, 0x7B2B, 0xD863, 0x302A, 0xF650, 0x6858, - 0xF651, 0x6861, 0x4978, 0, 0xF652, 0xD867, 0, 0, -}; -static const unsigned short utf8_to_euc_E892[] = { - 0, 0xD868, 0x685C, 0, 0x6857, 0xD869, 0, 0, - 0, 0, 0, 0x3E55, 0, 0, 0, 0, - 0x3D2F, 0, 0xD86A, 0xD86B, 0x3C2C, 0xD86C, 0, 0, - 0, 0x4C58, 0, 0, 0x4947, 0, 0xD86D, 0x6867, - 0, 0x6870, 0, 0, 0, 0, 0xD86E, 0, - 0xD86F, 0xD870, 0xD871, 0, 0, 0x685A, 0, 0xD872, - 0, 0xD873, 0x3377, 0, 0xD874, 0, 0, 0, - 0x3E78, 0x6865, 0xD875, 0x686A, 0x4173, 0xD876, 0xD877, 0x6866, -}; -static const unsigned short utf8_to_euc_E892_x0213[] = { - 0, 0xF653, 0x685C, 0, 0x6857, 0x7B2C, 0, 0, - 0, 0, 0, 0x3E55, 0, 0, 0, 0, - 0x3D2F, 0, 0xD86A, 0xD86B, 0x3C2C, 0xD86C, 0, 0xF656, - 0, 0x4C58, 0, 0, 0x4947, 0, 0x7B2D, 0x6867, - 0, 0x6870, 0, 0, 0, 0, 0xF657, 0, - 0xD86F, 0xD870, 0xD871, 0, 0, 0x685A, 0, 0x7B2E, - 0, 0xD873, 0x3377, 0, 0x7B2F, 0, 0, 0, - 0x3E78, 0x6865, 0x7B30, 0x686A, 0x4173, 0xD876, 0xF658, 0x6866, -}; -static const unsigned short utf8_to_euc_E893[] = { - 0xD878, 0x686D, 0xD879, 0, 0x435F, 0, 0x686E, 0xD87A, - 0xD87B, 0x4D56, 0x6863, 0x3338, 0xD87C, 0x6869, 0, 0xD87D, - 0x686C, 0x4C2C, 0, 0xD87E, 0, 0, 0x686F, 0, - 0, 0x6868, 0x686B, 0, 0xD921, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xD922, - 0, 0, 0xD923, 0, 0x4B29, 0, 0x4F21, 0xD924, - 0xD925, 0xD926, 0xD927, 0, 0x6873, 0, 0, 0xD928, - 0, 0, 0xD92A, 0xD92B, 0x687A, 0xD92C, 0, 0x6872, -}; -static const unsigned short utf8_to_euc_E893_x0213[] = { - 0x7B31, 0x686D, 0x7B32, 0, 0x435F, 0, 0x686E, 0xD87A, - 0xD87B, 0x4D56, 0x6863, 0x3338, 0xD87C, 0x6869, 0xF65A, 0xF65B, - 0x686C, 0x4C2C, 0, 0xF65C, 0, 0, 0x686F, 0, - 0, 0x6868, 0x686B, 0, 0xF655, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xF65E, - 0, 0, 0xF65F, 0, 0x4B29, 0, 0x4F21, 0xF660, - 0xF661, 0xF662, 0xD927, 0, 0x6873, 0, 0, 0xD928, - 0, 0, 0xF663, 0xD92B, 0x687A, 0xF664, 0, 0x6872, -}; -static const unsigned short utf8_to_euc_E894[] = { - 0x3C43, 0, 0xD92D, 0xD92E, 0, 0, 0x6851, 0xD92F, - 0, 0, 0, 0, 0xD930, 0, 0xD931, 0, - 0xD932, 0x4A4E, 0, 0x4C22, 0x6879, 0x6878, 0, 0x6874, - 0x6875, 0, 0x3136, 0, 0xD933, 0, 0xD934, 0x6877, - 0, 0x6871, 0xD935, 0xD936, 0xD937, 0xD938, 0x4455, 0xD939, - 0, 0, 0xD93A, 0xD93B, 0x6876, 0x307E, 0, 0xD93C, - 0, 0, 0xD929, 0xD93D, 0xD93E, 0x4222, 0xD93F, 0, - 0, 0, 0, 0, 0, 0x4A43, 0, 0xD940, -}; -static const unsigned short utf8_to_euc_E894_x0213[] = { - 0x3C43, 0, 0xD92D, 0xD92E, 0, 0, 0x6851, 0xD92F, - 0, 0, 0, 0, 0xF665, 0, 0xD931, 0, - 0xD932, 0x4A4E, 0, 0x4C22, 0x6879, 0x6878, 0, 0x6874, - 0x6875, 0, 0x3136, 0xF666, 0xD933, 0, 0x7B35, 0x6877, - 0, 0x6871, 0xD935, 0x7B36, 0xF667, 0xF668, 0x4455, 0xD939, - 0, 0, 0xD93A, 0xF669, 0x6876, 0x307E, 0, 0x7B37, - 0, 0, 0x7B34, 0xD93D, 0xF66A, 0x4222, 0xD93F, 0, - 0, 0, 0, 0, 0, 0x4A43, 0xF66F, 0xD940, -}; -static const unsigned short utf8_to_euc_E895[] = { - 0x687B, 0x6921, 0, 0x4859, 0, 0, 0xD941, 0, - 0x687E, 0x3E56, 0x3C49, 0x6923, 0, 0, 0x363E, 0xD942, - 0xD943, 0xD944, 0xD945, 0xD946, 0, 0x6924, 0xD947, 0x4979, - 0x687D, 0xD948, 0x6856, 0, 0xD949, 0xD94A, 0xD94B, 0xD94C, - 0xD94D, 0xD94E, 0xD94F, 0x687C, 0xD950, 0, 0, 0, - 0x4F4F, 0x4622, 0x4973, 0xD951, 0, 0x692B, 0, 0xD952, - 0, 0, 0, 0, 0, 0, 0, 0x6931, - 0, 0xD953, 0xD954, 0xD955, 0, 0xD956, 0x6932, 0xD957, -}; -static const unsigned short utf8_to_euc_E895_x0213[] = { - 0x687B, 0x6921, 0, 0x4859, 0, 0, 0xD941, 0, - 0x687E, 0x3E56, 0x3C49, 0x6923, 0, 0, 0x363E, 0xF66B, - 0xD943, 0xF670, 0xD945, 0xF671, 0, 0x6924, 0xD947, 0x4979, - 0x687D, 0x7B38, 0x6856, 0, 0xD949, 0xD94A, 0xF672, 0xD94C, - 0xD94D, 0xF673, 0xF674, 0x687C, 0x7B39, 0, 0, 0, - 0x4F4F, 0x4622, 0x4973, 0, 0, 0x692B, 0, 0xF66C, - 0, 0, 0, 0, 0, 0, 0, 0x6931, - 0, 0xD953, 0x7B3C, 0xF676, 0, 0xF677, 0x6932, 0xF678, -}; -static const unsigned short utf8_to_euc_E896[] = { - 0x6925, 0xD958, 0, 0, 0x4776, 0xD959, 0xD95A, 0x692F, - 0x6927, 0xD95B, 0x6929, 0xD95C, 0xD95D, 0, 0, 0xD95E, - 0x6933, 0x6928, 0, 0xD95F, 0x692C, 0, 0, 0x3172, - 0xD960, 0x4665, 0, 0x692D, 0x6930, 0xD961, 0, 0xD962, - 0xD963, 0, 0xD964, 0, 0x6926, 0xD965, 0x4126, 0xD966, - 0x692A, 0x3B27, 0x3F45, 0x3730, 0x4C74, 0xD974, 0x4C79, 0x3D72, - 0xF461, 0, 0, 0, 0xD967, 0, 0xD968, 0xD969, - 0xD96A, 0x6937, 0x6935, 0, 0xD96B, 0xD96C, 0xD96D, 0xD96E, -}; -static const unsigned short utf8_to_euc_E896_x0213[] = { - 0x6925, 0xF679, 0, 0, 0x4776, 0xD959, 0xF67A, 0x692F, - 0x6927, 0xD95B, 0x6929, 0xD95C, 0x7B3D, 0, 0, 0x7B3E, - 0x6933, 0x6928, 0, 0xF67B, 0x692C, 0, 0, 0x3172, - 0xD960, 0x4665, 0, 0x692D, 0x6930, 0xF67C, 0, 0xF67D, - 0xD963, 0, 0x7B3F, 0, 0x6926, 0xD965, 0x4126, 0xD966, - 0x692A, 0x3B27, 0x3F45, 0x3730, 0x4C74, 0x7B3B, 0x4C79, 0x3D72, - 0x7B40, 0, 0, 0, 0xD967, 0, 0xD968, 0xF723, - 0xD96A, 0x6937, 0x6935, 0, 0xF724, 0xD96C, 0xD96D, 0xD96E, -}; -static const unsigned short utf8_to_euc_E897[] = { - 0, 0x4F4E, 0xD96F, 0, 0, 0, 0, 0xD970, - 0, 0x6934, 0xD971, 0xD972, 0, 0x4D75, 0xD973, 0x6936, - 0x6938, 0, 0, 0, 0, 0x6939, 0, 0, - 0xD975, 0, 0xD976, 0, 0x693C, 0x693A, 0, 0xD977, - 0xD978, 0, 0, 0, 0x4623, 0x693B, 0xD979, 0, - 0xD97A, 0x484D, 0x692E, 0, 0, 0xD97B, 0, 0, - 0, 0, 0, 0xD97C, 0, 0, 0xD97D, 0x3D73, - 0, 0x693D, 0x6942, 0x4174, 0xD97E, 0, 0x6941, 0xDA21, -}; -static const unsigned short utf8_to_euc_E897_x0213[] = { - 0, 0x4F4E, 0xD96F, 0, 0, 0, 0, 0xF725, - 0, 0x6934, 0xF726, 0x7B41, 0, 0x4D75, 0x7B42, 0x6936, - 0x6938, 0, 0, 0, 0, 0x6939, 0, 0, - 0xF727, 0xF728, 0xD976, 0, 0x693C, 0x693A, 0, 0xF729, - 0xD978, 0xF72A, 0, 0, 0x4623, 0x693B, 0xF72B, 0, - 0xD97A, 0x484D, 0x692E, 0, 0, 0x7B43, 0, 0, - 0, 0, 0, 0xD97C, 0, 0, 0xF72C, 0x3D73, - 0, 0x693D, 0x6942, 0x4174, 0xD97E, 0, 0x6941, 0x7B45, -}; -static const unsigned short utf8_to_euc_E898[] = { - 0xDA22, 0, 0x6922, 0, 0xDA23, 0xDA24, 0x6943, 0x4149, - 0, 0, 0x693E, 0x6940, 0, 0xDA25, 0xDA26, 0, - 0xDA27, 0xDA28, 0xDA29, 0x693F, 0, 0, 0x5D31, 0x5D22, - 0xDA2A, 0xDA2B, 0x6945, 0xDA2C, 0, 0, 0xDA2D, 0, - 0, 0xDA2E, 0x6944, 0, 0, 0, 0, 0xDA2F, - 0, 0xDA30, 0, 0, 0, 0x4D76, 0, 0x623C, - 0x6946, 0, 0, 0, 0, 0, 0xDA31, 0, - 0xDA32, 0, 0xDA33, 0, 0xDA34, 0xDA35, 0, 0x6947, -}; -static const unsigned short utf8_to_euc_E898_x0213[] = { - 0xF72D, 0, 0x6922, 0, 0x7B46, 0x7B47, 0x6943, 0x4149, - 0, 0, 0x693E, 0x6940, 0, 0xDA25, 0xDA26, 0, - 0x7B48, 0xF72E, 0x7B44, 0x693F, 0, 0, 0x5D31, 0x5D22, - 0x7B4A, 0xDA2B, 0x6945, 0xDA2C, 0, 0, 0xF72F, 0, - 0, 0xF730, 0x6944, 0, 0xF731, 0, 0, 0xF732, - 0, 0x7B4B, 0, 0, 0, 0x4D76, 0, 0x623C, - 0x6946, 0, 0, 0, 0, 0, 0xDA31, 0, - 0x7B4C, 0xF734, 0xDA33, 0, 0xF735, 0xDA35, 0, 0x6947, -}; -static const unsigned short utf8_to_euc_E899[] = { - 0xDA36, 0xB866, 0xDA37, 0, 0, 0, 0xDA38, 0, - 0, 0, 0, 0, 0, 0x6948, 0x3857, 0, - 0x3554, 0, 0xDA39, 0xDA3A, 0x694A, 0x515D, 0xDA3B, 0xDA3C, - 0xDA3D, 0xDA3E, 0x3575, 0, 0x4E3A, 0xDA3F, 0x3673, 0x694B, - 0xDA40, 0xDA41, 0xDA42, 0xDA43, 0xDA44, 0, 0, 0x694C, - 0, 0xDA45, 0, 0x436E, 0xDA46, 0, 0, 0xDA47, - 0, 0x694D, 0, 0, 0, 0xDA48, 0xDA49, 0xDA4A, - 0, 0x467A, 0xDA4B, 0x303A, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E899_x0213[] = { - 0xF737, 0x2F68, 0xDA37, 0, 0, 0, 0xDA38, 0, - 0, 0, 0, 0, 0, 0x6948, 0x3857, 0, - 0x3554, 0, 0xDA39, 0xF739, 0x694A, 0x515D, 0xF73A, 0x7B4D, - 0xDA3D, 0xDA3E, 0x3575, 0x7B4E, 0x4E3A, 0xDA3F, 0x3673, 0x694B, - 0xDA40, 0xDA41, 0x7B50, 0xDA43, 0xDA44, 0, 0, 0x694C, - 0, 0xDA45, 0, 0x436E, 0x7B52, 0, 0, 0xF73B, - 0, 0x694D, 0, 0, 0, 0x7B53, 0xDA49, 0xF73C, - 0, 0x467A, 0xF73D, 0x303A, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E89A[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0xDA6D, 0, 0x3263, 0x6952, 0x6953, 0xDA4C, 0, 0, - 0, 0xDA4D, 0, 0x694E, 0, 0x3B3D, 0xDA4E, 0, - 0xDA4F, 0, 0xDA50, 0, 0xDA51, 0, 0, 0, - 0, 0xDA52, 0, 0x694F, 0x4742, 0, 0xDA53, 0xDA54, - 0xDA55, 0x6950, 0x6951, 0x695B, 0, 0xDA56, 0, 0x6955, - 0x6958, 0xDA57, 0, 0xDA58, 0xDA59, 0xDA5A, 0x6954, 0xDA5B, - 0xDA5C, 0xDA5D, 0, 0, 0, 0, 0, 0xDA5E, -}; -static const unsigned short utf8_to_euc_E89A_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0xF73E, - 0xDA6D, 0xF73F, 0x3263, 0x6952, 0x6953, 0xF740, 0, 0, - 0, 0xF741, 0, 0x694E, 0, 0x3B3D, 0xDA4E, 0, - 0x7B54, 0, 0xDA50, 0, 0xF742, 0xF743, 0, 0, - 0, 0xDA52, 0, 0x694F, 0x4742, 0, 0xDA53, 0xDA54, - 0xF744, 0x6950, 0x6951, 0x695B, 0, 0xDA56, 0, 0x6955, - 0x6958, 0xF746, 0, 0xF747, 0xDA59, 0xDA5A, 0x6954, 0xDA5B, - 0x7B55, 0xDA5D, 0, 0, 0, 0, 0, 0xDA5E, -}; -static const unsigned short utf8_to_euc_E89B[] = { - 0xDA5F, 0xDA60, 0, 0xDA61, 0x6956, 0xDA62, 0x6957, 0x3C58, - 0, 0x6959, 0, 0x4341, 0, 0x3756, 0x3342, 0, - 0, 0xDA63, 0xDA64, 0, 0x695C, 0xDA65, 0, 0xDA66, - 0, 0x333F, 0xDA67, 0x6961, 0xDA68, 0, 0x695D, 0x6960, - 0xDA69, 0, 0, 0xDA6A, 0x483A, 0xDA6B, 0, 0xDA6C, - 0, 0x695E, 0, 0, 0x695F, 0x4948, 0x485A, 0x6962, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x427D, 0x696C, 0xDA6E, 0x6968, 0xDA6F, 0xDA70, 0x326B, 0, -}; -static const unsigned short utf8_to_euc_E89B_x0213[] = { - 0xDA5F, 0xF748, 0, 0xF749, 0x6956, 0xDA62, 0x6957, 0x3C58, - 0, 0x6959, 0, 0x4341, 0, 0x3756, 0x3342, 0, - 0, 0xF74A, 0xDA64, 0, 0x695C, 0xF74B, 0, 0xF74C, - 0, 0x333F, 0xDA67, 0x6961, 0xDA68, 0, 0x695D, 0x6960, - 0xDA69, 0, 0, 0xF74D, 0x483A, 0xDA6B, 0xF74E, 0xDA6C, - 0, 0x695E, 0, 0, 0x695F, 0x4948, 0x485A, 0x6962, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x427D, 0x696C, 0x7B56, 0x6968, 0x7B57, 0x7B58, 0x326B, 0, -}; -static const unsigned short utf8_to_euc_E89C[] = { - 0x6966, 0, 0x4B2A, 0x6967, 0xDA71, 0xDA72, 0x6964, 0xDA73, - 0x6965, 0x696A, 0x696D, 0xDA74, 0, 0x696B, 0xDA75, 0xDA76, - 0xDA77, 0x6969, 0x6963, 0xDA78, 0xDA79, 0, 0, 0, - 0x4358, 0xDA7A, 0x6974, 0, 0x4C2A, 0, 0xDA7B, 0xDA7C, - 0, 0xDA7D, 0, 0xDA7E, 0, 0x6972, 0, 0, - 0xDB21, 0x6973, 0, 0, 0, 0, 0xDB22, 0xDB23, - 0, 0xDB24, 0xDB25, 0, 0x696E, 0, 0, 0x6970, - 0, 0xDB26, 0xDB27, 0x6971, 0xDB28, 0xDB29, 0xDB2A, 0x696F, -}; -static const unsigned short utf8_to_euc_E89C_x0213[] = { - 0x6966, 0, 0x4B2A, 0x6967, 0xDA71, 0xF750, 0x6964, 0xF751, - 0x6965, 0x696A, 0x696D, 0x7B59, 0, 0x696B, 0xF752, 0xDA76, - 0xF753, 0x6969, 0x6963, 0xF754, 0xDA79, 0, 0, 0, - 0x4358, 0xF755, 0x6974, 0, 0x4C2A, 0, 0xDA7B, 0xF756, - 0, 0xF757, 0, 0xF758, 0, 0x6972, 0, 0, - 0xDB21, 0x6973, 0, 0, 0, 0, 0xDB22, 0xDB23, - 0, 0xF759, 0xDB25, 0, 0x696E, 0, 0, 0x6970, - 0, 0xDB26, 0xF75A, 0x6971, 0xDB28, 0xDB29, 0xF75B, 0x696F, -}; -static const unsigned short utf8_to_euc_E89D[] = { - 0xDB2B, 0, 0, 0xDB2C, 0, 0xDB2D, 0, 0, - 0, 0x4066, 0, 0x4F39, 0x6978, 0xDB2E, 0x6979, 0, - 0, 0, 0, 0x6A21, 0, 0x3F2A, 0, 0x697B, - 0xDB2F, 0x697E, 0, 0, 0, 0xDB30, 0, 0x6976, - 0x6975, 0xDB31, 0, 0x6A22, 0xDB32, 0xDB33, 0x325C, 0, - 0x697C, 0, 0x6A23, 0, 0, 0, 0x697D, 0xDB34, - 0, 0xDB35, 0xDB36, 0, 0x697A, 0, 0x4433, 0, - 0x6977, 0, 0, 0xDB37, 0, 0, 0, 0x4768, -}; -static const unsigned short utf8_to_euc_E89D_x0213[] = { - 0xF75C, 0, 0, 0xF75D, 0, 0xDB2D, 0, 0, - 0, 0x4066, 0, 0x4F39, 0x6978, 0xDB2E, 0x6979, 0, - 0, 0xF75E, 0, 0x6A21, 0, 0x3F2A, 0, 0x697B, - 0xF75F, 0x697E, 0, 0, 0, 0xDB30, 0, 0x6976, - 0x6975, 0xDB31, 0, 0x6A22, 0xF760, 0xF761, 0x325C, 0, - 0x697C, 0, 0x6A23, 0, 0, 0, 0x697D, 0xDB34, - 0, 0x7B5A, 0xF762, 0, 0x697A, 0, 0x4433, 0, - 0x6977, 0, 0, 0xDB37, 0xF763, 0, 0, 0x4768, -}; -static const unsigned short utf8_to_euc_E89E[] = { - 0, 0, 0x6A27, 0xDB38, 0xDB39, 0xDB3A, 0xDB3B, 0xDB3C, - 0xDB3D, 0xDB3E, 0, 0xDB3F, 0xDB40, 0x4D3B, 0, 0, - 0xDB41, 0, 0, 0xDB42, 0, 0xDB43, 0, 0xDB44, - 0xDB45, 0xDB46, 0, 0, 0, 0, 0xDB47, 0x6A26, - 0xDB48, 0, 0x6A25, 0xDB49, 0, 0, 0, 0xDB4A, - 0, 0, 0, 0x6A2E, 0xDB4B, 0xDB4C, 0xDB4D, 0x6A28, - 0, 0xDB4E, 0, 0x6A30, 0, 0xDB4F, 0, 0, - 0, 0, 0x4D66, 0x6A33, 0, 0x6A2A, 0xDB50, 0xDB51, -}; -static const unsigned short utf8_to_euc_E89E_x0213[] = { - 0, 0, 0x6A27, 0xDB38, 0xDB39, 0xDB3A, 0xDB3B, 0x7B5B, - 0x7B5C, 0xF767, 0, 0xF768, 0xDB40, 0x4D3B, 0, 0, - 0xDB41, 0, 0, 0xF769, 0, 0xDB43, 0, 0xDB44, - 0xDB45, 0xDB46, 0, 0, 0, 0, 0xDB47, 0x6A26, - 0xF76A, 0, 0x6A25, 0xDB49, 0, 0, 0, 0xF766, - 0, 0, 0, 0x6A2E, 0x7B5D, 0x7B5E, 0xDB4D, 0x6A28, - 0, 0xDB4E, 0, 0x6A30, 0, 0x7B5F, 0, 0, - 0, 0, 0x4D66, 0x6A33, 0, 0x6A2A, 0xF76D, 0xDB51, -}; -static const unsigned short utf8_to_euc_E89F[] = { - 0x6A2B, 0xDB52, 0, 0, 0x6A2F, 0, 0x6A32, 0x6A31, - 0xDB53, 0xDB54, 0xDB55, 0x6A29, 0, 0, 0xDB56, 0, - 0x6A2C, 0, 0x6A3D, 0, 0, 0xDB57, 0xDB58, 0, - 0, 0xDB59, 0xDB5A, 0, 0xDB5B, 0, 0, 0xDB5C, - 0x6A36, 0, 0xDB5D, 0xDB5E, 0xDB5F, 0, 0, 0, - 0, 0, 0xDB60, 0xDB61, 0, 0xDB62, 0, 0x6A34, - 0, 0xDB63, 0x6A35, 0xDB64, 0, 0, 0x6A3A, 0x6A3B, - 0xDB65, 0x332A, 0xDB66, 0x3542, 0, 0, 0x6A39, 0xDB67, -}; -static const unsigned short utf8_to_euc_E89F_x0213[] = { - 0x6A2B, 0xF76F, 0, 0, 0x6A2F, 0, 0x6A32, 0x6A31, - 0xDB53, 0xDB54, 0xDB55, 0x6A29, 0, 0, 0xF770, 0, - 0x6A2C, 0, 0x6A3D, 0, 0, 0xDB57, 0x7B61, 0, - 0, 0xDB59, 0xDB5A, 0, 0xDB5B, 0, 0, 0xF772, - 0x6A36, 0, 0xDB5D, 0xF774, 0xDB5F, 0xF775, 0xF776, 0, - 0, 0, 0xF777, 0xF778, 0x7B62, 0xF779, 0, 0x6A34, - 0, 0xDB63, 0x6A35, 0xDB64, 0, 0xF771, 0x6A3A, 0x6A3B, - 0xDB65, 0x332A, 0xDB66, 0x3542, 0, 0, 0x6A39, 0xDB67, -}; -static const unsigned short utf8_to_euc_E8A0[] = { - 0, 0xDB68, 0, 0xDB69, 0, 0x6A24, 0xDB6A, 0xF464, - 0, 0xDB6B, 0xDB6C, 0xDB6D, 0, 0x6A38, 0x6A3C, 0x6A37, - 0xDB6E, 0x6A3E, 0xDB70, 0xDB71, 0xDB72, 0x6A40, 0x6A3F, 0, - 0xDB73, 0xDB6F, 0xDB74, 0xDB75, 0xDB76, 0, 0xDB77, 0xDB78, - 0, 0x6A42, 0x6A41, 0x695A, 0, 0, 0, 0x6A46, - 0xDB79, 0, 0, 0, 0, 0xDB7A, 0xDB7B, 0, - 0xDB7C, 0x6A43, 0xDB7D, 0, 0, 0xDB7E, 0x6A44, 0, - 0, 0x6A45, 0xDC21, 0x6A47, 0xDC22, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E8A0_x0213[] = { - 0, 0xF77A, 0, 0xF77B, 0, 0x6A24, 0x7B63, 0, - 0, 0xDB6B, 0x7B64, 0xF77C, 0, 0x6A38, 0x6A3C, 0x6A37, - 0x7B65, 0x6A3E, 0xDB70, 0xF77D, 0x7B66, 0x6A40, 0x6A3F, 0, - 0xDB73, 0xDB6F, 0xDB74, 0xDB75, 0xDB76, 0, 0xDB77, 0x7B67, - 0, 0x6A42, 0x6A41, 0x695A, 0, 0, 0, 0x6A46, - 0xF77E, 0, 0, 0, 0, 0xDB7A, 0xF821, 0, - 0xDB7C, 0x6A43, 0xF822, 0, 0, 0xDB7E, 0x6A44, 0, - 0, 0x6A45, 0xDC21, 0x6A47, 0xF823, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E8A1[] = { - 0x376C, 0xDC23, 0x6A49, 0xDC24, 0x6A48, 0xDC25, 0x3D30, 0, - 0xDC26, 0xDC27, 0xDC28, 0xDC29, 0x3954, 0x5E27, 0xDC2A, 0, - 0, 0xDC2B, 0x6A4A, 0x3D51, 0, 0xDC2C, 0xDC2D, 0x3339, - 0xDC2E, 0x6A4B, 0xDC2F, 0x3152, 0xDC30, 0x3E57, 0x6A4C, 0xDC31, - 0xDC32, 0x3955, 0x6A4D, 0x3061, 0xDC33, 0, 0, 0, - 0x493D, 0xDC34, 0, 0x6A4E, 0, 0, 0, 0, - 0x3F6A, 0xDC35, 0x6A55, 0, 0, 0x6A52, 0, 0x436F, - 0, 0xDC36, 0, 0xDC37, 0, 0x6A53, 0x6A50, 0x365E, -}; -static const unsigned short utf8_to_euc_E8A1_x0213[] = { - 0x376C, 0xDC23, 0x6A49, 0xDC24, 0x6A48, 0xDC25, 0x3D30, 0, - 0xDC26, 0xDC27, 0xF825, 0xDC29, 0x3954, 0x5E27, 0xDC2A, 0, - 0, 0xDC2B, 0x6A4A, 0x3D51, 0, 0xDC2C, 0xDC2D, 0x3339, - 0xF826, 0x6A4B, 0xDC2F, 0x3152, 0xDC30, 0x3E57, 0x6A4C, 0xF827, - 0xDC32, 0x3955, 0x6A4D, 0x3061, 0xF828, 0, 0, 0, - 0x493D, 0xF82B, 0, 0x6A4E, 0, 0, 0, 0xF82D, - 0x3F6A, 0xDC35, 0x6A55, 0, 0, 0x6A52, 0, 0x436F, - 0, 0xDC36, 0, 0xDC37, 0, 0x6A53, 0x6A50, 0x365E, -}; -static const unsigned short utf8_to_euc_E8A2[] = { - 0xDC38, 0x6A4F, 0x6A56, 0, 0, 0, 0, 0, - 0x3736, 0, 0, 0x425E, 0, 0x6A5C, 0, 0, - 0, 0, 0x6A58, 0, 0, 0, 0x4235, 0x6A57, - 0xDC39, 0x6A5A, 0xDC3A, 0xDC3B, 0xDC3C, 0, 0x6A51, 0xDC3D, - 0xDC3E, 0, 0x6A5B, 0, 0x6A5D, 0, 0, 0, - 0xDC3F, 0, 0xDC40, 0x486F, 0, 0, 0x6A59, 0, - 0x6A5E, 0x6A60, 0, 0, 0x3853, 0x6A54, 0, 0x3041, - 0, 0, 0xDC41, 0, 0, 0xDC42, 0xDC43, 0x6A5F, -}; -static const unsigned short utf8_to_euc_E8A2_x0213[] = { - 0xDC38, 0x6A4F, 0x6A56, 0, 0, 0, 0, 0, - 0x3736, 0, 0, 0x425E, 0, 0x6A5C, 0, 0, - 0, 0, 0x6A58, 0, 0, 0, 0x4235, 0x6A57, - 0x7B68, 0x6A5A, 0xDC3A, 0xDC3B, 0xDC3C, 0, 0x6A51, 0xDC3D, - 0xF82E, 0, 0x6A5B, 0, 0x6A5D, 0, 0, 0, - 0xDC3F, 0, 0x7B69, 0x486F, 0, 0, 0x6A59, 0, - 0x6A5E, 0x6A60, 0, 0, 0x3853, 0x6A54, 0, 0x3041, - 0, 0, 0xDC41, 0, 0xF82F, 0xF830, 0xF831, 0x6A5F, -}; -static const unsigned short utf8_to_euc_E8A3[] = { - 0xDC44, 0x3A5B, 0x4E76, 0x6A61, 0x6A62, 0x4175, 0, 0, - 0, 0, 0xDC45, 0xDC46, 0xDC47, 0xDC48, 0xDC49, 0x4E22, - 0, 0xDC4A, 0xDC4B, 0xDC4C, 0x6A63, 0x4D35, 0, 0, - 0x6A64, 0x6A65, 0, 0xDC4D, 0x4A64, 0x6A66, 0xDC4E, 0x3A40, - 0, 0x4E23, 0, 0, 0, 0, 0, 0xDC4F, - 0x6A6B, 0, 0, 0, 0, 0, 0, 0xDC50, - 0xDC51, 0xDC52, 0x6A6C, 0x3E58, 0x6A6A, 0xDC53, 0, 0xDC54, - 0x4D67, 0x6A67, 0, 0, 0x6A69, 0x403D, 0x3F7E, 0, -}; -static const unsigned short utf8_to_euc_E8A3_x0213[] = { - 0xF832, 0x3A5B, 0x4E76, 0x6A61, 0x6A62, 0x4175, 0, 0, - 0, 0, 0x7B6A, 0xDC46, 0xDC47, 0xDC48, 0x7B6B, 0x4E22, - 0, 0xF835, 0xF833, 0xF836, 0x6A63, 0x4D35, 0, 0, - 0x6A64, 0x6A65, 0, 0xF837, 0x4A64, 0x6A66, 0xDC4E, 0x3A40, - 0, 0x4E23, 0, 0, 0, 0, 0, 0xDC4F, - 0x6A6B, 0, 0, 0, 0, 0, 0, 0xDC50, - 0xF838, 0xF839, 0x6A6C, 0x3E58, 0x6A6A, 0x7B6D, 0, 0xDC54, - 0x4D67, 0x6A67, 0, 0, 0x6A69, 0x403D, 0x3F7E, 0, -}; -static const unsigned short utf8_to_euc_E8A4[] = { - 0, 0xDC55, 0x6A68, 0, 0x6A6D, 0, 0xDC56, 0x4A23, - 0, 0, 0x6A6F, 0, 0x6A6E, 0xDC57, 0xDC58, 0xDC59, - 0x336C, 0, 0x4B2B, 0x6A70, 0, 0xDC5A, 0xDC5B, 0, - 0xDC5C, 0xDC5D, 0xDC5E, 0, 0xDC5F, 0x6A7C, 0x6A72, 0, - 0xDC60, 0, 0, 0, 0, 0x6A73, 0xDC61, 0xDC62, - 0xDC63, 0, 0x6A74, 0x6A75, 0, 0, 0, 0, - 0xDC64, 0xDC65, 0xDC66, 0, 0, 0xDC67, 0x6A79, 0, - 0x6A7A, 0xDC68, 0xDC69, 0x6A78, 0, 0, 0xDC6A, 0, -}; -static const unsigned short utf8_to_euc_E8A4_x0213[] = { - 0, 0xF83B, 0x6A68, 0, 0x6A6D, 0, 0xDC56, 0x4A23, - 0, 0, 0x6A6F, 0, 0x6A6E, 0xDC57, 0xDC58, 0xDC59, - 0x336C, 0, 0x4B2B, 0x6A70, 0, 0xDC5A, 0xDC5B, 0, - 0x7B70, 0x7B71, 0x7B72, 0, 0x7B6E, 0x6A7C, 0x6A72, 0, - 0xDC60, 0, 0, 0, 0, 0x6A73, 0xDC61, 0x7B73, - 0xDC63, 0, 0x6A74, 0x6A75, 0, 0, 0, 0, - 0x7B74, 0xDC65, 0x7B75, 0, 0, 0xDC67, 0x6A79, 0xF83D, - 0x6A7A, 0x7B76, 0xDC69, 0x6A78, 0, 0, 0xDC6A, 0, -}; -static const unsigned short utf8_to_euc_E8A5[] = { - 0xDC6B, 0x6A76, 0xDC6C, 0x6A71, 0x6A77, 0xDC6D, 0xDC6E, 0, - 0, 0xDC6F, 0, 0, 0x6A7B, 0x7037, 0, 0xDC70, - 0, 0, 0xDC71, 0, 0, 0, 0x3228, 0xDC72, - 0, 0, 0xDC73, 0xDC74, 0xDC75, 0, 0x6A7E, 0x365F, - 0x6A7D, 0xDC76, 0xDC77, 0xDC78, 0x6B22, 0, 0x6B21, 0, - 0, 0, 0x6B24, 0xDC79, 0, 0x6B23, 0xDC7A, 0x6B25, - 0xDC7B, 0, 0x3D31, 0xDC7C, 0x6B26, 0xDC7D, 0, 0x6B27, - 0, 0, 0xDC7E, 0xDD21, 0xDD22, 0xDD23, 0x6B28, 0x403E, -}; -static const unsigned short utf8_to_euc_E8A5_x0213[] = { - 0x7B77, 0x6A76, 0xF83F, 0x6A71, 0x6A77, 0xF840, 0xDC6E, 0, - 0, 0xF841, 0, 0, 0x6A7B, 0x7037, 0, 0xDC70, - 0, 0, 0xDC71, 0, 0, 0, 0x3228, 0xDC72, - 0, 0, 0xDC73, 0xDC74, 0xDC75, 0, 0x6A7E, 0x365F, - 0x6A7D, 0xDC76, 0xF844, 0xDC78, 0x6B22, 0, 0x6B21, 0, - 0, 0, 0x6B24, 0xDC79, 0, 0x6B23, 0xDC7A, 0x6B25, - 0xDC7B, 0, 0x3D31, 0xDC7C, 0x6B26, 0xDC7D, 0, 0x6B27, - 0, 0, 0xDC7E, 0xDD21, 0xDD22, 0xDD23, 0x6B28, 0x403E, -}; -static const unsigned short utf8_to_euc_E8A6[] = { - 0, 0x4D57, 0, 0x6B29, 0, 0, 0x4A24, 0x4746, - 0x6B2A, 0xDD24, 0x6B2B, 0x382B, 0, 0xDD25, 0, 0x352C, - 0xDD26, 0, 0, 0x6B2C, 0xDD27, 0xDD28, 0x3B6B, 0x4741, - 0x6B2D, 0, 0x3350, 0xDD29, 0xDD2A, 0, 0, 0xDD2B, - 0xDD2C, 0x6B2E, 0, 0, 0, 0xDD2D, 0x6B30, 0x4D77, - 0, 0x6B2F, 0x3F46, 0, 0x6B31, 0, 0, 0x6B32, - 0xDD2E, 0, 0x6B33, 0x3451, 0xDD2F, 0xDD30, 0xDD31, 0xDD32, - 0, 0, 0x6B34, 0, 0xDD33, 0x6B35, 0, 0x6B36, -}; -static const unsigned short utf8_to_euc_E8A6_x0213[] = { - 0xF845, 0x4D57, 0, 0x6B29, 0, 0, 0x4A24, 0x4746, - 0x6B2A, 0xF846, 0x6B2B, 0x382B, 0, 0xDD25, 0, 0x352C, - 0xF847, 0, 0, 0x6B2C, 0x7B78, 0xDD28, 0x3B6B, 0x4741, - 0x6B2D, 0, 0x3350, 0xDD29, 0xDD2A, 0, 0, 0xF848, - 0xDD2C, 0x6B2E, 0, 0, 0, 0xDD2D, 0x6B30, 0x4D77, - 0, 0x6B2F, 0x3F46, 0, 0x6B31, 0, 0, 0x6B32, - 0xF849, 0, 0x6B33, 0x3451, 0xDD2F, 0xDD30, 0xDD31, 0xF84A, - 0, 0, 0x6B34, 0, 0xDD33, 0x6B35, 0, 0x6B36, -}; -static const unsigned short utf8_to_euc_E8A7[] = { - 0x6B37, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x3351, 0, 0xDD34, 0xDD35, 0xDD36, 0xDD37, - 0xDD38, 0, 0x6B38, 0, 0x6B39, 0x6B3A, 0, 0, - 0, 0, 0, 0x3272, 0, 0xDD39, 0x3F28, 0x6B3B, - 0, 0xDD3A, 0, 0xDD3B, 0, 0xDD3C, 0, 0, - 0, 0xDD3D, 0, 0xDD3E, 0x6B3C, 0, 0xDD3F, 0, - 0x6B3D, 0xDD40, 0, 0, 0, 0xDD41, 0, 0xDD42, -}; -static const unsigned short utf8_to_euc_E8A7_x0213[] = { - 0x6B37, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x3351, 0, 0x7B7A, 0xDD35, 0xF84B, 0xDD37, - 0xF84C, 0, 0x6B38, 0, 0x6B39, 0x6B3A, 0, 0, - 0, 0, 0, 0x3272, 0, 0x7B7B, 0x3F28, 0x6B3B, - 0, 0xDD3A, 0, 0xF84D, 0, 0xDD3C, 0, 0, - 0, 0xF84F, 0, 0xF850, 0x6B3C, 0, 0x7B7C, 0, - 0x6B3D, 0xDD40, 0, 0, 0, 0xF851, 0, 0xF852, -}; -static const unsigned short utf8_to_euc_E8A8[] = { - 0x3840, 0, 0x447B, 0x6B3E, 0xDD43, 0xDD44, 0, 0xDD45, - 0x3757, 0, 0x3F56, 0, 0x6B41, 0, 0x4624, 0xDD46, - 0x6B40, 0xDD47, 0xDD48, 0x3731, 0xDD49, 0xDD4A, 0x6B3F, 0x4277, - 0x352D, 0, 0, 0x6B42, 0, 0x6B43, 0xDD4B, 0x3E59, - 0xDD4C, 0, 0xDD4D, 0x376D, 0xDD4E, 0x6B44, 0xDD4F, 0, - 0, 0, 0x4B2C, 0xDD50, 0xDD51, 0x405F, 0, 0xDD52, - 0, 0x3576, 0, 0x4C75, 0x414A, 0xDD53, 0x6B45, 0xDD54, - 0, 0, 0x3F47, 0x4370, 0x3E5A, 0xDD55, 0xDD56, 0, -}; -static const unsigned short utf8_to_euc_E8A8_x0213[] = { - 0x3840, 0, 0x447B, 0x6B3E, 0xDD43, 0xDD44, 0, 0xDD45, - 0x3757, 0, 0x3F56, 0, 0x6B41, 0, 0x4624, 0xDD46, - 0x6B40, 0xF854, 0x7B7D, 0x3731, 0xF855, 0x7B7E, 0x6B3F, 0x4277, - 0x352D, 0, 0, 0x6B42, 0, 0x6B43, 0xDD4B, 0x3E59, - 0xDD4C, 0xF857, 0x7C21, 0x376D, 0xDD4E, 0x6B44, 0xDD4F, 0, - 0, 0, 0x4B2C, 0xDD50, 0xDD51, 0x405F, 0, 0xDD52, - 0, 0x3576, 0, 0x4C75, 0x414A, 0xF858, 0x6B45, 0x7C22, - 0, 0, 0x3F47, 0x4370, 0x3E5A, 0xDD55, 0xF859, 0, -}; -static const unsigned short utf8_to_euc_E8A9[] = { - 0xDD57, 0x6B46, 0, 0xDD58, 0, 0xDD59, 0x6B49, 0xDD5A, - 0x6B4A, 0xDD5B, 0, 0, 0, 0xDD5C, 0xDD5D, 0, - 0x3A3E, 0x4242, 0x6B48, 0xDD5E, 0x3E5B, 0x493E, 0xDD5F, 0xDD60, - 0xDD61, 0, 0, 0x6B47, 0xDD62, 0xDD63, 0x3B6C, 0, - 0x3153, 0xDD64, 0x6B4E, 0x3758, 0, 0xDD65, 0x3B6E, 0xDD66, - 0, 0x3B6D, 0, 0x4F4D, 0x6B4D, 0x6B4C, 0x4127, 0, - 0x354D, 0x4F43, 0x333A, 0x3E5C, 0, 0xDD67, 0xDD68, 0xDD69, - 0, 0xDD6A, 0xDD6B, 0xDD6C, 0x6B4B, 0, 0xDD6D, 0xDD6E, -}; -static const unsigned short utf8_to_euc_E8A9_x0213[] = { - 0xDD57, 0x6B46, 0, 0xDD58, 0, 0xF85A, 0x6B49, 0x7C23, - 0x6B4A, 0xDD5B, 0, 0, 0, 0xF85B, 0x7C24, 0, - 0x3A3E, 0x4242, 0x6B48, 0xDD5E, 0x3E5B, 0x493E, 0xDD5F, 0xDD60, - 0xF85C, 0, 0, 0x6B47, 0xDD62, 0x7C25, 0x3B6C, 0, - 0x3153, 0x7C26, 0x6B4E, 0x3758, 0, 0xDD65, 0x3B6E, 0xDD66, - 0, 0x3B6D, 0, 0x4F4D, 0x6B4D, 0x6B4C, 0x4127, 0, - 0x354D, 0x4F43, 0x333A, 0x3E5C, 0, 0x7C27, 0xDD68, 0xDD69, - 0, 0x7C28, 0xDD6B, 0xDD6C, 0x6B4B, 0, 0xDD6D, 0xDD6E, -}; -static const unsigned short utf8_to_euc_E8AA[] = { - 0xDD6F, 0, 0x6B50, 0xDD70, 0x6B51, 0x6B4F, 0xDD71, 0x3858, - 0, 0x4D40, 0, 0xDD72, 0x3B6F, 0x4727, 0, 0xDD73, - 0xDD74, 0x6B54, 0xDD75, 0x4040, 0, 0x4342, 0xDD76, 0xDD77, - 0x4D36, 0xDD78, 0x6B57, 0, 0, 0, 0x386C, 0xDD79, - 0x403F, 0x6B53, 0, 0x6B58, 0x386D, 0x6B55, 0x6B56, 0xDD7A, - 0x6B52, 0xDD7B, 0, 0, 0x4062, 0x4649, 0xDD7C, 0xDD7D, - 0x432F, 0, 0x325D, 0xDD7E, 0, 0, 0xDE21, 0xDE22, - 0, 0x4870, 0, 0xDE23, 0x3543, 0, 0xDE24, 0x4434, -}; -static const unsigned short utf8_to_euc_E8AA_x0213[] = { - 0xDD6F, 0, 0x6B50, 0xDD70, 0x6B51, 0x6B4F, 0xDD71, 0x3858, - 0, 0x4D40, 0, 0xDD72, 0x3B6F, 0x4727, 0, 0xDD73, - 0xF85E, 0x6B54, 0xDD75, 0x4040, 0, 0x4342, 0xDD76, 0xDD77, - 0x4D36, 0xDD78, 0x6B57, 0, 0, 0, 0x386C, 0xDD79, - 0x403F, 0x6B53, 0, 0x6B58, 0x386D, 0x6B55, 0x6B56, 0x7C29, - 0x6B52, 0xDD7B, 0, 0, 0x4062, 0x4649, 0xF85D, 0xDD7D, - 0x432F, 0, 0x325D, 0xDD7E, 0, 0, 0xDE21, 0xF85F, - 0, 0x4870, 0, 0xDE23, 0x3543, 0, 0xF860, 0x4434, -}; -static const unsigned short utf8_to_euc_E8AB[] = { - 0, 0, 0x6B5B, 0xDE25, 0x6B59, 0, 0xDE26, 0x434C, - 0xDE27, 0xDE28, 0xDE29, 0x4041, 0x3452, 0x6B5A, 0, 0x3F5B, - 0, 0xDE2A, 0x4E4A, 0xDE2B, 0xDE2C, 0xDE2D, 0x4F40, 0xDE2E, - 0, 0, 0x6B5C, 0x6B67, 0x4435, 0xDE2F, 0x6B66, 0xDE30, - 0x6B63, 0x6B6B, 0x6B64, 0, 0x6B60, 0, 0x447C, 0x6B5F, - 0, 0, 0, 0x6B5D, 0xDE31, 0x4D21, 0x3B70, 0, - 0xDE32, 0x6B61, 0, 0x6B5E, 0xDE33, 0xDE34, 0xDE35, 0x6B65, - 0x3D74, 0, 0x3841, 0, 0xDE36, 0, 0x427A, 0xDE37, -}; -static const unsigned short utf8_to_euc_E8AB_x0213[] = { - 0, 0, 0x6B5B, 0xDE25, 0x6B59, 0, 0xDE26, 0x434C, - 0xDE27, 0xDE28, 0xDE29, 0x4041, 0x3452, 0x6B5A, 0, 0x3F5B, - 0x7C2A, 0xDE2A, 0x4E4A, 0xDE2B, 0xDE2C, 0xDE2D, 0x4F40, 0xF861, - 0, 0, 0x6B5C, 0x6B67, 0x4435, 0xDE2F, 0x6B66, 0x7C2B, - 0x6B63, 0x6B6B, 0x6B64, 0, 0x6B60, 0, 0x447C, 0x6B5F, - 0, 0, 0, 0x6B5D, 0xDE31, 0x4D21, 0x3B70, 0, - 0xDE32, 0x6B61, 0, 0x6B5E, 0x7C2C, 0xDE34, 0x7C2D, 0x6B65, - 0x3D74, 0, 0x3841, 0, 0xF862, 0, 0x427A, 0xDE37, -}; -static const unsigned short utf8_to_euc_E8AC[] = { - 0x4B45, 0x315A, 0x3062, 0, 0x4625, 0xDE38, 0xDE39, 0x6B69, - 0, 0, 0xDE3F, 0xDE3A, 0x6B68, 0, 0x4666, 0, - 0x6B6D, 0xDE3B, 0, 0, 0x6B62, 0, 0x6B6C, 0x6B6E, - 0, 0x382C, 0x6B6A, 0x3956, 0xDE3C, 0x3C55, 0xDE3D, 0xDE3E, - 0x6B6F, 0x4D58, 0, 0, 0, 0, 0x6B72, 0, - 0x6B75, 0, 0, 0x6B73, 0x4935, 0xDE40, 0, 0, - 0xDE41, 0, 0, 0x6B70, 0, 0, 0, 0xDE42, - 0, 0x3660, 0, 0, 0xDE43, 0, 0x6B74, 0, -}; -static const unsigned short utf8_to_euc_E8AC_x0213[] = { - 0x4B45, 0x315A, 0x3062, 0, 0x4625, 0xF865, 0xDE39, 0x6B69, - 0, 0, 0xF864, 0xDE3A, 0x6B68, 0xF866, 0x4666, 0, - 0x6B6D, 0xDE3B, 0, 0, 0x6B62, 0, 0x6B6C, 0x6B6E, - 0, 0x382C, 0x6B6A, 0x3956, 0xF867, 0x3C55, 0xDE3D, 0xF868, - 0x6B6F, 0x4D58, 0, 0, 0, 0, 0x6B72, 0, - 0x6B75, 0, 0, 0x6B73, 0x4935, 0xF869, 0, 0, - 0xDE41, 0, 0, 0x6B70, 0, 0, 0, 0xDE42, - 0, 0x3660, 0, 0, 0xDE43, 0, 0x6B74, 0, -}; -static const unsigned short utf8_to_euc_E8AD[] = { - 0, 0x6B76, 0xDE44, 0xDE45, 0xDE46, 0xDE47, 0xDE48, 0, - 0xDE49, 0x6B7A, 0, 0, 0x6B77, 0xDE4E, 0x6B79, 0x6B78, - 0, 0, 0xDE4A, 0xDE4B, 0xDE4C, 0, 0x6B7B, 0, - 0x3C31, 0xDE4D, 0x6B7D, 0x6B7C, 0x4968, 0, 0xDE4F, 0x6C21, - 0, 0, 0, 0xDE50, 0, 0, 0x3759, 0, - 0, 0, 0, 0x6B7E, 0x6C22, 0xDE51, 0, 0x6C23, - 0x3544, 0x6641, 0x3E79, 0, 0x6C24, 0, 0xDE52, 0x386E, - 0xDE53, 0xDE54, 0, 0, 0xDE55, 0x6C25, 0xDE56, 0xF466, -}; -static const unsigned short utf8_to_euc_E8AD_x0213[] = { - 0, 0x6B76, 0xDE44, 0xF86A, 0xDE46, 0xDE47, 0x7C31, 0, - 0xDE49, 0x6B7A, 0, 0, 0x6B77, 0xDE4E, 0x6B79, 0x6B78, - 0, 0xF86C, 0xDE4A, 0, 0x7C32, 0, 0x6B7B, 0, - 0x3C31, 0x7C33, 0x6B7D, 0x6B7C, 0x4968, 0, 0xF86D, 0x6C21, - 0, 0, 0, 0xDE50, 0, 0, 0x3759, 0, - 0, 0x7C34, 0, 0x6B7E, 0x6C22, 0xDE51, 0, 0x6C23, - 0x3544, 0x6641, 0x3E79, 0, 0x6C24, 0, 0xF86E, 0x386E, - 0xDE53, 0xDE54, 0, 0, 0xDE55, 0x6C25, 0xDE56, 0xF86F, -}; -static const unsigned short utf8_to_euc_E8AE[] = { - 0x6C26, 0xDE57, 0, 0x3B3E, 0xDE58, 0xDE59, 0, 0, - 0, 0, 0x5A4E, 0xDE5A, 0x6C27, 0xDE5B, 0x6C28, 0xDE5C, - 0x3D32, 0, 0x6C29, 0x6C2A, 0xDE5D, 0xDE5E, 0x6C2B, 0, - 0, 0x6C2C, 0x6C2D, 0, 0xDE5F, 0, 0xDE60, 0xDE61, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E8AE_x0213[] = { - 0x6C26, 0xF870, 0, 0x3B3E, 0xDE58, 0xDE59, 0, 0, - 0, 0, 0x5A4E, 0xF871, 0x6C27, 0xDE5B, 0x6C28, 0xDE5C, - 0x3D32, 0, 0x6C29, 0x6C2A, 0xF872, 0xF873, 0x6C2B, 0, - 0, 0x6C2C, 0x6C2D, 0, 0xF874, 0x7C35, 0xF875, 0xDE61, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E8B0[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x432B, - 0xDE62, 0xDE63, 0x6C2E, 0, 0, 0xDE64, 0xDE65, 0x6C30, -}; -static const unsigned short utf8_to_euc_E8B0_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x432B, - 0xDE62, 0xF876, 0x6C2E, 0, 0, 0xF878, 0xDE65, 0x6C30, -}; -static const unsigned short utf8_to_euc_E8B1[] = { - 0, 0x6C2F, 0, 0, 0, 0xDE66, 0x4626, 0xDE67, - 0x6C31, 0xDE68, 0x4B2D, 0xDE69, 0x6C32, 0, 0x6C33, 0xDE6A, - 0x6C34, 0xDE6B, 0, 0xDE6C, 0xDE6D, 0x6C35, 0, 0xDE6E, - 0xDE6F, 0xDE72, 0x465A, 0xDE70, 0, 0xDE71, 0, 0, - 0, 0x3E5D, 0x6C36, 0xDE73, 0xDE74, 0, 0xDE75, 0, - 0xDE76, 0xDE77, 0x396B, 0x502E, 0x6C37, 0xDE78, 0, 0, - 0, 0, 0, 0xDE79, 0, 0xDE7A, 0xDE7B, 0, - 0x6C38, 0x493F, 0x6C39, 0xDE7C, 0x6C41, 0, 0xDE7D, 0, -}; -static const unsigned short utf8_to_euc_E8B1_x0213[] = { - 0, 0x6C2F, 0, 0, 0, 0xF87B, 0x4626, 0xF87C, - 0x6C31, 0x7C36, 0x4B2D, 0xDE69, 0x6C32, 0, 0x6C33, 0xF87D, - 0x6C34, 0xDE6B, 0, 0xDE6C, 0xF87E, 0x6C35, 0, 0xF921, - 0xDE6F, 0xDE72, 0x465A, 0xDE70, 0, 0xDE71, 0, 0, - 0, 0x3E5D, 0x6C36, 0xDE73, 0xDE74, 0, 0xDE75, 0, - 0x7C37, 0xF922, 0x396B, 0x502E, 0x6C37, 0xF923, 0, 0, - 0, 0, 0, 0xF924, 0, 0xDE7A, 0xDE7B, 0, - 0x6C38, 0x493F, 0x6C39, 0xDE7C, 0x6C41, 0, 0xDE7D, 0, -}; -static const unsigned short utf8_to_euc_E8B2[] = { - 0, 0, 0x6C3A, 0, 0, 0x6C3C, 0xDE7E, 0xDF21, - 0, 0x6C3B, 0x6C3D, 0xDF22, 0x4B46, 0x6C3E, 0x6C3F, 0, - 0xDF23, 0, 0xDF24, 0xDF25, 0x6C40, 0, 0, 0, - 0x6C42, 0xDF26, 0, 0xDF27, 0xDF28, 0x332D, 0x4467, 0, - 0x4969, 0x3A62, 0x3957, 0, 0xDF29, 0, 0, 0x494F, - 0x325F, 0x484E, 0x6C45, 0x3453, 0x4055, 0x6C44, 0x6C49, 0x4379, - 0x4C63, 0, 0x6C47, 0x6C48, 0x352E, 0, 0x6C4A, 0x4763, - 0x425F, 0xDF2A, 0xDF2B, 0x4871, 0x453D, 0x6C46, 0, 0x4B47, -}; -static const unsigned short utf8_to_euc_E8B2_x0213[] = { - 0, 0, 0x6C3A, 0, 0, 0x6C3C, 0xDE7E, 0xDF21, - 0, 0x6C3B, 0x6C3D, 0xDF22, 0x4B46, 0x6C3E, 0x6C3F, 0, - 0xDF23, 0, 0xF927, 0xF926, 0x6C40, 0, 0, 0, - 0x6C42, 0xF928, 0, 0xF92A, 0xDF28, 0x332D, 0x4467, 0, - 0x4969, 0x3A62, 0x3957, 0, 0xF92B, 0, 0, 0x494F, - 0x325F, 0x484E, 0x6C45, 0x3453, 0x4055, 0x6C44, 0x6C49, 0x4379, - 0x4C63, 0, 0x6C47, 0x6C48, 0x352E, 0, 0x6C4A, 0x4763, - 0x425F, 0xDF2A, 0xDF2B, 0x4871, 0x453D, 0x6C46, 0, 0x4B47, -}; -static const unsigned short utf8_to_euc_E8B3[] = { - 0x326C, 0x6C4C, 0x4F28, 0x4442, 0x4F45, 0xDF2C, 0xDF2D, 0x3B71, - 0x6C4B, 0xDF2E, 0x4231, 0xDF2F, 0, 0x6C5C, 0x4128, 0xDF30, - 0, 0x4678, 0, 0x4950, 0, 0xDF32, 0xDF31, 0, - 0, 0xDF33, 0x6C4F, 0x3B3F, 0x3B72, 0xDF34, 0x3E5E, 0, - 0x4765, 0xDF35, 0x382D, 0x6C4E, 0x6C4D, 0, 0x496A, 0, - 0xDF36, 0, 0x3C41, 0, 0xDF37, 0x4552, 0, 0xDF38, - 0xDF39, 0, 0xDF3A, 0, 0xF467, 0xDF3B, 0, 0xDF3C, - 0xDF3D, 0, 0x6C51, 0x6C52, 0x3958, 0x6C50, 0xDF3E, 0xDF3F, -}; -static const unsigned short utf8_to_euc_E8B3_x0213[] = { - 0x326C, 0x6C4C, 0x4F28, 0x4442, 0x4F45, 0xDF2C, 0xDF2D, 0x3B71, - 0x6C4B, 0xDF2E, 0x4231, 0xDF2F, 0, 0x6C5C, 0x4128, 0xDF30, - 0, 0x4678, 0, 0x4950, 0, 0xF92D, 0xF92C, 0, - 0, 0xF92E, 0x6C4F, 0x3B3F, 0x3B72, 0xDF34, 0x3E5E, 0, - 0x4765, 0x7C39, 0x382D, 0x6C4E, 0x6C4D, 0, 0x496A, 0, - 0xDF36, 0, 0x3C41, 0, 0xDF37, 0x4552, 0, 0xDF38, - 0xF930, 0xF931, 0xDF3A, 0, 0x7C3A, 0xDF3B, 0, 0xDF3C, - 0x7C3B, 0, 0x6C51, 0x6C52, 0x3958, 0x6C50, 0x7C3C, 0xDF3F, -}; -static const unsigned short utf8_to_euc_E8B4[] = { - 0, 0xDF40, 0, 0xDF41, 0x6C53, 0x6C54, 0, 0x6C56, - 0x4223, 0xDF42, 0x6C55, 0x3466, 0, 0x6C58, 0, 0x6C57, - 0x6C59, 0, 0xDF43, 0x6C5B, 0x6C5D, 0, 0x6C5E, 0xDF44, - 0, 0, 0, 0xDF45, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E8B4_x0213[] = { - 0, 0xDF40, 0, 0xDF41, 0x6C53, 0x6C54, 0, 0x6C56, - 0x4223, 0xF933, 0x6C55, 0x3466, 0, 0x6C58, 0xF934, 0x6C57, - 0x6C59, 0, 0x7C3E, 0x6C5B, 0x6C5D, 0, 0x6C5E, 0xDF44, - 0, 0, 0, 0x7C3F, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E8B5[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x4056, 0xDF46, 0x3C4F, 0x6C5F, - 0, 0xDF47, 0, 0x3352, 0xDF48, 0x6C60, 0xDF49, 0, - 0x4176, 0x6C61, 0, 0x6C62, 0x496B, 0, 0xF468, 0x352F, - 0, 0, 0, 0, 0, 0, 0, 0xDF4A, -}; -static const unsigned short utf8_to_euc_E8B5_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x4056, 0xDF46, 0x3C4F, 0x6C5F, - 0, 0xDF47, 0, 0x3352, 0xF935, 0x6C60, 0xDF49, 0, - 0x4176, 0x6C61, 0, 0x6C62, 0x496B, 0, 0, 0x352F, - 0, 0, 0, 0, 0, 0, 0, 0xDF4A, -}; -static const unsigned short utf8_to_euc_E8B6[] = { - 0, 0x6C63, 0xDF4B, 0, 0xDF4C, 0x4436, 0, 0, - 0xDF4D, 0, 0x315B, 0, 0, 0xDF4E, 0, 0, - 0xDF4F, 0xDF50, 0, 0, 0, 0xDF51, 0, 0, - 0, 0x6C64, 0, 0, 0, 0, 0xDF52, 0xDF53, - 0xDF54, 0, 0, 0x3C71, 0, 0, 0xDF55, 0, - 0x3F76, 0, 0, 0xDF56, 0xDF57, 0, 0, 0xDF58, - 0, 0, 0xDF59, 0x422D, 0, 0xDF5A, 0, 0xDF5B, - 0, 0xDF5C, 0x6C67, 0xDF5D, 0xDF6F, 0, 0x6C66, 0, -}; -static const unsigned short utf8_to_euc_E8B6_x0213[] = { - 0, 0x6C63, 0xDF4B, 0, 0xF936, 0x4436, 0, 0, - 0xDF4D, 0, 0x315B, 0, 0, 0xDF4E, 0, 0, - 0xDF4F, 0xDF50, 0, 0, 0, 0xF937, 0, 0, - 0, 0x6C64, 0, 0, 0, 0, 0xDF52, 0xDF53, - 0xDF54, 0, 0, 0x3C71, 0, 0, 0xF938, 0, - 0x3F76, 0, 0, 0xDF56, 0xDF57, 0, 0, 0x7C40, - 0, 0, 0xDF59, 0x422D, 0, 0xDF5A, 0, 0xDF5B, - 0, 0xDF5C, 0x6C67, 0xDF5D, 0xDF6F, 0, 0x6C66, 0, -}; -static const unsigned short utf8_to_euc_E8B7[] = { - 0xDF5E, 0, 0x6C65, 0, 0, 0xDF5F, 0xDF60, 0xDF61, - 0xDF62, 0, 0xDF63, 0x6C6D, 0x6C6B, 0, 0xDF64, 0x6C68, - 0, 0xDF65, 0, 0, 0xDF66, 0xDF67, 0x6C6A, 0xDF68, - 0, 0xDF69, 0x6C69, 0x6C6C, 0, 0x3577, 0, 0x6C70, - 0, 0x4057, 0, 0x6C71, 0xDF6A, 0xDF6B, 0, 0xDF6C, - 0x3859, 0, 0x6C6E, 0x6C6F, 0xDF6D, 0, 0, 0x4F29, - 0xDF6E, 0xDF70, 0xDF71, 0x4437, 0xDF72, 0x4129, 0, 0, - 0, 0, 0, 0, 0x6C72, 0xDF73, 0, 0x6C75, -}; -static const unsigned short utf8_to_euc_E8B7_x0213[] = { - 0xDF5E, 0, 0x6C65, 0, 0, 0xDF5F, 0xF93A, 0xDF61, - 0xF93B, 0, 0xDF63, 0x6C6D, 0x6C6B, 0, 0x7C41, 0x6C68, - 0, 0x7C42, 0, 0, 0xDF66, 0xDF67, 0x6C6A, 0x7C43, - 0, 0xF93C, 0x6C69, 0x6C6C, 0, 0x3577, 0, 0x6C70, - 0, 0x4057, 0, 0x6C71, 0xDF6A, 0xDF6B, 0, 0xDF6C, - 0x3859, 0, 0x6C6E, 0x6C6F, 0xF93D, 0, 0, 0x4F29, - 0xDF6E, 0xDF70, 0xDF71, 0x4437, 0xDF72, 0x4129, 0, 0, - 0, 0, 0, 0, 0x6C72, 0xF940, 0, 0x6C75, -}; -static const unsigned short utf8_to_euc_E8B8[] = { - 0, 0xDF74, 0, 0, 0xDF75, 0xDF76, 0xDF77, 0, - 0x6C73, 0x6C74, 0x4D59, 0xDF78, 0, 0, 0, 0x4627, - 0x6C78, 0xDF79, 0, 0, 0xDF7A, 0, 0xDF7B, 0, - 0, 0, 0, 0, 0, 0x6C76, 0x6C77, 0x6C79, - 0xDF7C, 0xDF7D, 0xDF7E, 0xE021, 0, 0, 0xE022, 0xE023, - 0, 0, 0x6D29, 0, 0, 0, 0, 0, - 0x6C7C, 0xE024, 0, 0xE025, 0x6C7D, 0x6C7B, 0xE026, 0xE027, - 0xE028, 0xE029, 0, 0, 0, 0xE02A, 0, 0, -}; -static const unsigned short utf8_to_euc_E8B8_x0213[] = { - 0, 0xDF74, 0, 0, 0xDF75, 0xDF76, 0xF941, 0, - 0x6C73, 0x6C74, 0x4D59, 0xDF78, 0xF93E, 0, 0, 0x4627, - 0x6C78, 0xDF79, 0, 0, 0xF943, 0, 0xF944, 0, - 0, 0, 0, 0, 0, 0x6C76, 0x6C77, 0x6C79, - 0x7C44, 0xF945, 0xF946, 0x7C45, 0, 0, 0xE022, 0xF947, - 0, 0, 0x6D29, 0, 0, 0, 0, 0, - 0x6C7C, 0xE024, 0, 0xE025, 0x6C7D, 0x6C7B, 0xF94A, 0xE027, - 0xE028, 0xF94B, 0, 0, 0, 0x7C46, 0, 0, -}; -static const unsigned short utf8_to_euc_E8B9[] = { - 0xE02B, 0xE02C, 0x6C7A, 0, 0x447D, 0, 0, 0x6D21, - 0x6D25, 0x6D22, 0x6C7E, 0xE02D, 0x6D23, 0xE02E, 0xE02F, 0xE030, - 0x6D24, 0, 0, 0, 0xE031, 0x6D2B, 0, 0, - 0, 0x6D26, 0, 0xE032, 0xE033, 0xE034, 0xE035, 0x4058, - 0x6D28, 0xE036, 0xE037, 0x6D2A, 0x6D27, 0, 0, 0, - 0, 0xE038, 0, 0, 0xE039, 0xE03A, 0, 0xE03B, - 0xE03C, 0xE03D, 0x6D2D, 0, 0x3D33, 0, 0x6D2C, 0, - 0, 0xE03E, 0xE03F, 0xE040, 0x6D2E, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E8B9_x0213[] = { - 0xE02B, 0xE02C, 0x6C7A, 0, 0x447D, 0, 0, 0x6D21, - 0x6D25, 0x6D22, 0x6C7E, 0xF94C, 0x6D23, 0xE02E, 0xE02F, 0xE030, - 0x6D24, 0, 0, 0, 0xF94D, 0x6D2B, 0, 0, - 0, 0x6D26, 0, 0xE032, 0xE033, 0xE034, 0xE035, 0x4058, - 0x6D28, 0xE036, 0xF94E, 0x6D2A, 0x6D27, 0, 0, 0, - 0, 0xE038, 0, 0, 0xF94F, 0xF950, 0, 0xF951, - 0x7C47, 0xE03D, 0x6D2D, 0, 0x3D33, 0, 0x6D2C, 0, - 0, 0xE03E, 0xE03F, 0x7C48, 0x6D2E, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E8BA[] = { - 0, 0x6D2F, 0xE041, 0xE042, 0x6D32, 0x6D31, 0, 0x6D30, - 0, 0xE043, 0x6D34, 0x6D33, 0, 0x4C76, 0, 0, - 0xE044, 0x6D36, 0xE045, 0x6D35, 0x6D37, 0xE046, 0, 0, - 0, 0x6D38, 0xE047, 0xE048, 0, 0xE049, 0xE04A, 0, - 0, 0x6D3A, 0xE04B, 0, 0, 0, 0, 0xE04C, - 0, 0xE04D, 0x6D39, 0x3F48, 0x6D3B, 0xE04E, 0xE04F, 0x366D, - 0x6D3C, 0x6D3E, 0, 0xE050, 0, 0xE051, 0, 0, - 0, 0, 0xE052, 0xE053, 0, 0, 0x6D3F, 0, -}; -static const unsigned short utf8_to_euc_E8BA_x0213[] = { - 0, 0x6D2F, 0xE041, 0xE042, 0x6D32, 0x6D31, 0, 0x6D30, - 0, 0xE043, 0x6D34, 0x6D33, 0, 0x4C76, 0, 0, - 0xE044, 0x6D36, 0xE045, 0x6D35, 0x6D37, 0xE046, 0, 0, - 0xF952, 0x6D38, 0xE047, 0xE048, 0, 0xE049, 0xF953, 0, - 0, 0x6D3A, 0xE04B, 0, 0, 0, 0, 0xE04C, - 0, 0xE04D, 0x6D39, 0x3F48, 0x6D3B, 0xE04E, 0xF954, 0x366D, - 0x6D3C, 0x6D3E, 0, 0xF955, 0, 0xF956, 0xF957, 0, - 0, 0, 0xE052, 0xF958, 0, 0, 0x6D3F, 0, -}; -static const unsigned short utf8_to_euc_E8BB[] = { - 0xE054, 0xE055, 0, 0xE056, 0xE057, 0x6D40, 0x6D3D, 0xE058, - 0x6D41, 0, 0x3C56, 0x6D42, 0x3530, 0x3733, 0, 0xE059, - 0, 0xE05A, 0x382E, 0, 0xE05B, 0, 0, 0, - 0, 0, 0, 0x6D43, 0xE05C, 0, 0, 0x4670, - 0, 0, 0x453E, 0x6D44, 0, 0, 0, 0, - 0xE05D, 0, 0, 0x6D47, 0, 0xE064, 0xE05E, 0, - 0xE05F, 0xE060, 0, 0, 0, 0, 0, 0xE061, - 0x3C34, 0xE062, 0xE063, 0x6D46, 0x6D45, 0x375A, 0x6D48, 0, -}; -static const unsigned short utf8_to_euc_E8BB_x0213[] = { - 0x7C4A, 0xE055, 0, 0xE056, 0xE057, 0x6D40, 0x6D3D, 0xE058, - 0x6D41, 0, 0x3C56, 0x6D42, 0x3530, 0x3733, 0, 0, - 0, 0xF95A, 0x382E, 0, 0xF95B, 0, 0, 0, - 0, 0, 0, 0x6D43, 0xE05C, 0, 0, 0x4670, - 0, 0, 0x453E, 0x6D44, 0, 0, 0, 0, - 0xE05D, 0, 0, 0x6D47, 0, 0xE064, 0xE05E, 0, - 0xE05F, 0xE060, 0, 0, 0, 0, 0, 0xE061, - 0x3C34, 0xF95D, 0x7C4C, 0x6D46, 0x6D45, 0x375A, 0x6D48, 0, -}; -static const unsigned short utf8_to_euc_E8BC[] = { - 0xE065, 0, 0xE066, 0x3353, 0, 0x6D4A, 0, 0xE067, - 0xE068, 0x3A5C, 0x6D49, 0, 0x6D52, 0, 0, 0xE069, - 0xE06A, 0, 0x6D4C, 0x6D4E, 0x4A65, 0x6D4B, 0xE06B, 0xE06C, - 0xE06D, 0x6D4D, 0, 0x6D51, 0x6D4F, 0x3531, 0xE06E, 0x6D50, - 0xE06F, 0xE070, 0, 0xE071, 0, 0xE072, 0x6D53, 0xE073, - 0xE074, 0x475A, 0x4E58, 0, 0xE075, 0xE076, 0xE077, 0x3D34, - 0, 0, 0, 0x6D54, 0xE078, 0xE079, 0xE07A, 0xE07B, - 0x4D22, 0x6D56, 0xE07C, 0x6D55, 0, 0, 0x6D59, 0x4D41, -}; -static const unsigned short utf8_to_euc_E8BC_x0213[] = { - 0xF95F, 0, 0xE066, 0x3353, 0, 0x6D4A, 0, 0xE067, - 0xF960, 0x3A5C, 0x6D49, 0, 0x6D52, 0, 0, 0xE069, - 0xE06A, 0, 0x6D4C, 0x6D4E, 0x4A65, 0x6D4B, 0xE06B, 0xF961, - 0xE06D, 0x6D4D, 0, 0x6D51, 0x6D4F, 0x3531, 0x7C4D, 0x6D50, - 0xE06F, 0xE070, 0, 0xE071, 0, 0xE072, 0x6D53, 0xE073, - 0xE074, 0x475A, 0x4E58, 0xF962, 0xE075, 0x7C4E, 0xE077, 0x3D34, - 0, 0, 0, 0x6D54, 0xE078, 0xE079, 0x7C4F, 0xE07B, - 0x4D22, 0x6D56, 0xE07C, 0x6D55, 0, 0, 0x6D59, 0x4D41, -}; -static const unsigned short utf8_to_euc_E8BD[] = { - 0xE07D, 0xE07E, 0x6D58, 0xE121, 0x336D, 0x6D57, 0x6D5C, 0xE122, - 0, 0x6D5B, 0, 0, 0x6D5A, 0x4532, 0x6D5D, 0xE123, - 0, 0xE124, 0xE125, 0xE126, 0xE127, 0xE128, 0, 0x6D5E, - 0xE129, 0, 0, 0, 0x6D5F, 0xE12A, 0xE12B, 0x396C, - 0, 0x3725, 0x6D60, 0x6D61, 0x6D62, 0xE12C, 0, 0, - 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 unsigned short utf8_to_euc_E8BD_x0213[] = { - 0xF963, 0xE07E, 0x6D58, 0xE121, 0x336D, 0x6D57, 0x6D5C, 0xE122, - 0, 0x6D5B, 0xF964, 0, 0x6D5A, 0x4532, 0x6D5D, 0xE123, - 0, 0xE124, 0xE125, 0xE126, 0x7C50, 0xE128, 0, 0x6D5E, - 0xF965, 0, 0, 0, 0x6D5F, 0xE12A, 0xE12B, 0x396C, - 0, 0x3725, 0x6D60, 0x6D61, 0x6D62, 0xE12C, 0, 0, - 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 unsigned short utf8_to_euc_E8BE[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x3F49, 0x6D63, 0xE12D, 0x3C2D, 0x6D64, - 0xE12E, 0xE12F, 0, 0x6D65, 0xE130, 0xE131, 0xE132, 0x5221, - 0x517E, 0, 0, 0, 0, 0x6D66, 0x6570, 0x6D67, - 0x4324, 0x3F2B, 0x4740, 0, 0, 0xE133, 0xE134, 0x6D68, - 0xE135, 0, 0x4A55, 0x4454, 0x397E, 0, 0xE136, 0x4329, -}; -static const unsigned short utf8_to_euc_E8BE_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x3F49, 0x6D63, 0xE12D, 0x3C2D, 0x6D64, - 0xE12E, 0xE12F, 0, 0x6D65, 0xF967, 0xE131, 0x7C52, 0x5221, - 0x517E, 0, 0, 0, 0, 0x6D66, 0x6570, 0x6D67, - 0x4324, 0x3F2B, 0x4740, 0, 0xF968, 0x7C53, 0xF96A, 0x6D68, - 0xE135, 0, 0x4A55, 0x4454, 0x397E, 0, 0xE136, 0x4329, -}; -static const unsigned short utf8_to_euc_E8BF[] = { - 0xE137, 0xE138, 0x312A, 0, 0x4B78, 0x3F57, 0xE139, 0, - 0, 0, 0xE13A, 0xE13B, 0, 0xE13C, 0x375E, 0, - 0xE13D, 0x3661, 0xE13E, 0xE13F, 0x4A56, 0xE140, 0, 0, - 0, 0, 0x6D69, 0, 0, 0, 0, 0, - 0xE141, 0, 0x6D6B, 0xE142, 0xE143, 0x6D6A, 0x3260, 0, - 0xE144, 0x4676, 0x6D6C, 0x4777, 0, 0x4533, 0xE145, 0x6D6D, - 0x3D52, 0xE146, 0, 0, 0x6D6F, 0xE147, 0xE148, 0x4C42, - 0x6D7E, 0x6D71, 0x6D72, 0xE149, 0, 0x4449, 0xE14A, 0, -}; -static const unsigned short utf8_to_euc_E8BF_x0213[] = { - 0xE137, 0xF96C, 0x312A, 0, 0x4B78, 0x3F57, 0xF96D, 0, - 0, 0, 0xF96F, 0xE13B, 0, 0xF970, 0x375E, 0, - 0xE13D, 0x3661, 0xE13E, 0xF971, 0x4A56, 0xF972, 0, 0, - 0, 0, 0x6D69, 0, 0, 0, 0, 0, - 0xF973, 0, 0x6D6B, 0xE142, 0x7C54, 0x6D6A, 0x3260, 0, - 0x7C55, 0x4676, 0x6D6C, 0x4777, 0, 0x4533, 0x7C56, 0x6D6D, - 0x3D52, 0xF974, 0, 0, 0x6D6F, 0xF975, 0xE148, 0x4C42, - 0x6D7E, 0x6D71, 0x6D72, 0xF976, 0, 0x4449, 0xE14A, 0, -}; -static const unsigned short utf8_to_euc_E980[] = { - 0x4260, 0x4177, 0xE14B, 0x4628, 0xE14C, 0x6D70, 0x3555, 0, - 0xE14D, 0, 0, 0x6D79, 0xE14E, 0x6D76, 0x6E25, 0x4629, - 0x4360, 0x6D73, 0, 0x447E, 0x4553, 0x6D74, 0x6D78, 0x3F60, - 0xE14F, 0x4767, 0x444C, 0xE150, 0, 0x4042, 0x6D77, 0x422E, - 0x4224, 0x6D75, 0x3029, 0x4F22, 0, 0, 0, 0x6D7A, - 0xE151, 0xE152, 0xE154, 0, 0xE155, 0xE156, 0x4261, 0xE153, - 0, 0x3D35, 0x3F4A, 0xE157, 0xE158, 0x6D7C, 0x6D7B, 0xE159, - 0x306F, 0x6D7D, 0, 0, 0x492F, 0, 0x6E27, 0xE15A, -}; -static const unsigned short utf8_to_euc_E980_x0213[] = { - 0x4260, 0x4177, 0xF977, 0x4628, 0xE14C, 0x6D70, 0x3555, 0, - 0x7C57, 0, 0, 0x6D79, 0xF978, 0x6D76, 0x6E25, 0x4629, - 0x4360, 0x6D73, 0, 0x447E, 0x4553, 0x6D74, 0x6D78, 0x3F60, - 0xE14F, 0x4767, 0x444C, 0xE150, 0, 0x4042, 0x6D77, 0x422E, - 0x4224, 0x6D75, 0x3029, 0x4F22, 0, 0, 0, 0x6D7A, - 0xE151, 0xE152, 0xE154, 0, 0xE155, 0x7C58, 0x4261, 0xE153, - 0, 0x3D35, 0x3F4A, 0xE157, 0xE158, 0x6D7C, 0x6D7B, 0xF979, - 0x306F, 0x6D7D, 0, 0, 0x492F, 0, 0x6E27, 0xE15A, -}; -static const unsigned short utf8_to_euc_E981[] = { - 0, 0x465B, 0x3F6B, 0xE15B, 0xE15C, 0x4359, 0, 0x3678, - 0, 0x6E26, 0x4D37, 0x313F, 0xE15D, 0x4A57, 0x3261, 0x6E21, - 0x6E22, 0x6E23, 0x6E24, 0x463B, 0x4323, 0x3063, 0x6E28, 0, - 0x6E29, 0x7423, 0, 0xE15E, 0x423D, 0xE15F, 0x6E2A, 0, - 0x3173, 0x414C, 0xE160, 0x382F, 0, 0x4D5A, 0xE161, 0xE162, - 0x6E2B, 0x452C, 0, 0, 0xE163, 0x4178, 0x3C57, 0x6E2C, - 0xE164, 0, 0x6E2F, 0, 0xE165, 0x3D65, 0x6E2D, 0x412B, - 0x412A, 0xE166, 0x3064, 0, 0x4E4B, 0x6E31, 0, 0x4872, -}; -static const unsigned short utf8_to_euc_E981_x0213[] = { - 0, 0x465B, 0x3F6B, 0xF97B, 0xF97C, 0x4359, 0, 0x3678, - 0, 0x6E26, 0x4D37, 0x313F, 0xE15D, 0x4A57, 0x3261, 0x6E21, - 0x6E22, 0x6E23, 0x6E24, 0x463B, 0x4323, 0x3063, 0x6E28, 0, - 0x6E29, 0x7423, 0, 0xE15E, 0x423D, 0xF97D, 0x6E2A, 0, - 0x3173, 0x414C, 0xE160, 0x382F, 0, 0x4D5A, 0xE161, 0, - 0x6E2B, 0x452C, 0, 0, 0xE163, 0x4178, 0x3C57, 0x6E2C, - 0xE164, 0, 0x6E2F, 0, 0xE165, 0x3D65, 0x6E2D, 0x412B, - 0x412A, 0xE166, 0x3064, 0, 0x4E4B, 0x6E31, 0, 0x4872, -}; -static const unsigned short utf8_to_euc_E982[] = { - 0x6E33, 0x6E32, 0x6E30, 0x6364, 0x3454, 0xE167, 0, 0x6D6E, - 0xE168, 0x6E35, 0x6E34, 0xE169, 0xE16A, 0, 0xE16B, 0x6E36, - 0xE16C, 0x4D38, 0, 0, 0, 0xE16D, 0, 0xE16E, - 0xE16F, 0xE170, 0, 0xE171, 0, 0, 0, 0, - 0xE172, 0xE173, 0xE174, 0x4661, 0, 0xE175, 0x4B2E, 0, - 0x6E37, 0, 0x3C59, 0, 0, 0, 0, 0x6E38, - 0xE176, 0x6E39, 0xE177, 0xE178, 0xE179, 0x6E3A, 0xE17A, 0, - 0x4521, 0, 0, 0, 0, 0xE17B, 0xE17D, 0, -}; -static const unsigned short utf8_to_euc_E982_x0213[] = { - 0x6E33, 0x6E32, 0x6E30, 0x6364, 0x3454, 0xFA22, 0, 0x6D6E, - 0x7C5A, 0x6E35, 0x6E34, 0xE169, 0xFA23, 0, 0xE16B, 0x6E36, - 0xFA24, 0x4D38, 0, 0, 0, 0x7C5B, 0, 0x7C5C, - 0xE16F, 0x7C5D, 0, 0x7C5E, 0, 0, 0, 0, - 0xE172, 0xFA26, 0x7C5F, 0x4661, 0, 0xE175, 0x4B2E, 0, - 0x6E37, 0, 0x3C59, 0, 0, 0, 0, 0x6E38, - 0xFA28, 0x6E39, 0xE177, 0x7C60, 0xE179, 0x6E3A, 0xFA29, 0, - 0x4521, 0, 0, 0, 0, 0xE17B, 0x7C61, 0, -}; -static const unsigned short utf8_to_euc_E983[] = { - 0, 0x306A, 0, 0xE17E, 0xE221, 0xE222, 0, 0xE223, - 0xE224, 0, 0x3959, 0, 0xE17C, 0, 0x4F3A, 0, - 0, 0, 0xE22D, 0, 0, 0xE225, 0, 0xE226, - 0xE227, 0xE228, 0, 0x6E3E, 0xE229, 0xE22A, 0xF46C, 0xE22B, - 0, 0x3734, 0x6E3B, 0, 0x6E3C, 0xE22C, 0, 0, - 0x4974, 0, 0, 0xE22F, 0, 0x3354, 0, 0xE230, - 0xE231, 0, 0, 0, 0xE232, 0x4D39, 0xE22E, 0x363F, - 0, 0, 0, 0, 0, 0x4554, 0xE233, 0xE234, -}; -static const unsigned short utf8_to_euc_E983_x0213[] = { - 0, 0x306A, 0, 0xFA2A, 0x7C62, 0x7C63, 0, 0x7C64, - 0xFA2B, 0, 0x3959, 0, 0xE17C, 0, 0x4F3A, 0, - 0, 0, 0xE22D, 0, 0, 0xE225, 0, 0x7C65, - 0xE227, 0xE228, 0, 0x6E3E, 0xFA2D, 0x7C66, 0x7C67, 0xFA2E, - 0, 0x3734, 0x6E3B, 0, 0x6E3C, 0xE22C, 0, 0, - 0x4974, 0, 0, 0xFA33, 0, 0x3354, 0, 0x7C68, - 0xE231, 0, 0xFA31, 0, 0x7C69, 0x4D39, 0xFA30, 0x363F, - 0, 0, 0, 0, 0, 0x4554, 0xFA34, 0xFA35, -}; -static const unsigned short utf8_to_euc_E984[] = { - 0xE235, 0, 0x6E3F, 0, 0xE236, 0xE237, 0xE238, 0, - 0xE239, 0, 0, 0, 0, 0xE23A, 0, 0, - 0xE23B, 0, 0x6E40, 0, 0xE23C, 0xF46E, 0xE23D, 0xE23E, - 0xE23F, 0x6E41, 0xE240, 0, 0xE241, 0, 0xE242, 0, - 0xE243, 0, 0xE245, 0xE246, 0, 0xE244, 0, 0xE247, - 0, 0xE248, 0, 0, 0, 0x4522, 0xE249, 0xE24A, - 0x6E43, 0xE24B, 0x6E42, 0, 0xE24C, 0, 0xE24D, 0xE24E, - 0, 0xE24F, 0xE250, 0, 0xE251, 0xE252, 0, 0, -}; -static const unsigned short utf8_to_euc_E984_x0213[] = { - 0xFA32, 0, 0x6E3F, 0, 0xFA36, 0xE237, 0xFA37, 0, - 0xE239, 0, 0, 0, 0, 0xE23A, 0, 0, - 0xE23B, 0, 0x6E40, 0, 0x7C6B, 0x7C6C, 0x7C6D, 0xE23E, - 0xFA38, 0x6E41, 0xE240, 0, 0xFA39, 0, 0xFA3A, 0, - 0xE243, 0, 0x7C6E, 0x7C6F, 0, 0xE244, 0, 0x7C70, - 0, 0xE248, 0, 0, 0, 0x4522, 0xE249, 0x7C71, - 0x6E43, 0x7C72, 0x6E42, 0, 0x7C73, 0, 0xE24D, 0xFA3B, - 0, 0xFA3C, 0xFA3D, 0, 0xE251, 0x7C74, 0, 0, -}; -static const unsigned short utf8_to_euc_E985[] = { - 0, 0, 0, 0xE253, 0, 0, 0, 0xE254, - 0xE255, 0x4653, 0x6E44, 0x3D36, 0x3C60, 0x475B, 0x4371, 0xE256, - 0, 0, 0x3C72, 0xE257, 0x3F6C, 0, 0x6E45, 0xE258, - 0x6E46, 0xE259, 0xE25A, 0xE25B, 0, 0, 0, 0, - 0, 0xE25C, 0x3F5D, 0x6E47, 0xE25D, 0x6E48, 0, 0xE25E, - 0, 0x6E49, 0x4D6F, 0, 0x3D37, 0xE25F, 0, 0, - 0, 0, 0x6E4B, 0x6E4A, 0xE260, 0x395A, 0, 0x3973, - 0x3B40, 0xE261, 0xE262, 0xE263, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E985_x0213[] = { - 0, 0, 0, 0xE253, 0, 0, 0xFA3E, 0xFA3F, - 0x7C75, 0x4653, 0x6E44, 0x3D36, 0x3C60, 0x475B, 0x4371, 0xE256, - 0, 0, 0x3C72, 0xE257, 0x3F6C, 0, 0x6E45, 0xFA40, - 0x6E46, 0xFA41, 0xE25A, 0x7C76, 0, 0, 0, 0, - 0, 0xFA42, 0x3F5D, 0x6E47, 0xFA43, 0x6E48, 0, 0xE25E, - 0, 0x6E49, 0x4D6F, 0, 0x3D37, 0xE25F, 0, 0, - 0, 0, 0x6E4B, 0x6E4A, 0xFA44, 0x395A, 0, 0x3973, - 0x3B40, 0xFA45, 0xE262, 0xE263, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E986[] = { - 0, 0xE264, 0x6E4E, 0xE265, 0, 0xE266, 0xE267, 0x3D66, - 0, 0x6E4D, 0xE268, 0x6E4C, 0, 0x4269, 0xE269, 0, - 0x386F, 0xE26A, 0x4043, 0xE26B, 0xE26C, 0xE26D, 0, 0x4830, - 0xE26E, 0, 0, 0, 0x3D39, 0, 0xE26F, 0, - 0, 0xE270, 0x6E4F, 0, 0x3E5F, 0, 0xE271, 0, - 0xE272, 0, 0x6E52, 0x6E50, 0xE273, 0xE274, 0xE275, 0x6E51, - 0xE276, 0xE277, 0xE278, 0xE279, 0x6E54, 0x6E53, 0xE27A, 0, - 0x3E7A, 0, 0x6E55, 0xE27B, 0xE27C, 0xE27D, 0, 0xE27E, -}; -static const unsigned short utf8_to_euc_E986_x0213[] = { - 0, 0xE264, 0x6E4E, 0x7C77, 0, 0xFA46, 0xE267, 0x3D66, - 0, 0x6E4D, 0xE268, 0x6E4C, 0, 0x4269, 0xFA47, 0, - 0x386F, 0xE26A, 0x4043, 0xE26B, 0xE26C, 0xE26D, 0, 0x4830, - 0xE26E, 0, 0, 0, 0x3D39, 0, 0x7C78, 0, - 0, 0xE270, 0x6E4F, 0, 0x3E5F, 0, 0xE271, 0, - 0xFA48, 0, 0x6E52, 0x6E50, 0x7C79, 0xE274, 0xFA49, 0x6E51, - 0xE276, 0x7C7A, 0xE278, 0xFA4A, 0x6E54, 0x6E53, 0xFA4B, 0, - 0x3E7A, 0, 0x6E55, 0xE27B, 0x7C7B, 0xE27D, 0, 0xE27E, -}; -static const unsigned short utf8_to_euc_E987[] = { - 0x6E56, 0x6E57, 0xE321, 0xE322, 0, 0xE323, 0x4850, 0x3A53, - 0x3C61, 0x6E58, 0, 0x6E59, 0x4E24, 0x3D45, 0x4C6E, 0x4E4C, - 0x6E5A, 0x3662, 0, 0xE324, 0xE325, 0, 0x6E5B, 0xE326, - 0x4523, 0xE327, 0xE328, 0x6E5E, 0x3378, 0x3F4B, 0xE329, 0x6E5C, - 0, 0x6E5D, 0, 0x4460, 0xE32A, 0xE32B, 0x4B55, 0x367C, - 0, 0xE32C, 0xE32D, 0, 0xE32E, 0xE32F, 0xE330, 0xE331, - 0xE332, 0xE333, 0, 0, 0, 0x6E60, 0x6E61, 0xE334, - 0, 0xE335, 0, 0xE336, 0x6E5F, 0xE337, 0, 0x6E63, -}; -static const unsigned short utf8_to_euc_E987_x0213[] = { - 0x6E56, 0x6E57, 0xE321, 0xFA4C, 0xFA4D, 0xE323, 0x4850, 0x3A53, - 0x3C61, 0x6E58, 0, 0x6E59, 0x4E24, 0x3D45, 0x4C6E, 0x4E4C, - 0x6E5A, 0x3662, 0, 0xE324, 0xE325, 0, 0x6E5B, 0x7C7C, - 0x4523, 0xE327, 0xFA4E, 0x6E5E, 0x3378, 0x3F4B, 0, 0x6E5C, - 0, 0x6E5D, 0, 0x4460, 0x7C7E, 0x7D21, 0x4B55, 0x367C, - 0, 0xE32C, 0xE32D, 0, 0xFA51, 0x7D22, 0xFA52, 0xE331, - 0xE332, 0x7D23, 0, 0, 0, 0x6E60, 0x6E61, 0xE334, - 0, 0xE335, 0, 0x7C7D, 0x6E5F, 0xE337, 0, 0x6E63, -}; -static const unsigned short utf8_to_euc_E988[] = { - 0xE338, 0xE339, 0, 0, 0xE33A, 0xE33B, 0xE33C, 0xE33D, - 0, 0xE33E, 0xE33F, 0, 0xE340, 0x465F, 0x3343, 0, - 0xE341, 0x6E67, 0xE342, 0xE343, 0x6E64, 0x6E66, 0xE344, 0, - 0xE345, 0, 0, 0, 0xE346, 0xE347, 0x6E62, 0, - 0, 0, 0, 0xE348, 0xE349, 0xE34A, 0xE34B, 0, - 0xE34C, 0x6F4F, 0, 0, 0x6E65, 0, 0xE34D, 0xE34E, - 0xE34F, 0, 0, 0xE350, 0x4E6B, 0xE351, 0xE352, 0x385A, - 0xE353, 0xE354, 0xE355, 0, 0xE356, 0, 0xE357, 0x6E6F, -}; -static const unsigned short utf8_to_euc_E988_x0213[] = { - 0xE338, 0xFA53, 0, 0, 0xE33A, 0xE33B, 0, 0x7D24, - 0, 0xE33E, 0xFA54, 0, 0xE340, 0x465F, 0x3343, 0, - 0x7D25, 0x6E67, 0xE342, 0xE343, 0x6E64, 0x6E66, 0xFA55, 0xFA56, - 0xE345, 0, 0, 0, 0xE346, 0xE347, 0x6E62, 0, - 0, 0, 0, 0xE348, 0xE349, 0xE34A, 0xE34B, 0, - 0xE34C, 0x6F4F, 0, 0, 0x6E65, 0, 0xE34D, 0xE34E, - 0xE34F, 0, 0, 0xFA58, 0x4E6B, 0xE351, 0xE352, 0x385A, - 0x7D26, 0x7D27, 0x7D28, 0, 0x7D29, 0, 0xE357, 0x6E6F, -}; -static const unsigned short utf8_to_euc_E989[] = { - 0xE358, 0, 0xE359, 0xE35A, 0x4534, 0x6E6A, 0xE35B, 0xE35C, - 0x6E6D, 0x6E6B, 0xE35D, 0x6E70, 0, 0xE35E, 0xE35F, 0xE360, - 0x6E71, 0xE361, 0, 0, 0, 0, 0, 0x6E69, - 0xE362, 0xE363, 0x6E76, 0x3174, 0xE364, 0xE365, 0x6E68, 0, - 0xE366, 0xE367, 0x482D, 0, 0x6E6C, 0xE368, 0x3E60, 0xE369, - 0xE36A, 0xE36B, 0, 0, 0, 0, 0xE36C, 0xE36D, - 0xE36E, 0x395B, 0, 0, 0, 0xE36F, 0xE370, 0xE371, - 0xE372, 0xE373, 0, 0xE374, 0xE375, 0xE376, 0x4B48, 0xE377, -}; -static const unsigned short utf8_to_euc_E989_x0213[] = { - 0x7D2A, 0, 0xFA59, 0x7D2B, 0x4534, 0x6E6A, 0xE35B, 0xFA5A, - 0x6E6D, 0x6E6B, 0xFA5B, 0x6E70, 0, 0xE35E, 0xFA5C, 0x7D2C, - 0x6E71, 0xFA5D, 0, 0, 0, 0, 0xFA5E, 0x6E69, - 0xE362, 0xFA5F, 0x6E76, 0x3174, 0xE364, 0xE365, 0x6E68, 0, - 0xFA60, 0xFA61, 0x482D, 0, 0x6E6C, 0xFA62, 0x3E60, 0xFA63, - 0xFA64, 0xE36B, 0, 0, 0, 0, 0xE36C, 0xE36D, - 0xE36E, 0x395B, 0, 0, 0, 0xE36F, 0xE370, 0, - 0x7D2D, 0xE373, 0, 0xE374, 0xFA67, 0xFA68, 0x4B48, 0xFA69, -}; -static const unsigned short utf8_to_euc_E98A[] = { - 0x3664, 0, 0, 0x3D46, 0, 0x463C, 0, 0, - 0xE378, 0xE379, 0xE37A, 0, 0, 0xE37B, 0xE37C, 0, - 0, 0x412D, 0xE37D, 0x6E74, 0, 0x6E6E, 0x6E73, 0xE37E, - 0x4C43, 0xE421, 0x4438, 0x6E75, 0x6E72, 0, 0, 0xE422, - 0xE423, 0, 0, 0, 0xE424, 0xE425, 0, 0xE426, - 0xE427, 0, 0, 0xE428, 0, 0x412C, 0, 0xE429, - 0, 0, 0xE42A, 0, 0, 0, 0xE42B, 0x6E79, - 0xE42C, 0x6E78, 0xE42D, 0xE42E, 0xE42F, 0xE430, 0, 0xE431, -}; -static const unsigned short utf8_to_euc_E98A_x0213[] = { - 0x3664, 0, 0, 0x3D46, 0, 0x463C, 0, 0, - 0x7D2E, 0xFA6A, 0xE37A, 0, 0, 0xFA6B, 0xE37C, 0, - 0, 0x412D, 0xE37D, 0x6E74, 0, 0x6E6E, 0x6E73, 0xFA6C, - 0x4C43, 0xFA6D, 0x4438, 0x6E75, 0x6E72, 0, 0, 0xFA6E, - 0xE423, 0, 0, 0, 0xE424, 0xE425, 0, 0xFA6F, - 0xE427, 0, 0, 0xFA70, 0, 0x412C, 0, 0xE429, - 0, 0, 0xFA73, 0, 0, 0, 0xE42B, 0x6E79, - 0xE42C, 0x6E78, 0xE42D, 0xE42E, 0xE42F, 0xE430, 0, 0xFA74, -}; -static const unsigned short utf8_to_euc_E98B[] = { - 0xE432, 0xE433, 0xE434, 0xE435, 0, 0xE436, 0xE437, 0xE438, - 0xE439, 0, 0, 0xE43A, 0xE43B, 0xE43C, 0xE43D, 0x6E77, - 0xE43E, 0, 0x4B2F, 0xE43F, 0, 0xE440, 0, 0xE441, - 0xE442, 0xE443, 0, 0, 0xE444, 0xE445, 0, 0xE446, - 0xE447, 0xE448, 0, 0xE449, 0x3D7B, 0xE44A, 0, 0xE44B, - 0xE44C, 0x6E7A, 0x4A5F, 0, 0xE44D, 0x3154, 0xE44E, 0, - 0xE44F, 0, 0x4946, 0x4372, 0, 0, 0, 0, - 0x3578, 0xE450, 0x6E7C, 0xE451, 0x395D, 0, 0, 0xE452, -}; -static const unsigned short utf8_to_euc_E98B_x0213[] = { - 0xFA75, 0xE433, 0x7D2F, 0xE435, 0, 0xE436, 0xFA76, 0xE438, - 0xE439, 0, 0, 0x7D30, 0x7D31, 0xE43C, 0xFA77, 0x6E77, - 0xFA78, 0, 0x4B2F, 0x7D32, 0, 0, 0, 0xFA79, - 0xE442, 0xFA7A, 0, 0, 0xE444, 0xE445, 0, 0xE446, - 0x7D33, 0xE448, 0, 0xE449, 0x3D7B, 0xFA7B, 0, 0xFA7C, - 0xE44C, 0x6E7A, 0x4A5F, 0, 0xE44D, 0x3154, 0xE44E, 0, - 0xE44F, 0, 0x4946, 0x4372, 0, 0, 0, 0xFB22, - 0x3578, 0xFB23, 0x6E7C, 0xFB24, 0x395D, 0, 0, 0x7D34, -}; -static const unsigned short utf8_to_euc_E98C[] = { - 0xE453, 0, 0xE454, 0, 0, 0, 0x3B2C, 0, - 0xE455, 0, 0, 0, 0, 0xE456, 0, 0x6E7B, - 0x3F6D, 0xE457, 0, 0, 0xE458, 0xE459, 0, 0, - 0x3F6E, 0x6F21, 0x6F23, 0, 0xE45A, 0xE45B, 0xE45C, 0xE45D, - 0x3E7B, 0xE45E, 0x6F22, 0x6F24, 0xE45F, 0xE460, 0x3653, 0xE461, - 0x4945, 0xE462, 0xE463, 0x3C62, 0x4F23, 0, 0x6E7E, 0x3A78, - 0, 0, 0x4F3F, 0xE464, 0xE465, 0x6F26, 0xE466, 0xE467, - 0, 0, 0x6F25, 0x6F27, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E98C_x0213[] = { - 0xE453, 0, 0xFB25, 0, 0x7D35, 0, 0x3B2C, 0, - 0xE455, 0, 0, 0, 0, 0xFB26, 0, 0x6E7B, - 0x3F6D, 0xFA7D, 0, 0, 0xE458, 0xFB27, 0, 0, - 0x3F6E, 0x6F21, 0x6F23, 0, 0xE45A, 0xFB28, 0xFB29, 0x7D36, - 0x3E7B, 0x7D37, 0x6F22, 0x6F24, 0xE45F, 0x7D38, 0x3653, 0xFB2A, - 0x4945, 0xFB2B, 0xE463, 0x3C62, 0x4F23, 0, 0x6E7E, 0x3A78, - 0, 0, 0x4F3F, 0xE464, 0xE465, 0x6F26, 0xE466, 0xE467, - 0, 0, 0x6F25, 0x6F27, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E98D[] = { - 0, 0, 0, 0, 0x6E7D, 0, 0, 0xE468, - 0xE469, 0xE46A, 0, 0x4669, 0, 0x4555, 0, 0, - 0xE46B, 0xE46C, 0xE46D, 0, 0x4457, 0xE46E, 0x6F2C, 0xE46F, - 0xE470, 0, 0xE471, 0x4343, 0x6F28, 0, 0xE472, 0, - 0x6F29, 0, 0, 0, 0xE473, 0xE474, 0, 0xE475, - 0, 0xE476, 0xE477, 0, 0x372D, 0xE478, 0x6F2B, 0xE479, - 0xE47A, 0xE47B, 0, 0xE47C, 0xE47D, 0x3830, 0xE47E, 0, - 0, 0, 0xE521, 0, 0x6F2A, 0xE522, 0x3E61, 0xE523, -}; -static const unsigned short utf8_to_euc_E98D_x0213[] = { - 0, 0, 0, 0, 0x6E7D, 0, 0, 0xFB2E, - 0x7D39, 0x7D3A, 0x7D3B, 0x4669, 0, 0x4555, 0, 0, - 0xE46B, 0xFB2F, 0xE46D, 0, 0x4457, 0xE46E, 0x6F2C, 0xFB30, - 0xE470, 0, 0xFB31, 0x4343, 0x6F28, 0, 0xE472, 0, - 0x6F29, 0, 0, 0, 0x7D3C, 0x7D3D, 0, 0xE475, - 0, 0xE476, 0x7D3E, 0xFB32, 0x372D, 0xE478, 0x6F2B, 0xE479, - 0x7D3F, 0xFB33, 0, 0xFB34, 0xE47D, 0x3830, 0xE47E, 0, - 0, 0, 0xE521, 0, 0x6F2A, 0xE522, 0x3E61, 0xE523, -}; -static const unsigned short utf8_to_euc_E98E[] = { - 0xE524, 0xE525, 0xE526, 0, 0, 0, 0, 0, - 0xE527, 0, 0xE528, 0xE529, 0x3379, 0xE52A, 0, 0xE52B, - 0, 0, 0xE52C, 0, 0x6F30, 0xE52D, 0x3A3F, 0x4179, - 0xE52E, 0, 0x444A, 0xE52F, 0, 0, 0xE530, 0, - 0, 0xE531, 0, 0xE532, 0xE533, 0, 0xE534, 0x333B, - 0xE535, 0xE53B, 0, 0xE536, 0x6F2E, 0x6F2F, 0x4443, 0, - 0x6F2D, 0, 0, 0, 0xE537, 0xE538, 0xE539, 0, - 0, 0x6F31, 0xE53A, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E98E_x0213[] = { - 0xE524, 0xE525, 0xE526, 0, 0, 0, 0, 0, - 0xFB38, 0, 0xE528, 0xFB39, 0x3379, 0xE52A, 0, 0xFB3A, - 0, 0, 0xE52C, 0, 0x6F30, 0xE52D, 0x3A3F, 0x4179, - 0xE52E, 0, 0x444A, 0x7D40, 0, 0, 0xFB3B, 0, - 0, 0xFB35, 0, 0x7D41, 0, 0, 0xE534, 0x333B, - 0xE535, 0xE53B, 0, 0xE536, 0x6F2E, 0x6F2F, 0x4443, 0, - 0x6F2D, 0, 0, 0, 0xE537, 0xE538, 0xE539, 0, - 0, 0x6F31, 0x7D42, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E98F[] = { - 0, 0xE53C, 0, 0x6F37, 0xE53D, 0xE53E, 0xE53F, 0xE540, - 0x6F3A, 0xE541, 0xE542, 0xE543, 0xE544, 0xE545, 0, 0, - 0x6F39, 0x452D, 0, 0xE546, 0, 0, 0x6F32, 0x6F33, - 0x6F36, 0xE547, 0, 0, 0xE548, 0x6F38, 0xE549, 0xE54A, - 0, 0x3640, 0xE54B, 0, 0x6F3B, 0x6F35, 0xE54C, 0xE54D, - 0x6F34, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xE54F, - 0xE550, 0xE54E, 0xE551, 0xE552, 0, 0xE553, 0, 0, -}; -static const unsigned short utf8_to_euc_E98F_x0213[] = { - 0, 0xFB40, 0, 0x6F37, 0xE53D, 0xE53E, 0x7D43, 0xFB41, - 0x6F3A, 0xE541, 0xE542, 0xE543, 0xE544, 0xE545, 0, 0, - 0x6F39, 0x452D, 0, 0xE546, 0, 0, 0x6F32, 0x6F33, - 0x6F36, 0xE547, 0, 0, 0xFB42, 0x6F38, 0x7D44, 0x7D45, - 0, 0x3640, 0xFB43, 0, 0x6F3B, 0x6F35, 0xE54C, 0xFB44, - 0x6F34, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFB3F, 0, 0, 0, 0xFB3C, 0, 0xE54F, - 0, 0xE54E, 0xE551, 0xFB49, 0, 0x7D47, 0, 0, -}; -static const unsigned short utf8_to_euc_E990[] = { - 0, 0xE554, 0xE555, 0x6F3F, 0xE556, 0, 0, 0x6F40, - 0xE557, 0xE558, 0, 0, 0, 0xE559, 0xE55A, 0xE55B, - 0x6F41, 0, 0, 0x6F3E, 0x6F3D, 0xE55C, 0xE55D, 0xE55E, - 0x3E62, 0x462A, 0x6F3C, 0, 0, 0, 0, 0xE55F, - 0, 0x6F45, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x6F43, 0, 0, 0xE560, 0xE561, - 0, 0xE562, 0xE563, 0xE564, 0xE565, 0x6F44, 0x6F42, 0, - 0x4278, 0, 0x6F46, 0xE566, 0, 0xE568, 0, 0xE567, -}; -static const unsigned short utf8_to_euc_E990_x0213[] = { - 0, 0xE554, 0xE555, 0x6F3F, 0x7D46, 0, 0, 0x6F40, - 0xE557, 0xFB45, 0, 0, 0, 0xE559, 0xE55A, 0xFB46, - 0x6F41, 0, 0, 0x6F3E, 0x6F3D, 0xE55C, 0xFB47, 0xFB48, - 0x3E62, 0x462A, 0x6F3C, 0, 0, 0, 0, 0xE55F, - 0, 0x6F45, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x6F43, 0, 0, 0xE560, 0xE561, - 0, 0, 0xFB4A, 0x7D48, 0xFB4B, 0x6F44, 0x6F42, 0, - 0x4278, 0, 0x6F46, 0xFB4C, 0, 0xE568, 0, 0xE567, -}; -static const unsigned short utf8_to_euc_E991[] = { - 0, 0x6F47, 0, 0xE569, 0x6F49, 0xE56A, 0, 0, - 0xE56B, 0, 0xE56C, 0, 0xE56D, 0, 0, 0, - 0, 0x3455, 0x6F48, 0x4C7A, 0, 0xE56E, 0, 0, - 0, 0xE56F, 0x6F54, 0x6F4A, 0xE570, 0, 0x6F4D, 0xE571, - 0x6F4B, 0xE572, 0x6F4C, 0xE573, 0, 0, 0, 0, - 0xE574, 0, 0x6F4E, 0xE575, 0, 0xE576, 0xE577, 0xE578, - 0x6F50, 0xE579, 0xE57A, 0, 0, 0x6F51, 0, 0x6F52, - 0, 0, 0, 0, 0x6F55, 0x6F53, 0x6F56, 0x6F58, -}; -static const unsigned short utf8_to_euc_E991_x0213[] = { - 0, 0x6F47, 0, 0xE569, 0x6F49, 0xFB4D, 0, 0, - 0, 0, 0x7D49, 0, 0xE56D, 0, 0, 0, - 0, 0x3455, 0x6F48, 0x4C7A, 0, 0xE56E, 0, 0, - 0, 0xE56F, 0x6F54, 0x6F4A, 0xE570, 0, 0x6F4D, 0xE571, - 0x6F4B, 0xE572, 0x6F4C, 0x7D4A, 0, 0, 0, 0, - 0xE574, 0, 0x6F4E, 0x7D4B, 0, 0xFB50, 0xE577, 0xFB51, - 0x6F50, 0x7D4C, 0x7D4D, 0, 0, 0x6F51, 0, 0x6F52, - 0, 0, 0, 0, 0x6F55, 0x6F53, 0x6F56, 0x6F58, -}; -static const unsigned short utf8_to_euc_E992[] = { - 0, 0x6F57, 0, 0xE57C, 0xE57B, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E995[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x4439, - 0xE57D, 0xE57E, 0, 0, 0, 0, 0xE621, 0, -}; -static const unsigned short utf8_to_euc_E995_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x4439, - 0xFB52, 0xFB53, 0, 0, 0, 0, 0xE621, 0, -}; -static const unsigned short utf8_to_euc_E996[] = { - 0x4C67, 0, 0x6F59, 0x412E, 0xE622, 0, 0, 0x6F5A, - 0xE623, 0x4A44, 0x6F5B, 0x332B, 0xE624, 0xE625, 0xE626, 0x313C, - 0, 0x3457, 0xF471, 0x3456, 0x6F5C, 0, 0x6F5D, 0, - 0x6F5E, 0x6F5F, 0, 0, 0, 0xE627, 0xE628, 0xE629, - 0x6F60, 0xE62A, 0x3458, 0x3355, 0x395E, 0x4836, 0xE62B, 0x6F62, - 0x6F61, 0xE62C, 0, 0xE62D, 0xE62E, 0x6F63, 0, 0, - 0, 0, 0x315C, 0, 0xE62F, 0, 0xE630, 0, - 0, 0x6F66, 0xE631, 0x6F65, 0x6F64, 0xE632, 0x6F67, 0xE633, -}; -static const unsigned short utf8_to_euc_E996_x0213[] = { - 0x4C67, 0, 0x6F59, 0x412E, 0xE622, 0, 0xFB54, 0x6F5A, - 0xE623, 0x4A44, 0x6F5B, 0x332B, 0xFB55, 0xFB56, 0x7D4E, 0x313C, - 0, 0x3457, 0, 0x3456, 0x6F5C, 0, 0x6F5D, 0, - 0x6F5E, 0x6F5F, 0, 0, 0, 0xE627, 0xE628, 0x7D4F, - 0x6F60, 0xE62A, 0x3458, 0x3355, 0x395E, 0x4836, 0x7D50, 0x6F62, - 0x6F61, 0x7D51, 0, 0xFB58, 0x7D52, 0x6F63, 0, 0, - 0, 0, 0x315C, 0, 0xFB59, 0, 0x7D53, 0, - 0, 0x6F66, 0xE631, 0x6F65, 0x6F64, 0x7D54, 0x6F67, 0xE633, -}; -static const unsigned short utf8_to_euc_E997[] = { - 0, 0, 0, 0x6F6A, 0, 0, 0xE634, 0x3047, - 0xE635, 0xE636, 0x6F68, 0xE637, 0x6F6C, 0x6F6B, 0, 0, - 0xE638, 0xE639, 0xE63A, 0xE63B, 0x6F6E, 0x6F6D, 0x6F6F, 0, - 0x462E, 0xE63C, 0xE63D, 0, 0x6F70, 0xE63E, 0xE63F, 0xE640, - 0xE641, 0x6F71, 0x6F73, 0, 0xE642, 0x6F72, 0xE643, 0, - 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 unsigned short utf8_to_euc_E997_x0213[] = { - 0, 0, 0, 0x6F6A, 0, 0, 0xE634, 0x3047, - 0xFB5B, 0xE636, 0x6F68, 0x7D55, 0x6F6C, 0x6F6B, 0, 0, - 0x7D56, 0xE639, 0xE63A, 0x7D57, 0x6F6E, 0x6F6D, 0x6F6F, 0, - 0x462E, 0xE63C, 0x7D59, 0, 0x6F70, 0xE63E, 0x7D5A, 0xE640, - 0xE641, 0x6F71, 0x6F73, 0, 0xE642, 0x6F72, 0xE643, 0, - 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 unsigned short utf8_to_euc_E998[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x496C, 0xE644, 0xE645, 0, - 0, 0x6F74, 0xE646, 0, 0xE647, 0xE648, 0xE649, 0, - 0x6F75, 0, 0x3A65, 0, 0xE64A, 0, 0x6F76, 0x6F77, - 0, 0xE64B, 0x4B49, 0xE64C, 0, 0, 0, 0xE64D, - 0xE64E, 0xE64F, 0xE650, 0x414B, 0xE651, 0xE652, 0, 0x3024, -}; -static const unsigned short utf8_to_euc_E998_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x496C, 0xFA25, 0xE645, 0, - 0, 0x6F74, 0xE646, 0, 0xE647, 0xE648, 0xE649, 0, - 0x6F75, 0, 0x3A65, 0, 0xFB5E, 0, 0x6F76, 0x6F77, - 0, 0xE64B, 0x4B49, 0xFB5F, 0xFB60, 0, 0, 0xE64D, - 0xE64E, 0xE64F, 0xE650, 0x414B, 0xFB62, 0xE652, 0, 0x3024, -}; -static const unsigned short utf8_to_euc_E999[] = { - 0x424B, 0xE653, 0x6F78, 0, 0x496D, 0, 0, 0, - 0, 0, 0, 0x6F7B, 0x6F79, 0x395F, 0, 0x6F7A, - 0x3842, 0, 0xE654, 0, 0xE655, 0, 0xE656, 0xE657, - 0xE658, 0, 0, 0x4A45, 0x6F7D, 0x7021, 0x6F7E, 0x7022, - 0, 0xE659, 0x3121, 0x3F58, 0x3D7C, 0x3459, 0x7023, 0, - 0, 0, 0x4766, 0, 0x7025, 0, 0xE65A, 0, - 0x3122, 0, 0x7024, 0x4444, 0xE65B, 0x4E4D, 0x462B, 0x6F7C, - 0x4E26, 0, 0x3831, 0xE65C, 0xE65D, 0x4D5B, 0xE65E, 0xE65F, -}; -static const unsigned short utf8_to_euc_E999_x0213[] = { - 0x424B, 0xFB63, 0x6F78, 0, 0x496D, 0, 0, 0, - 0, 0, 0, 0x6F7B, 0x6F79, 0x395F, 0, 0x6F7A, - 0x3842, 0, 0xE654, 0, 0xE655, 0, 0xE656, 0xE657, - 0x7D5B, 0, 0, 0x4A45, 0x6F7D, 0x7021, 0x6F7E, 0x7022, - 0, 0xFB64, 0x3121, 0x3F58, 0x3D7C, 0x3459, 0x7023, 0, - 0, 0, 0x4766, 0, 0x7025, 0, 0xE65A, 0, - 0x3122, 0, 0x7024, 0x4444, 0xE65B, 0x4E4D, 0x462B, 0x6F7C, - 0x4E26, 0, 0x3831, 0xE65C, 0xE65D, 0x4D5B, 0xE65E, 0xE65F, -}; -static const unsigned short utf8_to_euc_E99A[] = { - 0, 0xE660, 0xE661, 0xE662, 0xE663, 0x3679, 0x4E34, 0, - 0x3728, 0xE664, 0x4262, 0x6721, 0, 0x7026, 0x332C, 0x3F6F, - 0, 0xE665, 0, 0, 0x3356, 0x7028, 0xE666, 0x7029, - 0x7027, 0x3764, 0xE667, 0x3A5D, 0x3E63, 0xE668, 0, 0xE669, - 0x3123, 0, 0, 0x4E59, 0xE66A, 0xE66B, 0xE66C, 0x702B, - 0x6E2E, 0xE66D, 0x702A, 0, 0, 0, 0xE66E, 0xE66F, - 0x702E, 0x702C, 0x702D, 0xE670, 0x702F, 0, 0x7030, 0x4E6C, - 0x7031, 0x7032, 0xE671, 0x4049, 0x483B, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E99A_x0213[] = { - 0, 0xE660, 0xFB66, 0xE662, 0x7D5C, 0x3679, 0x4E34, 0, - 0x3728, 0xE664, 0x4262, 0x6721, 0, 0x7026, 0x332C, 0x3F6F, - 0, 0xE665, 0, 0, 0x3356, 0x7028, 0xE666, 0x7029, - 0x7027, 0x3764, 0xFB68, 0x3A5D, 0x3E63, 0x7D5E, 0, 0xE669, - 0x3123, 0, 0, 0x4E59, 0x7D5F, 0x7D60, 0xE66C, 0x702B, - 0x6E2E, 0xFB6B, 0x702A, 0, 0, 0, 0xE66E, 0xFB6C, - 0x702E, 0x702C, 0x702D, 0xFB6D, 0x702F, 0, 0x7030, 0x4E6C, - 0x7031, 0x7032, 0xFB6E, 0x4049, 0x483B, 0xFB6F, 0, 0, -}; -static const unsigned short utf8_to_euc_E99B[] = { - 0x3F7D, 0x3467, 0, 0, 0x4D3A, 0x326D, 0x3D38, 0x385B, - 0, 0x7035, 0xE672, 0x7034, 0x3B73, 0x7036, 0x7033, 0, - 0, 0x3B28, 0xE673, 0, 0, 0x703A, 0x6A2D, 0, - 0xE675, 0x5256, 0xE676, 0x3F77, 0x7038, 0xE677, 0xE678, 0xE679, - 0, 0, 0x4E25, 0x4671, 0, 0, 0, 0, - 0x312B, 0xE67A, 0x4063, 0x3C36, 0, 0, 0, 0xE67B, - 0x4A37, 0xE67C, 0x3140, 0, 0, 0, 0x4E6D, 0x4D6B, - 0, 0x703B, 0xE67D, 0x4545, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E99B_x0213[] = { - 0x3F7D, 0x3467, 0, 0, 0x4D3A, 0x326D, 0x3D38, 0x385B, - 0, 0x7035, 0xE672, 0x7034, 0x3B73, 0x7036, 0x7033, 0, - 0, 0x3B28, 0x7D61, 0, 0, 0x703A, 0x6A2D, 0, - 0xFB72, 0x5256, 0xFB73, 0x3F77, 0x7038, 0xFB74, 0x7D62, 0xE679, - 0, 0, 0x4E25, 0x4671, 0, 0, 0, 0, - 0x312B, 0x7D64, 0x4063, 0x3C36, 0, 0, 0, 0x7D65, - 0x4A37, 0xE67C, 0x3140, 0, 0, 0, 0x4E6D, 0x4D6B, - 0, 0x703B, 0xE67D, 0x4545, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E99C[] = { - 0x3C7B, 0, 0xE67E, 0xE721, 0x703C, 0xE722, 0x703D, 0x3F4C, - 0x703E, 0xE723, 0x4E6E, 0, 0, 0x7039, 0x7040, 0x7042, - 0, 0x7041, 0, 0x703F, 0, 0, 0x7043, 0, - 0, 0x7044, 0xE724, 0xE725, 0x417A, 0xE726, 0x3262, 0, - 0, 0xE727, 0xE728, 0xE729, 0x7045, 0, 0, 0x4C38, - 0xE72A, 0, 0x7046, 0, 0, 0, 0, 0, - 0x7047, 0xE72B, 0x4F2A, 0xE72C, 0, 0, 0, 0, - 0x5B31, 0x7048, 0, 0xF474, 0, 0x7049, 0x704A, 0, -}; -static const unsigned short utf8_to_euc_E99C_x0213[] = { - 0x3C7B, 0, 0xE67E, 0xE721, 0x703C, 0xE722, 0x703D, 0x3F4C, - 0x703E, 0xE723, 0x4E6E, 0, 0, 0x7039, 0x7040, 0x7042, - 0, 0x7041, 0, 0x703F, 0xFB76, 0, 0x7043, 0, - 0, 0x7044, 0xE724, 0xE725, 0x417A, 0xE726, 0x3262, 0, - 0, 0xE727, 0xE728, 0xFB77, 0x7045, 0, 0, 0x4C38, - 0xE72A, 0, 0x7046, 0, 0, 0, 0, 0, - 0x7047, 0xE72B, 0x4F2A, 0x7D66, 0, 0, 0xFB79, 0, - 0x5B31, 0x7048, 0, 0x7D67, 0, 0x7049, 0x704A, 0, -}; -static const unsigned short utf8_to_euc_E99D[] = { - 0, 0xE72D, 0x704E, 0xE72E, 0x704B, 0, 0x704C, 0, - 0x704D, 0x704F, 0xE72F, 0, 0, 0xF475, 0xE730, 0xE731, - 0, 0xF476, 0x4044, 0, 0, 0xE732, 0x4C77, 0xE733, - 0xE734, 0x4045, 0xE735, 0xE736, 0x7050, 0, 0x4873, 0, - 0x7051, 0x7353, 0x4C4C, 0xE737, 0x7052, 0, 0x7053, 0xE738, - 0x7054, 0x3357, 0xE739, 0x7056, 0, 0x3F59, 0xE73A, 0, - 0, 0x7057, 0, 0xE73B, 0x3724, 0, 0xE73C, 0xE73D, - 0xE73E, 0x7058, 0x705C, 0xE73F, 0x705A, 0xE740, 0, 0xE741, -}; -static const unsigned short utf8_to_euc_E99D_x0213[] = { - 0, 0xFB7A, 0x704E, 0, 0x704B, 0, 0x704C, 0xFB7B, - 0x704D, 0x704F, 0xE72F, 0, 0, 0x7D68, 0x7D69, 0x7D6A, - 0, 0, 0x4044, 0, 0, 0xFB7C, 0x4C77, 0xFB7D, - 0xE734, 0x4045, 0x7D6B, 0xFB7E, 0x7050, 0, 0x4873, 0, - 0x7051, 0x7353, 0x4C4C, 0xE737, 0x7052, 0, 0x7053, 0xE738, - 0x7054, 0x3357, 0xFC21, 0x7056, 0, 0x3F59, 0x7D6C, 0, - 0, 0x7057, 0, 0x7D6D, 0x3724, 0, 0xE73C, 0xE73D, - 0xE73E, 0x7058, 0x705C, 0xE73F, 0x705A, 0xE740, 0, 0xE741, -}; -static const unsigned short utf8_to_euc_E99E[] = { - 0xE742, 0x705B, 0, 0, 0x3373, 0x7059, 0x705D, 0, - 0, 0xE743, 0, 0x705E, 0, 0x3048, 0, 0x705F, - 0x7060, 0, 0, 0, 0, 0xE744, 0xE745, 0xE746, - 0x3E64, 0xE747, 0xE748, 0, 0x7061, 0, 0xE749, 0xE74A, - 0x3547, 0, 0xE74B, 0x7064, 0, 0, 0x7063, 0, - 0x7062, 0, 0, 0x6B71, 0xE74C, 0x4A5C, 0xE74D, 0, - 0, 0xE74E, 0xE74F, 0x7065, 0x7066, 0xE750, 0xE751, 0, - 0xE752, 0xE753, 0xE754, 0, 0xE755, 0, 0xE756, 0xE757, -}; -static const unsigned short utf8_to_euc_E99E_x0213[] = { - 0xE742, 0x705B, 0, 0, 0x3373, 0x7059, 0x705D, 0, - 0, 0xE743, 0, 0x705E, 0, 0x3048, 0, 0x705F, - 0x7060, 0, 0, 0, 0, 0x7D6E, 0xFC24, 0xE746, - 0x3E64, 0xE747, 0xFC25, 0, 0x7061, 0, 0xFC26, 0xE74A, - 0x3547, 0, 0xFC27, 0x7064, 0, 0, 0x7063, 0, - 0x7062, 0, 0, 0x6B71, 0xE74C, 0x4A5C, 0x7D6F, 0, - 0, 0xFC28, 0xFC29, 0x7065, 0x7066, 0xE750, 0xE751, 0, - 0xE752, 0xE753, 0x7D70, 0, 0xE755, 0, 0xFC2A, 0xE757, -}; -static const unsigned short utf8_to_euc_E99F[] = { - 0, 0xE758, 0, 0x7067, 0xE759, 0xE75A, 0x7068, 0xE75B, - 0x7069, 0xE75C, 0xE75D, 0x706A, 0xE75E, 0xE75F, 0xE760, 0, - 0xE761, 0xE762, 0, 0x345A, 0xE763, 0, 0, 0xE764, - 0xE765, 0xE766, 0, 0xE76A, 0x706B, 0xE767, 0xE768, 0, - 0xE769, 0xE76B, 0, 0, 0xE76C, 0, 0, 0, - 0, 0, 0, 0, 0, 0x706C, 0x4723, 0xE76D, - 0, 0xE76E, 0x706E, 0x323B, 0xE76F, 0x7071, 0x7070, 0xE770, - 0xE771, 0, 0xE772, 0x3124, 0, 0, 0, 0x3641, -}; -static const unsigned short utf8_to_euc_E99F_x0213[] = { - 0, 0x7D71, 0, 0x7067, 0xE759, 0xE75A, 0x7068, 0xE75B, - 0x7069, 0x7D72, 0xE75D, 0x706A, 0xFC2B, 0xE75F, 0xE760, 0, - 0xE761, 0xFC2C, 0, 0x345A, 0xFC2D, 0, 0, 0xE764, - 0xFC2E, 0xFC2F, 0, 0x7D74, 0x706B, 0xE767, 0x7D73, 0, - 0xE769, 0xFC30, 0, 0, 0xE76C, 0, 0, 0, - 0, 0, 0, 0, 0, 0x706C, 0x4723, 0xE76D, - 0, 0xFC31, 0x706E, 0x323B, 0x7D75, 0x7071, 0x7070, 0xE770, - 0xE771, 0, 0xE772, 0x3124, 0, 0, 0, 0x3641, -}; -static const unsigned short utf8_to_euc_E9A0[] = { - 0, 0x4A47, 0x443A, 0x3A22, 0, 0x3960, 0x3D67, 0xE773, - 0x3F5C, 0, 0xE774, 0, 0x7073, 0xE776, 0xE777, 0x7072, - 0x4D42, 0x3468, 0x4852, 0x465C, 0xE778, 0, 0xE779, 0x3F7C, - 0x4E4E, 0xE775, 0x375B, 0, 0xE77A, 0, 0xE77B, 0, - 0xE77C, 0x7076, 0, 0xE77D, 0x7075, 0xE828, 0xE77E, 0, - 0, 0, 0, 0xE821, 0x4B4B, 0x462C, 0xE822, 0xE823, - 0xE824, 0, 0xE825, 0xE826, 0x3150, 0xE827, 0, 0x7077, - 0x7074, 0, 0, 0x4951, 0x4D6A, 0x7078, 0xE829, 0, -}; -static const unsigned short utf8_to_euc_E9A0_x0213[] = { - 0, 0x4A47, 0x443A, 0x3A22, 0xFC32, 0x3960, 0x3D67, 0xE773, - 0x3F5C, 0, 0x7D77, 0, 0x7073, 0xFC33, 0xFC34, 0x7072, - 0x4D42, 0x3468, 0x4852, 0x465C, 0xFC35, 0, 0xFC36, 0x3F7C, - 0x4E4E, 0xE775, 0x375B, 0, 0xE77A, 0, 0x7D78, 0, - 0xE77C, 0x7076, 0, 0xFC39, 0x7075, 0xFC3C, 0xE77E, 0, - 0, 0, 0, 0x7D79, 0x4B4B, 0x462C, 0xE822, 0xE823, - 0x7D7A, 0, 0xFC3A, 0xFC3B, 0x3150, 0xE827, 0, 0x7077, - 0x7074, 0, 0, 0x4951, 0x4D6A, 0x7078, 0xE829, 0, -}; -static const unsigned short utf8_to_euc_E9A1[] = { - 0, 0, 0, 0, 0xE82A, 0, 0x7079, 0xE82B, - 0, 0, 0xE82C, 0x707B, 0x426A, 0x335B, 0x335C, 0x707A, - 0, 0xE82D, 0xE82E, 0xE82F, 0x3469, 0x3832, 0xE830, 0xE831, - 0x346A, 0xE832, 0xE833, 0x453F, 0, 0, 0x4E60, 0, - 0, 0, 0xE834, 0xE835, 0, 0xE836, 0xE837, 0x385C, - 0, 0, 0xE838, 0x707C, 0xE839, 0, 0, 0x707D, - 0x707E, 0x7121, 0, 0x7123, 0x7122, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E9A1_x0213[] = { - 0, 0, 0, 0, 0xE82A, 0, 0x7079, 0xFC3D, - 0, 0, 0xE82C, 0x707B, 0x426A, 0x335B, 0x335C, 0x707A, - 0, 0xE82D, 0x7D7C, 0x7D7D, 0x3469, 0x3832, 0x7D7E, 0x7E21, - 0x346A, 0x7E22, 0x7E23, 0x453F, 0, 0, 0x4E60, 0, - 0, 0, 0xE834, 0xE835, 0, 0x7E25, 0xFC3E, 0x385C, - 0, 0, 0xE838, 0x707C, 0x7E26, 0, 0, 0x707D, - 0x707E, 0x7121, 0, 0x7123, 0x7122, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E9A2[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x4977, 0, 0x7124, 0xE83A, 0, 0xE83B, 0xE83C, 0x7125, - 0xE83D, 0x7126, 0, 0, 0xE83E, 0, 0x7127, 0xE83F, - 0xE840, 0, 0xE841, 0xE842, 0, 0, 0, 0xE843, -}; -static const unsigned short utf8_to_euc_E9A2_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x4977, 0, 0x7124, 0xFC3F, 0, 0xFC40, 0xE83C, 0x7125, - 0xFC41, 0x7126, 0, 0, 0xE83E, 0, 0x7127, 0xFC43, - 0xFC44, 0, 0x7E27, 0xFC45, 0xFC46, 0, 0, 0xFC47, -}; -static const unsigned short utf8_to_euc_E9A3[] = { - 0, 0, 0xE844, 0x7129, 0x7128, 0xE845, 0x712A, 0, - 0xE846, 0, 0, 0, 0xE847, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x4874, 0x664C, 0, 0, 0x3F29, - 0, 0xE848, 0x3532, 0xE849, 0, 0xE84A, 0xE84B, 0xE84C, - 0, 0x712B, 0xE84D, 0x712C, 0, 0x522C, 0x5D3B, 0x4853, - 0, 0, 0x307B, 0xE84E, 0x303B, 0, 0xE84F, 0, - 0, 0, 0, 0, 0x3B74, 0x4B30, 0x3E7E, 0, -}; -static const unsigned short utf8_to_euc_E9A3_x0213[] = { - 0, 0, 0xFC48, 0x7129, 0x7128, 0xE845, 0x712A, 0xFC49, - 0x7E28, 0, 0, 0xFC4A, 0xE847, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x4874, 0x664C, 0, 0, 0x3F29, - 0xFC4B, 0xFC4D, 0x3532, 0xFC4E, 0, 0xFC4F, 0xE84B, 0x7E29, - 0, 0x712B, 0xFC50, 0x712C, 0, 0x522C, 0x5D3B, 0x4853, - 0xFC51, 0xFC52, 0x307B, 0xFC53, 0x303B, 0, 0xE84F, 0, - 0, 0, 0, 0, 0x3B74, 0x4B30, 0x3E7E, 0, -}; -static const unsigned short utf8_to_euc_E9A4[] = { - 0, 0, 0xE850, 0x712D, 0, 0x4C5F, 0, 0xE851, - 0xE852, 0x712E, 0x4D5C, 0, 0x3142, 0, 0, 0, - 0x3B41, 0xE853, 0x712F, 0x326E, 0x7130, 0xE854, 0xE855, 0xE856, - 0x7131, 0, 0xE857, 0xE858, 0xE859, 0x7133, 0x7134, 0xE85A, - 0x7136, 0x7132, 0xE85B, 0, 0x7135, 0, 0xE85C, 0xE85D, - 0x345B, 0, 0, 0xE85E, 0x7137, 0, 0x7138, 0, - 0, 0xE85F, 0xE860, 0xE861, 0xE862, 0xE863, 0, 0, - 0, 0xE864, 0xE865, 0xE866, 0xE867, 0x7139, 0x713A, 0, -}; -static const unsigned short utf8_to_euc_E9A4_x0213[] = { - 0, 0, 0xE850, 0x712D, 0, 0x4C5F, 0, 0xE851, - 0xFC54, 0x712E, 0x4D5C, 0, 0x3142, 0, 0, 0, - 0x3B41, 0xE853, 0x712F, 0x326E, 0x7130, 0xE854, 0xFC57, 0xFC58, - 0x7131, 0, 0xFC5A, 0xFC5B, 0xFC5C, 0x7133, 0x7134, 0xE85A, - 0x7136, 0x7132, 0xE85B, 0, 0x7135, 0, 0xE85C, 0, - 0x345B, 0, 0, 0xE85E, 0x7137, 0, 0x7138, 0, - 0, 0xFC5E, 0xFC5F, 0xFC60, 0xE862, 0xE863, 0, 0, - 0, 0xE864, 0xFC61, 0xFC62, 0xFC63, 0x7139, 0x713A, 0, -}; -static const unsigned short utf8_to_euc_E9A5[] = { - 0xE868, 0xE869, 0x713B, 0, 0, 0x713D, 0xE86A, 0xE86B, - 0xE86C, 0x713C, 0, 0x713F, 0x7142, 0xE86D, 0xE86E, 0, - 0x713E, 0x7140, 0x7141, 0, 0xE86F, 0x7143, 0, 0x3642, - 0xE870, 0xE871, 0, 0xE872, 0xE873, 0, 0xE874, 0xE875, - 0xE876, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E9A5_x0213[] = { - 0xFC64, 0xFC65, 0x713B, 0, 0, 0x713D, 0xFC66, 0xE86B, - 0xE86C, 0x713C, 0, 0x713F, 0x7142, 0xFC67, 0xFC68, 0, - 0x713E, 0x7140, 0x7141, 0, 0xE86F, 0x7143, 0, 0x3642, - 0x7E2A, 0xE871, 0, 0xE872, 0xFC69, 0, 0xE874, 0xFC6A, - 0xFC6B, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E9A6[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x3C73, 0x7144, - 0x7145, 0x3961, 0, 0xE877, 0, 0xE878, 0xF47A, 0xE879, - 0, 0, 0, 0, 0, 0x7146, 0xE87A, 0, - 0x333E, 0, 0, 0, 0x474F, 0x7147, 0x7148, 0, - 0xE87B, 0xE87C, 0xE87D, 0x435A, 0x466B, 0xE87E, 0, 0, - 0, 0xE921, 0xE922, 0, 0x7149, 0xE923, 0, 0xE924, -}; -static const unsigned short utf8_to_euc_E9A6_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x3C73, 0x7144, - 0x7145, 0x3961, 0, 0xE877, 0, 0xE878, 0x7E2B, 0xE879, - 0, 0, 0, 0xFC6C, 0, 0x7146, 0xFC6D, 0, - 0x333E, 0, 0, 0, 0x474F, 0x7147, 0x7148, 0, - 0xE87B, 0xE87C, 0xE87D, 0x435A, 0x466B, 0xE87E, 0, 0, - 0, 0xFC6E, 0xE922, 0, 0x7149, 0xFC6F, 0, 0xFC70, -}; -static const unsigned short utf8_to_euc_E9A7[] = { - 0, 0x477D, 0, 0xE925, 0x424C, 0x3158, 0x366E, 0, - 0x366F, 0xE926, 0, 0, 0, 0, 0, 0, - 0x4373, 0x714E, 0x3670, 0xE927, 0xE928, 0x326F, 0, 0, - 0x714D, 0xE929, 0xE92A, 0x714B, 0xE92B, 0x714C, 0xE92C, 0x714A, - 0, 0, 0x7158, 0, 0, 0, 0, 0xE92D, - 0, 0, 0xE92E, 0xE92F, 0xE930, 0x714F, 0x7150, 0, - 0xE931, 0x7151, 0x7152, 0, 0xE932, 0xE933, 0, 0, - 0x7154, 0xE934, 0, 0x7153, 0, 0xE935, 0xE936, 0x3D59, -}; -static const unsigned short utf8_to_euc_E9A7_x0213[] = { - 0, 0x477D, 0, 0xFC71, 0x424C, 0x3158, 0x366E, 0, - 0x366F, 0xFC72, 0, 0, 0, 0, 0, 0, - 0x4373, 0x714E, 0x3670, 0xE927, 0xFC73, 0x326F, 0, 0, - 0x714D, 0xFC74, 0xE92A, 0x714B, 0xE92B, 0x714C, 0xFC75, 0x714A, - 0, 0, 0x7158, 0, 0, 0, 0, 0xE92D, - 0, 0, 0xE92E, 0xE92F, 0xE930, 0x714F, 0x7150, 0, - 0xFC77, 0x7151, 0x7152, 0, 0xE932, 0xE933, 0, 0, - 0x7154, 0xFC78, 0, 0x7153, 0xFC79, 0xE935, 0xE936, 0x3D59, -}; -static const unsigned short utf8_to_euc_E9A8[] = { - 0, 0x7155, 0xE937, 0xE938, 0xE939, 0x7157, 0, 0, - 0, 0, 0, 0xE93A, 0xE93B, 0, 0x3533, 0x7156, - 0xE93C, 0xE93D, 0x417B, 0x3833, 0, 0, 0xE93E, 0, - 0, 0x7159, 0, 0, 0, 0, 0xE93F, 0, - 0xE940, 0, 0xE941, 0xE942, 0xE943, 0, 0, 0xE944, - 0x424D, 0, 0, 0x715A, 0, 0xE945, 0xE946, 0, - 0x462D, 0, 0, 0xE947, 0, 0xE948, 0xE949, 0x715B, - 0xE94A, 0, 0, 0, 0, 0, 0x7160, 0, -}; -static const unsigned short utf8_to_euc_E9A8_x0213[] = { - 0, 0x7155, 0x7E2C, 0x7E2D, 0xE939, 0x7157, 0, 0, - 0, 0, 0xFC7A, 0xE93A, 0xE93B, 0, 0x3533, 0x7156, - 0xE93C, 0xFC7B, 0x417B, 0x3833, 0, 0, 0xFC7C, 0, - 0, 0x7159, 0xFC7D, 0, 0, 0, 0xE93F, 0, - 0xFC7E, 0, 0xE941, 0xE942, 0x7E2E, 0, 0, 0xE944, - 0x424D, 0, 0, 0x715A, 0, 0x7E2F, 0x7E30, 0, - 0x462D, 0xFD21, 0, 0xE947, 0, 0xE948, 0xFD22, 0x715B, - 0x7E31, 0, 0, 0, 0, 0, 0x7160, 0, -}; -static const unsigned short utf8_to_euc_E9A9[] = { - 0x715E, 0xE94C, 0x715D, 0x715F, 0xE94D, 0x715C, 0, 0xE94B, - 0, 0, 0xE94E, 0xE94F, 0xE950, 0x7162, 0xE951, 0, - 0, 0xE952, 0, 0, 0xE953, 0x7161, 0xE954, 0x7164, - 0, 0, 0x3643, 0x7163, 0, 0xE955, 0, 0x7165, - 0, 0, 0x7166, 0, 0x7168, 0x7167, 0, 0, - 0, 0x7169, 0x716B, 0x716A, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E9A9_x0213[] = { - 0x715E, 0xE94C, 0x715D, 0x715F, 0xFD23, 0x715C, 0, 0xE94B, - 0, 0, 0x7E32, 0xE94F, 0xFD24, 0x7162, 0x7E33, 0, - 0, 0xE952, 0x7E34, 0, 0xE953, 0x7161, 0xE954, 0x7164, - 0xFD25, 0, 0x3643, 0x7163, 0, 0xE955, 0, 0x7165, - 0, 0, 0x7166, 0, 0x7168, 0x7167, 0, 0, - 0, 0x7169, 0x716B, 0x716A, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E9AA[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x397C, 0, 0xE956, 0, 0xE957, 0x716C, 0xE958, 0xE959, - 0x716D, 0, 0xE95A, 0, 0xE95B, 0xE95C, 0xE95D, 0, - 0x333C, 0xE95E, 0, 0xE95F, 0x716E, 0, 0xE960, 0xE961, -}; -static const unsigned short utf8_to_euc_E9AA_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x397C, 0, 0xE956, 0, 0xE957, 0x716C, 0xE958, 0xFD27, - 0x716D, 0, 0xE95A, 0, 0xE95B, 0xE95C, 0x7E35, 0xFD29, - 0x333C, 0xFD2B, 0, 0xE95F, 0x716E, 0, 0xE960, 0xE961, -}; -static const unsigned short utf8_to_euc_E9AB[] = { - 0x716F, 0xE962, 0, 0xE963, 0x3F71, 0, 0xE964, 0, - 0xE965, 0, 0, 0, 0, 0, 0xE966, 0x7170, - 0xE967, 0x7171, 0xE968, 0x7172, 0x7173, 0xE969, 0xE96A, 0xE96B, - 0x3962, 0xF47B, 0, 0xE96C, 0xE96D, 0, 0x7174, 0x7175, - 0xE96E, 0, 0x7176, 0x7177, 0xE96F, 0xE970, 0x7178, 0xE971, - 0, 0xE972, 0x4831, 0x717A, 0xE973, 0x4926, 0x717B, 0x7179, - 0, 0x717D, 0xE974, 0xE975, 0x717C, 0xE976, 0, 0x717E, - 0, 0xE977, 0xE978, 0x7221, 0, 0xE979, 0, 0xE97A, -}; -static const unsigned short utf8_to_euc_E9AB_x0213[] = { - 0x716F, 0x7E36, 0, 0x7E37, 0x3F71, 0, 0xFD2D, 0, - 0xE965, 0, 0, 0, 0, 0, 0x7E38, 0x7170, - 0xFD2E, 0x7171, 0xFD2F, 0x7172, 0x7173, 0xFD30, 0x7E39, 0xE96B, - 0x3962, 0, 0, 0xE96C, 0xFD32, 0, 0x7174, 0x7175, - 0xFD33, 0, 0x7176, 0x7177, 0xE96F, 0xFD34, 0x7178, 0xE971, - 0, 0xFD35, 0x4831, 0x717A, 0xE973, 0x4926, 0x717B, 0x7179, - 0, 0x717D, 0xE974, 0xE975, 0x717C, 0xE976, 0, 0x717E, - 0, 0x7E3A, 0xE978, 0x7221, 0, 0xE979, 0, 0xE97A, -}; -static const unsigned short utf8_to_euc_E9AC[] = { - 0xE97B, 0xE97C, 0xE97D, 0xE97E, 0xEA21, 0xEA22, 0x7222, 0, - 0xEA23, 0xEA24, 0, 0xEA25, 0xEA26, 0xEA27, 0xEA28, 0, - 0xEA29, 0, 0xEA2A, 0, 0, 0, 0xEA2B, 0, - 0x7223, 0xEA2C, 0x7224, 0xEA2D, 0xEA2E, 0, 0, 0x7225, - 0xEA2F, 0, 0x7226, 0x7227, 0, 0x7228, 0xEA30, 0x7229, - 0x722A, 0x722B, 0x722C, 0xEA31, 0, 0xEA32, 0x722D, 0x722E, - 0, 0x5D35, 0x722F, 0xEA33, 0xEA34, 0xEA35, 0, 0xEA36, - 0, 0xEA37, 0xEA38, 0x6478, 0x3534, 0xEA39, 0, 0, -}; -static const unsigned short utf8_to_euc_E9AC_x0213[] = { - 0xE97B, 0xE97C, 0x7E3B, 0xFD36, 0xEA21, 0xEA22, 0x7222, 0, - 0x7E3C, 0xEA24, 0, 0xEA25, 0xFD37, 0xEA27, 0xEA28, 0, - 0xFD38, 0, 0xFD39, 0, 0, 0, 0xFD3A, 0, - 0x7223, 0xEA2C, 0x7224, 0xEA2D, 0xFD3B, 0, 0, 0x7225, - 0x7E3D, 0, 0x7226, 0x7227, 0, 0x7228, 0xEA30, 0x7229, - 0x722A, 0x722B, 0x722C, 0xFD3C, 0, 0x7E3F, 0x722D, 0x722E, - 0, 0x5D35, 0x722F, 0xFD3D, 0xEA34, 0xEA35, 0, 0xEA36, - 0, 0xEA37, 0xEA38, 0x6478, 0x3534, 0xFD3E, 0, 0, -}; -static const unsigned short utf8_to_euc_E9AD[] = { - 0, 0x3321, 0x3A32, 0x7231, 0x7230, 0x4C25, 0, 0, - 0xEA3A, 0, 0, 0xEA3B, 0xEA3C, 0x7233, 0x7234, 0x7232, - 0, 0x7235, 0, 0, 0x4B62, 0xEA3D, 0xEA3E, 0xEA3F, - 0x7236, 0, 0x357B, 0xEA40, 0, 0, 0xEA41, 0, - 0, 0xEA42, 0, 0xEA43, 0, 0xEA44, 0xEA45, 0, - 0xEA46, 0, 0xEA47, 0xEA48, 0xEA49, 0xEA4A, 0xEA4B, 0x4F25, - 0, 0, 0xF47C, 0xEA4C, 0x7237, 0xEA4D, 0, 0xEA4E, - 0xEA4F, 0xEA50, 0, 0, 0, 0, 0, 0xEA51, -}; -static const unsigned short utf8_to_euc_E9AD_x0213[] = { - 0, 0x3321, 0x3A32, 0x7231, 0x7230, 0x4C25, 0, 0, - 0xEA3A, 0, 0, 0xFD40, 0xEA3C, 0x7233, 0x7234, 0x7232, - 0, 0x7235, 0, 0, 0x4B62, 0xEA3D, 0xEA3E, 0xEA3F, - 0x7236, 0, 0x357B, 0xEA40, 0, 0, 0x7E40, 0, - 0, 0xEA42, 0, 0xFD41, 0, 0xFD42, 0x7E42, 0, - 0xEA46, 0, 0xEA47, 0xFD43, 0xFD44, 0xEA4A, 0xEA4B, 0x4F25, - 0, 0, 0x7E43, 0xFD45, 0x7237, 0x7E44, 0xFD46, 0xFD47, - 0xEA4F, 0x7E41, 0, 0, 0, 0, 0, 0xEA51, -}; -static const unsigned short utf8_to_euc_E9AE[] = { - 0xEA52, 0, 0, 0x7239, 0xEA53, 0xEA54, 0xEA55, 0xEA56, - 0, 0xEA57, 0xEA58, 0xEA59, 0, 0xEA5A, 0x303E, 0xEA5B, - 0xEA5C, 0x723A, 0x4A2B, 0x7238, 0xEA5D, 0, 0x723B, 0x723C, - 0, 0, 0xEA5E, 0, 0, 0xEA5F, 0xEA60, 0x723D, - 0x723E, 0, 0, 0, 0, 0, 0xEA61, 0xEA62, - 0x723F, 0xEA63, 0x4B6E, 0x3B2D, 0xEA64, 0x3A7A, 0x412F, 0, - 0xEA65, 0xEA66, 0xEA67, 0, 0x7240, 0, 0, 0xEA68, - 0xEA69, 0x7243, 0, 0xEA6A, 0xEA6B, 0, 0xEA6C, 0xEA6D, -}; -static const unsigned short utf8_to_euc_E9AE_x0213[] = { - 0xEA52, 0, 0, 0x7239, 0x7E45, 0xEA54, 0xEA55, 0xEA56, - 0, 0xEA57, 0x7E46, 0xEA59, 0, 0xEA5A, 0x303E, 0x7E47, - 0xEA5C, 0x723A, 0x4A2B, 0x7238, 0xEA5D, 0, 0x723B, 0x723C, - 0, 0, 0xEA5E, 0, 0, 0xEA5F, 0x7E48, 0x723D, - 0x723E, 0, 0, 0, 0, 0, 0xFD48, 0x7E49, - 0x723F, 0xEA63, 0x4B6E, 0x3B2D, 0xFD49, 0x3A7A, 0x412F, 0, - 0xEA65, 0xFD4A, 0xFD4D, 0, 0x7240, 0, 0, 0xEA68, - 0xFD4E, 0x7243, 0, 0, 0xEA6B, 0, 0xFD4F, 0xEA6D, -}; -static const unsigned short utf8_to_euc_E9AF[] = { - 0x7241, 0xEA6E, 0, 0, 0, 0, 0x7244, 0xEA6F, - 0xEA70, 0x3871, 0x7242, 0, 0, 0, 0xEA71, 0x7245, - 0xEA72, 0x7246, 0x7247, 0, 0x724B, 0, 0x3B2A, 0xEA73, - 0xEA74, 0, 0, 0x4264, 0, 0xEA75, 0, 0xEA76, - 0, 0x724C, 0x7249, 0x7248, 0x724A, 0xEA77, 0, 0xEA78, - 0x375F, 0, 0xEA79, 0xEA7A, 0, 0, 0, 0xEA7B, - 0x7250, 0x724F, 0x724E, 0xEA7C, 0, 0x3033, 0, 0xEA7D, - 0xEA7E, 0xEB21, 0xEB22, 0, 0, 0xEB23, 0, 0xEB24, -}; -static const unsigned short utf8_to_euc_E9AF_x0213[] = { - 0x7241, 0x7E4A, 0, 0, 0, 0, 0x7244, 0xFD50, - 0xEA70, 0x3871, 0x7242, 0, 0, 0, 0x7E4B, 0x7245, - 0xEA72, 0x7246, 0x7247, 0, 0x724B, 0, 0x3B2A, 0xEA73, - 0xFD52, 0, 0, 0x4264, 0, 0xFD53, 0, 0xEA76, - 0, 0x724C, 0x7249, 0x7248, 0x724A, 0x7E4C, 0, 0xFD54, - 0x375F, 0, 0xFD55, 0xFD56, 0, 0, 0xFD58, 0xFD57, - 0x7250, 0x724F, 0x724E, 0xFD51, 0, 0x3033, 0, 0xFD5C, - 0x7E4D, 0xEB21, 0xFD5A, 0, 0, 0x7E4E, 0, 0xEB24, -}; -static const unsigned short utf8_to_euc_E9B0[] = { - 0xEB25, 0, 0xEB26, 0, 0x725A, 0, 0x7256, 0, - 0x7257, 0x7253, 0x7259, 0xEB27, 0x7255, 0x3362, 0, 0xEB28, - 0x4F4C, 0xEB29, 0x7258, 0x7254, 0x7252, 0x7251, 0xEB2A, 0, - 0xEB2B, 0xEB2C, 0xEB2D, 0x725C, 0xEB2E, 0, 0xEB2F, 0, - 0, 0x725F, 0xEB30, 0xEB31, 0x725E, 0x725D, 0xEB32, 0xEB33, - 0xEB34, 0xEB35, 0xEB36, 0, 0, 0x4949, 0x725B, 0x3073, - 0x7260, 0xEB37, 0x7262, 0, 0, 0xEB38, 0xEB39, 0xEB3A, - 0, 0x336F, 0x724D, 0x3137, 0, 0xEB3B, 0x7264, 0, -}; -static const unsigned short utf8_to_euc_E9B0_x0213[] = { - 0x7E4F, 0, 0xEB26, 0, 0x725A, 0, 0x7256, 0, - 0x7257, 0x7253, 0x7259, 0xEB27, 0x7255, 0x3362, 0, 0xEB28, - 0x4F4C, 0xEB29, 0x7258, 0x7254, 0x7252, 0x7251, 0xFD5E, 0, - 0xFD5F, 0xFD60, 0xFD61, 0x725C, 0xEB2E, 0xFD62, 0xEB2F, 0, - 0, 0x725F, 0xFD63, 0x7E50, 0x725E, 0x725D, 0xEB32, 0xFD64, - 0xEB34, 0xFD65, 0xFD66, 0, 0, 0x4949, 0x725B, 0x3073, - 0x7260, 0xFD68, 0x7262, 0, 0, 0xEB38, 0xFD69, 0xFD6A, - 0, 0x336F, 0x724D, 0x3137, 0, 0xEB3B, 0x7264, 0, -}; -static const unsigned short utf8_to_euc_E9B1[] = { - 0, 0xEB3C, 0, 0xEB3D, 0xEB3E, 0xEB3F, 0x7263, 0x7261, - 0x432D, 0xEB40, 0xEB41, 0, 0, 0, 0xEB42, 0xEB43, - 0xEB44, 0, 0x4B70, 0xEB45, 0xEB46, 0, 0xEB47, 0x4E5A, - 0xEB48, 0, 0x7265, 0xEB49, 0xEB50, 0xEB4A, 0xEB4B, 0xEB4C, - 0x7266, 0, 0, 0xEB4D, 0, 0, 0, 0x7267, - 0xEB52, 0xEB4E, 0xEB4F, 0xEB51, 0, 0, 0xEB53, 0, - 0xEB54, 0, 0xEB55, 0, 0, 0xEB56, 0x7268, 0xEB57, - 0x7269, 0, 0, 0xEB58, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E9B1_x0213[] = { - 0, 0x7E51, 0, 0xEB3D, 0xEB3E, 0xFD6B, 0x7263, 0x7261, - 0x432D, 0xFD6E, 0xFD6F, 0, 0, 0, 0xEB42, 0x7E52, - 0x7E53, 0, 0x4B70, 0x7E54, 0xFD71, 0, 0xEB47, 0x4E5A, - 0xFD72, 0, 0x7265, 0xFD73, 0xFD6C, 0xFD74, 0xEB4B, 0xFD75, - 0x7266, 0, 0, 0x7E55, 0, 0x7E56, 0, 0x7267, - 0xEB52, 0xFD76, 0xFD77, 0xFD78, 0, 0xFD79, 0xFD7A, 0, - 0xFD7B, 0, 0xFD7C, 0, 0, 0xFD7D, 0x7268, 0x7E57, - 0x7269, 0, 0xFD7E, 0xEB58, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E9B3[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x443B, 0xEB59, 0x726A, - 0, 0x4837, 0, 0x726F, 0x726B, 0, 0, 0, - 0x726C, 0, 0xEB5A, 0x4B31, 0x4C44, 0, 0x4650, 0xEB5B, - 0, 0xEB5C, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E9B3_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x443B, 0xFE21, 0x726A, - 0, 0x4837, 0, 0x726F, 0x726B, 0, 0, 0, - 0x726C, 0, 0xFE22, 0x4B31, 0x4C44, 0, 0x4650, 0xEB5B, - 0, 0xEB5C, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E9B4[] = { - 0, 0, 0xEB5E, 0x7270, 0, 0, 0x7271, 0x463E, - 0x726E, 0x726D, 0, 0xEB5D, 0, 0, 0x322A, 0, - 0, 0xEB5F, 0x7279, 0, 0, 0x7278, 0, 0xEB60, - 0xEB61, 0, 0, 0x3175, 0xEB62, 0xEB63, 0xEB64, 0x7276, - 0, 0, 0, 0x7275, 0, 0, 0x7273, 0, - 0x337B, 0, 0x7272, 0x3C32, 0x3229, 0, 0, 0xEB65, - 0xEB66, 0, 0xEB67, 0xEB68, 0xEB69, 0, 0, 0, - 0, 0, 0xEB6A, 0x3963, 0xEB6B, 0xEB6D, 0x727C, 0x727B, -}; -static const unsigned short utf8_to_euc_E9B4_x0213[] = { - 0, 0, 0xFE24, 0x7270, 0, 0, 0x7271, 0x463E, - 0x726E, 0x726D, 0, 0xFE23, 0, 0, 0x322A, 0, - 0, 0xFE26, 0x7279, 0, 0, 0x7278, 0, 0xFE27, - 0xFE28, 0, 0, 0x3175, 0xEB62, 0x7E58, 0x7E59, 0x7276, - 0, 0, 0, 0x7275, 0, 0, 0x7273, 0, - 0x337B, 0, 0x7272, 0x3C32, 0x3229, 0, 0, 0xEB65, - 0xEB66, 0, 0xFE2C, 0xEB68, 0xEB69, 0, 0, 0, - 0, 0, 0xEB6A, 0x3963, 0xEB6B, 0xEB6D, 0x727C, 0x727B, -}; -static const unsigned short utf8_to_euc_E9B5[] = { - 0, 0x727A, 0xEB6E, 0xEB6F, 0x7277, 0xEB6C, 0x727D, 0xEB70, - 0x727E, 0, 0xEB71, 0, 0, 0, 0, 0, - 0x7325, 0x7324, 0, 0xEB72, 0xEB73, 0, 0, 0, - 0, 0x7326, 0, 0, 0x312D, 0x7321, 0x7322, 0xEB74, - 0x3974, 0x4C39, 0xEB76, 0xEB75, 0x7323, 0xEB77, 0, 0, - 0, 0xEB78, 0xEB79, 0xEB7A, 0x4B32, 0, 0, 0x732B, - 0xEB7B, 0, 0x7327, 0, 0, 0, 0xEB7C, 0xEB7D, - 0, 0, 0x732C, 0xEB7E, 0xEC21, 0, 0xEC22, 0, -}; -static const unsigned short utf8_to_euc_E9B5_x0213[] = { - 0, 0x727A, 0xFE2E, 0x7E5A, 0x7277, 0xEB6C, 0x727D, 0x7E5B, - 0x727E, 0, 0xFE2F, 0, 0, 0, 0, 0, - 0x7325, 0x7324, 0x7E5C, 0xEB72, 0xEB73, 0, 0, 0, - 0, 0x7326, 0, 0, 0x312D, 0x7321, 0x7322, 0xFE30, - 0x3974, 0x4C39, 0xFE31, 0x7E5D, 0x7323, 0xEB77, 0, 0, - 0, 0xFE33, 0xEB79, 0xFE34, 0x4B32, 0, 0, 0x732B, - 0x7E5E, 0, 0x7327, 0xFE36, 0, 0, 0xFE37, 0xFE38, - 0, 0, 0x732C, 0xEB7E, 0x7E5F, 0, 0xFE39, 0, -}; -static const unsigned short utf8_to_euc_E9B6[] = { - 0, 0, 0, 0xEC23, 0xEC24, 0, 0xEC25, 0x7329, - 0, 0x7328, 0xEC26, 0, 0, 0xEC27, 0xEC28, 0x375C, - 0, 0, 0xEC29, 0xEC2A, 0, 0xEC2B, 0xEC2C, 0xEC2D, - 0xEC2E, 0, 0x732D, 0, 0, 0, 0, 0, - 0, 0xEC2F, 0, 0, 0x732E, 0, 0, 0, - 0, 0x732F, 0xEC30, 0x732A, 0xEC31, 0, 0xEC32, 0x7274, - 0, 0xEC33, 0x7330, 0, 0x4461, 0xEC34, 0, 0, - 0x7334, 0xEC35, 0x7335, 0x7333, 0xEC36, 0, 0, 0xEC37, -}; -static const unsigned short utf8_to_euc_E9B6_x0213[] = { - 0, 0, 0, 0xEC23, 0xFE3A, 0, 0xEC25, 0x7329, - 0, 0x7328, 0x7E60, 0, 0, 0xFE3B, 0xEC28, 0x375C, - 0, 0, 0xEC29, 0xEC2A, 0, 0xEC2B, 0x7E61, 0xEC2D, - 0xEC2E, 0xFE3C, 0x732D, 0, 0, 0, 0, 0, - 0, 0xFE3D, 0, 0, 0x732E, 0, 0, 0, - 0, 0x732F, 0xEC30, 0x732A, 0x7E63, 0, 0xEC32, 0x7274, - 0, 0xEC33, 0x7330, 0, 0x4461, 0xFE3F, 0, 0, - 0x7334, 0xFE40, 0x7335, 0x7333, 0x7E64, 0xFE41, 0, 0xFE3E, -}; -static const unsigned short utf8_to_euc_E9B7[] = { - 0, 0x7332, 0x7338, 0xEC38, 0x7331, 0, 0x7336, 0xEC39, - 0, 0xEC3A, 0xEC3B, 0, 0, 0, 0, 0x7337, - 0, 0, 0, 0x733A, 0xEC3C, 0xEC3D, 0xEC3E, 0xEC3F, - 0, 0x7339, 0xEC40, 0, 0, 0, 0xEC41, 0xEC42, - 0xEC43, 0, 0, 0, 0, 0xEC44, 0x733C, 0xEC45, - 0, 0xEC46, 0, 0xEC47, 0, 0x733D, 0xEC48, 0x733E, - 0xEC49, 0, 0x4F49, 0xEC4A, 0xEC4B, 0, 0, 0, - 0x733B, 0x426B, 0x3A6D, 0, 0, 0x733F, 0xEC4C, 0, -}; -static const unsigned short utf8_to_euc_E9B7_x0213[] = { - 0x7E62, 0x7332, 0x7338, 0xFE42, 0x7331, 0, 0x7336, 0xFE43, - 0, 0xFE44, 0xEC3B, 0, 0, 0, 0, 0x7337, - 0, 0, 0, 0x733A, 0xEC3C, 0xEC3D, 0xFE45, 0x7E65, - 0, 0x7339, 0xFE46, 0, 0, 0, 0xEC41, 0xFE47, - 0xFE48, 0, 0, 0xFE49, 0, 0xEC44, 0x733C, 0x7E67, - 0, 0xEC46, 0, 0xEC47, 0, 0x733D, 0xEC48, 0x733E, - 0xEC49, 0, 0x4F49, 0xEC4A, 0xFE4A, 0, 0, 0, - 0x733B, 0x426B, 0x3A6D, 0, 0, 0x733F, 0xEC4C, 0, -}; -static const unsigned short utf8_to_euc_E9B8[] = { - 0, 0, 0xEC4E, 0, 0, 0, 0, 0xEC4F, - 0, 0, 0xEC4D, 0, 0, 0, 0xEC50, 0, - 0xEC51, 0xEC52, 0xEC53, 0, 0, 0xEC54, 0xEC55, 0, - 0, 0xEC56, 0x7340, 0x7341, 0xEC57, 0xEC58, 0x7342, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E9B8_x0213[] = { - 0, 0, 0xFE4D, 0, 0, 0, 0, 0x7E68, - 0, 0, 0xFE4C, 0, 0, 0xFE4E, 0xEC50, 0, - 0xEC51, 0xEC52, 0xEC53, 0, 0, 0x7E69, 0xEC55, 0, - 0, 0xFE4F, 0x7340, 0x7341, 0xFE50, 0xFE51, 0x7342, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_E9B9[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x7343, 0, 0, - 0x3834, 0x7344, 0xEC59, 0xEC5A, 0xEC5B, 0x7345, 0, 0x3C2F, -}; -static const unsigned short utf8_to_euc_E9B9_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x7343, 0, 0, - 0x3834, 0x7344, 0xEC59, 0xFE52, 0x7E6A, 0x7345, 0, 0x3C2F, -}; -static const unsigned short utf8_to_euc_E9BA[] = { - 0xEC5C, 0x7346, 0xEC5D, 0xEC5E, 0xEC5F, 0xEC60, 0, 0xEC61, - 0x7347, 0, 0, 0x7348, 0x7349, 0, 0xEC62, 0xEC63, - 0, 0x734C, 0x734A, 0x4F3C, 0, 0x734B, 0xEC64, 0x4E6F, - 0xEC65, 0, 0, 0xEC66, 0, 0x734D, 0xEC67, 0x4E5B, - 0, 0, 0, 0, 0xEC68, 0x734E, 0x477E, 0, - 0xEC69, 0x734F, 0x7351, 0, 0xEC6A, 0x7352, 0xEC6B, 0xEC6C, - 0xEC6D, 0, 0, 0xEC6E, 0xEC6F, 0xEC70, 0, 0, - 0x7350, 0x396D, 0x4C4D, 0x4B63, 0x5677, 0, 0x5D60, 0x4B7B, -}; -static const unsigned short utf8_to_euc_E9BA_x0213[] = { - 0xFE54, 0x7346, 0xEC5D, 0xEC5E, 0xEC5F, 0xFE55, 0, 0xEC61, - 0x7347, 0, 0, 0x7348, 0x7349, 0, 0xEC62, 0xEC63, - 0, 0x734C, 0x734A, 0x4F3C, 0, 0x734B, 0xEC64, 0x4E6F, - 0xEC65, 0, 0, 0xFE56, 0, 0x734D, 0x7E6B, 0x4E5B, - 0, 0, 0, 0, 0x7E6C, 0x734E, 0x477E, 0, - 0xFE57, 0x734F, 0x7351, 0, 0x7E6D, 0x7352, 0xEC6B, 0x7E6E, - 0xEC6D, 0, 0, 0xEC6E, 0x7E6F, 0x7E70, 0, 0, - 0x7350, 0x396D, 0x4C4D, 0x4B63, 0x5677, 0xFE59, 0x5D60, 0x4B7B, -}; -static const unsigned short utf8_to_euc_E9BB[] = { - 0, 0, 0, 0, 0x322B, 0, 0xEC71, 0, - 0xEC72, 0, 0, 0xEC73, 0x7354, 0x3550, 0x7355, 0x7356, - 0x7357, 0xF47E, 0x3975, 0, 0x7358, 0xEC74, 0, 0, - 0x6054, 0x4C5B, 0, 0x4263, 0x7359, 0x735B, 0x735A, 0xEC75, - 0x735C, 0, 0, 0, 0xEC76, 0x735D, 0, 0xEC77, - 0x735E, 0, 0, 0, 0xEC78, 0xEC79, 0xEC7A, 0x735F, - 0xEC7B, 0xEC7C, 0xEC7D, 0, 0x7360, 0xEC7E, 0x7361, 0x7362, - 0xED21, 0x7363, 0, 0x7364, 0x7365, 0x7366, 0, 0xED22, -}; -static const unsigned short utf8_to_euc_E9BB_x0213[] = { - 0, 0, 0, 0x7E71, 0x322B, 0, 0xEC71, 0, - 0xEC72, 0, 0, 0xEC73, 0x7354, 0x3550, 0x7355, 0x7356, - 0x7357, 0x7E72, 0x3975, 0, 0x7358, 0xEC74, 0, 0, - 0x6054, 0x4C5B, 0, 0x4263, 0x7359, 0x735B, 0x735A, 0xFE5B, - 0x735C, 0, 0, 0, 0xEC76, 0x735D, 0, 0xFE5C, - 0x735E, 0, 0, 0, 0xEC78, 0xEC79, 0xFE5D, 0x735F, - 0xEC7B, 0xEC7C, 0xEC7D, 0, 0x7360, 0xEC7E, 0x7361, 0x7362, - 0xED21, 0x7363, 0, 0x7364, 0x7365, 0x7366, 0, 0xFE5E, -}; -static const unsigned short utf8_to_euc_E9BC[] = { - 0, 0, 0xED23, 0xED24, 0, 0, 0, 0x7367, - 0x7368, 0xED25, 0, 0, 0, 0, 0x4524, 0xED26, - 0xED27, 0xED28, 0xED29, 0x385D, 0xED2A, 0x736A, 0xED2B, 0xED2C, - 0, 0xED2D, 0xED2E, 0xED2F, 0, 0, 0, 0xED30, - 0x414D, 0x736B, 0xED31, 0, 0, 0, 0xED32, 0, - 0, 0, 0xED33, 0xED34, 0x736C, 0, 0, 0xED35, - 0, 0xED36, 0xED37, 0, 0xED38, 0, 0, 0xED39, - 0, 0xED3A, 0xED3B, 0x4921, 0xED3C, 0xED3D, 0x736D, 0xED3E, -}; -static const unsigned short utf8_to_euc_E9BC_x0213[] = { - 0, 0, 0xFE5F, 0xFE61, 0, 0, 0, 0x7367, - 0x7368, 0xED25, 0, 0, 0, 0, 0x4524, 0xED26, - 0x7E73, 0xED28, 0xED29, 0x385D, 0xED2A, 0x736A, 0xED2B, 0xFE62, - 0, 0xFE63, 0xED2E, 0xED2F, 0, 0, 0, 0xED30, - 0x414D, 0x736B, 0xED31, 0, 0, 0, 0xED32, 0, - 0, 0, 0xED33, 0xED34, 0x736C, 0, 0, 0xFE64, - 0, 0xED36, 0xED37, 0, 0xED38, 0, 0, 0xFE65, - 0, 0x7E74, 0xFE66, 0x4921, 0xED3C, 0xFE67, 0x736D, 0xED3E, -}; -static const unsigned short utf8_to_euc_E9BD[] = { - 0, 0xED3F, 0, 0xED40, 0xED41, 0xED42, 0xED43, 0xED44, - 0, 0, 0x736E, 0x6337, 0, 0, 0x6C5A, 0x706D, - 0, 0, 0x736F, 0xED45, 0x7370, 0xED46, 0xED47, 0xED48, - 0xED49, 0, 0xED4A, 0, 0, 0xED4B, 0xED4C, 0x7372, - 0x7373, 0x7374, 0x4E70, 0x7371, 0, 0, 0x7375, 0x7376, - 0xED4D, 0xED4E, 0x7378, 0, 0x7377, 0xED4F, 0xED50, 0xED51, - 0xED52, 0xED53, 0x737A, 0xED54, 0, 0xED55, 0x737B, 0x7379, - 0, 0, 0xED56, 0, 0, 0xED57, 0, 0, -}; -static const unsigned short utf8_to_euc_E9BD_x0213[] = { - 0, 0xFE68, 0, 0xED40, 0xED41, 0xFE69, 0xFE6A, 0xED44, - 0, 0, 0x736E, 0x6337, 0, 0, 0x6C5A, 0x706D, - 0, 0, 0x736F, 0xFE6B, 0x7370, 0xFE6C, 0xED47, 0x7E75, - 0xFE6D, 0, 0xED4A, 0, 0, 0xFE6F, 0xED4C, 0x7372, - 0x7373, 0x7374, 0x4E70, 0x7371, 0, 0, 0x7375, 0x7376, - 0xED4D, 0xFE71, 0x7378, 0, 0x7377, 0xFE73, 0xED50, 0xED51, - 0xFE74, 0xED53, 0x737A, 0xED54, 0, 0xFE75, 0x737B, 0x7379, - 0, 0, 0xED56, 0, 0, 0xED57, 0, 0, -}; -static const unsigned short utf8_to_euc_E9BE[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x4E36, 0, 0xED58, - 0xED59, 0xED5A, 0xED5B, 0, 0xED5C, 0x737C, 0xED5D, 0xED5E, - 0, 0, 0, 0, 0x737D, 0x6354, 0xED5F, 0, - 0x737E, 0xED60, 0xED61, 0xED62, 0, 0xED63, 0, 0, - 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 unsigned short utf8_to_euc_E9BE_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x4E36, 0, 0xED58, - 0x7E76, 0xED5A, 0xED5B, 0, 0x7E77, 0x737C, 0xED5D, 0x7E78, - 0, 0, 0, 0, 0x737D, 0x6354, 0xED5F, 0, - 0x737E, 0xED60, 0x7E79, 0xED62, 0, 0xED63, 0, 0, - 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 unsigned short utf8_to_euc_EFA4[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xF445, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_EFA4_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x763B, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x742E, 0x754E, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x7B4F, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_EFA5_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x7649, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_EFA7[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xF472, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_EFA7_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x7E24, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x7D5D, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_EFA8[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xF434, 0xF437, - 0xF438, 0xF43D, 0xF444, 0xF447, 0xF448, 0xF44E, 0xF44F, 0xF453, - 0xF455, 0xF456, 0xF457, 0xF458, 0xF45A, 0xF45B, 0xF45E, 0xF460, - 0xF462, 0xF463, 0xF465, 0xF469, 0xF46A, 0xF46B, 0xF46D, 0xF46F, - 0xF470, 0xF473, 0xF477, 0xF478, 0xF479, 0xF47D, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_EFA8_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x2F4B, - 0x2F57, 0x4F72, 0, 0xAE79, 0x757A, 0x775A, 0x776F, 0, - 0, 0x793C, 0x793D, 0x7941, 0, 0, 0, 0x7B3A, - 0xF738, 0xF745, 0x7C2E, 0, 0xF96E, 0, 0x7C6A, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2E38, 0x2E49, 0x2E50, 0x2E63, 0x2E68, 0x2E6E, 0x2F2C, 0x2F2F, - 0x2F36, 0x2F5A, 0x2F5E, 0x4F61, 0x4F62, 0x7450, 0x745C, 0x745E, -}; -static const unsigned short utf8_to_euc_EFA9_x0213[] = { - 0x7461, 0x7528, 0x752B, 0x7543, 0x7565, 0x7669, 0x7677, 0x7725, - 0x7755, 0xF029, 0x7825, 0x7927, 0x7933, 0x7934, 0x7937, 0x7938, - 0x7939, 0x793B, 0x793F, 0x7940, 0x794D, 0x7951, 0x7964, 0x7A2E, - 0xF450, 0x7A33, 0x7A3A, 0x7A44, 0x7A58, 0xF574, 0xF575, 0x7B27, - 0x7B6F, 0x7B79, 0x7C2F, 0x7C30, 0x7C38, 0x7C3D, 0xF969, 0x7C59, - 0x7D63, 0x7D76, 0x7D7B, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_EFB9_x0213[] = { - 0, 0, 0, 0, 0, 0x233E, 0x233D, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_EFBC[] = { - 0, 0x212A, 0xF42A, 0x2174, 0x2170, 0x2173, 0x2175, 0xF429, - 0x214A, 0x214B, 0x2176, 0x215C, 0x2124, 0x215D, 0x2125, 0x213F, - 0x2330, 0x2331, 0x2332, 0x2333, 0x2334, 0x2335, 0x2336, 0x2337, - 0x2338, 0x2339, 0x2127, 0x2128, 0x2163, 0x2161, 0x2164, 0x2129, - 0x2177, 0x2341, 0x2342, 0x2343, 0x2344, 0x2345, 0x2346, 0x2347, - 0x2348, 0x2349, 0x234A, 0x234B, 0x234C, 0x234D, 0x234E, 0x234F, - 0x2350, 0x2351, 0x2352, 0x2353, 0x2354, 0x2355, 0x2356, 0x2357, - 0x2358, 0x2359, 0x235A, 0x214E, 0x2140, 0x214F, 0x2130, 0x2132, -}; -static const unsigned short utf8_to_euc_EFBC_x0213[] = { - 0, 0x212A, 0x2230, 0x2174, 0x2170, 0x2173, 0x2175, 0x222F, - 0x214A, 0x214B, 0x2176, 0x215C, 0x2124, 0x2231, 0x2125, 0x213F, - 0x2330, 0x2331, 0x2332, 0x2333, 0x2334, 0x2335, 0x2336, 0x2337, - 0x2338, 0x2339, 0x2127, 0x2128, 0x2163, 0x2161, 0x2164, 0x2129, - 0x2177, 0x2341, 0x2342, 0x2343, 0x2344, 0x2345, 0x2346, 0x2347, - 0x2348, 0x2349, 0x234A, 0x234B, 0x234C, 0x234D, 0x234E, 0x234F, - 0x2350, 0x2351, 0x2352, 0x2353, 0x2354, 0x2355, 0x2356, 0x2357, - 0x2358, 0x2359, 0x235A, 0x214E, 0x2140, 0x214F, 0x2130, 0x2132, -}; -static const unsigned short utf8_to_euc_EFBD[] = { - 0x212E, 0x2361, 0x2362, 0x2363, 0x2364, 0x2365, 0x2366, 0x2367, - 0x2368, 0x2369, 0x236A, 0x236B, 0x236C, 0x236D, 0x236E, 0x236F, - 0x2370, 0x2371, 0x2372, 0x2373, 0x2374, 0x2375, 0x2376, 0x2377, - 0x2378, 0x2379, 0x237A, 0x2150, 0x2143, 0x2151, 0xA237, 0, - 0, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, - 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, - 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, - 0x0E38, 0x0E39, 0x0E3A, 0x0E3B, 0x0E3C, 0x0E3D, 0x0E3E, 0x0E3F, -}; -static const unsigned short utf8_to_euc_EFBD_ms[] = { - 0x212E, 0x2361, 0x2362, 0x2363, 0x2364, 0x2365, 0x2366, 0x2367, - 0x2368, 0x2369, 0x236A, 0x236B, 0x236C, 0x236D, 0x236E, 0x236F, - 0x2370, 0x2371, 0x2372, 0x2373, 0x2374, 0x2375, 0x2376, 0x2377, - 0x2378, 0x2379, 0x237A, 0x2150, 0x2143, 0x2151, 0x2141, 0, - 0, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, - 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, - 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, - 0x0E38, 0x0E39, 0x0E3A, 0x0E3B, 0x0E3C, 0x0E3D, 0x0E3E, 0x0E3F, -}; -static const unsigned short utf8_to_euc_EFBD_x0213[] = { - 0x212E, 0x2361, 0x2362, 0x2363, 0x2364, 0x2365, 0x2366, 0x2367, - 0x2368, 0x2369, 0x236A, 0x236B, 0x236C, 0x236D, 0x236E, 0x236F, - 0x2370, 0x2371, 0x2372, 0x2373, 0x2374, 0x2375, 0x2376, 0x2377, - 0x2378, 0x2379, 0x237A, 0x2150, 0x2143, 0x2151, 0x2232, 0x2256, - 0x2257, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, - 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, - 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, - 0x0E38, 0x0E39, 0x0E3A, 0x0E3B, 0x0E3C, 0x0E3D, 0x0E3E, 0x0E3F, -}; -static const unsigned short utf8_to_euc_EFBE[] = { - 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, - 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F, - 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, - 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0E5C, 0x0E5D, 0x0E5E, 0x0E5F, - 0, 0, 0, 0, 0, 0, 0, 0, - 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 unsigned short utf8_to_euc_EFBF[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2171, 0x2172, 0x224C, 0x2131, 0xA243, 0x216F, 0, 0, - 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 unsigned short utf8_to_euc_EFBF_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x2131, 0, 0x216F, 0, 0, - 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 unsigned short *const utf8_to_euc_E1_x0213[] = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - utf8_to_euc_E1B8_x0213, 0, 0, 0, - 0, utf8_to_euc_E1BD_x0213, 0, 0, -}; -static const unsigned short *const utf8_to_euc_E2[] = { - utf8_to_euc_E280, 0, 0, 0, - utf8_to_euc_E284, utf8_to_euc_E285, utf8_to_euc_E286, utf8_to_euc_E287, - utf8_to_euc_E288, utf8_to_euc_E289, utf8_to_euc_E28A, 0, - utf8_to_euc_E28C, 0, 0, 0, - 0, utf8_to_euc_E291, 0, 0, - utf8_to_euc_E294, utf8_to_euc_E295, utf8_to_euc_E296, utf8_to_euc_E297, - utf8_to_euc_E298, utf8_to_euc_E299, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 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 unsigned short *const utf8_to_euc_E2_ms[] = { - utf8_to_euc_E280_ms, 0, 0, 0, - utf8_to_euc_E284, utf8_to_euc_E285, utf8_to_euc_E286, utf8_to_euc_E287, - utf8_to_euc_E288, utf8_to_euc_E289, utf8_to_euc_E28A, 0, - utf8_to_euc_E28C, 0, 0, 0, - 0, utf8_to_euc_E291, 0, 0, - utf8_to_euc_E294, utf8_to_euc_E295, utf8_to_euc_E296, utf8_to_euc_E297, - utf8_to_euc_E298, utf8_to_euc_E299, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 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 unsigned short *const utf8_to_euc_E2_932[] = { - utf8_to_euc_E280_932, 0, 0, 0, - utf8_to_euc_E284, utf8_to_euc_E285, utf8_to_euc_E286, utf8_to_euc_E287, - utf8_to_euc_E288_932, utf8_to_euc_E289, utf8_to_euc_E28A, 0, - utf8_to_euc_E28C, 0, 0, 0, - 0, utf8_to_euc_E291, 0, 0, - utf8_to_euc_E294, utf8_to_euc_E295, utf8_to_euc_E296, utf8_to_euc_E297, - utf8_to_euc_E298, utf8_to_euc_E299, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 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 unsigned short *const utf8_to_euc_E2_mac[] = { - utf8_to_euc_E280_932, 0, 0, 0, - utf8_to_euc_E284_mac, utf8_to_euc_E285_mac, utf8_to_euc_E286, utf8_to_euc_E287, - utf8_to_euc_E288_mac, utf8_to_euc_E289, utf8_to_euc_E28A_mac, 0, - utf8_to_euc_E28C, 0, 0, 0, - 0, utf8_to_euc_E291_mac, 0, 0, - utf8_to_euc_E294, utf8_to_euc_E295, utf8_to_euc_E296, utf8_to_euc_E297, - utf8_to_euc_E298, utf8_to_euc_E299, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 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 unsigned short *const utf8_to_euc_E2_x0213[] = { - utf8_to_euc_E280_x0213, utf8_to_euc_E281_x0213, utf8_to_euc_E282_x0213, 0, - utf8_to_euc_E284_x0213, utf8_to_euc_E285_x0213, utf8_to_euc_E286_x0213, utf8_to_euc_E287_x0213, - utf8_to_euc_E288_x0213, utf8_to_euc_E289_x0213, utf8_to_euc_E28A_x0213, utf8_to_euc_E28B_x0213, - utf8_to_euc_E28C_x0213, 0, utf8_to_euc_E28E_x0213, utf8_to_euc_E28F_x0213, - utf8_to_euc_E290_x0213, utf8_to_euc_E291, 0, utf8_to_euc_E293_x0213, - utf8_to_euc_E294, utf8_to_euc_E295, utf8_to_euc_E296_x0213, utf8_to_euc_E297_x0213, - utf8_to_euc_E298_x0213, utf8_to_euc_E299_x0213, 0, 0, - utf8_to_euc_E29C_x0213, utf8_to_euc_E29D_x0213, 0, 0, - 0, 0, 0, 0, - utf8_to_euc_E2A4_x0213, 0, utf8_to_euc_E2A6_x0213, utf8_to_euc_E2A7_x0213, - 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 unsigned short *const utf8_to_euc_E3[] = { - utf8_to_euc_E380, utf8_to_euc_E381, utf8_to_euc_E382, utf8_to_euc_E383, - 0, 0, 0, 0, - utf8_to_euc_E388, 0, utf8_to_euc_E38A, 0, - utf8_to_euc_E38C, utf8_to_euc_E38D, utf8_to_euc_E38E, utf8_to_euc_E38F, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 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 unsigned short *const utf8_to_euc_E3_932[] = { - utf8_to_euc_E380_932, utf8_to_euc_E381, utf8_to_euc_E382_932, utf8_to_euc_E383, - 0, 0, 0, 0, - utf8_to_euc_E388, 0, utf8_to_euc_E38A, 0, - utf8_to_euc_E38C, utf8_to_euc_E38D, utf8_to_euc_E38E, utf8_to_euc_E38F, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 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 unsigned short *const utf8_to_euc_E3_mac[] = { - utf8_to_euc_E380_932, utf8_to_euc_E381, utf8_to_euc_E382_932, utf8_to_euc_E383, - 0, 0, 0, 0, - utf8_to_euc_E388_mac, 0, utf8_to_euc_E38A_mac, 0, - utf8_to_euc_E38C_mac, utf8_to_euc_E38D_mac, utf8_to_euc_E38E_mac, utf8_to_euc_E38F_mac, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 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 unsigned short *const utf8_to_euc_E3_x0213[] = { - utf8_to_euc_E380_x0213, utf8_to_euc_E381, utf8_to_euc_E382_x0213, utf8_to_euc_E383_x0213, - 0, 0, 0, utf8_to_euc_E387_x0213, - utf8_to_euc_E388, utf8_to_euc_E389_x0213, utf8_to_euc_E38A_x0213, utf8_to_euc_E38B_x0213, - utf8_to_euc_E38C, utf8_to_euc_E38D, utf8_to_euc_E38E, utf8_to_euc_E38F_x0213, - utf8_to_euc_E390_x0213, utf8_to_euc_E391_x0213, utf8_to_euc_E392_x0213, utf8_to_euc_E393_x0213, - utf8_to_euc_E394_x0213, utf8_to_euc_E395_x0213, utf8_to_euc_E396_x0213, utf8_to_euc_E397_x0213, - utf8_to_euc_E398_x0213, utf8_to_euc_E399_x0213, utf8_to_euc_E39A_x0213, utf8_to_euc_E39B_x0213, - 0, utf8_to_euc_E39D_x0213, utf8_to_euc_E39E_x0213, utf8_to_euc_E39F_x0213, - utf8_to_euc_E3A0_x0213, utf8_to_euc_E3A1_x0213, 0, utf8_to_euc_E3A3_x0213, - utf8_to_euc_E3A4_x0213, utf8_to_euc_E3A5_x0213, 0, 0, - 0, utf8_to_euc_E3A9_x0213, 0, utf8_to_euc_E3AB_x0213, - utf8_to_euc_E3AC_x0213, utf8_to_euc_E3AD_x0213, utf8_to_euc_E3AE_x0213, utf8_to_euc_E3AF_x0213, - utf8_to_euc_E3B0_x0213, 0, 0, utf8_to_euc_E3B3_x0213, - utf8_to_euc_E3B4_x0213, utf8_to_euc_E3B5_x0213, utf8_to_euc_E3B6_x0213, utf8_to_euc_E3B7_x0213, - utf8_to_euc_E3B8_x0213, utf8_to_euc_E3B9_x0213, utf8_to_euc_E3BA_x0213, 0, - 0, utf8_to_euc_E3BD_x0213, utf8_to_euc_E3BE_x0213, utf8_to_euc_E3BF_x0213, -}; -static const unsigned short *const utf8_to_euc_E4[] = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - utf8_to_euc_E4B8, utf8_to_euc_E4B9, utf8_to_euc_E4BA, utf8_to_euc_E4BB, - utf8_to_euc_E4BC, utf8_to_euc_E4BD, utf8_to_euc_E4BE, utf8_to_euc_E4BF, -}; -static const unsigned short *const utf8_to_euc_E4_x0213[] = { - utf8_to_euc_E480_x0213, utf8_to_euc_E481_x0213, utf8_to_euc_E482_x0213, 0, - utf8_to_euc_E484_x0213, utf8_to_euc_E485_x0213, utf8_to_euc_E486_x0213, utf8_to_euc_E487_x0213, - utf8_to_euc_E488_x0213, utf8_to_euc_E489_x0213, 0, utf8_to_euc_E48B_x0213, - utf8_to_euc_E48C_x0213, utf8_to_euc_E48D_x0213, 0, utf8_to_euc_E48F_x0213, - utf8_to_euc_E490_x0213, utf8_to_euc_E491_x0213, utf8_to_euc_E492_x0213, utf8_to_euc_E493_x0213, - utf8_to_euc_E494_x0213, utf8_to_euc_E495_x0213, utf8_to_euc_E496_x0213, utf8_to_euc_E497_x0213, - utf8_to_euc_E498_x0213, utf8_to_euc_E499_x0213, utf8_to_euc_E49A_x0213, 0, - utf8_to_euc_E49C_x0213, utf8_to_euc_E49D_x0213, 0, utf8_to_euc_E49F_x0213, - utf8_to_euc_E4A0_x0213, utf8_to_euc_E4A1_x0213, utf8_to_euc_E4A2_x0213, 0, - 0, 0, utf8_to_euc_E4A6_x0213, utf8_to_euc_E4A7_x0213, - utf8_to_euc_E4A8_x0213, 0, utf8_to_euc_E4AA_x0213, 0, - utf8_to_euc_E4AC_x0213, 0, 0, utf8_to_euc_E4AF_x0213, - utf8_to_euc_E4B0_x0213, 0, 0, utf8_to_euc_E4B3_x0213, - utf8_to_euc_E4B4_x0213, utf8_to_euc_E4B5_x0213, 0, 0, - utf8_to_euc_E4B8_x0213, utf8_to_euc_E4B9_x0213, utf8_to_euc_E4BA_x0213, utf8_to_euc_E4BB_x0213, - utf8_to_euc_E4BC_x0213, utf8_to_euc_E4BD_x0213, utf8_to_euc_E4BE_x0213, utf8_to_euc_E4BF_x0213, -}; -static const unsigned short *const utf8_to_euc_E5[] = { - utf8_to_euc_E580, utf8_to_euc_E581, utf8_to_euc_E582, utf8_to_euc_E583, - utf8_to_euc_E584, utf8_to_euc_E585, utf8_to_euc_E586, utf8_to_euc_E587, - utf8_to_euc_E588, utf8_to_euc_E589, utf8_to_euc_E58A, utf8_to_euc_E58B, - utf8_to_euc_E58C, utf8_to_euc_E58D, utf8_to_euc_E58E, utf8_to_euc_E58F, - utf8_to_euc_E590, utf8_to_euc_E591, utf8_to_euc_E592, utf8_to_euc_E593, - utf8_to_euc_E594, utf8_to_euc_E595, utf8_to_euc_E596, utf8_to_euc_E597, - utf8_to_euc_E598, utf8_to_euc_E599, utf8_to_euc_E59A, utf8_to_euc_E59B, - utf8_to_euc_E59C, utf8_to_euc_E59D, utf8_to_euc_E59E, utf8_to_euc_E59F, - utf8_to_euc_E5A0, utf8_to_euc_E5A1, utf8_to_euc_E5A2, utf8_to_euc_E5A3, - utf8_to_euc_E5A4, utf8_to_euc_E5A5, utf8_to_euc_E5A6, utf8_to_euc_E5A7, - utf8_to_euc_E5A8, utf8_to_euc_E5A9, utf8_to_euc_E5AA, utf8_to_euc_E5AB, - utf8_to_euc_E5AC, utf8_to_euc_E5AD, utf8_to_euc_E5AE, utf8_to_euc_E5AF, - utf8_to_euc_E5B0, utf8_to_euc_E5B1, utf8_to_euc_E5B2, utf8_to_euc_E5B3, - utf8_to_euc_E5B4, utf8_to_euc_E5B5, utf8_to_euc_E5B6, utf8_to_euc_E5B7, - utf8_to_euc_E5B8, utf8_to_euc_E5B9, utf8_to_euc_E5BA, utf8_to_euc_E5BB, - utf8_to_euc_E5BC, utf8_to_euc_E5BD, utf8_to_euc_E5BE, utf8_to_euc_E5BF, -}; -static const unsigned short *const utf8_to_euc_E5_x0213[] = { - utf8_to_euc_E580_x0213, utf8_to_euc_E581_x0213, utf8_to_euc_E582_x0213, utf8_to_euc_E583_x0213, - utf8_to_euc_E584_x0213, utf8_to_euc_E585_x0213, utf8_to_euc_E586_x0213, utf8_to_euc_E587_x0213, - utf8_to_euc_E588_x0213, utf8_to_euc_E589_x0213, utf8_to_euc_E58A_x0213, utf8_to_euc_E58B_x0213, - utf8_to_euc_E58C_x0213, utf8_to_euc_E58D_x0213, utf8_to_euc_E58E_x0213, utf8_to_euc_E58F_x0213, - utf8_to_euc_E590_x0213, utf8_to_euc_E591_x0213, utf8_to_euc_E592_x0213, utf8_to_euc_E593_x0213, - utf8_to_euc_E594_x0213, utf8_to_euc_E595_x0213, utf8_to_euc_E596_x0213, utf8_to_euc_E597_x0213, - utf8_to_euc_E598_x0213, utf8_to_euc_E599_x0213, utf8_to_euc_E59A_x0213, utf8_to_euc_E59B_x0213, - utf8_to_euc_E59C_x0213, utf8_to_euc_E59D_x0213, utf8_to_euc_E59E_x0213, utf8_to_euc_E59F_x0213, - utf8_to_euc_E5A0_x0213, utf8_to_euc_E5A1_x0213, utf8_to_euc_E5A2_x0213, utf8_to_euc_E5A3_x0213, - utf8_to_euc_E5A4_x0213, utf8_to_euc_E5A5_x0213, utf8_to_euc_E5A6_x0213, utf8_to_euc_E5A7_x0213, - utf8_to_euc_E5A8_x0213, utf8_to_euc_E5A9_x0213, utf8_to_euc_E5AA_x0213, utf8_to_euc_E5AB_x0213, - utf8_to_euc_E5AC_x0213, utf8_to_euc_E5AD_x0213, utf8_to_euc_E5AE_x0213, utf8_to_euc_E5AF_x0213, - utf8_to_euc_E5B0_x0213, utf8_to_euc_E5B1_x0213, utf8_to_euc_E5B2_x0213, utf8_to_euc_E5B3_x0213, - utf8_to_euc_E5B4_x0213, utf8_to_euc_E5B5_x0213, utf8_to_euc_E5B6_x0213, utf8_to_euc_E5B7_x0213, - utf8_to_euc_E5B8_x0213, utf8_to_euc_E5B9_x0213, utf8_to_euc_E5BA_x0213, utf8_to_euc_E5BB_x0213, - utf8_to_euc_E5BC_x0213, utf8_to_euc_E5BD_x0213, utf8_to_euc_E5BE_x0213, utf8_to_euc_E5BF_x0213, -}; -static const unsigned short *const utf8_to_euc_E6[] = { - utf8_to_euc_E680, utf8_to_euc_E681, utf8_to_euc_E682, utf8_to_euc_E683, - utf8_to_euc_E684, utf8_to_euc_E685, utf8_to_euc_E686, utf8_to_euc_E687, - utf8_to_euc_E688, utf8_to_euc_E689, utf8_to_euc_E68A, utf8_to_euc_E68B, - utf8_to_euc_E68C, utf8_to_euc_E68D, utf8_to_euc_E68E, utf8_to_euc_E68F, - utf8_to_euc_E690, utf8_to_euc_E691, utf8_to_euc_E692, utf8_to_euc_E693, - utf8_to_euc_E694, utf8_to_euc_E695, utf8_to_euc_E696, utf8_to_euc_E697, - utf8_to_euc_E698, utf8_to_euc_E699, utf8_to_euc_E69A, utf8_to_euc_E69B, - utf8_to_euc_E69C, utf8_to_euc_E69D, utf8_to_euc_E69E, utf8_to_euc_E69F, - utf8_to_euc_E6A0, utf8_to_euc_E6A1, utf8_to_euc_E6A2, utf8_to_euc_E6A3, - utf8_to_euc_E6A4, utf8_to_euc_E6A5, utf8_to_euc_E6A6, utf8_to_euc_E6A7, - utf8_to_euc_E6A8, utf8_to_euc_E6A9, utf8_to_euc_E6AA, utf8_to_euc_E6AB, - utf8_to_euc_E6AC, utf8_to_euc_E6AD, utf8_to_euc_E6AE, utf8_to_euc_E6AF, - utf8_to_euc_E6B0, utf8_to_euc_E6B1, utf8_to_euc_E6B2, utf8_to_euc_E6B3, - utf8_to_euc_E6B4, utf8_to_euc_E6B5, utf8_to_euc_E6B6, utf8_to_euc_E6B7, - utf8_to_euc_E6B8, utf8_to_euc_E6B9, utf8_to_euc_E6BA, utf8_to_euc_E6BB, - utf8_to_euc_E6BC, utf8_to_euc_E6BD, utf8_to_euc_E6BE, utf8_to_euc_E6BF, -}; -static const unsigned short *const utf8_to_euc_E6_x0213[] = { - utf8_to_euc_E680_x0213, utf8_to_euc_E681_x0213, utf8_to_euc_E682_x0213, utf8_to_euc_E683_x0213, - utf8_to_euc_E684_x0213, utf8_to_euc_E685_x0213, utf8_to_euc_E686_x0213, utf8_to_euc_E687_x0213, - utf8_to_euc_E688_x0213, utf8_to_euc_E689_x0213, utf8_to_euc_E68A_x0213, utf8_to_euc_E68B_x0213, - utf8_to_euc_E68C_x0213, utf8_to_euc_E68D_x0213, utf8_to_euc_E68E_x0213, utf8_to_euc_E68F_x0213, - utf8_to_euc_E690_x0213, utf8_to_euc_E691_x0213, utf8_to_euc_E692_x0213, utf8_to_euc_E693_x0213, - utf8_to_euc_E694_x0213, utf8_to_euc_E695_x0213, utf8_to_euc_E696_x0213, utf8_to_euc_E697_x0213, - utf8_to_euc_E698_x0213, utf8_to_euc_E699_x0213, utf8_to_euc_E69A_x0213, utf8_to_euc_E69B_x0213, - utf8_to_euc_E69C_x0213, utf8_to_euc_E69D_x0213, utf8_to_euc_E69E_x0213, utf8_to_euc_E69F_x0213, - utf8_to_euc_E6A0_x0213, utf8_to_euc_E6A1_x0213, utf8_to_euc_E6A2_x0213, utf8_to_euc_E6A3_x0213, - utf8_to_euc_E6A4_x0213, utf8_to_euc_E6A5_x0213, utf8_to_euc_E6A6_x0213, utf8_to_euc_E6A7_x0213, - utf8_to_euc_E6A8_x0213, utf8_to_euc_E6A9_x0213, utf8_to_euc_E6AA_x0213, utf8_to_euc_E6AB_x0213, - utf8_to_euc_E6AC_x0213, utf8_to_euc_E6AD_x0213, utf8_to_euc_E6AE_x0213, utf8_to_euc_E6AF_x0213, - utf8_to_euc_E6B0_x0213, utf8_to_euc_E6B1_x0213, utf8_to_euc_E6B2_x0213, utf8_to_euc_E6B3_x0213, - utf8_to_euc_E6B4_x0213, utf8_to_euc_E6B5_x0213, utf8_to_euc_E6B6_x0213, utf8_to_euc_E6B7_x0213, - utf8_to_euc_E6B8_x0213, utf8_to_euc_E6B9_x0213, utf8_to_euc_E6BA_x0213, utf8_to_euc_E6BB_x0213, - utf8_to_euc_E6BC_x0213, utf8_to_euc_E6BD_x0213, utf8_to_euc_E6BE_x0213, utf8_to_euc_E6BF_x0213, -}; -static const unsigned short *const utf8_to_euc_E7[] = { - utf8_to_euc_E780, utf8_to_euc_E781, utf8_to_euc_E782, utf8_to_euc_E783, - utf8_to_euc_E784, utf8_to_euc_E785, utf8_to_euc_E786, utf8_to_euc_E787, - utf8_to_euc_E788, utf8_to_euc_E789, utf8_to_euc_E78A, utf8_to_euc_E78B, - utf8_to_euc_E78C, utf8_to_euc_E78D, utf8_to_euc_E78E, utf8_to_euc_E78F, - utf8_to_euc_E790, utf8_to_euc_E791, utf8_to_euc_E792, utf8_to_euc_E793, - utf8_to_euc_E794, utf8_to_euc_E795, utf8_to_euc_E796, utf8_to_euc_E797, - utf8_to_euc_E798, utf8_to_euc_E799, utf8_to_euc_E79A, utf8_to_euc_E79B, - utf8_to_euc_E79C, utf8_to_euc_E79D, utf8_to_euc_E79E, utf8_to_euc_E79F, - utf8_to_euc_E7A0, utf8_to_euc_E7A1, utf8_to_euc_E7A2, utf8_to_euc_E7A3, - utf8_to_euc_E7A4, utf8_to_euc_E7A5, utf8_to_euc_E7A6, utf8_to_euc_E7A7, - utf8_to_euc_E7A8, utf8_to_euc_E7A9, utf8_to_euc_E7AA, utf8_to_euc_E7AB, - utf8_to_euc_E7AC, utf8_to_euc_E7AD, utf8_to_euc_E7AE, utf8_to_euc_E7AF, - utf8_to_euc_E7B0, utf8_to_euc_E7B1, utf8_to_euc_E7B2, utf8_to_euc_E7B3, - utf8_to_euc_E7B4, utf8_to_euc_E7B5, utf8_to_euc_E7B6, utf8_to_euc_E7B7, - utf8_to_euc_E7B8, utf8_to_euc_E7B9, utf8_to_euc_E7BA, 0, - utf8_to_euc_E7BC, utf8_to_euc_E7BD, utf8_to_euc_E7BE, utf8_to_euc_E7BF, -}; -static const unsigned short *const utf8_to_euc_E7_x0213[] = { - utf8_to_euc_E780_x0213, utf8_to_euc_E781_x0213, utf8_to_euc_E782_x0213, utf8_to_euc_E783_x0213, - utf8_to_euc_E784_x0213, utf8_to_euc_E785_x0213, utf8_to_euc_E786_x0213, utf8_to_euc_E787_x0213, - utf8_to_euc_E788_x0213, utf8_to_euc_E789_x0213, utf8_to_euc_E78A_x0213, utf8_to_euc_E78B_x0213, - utf8_to_euc_E78C_x0213, utf8_to_euc_E78D_x0213, utf8_to_euc_E78E_x0213, utf8_to_euc_E78F_x0213, - utf8_to_euc_E790_x0213, utf8_to_euc_E791_x0213, utf8_to_euc_E792_x0213, utf8_to_euc_E793_x0213, - utf8_to_euc_E794_x0213, utf8_to_euc_E795_x0213, utf8_to_euc_E796_x0213, utf8_to_euc_E797_x0213, - utf8_to_euc_E798_x0213, utf8_to_euc_E799_x0213, utf8_to_euc_E79A_x0213, utf8_to_euc_E79B_x0213, - utf8_to_euc_E79C_x0213, utf8_to_euc_E79D_x0213, utf8_to_euc_E79E_x0213, utf8_to_euc_E79F_x0213, - utf8_to_euc_E7A0_x0213, utf8_to_euc_E7A1_x0213, utf8_to_euc_E7A2_x0213, utf8_to_euc_E7A3_x0213, - utf8_to_euc_E7A4_x0213, utf8_to_euc_E7A5_x0213, utf8_to_euc_E7A6_x0213, utf8_to_euc_E7A7_x0213, - utf8_to_euc_E7A8_x0213, utf8_to_euc_E7A9_x0213, utf8_to_euc_E7AA_x0213, utf8_to_euc_E7AB_x0213, - utf8_to_euc_E7AC_x0213, utf8_to_euc_E7AD_x0213, utf8_to_euc_E7AE_x0213, utf8_to_euc_E7AF_x0213, - utf8_to_euc_E7B0_x0213, utf8_to_euc_E7B1_x0213, utf8_to_euc_E7B2_x0213, utf8_to_euc_E7B3_x0213, - utf8_to_euc_E7B4_x0213, utf8_to_euc_E7B5_x0213, utf8_to_euc_E7B6_x0213, utf8_to_euc_E7B7_x0213, - utf8_to_euc_E7B8_x0213, utf8_to_euc_E7B9_x0213, utf8_to_euc_E7BA_x0213, 0, - utf8_to_euc_E7BC_x0213, utf8_to_euc_E7BD_x0213, utf8_to_euc_E7BE_x0213, utf8_to_euc_E7BF_x0213, -}; -static const unsigned short *const utf8_to_euc_E8[] = { - utf8_to_euc_E880, utf8_to_euc_E881, utf8_to_euc_E882, utf8_to_euc_E883, - utf8_to_euc_E884, utf8_to_euc_E885, utf8_to_euc_E886, utf8_to_euc_E887, - utf8_to_euc_E888, utf8_to_euc_E889, utf8_to_euc_E88A, utf8_to_euc_E88B, - utf8_to_euc_E88C, utf8_to_euc_E88D, utf8_to_euc_E88E, utf8_to_euc_E88F, - utf8_to_euc_E890, utf8_to_euc_E891, utf8_to_euc_E892, utf8_to_euc_E893, - utf8_to_euc_E894, utf8_to_euc_E895, utf8_to_euc_E896, utf8_to_euc_E897, - utf8_to_euc_E898, utf8_to_euc_E899, utf8_to_euc_E89A, utf8_to_euc_E89B, - utf8_to_euc_E89C, utf8_to_euc_E89D, utf8_to_euc_E89E, utf8_to_euc_E89F, - utf8_to_euc_E8A0, utf8_to_euc_E8A1, utf8_to_euc_E8A2, utf8_to_euc_E8A3, - utf8_to_euc_E8A4, utf8_to_euc_E8A5, utf8_to_euc_E8A6, utf8_to_euc_E8A7, - utf8_to_euc_E8A8, utf8_to_euc_E8A9, utf8_to_euc_E8AA, utf8_to_euc_E8AB, - utf8_to_euc_E8AC, utf8_to_euc_E8AD, utf8_to_euc_E8AE, 0, - utf8_to_euc_E8B0, utf8_to_euc_E8B1, utf8_to_euc_E8B2, utf8_to_euc_E8B3, - utf8_to_euc_E8B4, utf8_to_euc_E8B5, utf8_to_euc_E8B6, utf8_to_euc_E8B7, - utf8_to_euc_E8B8, utf8_to_euc_E8B9, utf8_to_euc_E8BA, utf8_to_euc_E8BB, - utf8_to_euc_E8BC, utf8_to_euc_E8BD, utf8_to_euc_E8BE, utf8_to_euc_E8BF, -}; -static const unsigned short *const utf8_to_euc_E8_x0213[] = { - utf8_to_euc_E880_x0213, utf8_to_euc_E881_x0213, utf8_to_euc_E882_x0213, utf8_to_euc_E883_x0213, - utf8_to_euc_E884_x0213, utf8_to_euc_E885_x0213, utf8_to_euc_E886_x0213, utf8_to_euc_E887_x0213, - utf8_to_euc_E888_x0213, utf8_to_euc_E889_x0213, utf8_to_euc_E88A_x0213, utf8_to_euc_E88B_x0213, - utf8_to_euc_E88C_x0213, utf8_to_euc_E88D_x0213, utf8_to_euc_E88E_x0213, utf8_to_euc_E88F_x0213, - utf8_to_euc_E890_x0213, utf8_to_euc_E891_x0213, utf8_to_euc_E892_x0213, utf8_to_euc_E893_x0213, - utf8_to_euc_E894_x0213, utf8_to_euc_E895_x0213, utf8_to_euc_E896_x0213, utf8_to_euc_E897_x0213, - utf8_to_euc_E898_x0213, utf8_to_euc_E899_x0213, utf8_to_euc_E89A_x0213, utf8_to_euc_E89B_x0213, - utf8_to_euc_E89C_x0213, utf8_to_euc_E89D_x0213, utf8_to_euc_E89E_x0213, utf8_to_euc_E89F_x0213, - utf8_to_euc_E8A0_x0213, utf8_to_euc_E8A1_x0213, utf8_to_euc_E8A2_x0213, utf8_to_euc_E8A3_x0213, - utf8_to_euc_E8A4_x0213, utf8_to_euc_E8A5_x0213, utf8_to_euc_E8A6_x0213, utf8_to_euc_E8A7_x0213, - utf8_to_euc_E8A8_x0213, utf8_to_euc_E8A9_x0213, utf8_to_euc_E8AA_x0213, utf8_to_euc_E8AB_x0213, - utf8_to_euc_E8AC_x0213, utf8_to_euc_E8AD_x0213, utf8_to_euc_E8AE_x0213, 0, - utf8_to_euc_E8B0_x0213, utf8_to_euc_E8B1_x0213, utf8_to_euc_E8B2_x0213, utf8_to_euc_E8B3_x0213, - utf8_to_euc_E8B4_x0213, utf8_to_euc_E8B5_x0213, utf8_to_euc_E8B6_x0213, utf8_to_euc_E8B7_x0213, - utf8_to_euc_E8B8_x0213, utf8_to_euc_E8B9_x0213, utf8_to_euc_E8BA_x0213, utf8_to_euc_E8BB_x0213, - utf8_to_euc_E8BC_x0213, utf8_to_euc_E8BD_x0213, utf8_to_euc_E8BE_x0213, utf8_to_euc_E8BF_x0213, -}; -static const unsigned short *const utf8_to_euc_E9[] = { - utf8_to_euc_E980, utf8_to_euc_E981, utf8_to_euc_E982, utf8_to_euc_E983, - utf8_to_euc_E984, utf8_to_euc_E985, utf8_to_euc_E986, utf8_to_euc_E987, - utf8_to_euc_E988, utf8_to_euc_E989, utf8_to_euc_E98A, utf8_to_euc_E98B, - utf8_to_euc_E98C, utf8_to_euc_E98D, utf8_to_euc_E98E, utf8_to_euc_E98F, - utf8_to_euc_E990, utf8_to_euc_E991, utf8_to_euc_E992, 0, - 0, utf8_to_euc_E995, utf8_to_euc_E996, utf8_to_euc_E997, - utf8_to_euc_E998, utf8_to_euc_E999, utf8_to_euc_E99A, utf8_to_euc_E99B, - utf8_to_euc_E99C, utf8_to_euc_E99D, utf8_to_euc_E99E, utf8_to_euc_E99F, - utf8_to_euc_E9A0, utf8_to_euc_E9A1, utf8_to_euc_E9A2, utf8_to_euc_E9A3, - utf8_to_euc_E9A4, utf8_to_euc_E9A5, utf8_to_euc_E9A6, utf8_to_euc_E9A7, - utf8_to_euc_E9A8, utf8_to_euc_E9A9, utf8_to_euc_E9AA, utf8_to_euc_E9AB, - utf8_to_euc_E9AC, utf8_to_euc_E9AD, utf8_to_euc_E9AE, utf8_to_euc_E9AF, - utf8_to_euc_E9B0, utf8_to_euc_E9B1, 0, utf8_to_euc_E9B3, - utf8_to_euc_E9B4, utf8_to_euc_E9B5, utf8_to_euc_E9B6, utf8_to_euc_E9B7, - utf8_to_euc_E9B8, utf8_to_euc_E9B9, utf8_to_euc_E9BA, utf8_to_euc_E9BB, - utf8_to_euc_E9BC, utf8_to_euc_E9BD, utf8_to_euc_E9BE, 0, -}; -static const unsigned short *const utf8_to_euc_E9_x0213[] = { - utf8_to_euc_E980_x0213, utf8_to_euc_E981_x0213, utf8_to_euc_E982_x0213, utf8_to_euc_E983_x0213, - utf8_to_euc_E984_x0213, utf8_to_euc_E985_x0213, utf8_to_euc_E986_x0213, utf8_to_euc_E987_x0213, - utf8_to_euc_E988_x0213, utf8_to_euc_E989_x0213, utf8_to_euc_E98A_x0213, utf8_to_euc_E98B_x0213, - utf8_to_euc_E98C_x0213, utf8_to_euc_E98D_x0213, utf8_to_euc_E98E_x0213, utf8_to_euc_E98F_x0213, - utf8_to_euc_E990_x0213, utf8_to_euc_E991_x0213, utf8_to_euc_E992, 0, - 0, utf8_to_euc_E995_x0213, utf8_to_euc_E996_x0213, utf8_to_euc_E997_x0213, - utf8_to_euc_E998_x0213, utf8_to_euc_E999_x0213, utf8_to_euc_E99A_x0213, utf8_to_euc_E99B_x0213, - utf8_to_euc_E99C_x0213, utf8_to_euc_E99D_x0213, utf8_to_euc_E99E_x0213, utf8_to_euc_E99F_x0213, - utf8_to_euc_E9A0_x0213, utf8_to_euc_E9A1_x0213, utf8_to_euc_E9A2_x0213, utf8_to_euc_E9A3_x0213, - utf8_to_euc_E9A4_x0213, utf8_to_euc_E9A5_x0213, utf8_to_euc_E9A6_x0213, utf8_to_euc_E9A7_x0213, - utf8_to_euc_E9A8_x0213, utf8_to_euc_E9A9_x0213, utf8_to_euc_E9AA_x0213, utf8_to_euc_E9AB_x0213, - utf8_to_euc_E9AC_x0213, utf8_to_euc_E9AD_x0213, utf8_to_euc_E9AE_x0213, utf8_to_euc_E9AF_x0213, - utf8_to_euc_E9B0_x0213, utf8_to_euc_E9B1_x0213, 0, utf8_to_euc_E9B3_x0213, - utf8_to_euc_E9B4_x0213, utf8_to_euc_E9B5_x0213, utf8_to_euc_E9B6_x0213, utf8_to_euc_E9B7_x0213, - utf8_to_euc_E9B8_x0213, utf8_to_euc_E9B9_x0213, utf8_to_euc_E9BA_x0213, utf8_to_euc_E9BB_x0213, - utf8_to_euc_E9BC_x0213, utf8_to_euc_E9BD_x0213, utf8_to_euc_E9BE_x0213, 0, -}; -static const unsigned short *const utf8_to_euc_EF[] = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - utf8_to_euc_EFA4, 0, 0, utf8_to_euc_EFA7, - utf8_to_euc_EFA8, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - utf8_to_euc_EFBC, utf8_to_euc_EFBD, utf8_to_euc_EFBE, utf8_to_euc_EFBF, -}; -static const unsigned short *const utf8_to_euc_EF_ms[] = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - utf8_to_euc_EFA4, 0, 0, utf8_to_euc_EFA7, - utf8_to_euc_EFA8, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - utf8_to_euc_EFBC, utf8_to_euc_EFBD_ms, utf8_to_euc_EFBE, utf8_to_euc_EFBF, -}; -static const unsigned short *const utf8_to_euc_EF_x0213[] = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - utf8_to_euc_EFA4_x0213, utf8_to_euc_EFA5_x0213, 0, utf8_to_euc_EFA7_x0213, - utf8_to_euc_EFA8_x0213, utf8_to_euc_EFA9_x0213, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, utf8_to_euc_EFB9_x0213, 0, 0, - utf8_to_euc_EFBC_x0213, utf8_to_euc_EFBD_x0213, utf8_to_euc_EFBE, utf8_to_euc_EFBF_x0213, -}; -const unsigned short *const utf8_to_euc_2bytes[] = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, utf8_to_euc_C2, utf8_to_euc_C3, - utf8_to_euc_C4, utf8_to_euc_C5, 0, utf8_to_euc_C7, - 0, 0, 0, utf8_to_euc_CB, - 0, 0, utf8_to_euc_CE, utf8_to_euc_CF, - utf8_to_euc_D0, utf8_to_euc_D1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, -}; -const unsigned short *const utf8_to_euc_2bytes_ms[] = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, utf8_to_euc_C2_ms, utf8_to_euc_C3, - utf8_to_euc_C4, utf8_to_euc_C5, 0, utf8_to_euc_C7, - 0, 0, 0, utf8_to_euc_CB, - 0, 0, utf8_to_euc_CE, utf8_to_euc_CF, - utf8_to_euc_D0, utf8_to_euc_D1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, -}; -const unsigned short *const utf8_to_euc_2bytes_932[] = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, utf8_to_euc_C2_932, utf8_to_euc_C3_932, - utf8_to_euc_C4, utf8_to_euc_C5, 0, utf8_to_euc_C7, - 0, 0, 0, utf8_to_euc_CB, - 0, 0, utf8_to_euc_CE, utf8_to_euc_CF, - utf8_to_euc_D0, utf8_to_euc_D1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, -}; -const unsigned short *const utf8_to_euc_2bytes_mac[] = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, utf8_to_euc_C2_mac, utf8_to_euc_C3, - utf8_to_euc_C4, utf8_to_euc_C5, 0, utf8_to_euc_C7, - 0, 0, 0, utf8_to_euc_CB, - 0, 0, utf8_to_euc_CE, utf8_to_euc_CF, - utf8_to_euc_D0, utf8_to_euc_D1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, -}; -const unsigned short *const utf8_to_euc_2bytes_x0213[] = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, utf8_to_euc_C2_x0213, utf8_to_euc_C3_x0213, - utf8_to_euc_C4_x0213, utf8_to_euc_C5_x0213, utf8_to_euc_C6_x0213, utf8_to_euc_C7_x0213, - 0, utf8_to_euc_C9_x0213, utf8_to_euc_CA_x0213, utf8_to_euc_CB_x0213, - utf8_to_euc_CC_x0213, utf8_to_euc_CD_x0213, utf8_to_euc_CE, utf8_to_euc_CF_x0213, - utf8_to_euc_D0, utf8_to_euc_D1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, -}; -const unsigned short *const *const utf8_to_euc_3bytes[] = { - 0, 0, utf8_to_euc_E2, utf8_to_euc_E3, - utf8_to_euc_E4, utf8_to_euc_E5, utf8_to_euc_E6, utf8_to_euc_E7, - utf8_to_euc_E8, utf8_to_euc_E9, 0, 0, - 0, 0, 0, utf8_to_euc_EF, -}; -const unsigned short *const *const utf8_to_euc_3bytes_ms[] = { - 0, 0, utf8_to_euc_E2_ms, utf8_to_euc_E3, - utf8_to_euc_E4, utf8_to_euc_E5, utf8_to_euc_E6, utf8_to_euc_E7, - utf8_to_euc_E8, utf8_to_euc_E9, 0, 0, - 0, 0, 0, utf8_to_euc_EF_ms, -}; -const unsigned short *const *const utf8_to_euc_3bytes_932[] = { - 0, 0, utf8_to_euc_E2_932, utf8_to_euc_E3_932, - utf8_to_euc_E4, utf8_to_euc_E5, utf8_to_euc_E6, utf8_to_euc_E7, - utf8_to_euc_E8, utf8_to_euc_E9, 0, 0, - 0, 0, 0, utf8_to_euc_EF_ms, -}; -const unsigned short *const *const utf8_to_euc_3bytes_mac[] = { - 0, 0, utf8_to_euc_E2_mac, utf8_to_euc_E3_mac, - utf8_to_euc_E4, utf8_to_euc_E5, utf8_to_euc_E6, utf8_to_euc_E7, - utf8_to_euc_E8, utf8_to_euc_E9, 0, 0, - 0, 0, 0, utf8_to_euc_EF_ms, -}; -const unsigned short *const *const utf8_to_euc_3bytes_x0213[] = { - 0, utf8_to_euc_E1_x0213, utf8_to_euc_E2_x0213, utf8_to_euc_E3_x0213, - utf8_to_euc_E4_x0213, utf8_to_euc_E5_x0213, utf8_to_euc_E6_x0213, utf8_to_euc_E7_x0213, - utf8_to_euc_E8_x0213, utf8_to_euc_E9_x0213, 0, 0, - 0, 0, 0, utf8_to_euc_EF_x0213, -}; - -#ifdef UNICODE_NORMALIZATION - -/* Normalization Table by Apple */ -/* http://developer.apple.com/technotes/tn/tn1150table.html */ - -const struct normalization_pair normalization_table[] = { - {{0xcd,0xbe}, {0x3b}}, - {{0xc3,0x80}, {0x41,0xcc,0x80,0x00}}, - {{0xc3,0x81}, {0x41,0xcc,0x81}}, - {{0xc3,0x82}, {0x41,0xcc,0x82}}, - {{0xe1,0xba,0xa6}, {0x41,0xcc,0x82,0xcc,0x80}}, - {{0xe1,0xba,0xa4}, {0x41,0xcc,0x82,0xcc,0x81}}, - {{0xe1,0xba,0xaa}, {0x41,0xcc,0x82,0xcc,0x83}}, - {{0xe1,0xba,0xa8}, {0x41,0xcc,0x82,0xcc,0x89}}, - {{0xc3,0x83}, {0x41,0xcc,0x83}}, - {{0xc4,0x80}, {0x41,0xcc,0x84}}, - {{0xc4,0x82}, {0x41,0xcc,0x86}}, - {{0xe1,0xba,0xb0}, {0x41,0xcc,0x86,0xcc,0x80}}, - {{0xe1,0xba,0xae}, {0x41,0xcc,0x86,0xcc,0x81}}, - {{0xe1,0xba,0xb4}, {0x41,0xcc,0x86,0xcc,0x83}}, - {{0xe1,0xba,0xb2}, {0x41,0xcc,0x86,0xcc,0x89}}, - {{0xc7,0xa0}, {0x41,0xcc,0x87,0xcc,0x84}}, - {{0xc3,0x84}, {0x41,0xcc,0x88}}, - {{0xc7,0x9e}, {0x41,0xcc,0x88,0xcc,0x84}}, - {{0xe1,0xba,0xa2}, {0x41,0xcc,0x89}}, - {{0xc3,0x85}, {0x41,0xcc,0x8a}}, - {{0xc7,0xba}, {0x41,0xcc,0x8a,0xcc,0x81}}, - {{0xc7,0x8d}, {0x41,0xcc,0x8c}}, - {{0xc8,0x80}, {0x41,0xcc,0x8f}}, - {{0xc8,0x82}, {0x41,0xcc,0x91}}, - {{0xe1,0xba,0xa0}, {0x41,0xcc,0xa3}}, - {{0xe1,0xba,0xac}, {0x41,0xcc,0xa3,0xcc,0x82}}, - {{0xe1,0xba,0xb6}, {0x41,0xcc,0xa3,0xcc,0x86}}, - {{0xe1,0xb8,0x80}, {0x41,0xcc,0xa5}}, - {{0xc4,0x84}, {0x41,0xcc,0xa8}}, - {{0xe1,0xb8,0x82}, {0x42,0xcc,0x87}}, - {{0xe1,0xb8,0x84}, {0x42,0xcc,0xa3}}, - {{0xe1,0xb8,0x86}, {0x42,0xcc,0xb1}}, - {{0xc4,0x86}, {0x43,0xcc,0x81}}, - {{0xc4,0x88}, {0x43,0xcc,0x82}}, - {{0xc4,0x8a}, {0x43,0xcc,0x87}}, - {{0xc4,0x8c}, {0x43,0xcc,0x8c}}, - {{0xc3,0x87}, {0x43,0xcc,0xa7}}, - {{0xe1,0xb8,0x88}, {0x43,0xcc,0xa7,0xcc,0x81}}, - {{0xe1,0xb8,0x8a}, {0x44,0xcc,0x87}}, - {{0xc4,0x8e}, {0x44,0xcc,0x8c}}, - {{0xe1,0xb8,0x8c}, {0x44,0xcc,0xa3}}, - {{0xe1,0xb8,0x90}, {0x44,0xcc,0xa7}}, - {{0xe1,0xb8,0x92}, {0x44,0xcc,0xad}}, - {{0xe1,0xb8,0x8e}, {0x44,0xcc,0xb1}}, - {{0xc3,0x88}, {0x45,0xcc,0x80}}, - {{0xc3,0x89}, {0x45,0xcc,0x81}}, - {{0xc3,0x8a}, {0x45,0xcc,0x82}}, - {{0xe1,0xbb,0x80}, {0x45,0xcc,0x82,0xcc,0x80}}, - {{0xe1,0xba,0xbe}, {0x45,0xcc,0x82,0xcc,0x81}}, - {{0xe1,0xbb,0x84}, {0x45,0xcc,0x82,0xcc,0x83}}, - {{0xe1,0xbb,0x82}, {0x45,0xcc,0x82,0xcc,0x89}}, - {{0xe1,0xba,0xbc}, {0x45,0xcc,0x83}}, - {{0xc4,0x92}, {0x45,0xcc,0x84}}, - {{0xe1,0xb8,0x94}, {0x45,0xcc,0x84,0xcc,0x80}}, - {{0xe1,0xb8,0x96}, {0x45,0xcc,0x84,0xcc,0x81}}, - {{0xc4,0x94}, {0x45,0xcc,0x86}}, - {{0xc4,0x96}, {0x45,0xcc,0x87}}, - {{0xc3,0x8b}, {0x45,0xcc,0x88}}, - {{0xe1,0xba,0xba}, {0x45,0xcc,0x89}}, - {{0xc4,0x9a}, {0x45,0xcc,0x8c}}, - {{0xc8,0x84}, {0x45,0xcc,0x8f}}, - {{0xc8,0x86}, {0x45,0xcc,0x91}}, - {{0xe1,0xba,0xb8}, {0x45,0xcc,0xa3}}, - {{0xe1,0xbb,0x86}, {0x45,0xcc,0xa3,0xcc,0x82}}, - {{0xe1,0xb8,0x9c}, {0x45,0xcc,0xa7,0xcc,0x86}}, - {{0xc4,0x98}, {0x45,0xcc,0xa8}}, - {{0xe1,0xb8,0x98}, {0x45,0xcc,0xad}}, - {{0xe1,0xb8,0x9a}, {0x45,0xcc,0xb0}}, - {{0xe1,0xb8,0x9e}, {0x46,0xcc,0x87}}, - {{0xc7,0xb4}, {0x47,0xcc,0x81}}, - {{0xc4,0x9c}, {0x47,0xcc,0x82}}, - {{0xe1,0xb8,0xa0}, {0x47,0xcc,0x84}}, - {{0xc4,0x9e}, {0x47,0xcc,0x86}}, - {{0xc4,0xa0}, {0x47,0xcc,0x87}}, - {{0xc7,0xa6}, {0x47,0xcc,0x8c}}, - {{0xc4,0xa2}, {0x47,0xcc,0xa7}}, - {{0xc4,0xa4}, {0x48,0xcc,0x82}}, - {{0xe1,0xb8,0xa2}, {0x48,0xcc,0x87}}, - {{0xe1,0xb8,0xa6}, {0x48,0xcc,0x88}}, - {{0xe1,0xb8,0xa4}, {0x48,0xcc,0xa3}}, - {{0xe1,0xb8,0xa8}, {0x48,0xcc,0xa7}}, - {{0xe1,0xb8,0xaa}, {0x48,0xcc,0xae}}, - {{0xc3,0x8c}, {0x49,0xcc,0x80}}, - {{0xc3,0x8d}, {0x49,0xcc,0x81}}, - {{0xc3,0x8e}, {0x49,0xcc,0x82}}, - {{0xc4,0xa8}, {0x49,0xcc,0x83}}, - {{0xc4,0xaa}, {0x49,0xcc,0x84}}, - {{0xc4,0xac}, {0x49,0xcc,0x86}}, - {{0xc4,0xb0}, {0x49,0xcc,0x87}}, - {{0xc3,0x8f}, {0x49,0xcc,0x88}}, - {{0xe1,0xb8,0xae}, {0x49,0xcc,0x88,0xcc,0x81}}, - {{0xe1,0xbb,0x88}, {0x49,0xcc,0x89}}, - {{0xc7,0x8f}, {0x49,0xcc,0x8c}}, - {{0xc8,0x88}, {0x49,0xcc,0x8f}}, - {{0xc8,0x8a}, {0x49,0xcc,0x91}}, - {{0xe1,0xbb,0x8a}, {0x49,0xcc,0xa3}}, - {{0xc4,0xae}, {0x49,0xcc,0xa8}}, - {{0xe1,0xb8,0xac}, {0x49,0xcc,0xb0}}, - {{0xc4,0xb4}, {0x4a,0xcc,0x82}}, - {{0xe1,0xb8,0xb0}, {0x4b,0xcc,0x81}}, - {{0xc7,0xa8}, {0x4b,0xcc,0x8c}}, - {{0xe1,0xb8,0xb2}, {0x4b,0xcc,0xa3}}, - {{0xc4,0xb6}, {0x4b,0xcc,0xa7}}, - {{0xe1,0xb8,0xb4}, {0x4b,0xcc,0xb1}}, - {{0xc4,0xb9}, {0x4c,0xcc,0x81}}, - {{0xc4,0xbd}, {0x4c,0xcc,0x8c}}, - {{0xe1,0xb8,0xb6}, {0x4c,0xcc,0xa3}}, - {{0xe1,0xb8,0xb8}, {0x4c,0xcc,0xa3,0xcc,0x84}}, - {{0xc4,0xbb}, {0x4c,0xcc,0xa7}}, - {{0xe1,0xb8,0xbc}, {0x4c,0xcc,0xad}}, - {{0xe1,0xb8,0xba}, {0x4c,0xcc,0xb1}}, - {{0xe1,0xb8,0xbe}, {0x4d,0xcc,0x81}}, - {{0xe1,0xb9,0x80}, {0x4d,0xcc,0x87}}, - {{0xe1,0xb9,0x82}, {0x4d,0xcc,0xa3}}, - {{0xc5,0x83}, {0x4e,0xcc,0x81}}, - {{0xc3,0x91}, {0x4e,0xcc,0x83}}, - {{0xe1,0xb9,0x84}, {0x4e,0xcc,0x87}}, - {{0xc5,0x87}, {0x4e,0xcc,0x8c}}, - {{0xe1,0xb9,0x86}, {0x4e,0xcc,0xa3}}, - {{0xc5,0x85}, {0x4e,0xcc,0xa7}}, - {{0xe1,0xb9,0x8a}, {0x4e,0xcc,0xad}}, - {{0xe1,0xb9,0x88}, {0x4e,0xcc,0xb1}}, - {{0xc3,0x92}, {0x4f,0xcc,0x80}}, - {{0xc3,0x93}, {0x4f,0xcc,0x81}}, - {{0xc3,0x94}, {0x4f,0xcc,0x82}}, - {{0xe1,0xbb,0x92}, {0x4f,0xcc,0x82,0xcc,0x80}}, - {{0xe1,0xbb,0x90}, {0x4f,0xcc,0x82,0xcc,0x81}}, - {{0xe1,0xbb,0x96}, {0x4f,0xcc,0x82,0xcc,0x83}}, - {{0xe1,0xbb,0x94}, {0x4f,0xcc,0x82,0xcc,0x89}}, - {{0xc3,0x95}, {0x4f,0xcc,0x83}}, - {{0xe1,0xb9,0x8c}, {0x4f,0xcc,0x83,0xcc,0x81}}, - {{0xe1,0xb9,0x8e}, {0x4f,0xcc,0x83,0xcc,0x88}}, - {{0xc5,0x8c}, {0x4f,0xcc,0x84}}, - {{0xe1,0xb9,0x90}, {0x4f,0xcc,0x84,0xcc,0x80}}, - {{0xe1,0xb9,0x92}, {0x4f,0xcc,0x84,0xcc,0x81}}, - {{0xc5,0x8e}, {0x4f,0xcc,0x86}}, - {{0xc3,0x96}, {0x4f,0xcc,0x88}}, - {{0xe1,0xbb,0x8e}, {0x4f,0xcc,0x89}}, - {{0xc5,0x90}, {0x4f,0xcc,0x8b}}, - {{0xc7,0x91}, {0x4f,0xcc,0x8c}}, - {{0xc8,0x8c}, {0x4f,0xcc,0x8f}}, - {{0xc8,0x8e}, {0x4f,0xcc,0x91}}, - {{0xc6,0xa0}, {0x4f,0xcc,0x9b}}, - {{0xe1,0xbb,0x9c}, {0x4f,0xcc,0x9b,0xcc,0x80}}, - {{0xe1,0xbb,0x9a}, {0x4f,0xcc,0x9b,0xcc,0x81}}, - {{0xe1,0xbb,0xa0}, {0x4f,0xcc,0x9b,0xcc,0x83}}, - {{0xe1,0xbb,0x9e}, {0x4f,0xcc,0x9b,0xcc,0x89}}, - {{0xe1,0xbb,0xa2}, {0x4f,0xcc,0x9b,0xcc,0xa3}}, - {{0xe1,0xbb,0x8c}, {0x4f,0xcc,0xa3}}, - {{0xe1,0xbb,0x98}, {0x4f,0xcc,0xa3,0xcc,0x82}}, - {{0xc7,0xaa}, {0x4f,0xcc,0xa8}}, - {{0xc7,0xac}, {0x4f,0xcc,0xa8,0xcc,0x84}}, - {{0xe1,0xb9,0x94}, {0x50,0xcc,0x81}}, - {{0xe1,0xb9,0x96}, {0x50,0xcc,0x87}}, - {{0xc5,0x94}, {0x52,0xcc,0x81}}, - {{0xe1,0xb9,0x98}, {0x52,0xcc,0x87}}, - {{0xc5,0x98}, {0x52,0xcc,0x8c}}, - {{0xc8,0x90}, {0x52,0xcc,0x8f}}, - {{0xc8,0x92}, {0x52,0xcc,0x91}}, - {{0xe1,0xb9,0x9a}, {0x52,0xcc,0xa3}}, - {{0xe1,0xb9,0x9c}, {0x52,0xcc,0xa3,0xcc,0x84}}, - {{0xc5,0x96}, {0x52,0xcc,0xa7}}, - {{0xe1,0xb9,0x9e}, {0x52,0xcc,0xb1}}, - {{0xc5,0x9a}, {0x53,0xcc,0x81}}, - {{0xe1,0xb9,0xa4}, {0x53,0xcc,0x81,0xcc,0x87}}, - {{0xc5,0x9c}, {0x53,0xcc,0x82}}, - {{0xe1,0xb9,0xa0}, {0x53,0xcc,0x87}}, - {{0xc5,0xa0}, {0x53,0xcc,0x8c}}, - {{0xe1,0xb9,0xa6}, {0x53,0xcc,0x8c,0xcc,0x87}}, - {{0xe1,0xb9,0xa2}, {0x53,0xcc,0xa3}}, - {{0xe1,0xb9,0xa8}, {0x53,0xcc,0xa3,0xcc,0x87}}, - {{0xc5,0x9e}, {0x53,0xcc,0xa7}}, - {{0xe1,0xb9,0xaa}, {0x54,0xcc,0x87}}, - {{0xc5,0xa4}, {0x54,0xcc,0x8c}}, - {{0xe1,0xb9,0xac}, {0x54,0xcc,0xa3}}, - {{0xc5,0xa2}, {0x54,0xcc,0xa7}}, - {{0xe1,0xb9,0xb0}, {0x54,0xcc,0xad}}, - {{0xe1,0xb9,0xae}, {0x54,0xcc,0xb1}}, - {{0xc3,0x99}, {0x55,0xcc,0x80}}, - {{0xc3,0x9a}, {0x55,0xcc,0x81}}, - {{0xc3,0x9b}, {0x55,0xcc,0x82}}, - {{0xc5,0xa8}, {0x55,0xcc,0x83}}, - {{0xe1,0xb9,0xb8}, {0x55,0xcc,0x83,0xcc,0x81}}, - {{0xc5,0xaa}, {0x55,0xcc,0x84}}, - {{0xe1,0xb9,0xba}, {0x55,0xcc,0x84,0xcc,0x88}}, - {{0xc5,0xac}, {0x55,0xcc,0x86}}, - {{0xc3,0x9c}, {0x55,0xcc,0x88}}, - {{0xc7,0x9b}, {0x55,0xcc,0x88,0xcc,0x80}}, - {{0xc7,0x97}, {0x55,0xcc,0x88,0xcc,0x81}}, - {{0xc7,0x95}, {0x55,0xcc,0x88,0xcc,0x84}}, - {{0xc7,0x99}, {0x55,0xcc,0x88,0xcc,0x8c}}, - {{0xe1,0xbb,0xa6}, {0x55,0xcc,0x89}}, - {{0xc5,0xae}, {0x55,0xcc,0x8a}}, - {{0xc5,0xb0}, {0x55,0xcc,0x8b}}, - {{0xc7,0x93}, {0x55,0xcc,0x8c}}, - {{0xc8,0x94}, {0x55,0xcc,0x8f}}, - {{0xc8,0x96}, {0x55,0xcc,0x91}}, - {{0xc6,0xaf}, {0x55,0xcc,0x9b}}, - {{0xe1,0xbb,0xaa}, {0x55,0xcc,0x9b,0xcc,0x80}}, - {{0xe1,0xbb,0xa8}, {0x55,0xcc,0x9b,0xcc,0x81}}, - {{0xe1,0xbb,0xae}, {0x55,0xcc,0x9b,0xcc,0x83}}, - {{0xe1,0xbb,0xac}, {0x55,0xcc,0x9b,0xcc,0x89}}, - {{0xe1,0xbb,0xb0}, {0x55,0xcc,0x9b,0xcc,0xa3}}, - {{0xe1,0xbb,0xa4}, {0x55,0xcc,0xa3}}, - {{0xe1,0xb9,0xb2}, {0x55,0xcc,0xa4}}, - {{0xc5,0xb2}, {0x55,0xcc,0xa8}}, - {{0xe1,0xb9,0xb6}, {0x55,0xcc,0xad}}, - {{0xe1,0xb9,0xb4}, {0x55,0xcc,0xb0}}, - {{0xe1,0xb9,0xbc}, {0x56,0xcc,0x83}}, - {{0xe1,0xb9,0xbe}, {0x56,0xcc,0xa3}}, - {{0xe1,0xba,0x80}, {0x57,0xcc,0x80}}, - {{0xe1,0xba,0x82}, {0x57,0xcc,0x81}}, - {{0xc5,0xb4}, {0x57,0xcc,0x82}}, - {{0xe1,0xba,0x86}, {0x57,0xcc,0x87}}, - {{0xe1,0xba,0x84}, {0x57,0xcc,0x88}}, - {{0xe1,0xba,0x88}, {0x57,0xcc,0xa3}}, - {{0xe1,0xba,0x8a}, {0x58,0xcc,0x87}}, - {{0xe1,0xba,0x8c}, {0x58,0xcc,0x88}}, - {{0xe1,0xbb,0xb2}, {0x59,0xcc,0x80}}, - {{0xc3,0x9d}, {0x59,0xcc,0x81}}, - {{0xc5,0xb6}, {0x59,0xcc,0x82}}, - {{0xe1,0xbb,0xb8}, {0x59,0xcc,0x83}}, - {{0xe1,0xba,0x8e}, {0x59,0xcc,0x87}}, - {{0xc5,0xb8}, {0x59,0xcc,0x88}}, - {{0xe1,0xbb,0xb6}, {0x59,0xcc,0x89}}, - {{0xe1,0xbb,0xb4}, {0x59,0xcc,0xa3}}, - {{0xc5,0xb9}, {0x5a,0xcc,0x81}}, - {{0xe1,0xba,0x90}, {0x5a,0xcc,0x82}}, - {{0xc5,0xbb}, {0x5a,0xcc,0x87}}, - {{0xc5,0xbd}, {0x5a,0xcc,0x8c}}, - {{0xe1,0xba,0x92}, {0x5a,0xcc,0xa3}}, - {{0xe1,0xba,0x94}, {0x5a,0xcc,0xb1}}, - {{0xe1,0xbf,0xaf}, {0x60}}, - {{0xc3,0xa0}, {0x61,0xcc,0x80}}, - {{0xc3,0xa1}, {0x61,0xcc,0x81}}, - {{0xc3,0xa2}, {0x61,0xcc,0x82}}, - {{0xe1,0xba,0xa7}, {0x61,0xcc,0x82,0xcc,0x80}}, - {{0xe1,0xba,0xa5}, {0x61,0xcc,0x82,0xcc,0x81}}, - {{0xe1,0xba,0xab}, {0x61,0xcc,0x82,0xcc,0x83}}, - {{0xe1,0xba,0xa9}, {0x61,0xcc,0x82,0xcc,0x89}}, - {{0xc3,0xa3}, {0x61,0xcc,0x83}}, - {{0xc4,0x81}, {0x61,0xcc,0x84}}, - {{0xc4,0x83}, {0x61,0xcc,0x86}}, - {{0xe1,0xba,0xb1}, {0x61,0xcc,0x86,0xcc,0x80}}, - {{0xe1,0xba,0xaf}, {0x61,0xcc,0x86,0xcc,0x81}}, - {{0xe1,0xba,0xb5}, {0x61,0xcc,0x86,0xcc,0x83}}, - {{0xe1,0xba,0xb3}, {0x61,0xcc,0x86,0xcc,0x89}}, - {{0xc7,0xa1}, {0x61,0xcc,0x87,0xcc,0x84}}, - {{0xc3,0xa4}, {0x61,0xcc,0x88}}, - {{0xc7,0x9f}, {0x61,0xcc,0x88,0xcc,0x84}}, - {{0xe1,0xba,0xa3}, {0x61,0xcc,0x89}}, - {{0xc3,0xa5}, {0x61,0xcc,0x8a}}, - {{0xc7,0xbb}, {0x61,0xcc,0x8a,0xcc,0x81}}, - {{0xc7,0x8e}, {0x61,0xcc,0x8c}}, - {{0xc8,0x81}, {0x61,0xcc,0x8f}}, - {{0xc8,0x83}, {0x61,0xcc,0x91}}, - {{0xe1,0xba,0xa1}, {0x61,0xcc,0xa3}}, - {{0xe1,0xba,0xad}, {0x61,0xcc,0xa3,0xcc,0x82}}, - {{0xe1,0xba,0xb7}, {0x61,0xcc,0xa3,0xcc,0x86}}, - {{0xe1,0xb8,0x81}, {0x61,0xcc,0xa5}}, - {{0xc4,0x85}, {0x61,0xcc,0xa8}}, - {{0xe1,0xb8,0x83}, {0x62,0xcc,0x87}}, - {{0xe1,0xb8,0x85}, {0x62,0xcc,0xa3}}, - {{0xe1,0xb8,0x87}, {0x62,0xcc,0xb1}}, - {{0xc4,0x87}, {0x63,0xcc,0x81}}, - {{0xc4,0x89}, {0x63,0xcc,0x82}}, - {{0xc4,0x8b}, {0x63,0xcc,0x87}}, - {{0xc4,0x8d}, {0x63,0xcc,0x8c}}, - {{0xc3,0xa7}, {0x63,0xcc,0xa7}}, - {{0xe1,0xb8,0x89}, {0x63,0xcc,0xa7,0xcc,0x81}}, - {{0xe1,0xb8,0x8b}, {0x64,0xcc,0x87}}, - {{0xc4,0x8f}, {0x64,0xcc,0x8c}}, - {{0xe1,0xb8,0x8d}, {0x64,0xcc,0xa3}}, - {{0xe1,0xb8,0x91}, {0x64,0xcc,0xa7}}, - {{0xe1,0xb8,0x93}, {0x64,0xcc,0xad}}, - {{0xe1,0xb8,0x8f}, {0x64,0xcc,0xb1}}, - {{0xc3,0xa8}, {0x65,0xcc,0x80}}, - {{0xc3,0xa9}, {0x65,0xcc,0x81}}, - {{0xc3,0xaa}, {0x65,0xcc,0x82}}, - {{0xe1,0xbb,0x81}, {0x65,0xcc,0x82,0xcc,0x80}}, - {{0xe1,0xba,0xbf}, {0x65,0xcc,0x82,0xcc,0x81}}, - {{0xe1,0xbb,0x85}, {0x65,0xcc,0x82,0xcc,0x83}}, - {{0xe1,0xbb,0x83}, {0x65,0xcc,0x82,0xcc,0x89}}, - {{0xe1,0xba,0xbd}, {0x65,0xcc,0x83}}, - {{0xc4,0x93}, {0x65,0xcc,0x84}}, - {{0xe1,0xb8,0x95}, {0x65,0xcc,0x84,0xcc,0x80}}, - {{0xe1,0xb8,0x97}, {0x65,0xcc,0x84,0xcc,0x81}}, - {{0xc4,0x95}, {0x65,0xcc,0x86}}, - {{0xc4,0x97}, {0x65,0xcc,0x87}}, - {{0xc3,0xab}, {0x65,0xcc,0x88}}, - {{0xe1,0xba,0xbb}, {0x65,0xcc,0x89}}, - {{0xc4,0x9b}, {0x65,0xcc,0x8c}}, - {{0xc8,0x85}, {0x65,0xcc,0x8f}}, - {{0xc8,0x87}, {0x65,0xcc,0x91}}, - {{0xe1,0xba,0xb9}, {0x65,0xcc,0xa3}}, - {{0xe1,0xbb,0x87}, {0x65,0xcc,0xa3,0xcc,0x82}}, - {{0xe1,0xb8,0x9d}, {0x65,0xcc,0xa7,0xcc,0x86}}, - {{0xc4,0x99}, {0x65,0xcc,0xa8}}, - {{0xe1,0xb8,0x99}, {0x65,0xcc,0xad}}, - {{0xe1,0xb8,0x9b}, {0x65,0xcc,0xb0}}, - {{0xe1,0xb8,0x9f}, {0x66,0xcc,0x87}}, - {{0xc7,0xb5}, {0x67,0xcc,0x81}}, - {{0xc4,0x9d}, {0x67,0xcc,0x82}}, - {{0xe1,0xb8,0xa1}, {0x67,0xcc,0x84}}, - {{0xc4,0x9f}, {0x67,0xcc,0x86}}, - {{0xc4,0xa1}, {0x67,0xcc,0x87}}, - {{0xc7,0xa7}, {0x67,0xcc,0x8c}}, - {{0xc4,0xa3}, {0x67,0xcc,0xa7}}, - {{0xc4,0xa5}, {0x68,0xcc,0x82}}, - {{0xe1,0xb8,0xa3}, {0x68,0xcc,0x87}}, - {{0xe1,0xb8,0xa7}, {0x68,0xcc,0x88}}, - {{0xe1,0xb8,0xa5}, {0x68,0xcc,0xa3}}, - {{0xe1,0xb8,0xa9}, {0x68,0xcc,0xa7}}, - {{0xe1,0xb8,0xab}, {0x68,0xcc,0xae}}, - {{0xe1,0xba,0x96}, {0x68,0xcc,0xb1}}, - {{0xc3,0xac}, {0x69,0xcc,0x80}}, - {{0xc3,0xad}, {0x69,0xcc,0x81}}, - {{0xc3,0xae}, {0x69,0xcc,0x82}}, - {{0xc4,0xa9}, {0x69,0xcc,0x83}}, - {{0xc4,0xab}, {0x69,0xcc,0x84}}, - {{0xc4,0xad}, {0x69,0xcc,0x86}}, - {{0xc3,0xaf}, {0x69,0xcc,0x88}}, - {{0xe1,0xb8,0xaf}, {0x69,0xcc,0x88,0xcc,0x81}}, - {{0xe1,0xbb,0x89}, {0x69,0xcc,0x89}}, - {{0xc7,0x90}, {0x69,0xcc,0x8c}}, - {{0xc8,0x89}, {0x69,0xcc,0x8f}}, - {{0xc8,0x8b}, {0x69,0xcc,0x91}}, - {{0xe1,0xbb,0x8b}, {0x69,0xcc,0xa3}}, - {{0xc4,0xaf}, {0x69,0xcc,0xa8}}, - {{0xe1,0xb8,0xad}, {0x69,0xcc,0xb0}}, - {{0xc4,0xb5}, {0x6a,0xcc,0x82}}, - {{0xc7,0xb0}, {0x6a,0xcc,0x8c}}, - {{0xe1,0xb8,0xb1}, {0x6b,0xcc,0x81}}, - {{0xc7,0xa9}, {0x6b,0xcc,0x8c}}, - {{0xe1,0xb8,0xb3}, {0x6b,0xcc,0xa3}}, - {{0xc4,0xb7}, {0x6b,0xcc,0xa7}}, - {{0xe1,0xb8,0xb5}, {0x6b,0xcc,0xb1}}, - {{0xc4,0xba}, {0x6c,0xcc,0x81}}, - {{0xc4,0xbe}, {0x6c,0xcc,0x8c}}, - {{0xe1,0xb8,0xb7}, {0x6c,0xcc,0xa3}}, - {{0xe1,0xb8,0xb9}, {0x6c,0xcc,0xa3,0xcc,0x84}}, - {{0xc4,0xbc}, {0x6c,0xcc,0xa7}}, - {{0xe1,0xb8,0xbd}, {0x6c,0xcc,0xad}}, - {{0xe1,0xb8,0xbb}, {0x6c,0xcc,0xb1}}, - {{0xe1,0xb8,0xbf}, {0x6d,0xcc,0x81}}, - {{0xe1,0xb9,0x81}, {0x6d,0xcc,0x87}}, - {{0xe1,0xb9,0x83}, {0x6d,0xcc,0xa3}}, - {{0xc5,0x84}, {0x6e,0xcc,0x81}}, - {{0xc3,0xb1}, {0x6e,0xcc,0x83}}, - {{0xe1,0xb9,0x85}, {0x6e,0xcc,0x87}}, - {{0xc5,0x88}, {0x6e,0xcc,0x8c}}, - {{0xe1,0xb9,0x87}, {0x6e,0xcc,0xa3}}, - {{0xc5,0x86}, {0x6e,0xcc,0xa7}}, - {{0xe1,0xb9,0x8b}, {0x6e,0xcc,0xad}}, - {{0xe1,0xb9,0x89}, {0x6e,0xcc,0xb1}}, - {{0xc3,0xb2}, {0x6f,0xcc,0x80}}, - {{0xc3,0xb3}, {0x6f,0xcc,0x81}}, - {{0xc3,0xb4}, {0x6f,0xcc,0x82}}, - {{0xe1,0xbb,0x93}, {0x6f,0xcc,0x82,0xcc,0x80}}, - {{0xe1,0xbb,0x91}, {0x6f,0xcc,0x82,0xcc,0x81}}, - {{0xe1,0xbb,0x97}, {0x6f,0xcc,0x82,0xcc,0x83}}, - {{0xe1,0xbb,0x95}, {0x6f,0xcc,0x82,0xcc,0x89}}, - {{0xc3,0xb5}, {0x6f,0xcc,0x83}}, - {{0xe1,0xb9,0x8d}, {0x6f,0xcc,0x83,0xcc,0x81}}, - {{0xe1,0xb9,0x8f}, {0x6f,0xcc,0x83,0xcc,0x88}}, - {{0xc5,0x8d}, {0x6f,0xcc,0x84}}, - {{0xe1,0xb9,0x91}, {0x6f,0xcc,0x84,0xcc,0x80}}, - {{0xe1,0xb9,0x93}, {0x6f,0xcc,0x84,0xcc,0x81}}, - {{0xc5,0x8f}, {0x6f,0xcc,0x86}}, - {{0xc3,0xb6}, {0x6f,0xcc,0x88}}, - {{0xe1,0xbb,0x8f}, {0x6f,0xcc,0x89}}, - {{0xc5,0x91}, {0x6f,0xcc,0x8b}}, - {{0xc7,0x92}, {0x6f,0xcc,0x8c}}, - {{0xc8,0x8d}, {0x6f,0xcc,0x8f}}, - {{0xc8,0x8f}, {0x6f,0xcc,0x91}}, - {{0xc6,0xa1}, {0x6f,0xcc,0x9b}}, - {{0xe1,0xbb,0x9d}, {0x6f,0xcc,0x9b,0xcc,0x80}}, - {{0xe1,0xbb,0x9b}, {0x6f,0xcc,0x9b,0xcc,0x81}}, - {{0xe1,0xbb,0xa1}, {0x6f,0xcc,0x9b,0xcc,0x83}}, - {{0xe1,0xbb,0x9f}, {0x6f,0xcc,0x9b,0xcc,0x89}}, - {{0xe1,0xbb,0xa3}, {0x6f,0xcc,0x9b,0xcc,0xa3}}, - {{0xe1,0xbb,0x8d}, {0x6f,0xcc,0xa3}}, - {{0xe1,0xbb,0x99}, {0x6f,0xcc,0xa3,0xcc,0x82}}, - {{0xc7,0xab}, {0x6f,0xcc,0xa8}}, - {{0xc7,0xad}, {0x6f,0xcc,0xa8,0xcc,0x84}}, - {{0xe1,0xb9,0x95}, {0x70,0xcc,0x81}}, - {{0xe1,0xb9,0x97}, {0x70,0xcc,0x87}}, - {{0xc5,0x95}, {0x72,0xcc,0x81}}, - {{0xe1,0xb9,0x99}, {0x72,0xcc,0x87}}, - {{0xc5,0x99}, {0x72,0xcc,0x8c}}, - {{0xc8,0x91}, {0x72,0xcc,0x8f}}, - {{0xc8,0x93}, {0x72,0xcc,0x91}}, - {{0xe1,0xb9,0x9b}, {0x72,0xcc,0xa3}}, - {{0xe1,0xb9,0x9d}, {0x72,0xcc,0xa3,0xcc,0x84}}, - {{0xc5,0x97}, {0x72,0xcc,0xa7}}, - {{0xe1,0xb9,0x9f}, {0x72,0xcc,0xb1}}, - {{0xc5,0x9b}, {0x73,0xcc,0x81}}, - {{0xe1,0xb9,0xa5}, {0x73,0xcc,0x81,0xcc,0x87}}, - {{0xc5,0x9d}, {0x73,0xcc,0x82}}, - {{0xe1,0xb9,0xa1}, {0x73,0xcc,0x87}}, - {{0xc5,0xa1}, {0x73,0xcc,0x8c}}, - {{0xe1,0xb9,0xa7}, {0x73,0xcc,0x8c,0xcc,0x87}}, - {{0xe1,0xb9,0xa3}, {0x73,0xcc,0xa3}}, - {{0xe1,0xb9,0xa9}, {0x73,0xcc,0xa3,0xcc,0x87}}, - {{0xc5,0x9f}, {0x73,0xcc,0xa7}}, - {{0xe1,0xb9,0xab}, {0x74,0xcc,0x87}}, - {{0xe1,0xba,0x97}, {0x74,0xcc,0x88}}, - {{0xc5,0xa5}, {0x74,0xcc,0x8c}}, - {{0xe1,0xb9,0xad}, {0x74,0xcc,0xa3}}, - {{0xc5,0xa3}, {0x74,0xcc,0xa7}}, - {{0xe1,0xb9,0xb1}, {0x74,0xcc,0xad}}, - {{0xe1,0xb9,0xaf}, {0x74,0xcc,0xb1}}, - {{0xc3,0xb9}, {0x75,0xcc,0x80}}, - {{0xc3,0xba}, {0x75,0xcc,0x81}}, - {{0xc3,0xbb}, {0x75,0xcc,0x82}}, - {{0xc5,0xa9}, {0x75,0xcc,0x83}}, - {{0xe1,0xb9,0xb9}, {0x75,0xcc,0x83,0xcc,0x81}}, - {{0xc5,0xab}, {0x75,0xcc,0x84}}, - {{0xe1,0xb9,0xbb}, {0x75,0xcc,0x84,0xcc,0x88}}, - {{0xc5,0xad}, {0x75,0xcc,0x86}}, - {{0xc3,0xbc}, {0x75,0xcc,0x88}}, - {{0xc7,0x9c}, {0x75,0xcc,0x88,0xcc,0x80}}, - {{0xc7,0x98}, {0x75,0xcc,0x88,0xcc,0x81}}, - {{0xc7,0x96}, {0x75,0xcc,0x88,0xcc,0x84}}, - {{0xc7,0x9a}, {0x75,0xcc,0x88,0xcc,0x8c}}, - {{0xe1,0xbb,0xa7}, {0x75,0xcc,0x89}}, - {{0xc5,0xaf}, {0x75,0xcc,0x8a}}, - {{0xc5,0xb1}, {0x75,0xcc,0x8b}}, - {{0xc7,0x94}, {0x75,0xcc,0x8c}}, - {{0xc8,0x95}, {0x75,0xcc,0x8f}}, - {{0xc8,0x97}, {0x75,0xcc,0x91}}, - {{0xc6,0xb0}, {0x75,0xcc,0x9b}}, - {{0xe1,0xbb,0xab}, {0x75,0xcc,0x9b,0xcc,0x80}}, - {{0xe1,0xbb,0xa9}, {0x75,0xcc,0x9b,0xcc,0x81}}, - {{0xe1,0xbb,0xaf}, {0x75,0xcc,0x9b,0xcc,0x83}}, - {{0xe1,0xbb,0xad}, {0x75,0xcc,0x9b,0xcc,0x89}}, - {{0xe1,0xbb,0xb1}, {0x75,0xcc,0x9b,0xcc,0xa3}}, - {{0xe1,0xbb,0xa5}, {0x75,0xcc,0xa3}}, - {{0xe1,0xb9,0xb3}, {0x75,0xcc,0xa4}}, - {{0xc5,0xb3}, {0x75,0xcc,0xa8}}, - {{0xe1,0xb9,0xb7}, {0x75,0xcc,0xad}}, - {{0xe1,0xb9,0xb5}, {0x75,0xcc,0xb0}}, - {{0xe1,0xb9,0xbd}, {0x76,0xcc,0x83}}, - {{0xe1,0xb9,0xbf}, {0x76,0xcc,0xa3}}, - {{0xe1,0xba,0x81}, {0x77,0xcc,0x80}}, - {{0xe1,0xba,0x83}, {0x77,0xcc,0x81}}, - {{0xc5,0xb5}, {0x77,0xcc,0x82}}, - {{0xe1,0xba,0x87}, {0x77,0xcc,0x87}}, - {{0xe1,0xba,0x85}, {0x77,0xcc,0x88}}, - {{0xe1,0xba,0x98}, {0x77,0xcc,0x8a}}, - {{0xe1,0xba,0x89}, {0x77,0xcc,0xa3}}, - {{0xe1,0xba,0x8b}, {0x78,0xcc,0x87}}, - {{0xe1,0xba,0x8d}, {0x78,0xcc,0x88}}, - {{0xe1,0xbb,0xb3}, {0x79,0xcc,0x80}}, - {{0xc3,0xbd}, {0x79,0xcc,0x81}}, - {{0xc5,0xb7}, {0x79,0xcc,0x82}}, - {{0xe1,0xbb,0xb9}, {0x79,0xcc,0x83}}, - {{0xe1,0xba,0x8f}, {0x79,0xcc,0x87}}, - {{0xc3,0xbf}, {0x79,0xcc,0x88}}, - {{0xe1,0xbb,0xb7}, {0x79,0xcc,0x89}}, - {{0xe1,0xba,0x99}, {0x79,0xcc,0x8a}}, - {{0xe1,0xbb,0xb5}, {0x79,0xcc,0xa3}}, - {{0xc5,0xba}, {0x7a,0xcc,0x81}}, - {{0xe1,0xba,0x91}, {0x7a,0xcc,0x82}}, - {{0xc5,0xbc}, {0x7a,0xcc,0x87}}, - {{0xc5,0xbe}, {0x7a,0xcc,0x8c}}, - {{0xe1,0xba,0x93}, {0x7a,0xcc,0xa3}}, - {{0xe1,0xba,0x95}, {0x7a,0xcc,0xb1}}, - {{0xe1,0xbf,0xad}, {0xc2,0xa8,0xcc,0x80}}, - {{0xe1,0xbf,0xae}, {0xc2,0xa8,0xcc,0x81}}, - {{0xce,0x85}, {0xc2,0xa8,0xcc,0x8d}}, - {{0xe1,0xbf,0x81}, {0xc2,0xa8,0xcd,0x82}}, - {{0xe1,0xbf,0xbd}, {0xc2,0xb4}}, - {{0xce,0x87}, {0xc2,0xb7}}, - {{0xd3,0x94}, {0xc3,0x86}}, - {{0xc7,0xbc}, {0xc3,0x86,0xcc,0x81}}, - {{0xc7,0xa2}, {0xc3,0x86,0xcc,0x84}}, - {{0xc7,0xbe}, {0xc3,0x98,0xcc,0x81}}, - {{0xd3,0x95}, {0xc3,0xa6}}, - {{0xc7,0xbd}, {0xc3,0xa6,0xcc,0x81}}, - {{0xc7,0xa3}, {0xc3,0xa6,0xcc,0x84}}, - {{0xc7,0xbf}, {0xc3,0xb8,0xcc,0x81}}, - {{0xe1,0xba,0x9b}, {0xc5,0xbf,0xcc,0x87}}, - {{0xd3,0x98}, {0xc6,0x8f}}, - {{0xd3,0x9a}, {0xc6,0x8f,0xcc,0x88}}, - {{0xd3,0xa8}, {0xc6,0x9f}}, - {{0xd3,0xaa}, {0xc6,0x9f,0xcc,0x88}}, - {{0xd3,0xa0}, {0xc6,0xb7}}, - {{0xc7,0xae}, {0xc6,0xb7,0xcc,0x8c}}, - {{0xd3,0x99}, {0xc9,0x99}}, - {{0xd3,0x9b}, {0xc9,0x99,0xcc,0x88}}, - {{0xd3,0xa9}, {0xc9,0xb5}}, - {{0xd3,0xab}, {0xc9,0xb5,0xcc,0x88}}, - {{0xd3,0xa1}, {0xca,0x92}}, - {{0xc7,0xaf}, {0xca,0x92,0xcc,0x8c}}, - {{0xcd,0xb4}, {0xca,0xb9}}, - {{0xcd,0x80}, {0xcc,0x80}}, - {{0xcd,0x81}, {0xcc,0x81}}, - {{0xcc,0x90}, {0xcc,0x86,0xcc,0x87}}, - {{0xcd,0x84}, {0xcc,0x88,0xcc,0x8d}}, - {{0xcd,0x83}, {0xcc,0x93}}, - {{0xe1,0xbe,0xba}, {0xce,0x91,0xcc,0x80}}, - {{0xe1,0xbe,0xbb}, {0xce,0x91,0xcc,0x81}}, - {{0xe1,0xbe,0xb9}, {0xce,0x91,0xcc,0x84}}, - {{0xe1,0xbe,0xb8}, {0xce,0x91,0xcc,0x86}}, - {{0xce,0x86}, {0xce,0x91,0xcc,0x8d}}, - {{0xe1,0xbc,0x88}, {0xce,0x91,0xcc,0x93}}, - {{0xe1,0xbc,0x8a}, {0xce,0x91,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbc,0x8c}, {0xce,0x91,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbc,0x8e}, {0xce,0x91,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbc,0x89}, {0xce,0x91,0xcc,0x94}}, - {{0xe1,0xbc,0x8b}, {0xce,0x91,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbc,0x8d}, {0xce,0x91,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbc,0x8f}, {0xce,0x91,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbe,0xbc}, {0xce,0x91,0xcd,0x85}}, - {{0xe1,0xbe,0x88}, {0xce,0x91,0xcd,0x85,0xcc,0x93}}, - {{0xe1,0xbe,0x8a}, {0xce,0x91,0xcd,0x85,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbe,0x8c}, {0xce,0x91,0xcd,0x85,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbe,0x8e}, {0xce,0x91,0xcd,0x85,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbe,0x89}, {0xce,0x91,0xcd,0x85,0xcc,0x94}}, - {{0xe1,0xbe,0x8b}, {0xce,0x91,0xcd,0x85,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbe,0x8d}, {0xce,0x91,0xcd,0x85,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbe,0x8f}, {0xce,0x91,0xcd,0x85,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbf,0x88}, {0xce,0x95,0xcc,0x80}}, - {{0xe1,0xbf,0x89}, {0xce,0x95,0xcc,0x81}}, - {{0xce,0x88}, {0xce,0x95,0xcc,0x8d}}, - {{0xe1,0xbc,0x98}, {0xce,0x95,0xcc,0x93}}, - {{0xe1,0xbc,0x9a}, {0xce,0x95,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbc,0x9c}, {0xce,0x95,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbc,0x99}, {0xce,0x95,0xcc,0x94}}, - {{0xe1,0xbc,0x9b}, {0xce,0x95,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbc,0x9d}, {0xce,0x95,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbf,0x8a}, {0xce,0x97,0xcc,0x80}}, - {{0xe1,0xbf,0x8b}, {0xce,0x97,0xcc,0x81}}, - {{0xce,0x89}, {0xce,0x97,0xcc,0x8d}}, - {{0xe1,0xbc,0xa8}, {0xce,0x97,0xcc,0x93}}, - {{0xe1,0xbc,0xaa}, {0xce,0x97,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbc,0xac}, {0xce,0x97,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbc,0xae}, {0xce,0x97,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbc,0xa9}, {0xce,0x97,0xcc,0x94}}, - {{0xe1,0xbc,0xab}, {0xce,0x97,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbc,0xad}, {0xce,0x97,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbc,0xaf}, {0xce,0x97,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbf,0x8c}, {0xce,0x97,0xcd,0x85}}, - {{0xe1,0xbe,0x98}, {0xce,0x97,0xcd,0x85,0xcc,0x93}}, - {{0xe1,0xbe,0x9a}, {0xce,0x97,0xcd,0x85,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbe,0x9c}, {0xce,0x97,0xcd,0x85,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbe,0x9e}, {0xce,0x97,0xcd,0x85,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbe,0x99}, {0xce,0x97,0xcd,0x85,0xcc,0x94}}, - {{0xe1,0xbe,0x9b}, {0xce,0x97,0xcd,0x85,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbe,0x9d}, {0xce,0x97,0xcd,0x85,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbe,0x9f}, {0xce,0x97,0xcd,0x85,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbf,0x9a}, {0xce,0x99,0xcc,0x80}}, - {{0xe1,0xbf,0x9b}, {0xce,0x99,0xcc,0x81}}, - {{0xe1,0xbf,0x99}, {0xce,0x99,0xcc,0x84}}, - {{0xe1,0xbf,0x98}, {0xce,0x99,0xcc,0x86}}, - {{0xce,0xaa}, {0xce,0x99,0xcc,0x88}}, - {{0xce,0x8a}, {0xce,0x99,0xcc,0x8d}}, - {{0xe1,0xbc,0xb8}, {0xce,0x99,0xcc,0x93}}, - {{0xe1,0xbc,0xba}, {0xce,0x99,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbc,0xbc}, {0xce,0x99,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbc,0xbe}, {0xce,0x99,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbc,0xb9}, {0xce,0x99,0xcc,0x94}}, - {{0xe1,0xbc,0xbb}, {0xce,0x99,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbc,0xbd}, {0xce,0x99,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbc,0xbf}, {0xce,0x99,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbf,0xb8}, {0xce,0x9f,0xcc,0x80}}, - {{0xe1,0xbf,0xb9}, {0xce,0x9f,0xcc,0x81}}, - {{0xce,0x8c}, {0xce,0x9f,0xcc,0x8d}}, - {{0xe1,0xbd,0x88}, {0xce,0x9f,0xcc,0x93}}, - {{0xe1,0xbd,0x8a}, {0xce,0x9f,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbd,0x8c}, {0xce,0x9f,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbd,0x89}, {0xce,0x9f,0xcc,0x94}}, - {{0xe1,0xbd,0x8b}, {0xce,0x9f,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbd,0x8d}, {0xce,0x9f,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbf,0xac}, {0xce,0xa1,0xcc,0x94}}, - {{0xe1,0xbf,0xaa}, {0xce,0xa5,0xcc,0x80}}, - {{0xe1,0xbf,0xab}, {0xce,0xa5,0xcc,0x81}}, - {{0xe1,0xbf,0xa9}, {0xce,0xa5,0xcc,0x84}}, - {{0xe1,0xbf,0xa8}, {0xce,0xa5,0xcc,0x86}}, - {{0xce,0xab}, {0xce,0xa5,0xcc,0x88}}, - {{0xce,0x8e}, {0xce,0xa5,0xcc,0x8d}}, - {{0xe1,0xbd,0x99}, {0xce,0xa5,0xcc,0x94}}, - {{0xe1,0xbd,0x9b}, {0xce,0xa5,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbd,0x9d}, {0xce,0xa5,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbd,0x9f}, {0xce,0xa5,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbf,0xba}, {0xce,0xa9,0xcc,0x80}}, - {{0xe1,0xbf,0xbb}, {0xce,0xa9,0xcc,0x81}}, - {{0xce,0x8f}, {0xce,0xa9,0xcc,0x8d}}, - {{0xe1,0xbd,0xa8}, {0xce,0xa9,0xcc,0x93}}, - {{0xe1,0xbd,0xaa}, {0xce,0xa9,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbd,0xac}, {0xce,0xa9,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbd,0xae}, {0xce,0xa9,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbd,0xa9}, {0xce,0xa9,0xcc,0x94}}, - {{0xe1,0xbd,0xab}, {0xce,0xa9,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbd,0xad}, {0xce,0xa9,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbd,0xaf}, {0xce,0xa9,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbf,0xbc}, {0xce,0xa9,0xcd,0x85}}, - {{0xe1,0xbe,0xa8}, {0xce,0xa9,0xcd,0x85,0xcc,0x93}}, - {{0xe1,0xbe,0xaa}, {0xce,0xa9,0xcd,0x85,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbe,0xac}, {0xce,0xa9,0xcd,0x85,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbe,0xae}, {0xce,0xa9,0xcd,0x85,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbe,0xa9}, {0xce,0xa9,0xcd,0x85,0xcc,0x94}}, - {{0xe1,0xbe,0xab}, {0xce,0xa9,0xcd,0x85,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbe,0xad}, {0xce,0xa9,0xcd,0x85,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbe,0xaf}, {0xce,0xa9,0xcd,0x85,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbd,0xb0}, {0xce,0xb1,0xcc,0x80}}, - {{0xe1,0xbd,0xb1}, {0xce,0xb1,0xcc,0x81}}, - {{0xe1,0xbe,0xb1}, {0xce,0xb1,0xcc,0x84}}, - {{0xe1,0xbe,0xb0}, {0xce,0xb1,0xcc,0x86}}, - {{0xce,0xac}, {0xce,0xb1,0xcc,0x8d}}, - {{0xe1,0xbc,0x80}, {0xce,0xb1,0xcc,0x93}}, - {{0xe1,0xbc,0x82}, {0xce,0xb1,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbc,0x84}, {0xce,0xb1,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbc,0x86}, {0xce,0xb1,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbc,0x81}, {0xce,0xb1,0xcc,0x94}}, - {{0xe1,0xbc,0x83}, {0xce,0xb1,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbc,0x85}, {0xce,0xb1,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbc,0x87}, {0xce,0xb1,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbe,0xb6}, {0xce,0xb1,0xcd,0x82}}, - {{0xe1,0xbe,0xb3}, {0xce,0xb1,0xcd,0x85}}, - {{0xe1,0xbe,0xb2}, {0xce,0xb1,0xcd,0x85,0xcc,0x80}}, - {{0xe1,0xbe,0xb4}, {0xce,0xb1,0xcd,0x85,0xcc,0x81}}, - {{0xe1,0xbe,0x80}, {0xce,0xb1,0xcd,0x85,0xcc,0x93}}, - {{0xe1,0xbe,0x82}, {0xce,0xb1,0xcd,0x85,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbe,0x84}, {0xce,0xb1,0xcd,0x85,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbe,0x86}, {0xce,0xb1,0xcd,0x85,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbe,0x81}, {0xce,0xb1,0xcd,0x85,0xcc,0x94}}, - {{0xe1,0xbe,0x83}, {0xce,0xb1,0xcd,0x85,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbe,0x85}, {0xce,0xb1,0xcd,0x85,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbe,0x87}, {0xce,0xb1,0xcd,0x85,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbe,0xb7}, {0xce,0xb1,0xcd,0x85,0xcd,0x82}}, - {{0xe1,0xbd,0xb2}, {0xce,0xb5,0xcc,0x80}}, - {{0xe1,0xbd,0xb3}, {0xce,0xb5,0xcc,0x81}}, - {{0xce,0xad}, {0xce,0xb5,0xcc,0x8d}}, - {{0xe1,0xbc,0x90}, {0xce,0xb5,0xcc,0x93}}, - {{0xe1,0xbc,0x92}, {0xce,0xb5,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbc,0x94}, {0xce,0xb5,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbc,0x91}, {0xce,0xb5,0xcc,0x94}}, - {{0xe1,0xbc,0x93}, {0xce,0xb5,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbc,0x95}, {0xce,0xb5,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbd,0xb4}, {0xce,0xb7,0xcc,0x80}}, - {{0xe1,0xbd,0xb5}, {0xce,0xb7,0xcc,0x81}}, - {{0xce,0xae}, {0xce,0xb7,0xcc,0x8d}}, - {{0xe1,0xbc,0xa0}, {0xce,0xb7,0xcc,0x93}}, - {{0xe1,0xbc,0xa2}, {0xce,0xb7,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbc,0xa4}, {0xce,0xb7,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbc,0xa6}, {0xce,0xb7,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbc,0xa1}, {0xce,0xb7,0xcc,0x94}}, - {{0xe1,0xbc,0xa3}, {0xce,0xb7,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbc,0xa5}, {0xce,0xb7,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbc,0xa7}, {0xce,0xb7,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbf,0x86}, {0xce,0xb7,0xcd,0x82}}, - {{0xe1,0xbf,0x83}, {0xce,0xb7,0xcd,0x85}}, - {{0xe1,0xbf,0x82}, {0xce,0xb7,0xcd,0x85,0xcc,0x80}}, - {{0xe1,0xbf,0x84}, {0xce,0xb7,0xcd,0x85,0xcc,0x81}}, - {{0xe1,0xbe,0x90}, {0xce,0xb7,0xcd,0x85,0xcc,0x93}}, - {{0xe1,0xbe,0x92}, {0xce,0xb7,0xcd,0x85,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbe,0x94}, {0xce,0xb7,0xcd,0x85,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbe,0x96}, {0xce,0xb7,0xcd,0x85,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbe,0x91}, {0xce,0xb7,0xcd,0x85,0xcc,0x94}}, - {{0xe1,0xbe,0x93}, {0xce,0xb7,0xcd,0x85,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbe,0x95}, {0xce,0xb7,0xcd,0x85,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbe,0x97}, {0xce,0xb7,0xcd,0x85,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbf,0x87}, {0xce,0xb7,0xcd,0x85,0xcd,0x82}}, - {{0xe1,0xbe,0xbe}, {0xce,0xb9}}, - {{0xe1,0xbd,0xb6}, {0xce,0xb9,0xcc,0x80}}, - {{0xe1,0xbd,0xb7}, {0xce,0xb9,0xcc,0x81}}, - {{0xe1,0xbf,0x91}, {0xce,0xb9,0xcc,0x84}}, - {{0xe1,0xbf,0x90}, {0xce,0xb9,0xcc,0x86}}, - {{0xcf,0x8a}, {0xce,0xb9,0xcc,0x88}}, - {{0xe1,0xbf,0x92}, {0xce,0xb9,0xcc,0x88,0xcc,0x80}}, - {{0xe1,0xbf,0x93}, {0xce,0xb9,0xcc,0x88,0xcc,0x81}}, - {{0xce,0x90}, {0xce,0xb9,0xcc,0x88,0xcc,0x8d}}, - {{0xe1,0xbf,0x97}, {0xce,0xb9,0xcc,0x88,0xcd,0x82}}, - {{0xce,0xaf}, {0xce,0xb9,0xcc,0x8d}}, - {{0xe1,0xbc,0xb0}, {0xce,0xb9,0xcc,0x93}}, - {{0xe1,0xbc,0xb2}, {0xce,0xb9,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbc,0xb4}, {0xce,0xb9,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbc,0xb6}, {0xce,0xb9,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbc,0xb1}, {0xce,0xb9,0xcc,0x94}}, - {{0xe1,0xbc,0xb3}, {0xce,0xb9,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbc,0xb5}, {0xce,0xb9,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbc,0xb7}, {0xce,0xb9,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbf,0x96}, {0xce,0xb9,0xcd,0x82}}, - {{0xe1,0xbd,0xb8}, {0xce,0xbf,0xcc,0x80}}, - {{0xe1,0xbd,0xb9}, {0xce,0xbf,0xcc,0x81}}, - {{0xcf,0x8c}, {0xce,0xbf,0xcc,0x8d}}, - {{0xe1,0xbd,0x80}, {0xce,0xbf,0xcc,0x93}}, - {{0xe1,0xbd,0x82}, {0xce,0xbf,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbd,0x84}, {0xce,0xbf,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbd,0x81}, {0xce,0xbf,0xcc,0x94}}, - {{0xe1,0xbd,0x83}, {0xce,0xbf,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbd,0x85}, {0xce,0xbf,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbf,0xb4}, {0xce,0xbf,0xcd,0x85,0xcc,0x81}}, - {{0xe1,0xbf,0xa4}, {0xcf,0x81,0xcc,0x93}}, - {{0xe1,0xbf,0xa5}, {0xcf,0x81,0xcc,0x94}}, - {{0xe1,0xbd,0xba}, {0xcf,0x85,0xcc,0x80}}, - {{0xe1,0xbd,0xbb}, {0xcf,0x85,0xcc,0x81}}, - {{0xe1,0xbf,0xa1}, {0xcf,0x85,0xcc,0x84}}, - {{0xe1,0xbf,0xa0}, {0xcf,0x85,0xcc,0x86}}, - {{0xcf,0x8b}, {0xcf,0x85,0xcc,0x88}}, - {{0xe1,0xbf,0xa2}, {0xcf,0x85,0xcc,0x88,0xcc,0x80}}, - {{0xe1,0xbf,0xa3}, {0xcf,0x85,0xcc,0x88,0xcc,0x81}}, - {{0xce,0xb0}, {0xcf,0x85,0xcc,0x88,0xcc,0x8d}}, - {{0xe1,0xbf,0xa7}, {0xcf,0x85,0xcc,0x88,0xcd,0x82}}, - {{0xcf,0x8d}, {0xcf,0x85,0xcc,0x8d}}, - {{0xe1,0xbd,0x90}, {0xcf,0x85,0xcc,0x93}}, - {{0xe1,0xbd,0x92}, {0xcf,0x85,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbd,0x94}, {0xcf,0x85,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbd,0x96}, {0xcf,0x85,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbd,0x91}, {0xcf,0x85,0xcc,0x94}}, - {{0xe1,0xbd,0x93}, {0xcf,0x85,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbd,0x95}, {0xcf,0x85,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbd,0x97}, {0xcf,0x85,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbf,0xa6}, {0xcf,0x85,0xcd,0x82}}, - {{0xe1,0xbd,0xbc}, {0xcf,0x89,0xcc,0x80}}, - {{0xe1,0xbd,0xbd}, {0xcf,0x89,0xcc,0x81}}, - {{0xcf,0x8e}, {0xcf,0x89,0xcc,0x8d}}, - {{0xe1,0xbd,0xa0}, {0xcf,0x89,0xcc,0x93}}, - {{0xe1,0xbd,0xa2}, {0xcf,0x89,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbd,0xa4}, {0xcf,0x89,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbd,0xa6}, {0xcf,0x89,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbd,0xa1}, {0xcf,0x89,0xcc,0x94}}, - {{0xe1,0xbd,0xa3}, {0xcf,0x89,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbd,0xa5}, {0xcf,0x89,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbd,0xa7}, {0xcf,0x89,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbf,0xb6}, {0xcf,0x89,0xcd,0x82}}, - {{0xe1,0xbf,0xb3}, {0xcf,0x89,0xcd,0x85}}, - {{0xe1,0xbf,0xb2}, {0xcf,0x89,0xcd,0x85,0xcc,0x80}}, - {{0xe1,0xbe,0xa0}, {0xcf,0x89,0xcd,0x85,0xcc,0x93}}, - {{0xe1,0xbe,0xa2}, {0xcf,0x89,0xcd,0x85,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbe,0xa4}, {0xcf,0x89,0xcd,0x85,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbe,0xa6}, {0xcf,0x89,0xcd,0x85,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbe,0xa1}, {0xcf,0x89,0xcd,0x85,0xcc,0x94}}, - {{0xe1,0xbe,0xa3}, {0xcf,0x89,0xcd,0x85,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbe,0xa5}, {0xcf,0x89,0xcd,0x85,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbe,0xa7}, {0xcf,0x89,0xcd,0x85,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbf,0xb7}, {0xcf,0x89,0xcd,0x85,0xcd,0x82}}, - {{0xcf,0x94}, {0xcf,0x92,0xcc,0x88}}, - {{0xcf,0x93}, {0xcf,0x92,0xcc,0x8d}}, - {{0xd0,0x87}, {0xd0,0x86,0xcc,0x88}}, - {{0xd3,0x90}, {0xd0,0x90,0xcc,0x86}}, - {{0xd3,0x92}, {0xd0,0x90,0xcc,0x88}}, - {{0xd0,0x83}, {0xd0,0x93,0xcc,0x81}}, - {{0xd3,0x96}, {0xd0,0x95,0xcc,0x86}}, - {{0xd0,0x81}, {0xd0,0x95,0xcc,0x88}}, - {{0xd3,0x81}, {0xd0,0x96,0xcc,0x86}}, - {{0xd3,0x9c}, {0xd0,0x96,0xcc,0x88}}, - {{0xd3,0x9e}, {0xd0,0x97,0xcc,0x88}}, - {{0xd3,0xa2}, {0xd0,0x98,0xcc,0x84}}, - {{0xd0,0x99}, {0xd0,0x98,0xcc,0x86}}, - {{0xd3,0xa4}, {0xd0,0x98,0xcc,0x88}}, - {{0xd0,0x8c}, {0xd0,0x9a,0xcc,0x81}}, - {{0xd3,0xa6}, {0xd0,0x9e,0xcc,0x88}}, - {{0xd3,0xae}, {0xd0,0xa3,0xcc,0x84}}, - {{0xd0,0x8e}, {0xd0,0xa3,0xcc,0x86}}, - {{0xd3,0xb0}, {0xd0,0xa3,0xcc,0x88}}, - {{0xd3,0xb2}, {0xd0,0xa3,0xcc,0x8b}}, - {{0xd3,0xb4}, {0xd0,0xa7,0xcc,0x88}}, - {{0xd3,0xb8}, {0xd0,0xab,0xcc,0x88}}, - {{0xd3,0x91}, {0xd0,0xb0,0xcc,0x86}}, - {{0xd3,0x93}, {0xd0,0xb0,0xcc,0x88}}, - {{0xd1,0x93}, {0xd0,0xb3,0xcc,0x81}}, - {{0xd3,0x97}, {0xd0,0xb5,0xcc,0x86}}, - {{0xd1,0x91}, {0xd0,0xb5,0xcc,0x88}}, - {{0xd3,0x82}, {0xd0,0xb6,0xcc,0x86}}, - {{0xd3,0x9d}, {0xd0,0xb6,0xcc,0x88}}, - {{0xd3,0x9f}, {0xd0,0xb7,0xcc,0x88}}, - {{0xd3,0xa3}, {0xd0,0xb8,0xcc,0x84}}, - {{0xd0,0xb9}, {0xd0,0xb8,0xcc,0x86}}, - {{0xd3,0xa5}, {0xd0,0xb8,0xcc,0x88}}, - {{0xd1,0x9c}, {0xd0,0xba,0xcc,0x81}}, - {{0xd3,0xa7}, {0xd0,0xbe,0xcc,0x88}}, - {{0xd3,0xaf}, {0xd1,0x83,0xcc,0x84}}, - {{0xd1,0x9e}, {0xd1,0x83,0xcc,0x86}}, - {{0xd3,0xb1}, {0xd1,0x83,0xcc,0x88}}, - {{0xd3,0xb3}, {0xd1,0x83,0xcc,0x8b}}, - {{0xd3,0xb5}, {0xd1,0x87,0xcc,0x88}}, - {{0xd3,0xb9}, {0xd1,0x8b,0xcc,0x88}}, - {{0xd1,0x97}, {0xd1,0x96,0xcc,0x88}}, - {{0xd1,0xb6}, {0xd1,0xb4,0xcc,0x8f}}, - {{0xd1,0xb7}, {0xd1,0xb5,0xcc,0x8f}}, - {{0xef,0xac,0xae}, {0xd7,0x90,0xd6,0xb7}}, - {{0xef,0xac,0xaf}, {0xd7,0x90,0xd6,0xb8}}, - {{0xef,0xac,0xb0}, {0xd7,0x90,0xd6,0xbc}}, - {{0xef,0xac,0xb1}, {0xd7,0x91,0xd6,0xbc}}, - {{0xef,0xad,0x8c}, {0xd7,0x91,0xd6,0xbf}}, - {{0xef,0xac,0xb2}, {0xd7,0x92,0xd6,0xbc}}, - {{0xef,0xac,0xb3}, {0xd7,0x93,0xd6,0xbc}}, - {{0xef,0xac,0xb4}, {0xd7,0x94,0xd6,0xbc}}, - {{0xef,0xad,0x8b}, {0xd7,0x95,0xd6,0xb9}}, - {{0xef,0xac,0xb5}, {0xd7,0x95,0xd6,0xbc}}, - {{0xef,0xac,0xb6}, {0xd7,0x96,0xd6,0xbc}}, - {{0xef,0xac,0xb8}, {0xd7,0x98,0xd6,0xbc}}, - {{0xef,0xac,0xb9}, {0xd7,0x99,0xd6,0xbc}}, - {{0xef,0xac,0xba}, {0xd7,0x9a,0xd6,0xbc}}, - {{0xef,0xac,0xbb}, {0xd7,0x9b,0xd6,0xbc}}, - {{0xef,0xad,0x8d}, {0xd7,0x9b,0xd6,0xbf}}, - {{0xef,0xac,0xbc}, {0xd7,0x9c,0xd6,0xbc}}, - {{0xef,0xac,0xbe}, {0xd7,0x9e,0xd6,0xbc}}, - {{0xef,0xad,0x80}, {0xd7,0xa0,0xd6,0xbc}}, - {{0xef,0xad,0x81}, {0xd7,0xa1,0xd6,0xbc}}, - {{0xef,0xad,0x83}, {0xd7,0xa3,0xd6,0xbc}}, - {{0xef,0xad,0x84}, {0xd7,0xa4,0xd6,0xbc}}, - {{0xef,0xad,0x8e}, {0xd7,0xa4,0xd6,0xbf}}, - {{0xef,0xad,0x86}, {0xd7,0xa6,0xd6,0xbc}}, - {{0xef,0xad,0x87}, {0xd7,0xa7,0xd6,0xbc}}, - {{0xef,0xad,0x88}, {0xd7,0xa8,0xd6,0xbc}}, - {{0xef,0xad,0x89}, {0xd7,0xa9,0xd6,0xbc}}, - {{0xef,0xac,0xac}, {0xd7,0xa9,0xd6,0xbc,0xd7,0x81}}, - {{0xef,0xac,0xad}, {0xd7,0xa9,0xd6,0xbc,0xd7,0x82}}, - {{0xef,0xac,0xaa}, {0xd7,0xa9,0xd7,0x81}}, - {{0xef,0xac,0xab}, {0xd7,0xa9,0xd7,0x82}}, - {{0xef,0xad,0x8a}, {0xd7,0xaa,0xd6,0xbc}}, - {{0xef,0xac,0x9f}, {0xd7,0xb2,0xd6,0xb7}}, - {{0xe0,0xa5,0x98}, {0xe0,0xa4,0x95,0xe0,0xa4,0xbc}}, - {{0xe0,0xa5,0x99}, {0xe0,0xa4,0x96,0xe0,0xa4,0xbc}}, - {{0xe0,0xa5,0x9a}, {0xe0,0xa4,0x97,0xe0,0xa4,0xbc}}, - {{0xe0,0xa5,0x9b}, {0xe0,0xa4,0x9c,0xe0,0xa4,0xbc}}, - {{0xe0,0xa5,0x9c}, {0xe0,0xa4,0xa1,0xe0,0xa4,0xbc}}, - {{0xe0,0xa5,0x9d}, {0xe0,0xa4,0xa2,0xe0,0xa4,0xbc}}, - {{0xe0,0xa4,0xa9}, {0xe0,0xa4,0xa8,0xe0,0xa4,0xbc}}, - {{0xe0,0xa5,0x9e}, {0xe0,0xa4,0xab,0xe0,0xa4,0xbc}}, - {{0xe0,0xa5,0x9f}, {0xe0,0xa4,0xaf,0xe0,0xa4,0xbc}}, - {{0xe0,0xa4,0xb1}, {0xe0,0xa4,0xb0,0xe0,0xa4,0xbc}}, - {{0xe0,0xa4,0xb4}, {0xe0,0xa4,0xb3,0xe0,0xa4,0xbc}}, - {{0xe0,0xa7,0x9c}, {0xe0,0xa6,0xa1,0xe0,0xa6,0xbc}}, - {{0xe0,0xa7,0x9d}, {0xe0,0xa6,0xa2,0xe0,0xa6,0xbc}}, - {{0xe0,0xa6,0xb0}, {0xe0,0xa6,0xac,0xe0,0xa6,0xbc}}, - {{0xe0,0xa7,0x9f}, {0xe0,0xa6,0xaf,0xe0,0xa6,0xbc}}, - {{0xe0,0xa7,0x8b}, {0xe0,0xa7,0x87,0xe0,0xa6,0xbe}}, - {{0xe0,0xa7,0x8c}, {0xe0,0xa7,0x87,0xe0,0xa7,0x97}}, - {{0xe0,0xa9,0x99}, {0xe0,0xa8,0x96,0xe0,0xa8,0xbc}}, - {{0xe0,0xa9,0x9a}, {0xe0,0xa8,0x97,0xe0,0xa8,0xbc}}, - {{0xe0,0xa9,0x9b}, {0xe0,0xa8,0x9c,0xe0,0xa8,0xbc}}, - {{0xe0,0xa9,0x9c}, {0xe0,0xa8,0xa1,0xe0,0xa8,0xbc}}, - {{0xe0,0xa9,0x9e}, {0xe0,0xa8,0xab,0xe0,0xa8,0xbc}}, - {{0xe0,0xad,0x9c}, {0xe0,0xac,0xa1,0xe0,0xac,0xbc}}, - {{0xe0,0xad,0x9d}, {0xe0,0xac,0xa2,0xe0,0xac,0xbc}}, - {{0xe0,0xad,0x9f}, {0xe0,0xac,0xaf,0xe0,0xac,0xbc}}, - {{0xe0,0xad,0x8b}, {0xe0,0xad,0x87,0xe0,0xac,0xbe}}, - {{0xe0,0xad,0x88}, {0xe0,0xad,0x87,0xe0,0xad,0x96}}, - {{0xe0,0xad,0x8c}, {0xe0,0xad,0x87,0xe0,0xad,0x97}}, - {{0xe0,0xae,0x94}, {0xe0,0xae,0x92,0xe0,0xaf,0x97}}, - {{0xe0,0xaf,0x8a}, {0xe0,0xaf,0x86,0xe0,0xae,0xbe}}, - {{0xe0,0xaf,0x8c}, {0xe0,0xaf,0x86,0xe0,0xaf,0x97}}, - {{0xe0,0xaf,0x8b}, {0xe0,0xaf,0x87,0xe0,0xae,0xbe}}, - {{0xe0,0xb1,0x88}, {0xe0,0xb1,0x86,0xe0,0xb1,0x96}}, - {{0xe0,0xb3,0x80}, {0xe0,0xb2,0xbf,0xe0,0xb3,0x95}}, - {{0xe0,0xb3,0x8a}, {0xe0,0xb3,0x86,0xe0,0xb3,0x82}}, - {{0xe0,0xb3,0x8b}, {0xe0,0xb3,0x86,0xe0,0xb3,0x82,0xe0,0xb3,0x95}}, - {{0xe0,0xb3,0x87}, {0xe0,0xb3,0x86,0xe0,0xb3,0x95}}, - {{0xe0,0xb3,0x88}, {0xe0,0xb3,0x86,0xe0,0xb3,0x96}}, - {{0xe0,0xb5,0x8a}, {0xe0,0xb5,0x86,0xe0,0xb4,0xbe}}, - {{0xe0,0xb5,0x8c}, {0xe0,0xb5,0x86,0xe0,0xb5,0x97}}, - {{0xe0,0xb5,0x8b}, {0xe0,0xb5,0x87,0xe0,0xb4,0xbe}}, - {{0xe0,0xb8,0xb3}, {0xe0,0xb9,0x8d,0xe0,0xb8,0xb2}}, - {{0xe0,0xba,0xb3}, {0xe0,0xbb,0x8d,0xe0,0xba,0xb2}}, - {{0xe0,0xbd,0xa9}, {0xe0,0xbd,0x80,0xe0,0xbe,0xb5}}, - {{0xe0,0xbd,0x83}, {0xe0,0xbd,0x82,0xe0,0xbe,0xb7}}, - {{0xe0,0xbd,0x8d}, {0xe0,0xbd,0x8c,0xe0,0xbe,0xb7}}, - {{0xe0,0xbd,0x92}, {0xe0,0xbd,0x91,0xe0,0xbe,0xb7}}, - {{0xe0,0xbd,0x97}, {0xe0,0xbd,0x96,0xe0,0xbe,0xb7}}, - {{0xe0,0xbd,0x9c}, {0xe0,0xbd,0x9b,0xe0,0xbe,0xb7}}, - {{0xe0,0xbd,0xb3}, {0xe0,0xbd,0xb2,0xe0,0xbd,0xb1}}, - {{0xe0,0xbd,0xb5}, {0xe0,0xbd,0xb4,0xe0,0xbd,0xb1}}, - {{0xe0,0xbe,0x81}, {0xe0,0xbe,0x80,0xe0,0xbd,0xb1}}, - {{0xe0,0xbe,0xb9}, {0xe0,0xbe,0x90,0xe0,0xbe,0xb5}}, - {{0xe0,0xbe,0x93}, {0xe0,0xbe,0x92,0xe0,0xbe,0xb7}}, - {{0xe0,0xbe,0x9d}, {0xe0,0xbe,0x9c,0xe0,0xbe,0xb7}}, - {{0xe0,0xbe,0xa2}, {0xe0,0xbe,0xa1,0xe0,0xbe,0xb7}}, - {{0xe0,0xbe,0xa7}, {0xe0,0xbe,0xa6,0xe0,0xbe,0xb7}}, - {{0xe0,0xbe,0xac}, {0xe0,0xbe,0xab,0xe0,0xbe,0xb7}}, - {{0xe0,0xbd,0xb6}, {0xe0,0xbe,0xb2,0xe0,0xbe,0x80}}, - {{0xe0,0xbd,0xb7}, {0xe0,0xbe,0xb2,0xe0,0xbe,0x80,0xe0,0xbd,0xb1}}, - {{0xe0,0xbd,0xb8}, {0xe0,0xbe,0xb3,0xe0,0xbe,0x80}}, - {{0xe0,0xbd,0xb9}, {0xe0,0xbe,0xb3,0xe0,0xbe,0x80,0xe0,0xbd,0xb1}}, - {{0xe1,0xbf,0x8d}, {0xe1,0xbe,0xbf,0xcc,0x80}}, - {{0xe1,0xbf,0x8e}, {0xe1,0xbe,0xbf,0xcc,0x81}}, - {{0xe1,0xbf,0x8f}, {0xe1,0xbe,0xbf,0xcd,0x82}}, - {{0xe1,0xbf,0x9d}, {0xe1,0xbf,0xbe,0xcc,0x80}}, - {{0xe1,0xbf,0x9e}, {0xe1,0xbf,0xbe,0xcc,0x81}}, - {{0xe1,0xbf,0x9f}, {0xe1,0xbf,0xbe,0xcd,0x82}}, - {{0xe3,0x82,0x94}, {0xe3,0x81,0x86,0xe3,0x82,0x99}}, - {{0xe3,0x81,0x8c}, {0xe3,0x81,0x8b,0xe3,0x82,0x99}}, - {{0xe3,0x81,0x8e}, {0xe3,0x81,0x8d,0xe3,0x82,0x99}}, - {{0xe3,0x81,0x90}, {0xe3,0x81,0x8f,0xe3,0x82,0x99}}, - {{0xe3,0x81,0x92}, {0xe3,0x81,0x91,0xe3,0x82,0x99}}, - {{0xe3,0x81,0x94}, {0xe3,0x81,0x93,0xe3,0x82,0x99}}, - {{0xe3,0x81,0x96}, {0xe3,0x81,0x95,0xe3,0x82,0x99}}, - {{0xe3,0x81,0x98}, {0xe3,0x81,0x97,0xe3,0x82,0x99}}, - {{0xe3,0x81,0x9a}, {0xe3,0x81,0x99,0xe3,0x82,0x99}}, - {{0xe3,0x81,0x9c}, {0xe3,0x81,0x9b,0xe3,0x82,0x99}}, - {{0xe3,0x81,0x9e}, {0xe3,0x81,0x9d,0xe3,0x82,0x99}}, - {{0xe3,0x81,0xa0}, {0xe3,0x81,0x9f,0xe3,0x82,0x99}}, - {{0xe3,0x81,0xa2}, {0xe3,0x81,0xa1,0xe3,0x82,0x99}}, - {{0xe3,0x81,0xa5}, {0xe3,0x81,0xa4,0xe3,0x82,0x99}}, - {{0xe3,0x81,0xa7}, {0xe3,0x81,0xa6,0xe3,0x82,0x99}}, - {{0xe3,0x81,0xa9}, {0xe3,0x81,0xa8,0xe3,0x82,0x99}}, - {{0xe3,0x81,0xb0}, {0xe3,0x81,0xaf,0xe3,0x82,0x99}}, - {{0xe3,0x81,0xb1}, {0xe3,0x81,0xaf,0xe3,0x82,0x9a}}, - {{0xe3,0x81,0xb3}, {0xe3,0x81,0xb2,0xe3,0x82,0x99}}, - {{0xe3,0x81,0xb4}, {0xe3,0x81,0xb2,0xe3,0x82,0x9a}}, - {{0xe3,0x81,0xb6}, {0xe3,0x81,0xb5,0xe3,0x82,0x99}}, - {{0xe3,0x81,0xb7}, {0xe3,0x81,0xb5,0xe3,0x82,0x9a}}, - {{0xe3,0x81,0xb9}, {0xe3,0x81,0xb8,0xe3,0x82,0x99}}, - {{0xe3,0x81,0xba}, {0xe3,0x81,0xb8,0xe3,0x82,0x9a}}, - {{0xe3,0x81,0xbc}, {0xe3,0x81,0xbb,0xe3,0x82,0x99}}, - {{0xe3,0x81,0xbd}, {0xe3,0x81,0xbb,0xe3,0x82,0x9a}}, - {{0xe3,0x82,0x9e}, {0xe3,0x82,0x9d,0xe3,0x82,0x99}}, - {{0xe3,0x83,0xb4}, {0xe3,0x82,0xa6,0xe3,0x82,0x99}}, - {{0xe3,0x82,0xac}, {0xe3,0x82,0xab,0xe3,0x82,0x99}}, - {{0xe3,0x82,0xae}, {0xe3,0x82,0xad,0xe3,0x82,0x99}}, - {{0xe3,0x82,0xb0}, {0xe3,0x82,0xaf,0xe3,0x82,0x99}}, - {{0xe3,0x82,0xb2}, {0xe3,0x82,0xb1,0xe3,0x82,0x99}}, - {{0xe3,0x82,0xb4}, {0xe3,0x82,0xb3,0xe3,0x82,0x99}}, - {{0xe3,0x82,0xb6}, {0xe3,0x82,0xb5,0xe3,0x82,0x99}}, - {{0xe3,0x82,0xb8}, {0xe3,0x82,0xb7,0xe3,0x82,0x99}}, - {{0xe3,0x82,0xba}, {0xe3,0x82,0xb9,0xe3,0x82,0x99}}, - {{0xe3,0x82,0xbc}, {0xe3,0x82,0xbb,0xe3,0x82,0x99}}, - {{0xe3,0x82,0xbe}, {0xe3,0x82,0xbd,0xe3,0x82,0x99}}, - {{0xe3,0x83,0x80}, {0xe3,0x82,0xbf,0xe3,0x82,0x99}}, - {{0xe3,0x83,0x82}, {0xe3,0x83,0x81,0xe3,0x82,0x99}}, - {{0xe3,0x83,0x85}, {0xe3,0x83,0x84,0xe3,0x82,0x99}}, - {{0xe3,0x83,0x87}, {0xe3,0x83,0x86,0xe3,0x82,0x99}}, - {{0xe3,0x83,0x89}, {0xe3,0x83,0x88,0xe3,0x82,0x99}}, - {{0xe3,0x83,0x90}, {0xe3,0x83,0x8f,0xe3,0x82,0x99}}, - {{0xe3,0x83,0x91}, {0xe3,0x83,0x8f,0xe3,0x82,0x9a}}, - {{0xe3,0x83,0x93}, {0xe3,0x83,0x92,0xe3,0x82,0x99}}, - {{0xe3,0x83,0x94}, {0xe3,0x83,0x92,0xe3,0x82,0x9a}}, - {{0xe3,0x83,0x96}, {0xe3,0x83,0x95,0xe3,0x82,0x99}}, - {{0xe3,0x83,0x97}, {0xe3,0x83,0x95,0xe3,0x82,0x9a}}, - {{0xe3,0x83,0x99}, {0xe3,0x83,0x98,0xe3,0x82,0x99}}, - {{0xe3,0x83,0x9a}, {0xe3,0x83,0x98,0xe3,0x82,0x9a}}, - {{0xe3,0x83,0x9c}, {0xe3,0x83,0x9b,0xe3,0x82,0x99}}, - {{0xe3,0x83,0x9d}, {0xe3,0x83,0x9b,0xe3,0x82,0x9a}}, - {{0xe3,0x83,0xb7}, {0xe3,0x83,0xaf,0xe3,0x82,0x99}}, - {{0xe3,0x83,0xb8}, {0xe3,0x83,0xb0,0xe3,0x82,0x99}}, - {{0xe3,0x83,0xb9}, {0xe3,0x83,0xb1,0xe3,0x82,0x99}}, - {{0xe3,0x83,0xba}, {0xe3,0x83,0xb2,0xe3,0x82,0x99}}, - {{0xe3,0x83,0xbe}, {0xe3,0x83,0xbd,0xe3,0x82,0x99}}, -}; -#endif /* UNICODE_NORMALIZATION */ -#endif /* UTF8_INPUT_ENABLE */ - -#ifdef SHIFTJIS_CP932 -const unsigned short shiftjis_cp932[3][189] = { - { - 0xEEEF, 0xEEF0, 0xEEF1, 0xEEF2, 0xEEF3, 0xEEF4, 0xEEF5, 0xEEF6, - 0xEEF7, 0xEEF8, 0x8754, 0x8755, 0x8756, 0x8757, 0x8758, 0x8759, - 0x875A, 0x875B, 0x875C, 0x875D, 0x81CA, 0xEEFA, 0xEEFB, 0xEEFC, - 0x878A, 0x8782, 0x8784, 0x81E6, 0xED40, 0xED41, 0xED42, 0xED43, - 0xED44, 0xED45, 0xED46, 0xED47, 0xED48, 0xED49, 0xED4A, 0xED4B, - 0xED4C, 0xED4D, 0xED4E, 0xED4F, 0xED50, 0xED51, 0xED52, 0xED53, - 0xED54, 0xED55, 0xED56, 0xED57, 0xED58, 0xED59, 0xED5A, 0xED5B, - 0xED5C, 0xED5D, 0xED5E, 0xED5F, 0xED60, 0xED61, 0xED62, 0, - 0xED63, 0xED64, 0xED65, 0xED66, 0xED67, 0xED68, 0xED69, 0xED6A, - 0xED6B, 0xED6C, 0xED6D, 0xED6E, 0xED6F, 0xED70, 0xED71, 0xED72, - 0xED73, 0xED74, 0xED75, 0xED76, 0xED77, 0xED78, 0xED79, 0xED7A, - 0xED7B, 0xED7C, 0xED7D, 0xED7E, 0xED80, 0xED81, 0xED82, 0xED83, - 0xED84, 0xED85, 0xED86, 0xED87, 0xED88, 0xED89, 0xED8A, 0xED8B, - 0xED8C, 0xED8D, 0xED8E, 0xED8F, 0xED90, 0xED91, 0xED92, 0xED93, - 0xED94, 0xED95, 0xED96, 0xED97, 0xED98, 0xED99, 0xED9A, 0xED9B, - 0xED9C, 0xED9D, 0xED9E, 0xED9F, 0xEDA0, 0xEDA1, 0xEDA2, 0xEDA3, - 0xEDA4, 0xEDA5, 0xEDA6, 0xEDA7, 0xEDA8, 0xEDA9, 0xEDAA, 0xEDAB, - 0xEDAC, 0xEDAD, 0xEDAE, 0xEDAF, 0xEDB0, 0xEDB1, 0xEDB2, 0xEDB3, - 0xEDB4, 0xEDB5, 0xEDB6, 0xEDB7, 0xEDB8, 0xEDB9, 0xEDBA, 0xEDBB, - 0xEDBC, 0xEDBD, 0xEDBE, 0xEDBF, 0xEDC0, 0xEDC1, 0xEDC2, 0xEDC3, - 0xEDC4, 0xEDC5, 0xEDC6, 0xEDC7, 0xEDC8, 0xEDC9, 0xEDCA, 0xEDCB, - 0xEDCC, 0xEDCD, 0xEDCE, 0xEDCF, 0xEDD0, 0xEDD1, 0xEDD2, 0xEDD3, - 0xEDD4, 0xEDD5, 0xEDD6, 0xEDD7, 0xEDD8, 0xEDD9, 0xEDDA, 0xEDDB, - 0xEDDC, 0xEDDD, 0xEDDE, 0xEDDF, 0xEDE0, - }, - { - 0xEDE1, 0xEDE2, 0xEDE3, 0xEDE4, 0xEDE5, 0xEDE6, 0xEDE7, 0xEDE8, - 0xEDE9, 0xEDEA, 0xEDEB, 0xEDEC, 0xEDED, 0xEDEE, 0xEDEF, 0xEDF0, - 0xEDF1, 0xEDF2, 0xEDF3, 0xEDF4, 0xEDF5, 0xEDF6, 0xEDF7, 0xEDF8, - 0xEDF9, 0xEDFA, 0xEDFB, 0xEDFC, 0xEE40, 0xEE41, 0xEE42, 0xEE43, - 0xEE44, 0xEE45, 0xEE46, 0xEE47, 0xEE48, 0xEE49, 0xEE4A, 0xEE4B, - 0xEE4C, 0xEE4D, 0xEE4E, 0xEE4F, 0xEE50, 0xEE51, 0xEE52, 0xEE53, - 0xEE54, 0xEE55, 0xEE56, 0xEE57, 0xEE58, 0xEE59, 0xEE5A, 0xEE5B, - 0xEE5C, 0xEE5D, 0xEE5E, 0xEE5F, 0xEE60, 0xEE61, 0xEE62, 0, - 0xEE63, 0xEE64, 0xEE65, 0xEE66, 0xEE67, 0xEE68, 0xEE69, 0xEE6A, - 0xEE6B, 0xEE6C, 0xEE6D, 0xEE6E, 0xEE6F, 0xEE70, 0xEE71, 0xEE72, - 0xEE73, 0xEE74, 0xEE75, 0xEE76, 0xEE77, 0xEE78, 0xEE79, 0xEE7A, - 0xEE7B, 0xEE7C, 0xEE7D, 0xEE7E, 0xEE80, 0xEE81, 0xEE82, 0xEE83, - 0xEE84, 0xEE85, 0xEE86, 0xEE87, 0xEE88, 0xEE89, 0xEE8A, 0xEE8B, - 0xEE8C, 0xEE8D, 0xEE8E, 0xEE8F, 0xEE90, 0xEE91, 0xEE92, 0xEE93, - 0xEE94, 0xEE95, 0xEE96, 0xEE97, 0xEE98, 0xEE99, 0xEE9A, 0xEE9B, - 0xEE9C, 0xEE9D, 0xEE9E, 0xEE9F, 0xEEA0, 0xEEA1, 0xEEA2, 0xEEA3, - 0xEEA4, 0xEEA5, 0xEEA6, 0xEEA7, 0xEEA8, 0xEEA9, 0xEEAA, 0xEEAB, - 0xEEAC, 0xEEAD, 0xEEAE, 0xEEAF, 0xEEB0, 0xEEB1, 0xEEB2, 0xEEB3, - 0xEEB4, 0xEEB5, 0xEEB6, 0xEEB7, 0xEEB8, 0xEEB9, 0xEEBA, 0xEEBB, - 0xEEBC, 0xEEBD, 0xEEBE, 0xEEBF, 0xEEC0, 0xEEC1, 0xEEC2, 0xEEC3, - 0xEEC4, 0xEEC5, 0xEEC6, 0xEEC7, 0xEEC8, 0xEEC9, 0xEECA, 0xEECB, - 0xEECC, 0xEECD, 0xEECE, 0xEECF, 0xEED0, 0xEED1, 0xEED2, 0xEED3, - 0xEED4, 0xEED5, 0xEED6, 0xEED7, 0xEED8, 0xEED9, 0xEEDA, 0xEEDB, - 0xEEDC, 0xEEDD, 0xEEDE, 0xEEDF, 0xEEE0, - }, - { - 0xEEE1, 0xEEE2, 0xEEE3, 0xEEE4, 0xEEE5, 0xEEE6, 0xEEE7, 0xEEE8, - 0xEEE9, 0xEEEA, 0xEEEB, 0xEEEC, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - }, -}; -const unsigned short cp932inv[2][189] = { - { - 0xFA5C, 0xFA5D, 0xFA5E, 0xFA5F, 0xFA60, 0xFA61, 0xFA62, 0xFA63, - 0xFA64, 0xFA65, 0xFA66, 0xFA67, 0xFA68, 0xFA69, 0xFA6A, 0xFA6B, - 0xFA6C, 0xFA6D, 0xFA6E, 0xFA6F, 0xFA70, 0xFA71, 0xFA72, 0xFA73, - 0xFA74, 0xFA75, 0xFA76, 0xFA77, 0xFA78, 0xFA79, 0xFA7A, 0xFA7B, - 0xFA7C, 0xFA7D, 0xFA7E, 0xFA80, 0xFA81, 0xFA82, 0xFA83, 0xFA84, - 0xFA85, 0xFA86, 0xFA87, 0xFA88, 0xFA89, 0xFA8A, 0xFA8B, 0xFA8C, - 0xFA8D, 0xFA8E, 0xFA8F, 0xFA90, 0xFA91, 0xFA92, 0xFA93, 0xFA94, - 0xFA95, 0xFA96, 0xFA97, 0xFA98, 0xFA99, 0xFA9A, 0xFA9B, 0, - 0xFA9C, 0xFA9D, 0xFA9E, 0xFA9F, 0xFAA0, 0xFAA1, 0xFAA2, 0xFAA3, - 0xFAA4, 0xFAA5, 0xFAA6, 0xFAA7, 0xFAA8, 0xFAA9, 0xFAAA, 0xFAAB, - 0xFAAC, 0xFAAD, 0xFAAE, 0xFAAF, 0xFAB0, 0xFAB1, 0xFAB2, 0xFAB3, - 0xFAB4, 0xFAB5, 0xFAB6, 0xFAB7, 0xFAB8, 0xFAB9, 0xFABA, 0xFABB, - 0xFABC, 0xFABD, 0xFABE, 0xFABF, 0xFAC0, 0xFAC1, 0xFAC2, 0xFAC3, - 0xFAC4, 0xFAC5, 0xFAC6, 0xFAC7, 0xFAC8, 0xFAC9, 0xFACA, 0xFACB, - 0xFACC, 0xFACD, 0xFACE, 0xFACF, 0xFAD0, 0xFAD1, 0xFAD2, 0xFAD3, - 0xFAD4, 0xFAD5, 0xFAD6, 0xFAD7, 0xFAD8, 0xFAD9, 0xFADA, 0xFADB, - 0xFADC, 0xFADD, 0xFADE, 0xFADF, 0xFAE0, 0xFAE1, 0xFAE2, 0xFAE3, - 0xFAE4, 0xFAE5, 0xFAE6, 0xFAE7, 0xFAE8, 0xFAE9, 0xFAEA, 0xFAEB, - 0xFAEC, 0xFAED, 0xFAEE, 0xFAEF, 0xFAF0, 0xFAF1, 0xFAF2, 0xFAF3, - 0xFAF4, 0xFAF5, 0xFAF6, 0xFAF7, 0xFAF8, 0xFAF9, 0xFAFA, 0xFAFB, - 0xFAFC, 0xFB40, 0xFB41, 0xFB42, 0xFB43, 0xFB44, 0xFB45, 0xFB46, - 0xFB47, 0xFB48, 0xFB49, 0xFB4A, 0xFB4B, 0xFB4C, 0xFB4D, 0xFB4E, - 0xFB4F, 0xFB50, 0xFB51, 0xFB52, 0xFB53, 0xFB54, 0xFB55, 0xFB56, - 0xFB57, 0xFB58, 0xFB59, 0xFB5A, 0xFB5B, - }, - { - 0xFB5C, 0xFB5D, 0xFB5E, 0xFB5F, 0xFB60, 0xFB61, 0xFB62, 0xFB63, - 0xFB64, 0xFB65, 0xFB66, 0xFB67, 0xFB68, 0xFB69, 0xFB6A, 0xFB6B, - 0xFB6C, 0xFB6D, 0xFB6E, 0xFB6F, 0xFB70, 0xFB71, 0xFB72, 0xFB73, - 0xFB74, 0xFB75, 0xFB76, 0xFB77, 0xFB78, 0xFB79, 0xFB7A, 0xFB7B, - 0xFB7C, 0xFB7D, 0xFB7E, 0xFB80, 0xFB81, 0xFB82, 0xFB83, 0xFB84, - 0xFB85, 0xFB86, 0xFB87, 0xFB88, 0xFB89, 0xFB8A, 0xFB8B, 0xFB8C, - 0xFB8D, 0xFB8E, 0xFB8F, 0xFB90, 0xFB91, 0xFB92, 0xFB93, 0xFB94, - 0xFB95, 0xFB96, 0xFB97, 0xFB98, 0xFB99, 0xFB9A, 0xFB9B, 0, - 0xFB9C, 0xFB9D, 0xFB9E, 0xFB9F, 0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3, - 0xFBA4, 0xFBA5, 0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9, 0xFBAA, 0xFBAB, - 0xFBAC, 0xFBAD, 0xFBAE, 0xFBAF, 0xFBB0, 0xFBB1, 0xFBB2, 0xFBB3, - 0xFBB4, 0xFBB5, 0xFBB6, 0xFBB7, 0xFBB8, 0xFBB9, 0xFBBA, 0xFBBB, - 0xFBBC, 0xFBBD, 0xFBBE, 0xFBBF, 0xFBC0, 0xFBC1, 0xFBC2, 0xFBC3, - 0xFBC4, 0xFBC5, 0xFBC6, 0xFBC7, 0xFBC8, 0xFBC9, 0xFBCA, 0xFBCB, - 0xFBCC, 0xFBCD, 0xFBCE, 0xFBCF, 0xFBD0, 0xFBD1, 0xFBD2, 0xFBD3, - 0xFBD4, 0xFBD5, 0xFBD6, 0xFBD7, 0xFBD8, 0xFBD9, 0xFBDA, 0xFBDB, - 0xFBDC, 0xFBDD, 0xFBDE, 0xFBDF, 0xFBE0, 0xFBE1, 0xFBE2, 0xFBE3, - 0xFBE4, 0xFBE5, 0xFBE6, 0xFBE7, 0xFBE8, 0xFBE9, 0xFBEA, 0xFBEB, - 0xFBEC, 0xFBED, 0xFBEE, 0xFBEF, 0xFBF0, 0xFBF1, 0xFBF2, 0xFBF3, - 0xFBF4, 0xFBF5, 0xFBF6, 0xFBF7, 0xFBF8, 0xFBF9, 0xFBFA, 0xFBFB, - 0xFBFC, 0xFC40, 0xFC41, 0xFC42, 0xFC43, 0xFC44, 0xFC45, 0xFC46, - 0xFC47, 0xFC48, 0xFC49, 0xFC4A, 0xFC4B, 0, 0, 0xFA40, - 0xFA41, 0xFA42, 0xFA43, 0xFA44, 0xFA45, 0xFA46, 0xFA47, 0xFA48, - 0xFA49, 0x81CA, 0xFA55, 0xFA56, 0xFA57, - }, -}; -#endif /* SHIFTJIS_CP932 */ - -#ifdef X0212_ENABLE -const unsigned short shiftjis_x0212[3][189] = { - { - 0xF373, 0xF374, 0xF375, 0xF376, 0xF377, 0xF378, 0xF379, 0xF37A, - 0xF37B, 0xF37C, 0xF37D, 0xF37E, 0xF421, 0xF422, 0xF423, 0xF424, - 0xF425, 0xF426, 0xF427, 0xF428, 0x224C, 0xA243, 0xF429, 0xF42A, - 0xF42B, 0xF42C, 0xF42D, 0x2268, 0xD463, 0xDC5F, 0xE469, 0xE378, - 0xD921, 0xB13B, 0xF42E, 0xC22D, 0xC37C, 0xE450, 0xC23F, 0xBC74, - 0xB029, 0xB048, 0xF42F, 0xB052, 0xB054, 0xB063, 0xB06E, 0xB127, - 0xB123, 0xB12C, 0xB129, 0xB13E, 0xB15F, 0xB158, 0xB148, 0xB157, - 0xB163, 0xB174, 0xB161, 0xB223, 0xF430, 0xB23B, 0xB266, 0, - 0xB26D, 0xB275, 0xB27C, 0xF431, 0xB335, 0xB358, 0xB35B, 0xB365, - 0xB36E, 0xB37B, 0xF432, 0xF433, 0xB440, 0xB447, 0xB450, 0xB45E, - 0xF434, 0xB52A, 0xF435, 0xB52F, 0xB544, 0xB568, 0xF436, 0xB742, - 0xB764, 0xB768, 0xB767, 0xF437, 0xF438, 0xF439, 0xB84E, 0xB861, - 0xB875, 0xB877, 0xB878, 0xB87C, 0xB92F, 0xB937, 0xBA3E, 0xBA5B, - 0xCD2A, 0xBA61, 0xF43A, 0xBA6B, 0xBB33, 0xBB38, 0xF43B, 0xBB4A, - 0xF43C, 0xF43D, 0xBB50, 0xBB5E, 0xBB74, 0xBB75, 0xBB79, 0xBC64, - 0xBC6D, 0xBC7E, 0xF43E, 0xBD42, 0xBD67, 0xF43F, 0xBD70, 0xBE30, - 0xBE2C, 0xF440, 0xBE33, 0xBE3D, 0xBE4D, 0xBE49, 0xBE64, 0xBF28, - 0xBF49, 0xC044, 0xC064, 0xC074, 0xC126, 0xF441, 0xC175, 0xC17C, - 0xF442, 0xC178, 0xC22B, 0xC221, 0xC225, 0xF443, 0xC238, 0xC23A, - 0xF444, 0xC244, 0xC252, 0xC257, 0xC25B, 0xC25E, 0xC26D, 0xC270, - 0xF445, 0xC321, 0xC335, 0xC349, 0xC339, 0xF446, 0xC358, 0xC37E, - 0xF447, 0xC44C, 0xF448, 0xC459, 0xC46A, 0xC47D, 0xF449, 0xC527, - 0xC535, 0xC536, 0xF44A, 0xC555, 0xC638, 0xC657, 0xC660, 0xC66A, - 0xC663, 0xC721, 0xC72B, 0xC747, 0xC743, - }, - { - 0xC74B, 0xC74F, 0xC759, 0xF44B, 0xF44C, 0xC766, 0xC76E, 0xC77C, - 0xC76B, 0xC770, 0xC831, 0xC865, 0xC878, 0xC926, 0xC92B, 0xC92D, - 0xF44D, 0xC94A, 0xC953, 0xC969, 0xC963, 0xC97C, 0xC974, 0xC975, - 0xF44E, 0xCA33, 0xCA3D, 0xCA6F, 0xCA71, 0xCB2E, 0xF44F, 0xCB4A, - 0xCB66, 0xCB6A, 0xCB70, 0xCB74, 0xCB6E, 0xCC25, 0xCB79, 0xCC2B, - 0xCC2E, 0xCC2D, 0xCC32, 0xCC42, 0xCC50, 0xCC59, 0xF450, 0xCD3B, - 0xF451, 0xCE3B, 0xF452, 0xCE3A, 0xCE43, 0xF453, 0xCE72, 0xB35D, - 0xCF55, 0xCF62, 0xCF69, 0xCF6D, 0xF454, 0xF455, 0xF456, 0, - 0xF457, 0xD065, 0xF458, 0xD069, 0xD168, 0xF459, 0xF45A, 0xD16C, - 0xD23B, 0xF45B, 0xD361, 0xD368, 0xD427, 0xF45C, 0xF45D, 0xD454, - 0xD472, 0xD52E, 0xF45E, 0xD75E, 0xF45F, 0xD822, 0xD837, 0xD841, - 0xD851, 0xD874, 0xD946, 0xD948, 0xD951, 0xF460, 0xF461, 0xF462, - 0xF463, 0xF464, 0xDC53, 0xDD48, 0xDD54, 0xDD6A, 0xDD7A, 0xDE24, - 0xDE30, 0xF465, 0xDE35, 0xDE4B, 0xF466, 0xDF39, 0xF467, 0xDF43, - 0xF468, 0xF469, 0xE059, 0xF46A, 0xF46B, 0xE162, 0xF46C, 0xF46D, - 0xF46E, 0xE247, 0xE328, 0xE326, 0xE329, 0xE32F, 0xE330, 0xE32A, - 0xE32B, 0xE33C, 0xE341, 0xE33F, 0xE355, 0xE358, 0xE356, 0xE35F, - 0xE363, 0xE361, 0xE354, 0xE369, 0xE426, 0xE371, 0xE372, 0xE44B, - 0xE441, 0xE443, 0xE43E, 0xF46F, 0xE440, 0xE447, 0xE43F, 0xE460, - 0xE45E, 0xE451, 0xF470, 0xE45C, 0xE452, 0xE45B, 0xE454, 0xE47A, - 0xE46F, 0xE533, 0xE53F, 0xE549, 0xE550, 0xE562, 0xE56A, 0xE56B, - 0xF471, 0xF472, 0xF473, 0xE668, 0xE66F, 0xE72C, 0xF474, 0xE72E, - 0xF475, 0xE731, 0xF476, 0xE732, 0xE831, 0xE836, 0xF477, 0xF478, - 0xE85D, 0xF479, 0xF47A, 0xE951, 0xF47B, - }, - { - 0xE96D, 0xEA4D, 0xF47C, 0xEA5B, 0xEA66, 0xEA6A, 0xEB25, 0xEB7B, - 0xEB7A, 0xF47D, 0xEC56, 0xF47E, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 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 unsigned short x0212_shiftjis_A2[] = { - 0x819F, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x8143, 0, 0, 0x8150, 0, 0, 0x8160, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFA55, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short x0212_shiftjis_B0[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0xFA68, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFA69, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFA6B, 0, 0xFA6C, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFA6D, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFA6E, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_B1[] = { - 0, 0, 0xFA70, 0, 0, 0, 0xFA6F, - 0, 0xFA72, 0, 0, 0xFA71, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFA61, 0, 0, 0xFA73, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFA76, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xFA77, - 0xFA75, 0, 0, 0, 0, 0, 0, 0xFA74, - 0, 0xFA7A, 0, 0xFA78, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFA79, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_B2[] = { - 0, 0, 0xFA7B, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFA7D, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFA7E, 0, - 0, 0, 0, 0, 0, 0xFA80, 0, 0, - 0, 0, 0, 0, 0, 0xFA81, 0, 0, - 0, 0, 0, 0, 0xFA82, 0, 0, -}; -static const unsigned short x0212_shiftjis_B3[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFA84, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFA85, 0, 0, 0xFA86, 0, 0xFB77, 0, 0, - 0, 0, 0, 0, 0, 0xFA87, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFA88, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFA89, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_B4[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFA8C, 0, 0, 0, 0, 0, 0, 0xFA8D, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFA8E, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFA8F, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short x0212_shiftjis_B5[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFA91, 0, 0, 0, 0, 0xFA93, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFA94, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFA95, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_B7[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFA97, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFA98, 0, 0, 0xFA9A, - 0xFA99, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_B8[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFA9E, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFA9F, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFAA0, 0, 0xFAA1, - 0xFAA2, 0, 0, 0, 0xFAA3, 0, 0, -}; -static const unsigned short x0212_shiftjis_B9[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xFAA4, - 0, 0, 0, 0, 0, 0, 0, 0xFAA5, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short x0212_shiftjis_BA[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFAA6, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFAA7, 0, 0, 0, 0, - 0, 0xFAA9, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFAAB, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_BB[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFAAC, 0, 0, 0, 0, - 0xFAAD, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFAAF, 0, 0, 0, 0, 0, - 0xFAB2, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFAB3, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFAB4, 0xFAB5, 0, 0, - 0, 0xFAB6, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_BC[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFAB7, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFAB8, 0, 0, - 0, 0, 0, 0, 0xFA67, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFAB9, -}; -static const unsigned short x0212_shiftjis_BD[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFABB, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xFABC, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFABE, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_BE[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFAC0, 0, 0, 0, - 0xFABF, 0, 0, 0xFAC2, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFAC3, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFAC5, 0, 0, 0, 0xFAC4, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFAC6, 0, 0, 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 unsigned short x0212_shiftjis_BF[] = { - 0, 0, 0, 0, 0, 0, 0, - 0xFAC7, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFAC8, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short x0212_shiftjis_C0[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFAC9, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFACA, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFACB, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_C1[] = { - 0, 0, 0, 0, 0, 0xFACC, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFACE, 0, 0, - 0xFAD1, 0, 0, 0, 0xFACF, 0, 0, -}; -static const unsigned short x0212_shiftjis_C2[] = { - 0xFAD3, 0, 0, 0, 0xFAD4, 0, 0, - 0, 0, 0, 0xFAD2, 0, 0xFA63, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFAD6, 0, 0xFAD7, 0, 0, 0, 0, 0xFA66, - 0, 0, 0, 0, 0xFAD9, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFADA, 0, 0, 0, 0, 0xFADB, - 0, 0, 0, 0xFADC, 0, 0, 0xFADD, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFADE, 0, 0, - 0xFADF, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_C3[] = { - 0xFAE1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFAE2, 0, 0, - 0, 0xFAE4, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFAE3, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFAE6, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFA64, 0, 0xFAE7, -}; -static const unsigned short x0212_shiftjis_C4[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFAE9, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFAEB, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFAEC, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFAED, 0, -}; -static const unsigned short x0212_shiftjis_C5[] = { - 0, 0, 0, 0, 0, 0, 0xFAEF, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFAF0, 0xFAF1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFAF3, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short x0212_shiftjis_C6[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFAF4, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xFAF5, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFAF6, 0, 0, 0xFAF8, 0, 0, 0, 0, - 0, 0, 0xFAF7, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_C7[] = { - 0xFAF9, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFAFA, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFAFC, 0, 0, 0, 0xFAFB, - 0, 0, 0, 0xFB40, 0, 0, 0, 0xFB41, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFB42, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFB45, 0, - 0, 0, 0, 0xFB48, 0, 0, 0xFB46, 0, - 0xFB49, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFB47, 0, 0, -}; -static const unsigned short x0212_shiftjis_C8[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFB4A, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFB4B, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFB4C, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_C9[] = { - 0, 0, 0, 0, 0, 0xFB4D, 0, - 0, 0, 0, 0xFB4E, 0, 0xFB4F, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFB51, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFB52, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFB54, 0, 0, 0, 0, - 0, 0xFB53, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFB56, 0xFB57, 0, 0, - 0, 0, 0, 0, 0xFB55, 0, 0, -}; -static const unsigned short x0212_shiftjis_CA[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFB59, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFB5A, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xFB5B, - 0, 0xFB5C, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_CB[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFB5D, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFB5F, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFB60, 0, - 0, 0, 0xFB61, 0, 0, 0, 0xFB64, 0, - 0xFB62, 0, 0, 0, 0xFB63, 0, 0, 0, - 0, 0xFB66, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_CC[] = { - 0, 0, 0, 0, 0xFB65, 0, 0, - 0, 0, 0, 0xFB67, 0, 0xFB69, 0xFB68, 0, - 0, 0, 0xFB6A, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFB6B, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFB6C, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFB6D, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short x0212_shiftjis_CD[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFAA8, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFB6F, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short x0212_shiftjis_CE[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFB73, 0xFB71, 0, 0, 0, 0, - 0, 0, 0, 0xFB74, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFB76, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_CF[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFB78, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFB79, 0, 0, 0, 0, 0, - 0, 0xFB7A, 0, 0, 0, 0xFB7B, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_D0[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFB81, 0, 0, - 0, 0xFB83, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_D1[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFB84, 0, 0, 0, 0xFB87, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_D2[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFB88, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short x0212_shiftjis_D3[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFB8A, 0, 0, 0, 0, 0, 0, - 0xFB8B, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_D4[] = { - 0, 0, 0, 0, 0, 0, 0xFB8C, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFB8F, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFA5C, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFB90, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_D5[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFB91, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short x0212_shiftjis_D7[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFB93, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short x0212_shiftjis_D8[] = { - 0, 0xFB95, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xFB96, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFB97, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFB98, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFB99, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_D9[] = { - 0xFA60, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFB9A, 0, - 0xFB9B, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFB9C, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short x0212_shiftjis_DC[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFBA2, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xFA5D, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short x0212_shiftjis_DD[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFBA3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFBA4, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFBA5, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFBA6, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_DE[] = { - 0, 0, 0, 0xFBA7, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFBA8, 0, 0, 0, 0, 0xFBAA, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFBAB, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short x0212_shiftjis_DF[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFBAD, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFBAF, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short x0212_shiftjis_E0[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFBB2, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short x0212_shiftjis_E1[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFBB5, 0, 0, 0, 0, 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 unsigned short x0212_shiftjis_E2[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xFBB9, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short x0212_shiftjis_E3[] = { - 0, 0, 0, 0, 0, 0xFBBB, 0, - 0xFBBA, 0xFBBC, 0xFBBF, 0xFBC0, 0, 0, 0, 0xFBBD, - 0xFBBE, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFBC1, 0, 0, 0xFBC3, - 0, 0xFBC2, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFBCA, 0xFBC4, 0xFBC6, 0, - 0xFBC5, 0, 0, 0, 0, 0, 0, 0xFBC7, - 0, 0xFBC9, 0, 0xFBC8, 0, 0, 0, 0, - 0, 0xFBCB, 0, 0, 0, 0, 0, 0, - 0, 0xFBCD, 0xFBCE, 0, 0, 0, 0, 0, - 0xFA5F, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_E4[] = { - 0, 0, 0, 0, 0, 0xFBCC, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFBD2, 0xFBD6, - 0xFBD4, 0xFBD0, 0, 0xFBD1, 0, 0, 0, 0xFBD5, - 0, 0, 0, 0xFBCF, 0, 0, 0, 0, - 0xFA65, 0xFBD9, 0xFBDC, 0, 0xFBDE, 0, 0, 0, - 0, 0, 0, 0xFBDD, 0xFBDB, 0, 0xFBD8, 0, - 0xFBD7, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFA5E, 0, 0, 0, 0, 0, 0xFBE0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFBDF, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_E5[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFBE1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xFBE2, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFBE3, 0, 0, 0, 0, 0, 0, - 0xFBE4, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFBE5, 0, 0, 0, 0, 0, - 0, 0, 0xFBE6, 0xFBE7, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_E6[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFBEB, 0, 0, 0, 0, 0, 0, 0xFBEC, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_E7[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFBED, 0, 0xFBEF, 0, - 0, 0xFBF1, 0xFBF3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short x0212_shiftjis_E8[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFBF4, 0, 0, 0, 0, 0xFBF5, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFBF8, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short x0212_shiftjis_E9[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFBFB, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFC40, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_EA[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFC41, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFC43, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFC44, 0, - 0, 0, 0xFC45, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_EB[] = { - 0, 0, 0, 0, 0xFC46, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFC48, 0xFC47, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_EC[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFC4A, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 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 unsigned short x0212_shiftjis_F3[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFA40, 0xFA41, 0xFA42, 0xFA43, 0xFA44, - 0xFA45, 0xFA46, 0xFA47, 0xFA48, 0xFA49, 0xFA4A, 0xFA4B, -}; -static const unsigned short x0212_shiftjis_F4[] = { - 0xFA4C, 0xFA4D, 0xFA4E, 0xFA4F, 0xFA50, 0xFA51, 0xFA52, - 0xFA53, 0xFA56, 0xFA57, 0xFA58, 0xFA59, 0xFA5A, 0xFA62, 0xFA6A, - 0xFA7C, 0xFA83, 0xFA8A, 0xFA8B, 0xFA90, 0xFA92, 0xFA96, 0xFA9B, - 0xFA9C, 0xFA9D, 0xFAAA, 0xFAAE, 0xFAB0, 0xFAB1, 0xFABA, 0xFABD, - 0xFAC1, 0xFACD, 0xFAD0, 0xFAD5, 0xFAD8, 0xFAE0, 0xFAE5, 0xFAE8, - 0xFAEA, 0xFAEE, 0xFAF2, 0xFB43, 0xFB44, 0xFB50, 0xFB58, 0xFB5E, - 0xFB6E, 0xFB70, 0xFB72, 0xFB75, 0xFB7C, 0xFB7D, 0xFB7E, 0xFB80, - 0xFB82, 0xFB85, 0xFB86, 0xFB89, 0xFB8D, 0xFB8E, 0xFB92, 0xFB94, - 0xFB9D, 0xFB9E, 0xFB9F, 0xFBA0, 0xFBA1, 0xFBA9, 0xFBAC, 0xFBAE, - 0xFBB0, 0xFBB1, 0xFBB3, 0xFBB4, 0xFBB6, 0xFBB7, 0xFBB8, 0xFBD3, - 0xFBDA, 0xFBE8, 0xFBE9, 0xFBEA, 0xFBEE, 0xFBF0, 0xFBF2, 0xFBF6, - 0xFBF7, 0xFBF9, 0xFBFA, 0xFBFC, 0xFC42, 0xFC49, 0xFC4B, -}; -const unsigned short *const x0212_shiftjis[] = { - 0, x0212_shiftjis_A2, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - x0212_shiftjis_B0, x0212_shiftjis_B1, x0212_shiftjis_B2, x0212_shiftjis_B3, - x0212_shiftjis_B4, x0212_shiftjis_B5, 0, x0212_shiftjis_B7, - x0212_shiftjis_B8, x0212_shiftjis_B9, x0212_shiftjis_BA, x0212_shiftjis_BB, - x0212_shiftjis_BC, x0212_shiftjis_BD, x0212_shiftjis_BE, x0212_shiftjis_BF, - x0212_shiftjis_C0, x0212_shiftjis_C1, x0212_shiftjis_C2, x0212_shiftjis_C3, - x0212_shiftjis_C4, x0212_shiftjis_C5, x0212_shiftjis_C6, x0212_shiftjis_C7, - x0212_shiftjis_C8, x0212_shiftjis_C9, x0212_shiftjis_CA, x0212_shiftjis_CB, - x0212_shiftjis_CC, x0212_shiftjis_CD, x0212_shiftjis_CE, x0212_shiftjis_CF, - x0212_shiftjis_D0, x0212_shiftjis_D1, x0212_shiftjis_D2, x0212_shiftjis_D3, - x0212_shiftjis_D4, x0212_shiftjis_D5, 0, x0212_shiftjis_D7, - x0212_shiftjis_D8, x0212_shiftjis_D9, 0, 0, - x0212_shiftjis_DC, x0212_shiftjis_DD, x0212_shiftjis_DE, x0212_shiftjis_DF, - x0212_shiftjis_E0, x0212_shiftjis_E1, x0212_shiftjis_E2, x0212_shiftjis_E3, - x0212_shiftjis_E4, x0212_shiftjis_E5, x0212_shiftjis_E6, x0212_shiftjis_E7, - x0212_shiftjis_E8, x0212_shiftjis_E9, x0212_shiftjis_EA, x0212_shiftjis_EB, - x0212_shiftjis_EC, 0, 0, 0, - 0, 0, 0, x0212_shiftjis_F3, - x0212_shiftjis_F4, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, -}; -#endif /* X0212_ENABLE */ diff --git a/ext/nkf/nkf-utf8/utf8tbl.h b/ext/nkf/nkf-utf8/utf8tbl.h deleted file mode 100644 index 54a34271ddc02c..00000000000000 --- a/ext/nkf/nkf-utf8/utf8tbl.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * utf8tbl.h - Header file for Conversion Table - * - */ - -#ifndef _UTF8TBL_H_ -#define _UTF8TBL_H_ - -#ifdef UTF8_OUTPUT_ENABLE -#define sizeof_euc_to_utf8_1byte 94 -#define sizeof_euc_to_utf8_2bytes 94 -extern const unsigned short euc_to_utf8_1byte[]; -extern const unsigned short *const euc_to_utf8_2bytes[]; -extern const unsigned short *const euc_to_utf8_2bytes_ms[]; -extern const unsigned short *const euc_to_utf8_2bytes_mac[]; -extern const unsigned short *const euc_to_utf8_2bytes_x0213[]; -extern const unsigned short *const x0212_to_utf8_2bytes[]; -extern const unsigned short *const x0212_to_utf8_2bytes_x0213[]; -#define sizeof_x0213_combining_chars 5 -#define sizeof_x0213_combining_table 25 -#define sizeof_x0213_1_surrogate_table 26 -#define sizeof_x0213_2_surrogate_table 277 -extern const unsigned short x0213_combining_chars[sizeof_x0213_combining_chars]; -extern const unsigned short x0213_combining_table[sizeof_x0213_combining_table][3]; -extern const unsigned short x0213_1_surrogate_table[sizeof_x0213_1_surrogate_table][3]; -extern const unsigned short x0213_2_surrogate_table[sizeof_x0213_2_surrogate_table][3]; -#endif /* UTF8_OUTPUT_ENABLE */ - -#ifdef UTF8_INPUT_ENABLE -#define sizeof_utf8_to_euc_C2 64 -#define sizeof_utf8_to_euc_E5B8 64 -#define sizeof_utf8_to_euc_2bytes 112 -#define sizeof_utf8_to_euc_3bytes 16 -extern const unsigned short *const utf8_to_euc_2bytes[]; -extern const unsigned short *const utf8_to_euc_2bytes_ms[]; -extern const unsigned short *const utf8_to_euc_2bytes_932[]; -extern const unsigned short *const utf8_to_euc_2bytes_mac[]; -extern const unsigned short *const utf8_to_euc_2bytes_x0213[]; -extern const unsigned short *const *const utf8_to_euc_3bytes[]; -extern const unsigned short *const *const utf8_to_euc_3bytes_ms[]; -extern const unsigned short *const *const utf8_to_euc_3bytes_932[]; -extern const unsigned short *const *const utf8_to_euc_3bytes_mac[]; -extern const unsigned short *const *const utf8_to_euc_3bytes_x0213[]; -#endif /* UTF8_INPUT_ENABLE */ - -#ifdef UNICODE_NORMALIZATION - -#define NORMALIZATION_TABLE_LENGTH 942 -#define NORMALIZATION_TABLE_NFC_LENGTH 3 -#define NORMALIZATION_TABLE_NFD_LENGTH 9 -struct normalization_pair { - const unsigned char nfc[NORMALIZATION_TABLE_NFC_LENGTH]; - const unsigned char nfd[NORMALIZATION_TABLE_NFD_LENGTH]; -}; -extern const struct normalization_pair normalization_table[]; -#endif - -#ifdef SHIFTJIS_CP932 -#define CP932_TABLE_BEGIN 0xFA -#define CP932_TABLE_END 0xFC -extern const unsigned short shiftjis_cp932[3][189]; -#define CP932INV_TABLE_BEGIN 0xED -#define CP932INV_TABLE_END 0xEE -extern const unsigned short cp932inv[2][189]; -#endif /* SHIFTJIS_CP932 */ - -#ifdef X0212_ENABLE -extern const unsigned short shiftjis_x0212[3][189]; -extern const unsigned short *const x0212_shiftjis[]; -#endif /* X0212_ENABLE */ - -#endif diff --git a/ext/nkf/nkf.c b/ext/nkf/nkf.c deleted file mode 100644 index 3d1ad42e9f457e..00000000000000 --- a/ext/nkf/nkf.c +++ /dev/null @@ -1,506 +0,0 @@ -/* - * NKF - Ruby extension for Network Kanji Filter - * - * original nkf2.x is maintained at http://sourceforge.jp/projects/nkf/ - * - * $Id$ - * - */ - -#define RUBY_NKF_REVISION "$Revision$" -#define RUBY_NKF_VERSION NKF_VERSION " (" NKF_RELEASE_DATE ")" -#define NKF_GEM_VERSION "0.2.0" - -#include "ruby/ruby.h" -#include "ruby/encoding.h" - -/* Replace nkf's getchar/putchar for variable modification */ -/* we never use getc, ungetc */ - -#undef getc -#undef ungetc -#define getc(f) (input_ctr>=i_len?-1:input[input_ctr++]) -#define ungetc(c,f) input_ctr-- - -#define INCSIZE 32 -#undef putchar -#undef TRUE -#undef FALSE -#define putchar(c) rb_nkf_putchar(c) - -/* Input/Output pointers */ - -static unsigned char *output; -static unsigned char *input; -static int input_ctr; -static int i_len; -static int output_ctr; -static int o_len; -static int incsize; - -static VALUE result; - -static int -rb_nkf_putchar(unsigned int c) -{ - if (output_ctr >= o_len) { - o_len += incsize; - rb_str_resize(result, o_len); - incsize *= 2; - output = (unsigned char *)RSTRING_PTR(result); - } - output[output_ctr++] = c; - - return c; -} - -/* Include kanji filter main part */ -/* getchar and putchar will be replaced during inclusion */ - -#define PERL_XS 1 -#include "nkf-utf8/config.h" -#include "nkf-utf8/utf8tbl.c" -#include "nkf-utf8/nkf.c" - -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); - } - } - return rb_enc_from_index(idx); -} - -int nkf_split_options(const char *arg) -{ - int count = 0; - unsigned char option[256]; - int i = 0, j = 0; - int is_escaped = FALSE; - 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){ - option[j] = '\0'; - options(option); - } - return count; -} - -/* - * call-seq: - * NKF.nkf(opt, str) => string - * - * Convert _str_ and return converted result. - * Conversion details are specified by _opt_ as String. - * - * require 'nkf' - * output = NKF.nkf("-s", input) - */ - -static VALUE -rb_nkf_convert(VALUE obj, VALUE opt, VALUE src) -{ - VALUE tmp; - reinit(); - nkf_split_options(StringValueCStr(opt)); - if (!output_encoding) rb_raise(rb_eArgError, "no output encoding given"); - - switch (nkf_enc_to_index(output_encoding)) { - case UTF_8_BOM: output_encoding = nkf_enc_from_index(UTF_8); break; - case UTF_16BE_BOM: output_encoding = nkf_enc_from_index(UTF_16BE); break; - case UTF_16LE_BOM: output_encoding = nkf_enc_from_index(UTF_16LE); break; - case UTF_32BE_BOM: output_encoding = nkf_enc_from_index(UTF_32BE); break; - case UTF_32LE_BOM: output_encoding = nkf_enc_from_index(UTF_32LE); break; - } - output_bom_f = FALSE; - - incsize = INCSIZE; - - input_ctr = 0; - input = (unsigned char *)StringValuePtr(src); - i_len = RSTRING_LENINT(src); - tmp = rb_str_new(0, i_len*3 + 10); - - output_ctr = 0; - output = (unsigned char *)RSTRING_PTR(tmp); - o_len = RSTRING_LENINT(tmp); - *output = '\0'; - - /* use _result_ begin*/ - result = tmp; - kanji_convert(NULL); - result = Qnil; - /* use _result_ end */ - - rb_str_set_len(tmp, output_ctr); - - if (mimeout_f) - rb_enc_associate(tmp, rb_usascii_encoding()); - else - rb_enc_associate(tmp, rb_nkf_enc_get(nkf_enc_name(output_encoding))); - - return tmp; -} - - -/* - * call-seq: - * NKF.guess(str) => encoding - * - * Returns guessed encoding of _str_ by nkf routine. - * - */ - -static VALUE -rb_nkf_guess(VALUE obj, VALUE src) -{ - reinit(); - - input_ctr = 0; - input = (unsigned char *)StringValuePtr(src); - i_len = RSTRING_LENINT(src); - - guess_f = TRUE; - kanji_convert( NULL ); - guess_f = FALSE; - - return rb_enc_from_encoding(rb_nkf_enc_get(get_guessed_code())); -} - - -/* - * NKF - Ruby extension for Network Kanji Filter - * - * == Description - * - * This is a Ruby Extension version of nkf (Network Kanji Filter). - * It converts the first argument and returns converted result. Conversion - * details are specified by flags as the first argument. - * - * *Nkf* is a yet another kanji code converter among networks, hosts and terminals. - * It converts input kanji code to designated kanji code - * such as ISO-2022-JP, Shift_JIS, EUC-JP, UTF-8 or UTF-16. - * - * One of the most unique faculty of *nkf* is the guess of the input kanji encodings. - * It currently recognizes ISO-2022-JP, Shift_JIS, EUC-JP, UTF-8 and UTF-16. - * So users needn't set the input kanji code explicitly. - * - * By default, X0201 kana is converted into X0208 kana. - * For X0201 kana, SO/SI, SSO and ESC-(-I methods are supported. - * For automatic code detection, nkf assumes no X0201 kana in Shift_JIS. - * To accept X0201 in Shift_JIS, use -X, -x or -S. - * - * == Flags - * - * === -b -u - * - * Output is buffered (DEFAULT), Output is unbuffered. - * - * === -j -s -e -w -w16 -w32 - * - * Output code is ISO-2022-JP (7bit JIS), Shift_JIS, EUC-JP, - * UTF-8N, UTF-16BE, UTF-32BE. - * Without this option and compile option, ISO-2022-JP is assumed. - * - * === -J -S -E -W -W16 -W32 - * - * Input assumption is JIS 7 bit, Shift_JIS, EUC-JP, - * UTF-8, UTF-16, UTF-32. - * - * ==== -J - * - * Assume JIS input. It also accepts EUC-JP. - * This is the default. This flag does not exclude Shift_JIS. - * - * ==== -S - * - * Assume Shift_JIS and X0201 kana input. It also accepts JIS. - * EUC-JP is recognized as X0201 kana. Without -x flag, - * X0201 kana (halfwidth kana) is converted into X0208. - * - * ==== -E - * - * Assume EUC-JP input. It also accepts JIS. - * Same as -J. - * - * === -t - * - * No conversion. - * - * === -i_ - * - * Output sequence to designate JIS-kanji. (DEFAULT B) - * - * === -o_ - * - * Output sequence to designate ASCII. (DEFAULT B) - * - * === -r - * - * {de/en}crypt ROT13/47 - * - * === \-h[123] --hiragana --katakana --katakana-hiragana - * - * [-h1 --hiragana] Katakana to Hiragana conversion. - * - * [-h2 --katakana] Hiragana to Katakana conversion. - * - * [-h3 --katakana-hiragana] Katakana to Hiragana and Hiragana to Katakana conversion. - * - * === -T - * - * Text mode output (MS-DOS) - * - * === -l - * - * ISO8859-1 (Latin-1) support - * - * === -f[m [- n]] - * - * Folding on m length with n margin in a line. - * Without this option, fold length is 60 and fold margin is 10. - * - * === -F - * - * New line preserving line folding. - * - * === \-Z[0-3] - * - * Convert X0208 alphabet (Fullwidth Alphabets) to ASCII. - * - * [-Z -Z0] Convert X0208 alphabet to ASCII. - * - * [-Z1] Converts X0208 kankaku to single ASCII space. - * - * [-Z2] Converts X0208 kankaku to double ASCII spaces. - * - * [-Z3] Replacing Fullwidth >, <, ", & into '>', '<', '"', '&' as in HTML. - * - * === -X -x - * - * Assume X0201 kana in MS-Kanji. - * With -X or without this option, X0201 is converted into X0208 Kana. - * With -x, 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] - * - * Assume broken JIS-Kanji input, which lost ESC. - * Useful when your site is using old B-News Nihongo patch. - * - * [-B1] allows any char after ESC-( or ESC-$. - * - * [-B2] forces ASCII after NL. - * - * === -I - * - * Replacing non iso-2022-jp char into a geta character - * (substitute character in Japanese). - * - * === -d -c - * - * Delete \r in line feed, Add \r in line feed. - * - * === \-m[BQN0] - * - * MIME ISO-2022-JP/ISO8859-1 decode. (DEFAULT) - * To see ISO8859-1 (Latin-1) -l is necessary. - * - * [-mB] Decode MIME base64 encoded stream. Remove header or other part before - * conversion. - * - * [-mQ] Decode MIME quoted stream. '_' in quoted stream is converted to space. - * - * [-mN] Non-strict decoding. - * It allows line break in the middle of the base64 encoding. - * - * [-m0] No MIME decode. - * - * === -M - * - * MIME encode. Header style. All ASCII code and control characters are intact. - * Kanji conversion is performed before encoding, so this cannot be used as a picture encoder. - * - * [-MB] MIME encode Base64 stream. - * - * [-MQ] Perform quoted encoding. - * - * === -l - * - * Input and output code is ISO8859-1 (Latin-1) and ISO-2022-JP. - * -s, -e and -x are not compatible with this option. - * - * === \-L[uwm] - * - * new line mode - * Without this option, nkf doesn't convert line breaks. - * - * [-Lu] unix (LF) - * - * [-Lw] windows (CRLF) - * - * [-Lm] mac (CR) - * - * === --fj --unix --mac --msdos --windows - * - * convert for these system - * - * === --jis --euc --sjis --mime --base64 - * - * convert for named code - * - * === --jis-input --euc-input --sjis-input --mime-input --base64-input - * - * assume input system - * - * === --ic=input codeset --oc=output codeset - * - * Set the input or output codeset. - * NKF supports following codesets and those codeset name are case insensitive. - * - * [ISO-2022-JP] a.k.a. RFC1468, 7bit JIS, JUNET - * - * [EUC-JP (eucJP-nkf)] a.k.a. AT&T JIS, Japanese EUC, UJIS - * - * [eucJP-ascii] a.k.a. x-eucjp-open-19970715-ascii - * - * [eucJP-ms] a.k.a. x-eucjp-open-19970715-ms - * - * [CP51932] Microsoft Version of EUC-JP. - * - * [Shift_JIS] SJIS, MS-Kanji - * - * [Windows-31J] a.k.a. CP932 - * - * [UTF-8] same as UTF-8N - * - * [UTF-8N] UTF-8 without BOM - * - * [UTF-8-BOM] UTF-8 with BOM - * - * [UTF-16] same as UTF-16BE - * - * [UTF-16BE] UTF-16 Big Endian without BOM - * - * [UTF-16BE-BOM] UTF-16 Big Endian with BOM - * - * [UTF-16LE] UTF-16 Little Endian without BOM - * - * [UTF-16LE-BOM] UTF-16 Little Endian with BOM - * - * [UTF-32] same as UTF-32BE - * - * [UTF-32BE] UTF-32 Big Endian without BOM - * - * [UTF-32BE-BOM] UTF-32 Big Endian with BOM - * - * [UTF-32LE] UTF-32 Little Endian without BOM - * - * [UTF-32LE-BOM] UTF-32 Little Endian with BOM - * - * [UTF8-MAC] NKDed UTF-8, a.k.a. UTF8-NFD (input only) - * - * === --fb-{skip, html, xml, perl, java, subchar} - * - * Specify the way that nkf handles unassigned characters. - * Without this option, --fb-skip is assumed. - * - * === --prefix= escape character target character .. - * - * When nkf converts to Shift_JIS, - * nkf adds a specified escape character to specified 2nd byte of Shift_JIS characters. - * 1st byte of argument is the escape character and following bytes are target characters. - * - * === --no-cp932ext - * - * Handle the characters extended in CP932 as unassigned characters. - * - * == --no-best-fit-chars - * - * When Unicode to Encoded byte conversion, - * don't convert characters which is not round trip safe. - * When Unicode to Unicode conversion, - * with this and -x option, nkf can be used as UTF converter. - * (In other words, without this and -x option, nkf doesn't save some characters) - * - * When nkf convert string which related to path, you should use this option. - * - * === --cap-input - * - * Decode hex encoded characters. - * - * === --url-input - * - * Unescape percent escaped characters. - * - * === -- - * - * Ignore rest of -option. - */ - -void -Init_nkf(void) -{ - VALUE mNKF = rb_define_module("NKF"); - - rb_define_module_function(mNKF, "nkf", rb_nkf_convert, 2); - rb_define_module_function(mNKF, "guess", rb_nkf_guess, 1); - rb_define_alias(rb_singleton_class(mNKF), "guess", "guess"); - - rb_define_const(mNKF, "AUTO", Qnil); - rb_define_const(mNKF, "NOCONV", Qnil); - rb_define_const(mNKF, "UNKNOWN", Qnil); - rb_define_const(mNKF, "BINARY", rb_enc_from_encoding(rb_nkf_enc_get("BINARY"))); - rb_define_const(mNKF, "ASCII", rb_enc_from_encoding(rb_nkf_enc_get("US-ASCII"))); - rb_define_const(mNKF, "JIS", rb_enc_from_encoding(rb_nkf_enc_get("ISO-2022-JP"))); - rb_define_const(mNKF, "EUC", rb_enc_from_encoding(rb_nkf_enc_get("EUC-JP"))); - rb_define_const(mNKF, "SJIS", rb_enc_from_encoding(rb_nkf_enc_get("Shift_JIS"))); - rb_define_const(mNKF, "UTF8", rb_enc_from_encoding(rb_utf8_encoding())); - rb_define_const(mNKF, "UTF16", rb_enc_from_encoding(rb_nkf_enc_get("UTF-16BE"))); - rb_define_const(mNKF, "UTF32", rb_enc_from_encoding(rb_nkf_enc_get("UTF-32BE"))); - - /* Full version string of nkf */ - rb_define_const(mNKF, "VERSION", rb_str_new2(RUBY_NKF_VERSION)); - /* Version of nkf */ - rb_define_const(mNKF, "NKF_VERSION", rb_str_new2(NKF_VERSION)); - /* Release date of nkf */ - rb_define_const(mNKF, "NKF_RELEASE_DATE", rb_str_new2(NKF_RELEASE_DATE)); - /* Version of nkf library */ - rb_define_const(mNKF, "GEM_VERSION", rb_str_new_cstr(NKF_GEM_VERSION)); -} diff --git a/ext/nkf/nkf.gemspec b/ext/nkf/nkf.gemspec deleted file mode 100644 index 62a767c94b58eb..00000000000000 --- a/ext/nkf/nkf.gemspec +++ /dev/null @@ -1,43 +0,0 @@ -source_version = ["", "ext/nkf/"].find do |dir| - begin - break File.open(File.join(__dir__, "#{dir}nkf.c")) {|f| - f.gets("\n#define NKF_GEM_VERSION ") - f.gets[/\s*"(.+)"/, 1] - } - rescue Errno::ENOENT - end -end - -Gem::Specification.new do |spec| - spec.name = "nkf" - spec.version = source_version - spec.authors = ["NARUSE Yui", "Charles Oliver Nutter"] - spec.email = ["naruse@airemix.jp", "headius@headius.com"] - - spec.summary = %q{Ruby extension for Network Kanji Filter} - spec.description = %q{Ruby extension for Network Kanji Filter} - spec.homepage = "https://github.com/ruby/nkf" - spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0") - spec.licenses = ["Ruby", "BSD-2-Clause"] - - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = spec.homepage - - # Specify which files should be added to the gem when it is released. - # The `git ls-files -z` loads the files in the RubyGem that have been added into git. - spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do - `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } - end - - if Gem::Platform === spec.platform and spec.platform =~ 'java' or RUBY_ENGINE == 'jruby' - spec.platform = 'java' - spec.licenses += ["EPL-2.0", "LGPL-2.1"] - spec.files += Dir["lib/nkf.jar"] - else - spec.extensions = ["ext/nkf/extconf.rb"] - end - - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } - spec.require_paths = ["lib"] -end diff --git a/gems/bundled_gems b/gems/bundled_gems index 23945f045ef43b..29cb81642eb81b 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -30,3 +30,4 @@ abbrev 0.1.2 https://github.com/ruby/abbrev resolv-replace 0.1.1 https://github.com/ruby/resolv-replace rinda 0.2.0 https://github.com/ruby/rinda drb 2.2.0 https://github.com/ruby/drb +nkf 0.2.0 https://github.com/ruby/nkf diff --git a/lib/nkf.rb b/lib/nkf.rb deleted file mode 100644 index d71717d8d8b7d0..00000000000000 --- a/lib/nkf.rb +++ /dev/null @@ -1,6 +0,0 @@ -if RUBY_ENGINE == "jruby" - require 'nkf.jar' - JRuby::Util.load_ext('org.jruby.ext.nkf.NKFLibrary') -else - require 'nkf.so' -end diff --git a/test/nkf/test_kconv.rb b/test/nkf/test_kconv.rb deleted file mode 100644 index 3968cc47dc432f..00000000000000 --- a/test/nkf/test_kconv.rb +++ /dev/null @@ -1,82 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' -require 'kconv' - -class TestKconv < Test::Unit::TestCase - def setup - @euc_str = "\ -\xa5\xaa\xa5\xd6\xa5\xb8\xa5\xa7\xa5\xaf\xa5\xc8\xbb\xd8\xb8\xfe\ -\xa5\xd7\xa5\xed\xa5\xb0\xa5\xe9\xa5\xdf\xa5\xf3\xa5\xb0\xb8\xc0\xb8\xec\ -\x52\x75\x62\x79".force_encoding('EUC-JP') - @utf8_str = "\ -\xe3\x82\xaa\xe3\x83\x96\xe3\x82\xb8\xe3\x82\xa7\ -\xe3\x82\xaf\xe3\x83\x88\xe6\x8c\x87\xe5\x90\x91\ -\xe3\x83\x97\xe3\x83\xad\xe3\x82\xb0\xe3\x83\xa9\xe3\x83\x9f\ -\xe3\x83\xb3\xe3\x82\xb0\xe8\xa8\x80\xe8\xaa\x9e\ -\x52\x75\x62\x79".force_encoding('UTF-8') - @sjis_str = "\ -\x83\x49\x83\x75\x83\x57\x83\x46\x83\x4e\x83\x67\x8e\x77\x8c\xfc\ -\x83\x76\x83\x8d\x83\x4f\x83\x89\x83\x7e\x83\x93\x83\x4f\x8c\xbe\x8c\xea\ -\x52\x75\x62\x79".force_encoding('Shift_JIS') - @jis_str = "\ -\x1b\x24\x42\x25\x2a\x25\x56\x25\x38\x25\x27\x25\x2f\x25\x48\x3b\x58\x38\x7e\ -\x25\x57\x25\x6d\x25\x30\x25\x69\x25\x5f\x25\x73\x25\x30\x38\x40\x38\x6c\x1b\x28\x42\ -\x52\x75\x62\x79".force_encoding('ISO-2022-JP') - end - - - def test_eucjp - assert(@euc_str.iseuc) - assert_equal(::Kconv::EUC, Kconv.guess(@euc_str)) - assert_equal(@euc_str, @euc_str.toeuc) - assert_equal(@euc_str, @sjis_str.toeuc) - assert_equal(@euc_str, @utf8_str.toeuc) - assert_equal(@euc_str, @jis_str.toeuc) - assert_equal(@euc_str, @euc_str.kconv(::NKF::EUC)) - assert_equal(@euc_str, @sjis_str.kconv(::NKF::EUC)) - assert_equal(@euc_str, @utf8_str.kconv(::NKF::EUC)) - assert_equal(@euc_str, @jis_str.kconv(::NKF::EUC)) - end - def test_shiftjis - assert(@sjis_str.issjis) - assert_equal(::Kconv::SJIS, Kconv.guess(@sjis_str)) - assert_equal(@sjis_str, @euc_str.tosjis) - assert_equal(@sjis_str, @sjis_str.tosjis) - assert_equal(@sjis_str, @utf8_str.tosjis) - assert_equal(@sjis_str, @jis_str.tosjis) - assert_equal(@sjis_str, @euc_str.kconv(::NKF::SJIS)) - assert_equal(@sjis_str, @sjis_str.kconv(::NKF::SJIS)) - assert_equal(@sjis_str, @utf8_str.kconv(::NKF::SJIS)) - assert_equal(@sjis_str, @jis_str.kconv(::NKF::SJIS)) - end - def test_utf8 - assert(@utf8_str.isutf8) - assert_equal(::Kconv::UTF8, Kconv.guess(@utf8_str)) - assert_equal(@utf8_str, @euc_str.toutf8) - assert_equal(@utf8_str, @sjis_str.toutf8) - assert_equal(@utf8_str, @utf8_str.toutf8) - assert_equal(@utf8_str, @jis_str.toutf8) - assert_equal(@utf8_str, @euc_str.kconv(::NKF::UTF8)) - assert_equal(@utf8_str, @sjis_str.kconv(::NKF::UTF8)) - assert_equal(@utf8_str, @utf8_str.kconv(::NKF::UTF8)) - assert_equal(@utf8_str, @jis_str.kconv(::NKF::UTF8)) - end - def test_jis - assert_equal(::Kconv::JIS, Kconv.guess(@jis_str)) - assert_equal(@jis_str, @euc_str.tojis) - assert_equal(@jis_str, @sjis_str.tojis) - assert_equal(@jis_str, @utf8_str.tojis) - assert_equal(@jis_str, @jis_str.tojis) - assert_equal(@jis_str, @euc_str.kconv(::NKF::JIS)) - assert_equal(@jis_str, @sjis_str.kconv(::NKF::JIS)) - assert_equal(@jis_str, @utf8_str.kconv(::NKF::JIS)) - assert_equal(@jis_str, @jis_str.kconv(::NKF::JIS)) - end - def test_kconv - str = "\xc2\xa1" - %w/UTF-8 EUC-JP/.each do |enc| - s = str.dup.force_encoding(enc) - assert_equal(s, s.kconv(enc)) - end - end -end diff --git a/test/nkf/test_nkf.rb b/test/nkf/test_nkf.rb deleted file mode 100644 index eb51bf8e7d5f71..00000000000000 --- a/test/nkf/test_nkf.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: false -require 'test/unit' -require 'nkf' - -class TestNKF < Test::Unit::TestCase - EUC_STR = "\xa5\xaa\xa5\xd6\xa5\xb8\xa5\xa7\xa5\xaf\xa5\xc8\xbb\xd8\xb8\xfe\ -\xa5\xb9\xa5\xaf\xa5\xea\xa5\xd7\xa5\xc8\xb8\xc0\xb8\xec\ -Ruby" - - def test_guess - str_euc = EUC_STR - str_jis = NKF.nkf('-j', str_euc) - assert_equal(::NKF::JIS, NKF.guess(str_jis)) - assert_equal(::NKF::EUC, NKF.guess(str_euc)) - end - - def test_ruby_dev_36909 - assert_nothing_raised do - 100.times { NKF.nkf("--oc=eucJP-nkf", "foo") } - end - end - -end From f869f2ecf1d1631880d0f885220c48592429a695 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 22 Jan 2024 12:34:07 +0900 Subject: [PATCH 384/640] Stop sync nkf repo --- tool/sync_default_gems.rb | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb index af7658b61a7d94..7cf98bbd9fc3ba 100755 --- a/tool/sync_default_gems.rb +++ b/tool/sync_default_gems.rb @@ -37,7 +37,6 @@ module SyncDefaultGems irb: 'ruby/irb', json: 'flori/json', logger: 'ruby/logger', - nkf: "ruby/nkf", open3: "ruby/open3", openssl: "ruby/openssl", optparse: "ruby/optparse", @@ -318,13 +317,6 @@ def sync_default_gems(gem) cp_r("#{upstream}/test/erb", "test") cp_r("#{upstream}/erb.gemspec", "lib") cp_r("#{upstream}/libexec/erb", "libexec") - when "nkf" - rm_rf(%w[ext/nkf test/nkf]) - cp_r("#{upstream}/ext/nkf", "ext") - cp_r("#{upstream}/lib", "ext/nkf") - cp_r("#{upstream}/test/nkf", "test") - cp_r("#{upstream}/nkf.gemspec", "ext/nkf") - `git checkout ext/nkf/depend` when "syslog" rm_rf(%w[ext/syslog test/syslog test/test_syslog.rb]) cp_r("#{upstream}/ext/syslog", "ext") From 52a0ebe292689e9c7e66bc548b7cd2c6f7e5b8c8 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 22 Jan 2024 12:34:54 +0900 Subject: [PATCH 385/640] Document about nkf at Ruby 3.4 --- doc/maintainers.md | 8 +++----- doc/standard_library.rdoc | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/doc/maintainers.md b/doc/maintainers.md index 2a6a0545ef0dbd..5e117196c7498b 100644 --- a/doc/maintainers.md +++ b/doc/maintainers.md @@ -350,11 +350,6 @@ have commit right, others don't. * https://github.com/flori/json * https://rubygems.org/gems/json -#### ext/nkf -* NARUSE, Yui (naruse) -* https://github.com/ruby/nkf -* https://rubygems.org/gems/nkf - #### ext/openssl * Kazuki Yamaguchi (rhe) * https://github.com/ruby/openssl @@ -472,6 +467,9 @@ have commit right, others don't. #### drb * https://github.com/ruby/drb +#### nkf +* https://github.com/ruby/nkf + ## Platform Maintainers ### mswin64 (Microsoft Windows) * NAKAMURA Usaku (usa) diff --git a/doc/standard_library.rdoc b/doc/standard_library.rdoc index 4833defe45d9f6..c099ea5c712798 100644 --- a/doc/standard_library.rdoc +++ b/doc/standard_library.rdoc @@ -85,7 +85,6 @@ Fcntl:: Loads constants defined in the OS fcntl.h C header file Fiddle:: A libffi wrapper for Ruby IO:: Extensions for Ruby IO class, including #wait, #nonblock and ::console JSON:: Implements Javascript Object Notation for Ruby -NKF:: Ruby extension for Network Kanji Filter OpenSSL:: Provides SSL, TLS and general purpose cryptography for Ruby Pathname:: Representation of the name of a file or directory on the filesystem Psych:: A YAML parser and emitter for Ruby @@ -130,3 +129,4 @@ Abbrev:: Calculates a set of unique abbreviations for a given set of strings resolv-replace.rb:: Replace Socket DNS with Resolv Rinda:: The Linda distributed computing paradigm in Ruby DRb:: Distributed object system for Ruby +NKF:: Ruby extension for Network Kanji Filter From 38a1b88d1eb7cc1c0ff2baa36e85509ae8846b1e Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 22 Jan 2024 13:37:19 +0900 Subject: [PATCH 386/640] Skip nkf from check_existence --- test/test_extlibs.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/test/test_extlibs.rb b/test/test_extlibs.rb index 3e0276d8524ffa..d3688da76560f7 100644 --- a/test/test_extlibs.rb +++ b/test/test_extlibs.rb @@ -58,7 +58,6 @@ def windows? check_existence "io/nonblock" check_existence "io/wait" check_existence "json" - check_existence "nkf" check_existence "objspace" check_existence "openssl", "this may be false positive, but should assert because rubygems requires this" check_existence "pathname" From 4d31d6802a41b63c0fa82199c7e2d92902dc5766 Mon Sep 17 00:00:00 2001 From: git Date: Mon, 22 Jan 2024 05:18:23 +0000 Subject: [PATCH 387/640] Update bundled gems list at 38a1b88d1eb7cc1c0ff2baa36e8550 [ci skip] --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index ab4c8e3e54bb84..3f4f2a83c38eef 100644 --- a/NEWS.md +++ b/NEWS.md @@ -56,6 +56,7 @@ The following bundled gems are promoted from default gems. * resolv-replace 0.1.1 * rinda 0.2.0 * drb 2.2.0 +* nkf 0.2.0 See GitHub releases like [GitHub Releases of Logger](https://github.com/ruby/logger/releases) or changelog for details of the default gems or bundled gems. From 029b6d5b76e49d2b5fc1494856e5410d57e5352a Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 22 Jan 2024 15:24:50 +0900 Subject: [PATCH 388/640] Extract syslog --- ext/syslog/depend | 161 -------- ext/syslog/extconf.rb | 13 - ext/syslog/lib/syslog/logger.rb | 209 ----------- ext/syslog/syslog.c | 592 ------------------------------ ext/syslog/syslog.gemspec | 28 -- ext/syslog/syslog.txt | 124 ------- gems/bundled_gems | 1 + test/syslog/test_syslog_logger.rb | 588 ----------------------------- test/test_extlibs.rb | 3 +- 9 files changed, 2 insertions(+), 1717 deletions(-) delete mode 100644 ext/syslog/depend delete mode 100644 ext/syslog/extconf.rb delete mode 100644 ext/syslog/lib/syslog/logger.rb delete mode 100644 ext/syslog/syslog.c delete mode 100644 ext/syslog/syslog.gemspec delete mode 100644 ext/syslog/syslog.txt delete mode 100644 test/syslog/test_syslog_logger.rb diff --git a/ext/syslog/depend b/ext/syslog/depend deleted file mode 100644 index ee4ac5f47db5e5..00000000000000 --- a/ext/syslog/depend +++ /dev/null @@ -1,161 +0,0 @@ -# AUTOGENERATED DEPENDENCIES START -syslog.o: $(RUBY_EXTCONF_H) -syslog.o: $(arch_hdrdir)/ruby/config.h -syslog.o: $(hdrdir)/ruby/assert.h -syslog.o: $(hdrdir)/ruby/backward.h -syslog.o: $(hdrdir)/ruby/backward/2/assume.h -syslog.o: $(hdrdir)/ruby/backward/2/attributes.h -syslog.o: $(hdrdir)/ruby/backward/2/bool.h -syslog.o: $(hdrdir)/ruby/backward/2/inttypes.h -syslog.o: $(hdrdir)/ruby/backward/2/limits.h -syslog.o: $(hdrdir)/ruby/backward/2/long_long.h -syslog.o: $(hdrdir)/ruby/backward/2/stdalign.h -syslog.o: $(hdrdir)/ruby/backward/2/stdarg.h -syslog.o: $(hdrdir)/ruby/defines.h -syslog.o: $(hdrdir)/ruby/intern.h -syslog.o: $(hdrdir)/ruby/internal/abi.h -syslog.o: $(hdrdir)/ruby/internal/anyargs.h -syslog.o: $(hdrdir)/ruby/internal/arithmetic.h -syslog.o: $(hdrdir)/ruby/internal/arithmetic/char.h -syslog.o: $(hdrdir)/ruby/internal/arithmetic/double.h -syslog.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -syslog.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -syslog.o: $(hdrdir)/ruby/internal/arithmetic/int.h -syslog.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -syslog.o: $(hdrdir)/ruby/internal/arithmetic/long.h -syslog.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -syslog.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -syslog.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -syslog.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -syslog.o: $(hdrdir)/ruby/internal/arithmetic/short.h -syslog.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -syslog.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -syslog.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -syslog.o: $(hdrdir)/ruby/internal/assume.h -syslog.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -syslog.o: $(hdrdir)/ruby/internal/attr/artificial.h -syslog.o: $(hdrdir)/ruby/internal/attr/cold.h -syslog.o: $(hdrdir)/ruby/internal/attr/const.h -syslog.o: $(hdrdir)/ruby/internal/attr/constexpr.h -syslog.o: $(hdrdir)/ruby/internal/attr/deprecated.h -syslog.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -syslog.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -syslog.o: $(hdrdir)/ruby/internal/attr/error.h -syslog.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -syslog.o: $(hdrdir)/ruby/internal/attr/forceinline.h -syslog.o: $(hdrdir)/ruby/internal/attr/format.h -syslog.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -syslog.o: $(hdrdir)/ruby/internal/attr/noalias.h -syslog.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -syslog.o: $(hdrdir)/ruby/internal/attr/noexcept.h -syslog.o: $(hdrdir)/ruby/internal/attr/noinline.h -syslog.o: $(hdrdir)/ruby/internal/attr/nonnull.h -syslog.o: $(hdrdir)/ruby/internal/attr/noreturn.h -syslog.o: $(hdrdir)/ruby/internal/attr/packed_struct.h -syslog.o: $(hdrdir)/ruby/internal/attr/pure.h -syslog.o: $(hdrdir)/ruby/internal/attr/restrict.h -syslog.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h -syslog.o: $(hdrdir)/ruby/internal/attr/warning.h -syslog.o: $(hdrdir)/ruby/internal/attr/weakref.h -syslog.o: $(hdrdir)/ruby/internal/cast.h -syslog.o: $(hdrdir)/ruby/internal/compiler_is.h -syslog.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -syslog.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -syslog.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -syslog.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -syslog.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -syslog.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -syslog.o: $(hdrdir)/ruby/internal/compiler_since.h -syslog.o: $(hdrdir)/ruby/internal/config.h -syslog.o: $(hdrdir)/ruby/internal/constant_p.h -syslog.o: $(hdrdir)/ruby/internal/core.h -syslog.o: $(hdrdir)/ruby/internal/core/rarray.h -syslog.o: $(hdrdir)/ruby/internal/core/rbasic.h -syslog.o: $(hdrdir)/ruby/internal/core/rbignum.h -syslog.o: $(hdrdir)/ruby/internal/core/rclass.h -syslog.o: $(hdrdir)/ruby/internal/core/rdata.h -syslog.o: $(hdrdir)/ruby/internal/core/rfile.h -syslog.o: $(hdrdir)/ruby/internal/core/rhash.h -syslog.o: $(hdrdir)/ruby/internal/core/robject.h -syslog.o: $(hdrdir)/ruby/internal/core/rregexp.h -syslog.o: $(hdrdir)/ruby/internal/core/rstring.h -syslog.o: $(hdrdir)/ruby/internal/core/rstruct.h -syslog.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -syslog.o: $(hdrdir)/ruby/internal/ctype.h -syslog.o: $(hdrdir)/ruby/internal/dllexport.h -syslog.o: $(hdrdir)/ruby/internal/dosish.h -syslog.o: $(hdrdir)/ruby/internal/error.h -syslog.o: $(hdrdir)/ruby/internal/eval.h -syslog.o: $(hdrdir)/ruby/internal/event.h -syslog.o: $(hdrdir)/ruby/internal/fl_type.h -syslog.o: $(hdrdir)/ruby/internal/gc.h -syslog.o: $(hdrdir)/ruby/internal/glob.h -syslog.o: $(hdrdir)/ruby/internal/globals.h -syslog.o: $(hdrdir)/ruby/internal/has/attribute.h -syslog.o: $(hdrdir)/ruby/internal/has/builtin.h -syslog.o: $(hdrdir)/ruby/internal/has/c_attribute.h -syslog.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -syslog.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -syslog.o: $(hdrdir)/ruby/internal/has/extension.h -syslog.o: $(hdrdir)/ruby/internal/has/feature.h -syslog.o: $(hdrdir)/ruby/internal/has/warning.h -syslog.o: $(hdrdir)/ruby/internal/intern/array.h -syslog.o: $(hdrdir)/ruby/internal/intern/bignum.h -syslog.o: $(hdrdir)/ruby/internal/intern/class.h -syslog.o: $(hdrdir)/ruby/internal/intern/compar.h -syslog.o: $(hdrdir)/ruby/internal/intern/complex.h -syslog.o: $(hdrdir)/ruby/internal/intern/cont.h -syslog.o: $(hdrdir)/ruby/internal/intern/dir.h -syslog.o: $(hdrdir)/ruby/internal/intern/enum.h -syslog.o: $(hdrdir)/ruby/internal/intern/enumerator.h -syslog.o: $(hdrdir)/ruby/internal/intern/error.h -syslog.o: $(hdrdir)/ruby/internal/intern/eval.h -syslog.o: $(hdrdir)/ruby/internal/intern/file.h -syslog.o: $(hdrdir)/ruby/internal/intern/hash.h -syslog.o: $(hdrdir)/ruby/internal/intern/io.h -syslog.o: $(hdrdir)/ruby/internal/intern/load.h -syslog.o: $(hdrdir)/ruby/internal/intern/marshal.h -syslog.o: $(hdrdir)/ruby/internal/intern/numeric.h -syslog.o: $(hdrdir)/ruby/internal/intern/object.h -syslog.o: $(hdrdir)/ruby/internal/intern/parse.h -syslog.o: $(hdrdir)/ruby/internal/intern/proc.h -syslog.o: $(hdrdir)/ruby/internal/intern/process.h -syslog.o: $(hdrdir)/ruby/internal/intern/random.h -syslog.o: $(hdrdir)/ruby/internal/intern/range.h -syslog.o: $(hdrdir)/ruby/internal/intern/rational.h -syslog.o: $(hdrdir)/ruby/internal/intern/re.h -syslog.o: $(hdrdir)/ruby/internal/intern/ruby.h -syslog.o: $(hdrdir)/ruby/internal/intern/select.h -syslog.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -syslog.o: $(hdrdir)/ruby/internal/intern/signal.h -syslog.o: $(hdrdir)/ruby/internal/intern/sprintf.h -syslog.o: $(hdrdir)/ruby/internal/intern/string.h -syslog.o: $(hdrdir)/ruby/internal/intern/struct.h -syslog.o: $(hdrdir)/ruby/internal/intern/thread.h -syslog.o: $(hdrdir)/ruby/internal/intern/time.h -syslog.o: $(hdrdir)/ruby/internal/intern/variable.h -syslog.o: $(hdrdir)/ruby/internal/intern/vm.h -syslog.o: $(hdrdir)/ruby/internal/interpreter.h -syslog.o: $(hdrdir)/ruby/internal/iterator.h -syslog.o: $(hdrdir)/ruby/internal/memory.h -syslog.o: $(hdrdir)/ruby/internal/method.h -syslog.o: $(hdrdir)/ruby/internal/module.h -syslog.o: $(hdrdir)/ruby/internal/newobj.h -syslog.o: $(hdrdir)/ruby/internal/scan_args.h -syslog.o: $(hdrdir)/ruby/internal/special_consts.h -syslog.o: $(hdrdir)/ruby/internal/static_assert.h -syslog.o: $(hdrdir)/ruby/internal/stdalign.h -syslog.o: $(hdrdir)/ruby/internal/stdbool.h -syslog.o: $(hdrdir)/ruby/internal/symbol.h -syslog.o: $(hdrdir)/ruby/internal/value.h -syslog.o: $(hdrdir)/ruby/internal/value_type.h -syslog.o: $(hdrdir)/ruby/internal/variable.h -syslog.o: $(hdrdir)/ruby/internal/warning_push.h -syslog.o: $(hdrdir)/ruby/internal/xmalloc.h -syslog.o: $(hdrdir)/ruby/missing.h -syslog.o: $(hdrdir)/ruby/ruby.h -syslog.o: $(hdrdir)/ruby/st.h -syslog.o: $(hdrdir)/ruby/subst.h -syslog.o: $(hdrdir)/ruby/util.h -syslog.o: syslog.c -# AUTOGENERATED DEPENDENCIES END diff --git a/ext/syslog/extconf.rb b/ext/syslog/extconf.rb deleted file mode 100644 index 1230a4d52edc2f..00000000000000 --- a/ext/syslog/extconf.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: false -# $RoughId: extconf.rb,v 1.3 2001/11/24 17:49:26 knu Exp $ -# $Id$ - -require 'mkmf' - -have_library("log") # for Android - -have_header("syslog.h") && - have_func("openlog") && - have_func("setlogmask") && - create_makefile("syslog") - diff --git a/ext/syslog/lib/syslog/logger.rb b/ext/syslog/lib/syslog/logger.rb deleted file mode 100644 index 453ca2785c7a87..00000000000000 --- a/ext/syslog/lib/syslog/logger.rb +++ /dev/null @@ -1,209 +0,0 @@ -# frozen_string_literal: false -require 'syslog' -require 'logger' - -## -# Syslog::Logger is a Logger work-alike that logs via syslog instead of to a -# file. You can use Syslog::Logger to aggregate logs between multiple -# machines. -# -# By default, Syslog::Logger uses the program name 'ruby', but this can be -# changed via the first argument to Syslog::Logger.new. -# -# NOTE! You can only set the Syslog::Logger program name when you initialize -# Syslog::Logger for the first time. This is a limitation of the way -# Syslog::Logger uses syslog (and in some ways, a limitation of the way -# syslog(3) works). Attempts to change Syslog::Logger's program name after -# the first initialization will be ignored. -# -# === Example -# -# The following will log to syslogd on your local machine: -# -# require 'syslog/logger' -# -# log = Syslog::Logger.new 'my_program' -# log.info 'this line will be logged via syslog(3)' -# -# Also the facility may be set to specify the facility level which will be used: -# -# log.info 'this line will be logged using Syslog default facility level' -# -# log_local1 = Syslog::Logger.new 'my_program', Syslog::LOG_LOCAL1 -# log_local1.info 'this line will be logged using local1 facility level' -# -# -# You may need to perform some syslog.conf setup first. For a BSD machine add -# the following lines to /etc/syslog.conf: -# -# !my_program -# *.* /var/log/my_program.log -# -# Then touch /var/log/my_program.log and signal syslogd with a HUP -# (killall -HUP syslogd, on FreeBSD). -# -# If you wish to have logs automatically roll over and archive, see the -# newsyslog.conf(5) and newsyslog(8) man pages. - -class Syslog::Logger - # Default formatter for log messages. - class Formatter - def call severity, time, progname, msg - clean msg - end - - private - - ## - # Clean up messages so they're nice and pretty. - - def clean message - message = message.to_s.strip - message.gsub!(/\e\[[0-9;]*m/, '') # remove useless ansi color codes - return message - end - end - - ## - # The version of Syslog::Logger you are using. - - VERSION = '2.1.0' - - ## - # Maps Logger warning types to syslog(3) warning types. - # - # Messages from Ruby applications are not considered as critical as messages - # from other system daemons using syslog(3), so most messages are reduced by - # one level. For example, a fatal message for Ruby's Logger is considered - # an error for syslog(3). - - LEVEL_MAP = { - ::Logger::UNKNOWN => Syslog::LOG_ALERT, - ::Logger::FATAL => Syslog::LOG_ERR, - ::Logger::ERROR => Syslog::LOG_WARNING, - ::Logger::WARN => Syslog::LOG_NOTICE, - ::Logger::INFO => Syslog::LOG_INFO, - ::Logger::DEBUG => Syslog::LOG_DEBUG, - } - - ## - # Returns the internal Syslog object that is initialized when the - # first instance is created. - - def self.syslog - @@syslog - end - - ## - # Specifies the internal Syslog object to be used. - - def self.syslog= syslog - @@syslog = syslog - end - - ## - # Builds a methods for level +meth+. - - def self.make_methods meth - level = ::Logger.const_get(meth.upcase) - eval <<-EOM, nil, __FILE__, __LINE__ + 1 - def #{meth}(message = nil, &block) - add(#{level}, message, &block) - end - - def #{meth}? - level <= #{level} - end - EOM - end - - ## - # :method: unknown - # - # Logs a +message+ at the unknown (syslog alert) log level, or logs the - # message returned from the block. - - ## - # :method: fatal - # - # Logs a +message+ at the fatal (syslog err) log level, or logs the message - # returned from the block. - - ## - # :method: error - # - # Logs a +message+ at the error (syslog warning) log level, or logs the - # message returned from the block. - - ## - # :method: warn - # - # Logs a +message+ at the warn (syslog notice) log level, or logs the - # message returned from the block. - - ## - # :method: info - # - # Logs a +message+ at the info (syslog info) log level, or logs the message - # returned from the block. - - ## - # :method: debug - # - # Logs a +message+ at the debug (syslog debug) log level, or logs the - # message returned from the block. - - Logger::Severity::constants.each do |severity| - make_methods severity.downcase - end - - ## - # Log level for Logger compatibility. - - attr_accessor :level - - # Logging formatter, as a +Proc+ that will take four arguments and - # return the formatted message. The arguments are: - # - # +severity+:: The Severity of the log message. - # +time+:: A Time instance representing when the message was logged. - # +progname+:: The #progname configured, or passed to the logger method. - # +msg+:: The _Object_ the user passed to the log message; not necessarily a - # String. - # - # The block should return an Object that can be written to the logging - # device via +write+. The default formatter is used when no formatter is - # set. - attr_accessor :formatter - - ## - # The facility argument is used to specify what type of program is logging the message. - - attr_accessor :facility - - ## - # Fills in variables for Logger compatibility. If this is the first - # instance of Syslog::Logger, +program_name+ may be set to change the logged - # program name. The +facility+ may be set to specify the facility level which will be used. - # - # Due to the way syslog works, only one program name may be chosen. - - def initialize program_name = 'ruby', facility = nil - @level = ::Logger::DEBUG - @formatter = Formatter.new - - @@syslog ||= Syslog.open(program_name) - - @facility = (facility || @@syslog.facility) - end - - ## - # Almost duplicates Logger#add. +progname+ is ignored. - - def add severity, message = nil, progname = nil, &block - severity ||= ::Logger::UNKNOWN - level <= severity and - @@syslog.log( (LEVEL_MAP[severity] | @facility), '%s', formatter.call(severity, Time.now, progname, (message || block.call)) ) - true - end -end diff --git a/ext/syslog/syslog.c b/ext/syslog/syslog.c deleted file mode 100644 index 4fbbb2ec6e5591..00000000000000 --- a/ext/syslog/syslog.c +++ /dev/null @@ -1,592 +0,0 @@ -/* - * UNIX Syslog extension for Ruby - * Amos Gouaux, University of Texas at Dallas - * - * Documented by mathew - * - * $RoughId: syslog.c,v 1.21 2002/02/25 12:21:17 knu Exp $ - * $Id$ - */ - -#include "ruby/ruby.h" -#include "ruby/util.h" -#include - -#define SYSLOG_VERSION "0.1.2" - -/* Syslog class */ -static VALUE mSyslog; -/* - * Module holding all Syslog constants. See Syslog::log and - * Syslog::open for constant descriptions. - */ -static VALUE mSyslogConstants; -/* Module holding Syslog option constants */ -static VALUE mSyslogOption; -/* Module holding Syslog facility constants */ -static VALUE mSyslogFacility; -/* Module holding Syslog level constants */ -static VALUE mSyslogLevel; -/* Module holding Syslog utility macros */ -static VALUE mSyslogMacros; - -static const char *syslog_ident = NULL; -static int syslog_options = -1, syslog_facility = -1, syslog_mask = -1; -static int syslog_opened = 0; - -/* Package helper routines */ -static void syslog_write(int pri, int argc, VALUE *argv) -{ - VALUE str; - - if (argc < 1) { - rb_raise(rb_eArgError, "no log message supplied"); - } - - if (!syslog_opened) { - rb_raise(rb_eRuntimeError, "must open syslog before write"); - } - - str = rb_f_sprintf(argc, argv); - - syslog(pri, "%s", RSTRING_PTR(str)); -} - -/* Closes the syslog facility. - * Raises a runtime exception if it is not open. - */ -static VALUE mSyslog_close(VALUE self) -{ - if (!syslog_opened) { - rb_raise(rb_eRuntimeError, "syslog not opened"); - } - - closelog(); - - xfree((void *)syslog_ident); - syslog_ident = NULL; - syslog_options = syslog_facility = syslog_mask = -1; - syslog_opened = 0; - - return Qnil; -} - -/* call-seq: - * open(ident, options, facility) => syslog - * - * :yields: syslog - * - * Open the syslog facility. - * Raises a runtime exception if it is already open. - * - * Can be called with or without a code block. If called with a block, the - * Syslog object created is passed to the block. - * - * If the syslog is already open, raises a RuntimeError. - * - * +ident+ is a String which identifies the calling program. - * - * +options+ is the logical OR of any of the following: - * - * LOG_CONS:: If there is an error while sending to the system logger, - * write directly to the console instead. - * - * LOG_NDELAY:: Open the connection now, rather than waiting for the first - * message to be written. - * - * LOG_NOWAIT:: Don't wait for any child processes created while logging - * messages. (Has no effect on Linux.) - * - * LOG_ODELAY:: Opposite of LOG_NDELAY; wait until a message is sent before - * opening the connection. (This is the default.) - * - * LOG_PERROR:: Print the message to stderr as well as sending it to syslog. - * (Not in POSIX.1-2001.) - * - * LOG_PID:: Include the current process ID with each message. - * - * +facility+ describes the type of program opening the syslog, and is - * the logical OR of any of the following which are defined for the host OS: - * - * LOG_AUTH:: Security or authorization. Deprecated, use LOG_AUTHPRIV - * instead. - * - * LOG_AUTHPRIV:: Security or authorization messages which should be kept - * private. - * - * LOG_CONSOLE:: System console message. - * - * LOG_CRON:: System task scheduler (cron or at). - * - * LOG_DAEMON:: A system daemon which has no facility value of its own. - * - * LOG_FTP:: An FTP server. - * - * LOG_KERN:: A kernel message (not sendable by user processes, so not of - * much use to Ruby, but listed here for completeness). - * - * LOG_LPR:: Line printer subsystem. - * - * LOG_MAIL:: Mail delivery or transport subsystem. - * - * LOG_NEWS:: Usenet news system. - * - * LOG_NTP:: Network Time Protocol server. - * - * LOG_SECURITY:: General security message. - * - * LOG_SYSLOG:: Messages generated internally by syslog. - * - * LOG_USER:: Generic user-level message. - * - * LOG_UUCP:: UUCP subsystem. - * - * LOG_LOCAL0 to LOG_LOCAL7:: Locally-defined facilities. - * - * Example: - * - * Syslog.open("webrick", Syslog::LOG_PID, - * Syslog::LOG_DAEMON | Syslog::LOG_LOCAL3) - * - */ -static VALUE mSyslog_open(int argc, VALUE *argv, VALUE self) -{ - VALUE ident, opt, fac; - const char *ident_ptr; - - if (syslog_opened) { - rb_raise(rb_eRuntimeError, "syslog already open"); - } - - rb_scan_args(argc, argv, "03", &ident, &opt, &fac); - - if (NIL_P(ident)) { - ident = rb_gv_get("$0"); - } - ident_ptr = StringValueCStr(ident); - syslog_ident = strdup(ident_ptr); - - if (NIL_P(opt)) { - syslog_options = LOG_PID | LOG_CONS; - } else { - syslog_options = NUM2INT(opt); - } - - if (NIL_P(fac)) { - syslog_facility = LOG_USER; - } else { - syslog_facility = NUM2INT(fac); - } - - openlog(syslog_ident, syslog_options, syslog_facility); - - syslog_opened = 1; - - setlogmask(syslog_mask = setlogmask(0)); - - /* be like File.new.open {...} */ - if (rb_block_given_p()) { - rb_ensure(rb_yield, self, mSyslog_close, self); - } - - return self; -} - -/* call-seq: - * reopen(ident, options, facility) => syslog - * - * :yields: syslog - * - * Closes and then reopens the syslog. - * - * Arguments are the same as for open(). - */ -static VALUE mSyslog_reopen(int argc, VALUE *argv, VALUE self) -{ - mSyslog_close(self); - - return mSyslog_open(argc, argv, self); -} - -/* call-seq: - * opened? - * - * Returns true if the syslog is open. - */ -static VALUE mSyslog_isopen(VALUE self) -{ - return syslog_opened ? Qtrue : Qfalse; -} - -/* Returns the identity string used in the last call to open() - */ -static VALUE mSyslog_ident(VALUE self) -{ - return syslog_opened ? rb_str_new2(syslog_ident) : Qnil; -} - -/* Returns the options bitmask used in the last call to open() - */ -static VALUE mSyslog_options(VALUE self) -{ - return syslog_opened ? INT2NUM(syslog_options) : Qnil; -} - -/* Returns the facility number used in the last call to open() - */ -static VALUE mSyslog_facility(VALUE self) -{ - return syslog_opened ? INT2NUM(syslog_facility) : Qnil; -} - -/* Returns the log priority mask in effect. The mask is not reset by opening - * or closing syslog. - */ -static VALUE mSyslog_get_mask(VALUE self) -{ - return syslog_opened ? INT2NUM(syslog_mask) : Qnil; -} - -/* call-seq: - * mask=(priority_mask) - * - * Sets the log priority mask. A method LOG_UPTO is defined to make it easier - * to set mask values. Example: - * - * Syslog.mask = Syslog::LOG_UPTO(Syslog::LOG_ERR) - * - * Alternatively, specific priorities can be selected and added together using - * binary OR. Example: - * - * Syslog.mask = Syslog::LOG_MASK(Syslog::LOG_ERR) | Syslog::LOG_MASK(Syslog::LOG_CRIT) - * - * The priority mask persists through calls to open() and close(). - */ -static VALUE mSyslog_set_mask(VALUE self, VALUE mask) -{ - if (!syslog_opened) { - rb_raise(rb_eRuntimeError, "must open syslog before setting log mask"); - } - - setlogmask(syslog_mask = NUM2INT(mask)); - - return mask; -} - -/* call-seq: - * log(priority, format_string, *format_args) - * - * Log a message with the specified priority. Example: - * - * Syslog.log(Syslog::LOG_CRIT, "Out of disk space") - * Syslog.log(Syslog::LOG_CRIT, "User %s logged in", ENV['USER']) - * - * The priority levels, in descending order, are: - * - * LOG_EMERG:: System is unusable - * LOG_ALERT:: Action needs to be taken immediately - * LOG_CRIT:: A critical condition has occurred - * LOG_ERR:: An error occurred - * LOG_WARNING:: Warning of a possible problem - * LOG_NOTICE:: A normal but significant condition occurred - * LOG_INFO:: Informational message - * LOG_DEBUG:: Debugging information - * - * Each priority level also has a shortcut method that logs with it's named priority. - * As an example, the two following statements would produce the same result: - * - * Syslog.log(Syslog::LOG_ALERT, "Out of memory") - * Syslog.alert("Out of memory") - * - */ -static VALUE mSyslog_log(int argc, VALUE *argv, VALUE self) -{ - VALUE pri; - - rb_check_arity(argc, 2, UNLIMITED_ARGUMENTS); - - argc--; - pri = *argv++; - - if (!FIXNUM_P(pri)) { - rb_raise(rb_eTypeError, "type mismatch: %"PRIsVALUE" given", rb_obj_class(pri)); - } - - syslog_write(FIX2INT(pri), argc, argv); - - return self; -} - -/* Returns an inspect() string summarizing the object state. - */ -static VALUE mSyslog_inspect(VALUE self) -{ - Check_Type(self, T_MODULE); - - if (!syslog_opened) - return rb_sprintf("<#%"PRIsVALUE": opened=false>", self); - - return rb_sprintf("<#%"PRIsVALUE": opened=true, ident=\"%s\", options=%d, facility=%d, mask=%d>", - self, - syslog_ident, - syslog_options, - syslog_facility, - syslog_mask); -} - -/* Returns self, for backward compatibility. - */ -static VALUE mSyslog_instance(VALUE self) -{ - return self; -} - -#define define_syslog_shortcut_method(pri, name) \ -static VALUE mSyslog_##name(int argc, VALUE *argv, VALUE self) \ -{ \ - syslog_write((pri), argc, argv); \ -\ - return self; \ -} - -#ifdef LOG_EMERG -define_syslog_shortcut_method(LOG_EMERG, emerg) -#endif -#ifdef LOG_ALERT -define_syslog_shortcut_method(LOG_ALERT, alert) -#endif -#ifdef LOG_CRIT -define_syslog_shortcut_method(LOG_CRIT, crit) -#endif -#ifdef LOG_ERR -define_syslog_shortcut_method(LOG_ERR, err) -#endif -#ifdef LOG_WARNING -define_syslog_shortcut_method(LOG_WARNING, warning) -#endif -#ifdef LOG_NOTICE -define_syslog_shortcut_method(LOG_NOTICE, notice) -#endif -#ifdef LOG_INFO -define_syslog_shortcut_method(LOG_INFO, info) -#endif -#ifdef LOG_DEBUG -define_syslog_shortcut_method(LOG_DEBUG, debug) -#endif - -/* call-seq: - * LOG_MASK(priority_level) => priority_mask - * - * Generates a mask bit for a priority level. See #mask= - */ -static VALUE mSyslogMacros_LOG_MASK(VALUE mod, VALUE pri) -{ - return INT2FIX(LOG_MASK(NUM2INT(pri))); -} - -/* call-seq: - * LOG_UPTO(priority_level) => priority_mask - * - * Generates a mask value for priority levels at or below the level specified. - * See #mask= - */ -static VALUE mSyslogMacros_LOG_UPTO(VALUE mod, VALUE pri) -{ - return INT2FIX(LOG_UPTO(NUM2INT(pri))); -} - -static VALUE mSyslogMacros_included(VALUE mod, VALUE target) -{ - rb_extend_object(target, mSyslogMacros); - return mod; -} - -/* The syslog package provides a Ruby interface to the POSIX system logging - * facility. - * - * Syslog messages are typically passed to a central logging daemon. - * The daemon may filter them; route them into different files (usually - * found under /var/log); place them in SQL databases; forward - * them to centralized logging servers via TCP or UDP; or even alert the - * system administrator via email, pager or text message. - * - * Unlike application-level logging via Logger or Log4r, syslog is designed - * to allow secure tamper-proof logging. - * - * The syslog protocol is standardized in RFC 5424. - */ -void Init_syslog(void) -{ -#undef rb_intern - mSyslog = rb_define_module("Syslog"); - - mSyslogConstants = rb_define_module_under(mSyslog, "Constants"); - - mSyslogOption = rb_define_module_under(mSyslog, "Option"); - mSyslogFacility = rb_define_module_under(mSyslog, "Facility"); - mSyslogLevel = rb_define_module_under(mSyslog, "Level"); - mSyslogMacros = rb_define_module_under(mSyslog, "Macros"); - - rb_define_module_function(mSyslog, "open", mSyslog_open, -1); - rb_define_module_function(mSyslog, "reopen", mSyslog_reopen, -1); - rb_define_module_function(mSyslog, "open!", mSyslog_reopen, -1); - rb_define_module_function(mSyslog, "opened?", mSyslog_isopen, 0); - - rb_define_module_function(mSyslog, "ident", mSyslog_ident, 0); - rb_define_module_function(mSyslog, "options", mSyslog_options, 0); - rb_define_module_function(mSyslog, "facility", mSyslog_facility, 0); - - rb_define_module_function(mSyslog, "log", mSyslog_log, -1); - rb_define_module_function(mSyslog, "close", mSyslog_close, 0); - rb_define_module_function(mSyslog, "mask", mSyslog_get_mask, 0); - rb_define_module_function(mSyslog, "mask=", mSyslog_set_mask, 1); - - rb_define_singleton_method(mSyslog, "inspect", mSyslog_inspect, 0); - rb_define_module_function(mSyslog, "instance", mSyslog_instance, 0); - - /* Syslog options */ - -#define rb_define_syslog_option(c) \ - rb_define_const(mSyslogOption, #c, INT2NUM(c)) - -#ifdef LOG_PID - rb_define_syslog_option(LOG_PID); -#endif -#ifdef LOG_CONS - rb_define_syslog_option(LOG_CONS); -#endif -#ifdef LOG_ODELAY - rb_define_syslog_option(LOG_ODELAY); /* deprecated */ -#endif -#ifdef LOG_NDELAY - rb_define_syslog_option(LOG_NDELAY); -#endif -#ifdef LOG_NOWAIT - rb_define_syslog_option(LOG_NOWAIT); /* deprecated */ -#endif -#ifdef LOG_PERROR - rb_define_syslog_option(LOG_PERROR); -#endif - - /* Syslog facilities */ - -#define rb_define_syslog_facility(c) \ - rb_define_const(mSyslogFacility, #c, INT2NUM(c)) - -#ifdef LOG_AUTH - rb_define_syslog_facility(LOG_AUTH); -#endif -#ifdef LOG_AUTHPRIV - rb_define_syslog_facility(LOG_AUTHPRIV); -#endif -#ifdef LOG_CONSOLE - rb_define_syslog_facility(LOG_CONSOLE); -#endif -#ifdef LOG_CRON - rb_define_syslog_facility(LOG_CRON); -#endif -#ifdef LOG_DAEMON - rb_define_syslog_facility(LOG_DAEMON); -#endif -#ifdef LOG_FTP - rb_define_syslog_facility(LOG_FTP); -#endif -#ifdef LOG_KERN - rb_define_syslog_facility(LOG_KERN); -#endif -#ifdef LOG_LPR - rb_define_syslog_facility(LOG_LPR); -#endif -#ifdef LOG_MAIL - rb_define_syslog_facility(LOG_MAIL); -#endif -#ifdef LOG_NEWS - rb_define_syslog_facility(LOG_NEWS); -#endif -#ifdef LOG_NTP - rb_define_syslog_facility(LOG_NTP); -#endif -#ifdef LOG_SECURITY - rb_define_syslog_facility(LOG_SECURITY); -#endif -#ifdef LOG_SYSLOG - rb_define_syslog_facility(LOG_SYSLOG); -#endif -#ifdef LOG_USER - rb_define_syslog_facility(LOG_USER); -#endif -#ifdef LOG_UUCP - rb_define_syslog_facility(LOG_UUCP); -#endif -#ifdef LOG_LOCAL0 - rb_define_syslog_facility(LOG_LOCAL0); -#endif -#ifdef LOG_LOCAL1 - rb_define_syslog_facility(LOG_LOCAL1); -#endif -#ifdef LOG_LOCAL2 - rb_define_syslog_facility(LOG_LOCAL2); -#endif -#ifdef LOG_LOCAL3 - rb_define_syslog_facility(LOG_LOCAL3); -#endif -#ifdef LOG_LOCAL4 - rb_define_syslog_facility(LOG_LOCAL4); -#endif -#ifdef LOG_LOCAL5 - rb_define_syslog_facility(LOG_LOCAL5); -#endif -#ifdef LOG_LOCAL6 - rb_define_syslog_facility(LOG_LOCAL6); -#endif -#ifdef LOG_LOCAL7 - rb_define_syslog_facility(LOG_LOCAL7); -#endif - - /* Syslog levels and the shortcut methods */ - -#define rb_define_syslog_level(c, m) \ - rb_define_const(mSyslogLevel, #c, INT2NUM(c)); \ - rb_define_module_function(mSyslog, #m, mSyslog_##m, -1) - -#ifdef LOG_EMERG - rb_define_syslog_level(LOG_EMERG, emerg); -#endif -#ifdef LOG_ALERT - rb_define_syslog_level(LOG_ALERT, alert); -#endif -#ifdef LOG_CRIT - rb_define_syslog_level(LOG_CRIT, crit); -#endif -#ifdef LOG_ERR - rb_define_syslog_level(LOG_ERR, err); -#endif -#ifdef LOG_WARNING - rb_define_syslog_level(LOG_WARNING, warning); -#endif -#ifdef LOG_NOTICE - rb_define_syslog_level(LOG_NOTICE, notice); -#endif -#ifdef LOG_INFO - rb_define_syslog_level(LOG_INFO, info); -#endif -#ifdef LOG_DEBUG - rb_define_syslog_level(LOG_DEBUG, debug); -#endif - - /* Syslog macros */ - - rb_define_const(mSyslog, "VERSION", rb_str_new_cstr(SYSLOG_VERSION)); - - rb_define_method(mSyslogMacros, "LOG_MASK", mSyslogMacros_LOG_MASK, 1); - rb_define_method(mSyslogMacros, "LOG_UPTO", mSyslogMacros_LOG_UPTO, 1); - rb_define_singleton_method(mSyslogMacros, "included", mSyslogMacros_included, 1); - - rb_include_module(mSyslogConstants, mSyslogOption); - rb_include_module(mSyslogConstants, mSyslogFacility); - rb_include_module(mSyslogConstants, mSyslogLevel); - rb_funcall(mSyslogConstants, rb_intern("include"), 1, mSyslogMacros); - - rb_define_singleton_method(mSyslogConstants, "included", mSyslogMacros_included, 1); - rb_funcall(mSyslog, rb_intern("include"), 1, mSyslogConstants); -} diff --git a/ext/syslog/syslog.gemspec b/ext/syslog/syslog.gemspec deleted file mode 100644 index 10a6d1f25c3b7a..00000000000000 --- a/ext/syslog/syslog.gemspec +++ /dev/null @@ -1,28 +0,0 @@ -source_version = %w[. ext/syslog].find do |dir| - break $1 if File.foreach(File.join(__dir__, dir, "syslog.c")).any?(/^#define\s+SYSLOG_VERSION\s+"(.+)"/) -rescue Errno::ENOENT -end - -Gem::Specification.new do |spec| - spec.name = "syslog" - spec.version = source_version - spec.authors = ["Akinori MUSHA"] - spec.email = ["knu@idaemons.org"] - - spec.summary = %q{Ruby interface for the POSIX system logging facility.} - spec.description = %q{Ruby interface for the POSIX system logging facility.} - spec.homepage = "https://github.com/ruby/syslog" - spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0") - spec.licenses = ["Ruby", "BSD-2-Clause"] - - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = spec.homepage - - spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do - `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } - end - spec.extensions = ["ext/syslog/extconf.rb"] - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } - spec.require_paths = ["lib"] -end diff --git a/ext/syslog/syslog.txt b/ext/syslog/syslog.txt deleted file mode 100644 index 1507a87924e26b..00000000000000 --- a/ext/syslog/syslog.txt +++ /dev/null @@ -1,124 +0,0 @@ -.\" syslog.txt - -*- Indented-Text -*- -$RoughId: syslog.txt,v 1.18 2002/02/25 08:20:14 knu Exp $ -$Id$ - -UNIX Syslog extension for Ruby -Amos Gouaux, University of Texas at Dallas - -& -Akinori MUSHA - - -Contact: - - Akinori MUSHA (current maintainer) - -** Syslog(Module) - -Included Modules: Syslog::Constants - -require 'syslog' - -A Simple wrapper for the UNIX syslog system calls that might be handy -if you're writing a server in Ruby. For the details of the syslog(8) -architecture and constants, see the syslog(3) manual page of your -platform. - -Module Methods: - - open(ident = $0, logopt = Syslog::LOG_PID | Syslog::LOG_CONS, - facility = Syslog::LOG_USER) [{ |syslog| ... }] - - Opens syslog with the given options and returns the module - itself. If a block is given, calls it with an argument of - itself. If syslog is already opened, raises RuntimeError. - - Example: - Syslog.open('ftpd', Syslog::LOG_PID | Syslog::LOG_NDELAY, - Syslog::LOG_FTP) - - open!(ident = $0, logopt = Syslog::LOG_PID | Syslog::LOG_CONS, - facility = Syslog::LOG_USER) - reopen(ident = $0, logopt = Syslog::LOG_PID | Syslog::LOG_CONS, - facility = Syslog::LOG_USER) - - Same as open, but does a close first. - - opened? - - Returns true if syslog opened, otherwise false. - - ident - options - facility - - Returns the parameters given in the last open, respectively. - Every call of Syslog::open resets these values. - - log(pri, message, ...) - - Writes message to syslog. - - Example: - Syslog.log(Syslog::LOG_CRIT, "the sky is falling in %d seconds!", 10) - - crit(message, ...) - emerg(message, ...) - alert(message, ...) - err(message, ...) - warning(message, ...) - notice(message, ...) - info(message, ...) - debug(message, ...) - - These are shortcut methods of Syslog::log(). The lineup may - vary depending on what priorities are defined on your system. - - Example: - Syslog.crit("the sky is falling in %d seconds!", 5) - - mask - mask=(mask) - - Returns or sets the log priority mask. The value of the mask - is persistent and will not be reset by Syslog::open or - Syslog::close. - - Example: - Syslog.mask = Syslog::LOG_UPTO(Syslog::LOG_ERR) - - close - - Closes syslog. - - inspect - - Returns the "inspect" string of the Syslog module. - - instance - - Returns the module itself. (Just for backward compatibility) - - LOG_MASK(pri) - - Creates a mask for one priority. - - LOG_UPTO(pri) - - Creates a mask for all priorities up to pri. - -** Syslog::Constants(Module) - -require 'syslog' -include Syslog::Constants - -This module includes the LOG_* constants available on the system. - -Module Methods: - - LOG_MASK(pri) - - Creates a mask for one priority. - - LOG_UPTO(pri) - - Creates a mask for all priorities up to pri. diff --git a/gems/bundled_gems b/gems/bundled_gems index 29cb81642eb81b..15944356cdeb7e 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -31,3 +31,4 @@ resolv-replace 0.1.1 https://github.com/ruby/resolv-replace rinda 0.2.0 https://github.com/ruby/rinda drb 2.2.0 https://github.com/ruby/drb nkf 0.2.0 https://github.com/ruby/nkf +syslog 0.1.2 https://github.com/ruby/syslog diff --git a/test/syslog/test_syslog_logger.rb b/test/syslog/test_syslog_logger.rb deleted file mode 100644 index d9ffae39017255..00000000000000 --- a/test/syslog/test_syslog_logger.rb +++ /dev/null @@ -1,588 +0,0 @@ -# coding: US-ASCII -# frozen_string_literal: false -require 'test/unit' -require 'tempfile' -begin - require 'syslog/logger' -rescue LoadError - # skip. see the bottom of this file. -end - -# These tests ensure Syslog::Logger works like Logger - -class TestSyslogRootLogger < Test::Unit::TestCase - - module MockSyslog - - PRIMASK = Syslog::Level.constants.inject(0) { |mask, name| mask | Syslog::Level.const_get(name) } - - LEVEL_LABEL_MAP = { - Syslog::LOG_ALERT => 'ALERT', - Syslog::LOG_ERR => 'ERR', - Syslog::LOG_WARNING => 'WARNING', - Syslog::LOG_NOTICE => 'NOTICE', - Syslog::LOG_INFO => 'INFO', - Syslog::LOG_DEBUG => 'DEBUG' - } - - @facility = Syslog::LOG_USER - - class << self - - attr_reader :facility - attr_reader :line - attr_reader :program_name - - def log(priority, format, *args) - level = priority & PRIMASK - @line = "<#{priority}> #{LEVEL_LABEL_MAP[level]} - #{format % args}" - end - - def open(program_name) - @program_name = program_name - end - - def reset - @line = '' - end - - end - end - - Syslog::Logger.syslog = MockSyslog - - LEVEL_LABEL_MAP = { - Logger::DEBUG => 'DEBUG', - Logger::INFO => 'INFO', - Logger::WARN => 'WARN', - Logger::ERROR => 'ERROR', - Logger::FATAL => 'FATAL', - Logger::UNKNOWN => 'ANY', - } - - def setup - @logger = Logger.new(nil) - end - - class Log - attr_reader :line, :label, :datetime, :pid, :severity, :progname, :msg - def initialize(line) - @line = line - /\A(\w+), \[([^#]*)#(\d+)\]\s+(\w+) -- (\w*): ([\x0-\xff]*)/ =~ @line - @label, @datetime, @pid, @severity, @progname, @msg = $1, $2, $3, $4, $5, $6 - end - end - - def log_add(severity, msg, progname = nil, &block) - log(:add, severity, msg, progname, &block) - end - - def log(msg_id, *arg, &block) - Log.new(log_raw(msg_id, *arg, &block)) - end - - def log_raw(msg_id, *arg, &block) - Tempfile.create(File.basename(__FILE__) + '.log') {|logdev| - @logger.instance_eval { @logdev = Logger::LogDevice.new(logdev) } - assert_equal true, @logger.__send__(msg_id, *arg, &block) - logdev.rewind - logdev.read - } - end - - def test_initialize - assert_equal Logger::DEBUG, @logger.level - end - - def test_custom_formatter - @logger.formatter = Class.new { - def call severity, time, progname, msg - "hi mom!" - end - }.new - - assert_match(/hi mom!/, log_raw(:fatal, 'fatal level message')) - end - - def test_add - msg = log_add nil, 'unknown level message' # nil == unknown - assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity - - msg = log_add Logger::FATAL, 'fatal level message' - assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity - - msg = log_add Logger::ERROR, 'error level message' - assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity - - msg = log_add Logger::WARN, 'warn level message' - assert_equal LEVEL_LABEL_MAP[Logger::WARN], msg.severity - - msg = log_add Logger::INFO, 'info level message' - assert_equal LEVEL_LABEL_MAP[Logger::INFO], msg.severity - - msg = log_add Logger::DEBUG, 'debug level message' - assert_equal LEVEL_LABEL_MAP[Logger::DEBUG], msg.severity - end - - def test_add_level_unknown - @logger.level = Logger::UNKNOWN - - msg = log_add nil, 'unknown level message' # nil == unknown - assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity - - msg = log_add Logger::FATAL, 'fatal level message' - assert_equal '', msg.line - - msg = log_add Logger::ERROR, 'error level message' - assert_equal '', msg.line - - msg = log_add Logger::WARN, 'warn level message' - assert_equal '', msg.line - - msg = log_add Logger::INFO, 'info level message' - assert_equal '', msg.line - - msg = log_add Logger::DEBUG, 'debug level message' - assert_equal '', msg.line - end - - def test_add_level_fatal - @logger.level = Logger::FATAL - - msg = log_add nil, 'unknown level message' # nil == unknown - assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity - - msg = log_add Logger::FATAL, 'fatal level message' - assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity - - msg = log_add Logger::ERROR, 'error level message' - assert_equal '', msg.line - - msg = log_add Logger::WARN, 'warn level message' - assert_equal '', msg.line - - msg = log_add Logger::INFO, 'info level message' - assert_equal '', msg.line - - msg = log_add Logger::DEBUG, 'debug level message' - assert_equal '', msg.line - end - - def test_add_level_error - @logger.level = Logger::ERROR - - msg = log_add nil, 'unknown level message' # nil == unknown - assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity - - msg = log_add Logger::FATAL, 'fatal level message' - assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity - - msg = log_add Logger::ERROR, 'error level message' - assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity - - msg = log_add Logger::WARN, 'warn level message' - assert_equal '', msg.line - - msg = log_add Logger::INFO, 'info level message' - assert_equal '', msg.line - - msg = log_add Logger::DEBUG, 'debug level message' - assert_equal '', msg.line - end - - def test_add_level_warn - @logger.level = Logger::WARN - - msg = log_add nil, 'unknown level message' # nil == unknown - assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity - - msg = log_add Logger::FATAL, 'fatal level message' - assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity - - msg = log_add Logger::ERROR, 'error level message' - assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity - - msg = log_add Logger::WARN, 'warn level message' - assert_equal LEVEL_LABEL_MAP[Logger::WARN], msg.severity - - msg = log_add Logger::INFO, 'info level message' - assert_equal '', msg.line - - msg = log_add Logger::DEBUG, 'debug level message' - assert_equal '', msg.line - end - - def test_add_level_info - @logger.level = Logger::INFO - - msg = log_add nil, 'unknown level message' # nil == unknown - assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity - - msg = log_add Logger::FATAL, 'fatal level message' - assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity - - msg = log_add Logger::ERROR, 'error level message' - assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity - - msg = log_add Logger::WARN, 'warn level message' - assert_equal LEVEL_LABEL_MAP[Logger::WARN], msg.severity - - msg = log_add Logger::INFO, 'info level message' - assert_equal LEVEL_LABEL_MAP[Logger::INFO], msg.severity - - msg = log_add Logger::DEBUG, 'debug level message' - assert_equal '', msg.line - end - - def test_add_level_debug - @logger.level = Logger::DEBUG - - msg = log_add nil, 'unknown level message' # nil == unknown - assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity - - msg = log_add Logger::FATAL, 'fatal level message' - assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity - - msg = log_add Logger::ERROR, 'error level message' - assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity - - msg = log_add Logger::WARN, 'warn level message' - assert_equal LEVEL_LABEL_MAP[Logger::WARN], msg.severity - - msg = log_add Logger::INFO, 'info level message' - assert_equal LEVEL_LABEL_MAP[Logger::INFO], msg.severity - - msg = log_add Logger::DEBUG, 'debug level message' - assert_equal LEVEL_LABEL_MAP[Logger::DEBUG], msg.severity - end - - def test_unknown - msg = log :unknown, 'unknown level message' - assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity - - @logger.level = Logger::UNKNOWN - msg = log :unknown, 'unknown level message' - assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity - - @logger.level = Logger::FATAL - msg = log :unknown, 'unknown level message' - assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity - - @logger.level = Logger::ERROR - msg = log :unknown, 'unknown level message' - assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity - - @logger.level = Logger::WARN - msg = log :unknown, 'unknown level message' - assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity - - @logger.level = Logger::INFO - msg = log :unknown, 'unknown level message' - assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity - - @logger.level = Logger::DEBUG - msg = log :unknown, 'unknown level message' - assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity - end - - def test_fatal - msg = log :fatal, 'fatal level message' - assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity - - @logger.level = Logger::UNKNOWN - msg = log :fatal, 'fatal level message' - assert_equal '', msg.line - - @logger.level = Logger::FATAL - msg = log :fatal, 'fatal level message' - assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity - - @logger.level = Logger::ERROR - msg = log :fatal, 'fatal level message' - assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity - - @logger.level = Logger::WARN - msg = log :fatal, 'fatal level message' - assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity - - @logger.level = Logger::INFO - msg = log :fatal, 'fatal level message' - assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity - - @logger.level = Logger::DEBUG - msg = log :fatal, 'fatal level message' - assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity - end - - def test_fatal_eh - @logger.level = Logger::FATAL - assert_equal true, @logger.fatal? - - @logger.level = Logger::UNKNOWN - assert_equal false, @logger.fatal? - end - - def test_error - msg = log :error, 'error level message' - assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity - - @logger.level = Logger::UNKNOWN - msg = log :error, 'error level message' - assert_equal '', msg.line - - @logger.level = Logger::FATAL - msg = log :error, 'error level message' - assert_equal '', msg.line - - @logger.level = Logger::ERROR - msg = log :error, 'error level message' - assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity - - @logger.level = Logger::WARN - msg = log :error, 'error level message' - assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity - - @logger.level = Logger::INFO - msg = log :error, 'error level message' - assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity - - @logger.level = Logger::DEBUG - msg = log :error, 'error level message' - assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity - end - - def test_error_eh - @logger.level = Logger::ERROR - assert_equal true, @logger.error? - - @logger.level = Logger::FATAL - assert_equal false, @logger.error? - end - - def test_warn - msg = log :warn, 'warn level message' - assert_equal LEVEL_LABEL_MAP[Logger::WARN], msg.severity - - @logger.level = Logger::UNKNOWN - msg = log :warn, 'warn level message' - assert_equal '', msg.line - - @logger.level = Logger::FATAL - msg = log :warn, 'warn level message' - assert_equal '', msg.line - - @logger.level = Logger::ERROR - msg = log :warn, 'warn level message' - assert_equal '', msg.line - - @logger.level = Logger::WARN - msg = log :warn, 'warn level message' - assert_equal LEVEL_LABEL_MAP[Logger::WARN], msg.severity - - @logger.level = Logger::INFO - msg = log :warn, 'warn level message' - assert_equal LEVEL_LABEL_MAP[Logger::WARN], msg.severity - - @logger.level = Logger::DEBUG - msg = log :warn, 'warn level message' - assert_equal LEVEL_LABEL_MAP[Logger::WARN], msg.severity - end - - def test_warn_eh - @logger.level = Logger::WARN - assert_equal true, @logger.warn? - - @logger.level = Logger::ERROR - assert_equal false, @logger.warn? - end - - def test_info - msg = log :info, 'info level message' - assert_equal LEVEL_LABEL_MAP[Logger::INFO], msg.severity - - @logger.level = Logger::UNKNOWN - msg = log :info, 'info level message' - assert_equal '', msg.line - - @logger.level = Logger::FATAL - msg = log :info, 'info level message' - assert_equal '', msg.line - - @logger.level = Logger::ERROR - msg = log :info, 'info level message' - assert_equal '', msg.line - - @logger.level = Logger::WARN - msg = log :info, 'info level message' - assert_equal '', msg.line - - @logger.level = Logger::INFO - msg = log :info, 'info level message' - assert_equal LEVEL_LABEL_MAP[Logger::INFO], msg.severity - - @logger.level = Logger::DEBUG - msg = log :info, 'info level message' - assert_equal LEVEL_LABEL_MAP[Logger::INFO], msg.severity - end - - def test_info_eh - @logger.level = Logger::INFO - assert_equal true, @logger.info? - - @logger.level = Logger::WARN - assert_equal false, @logger.info? - end - - def test_debug - msg = log :debug, 'debug level message' - assert_equal LEVEL_LABEL_MAP[Logger::DEBUG], msg.severity - - @logger.level = Logger::UNKNOWN - msg = log :debug, 'debug level message' - assert_equal '', msg.line - - @logger.level = Logger::FATAL - msg = log :debug, 'debug level message' - assert_equal '', msg.line - - @logger.level = Logger::ERROR - msg = log :debug, 'debug level message' - assert_equal '', msg.line - - @logger.level = Logger::WARN - msg = log :debug, 'debug level message' - assert_equal '', msg.line - - @logger.level = Logger::INFO - msg = log :debug, 'debug level message' - assert_equal '', msg.line - - @logger.level = Logger::DEBUG - msg = log :debug, 'debug level message' - assert_equal LEVEL_LABEL_MAP[Logger::DEBUG], msg.severity - end - - def test_debug_eh - @logger.level = Logger::DEBUG - assert_equal true, @logger.debug? - - @logger.level = Logger::INFO - assert_equal false, @logger.debug? - end - -end if defined?(Syslog) - -class TestSyslogLogger < TestSyslogRootLogger - - @facility = Syslog::LOG_USER - - def facility - self.class.instance_variable_get("@facility") - end - - def setup - super - @logger = Syslog::Logger.new - end - - SEVERITY_MAP = {}.tap { |map| - level2severity = Syslog::Logger::LEVEL_MAP.invert - - MockSyslog::LEVEL_LABEL_MAP.each { |level, name| - map[name] = TestSyslogRootLogger::LEVEL_LABEL_MAP[level2severity[level]] - } - } - - class Log - attr_reader :line, :label, :datetime, :pid, :severity, :progname, :msg, :priority - def initialize(line) - @line = line - return unless /\A<(\d+)> (\w+) - (.*)\Z/ =~ @line - priority, severity, @msg = $1, $2, $3 - @severity = SEVERITY_MAP[severity] - @priority = priority.to_i - end - end - - def log_add(severity, msg, progname = nil, &block) - log(:add, severity, msg, progname, &block) - end - - def log(msg_id, *arg, &block) - Log.new(log_raw(msg_id, *arg, &block)) - end - - def log_raw(msg_id, *arg, &block) - assert_equal true, @logger.__send__(msg_id, *arg, &block) - msg = MockSyslog.line - MockSyslog.reset - return msg - end - - def test_unknown_eh - @logger.level = Logger::UNKNOWN - assert_equal true, @logger.unknown? - - @logger.level = Logger::UNKNOWN + 1 - assert_equal false, @logger.unknown? - end - - def test_facility - assert_equal facility, @logger.facility - end - - def test_priority - msg = log_add nil, 'unknown level message' # nil == unknown - assert_equal facility|Syslog::LOG_ALERT, msg.priority - - msg = log_add Logger::FATAL, 'fatal level message' - assert_equal facility|Syslog::LOG_ERR, msg.priority - - msg = log_add Logger::ERROR, 'error level message' - assert_equal facility|Syslog::LOG_WARNING, msg.priority - - msg = log_add Logger::WARN, 'warn level message' - assert_equal facility|Syslog::LOG_NOTICE, msg.priority - - msg = log_add Logger::INFO, 'info level message' - assert_equal facility|Syslog::LOG_INFO, msg.priority - - msg = log_add Logger::DEBUG, 'debug level message' - assert_equal facility|Syslog::LOG_DEBUG, msg.priority - end - - class CustomSyslogLogger < Syslog::Logger - def level - Logger::INFO - end - end - - def test_overriding_level - @logger = CustomSyslogLogger.new - log = log_add Logger::INFO, 'msg' - assert_equal 'msg', log.msg - - log = log_add Logger::DEBUG, 'msg' - assert_nil log.msg - end - -end if defined?(Syslog) - - -# Create test class for each available facility - -Syslog::Facility.constants.each do |facility_symb| - - test_syslog_class = Class.new(TestSyslogLogger) do - - @facility = Syslog.const_get(facility_symb) - - def setup - super - @logger.facility = facility - end - - end - Object.const_set("TestSyslogLogger_#{facility_symb}", test_syslog_class) - -end if defined?(Syslog) diff --git a/test/test_extlibs.rb b/test/test_extlibs.rb index d3688da76560f7..9b6676416cfc9d 100644 --- a/test/test_extlibs.rb +++ b/test/test_extlibs.rb @@ -34,7 +34,7 @@ def windows? end.flatten.compact excluded << '+' if excluded.empty? if windows? - excluded.map! {|i| i == '+' ? ['pty', 'syslog'] : i} + excluded.map! {|i| i == '+' ? ['pty'] : i} excluded.flatten! else excluded.map! {|i| i == '+' ? '*win32*' : i} @@ -68,7 +68,6 @@ def windows? check_existence "socket" check_existence "stringio" check_existence "strscan" - check_existence "syslog" check_existence "thread" check_existence "win32ole" check_existence "zlib", "this may be false positive, but should assert because rubygems requires this" From b5b98546cfb07988051877f08f84233665ab5fcd Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 22 Jan 2024 15:25:21 +0900 Subject: [PATCH 389/640] spec/mspec/tool/wrap_with_guard.rb 'ruby_version_is ""..."3.4"' spec/ruby/library/syslog/**/*.rb --- spec/ruby/library/syslog/alert_spec.rb | 13 +- spec/ruby/library/syslog/close_spec.rb | 107 ++++++++------- spec/ruby/library/syslog/constants_spec.rb | 57 ++++---- spec/ruby/library/syslog/crit_spec.rb | 13 +- spec/ruby/library/syslog/debug_spec.rb | 13 +- spec/ruby/library/syslog/emerg_spec.rb | 23 ++-- spec/ruby/library/syslog/err_spec.rb | 13 +- spec/ruby/library/syslog/facility_spec.rb | 87 ++++++------ spec/ruby/library/syslog/ident_spec.rb | 49 +++---- spec/ruby/library/syslog/info_spec.rb | 13 +- spec/ruby/library/syslog/inspect_spec.rb | 57 ++++---- spec/ruby/library/syslog/instance_spec.rb | 15 +- spec/ruby/library/syslog/log_spec.rb | 85 ++++++------ spec/ruby/library/syslog/mask_spec.rb | 151 +++++++++++---------- spec/ruby/library/syslog/notice_spec.rb | 13 +- spec/ruby/library/syslog/open_spec.rb | 141 +++++++++---------- spec/ruby/library/syslog/opened_spec.rb | 55 ++++---- spec/ruby/library/syslog/options_spec.rb | 87 ++++++------ spec/ruby/library/syslog/reopen_spec.rb | 13 +- spec/ruby/library/syslog/shared/log.rb | 66 ++++----- spec/ruby/library/syslog/shared/reopen.rb | 64 ++++----- spec/ruby/library/syslog/warning_spec.rb | 13 +- 22 files changed, 606 insertions(+), 542 deletions(-) diff --git a/spec/ruby/library/syslog/alert_spec.rb b/spec/ruby/library/syslog/alert_spec.rb index edff789dc960f7..a3a616bd6d88ba 100644 --- a/spec/ruby/library/syslog/alert_spec.rb +++ b/spec/ruby/library/syslog/alert_spec.rb @@ -1,10 +1,13 @@ require_relative '../../spec_helper' -platform_is_not :windows do - require_relative 'shared/log' - require 'syslog' +ruby_version_is ""..."3.4" do - describe "Syslog.alert" do - it_behaves_like :syslog_log, :alert + platform_is_not :windows do + require_relative 'shared/log' + require 'syslog' + + describe "Syslog.alert" do + it_behaves_like :syslog_log, :alert + end end end diff --git a/spec/ruby/library/syslog/close_spec.rb b/spec/ruby/library/syslog/close_spec.rb index 8c3b67c05bd8d6..60866de9715b4a 100644 --- a/spec/ruby/library/syslog/close_spec.rb +++ b/spec/ruby/library/syslog/close_spec.rb @@ -1,57 +1,60 @@ require_relative '../../spec_helper' -platform_is_not :windows do - require 'syslog' - - describe "Syslog.close" do - platform_is_not :windows do - - before :each do - Syslog.opened?.should be_false - end - - after :each do - Syslog.opened?.should be_false - end - - it "closes the log" do - Syslog.opened?.should be_false - Syslog.open - Syslog.opened?.should be_true - Syslog.close - Syslog.opened?.should be_false - end - - it "raises a RuntimeError if the log's already closed" do - -> { Syslog.close }.should raise_error(RuntimeError) - end - - it "it does not work inside blocks" do - -> { - Syslog.open { |s| s.close } - }.should raise_error(RuntimeError) - Syslog.should_not.opened? - end - - it "sets the identity to nil" do - Syslog.open("rubyspec") - Syslog.ident.should == "rubyspec" - Syslog.close - Syslog.ident.should be_nil - end - - it "sets the options to nil" do - Syslog.open("rubyspec", Syslog::LOG_PID) - Syslog.options.should == Syslog::LOG_PID - Syslog.close - Syslog.options.should == nil - end - - it "sets the facility to nil" do - Syslog.open - Syslog.facility.should == 8 - Syslog.close - Syslog.facility.should == nil +ruby_version_is ""..."3.4" do + + platform_is_not :windows do + require 'syslog' + + describe "Syslog.close" do + platform_is_not :windows do + + before :each do + Syslog.opened?.should be_false + end + + after :each do + Syslog.opened?.should be_false + end + + it "closes the log" do + Syslog.opened?.should be_false + Syslog.open + Syslog.opened?.should be_true + Syslog.close + Syslog.opened?.should be_false + end + + it "raises a RuntimeError if the log's already closed" do + -> { Syslog.close }.should raise_error(RuntimeError) + end + + it "it does not work inside blocks" do + -> { + Syslog.open { |s| s.close } + }.should raise_error(RuntimeError) + Syslog.should_not.opened? + end + + it "sets the identity to nil" do + Syslog.open("rubyspec") + Syslog.ident.should == "rubyspec" + Syslog.close + Syslog.ident.should be_nil + end + + it "sets the options to nil" do + Syslog.open("rubyspec", Syslog::LOG_PID) + Syslog.options.should == Syslog::LOG_PID + Syslog.close + Syslog.options.should == nil + end + + it "sets the facility to nil" do + Syslog.open + Syslog.facility.should == 8 + Syslog.close + Syslog.facility.should == nil + end end end end diff --git a/spec/ruby/library/syslog/constants_spec.rb b/spec/ruby/library/syslog/constants_spec.rb index 2b9524c53d847d..d44d67e2de8cb9 100644 --- a/spec/ruby/library/syslog/constants_spec.rb +++ b/spec/ruby/library/syslog/constants_spec.rb @@ -1,40 +1,43 @@ require_relative '../../spec_helper' -platform_is_not :windows do - require 'syslog' +ruby_version_is ""..."3.4" do - describe "Syslog::Constants" do - platform_is_not :windows, :solaris, :aix do - before :all do - @constants = %w(LOG_AUTHPRIV LOG_USER LOG_LOCAL2 LOG_NOTICE LOG_NDELAY - LOG_SYSLOG LOG_ALERT LOG_FTP LOG_LOCAL5 LOG_ERR LOG_AUTH - LOG_LOCAL1 LOG_ODELAY LOG_NEWS LOG_DAEMON LOG_LOCAL4 - LOG_CRIT LOG_INFO LOG_PERROR LOG_LOCAL0 LOG_CONS LOG_LPR - LOG_LOCAL7 LOG_WARNING LOG_CRON LOG_LOCAL3 LOG_EMERG - LOG_NOWAIT LOG_UUCP LOG_PID LOG_KERN LOG_MAIL LOG_LOCAL6 - LOG_DEBUG) - end + platform_is_not :windows do + require 'syslog' + + describe "Syslog::Constants" do + platform_is_not :windows, :solaris, :aix do + before :all do + @constants = %w(LOG_AUTHPRIV LOG_USER LOG_LOCAL2 LOG_NOTICE LOG_NDELAY + LOG_SYSLOG LOG_ALERT LOG_FTP LOG_LOCAL5 LOG_ERR LOG_AUTH + LOG_LOCAL1 LOG_ODELAY LOG_NEWS LOG_DAEMON LOG_LOCAL4 + LOG_CRIT LOG_INFO LOG_PERROR LOG_LOCAL0 LOG_CONS LOG_LPR + LOG_LOCAL7 LOG_WARNING LOG_CRON LOG_LOCAL3 LOG_EMERG + LOG_NOWAIT LOG_UUCP LOG_PID LOG_KERN LOG_MAIL LOG_LOCAL6 + LOG_DEBUG) + end - it "includes the Syslog constants" do - @constants.each do |c| - Syslog::Constants.should have_constant(c) + it "includes the Syslog constants" do + @constants.each do |c| + Syslog::Constants.should have_constant(c) + end end end - end - # The masks are defined in + # The masks are defined in - describe "Syslog::Constants.LOG_MASK" do - it "returns the mask value for a priority" do - Syslog::Constants.LOG_MASK(Syslog::LOG_DEBUG).should == 128 - Syslog::Constants.LOG_MASK(Syslog::LOG_WARNING).should == 16 + describe "Syslog::Constants.LOG_MASK" do + it "returns the mask value for a priority" do + Syslog::Constants.LOG_MASK(Syslog::LOG_DEBUG).should == 128 + Syslog::Constants.LOG_MASK(Syslog::LOG_WARNING).should == 16 + end end - end - describe "Syslog::Constants.LOG_UPTO" do - it "returns a mask for the priorities up to a given argument" do - Syslog::Constants.LOG_UPTO(Syslog::LOG_ALERT).should == 3 - Syslog::Constants.LOG_UPTO(Syslog::LOG_DEBUG).should == 255 + describe "Syslog::Constants.LOG_UPTO" do + it "returns a mask for the priorities up to a given argument" do + Syslog::Constants.LOG_UPTO(Syslog::LOG_ALERT).should == 3 + Syslog::Constants.LOG_UPTO(Syslog::LOG_DEBUG).should == 255 + end end end end diff --git a/spec/ruby/library/syslog/crit_spec.rb b/spec/ruby/library/syslog/crit_spec.rb index 5d3904f7196e47..d7841ac0102c39 100644 --- a/spec/ruby/library/syslog/crit_spec.rb +++ b/spec/ruby/library/syslog/crit_spec.rb @@ -1,10 +1,13 @@ require_relative '../../spec_helper' -platform_is_not :windows do - require_relative 'shared/log' - require 'syslog' +ruby_version_is ""..."3.4" do - describe "Syslog.crit" do - it_behaves_like :syslog_log, :crit + platform_is_not :windows do + require_relative 'shared/log' + require 'syslog' + + describe "Syslog.crit" do + it_behaves_like :syslog_log, :crit + end end end diff --git a/spec/ruby/library/syslog/debug_spec.rb b/spec/ruby/library/syslog/debug_spec.rb index d03e8a88c9f691..94e640c74131dc 100644 --- a/spec/ruby/library/syslog/debug_spec.rb +++ b/spec/ruby/library/syslog/debug_spec.rb @@ -1,10 +1,13 @@ require_relative '../../spec_helper' -platform_is_not :windows do - require_relative 'shared/log' - require 'syslog' +ruby_version_is ""..."3.4" do - describe "Syslog.debug" do - it_behaves_like :syslog_log, :debug + platform_is_not :windows do + require_relative 'shared/log' + require 'syslog' + + describe "Syslog.debug" do + it_behaves_like :syslog_log, :debug + end end end diff --git a/spec/ruby/library/syslog/emerg_spec.rb b/spec/ruby/library/syslog/emerg_spec.rb index 2ab4d60291cb20..86938ce8897c59 100644 --- a/spec/ruby/library/syslog/emerg_spec.rb +++ b/spec/ruby/library/syslog/emerg_spec.rb @@ -1,16 +1,19 @@ require_relative '../../spec_helper' -platform_is_not :windows do - require_relative 'shared/log' - require 'syslog' +ruby_version_is ""..."3.4" do - describe "Syslog.emerg" do - # Some way needs do be found to prevent this spec - # from causing output on all open terminals. If this - # is not possible, this spec may need a special guard - # that only runs when requested. - quarantine! do - it_behaves_like :syslog_log, :emerg + platform_is_not :windows do + require_relative 'shared/log' + require 'syslog' + + describe "Syslog.emerg" do + # Some way needs do be found to prevent this spec + # from causing output on all open terminals. If this + # is not possible, this spec may need a special guard + # that only runs when requested. + quarantine! do + it_behaves_like :syslog_log, :emerg + end end end end diff --git a/spec/ruby/library/syslog/err_spec.rb b/spec/ruby/library/syslog/err_spec.rb index 43e876ed3782a6..a7b39ea5c0abe7 100644 --- a/spec/ruby/library/syslog/err_spec.rb +++ b/spec/ruby/library/syslog/err_spec.rb @@ -1,10 +1,13 @@ require_relative '../../spec_helper' -platform_is_not :windows do - require_relative 'shared/log' - require 'syslog' +ruby_version_is ""..."3.4" do - describe "Syslog.err" do - it_behaves_like :syslog_log, :err + platform_is_not :windows do + require_relative 'shared/log' + require 'syslog' + + describe "Syslog.err" do + it_behaves_like :syslog_log, :err + end end end diff --git a/spec/ruby/library/syslog/facility_spec.rb b/spec/ruby/library/syslog/facility_spec.rb index 550ca70b112cf9..1129dd9ee3e28a 100644 --- a/spec/ruby/library/syslog/facility_spec.rb +++ b/spec/ruby/library/syslog/facility_spec.rb @@ -1,47 +1,50 @@ require_relative '../../spec_helper' -platform_is_not :windows do - require 'syslog' - - describe "Syslog.facility" do - platform_is_not :windows do - - before :each do - Syslog.opened?.should be_false - end - - after :each do - Syslog.opened?.should be_false - end - - it "returns the logging facility" do - Syslog.open("rubyspec", 3, Syslog::LOG_MAIL) - Syslog.facility.should == Syslog::LOG_MAIL - Syslog.close - end - - it "returns nil if the log is closed" do - Syslog.opened?.should be_false - Syslog.facility.should == nil - end - - it "defaults to LOG_USER" do - Syslog.open - Syslog.facility.should == Syslog::LOG_USER - Syslog.close - end - - it "resets after each open call" do - Syslog.open - Syslog.facility.should == Syslog::LOG_USER - - Syslog.open!("rubyspec", 3, Syslog::LOG_MAIL) - Syslog.facility.should == Syslog::LOG_MAIL - Syslog.close - - Syslog.open - Syslog.facility.should == Syslog::LOG_USER - Syslog.close +ruby_version_is ""..."3.4" do + + platform_is_not :windows do + require 'syslog' + + describe "Syslog.facility" do + platform_is_not :windows do + + before :each do + Syslog.opened?.should be_false + end + + after :each do + Syslog.opened?.should be_false + end + + it "returns the logging facility" do + Syslog.open("rubyspec", 3, Syslog::LOG_MAIL) + Syslog.facility.should == Syslog::LOG_MAIL + Syslog.close + end + + it "returns nil if the log is closed" do + Syslog.opened?.should be_false + Syslog.facility.should == nil + end + + it "defaults to LOG_USER" do + Syslog.open + Syslog.facility.should == Syslog::LOG_USER + Syslog.close + end + + it "resets after each open call" do + Syslog.open + Syslog.facility.should == Syslog::LOG_USER + + Syslog.open!("rubyspec", 3, Syslog::LOG_MAIL) + Syslog.facility.should == Syslog::LOG_MAIL + Syslog.close + + Syslog.open + Syslog.facility.should == Syslog::LOG_USER + Syslog.close + end end end end diff --git a/spec/ruby/library/syslog/ident_spec.rb b/spec/ruby/library/syslog/ident_spec.rb index 3b083271406a68..524e56037389df 100644 --- a/spec/ruby/library/syslog/ident_spec.rb +++ b/spec/ruby/library/syslog/ident_spec.rb @@ -1,34 +1,37 @@ require_relative '../../spec_helper' -platform_is_not :windows do - require 'syslog' +ruby_version_is ""..."3.4" do - describe "Syslog.ident" do - platform_is_not :windows do + platform_is_not :windows do + require 'syslog' - before :each do - Syslog.opened?.should be_false - end + describe "Syslog.ident" do + platform_is_not :windows do - after :each do - Syslog.opened?.should be_false - end + before :each do + Syslog.opened?.should be_false + end - it "returns the logging identity" do - Syslog.open("rubyspec") - Syslog.ident.should == "rubyspec" - Syslog.close - end + after :each do + Syslog.opened?.should be_false + end - it "returns nil if the log is closed" do - Syslog.should_not.opened? - Syslog.ident.should == nil - end + it "returns the logging identity" do + Syslog.open("rubyspec") + Syslog.ident.should == "rubyspec" + Syslog.close + end + + it "returns nil if the log is closed" do + Syslog.should_not.opened? + Syslog.ident.should == nil + end - it "defaults to $0" do - Syslog.open - Syslog.ident.should == $0 - Syslog.close + it "defaults to $0" do + Syslog.open + Syslog.ident.should == $0 + Syslog.close + end end end end diff --git a/spec/ruby/library/syslog/info_spec.rb b/spec/ruby/library/syslog/info_spec.rb index f2d535299c58a2..03bb6f6003b73d 100644 --- a/spec/ruby/library/syslog/info_spec.rb +++ b/spec/ruby/library/syslog/info_spec.rb @@ -1,10 +1,13 @@ require_relative '../../spec_helper' -platform_is_not :windows do - require_relative 'shared/log' - require 'syslog' +ruby_version_is ""..."3.4" do - describe "Syslog.info" do - it_behaves_like :syslog_log, :info + platform_is_not :windows do + require_relative 'shared/log' + require 'syslog' + + describe "Syslog.info" do + it_behaves_like :syslog_log, :info + end end end diff --git a/spec/ruby/library/syslog/inspect_spec.rb b/spec/ruby/library/syslog/inspect_spec.rb index f45231f8e31def..5e1e09e86fccb5 100644 --- a/spec/ruby/library/syslog/inspect_spec.rb +++ b/spec/ruby/library/syslog/inspect_spec.rb @@ -1,38 +1,41 @@ require_relative '../../spec_helper' -platform_is_not :windows do - require 'syslog' +ruby_version_is ""..."3.4" do - describe "Syslog.inspect" do - platform_is_not :windows do + platform_is_not :windows do + require 'syslog' - before :each do - Syslog.opened?.should be_false - end + describe "Syslog.inspect" do + platform_is_not :windows do - after :each do - Syslog.opened?.should be_false - end + before :each do + Syslog.opened?.should be_false + end - it "returns a string a closed log" do - Syslog.inspect.should =~ /opened=false/ - end + after :each do + Syslog.opened?.should be_false + end - it "returns a string for an opened log" do - Syslog.open - Syslog.inspect.should =~ /opened=true.*/ - Syslog.close - end + it "returns a string a closed log" do + Syslog.inspect.should =~ /opened=false/ + end + + it "returns a string for an opened log" do + Syslog.open + Syslog.inspect.should =~ /opened=true.*/ + Syslog.close + end - it "includes the ident, options, facility and mask" do - Syslog.open("rubyspec", Syslog::LOG_PID, Syslog::LOG_USER) - inspect_str = Syslog.inspect.split ", " - inspect_str[0].should =~ /opened=true/ - inspect_str[1].should == "ident=\"rubyspec\"" - inspect_str[2].should == "options=#{Syslog::LOG_PID}" - inspect_str[3].should == "facility=#{Syslog::LOG_USER}" - inspect_str[4].should == "mask=255>" - Syslog.close + it "includes the ident, options, facility and mask" do + Syslog.open("rubyspec", Syslog::LOG_PID, Syslog::LOG_USER) + inspect_str = Syslog.inspect.split ", " + inspect_str[0].should =~ /opened=true/ + inspect_str[1].should == "ident=\"rubyspec\"" + inspect_str[2].should == "options=#{Syslog::LOG_PID}" + inspect_str[3].should == "facility=#{Syslog::LOG_USER}" + inspect_str[4].should == "mask=255>" + Syslog.close + end end end end diff --git a/spec/ruby/library/syslog/instance_spec.rb b/spec/ruby/library/syslog/instance_spec.rb index 891296c52d1a0a..b7a7d122f0990c 100644 --- a/spec/ruby/library/syslog/instance_spec.rb +++ b/spec/ruby/library/syslog/instance_spec.rb @@ -1,12 +1,15 @@ require_relative '../../spec_helper' -platform_is_not :windows do - require 'syslog' +ruby_version_is ""..."3.4" do - describe "Syslog.instance" do - platform_is_not :windows do - it "returns the module" do - Syslog.instance.should == Syslog + platform_is_not :windows do + require 'syslog' + + describe "Syslog.instance" do + platform_is_not :windows do + it "returns the module" do + Syslog.instance.should == Syslog + end end end end diff --git a/spec/ruby/library/syslog/log_spec.rb b/spec/ruby/library/syslog/log_spec.rb index 8589fb1f7332ce..749d825c104afa 100644 --- a/spec/ruby/library/syslog/log_spec.rb +++ b/spec/ruby/library/syslog/log_spec.rb @@ -1,55 +1,58 @@ require_relative '../../spec_helper' -platform_is_not :windows do - require 'syslog' +ruby_version_is ""..."3.4" do - describe "Syslog.log" do - platform_is_not :windows, :darwin, :solaris, :aix, :android do + platform_is_not :windows do + require 'syslog' - before :each do - Syslog.opened?.should be_false - end - - after :each do - Syslog.opened?.should be_false - end + describe "Syslog.log" do + platform_is_not :windows, :darwin, :solaris, :aix, :android do - it "receives a priority as first argument" do - -> { - Syslog.open("rubyspec", Syslog::LOG_PERROR) do |s| - s.log(Syslog::LOG_ALERT, "Hello") - s.log(Syslog::LOG_CRIT, "World") - end - }.should output_to_fd(/\Arubyspec(?::| \d+ - -) Hello\nrubyspec(?::| \d+ - -) World\n\z/, $stderr) - end + before :each do + Syslog.opened?.should be_false + end - it "accepts undefined priorities" do - -> { - Syslog.open("rubyspec", Syslog::LOG_PERROR) do |s| - s.log(1337, "Hello") - end - # use a regex since it'll output unknown facility/priority messages - }.should output_to_fd(/rubyspec(?::| \d+ - -) Hello\n\z/, $stderr) - end + after :each do + Syslog.opened?.should be_false + end - it "fails with TypeError on nil log messages" do - Syslog.open do |s| - -> { s.log(1, nil) }.should raise_error(TypeError) + it "receives a priority as first argument" do + -> { + Syslog.open("rubyspec", Syslog::LOG_PERROR) do |s| + s.log(Syslog::LOG_ALERT, "Hello") + s.log(Syslog::LOG_CRIT, "World") + end + }.should output_to_fd(/\Arubyspec(?::| \d+ - -) Hello\nrubyspec(?::| \d+ - -) World\n\z/, $stderr) end - end - it "fails if the log is closed" do - -> { - Syslog.log(Syslog::LOG_ALERT, "test") - }.should raise_error(RuntimeError) - end + it "accepts undefined priorities" do + -> { + Syslog.open("rubyspec", Syslog::LOG_PERROR) do |s| + s.log(1337, "Hello") + end + # use a regex since it'll output unknown facility/priority messages + }.should output_to_fd(/rubyspec(?::| \d+ - -) Hello\n\z/, $stderr) + end - it "accepts printf parameters" do - -> { - Syslog.open("rubyspec", Syslog::LOG_PERROR) do |s| - s.log(Syslog::LOG_ALERT, "%s x %d", "chunky bacon", 2) + it "fails with TypeError on nil log messages" do + Syslog.open do |s| + -> { s.log(1, nil) }.should raise_error(TypeError) end - }.should output_to_fd(/rubyspec(?::| \d+ - -) chunky bacon x 2\n\z/, $stderr) + end + + it "fails if the log is closed" do + -> { + Syslog.log(Syslog::LOG_ALERT, "test") + }.should raise_error(RuntimeError) + end + + it "accepts printf parameters" do + -> { + Syslog.open("rubyspec", Syslog::LOG_PERROR) do |s| + s.log(Syslog::LOG_ALERT, "%s x %d", "chunky bacon", 2) + end + }.should output_to_fd(/rubyspec(?::| \d+ - -) chunky bacon x 2\n\z/, $stderr) + end end end end diff --git a/spec/ruby/library/syslog/mask_spec.rb b/spec/ruby/library/syslog/mask_spec.rb index b3f1250b24ac9d..05c64ceec89c05 100644 --- a/spec/ruby/library/syslog/mask_spec.rb +++ b/spec/ruby/library/syslog/mask_spec.rb @@ -1,111 +1,114 @@ require_relative '../../spec_helper' -platform_is_not :windows do - require 'syslog' +ruby_version_is ""..."3.4" do - describe "Syslog.mask" do - platform_is_not :windows do + platform_is_not :windows do + require 'syslog' - before :each do - Syslog.opened?.should be_false - end + describe "Syslog.mask" do + platform_is_not :windows do - after :each do - Syslog.opened?.should be_false - # make sure we return the mask to the default value - Syslog.open { |s| s.mask = 255 } - end + before :each do + Syslog.opened?.should be_false + end - it "returns the log priority mask" do - Syslog.open("rubyspec") do - Syslog.mask.should == 255 - Syslog.mask = 3 - Syslog.mask.should == 3 - Syslog.mask = 255 + after :each do + Syslog.opened?.should be_false + # make sure we return the mask to the default value + Syslog.open { |s| s.mask = 255 } end - end - it "defaults to 255" do - Syslog.open do |s| - s.mask.should == 255 + it "returns the log priority mask" do + Syslog.open("rubyspec") do + Syslog.mask.should == 255 + Syslog.mask = 3 + Syslog.mask.should == 3 + Syslog.mask = 255 + end end - end - it "returns nil if the log is closed" do - Syslog.should_not.opened? - Syslog.mask.should == nil - end + it "defaults to 255" do + Syslog.open do |s| + s.mask.should == 255 + end + end - platform_is :darwin do - it "resets if the log is reopened" do - Syslog.open - Syslog.mask.should == 255 - Syslog.mask = 64 + it "returns nil if the log is closed" do + Syslog.should_not.opened? + Syslog.mask.should == nil + end - Syslog.reopen("rubyspec") do + platform_is :darwin do + it "resets if the log is reopened" do + Syslog.open Syslog.mask.should == 255 - end + Syslog.mask = 64 - Syslog.open do - Syslog.mask.should == 255 + Syslog.reopen("rubyspec") do + Syslog.mask.should == 255 + end + + Syslog.open do + Syslog.mask.should == 255 + end end end - end - platform_is_not :darwin do - it "persists if the log is reopened" do - Syslog.open - Syslog.mask.should == 255 - Syslog.mask = 64 + platform_is_not :darwin do + it "persists if the log is reopened" do + Syslog.open + Syslog.mask.should == 255 + Syslog.mask = 64 - Syslog.reopen("rubyspec") do - Syslog.mask.should == 64 - end + Syslog.reopen("rubyspec") do + Syslog.mask.should == 64 + end - Syslog.open do - Syslog.mask.should == 64 + Syslog.open do + Syslog.mask.should == 64 + end end end end end - end - describe "Syslog.mask=" do - platform_is_not :windows do + describe "Syslog.mask=" do + platform_is_not :windows do - before :each do - Syslog.opened?.should be_false - end + before :each do + Syslog.opened?.should be_false + end - after :each do - Syslog.opened?.should be_false - # make sure we return the mask to the default value - Syslog.open { |s| s.mask = 255 } - end + after :each do + Syslog.opened?.should be_false + # make sure we return the mask to the default value + Syslog.open { |s| s.mask = 255 } + end - it "sets the log priority mask" do - Syslog.open do - Syslog.mask = 64 - Syslog.mask.should == 64 + it "sets the log priority mask" do + Syslog.open do + Syslog.mask = 64 + Syslog.mask.should == 64 + end end - end - it "raises an error if the log is closed" do - -> { Syslog.mask = 1337 }.should raise_error(RuntimeError) - end + it "raises an error if the log is closed" do + -> { Syslog.mask = 1337 }.should raise_error(RuntimeError) + end - it "only accepts numbers" do - Syslog.open do + it "only accepts numbers" do + Syslog.open do - Syslog.mask = 1337 - Syslog.mask.should == 1337 + Syslog.mask = 1337 + Syslog.mask.should == 1337 - Syslog.mask = 3.1416 - Syslog.mask.should == 3 + Syslog.mask = 3.1416 + Syslog.mask.should == 3 - -> { Syslog.mask = "oh hai" }.should raise_error(TypeError) - -> { Syslog.mask = "43" }.should raise_error(TypeError) + -> { Syslog.mask = "oh hai" }.should raise_error(TypeError) + -> { Syslog.mask = "43" }.should raise_error(TypeError) + end end end end diff --git a/spec/ruby/library/syslog/notice_spec.rb b/spec/ruby/library/syslog/notice_spec.rb index a2134e0140f15b..41c175cb49f702 100644 --- a/spec/ruby/library/syslog/notice_spec.rb +++ b/spec/ruby/library/syslog/notice_spec.rb @@ -1,10 +1,13 @@ require_relative '../../spec_helper' -platform_is_not :windows do - require_relative 'shared/log' - require 'syslog' +ruby_version_is ""..."3.4" do - describe "Syslog.notice" do - it_behaves_like :syslog_log, :notice + platform_is_not :windows do + require_relative 'shared/log' + require 'syslog' + + describe "Syslog.notice" do + it_behaves_like :syslog_log, :notice + end end end diff --git a/spec/ruby/library/syslog/open_spec.rb b/spec/ruby/library/syslog/open_spec.rb index 543f5d418b3c09..9cd65cda4a107f 100644 --- a/spec/ruby/library/syslog/open_spec.rb +++ b/spec/ruby/library/syslog/open_spec.rb @@ -1,92 +1,95 @@ require_relative '../../spec_helper' -platform_is_not :windows do - require_relative 'shared/reopen' - require 'syslog' +ruby_version_is ""..."3.4" do - describe "Syslog.open" do - platform_is_not :windows do + platform_is_not :windows do + require_relative 'shared/reopen' + require 'syslog' - before :each do - Syslog.opened?.should be_false - end + describe "Syslog.open" do + platform_is_not :windows do - after :each do - Syslog.opened?.should be_false - end + before :each do + Syslog.opened?.should be_false + end - it "returns the module" do - Syslog.open.should == Syslog - Syslog.close - Syslog.open("Test", 5, 9).should == Syslog - Syslog.close - end + after :each do + Syslog.opened?.should be_false + end - it "receives an identity as first argument" do - Syslog.open("rubyspec") - Syslog.ident.should == "rubyspec" - Syslog.close - end + it "returns the module" do + Syslog.open.should == Syslog + Syslog.close + Syslog.open("Test", 5, 9).should == Syslog + Syslog.close + end - it "defaults the identity to $0" do - Syslog.open - Syslog.ident.should == $0 - Syslog.close - end + it "receives an identity as first argument" do + Syslog.open("rubyspec") + Syslog.ident.should == "rubyspec" + Syslog.close + end - it "receives the logging options as second argument" do - Syslog.open("rubyspec", Syslog::LOG_PID) - Syslog.options.should == Syslog::LOG_PID - Syslog.close - end + it "defaults the identity to $0" do + Syslog.open + Syslog.ident.should == $0 + Syslog.close + end - it "defaults the logging options to LOG_PID | LOG_CONS" do - Syslog.open - Syslog.options.should == Syslog::LOG_PID | Syslog::LOG_CONS - Syslog.close - end + it "receives the logging options as second argument" do + Syslog.open("rubyspec", Syslog::LOG_PID) + Syslog.options.should == Syslog::LOG_PID + Syslog.close + end - it "receives a facility as third argument" do - Syslog.open("rubyspec", Syslog::LOG_PID, 0) - Syslog.facility.should == 0 - Syslog.close - end + it "defaults the logging options to LOG_PID | LOG_CONS" do + Syslog.open + Syslog.options.should == Syslog::LOG_PID | Syslog::LOG_CONS + Syslog.close + end - it "defaults the facility to LOG_USER" do - Syslog.open - Syslog.facility.should == Syslog::LOG_USER - Syslog.close - end + it "receives a facility as third argument" do + Syslog.open("rubyspec", Syslog::LOG_PID, 0) + Syslog.facility.should == 0 + Syslog.close + end + + it "defaults the facility to LOG_USER" do + Syslog.open + Syslog.facility.should == Syslog::LOG_USER + Syslog.close + end - it "receives a block and calls it with the module" do - Syslog.open("rubyspec", 3, 8) do |s| - s.should == Syslog - s.ident.should == "rubyspec" - s.options.should == 3 - s.facility.should == Syslog::LOG_USER + it "receives a block and calls it with the module" do + Syslog.open("rubyspec", 3, 8) do |s| + s.should == Syslog + s.ident.should == "rubyspec" + s.options.should == 3 + s.facility.should == Syslog::LOG_USER + end end - end - it "closes the log if after it receives a block" do - Syslog.open{ } - Syslog.opened?.should be_false - end + it "closes the log if after it receives a block" do + Syslog.open{ } + Syslog.opened?.should be_false + end - it "raises an error if the log is opened" do - Syslog.open - -> { + it "raises an error if the log is opened" do Syslog.open - }.should raise_error(RuntimeError, /syslog already open/) - -> { + -> { + Syslog.open + }.should raise_error(RuntimeError, /syslog already open/) + -> { + Syslog.close + Syslog.open + }.should_not raise_error Syslog.close - Syslog.open - }.should_not raise_error - Syslog.close + end end end - end - describe "Syslog.open!" do - it_behaves_like :syslog_reopen, :open! + describe "Syslog.open!" do + it_behaves_like :syslog_reopen, :open! + end end end diff --git a/spec/ruby/library/syslog/opened_spec.rb b/spec/ruby/library/syslog/opened_spec.rb index 94432e65a440d7..ee7a884a50fce0 100644 --- a/spec/ruby/library/syslog/opened_spec.rb +++ b/spec/ruby/library/syslog/opened_spec.rb @@ -1,38 +1,41 @@ require_relative '../../spec_helper' -platform_is_not :windows do - require 'syslog' +ruby_version_is ""..."3.4" do - describe "Syslog.opened?" do - platform_is_not :windows do + platform_is_not :windows do + require 'syslog' - before :each do - Syslog.opened?.should be_false - end - - after :each do - Syslog.opened?.should be_false - end + describe "Syslog.opened?" do + platform_is_not :windows do - it "returns true if the log is opened" do - Syslog.open - Syslog.opened?.should be_true - Syslog.close - end + before :each do + Syslog.opened?.should be_false + end - it "returns false otherwise" do - Syslog.opened?.should be_false - Syslog.open - Syslog.close - Syslog.opened?.should be_false - end + after :each do + Syslog.opened?.should be_false + end - it "works inside a block" do - Syslog.open do |s| - s.opened?.should be_true + it "returns true if the log is opened" do + Syslog.open Syslog.opened?.should be_true + Syslog.close + end + + it "returns false otherwise" do + Syslog.opened?.should be_false + Syslog.open + Syslog.close + Syslog.opened?.should be_false + end + + it "works inside a block" do + Syslog.open do |s| + s.opened?.should be_true + Syslog.opened?.should be_true + end + Syslog.opened?.should be_false end - Syslog.opened?.should be_false end end end diff --git a/spec/ruby/library/syslog/options_spec.rb b/spec/ruby/library/syslog/options_spec.rb index 83ba43503ec674..814f7daee60a68 100644 --- a/spec/ruby/library/syslog/options_spec.rb +++ b/spec/ruby/library/syslog/options_spec.rb @@ -1,47 +1,50 @@ require_relative '../../spec_helper' -platform_is_not :windows do - require 'syslog' - - describe "Syslog.options" do - platform_is_not :windows do - - before :each do - Syslog.opened?.should be_false - end - - after :each do - Syslog.opened?.should be_false - end - - it "returns the logging options" do - Syslog.open("rubyspec", Syslog::LOG_PID) - Syslog.options.should == Syslog::LOG_PID - Syslog.close - end - - it "returns nil when the log is closed" do - Syslog.opened?.should be_false - Syslog.options.should == nil - end - - it "defaults to LOG_PID | LOG_CONS" do - Syslog.open - Syslog.options.should == Syslog::LOG_PID | Syslog::LOG_CONS - Syslog.close - end - - it "resets after each open call" do - Syslog.open - Syslog.options.should == Syslog::LOG_PID | Syslog::LOG_CONS - - Syslog.open!("rubyspec", Syslog::LOG_PID) - Syslog.options.should == Syslog::LOG_PID - Syslog.close - - Syslog.open - Syslog.options.should == Syslog::LOG_PID | Syslog::LOG_CONS - Syslog.close +ruby_version_is ""..."3.4" do + + platform_is_not :windows do + require 'syslog' + + describe "Syslog.options" do + platform_is_not :windows do + + before :each do + Syslog.opened?.should be_false + end + + after :each do + Syslog.opened?.should be_false + end + + it "returns the logging options" do + Syslog.open("rubyspec", Syslog::LOG_PID) + Syslog.options.should == Syslog::LOG_PID + Syslog.close + end + + it "returns nil when the log is closed" do + Syslog.opened?.should be_false + Syslog.options.should == nil + end + + it "defaults to LOG_PID | LOG_CONS" do + Syslog.open + Syslog.options.should == Syslog::LOG_PID | Syslog::LOG_CONS + Syslog.close + end + + it "resets after each open call" do + Syslog.open + Syslog.options.should == Syslog::LOG_PID | Syslog::LOG_CONS + + Syslog.open!("rubyspec", Syslog::LOG_PID) + Syslog.options.should == Syslog::LOG_PID + Syslog.close + + Syslog.open + Syslog.options.should == Syslog::LOG_PID | Syslog::LOG_CONS + Syslog.close + end end end end diff --git a/spec/ruby/library/syslog/reopen_spec.rb b/spec/ruby/library/syslog/reopen_spec.rb index a78529fa1fe083..47861bc1c0df39 100644 --- a/spec/ruby/library/syslog/reopen_spec.rb +++ b/spec/ruby/library/syslog/reopen_spec.rb @@ -1,10 +1,13 @@ require_relative '../../spec_helper' -platform_is_not :windows do - require_relative 'shared/reopen' - require 'syslog' +ruby_version_is ""..."3.4" do - describe "Syslog.reopen" do - it_behaves_like :syslog_reopen, :reopen + platform_is_not :windows do + require_relative 'shared/reopen' + require 'syslog' + + describe "Syslog.reopen" do + it_behaves_like :syslog_reopen, :reopen + end end end diff --git a/spec/ruby/library/syslog/shared/log.rb b/spec/ruby/library/syslog/shared/log.rb index 12e4ea8366a2e3..d6daf3cc67c9a7 100644 --- a/spec/ruby/library/syslog/shared/log.rb +++ b/spec/ruby/library/syslog/shared/log.rb @@ -1,39 +1,41 @@ -describe :syslog_log, shared: true do - platform_is_not :windows, :darwin, :solaris, :aix, :android do - before :each do - Syslog.opened?.should be_false - end +ruby_version_is ""..."3.4" do + describe :syslog_log, shared: true do + platform_is_not :windows, :darwin, :solaris, :aix, :android do + before :each do + Syslog.opened?.should be_false + end - after :each do - Syslog.opened?.should be_false - end + after :each do + Syslog.opened?.should be_false + end - it "logs a message" do - -> { - Syslog.open("rubyspec", Syslog::LOG_PERROR) do - Syslog.send(@method, "Hello") - end - }.should output_to_fd(/\Arubyspec(?::| \d+ - -) Hello\n\z/, $stderr) - end + it "logs a message" do + -> { + Syslog.open("rubyspec", Syslog::LOG_PERROR) do + Syslog.send(@method, "Hello") + end + }.should output_to_fd(/\Arubyspec(?::| \d+ - -) Hello\n\z/, $stderr) + end - it "accepts sprintf arguments" do - -> { - Syslog.open("rubyspec", Syslog::LOG_PERROR) do - Syslog.send(@method, "Hello %s", "world") - Syslog.send(@method, "%d dogs", 2) - end - }.should output_to_fd(/\Arubyspec(?::| \d+ - -) Hello world\nrubyspec(?::| \d+ - -) 2 dogs\n\z/, $stderr) - end + it "accepts sprintf arguments" do + -> { + Syslog.open("rubyspec", Syslog::LOG_PERROR) do + Syslog.send(@method, "Hello %s", "world") + Syslog.send(@method, "%d dogs", 2) + end + }.should output_to_fd(/\Arubyspec(?::| \d+ - -) Hello world\nrubyspec(?::| \d+ - -) 2 dogs\n\z/, $stderr) + end - it "works as an alias for Syslog.log" do - level = Syslog.const_get "LOG_#{@method.to_s.upcase}" - -> { - Syslog.open("rubyspec", Syslog::LOG_PERROR) do - Syslog.send(@method, "Hello") - Syslog.log(level, "Hello") - end - # make sure the same thing is written to $stderr. - }.should output_to_fd(/\A(?:rubyspec(?::| \d+ - -) Hello\n){2}\z/, $stderr) + it "works as an alias for Syslog.log" do + level = Syslog.const_get "LOG_#{@method.to_s.upcase}" + -> { + Syslog.open("rubyspec", Syslog::LOG_PERROR) do + Syslog.send(@method, "Hello") + Syslog.log(level, "Hello") + end + # make sure the same thing is written to $stderr. + }.should output_to_fd(/\A(?:rubyspec(?::| \d+ - -) Hello\n){2}\z/, $stderr) + end end end end diff --git a/spec/ruby/library/syslog/shared/reopen.rb b/spec/ruby/library/syslog/shared/reopen.rb index 621437a01d8528..935349010bed7f 100644 --- a/spec/ruby/library/syslog/shared/reopen.rb +++ b/spec/ruby/library/syslog/shared/reopen.rb @@ -1,40 +1,42 @@ -describe :syslog_reopen, shared: true do - platform_is_not :windows do - before :each do - Syslog.opened?.should be_false - end +ruby_version_is ""..."3.4" do + describe :syslog_reopen, shared: true do + platform_is_not :windows do + before :each do + Syslog.opened?.should be_false + end - after :each do - Syslog.opened?.should be_false - end + after :each do + Syslog.opened?.should be_false + end - it "reopens the log" do - Syslog.open - -> { Syslog.send(@method)}.should_not raise_error - Syslog.opened?.should be_true - Syslog.close - end + it "reopens the log" do + Syslog.open + -> { Syslog.send(@method)}.should_not raise_error + Syslog.opened?.should be_true + Syslog.close + end - it "fails with RuntimeError if the log is closed" do - -> { Syslog.send(@method)}.should raise_error(RuntimeError) - end + it "fails with RuntimeError if the log is closed" do + -> { Syslog.send(@method)}.should raise_error(RuntimeError) + end - it "receives the same parameters as Syslog.open" do - Syslog.open - Syslog.send(@method, "rubyspec", 3, 8) do |s| - s.should == Syslog - s.ident.should == "rubyspec" - s.options.should == 3 - s.facility.should == Syslog::LOG_USER - s.opened?.should be_true + it "receives the same parameters as Syslog.open" do + Syslog.open + Syslog.send(@method, "rubyspec", 3, 8) do |s| + s.should == Syslog + s.ident.should == "rubyspec" + s.options.should == 3 + s.facility.should == Syslog::LOG_USER + s.opened?.should be_true + end + Syslog.opened?.should be_false end - Syslog.opened?.should be_false - end - it "returns the module" do - Syslog.open - Syslog.send(@method).should == Syslog - Syslog.close + it "returns the module" do + Syslog.open + Syslog.send(@method).should == Syslog + Syslog.close + end end end end diff --git a/spec/ruby/library/syslog/warning_spec.rb b/spec/ruby/library/syslog/warning_spec.rb index eeca603136211f..cf0f7d0dc21484 100644 --- a/spec/ruby/library/syslog/warning_spec.rb +++ b/spec/ruby/library/syslog/warning_spec.rb @@ -1,10 +1,13 @@ require_relative '../../spec_helper' -platform_is_not :windows do - require_relative 'shared/log' - require 'syslog' +ruby_version_is ""..."3.4" do - describe "Syslog.warning" do - it_behaves_like :syslog_log, :warning + platform_is_not :windows do + require_relative 'shared/log' + require 'syslog' + + describe "Syslog.warning" do + it_behaves_like :syslog_log, :warning + end end end From 8bcc764f71c8bb93871dc6a7526319ca78242518 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 22 Jan 2024 15:26:08 +0900 Subject: [PATCH 390/640] Document about syslog at Ruby 3.4 --- doc/maintainers.md | 8 +++----- doc/standard_library.rdoc | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/doc/maintainers.md b/doc/maintainers.md index 5e117196c7498b..65ae8f74e5e431 100644 --- a/doc/maintainers.md +++ b/doc/maintainers.md @@ -376,11 +376,6 @@ have commit right, others don't. * https://github.com/ruby/strscan * https://rubygems.org/gems/strscan -#### ext/syslog -* Akinori MUSHA (knu) -* https://github.com/ruby/syslog -* https://rubygems.org/gems/syslog - #### ext/win32ole * Masaki Suketa (suke) * https://github.com/ruby/win32ole @@ -470,6 +465,9 @@ have commit right, others don't. #### nkf * https://github.com/ruby/nkf +#### syslog +* https://github.com/ruby/syslog + ## Platform Maintainers ### mswin64 (Microsoft Windows) * NAKAMURA Usaku (usa) diff --git a/doc/standard_library.rdoc b/doc/standard_library.rdoc index c099ea5c712798..709358fcda4e0b 100644 --- a/doc/standard_library.rdoc +++ b/doc/standard_library.rdoc @@ -90,7 +90,6 @@ Pathname:: Representation of the name of a file or directory on the filesystem Psych:: A YAML parser and emitter for Ruby StringIO:: Pseudo I/O on String objects StringScanner:: Provides lexical scanning operations on a String -Syslog:: Ruby interface for the POSIX system logging facility WIN32OLE:: Provides an interface for OLE Automation in Ruby Zlib:: Ruby interface for the zlib compression/decompression library @@ -130,3 +129,4 @@ resolv-replace.rb:: Replace Socket DNS with Resolv Rinda:: The Linda distributed computing paradigm in Ruby DRb:: Distributed object system for Ruby NKF:: Ruby extension for Network Kanji Filter +Syslog:: Ruby interface for the POSIX system logging facility From 3736130dfaca096e3443180d89e46b48179dfa1e Mon Sep 17 00:00:00 2001 From: git Date: Mon, 22 Jan 2024 07:00:13 +0000 Subject: [PATCH 391/640] Update bundled gems list at 8bcc764f71c8bb93871dc6a7526319 [ci skip] --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index 3f4f2a83c38eef..5048d356131d7e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -57,6 +57,7 @@ The following bundled gems are promoted from default gems. * rinda 0.2.0 * drb 2.2.0 * nkf 0.2.0 +* syslog 0.1.2 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. From 3d19409637de1462b6790d2a92344bf0a10d8c52 Mon Sep 17 00:00:00 2001 From: yui-knk Date: Thu, 18 Jan 2024 23:41:04 +0900 Subject: [PATCH 392/640] Use index for referring to symbols in `args` rule instead of named references In `args: args ',' arg_splat`, `args` is not unique name. Currently the associated rule is interpreted as `$$ = rest_arg_append(p, $$, $3, &@$);`. The action works as expected because `$$` is initialized with `$1` before each action is executed. However it's misleading then change to use index. --- parse.y | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parse.y b/parse.y index 7cb92b88e3385b..66f8545e6d3f83 100644 --- a/parse.y +++ b/parse.y @@ -4043,9 +4043,9 @@ args : arg_value | args ',' arg_splat { /*%%%*/ - $$ = rest_arg_append(p, $args, $arg_splat, &@$); + $$ = rest_arg_append(p, $1, $3, &@$); /*% %*/ - /*% ripper: args_add_star!($args, $arg_splat) %*/ + /*% ripper: args_add_star!($1, $3) %*/ } ; From a70e500494015b54fffd5a83104684eb66239a30 Mon Sep 17 00:00:00 2001 From: git Date: Mon, 22 Jan 2024 07:06:37 +0000 Subject: [PATCH 393/640] Update default gems list at 3d19409637de1462b6790d2a92344b [ci skip] --- NEWS.md | 1 - 1 file changed, 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 5048d356131d7e..ef8dab37d45972 100644 --- a/NEWS.md +++ b/NEWS.md @@ -30,7 +30,6 @@ The following default gems are updated. * io-console 0.7.2 * irb 1.11.1 * net-http 0.4.1 -* nkf 0.2.0 * reline 0.4.2 * stringio 3.1.1 * strscan 3.0.9 From e195710d10225458008b79dbb734b1cddcd6230d Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 22 Jan 2024 17:23:16 +0900 Subject: [PATCH 394/640] Extract csv --- gems/bundled_gems | 1 + lib/csv.rb | 2882 --------------------- lib/csv/core_ext/array.rb | 9 - lib/csv/core_ext/string.rb | 9 - lib/csv/csv.gemspec | 64 - lib/csv/fields_converter.rb | 89 - lib/csv/input_record_separator.rb | 18 - lib/csv/parser.rb | 1288 --------- lib/csv/row.rb | 757 ------ lib/csv/table.rb | 1055 -------- lib/csv/version.rb | 6 - lib/csv/writer.rb | 210 -- test/csv/helper.rb | 42 - test/csv/interface/test_delegation.rb | 47 - test/csv/interface/test_read.rb | 381 --- test/csv/interface/test_read_write.rb | 124 - test/csv/interface/test_write.rb | 217 -- test/csv/line_endings.gz | Bin 59 -> 0 bytes test/csv/parse/test_column_separator.rb | 40 - test/csv/parse/test_convert.rb | 165 -- test/csv/parse/test_each.rb | 23 - test/csv/parse/test_general.rb | 348 --- test/csv/parse/test_header.rb | 342 --- test/csv/parse/test_inputs_scanner.rb | 63 - test/csv/parse/test_invalid.rb | 52 - test/csv/parse/test_liberal_parsing.rb | 171 -- test/csv/parse/test_quote_char_nil.rb | 93 - test/csv/parse/test_read.rb | 27 - test/csv/parse/test_rewind.rb | 40 - test/csv/parse/test_row_separator.rb | 16 - test/csv/parse/test_skip_lines.rb | 126 - test/csv/parse/test_strip.rb | 112 - test/csv/parse/test_unconverted_fields.rb | 117 - test/csv/test_data_converters.rb | 190 -- test/csv/test_encodings.rb | 403 --- test/csv/test_features.rb | 359 --- test/csv/test_patterns.rb | 27 - test/csv/test_row.rb | 435 ---- test/csv/test_table.rb | 691 ----- test/csv/write/test_converters.rb | 53 - test/csv/write/test_force_quotes.rb | 78 - test/csv/write/test_general.rb | 246 -- test/csv/write/test_quote_empty.rb | 70 - 43 files changed, 1 insertion(+), 11485 deletions(-) delete mode 100644 lib/csv.rb delete mode 100644 lib/csv/core_ext/array.rb delete mode 100644 lib/csv/core_ext/string.rb delete mode 100644 lib/csv/csv.gemspec delete mode 100644 lib/csv/fields_converter.rb delete mode 100644 lib/csv/input_record_separator.rb delete mode 100644 lib/csv/parser.rb delete mode 100644 lib/csv/row.rb delete mode 100644 lib/csv/table.rb delete mode 100644 lib/csv/version.rb delete mode 100644 lib/csv/writer.rb delete mode 100644 test/csv/helper.rb delete mode 100644 test/csv/interface/test_delegation.rb delete mode 100644 test/csv/interface/test_read.rb delete mode 100644 test/csv/interface/test_read_write.rb delete mode 100644 test/csv/interface/test_write.rb delete mode 100644 test/csv/line_endings.gz delete mode 100644 test/csv/parse/test_column_separator.rb delete mode 100644 test/csv/parse/test_convert.rb delete mode 100644 test/csv/parse/test_each.rb delete mode 100644 test/csv/parse/test_general.rb delete mode 100644 test/csv/parse/test_header.rb delete mode 100644 test/csv/parse/test_inputs_scanner.rb delete mode 100644 test/csv/parse/test_invalid.rb delete mode 100644 test/csv/parse/test_liberal_parsing.rb delete mode 100644 test/csv/parse/test_quote_char_nil.rb delete mode 100644 test/csv/parse/test_read.rb delete mode 100644 test/csv/parse/test_rewind.rb delete mode 100644 test/csv/parse/test_row_separator.rb delete mode 100644 test/csv/parse/test_skip_lines.rb delete mode 100644 test/csv/parse/test_strip.rb delete mode 100644 test/csv/parse/test_unconverted_fields.rb delete mode 100644 test/csv/test_data_converters.rb delete mode 100644 test/csv/test_encodings.rb delete mode 100644 test/csv/test_features.rb delete mode 100644 test/csv/test_patterns.rb delete mode 100644 test/csv/test_row.rb delete mode 100644 test/csv/test_table.rb delete mode 100644 test/csv/write/test_converters.rb delete mode 100644 test/csv/write/test_force_quotes.rb delete mode 100644 test/csv/write/test_general.rb delete mode 100644 test/csv/write/test_quote_empty.rb diff --git a/gems/bundled_gems b/gems/bundled_gems index 15944356cdeb7e..4d9e6cbf942480 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -32,3 +32,4 @@ rinda 0.2.0 https://github.com/ruby/rinda drb 2.2.0 https://github.com/ruby/drb nkf 0.2.0 https://github.com/ruby/nkf syslog 0.1.2 https://github.com/ruby/syslog +csv 3.2.8 https://github.com/ruby/csv diff --git a/lib/csv.rb b/lib/csv.rb deleted file mode 100644 index e8aa20ddd252ef..00000000000000 --- a/lib/csv.rb +++ /dev/null @@ -1,2882 +0,0 @@ -# encoding: US-ASCII -# frozen_string_literal: true -# = csv.rb -- CSV Reading and Writing -# -# Created by James Edward Gray II on 2005-10-31. -# -# See CSV for documentation. -# -# == Description -# -# Welcome to the new and improved CSV. -# -# This version of the CSV library began its life as FasterCSV. FasterCSV was -# intended as a replacement to Ruby's then standard CSV library. It was -# designed to address concerns users of that library had and it had three -# primary goals: -# -# 1. Be significantly faster than CSV while remaining a pure Ruby library. -# 2. Use a smaller and easier to maintain code base. (FasterCSV eventually -# grew larger, was also but considerably richer in features. The parsing -# core remains quite small.) -# 3. Improve on the CSV interface. -# -# Obviously, the last one is subjective. I did try to defer to the original -# interface whenever I didn't have a compelling reason to change it though, so -# hopefully this won't be too radically different. -# -# We must have met our goals because FasterCSV was renamed to CSV and replaced -# the original library as of Ruby 1.9. If you are migrating code from 1.8 or -# earlier, you may have to change your code to comply with the new interface. -# -# == What's the Different From the Old CSV? -# -# I'm sure I'll miss something, but I'll try to mention most of the major -# differences I am aware of, to help others quickly get up to speed: -# -# === \CSV Parsing -# -# * This parser is m17n aware. See CSV for full details. -# * This library has a stricter parser and will throw MalformedCSVErrors on -# problematic data. -# * This library has a less liberal idea of a line ending than CSV. What you -# set as the :row_sep is law. It can auto-detect your line endings -# though. -# * The old library returned empty lines as [nil]. This library calls -# them []. -# * This library has a much faster parser. -# -# === Interface -# -# * CSV now uses keyword parameters to set options. -# * CSV no longer has generate_row() or parse_row(). -# * The old CSV's Reader and Writer classes have been dropped. -# * CSV::open() is now more like Ruby's open(). -# * CSV objects now support most standard IO methods. -# * CSV now has a new() method used to wrap objects like String and IO for -# reading and writing. -# * CSV::generate() is different from the old method. -# * CSV no longer supports partial reads. It works line-by-line. -# * CSV no longer allows the instance methods to override the separators for -# performance reasons. They must be set in the constructor. -# -# If you use this library and find yourself missing any functionality I have -# trimmed, please {let me know}[mailto:james@grayproductions.net]. -# -# == Documentation -# -# See CSV for documentation. -# -# == What is CSV, really? -# -# CSV maintains a pretty strict definition of CSV taken directly from -# {the RFC}[https://www.ietf.org/rfc/rfc4180.txt]. I relax the rules in only one -# place and that is to make using this library easier. CSV will parse all valid -# CSV. -# -# What you don't want to do is to feed CSV invalid data. Because of the way the -# CSV format works, it's common for a parser to need to read until the end of -# the file to be sure a field is invalid. This consumes a lot of time and memory. -# -# Luckily, when working with invalid CSV, Ruby's built-in methods will almost -# always be superior in every way. For example, parsing non-quoted fields is as -# easy as: -# -# data.split(",") -# -# == Questions and/or Comments -# -# Feel free to email {James Edward Gray II}[mailto:james@grayproductions.net] -# with any questions. - -require "forwardable" -require "date" -require "stringio" - -require_relative "csv/fields_converter" -require_relative "csv/input_record_separator" -require_relative "csv/parser" -require_relative "csv/row" -require_relative "csv/table" -require_relative "csv/writer" - -# == \CSV -# -# === \CSV Data -# -# \CSV (comma-separated values) data is a text representation of a table: -# - A _row_ _separator_ delimits table rows. -# A common row separator is the newline character "\n". -# - A _column_ _separator_ delimits fields in a row. -# A common column separator is the comma character ",". -# -# This \CSV \String, with row separator "\n" -# and column separator ",", -# has three rows and two columns: -# "foo,0\nbar,1\nbaz,2\n" -# -# Despite the name \CSV, a \CSV representation can use different separators. -# -# For more about tables, see the Wikipedia article -# "{Table (information)}[https://en.wikipedia.org/wiki/Table_(information)]", -# especially its section -# "{Simple table}[https://en.wikipedia.org/wiki/Table_(information)#Simple_table]" -# -# == \Class \CSV -# -# Class \CSV provides methods for: -# - Parsing \CSV data from a \String object, a \File (via its file path), or an \IO object. -# - Generating \CSV data to a \String object. -# -# To make \CSV available: -# require 'csv' -# -# All examples here assume that this has been done. -# -# == Keeping It Simple -# -# A \CSV object has dozens of instance methods that offer fine-grained control -# of parsing and generating \CSV data. -# For many needs, though, simpler approaches will do. -# -# This section summarizes the singleton methods in \CSV -# that allow you to parse and generate without explicitly -# creating \CSV objects. -# For details, follow the links. -# -# === Simple Parsing -# -# Parsing methods commonly return either of: -# - An \Array of Arrays of Strings: -# - The outer \Array is the entire "table". -# - Each inner \Array is a row. -# - Each \String is a field. -# - A CSV::Table object. For details, see -# {\CSV with Headers}[#class-CSV-label-CSV+with+Headers]. -# -# ==== Parsing a \String -# -# The input to be parsed can be a string: -# string = "foo,0\nbar,1\nbaz,2\n" -# -# \Method CSV.parse returns the entire \CSV data: -# CSV.parse(string) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] -# -# \Method CSV.parse_line returns only the first row: -# CSV.parse_line(string) # => ["foo", "0"] -# -# \CSV extends class \String with instance method String#parse_csv, -# which also returns only the first row: -# string.parse_csv # => ["foo", "0"] -# -# ==== Parsing Via a \File Path -# -# The input to be parsed can be in a file: -# string = "foo,0\nbar,1\nbaz,2\n" -# path = 't.csv' -# File.write(path, string) -# -# \Method CSV.read returns the entire \CSV data: -# CSV.read(path) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] -# -# \Method CSV.foreach iterates, passing each row to the given block: -# CSV.foreach(path) do |row| -# p row -# end -# Output: -# ["foo", "0"] -# ["bar", "1"] -# ["baz", "2"] -# -# \Method CSV.table returns the entire \CSV data as a CSV::Table object: -# CSV.table(path) # => # -# -# ==== Parsing from an Open \IO Stream -# -# The input to be parsed can be in an open \IO stream: -# -# \Method CSV.read returns the entire \CSV data: -# File.open(path) do |file| -# CSV.read(file) -# end # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] -# -# As does method CSV.parse: -# File.open(path) do |file| -# CSV.parse(file) -# end # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] -# -# \Method CSV.parse_line returns only the first row: -# File.open(path) do |file| -# CSV.parse_line(file) -# end # => ["foo", "0"] -# -# \Method CSV.foreach iterates, passing each row to the given block: -# File.open(path) do |file| -# CSV.foreach(file) do |row| -# p row -# end -# end -# Output: -# ["foo", "0"] -# ["bar", "1"] -# ["baz", "2"] -# -# \Method CSV.table returns the entire \CSV data as a CSV::Table object: -# File.open(path) do |file| -# CSV.table(file) -# end # => # -# -# === Simple Generating -# -# \Method CSV.generate returns a \String; -# this example uses method CSV#<< to append the rows -# that are to be generated: -# output_string = CSV.generate do |csv| -# csv << ['foo', 0] -# csv << ['bar', 1] -# csv << ['baz', 2] -# end -# output_string # => "foo,0\nbar,1\nbaz,2\n" -# -# \Method CSV.generate_line returns a \String containing the single row -# constructed from an \Array: -# CSV.generate_line(['foo', '0']) # => "foo,0\n" -# -# \CSV extends class \Array with instance method Array#to_csv, -# which forms an \Array into a \String: -# ['foo', '0'].to_csv # => "foo,0\n" -# -# === "Filtering" \CSV -# -# \Method CSV.filter provides a Unix-style filter for \CSV data. -# The input data is processed to form the output data: -# in_string = "foo,0\nbar,1\nbaz,2\n" -# out_string = '' -# CSV.filter(in_string, out_string) do |row| -# row[0] = row[0].upcase -# row[1] *= 4 -# end -# out_string # => "FOO,0000\nBAR,1111\nBAZ,2222\n" -# -# == \CSV Objects -# -# There are three ways to create a \CSV object: -# - \Method CSV.new returns a new \CSV object. -# - \Method CSV.instance returns a new or cached \CSV object. -# - \Method \CSV() also returns a new or cached \CSV object. -# -# === Instance Methods -# -# \CSV has three groups of instance methods: -# - Its own internally defined instance methods. -# - Methods included by module Enumerable. -# - Methods delegated to class IO. See below. -# -# ==== Delegated Methods -# -# For convenience, a CSV object will delegate to many methods in class IO. -# (A few have wrapper "guard code" in \CSV.) You may call: -# * IO#binmode -# * #binmode? -# * IO#close -# * IO#close_read -# * IO#close_write -# * IO#closed? -# * #eof -# * #eof? -# * IO#external_encoding -# * IO#fcntl -# * IO#fileno -# * #flock -# * IO#flush -# * IO#fsync -# * IO#internal_encoding -# * #ioctl -# * IO#isatty -# * #path -# * IO#pid -# * IO#pos -# * IO#pos= -# * IO#reopen -# * #rewind -# * IO#seek -# * #stat -# * IO#string -# * IO#sync -# * IO#sync= -# * IO#tell -# * #to_i -# * #to_io -# * IO#truncate -# * IO#tty? -# -# === Options -# -# The default values for options are: -# DEFAULT_OPTIONS = { -# # For both parsing and generating. -# col_sep: ",", -# row_sep: :auto, -# quote_char: '"', -# # For parsing. -# field_size_limit: nil, -# converters: nil, -# unconverted_fields: nil, -# headers: false, -# return_headers: false, -# header_converters: nil, -# skip_blanks: false, -# skip_lines: nil, -# liberal_parsing: false, -# nil_value: nil, -# empty_value: "", -# strip: false, -# # For generating. -# write_headers: nil, -# quote_empty: true, -# force_quotes: false, -# write_converters: nil, -# write_nil_value: nil, -# write_empty_value: "", -# } -# -# ==== Options for Parsing -# -# Options for parsing, described in detail below, include: -# - +row_sep+: Specifies the row separator; used to delimit rows. -# - +col_sep+: Specifies the column separator; used to delimit fields. -# - +quote_char+: Specifies the quote character; used to quote fields. -# - +field_size_limit+: Specifies the maximum field size + 1 allowed. -# Deprecated since 3.2.3. Use +max_field_size+ instead. -# - +max_field_size+: Specifies the maximum field size allowed. -# - +converters+: Specifies the field converters to be used. -# - +unconverted_fields+: Specifies whether unconverted fields are to be available. -# - +headers+: Specifies whether data contains headers, -# or specifies the headers themselves. -# - +return_headers+: Specifies whether headers are to be returned. -# - +header_converters+: Specifies the header converters to be used. -# - +skip_blanks+: Specifies whether blanks lines are to be ignored. -# - +skip_lines+: Specifies how comments lines are to be recognized. -# - +strip+: Specifies whether leading and trailing whitespace are to be -# stripped from fields. This must be compatible with +col_sep+; if it is not, -# then an +ArgumentError+ exception will be raised. -# - +liberal_parsing+: Specifies whether \CSV should attempt to parse -# non-compliant data. -# - +nil_value+: Specifies the object that is to be substituted for each null (no-text) field. -# - +empty_value+: Specifies the object that is to be substituted for each empty field. -# -# :include: ../doc/csv/options/common/row_sep.rdoc -# -# :include: ../doc/csv/options/common/col_sep.rdoc -# -# :include: ../doc/csv/options/common/quote_char.rdoc -# -# :include: ../doc/csv/options/parsing/field_size_limit.rdoc -# -# :include: ../doc/csv/options/parsing/converters.rdoc -# -# :include: ../doc/csv/options/parsing/unconverted_fields.rdoc -# -# :include: ../doc/csv/options/parsing/headers.rdoc -# -# :include: ../doc/csv/options/parsing/return_headers.rdoc -# -# :include: ../doc/csv/options/parsing/header_converters.rdoc -# -# :include: ../doc/csv/options/parsing/skip_blanks.rdoc -# -# :include: ../doc/csv/options/parsing/skip_lines.rdoc -# -# :include: ../doc/csv/options/parsing/strip.rdoc -# -# :include: ../doc/csv/options/parsing/liberal_parsing.rdoc -# -# :include: ../doc/csv/options/parsing/nil_value.rdoc -# -# :include: ../doc/csv/options/parsing/empty_value.rdoc -# -# ==== Options for Generating -# -# Options for generating, described in detail below, include: -# - +row_sep+: Specifies the row separator; used to delimit rows. -# - +col_sep+: Specifies the column separator; used to delimit fields. -# - +quote_char+: Specifies the quote character; used to quote fields. -# - +write_headers+: Specifies whether headers are to be written. -# - +force_quotes+: Specifies whether each output field is to be quoted. -# - +quote_empty+: Specifies whether each empty output field is to be quoted. -# - +write_converters+: Specifies the field converters to be used in writing. -# - +write_nil_value+: Specifies the object that is to be substituted for each +nil+-valued field. -# - +write_empty_value+: Specifies the object that is to be substituted for each empty field. -# -# :include: ../doc/csv/options/common/row_sep.rdoc -# -# :include: ../doc/csv/options/common/col_sep.rdoc -# -# :include: ../doc/csv/options/common/quote_char.rdoc -# -# :include: ../doc/csv/options/generating/write_headers.rdoc -# -# :include: ../doc/csv/options/generating/force_quotes.rdoc -# -# :include: ../doc/csv/options/generating/quote_empty.rdoc -# -# :include: ../doc/csv/options/generating/write_converters.rdoc -# -# :include: ../doc/csv/options/generating/write_nil_value.rdoc -# -# :include: ../doc/csv/options/generating/write_empty_value.rdoc -# -# === \CSV with Headers -# -# CSV allows to specify column names of CSV file, whether they are in data, or -# provided separately. If headers are specified, reading methods return an instance -# of CSV::Table, consisting of CSV::Row. -# -# # Headers are part of data -# data = CSV.parse(<<~ROWS, headers: true) -# Name,Department,Salary -# Bob,Engineering,1000 -# Jane,Sales,2000 -# John,Management,5000 -# ROWS -# -# data.class #=> CSV::Table -# data.first #=> # -# data.first.to_h #=> {"Name"=>"Bob", "Department"=>"Engineering", "Salary"=>"1000"} -# -# # Headers provided by developer -# data = CSV.parse('Bob,Engineering,1000', headers: %i[name department salary]) -# data.first #=> # -# -# === \Converters -# -# By default, each value (field or header) parsed by \CSV is formed into a \String. -# You can use a _field_ _converter_ or _header_ _converter_ -# to intercept and modify the parsed values: -# - See {Field Converters}[#class-CSV-label-Field+Converters]. -# - See {Header Converters}[#class-CSV-label-Header+Converters]. -# -# Also by default, each value to be written during generation is written 'as-is'. -# You can use a _write_ _converter_ to modify values before writing. -# - See {Write Converters}[#class-CSV-label-Write+Converters]. -# -# ==== Specifying \Converters -# -# You can specify converters for parsing or generating in the +options+ -# argument to various \CSV methods: -# - Option +converters+ for converting parsed field values. -# - Option +header_converters+ for converting parsed header values. -# - Option +write_converters+ for converting values to be written (generated). -# -# There are three forms for specifying converters: -# - A converter proc: executable code to be used for conversion. -# - A converter name: the name of a stored converter. -# - A converter list: an array of converter procs, converter names, and converter lists. -# -# ===== Converter Procs -# -# This converter proc, +strip_converter+, accepts a value +field+ -# and returns field.strip: -# strip_converter = proc {|field| field.strip } -# In this call to CSV.parse, -# the keyword argument converters: string_converter -# specifies that: -# - \Proc +string_converter+ is to be called for each parsed field. -# - The converter's return value is to replace the +field+ value. -# Example: -# string = " foo , 0 \n bar , 1 \n baz , 2 \n" -# array = CSV.parse(string, converters: strip_converter) -# array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] -# -# A converter proc can receive a second argument, +field_info+, -# that contains details about the field. -# This modified +strip_converter+ displays its arguments: -# strip_converter = proc do |field, field_info| -# p [field, field_info] -# field.strip -# end -# string = " foo , 0 \n bar , 1 \n baz , 2 \n" -# array = CSV.parse(string, converters: strip_converter) -# array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] -# Output: -# [" foo ", #] -# [" 0 ", #] -# [" bar ", #] -# [" 1 ", #] -# [" baz ", #] -# [" 2 ", #] -# Each CSV::FieldInfo object shows: -# - The 0-based field index. -# - The 1-based line index. -# - The field header, if any. -# -# ===== Stored \Converters -# -# A converter may be given a name and stored in a structure where -# the parsing methods can find it by name. -# -# The storage structure for field converters is the \Hash CSV::Converters. -# It has several built-in converter procs: -# - :integer: converts each \String-embedded integer into a true \Integer. -# - :float: converts each \String-embedded float into a true \Float. -# - :date: converts each \String-embedded date into a true \Date. -# - :date_time: converts each \String-embedded date-time into a true \DateTime -# . -# This example creates a converter proc, then stores it: -# strip_converter = proc {|field| field.strip } -# CSV::Converters[:strip] = strip_converter -# Then the parsing method call can refer to the converter -# by its name, :strip: -# string = " foo , 0 \n bar , 1 \n baz , 2 \n" -# array = CSV.parse(string, converters: :strip) -# array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] -# -# The storage structure for header converters is the \Hash CSV::HeaderConverters, -# which works in the same way. -# It also has built-in converter procs: -# - :downcase: Downcases each header. -# - :symbol: Converts each header to a \Symbol. -# -# There is no such storage structure for write headers. -# -# In order for the parsing methods to access stored converters in non-main-Ractors, the -# storage structure must be made shareable first. -# Therefore, Ractor.make_shareable(CSV::Converters) and -# Ractor.make_shareable(CSV::HeaderConverters) must be called before the creation -# of Ractors that use the converters stored in these structures. (Since making the storage -# structures shareable involves freezing them, any custom converters that are to be used -# must be added first.) -# -# ===== Converter Lists -# -# A _converter_ _list_ is an \Array that may include any assortment of: -# - Converter procs. -# - Names of stored converters. -# - Nested converter lists. -# -# Examples: -# numeric_converters = [:integer, :float] -# date_converters = [:date, :date_time] -# [numeric_converters, strip_converter] -# [strip_converter, date_converters, :float] -# -# Like a converter proc, a converter list may be named and stored in either -# \CSV::Converters or CSV::HeaderConverters: -# CSV::Converters[:custom] = [strip_converter, date_converters, :float] -# CSV::HeaderConverters[:custom] = [:downcase, :symbol] -# -# There are two built-in converter lists: -# CSV::Converters[:numeric] # => [:integer, :float] -# CSV::Converters[:all] # => [:date_time, :numeric] -# -# ==== Field \Converters -# -# With no conversion, all parsed fields in all rows become Strings: -# string = "foo,0\nbar,1\nbaz,2\n" -# ary = CSV.parse(string) -# ary # => # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] -# -# When you specify a field converter, each parsed field is passed to the converter; -# its return value becomes the stored value for the field. -# A converter might, for example, convert an integer embedded in a \String -# into a true \Integer. -# (In fact, that's what built-in field converter +:integer+ does.) -# -# There are three ways to use field \converters. -# -# - Using option {converters}[#class-CSV-label-Option+converters] with a parsing method: -# ary = CSV.parse(string, converters: :integer) -# ary # => [0, 1, 2] # => [["foo", 0], ["bar", 1], ["baz", 2]] -# - Using option {converters}[#class-CSV-label-Option+converters] with a new \CSV instance: -# csv = CSV.new(string, converters: :integer) -# # Field converters in effect: -# csv.converters # => [:integer] -# csv.read # => [["foo", 0], ["bar", 1], ["baz", 2]] -# - Using method #convert to add a field converter to a \CSV instance: -# csv = CSV.new(string) -# # Add a converter. -# csv.convert(:integer) -# csv.converters # => [:integer] -# csv.read # => [["foo", 0], ["bar", 1], ["baz", 2]] -# -# Installing a field converter does not affect already-read rows: -# csv = CSV.new(string) -# csv.shift # => ["foo", "0"] -# # Add a converter. -# csv.convert(:integer) -# csv.converters # => [:integer] -# csv.read # => [["bar", 1], ["baz", 2]] -# -# There are additional built-in \converters, and custom \converters are also supported. -# -# ===== Built-In Field \Converters -# -# The built-in field converters are in \Hash CSV::Converters: -# - Each key is a field converter name. -# - Each value is one of: -# - A \Proc field converter. -# - An \Array of field converter names. -# -# Display: -# CSV::Converters.each_pair do |name, value| -# if value.kind_of?(Proc) -# p [name, value.class] -# else -# p [name, value] -# end -# end -# Output: -# [:integer, Proc] -# [:float, Proc] -# [:numeric, [:integer, :float]] -# [:date, Proc] -# [:date_time, Proc] -# [:all, [:date_time, :numeric]] -# -# Each of these converters transcodes values to UTF-8 before attempting conversion. -# If a value cannot be transcoded to UTF-8 the conversion will -# fail and the value will remain unconverted. -# -# Converter +:integer+ converts each field that Integer() accepts: -# data = '0,1,2,x' -# # Without the converter -# csv = CSV.parse_line(data) -# csv # => ["0", "1", "2", "x"] -# # With the converter -# csv = CSV.parse_line(data, converters: :integer) -# csv # => [0, 1, 2, "x"] -# -# Converter +:float+ converts each field that Float() accepts: -# data = '1.0,3.14159,x' -# # Without the converter -# csv = CSV.parse_line(data) -# csv # => ["1.0", "3.14159", "x"] -# # With the converter -# csv = CSV.parse_line(data, converters: :float) -# csv # => [1.0, 3.14159, "x"] -# -# Converter +:numeric+ converts with both +:integer+ and +:float+.. -# -# Converter +:date+ converts each field that Date::parse accepts: -# data = '2001-02-03,x' -# # Without the converter -# csv = CSV.parse_line(data) -# csv # => ["2001-02-03", "x"] -# # With the converter -# csv = CSV.parse_line(data, converters: :date) -# csv # => [#, "x"] -# -# Converter +:date_time+ converts each field that DateTime::parse accepts: -# data = '2020-05-07T14:59:00-05:00,x' -# # Without the converter -# csv = CSV.parse_line(data) -# csv # => ["2020-05-07T14:59:00-05:00", "x"] -# # With the converter -# csv = CSV.parse_line(data, converters: :date_time) -# csv # => [#, "x"] -# -# Converter +:numeric+ converts with both +:date_time+ and +:numeric+.. -# -# As seen above, method #convert adds \converters to a \CSV instance, -# and method #converters returns an \Array of the \converters in effect: -# csv = CSV.new('0,1,2') -# csv.converters # => [] -# csv.convert(:integer) -# csv.converters # => [:integer] -# csv.convert(:date) -# csv.converters # => [:integer, :date] -# -# ===== Custom Field \Converters -# -# You can define a custom field converter: -# strip_converter = proc {|field| field.strip } -# string = " foo , 0 \n bar , 1 \n baz , 2 \n" -# array = CSV.parse(string, converters: strip_converter) -# array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] -# You can register the converter in \Converters \Hash, -# which allows you to refer to it by name: -# CSV::Converters[:strip] = strip_converter -# string = " foo , 0 \n bar , 1 \n baz , 2 \n" -# array = CSV.parse(string, converters: :strip) -# array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] -# -# ==== Header \Converters -# -# Header converters operate only on headers (and not on other rows). -# -# There are three ways to use header \converters; -# these examples use built-in header converter +:downcase+, -# which downcases each parsed header. -# -# - Option +header_converters+ with a singleton parsing method: -# string = "Name,Count\nFoo,0\n,Bar,1\nBaz,2" -# tbl = CSV.parse(string, headers: true, header_converters: :downcase) -# tbl.class # => CSV::Table -# tbl.headers # => ["name", "count"] -# -# - Option +header_converters+ with a new \CSV instance: -# csv = CSV.new(string, header_converters: :downcase) -# # Header converters in effect: -# csv.header_converters # => [:downcase] -# tbl = CSV.parse(string, headers: true) -# tbl.headers # => ["Name", "Count"] -# -# - Method #header_convert adds a header converter to a \CSV instance: -# csv = CSV.new(string) -# # Add a header converter. -# csv.header_convert(:downcase) -# csv.header_converters # => [:downcase] -# tbl = CSV.parse(string, headers: true) -# tbl.headers # => ["Name", "Count"] -# -# ===== Built-In Header \Converters -# -# The built-in header \converters are in \Hash CSV::HeaderConverters. -# The keys there are the names of the \converters: -# CSV::HeaderConverters.keys # => [:downcase, :symbol] -# -# Converter +:downcase+ converts each header by downcasing it: -# string = "Name,Count\nFoo,0\n,Bar,1\nBaz,2" -# tbl = CSV.parse(string, headers: true, header_converters: :downcase) -# tbl.class # => CSV::Table -# tbl.headers # => ["name", "count"] -# -# Converter +:symbol+ converts each header by making it into a \Symbol: -# string = "Name,Count\nFoo,0\n,Bar,1\nBaz,2" -# tbl = CSV.parse(string, headers: true, header_converters: :symbol) -# tbl.headers # => [:name, :count] -# Details: -# - Strips leading and trailing whitespace. -# - Downcases the header. -# - Replaces embedded spaces with underscores. -# - Removes non-word characters. -# - Makes the string into a \Symbol. -# -# ===== Custom Header \Converters -# -# You can define a custom header converter: -# upcase_converter = proc {|header| header.upcase } -# string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" -# table = CSV.parse(string, headers: true, header_converters: upcase_converter) -# table # => # -# table.headers # => ["NAME", "VALUE"] -# You can register the converter in \HeaderConverters \Hash, -# which allows you to refer to it by name: -# CSV::HeaderConverters[:upcase] = upcase_converter -# table = CSV.parse(string, headers: true, header_converters: :upcase) -# table # => # -# table.headers # => ["NAME", "VALUE"] -# -# ===== Write \Converters -# -# When you specify a write converter for generating \CSV, -# each field to be written is passed to the converter; -# its return value becomes the new value for the field. -# A converter might, for example, strip whitespace from a field. -# -# Using no write converter (all fields unmodified): -# output_string = CSV.generate do |csv| -# csv << [' foo ', 0] -# csv << [' bar ', 1] -# csv << [' baz ', 2] -# end -# output_string # => " foo ,0\n bar ,1\n baz ,2\n" -# Using option +write_converters+ with two custom write converters: -# strip_converter = proc {|field| field.respond_to?(:strip) ? field.strip : field } -# upcase_converter = proc {|field| field.respond_to?(:upcase) ? field.upcase : field } -# write_converters = [strip_converter, upcase_converter] -# output_string = CSV.generate(write_converters: write_converters) do |csv| -# csv << [' foo ', 0] -# csv << [' bar ', 1] -# csv << [' baz ', 2] -# end -# output_string # => "FOO,0\nBAR,1\nBAZ,2\n" -# -# === Character Encodings (M17n or Multilingualization) -# -# This new CSV parser is m17n savvy. The parser works in the Encoding of the IO -# or String object being read from or written to. Your data is never transcoded -# (unless you ask Ruby to transcode it for you) and will literally be parsed in -# the Encoding it is in. Thus CSV will return Arrays or Rows of Strings in the -# Encoding of your data. This is accomplished by transcoding the parser itself -# into your Encoding. -# -# Some transcoding must take place, of course, to accomplish this multiencoding -# support. For example, :col_sep, :row_sep, and -# :quote_char must be transcoded to match your data. Hopefully this -# makes the entire process feel transparent, since CSV's defaults should just -# magically work for your data. However, you can set these values manually in -# the target Encoding to avoid the translation. -# -# It's also important to note that while all of CSV's core parser is now -# Encoding agnostic, some features are not. For example, the built-in -# converters will try to transcode data to UTF-8 before making conversions. -# Again, you can provide custom converters that are aware of your Encodings to -# avoid this translation. It's just too hard for me to support native -# conversions in all of Ruby's Encodings. -# -# Anyway, the practical side of this is simple: make sure IO and String objects -# passed into CSV have the proper Encoding set and everything should just work. -# CSV methods that allow you to open IO objects (CSV::foreach(), CSV::open(), -# CSV::read(), and CSV::readlines()) do allow you to specify the Encoding. -# -# One minor exception comes when generating CSV into a String with an Encoding -# that is not ASCII compatible. There's no existing data for CSV to use to -# prepare itself and thus you will probably need to manually specify the desired -# Encoding for most of those cases. It will try to guess using the fields in a -# row of output though, when using CSV::generate_line() or Array#to_csv(). -# -# I try to point out any other Encoding issues in the documentation of methods -# as they come up. -# -# This has been tested to the best of my ability with all non-"dummy" Encodings -# Ruby ships with. However, it is brave new code and may have some bugs. -# Please feel free to {report}[mailto:james@grayproductions.net] any issues you -# find with it. -# -class CSV - - # The error thrown when the parser encounters illegal CSV formatting. - class MalformedCSVError < RuntimeError - attr_reader :line_number - alias_method :lineno, :line_number - def initialize(message, line_number) - @line_number = line_number - super("#{message} in line #{line_number}.") - end - end - - # The error thrown when the parser encounters invalid encoding in CSV. - class InvalidEncodingError < MalformedCSVError - attr_reader :encoding - def initialize(encoding, line_number) - @encoding = encoding - super("Invalid byte sequence in #{encoding}", line_number) - end - end - - # - # A FieldInfo Struct contains details about a field's position in the data - # source it was read from. CSV will pass this Struct to some blocks that make - # decisions based on field structure. See CSV.convert_fields() for an - # example. - # - # index:: The zero-based index of the field in its row. - # line:: The line of the data source this row is from. - # header:: The header for the column, when available. - # quoted?:: True or false, whether the original value is quoted or not. - # - FieldInfo = Struct.new(:index, :line, :header, :quoted?) - - # A Regexp used to find and convert some common Date formats. - DateMatcher = / \A(?: (\w+,?\s+)?\w+\s+\d{1,2},?\s+\d{2,4} | - \d{4}-\d{2}-\d{2} )\z /x - # A Regexp used to find and convert some common DateTime formats. - DateTimeMatcher = - / \A(?: (\w+,?\s+)?\w+\s+\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2},?\s+\d{2,4} | - # ISO-8601 and RFC-3339 (space instead of T) recognized by DateTime.parse - \d{4}-\d{2}-\d{2} - (?:[T\s]\d{2}:\d{2}(?::\d{2}(?:\.\d+)?(?:[+-]\d{2}(?::\d{2})|Z)?)?)? - )\z /x - - # The encoding used by all converters. - ConverterEncoding = Encoding.find("UTF-8") - - # A \Hash containing the names and \Procs for the built-in field converters. - # See {Built-In Field Converters}[#class-CSV-label-Built-In+Field+Converters]. - # - # This \Hash is intentionally left unfrozen, and may be extended with - # custom field converters. - # See {Custom Field Converters}[#class-CSV-label-Custom+Field+Converters]. - Converters = { - integer: lambda { |f| - Integer(f.encode(ConverterEncoding)) rescue f - }, - float: lambda { |f| - Float(f.encode(ConverterEncoding)) rescue f - }, - numeric: [:integer, :float], - date: lambda { |f| - begin - e = f.encode(ConverterEncoding) - e.match?(DateMatcher) ? Date.parse(e) : f - rescue # encoding conversion or date parse errors - f - end - }, - date_time: lambda { |f| - begin - e = f.encode(ConverterEncoding) - e.match?(DateTimeMatcher) ? DateTime.parse(e) : f - rescue # encoding conversion or date parse errors - f - end - }, - all: [:date_time, :numeric], - } - - # A \Hash containing the names and \Procs for the built-in header converters. - # See {Built-In Header Converters}[#class-CSV-label-Built-In+Header+Converters]. - # - # This \Hash is intentionally left unfrozen, and may be extended with - # custom field converters. - # See {Custom Header Converters}[#class-CSV-label-Custom+Header+Converters]. - HeaderConverters = { - downcase: lambda { |h| h.encode(ConverterEncoding).downcase }, - symbol: lambda { |h| - h.encode(ConverterEncoding).downcase.gsub(/[^\s\w]+/, "").strip. - gsub(/\s+/, "_").to_sym - }, - symbol_raw: lambda { |h| h.encode(ConverterEncoding).to_sym } - } - - # Default values for method options. - DEFAULT_OPTIONS = { - # For both parsing and generating. - col_sep: ",", - row_sep: :auto, - quote_char: '"', - # For parsing. - field_size_limit: nil, - max_field_size: nil, - converters: nil, - unconverted_fields: nil, - headers: false, - return_headers: false, - header_converters: nil, - skip_blanks: false, - skip_lines: nil, - liberal_parsing: false, - nil_value: nil, - empty_value: "", - strip: false, - # For generating. - write_headers: nil, - quote_empty: true, - force_quotes: false, - write_converters: nil, - write_nil_value: nil, - write_empty_value: "", - }.freeze - - class << self - # :call-seq: - # instance(string, **options) - # instance(io = $stdout, **options) - # instance(string, **options) {|csv| ... } - # instance(io = $stdout, **options) {|csv| ... } - # - # Creates or retrieves cached \CSV objects. - # For arguments and options, see CSV.new. - # - # This API is not Ractor-safe. - # - # --- - # - # With no block given, returns a \CSV object. - # - # The first call to +instance+ creates and caches a \CSV object: - # s0 = 's0' - # csv0 = CSV.instance(s0) - # csv0.class # => CSV - # - # Subsequent calls to +instance+ with that _same_ +string+ or +io+ - # retrieve that same cached object: - # csv1 = CSV.instance(s0) - # csv1.class # => CSV - # csv1.equal?(csv0) # => true # Same CSV object - # - # A subsequent call to +instance+ with a _different_ +string+ or +io+ - # creates and caches a _different_ \CSV object. - # s1 = 's1' - # csv2 = CSV.instance(s1) - # csv2.equal?(csv0) # => false # Different CSV object - # - # All the cached objects remains available: - # csv3 = CSV.instance(s0) - # csv3.equal?(csv0) # true # Same CSV object - # csv4 = CSV.instance(s1) - # csv4.equal?(csv2) # true # Same CSV object - # - # --- - # - # When a block is given, calls the block with the created or retrieved - # \CSV object; returns the block's return value: - # CSV.instance(s0) {|csv| :foo } # => :foo - def instance(data = $stdout, **options) - # create a _signature_ for this method call, data object and options - sig = [data.object_id] + - options.values_at(*DEFAULT_OPTIONS.keys) - - # fetch or create the instance for this signature - @@instances ||= Hash.new - instance = (@@instances[sig] ||= new(data, **options)) - - if block_given? - yield instance # run block, if given, returning result - else - instance # or return the instance - end - end - - # :call-seq: - # filter(in_string_or_io, **options) {|row| ... } -> array_of_arrays or csv_table - # filter(in_string_or_io, out_string_or_io, **options) {|row| ... } -> array_of_arrays or csv_table - # filter(**options) {|row| ... } -> array_of_arrays or csv_table - # - # - Parses \CSV from a source (\String, \IO stream, or ARGF). - # - Calls the given block with each parsed row: - # - Without headers, each row is an \Array. - # - With headers, each row is a CSV::Row. - # - Generates \CSV to an output (\String, \IO stream, or STDOUT). - # - Returns the parsed source: - # - Without headers, an \Array of \Arrays. - # - With headers, a CSV::Table. - # - # When +in_string_or_io+ is given, but not +out_string_or_io+, - # parses from the given +in_string_or_io+ - # and generates to STDOUT. - # - # \String input without headers: - # - # in_string = "foo,0\nbar,1\nbaz,2" - # CSV.filter(in_string) do |row| - # row[0].upcase! - # row[1] = - row[1].to_i - # end # => [["FOO", 0], ["BAR", -1], ["BAZ", -2]] - # - # Output (to STDOUT): - # - # FOO,0 - # BAR,-1 - # BAZ,-2 - # - # \String input with headers: - # - # in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2" - # CSV.filter(in_string, headers: true) do |row| - # row[0].upcase! - # row[1] = - row[1].to_i - # end # => # - # - # Output (to STDOUT): - # - # Name,Value - # FOO,0 - # BAR,-1 - # BAZ,-2 - # - # \IO stream input without headers: - # - # File.write('t.csv', "foo,0\nbar,1\nbaz,2") - # File.open('t.csv') do |in_io| - # CSV.filter(in_io) do |row| - # row[0].upcase! - # row[1] = - row[1].to_i - # end - # end # => [["FOO", 0], ["BAR", -1], ["BAZ", -2]] - # - # Output (to STDOUT): - # - # FOO,0 - # BAR,-1 - # BAZ,-2 - # - # \IO stream input with headers: - # - # File.write('t.csv', "Name,Value\nfoo,0\nbar,1\nbaz,2") - # File.open('t.csv') do |in_io| - # CSV.filter(in_io, headers: true) do |row| - # row[0].upcase! - # row[1] = - row[1].to_i - # end - # end # => # - # - # Output (to STDOUT): - # - # Name,Value - # FOO,0 - # BAR,-1 - # BAZ,-2 - # - # When both +in_string_or_io+ and +out_string_or_io+ are given, - # parses from +in_string_or_io+ and generates to +out_string_or_io+. - # - # \String output without headers: - # - # in_string = "foo,0\nbar,1\nbaz,2" - # out_string = '' - # CSV.filter(in_string, out_string) do |row| - # row[0].upcase! - # row[1] = - row[1].to_i - # end # => [["FOO", 0], ["BAR", -1], ["BAZ", -2]] - # out_string # => "FOO,0\nBAR,-1\nBAZ,-2\n" - # - # \String output with headers: - # - # in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2" - # out_string = '' - # CSV.filter(in_string, out_string, headers: true) do |row| - # row[0].upcase! - # row[1] = - row[1].to_i - # end # => # - # out_string # => "Name,Value\nFOO,0\nBAR,-1\nBAZ,-2\n" - # - # \IO stream output without headers: - # - # in_string = "foo,0\nbar,1\nbaz,2" - # File.open('t.csv', 'w') do |out_io| - # CSV.filter(in_string, out_io) do |row| - # row[0].upcase! - # row[1] = - row[1].to_i - # end - # end # => [["FOO", 0], ["BAR", -1], ["BAZ", -2]] - # File.read('t.csv') # => "FOO,0\nBAR,-1\nBAZ,-2\n" - # - # \IO stream output with headers: - # - # in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2" - # File.open('t.csv', 'w') do |out_io| - # CSV.filter(in_string, out_io, headers: true) do |row| - # row[0].upcase! - # row[1] = - row[1].to_i - # end - # end # => # - # File.read('t.csv') # => "Name,Value\nFOO,0\nBAR,-1\nBAZ,-2\n" - # - # When neither +in_string_or_io+ nor +out_string_or_io+ given, - # parses from {ARGF}[rdoc-ref:ARGF] - # and generates to STDOUT. - # - # Without headers: - # - # # Put Ruby code into a file. - # ruby = <<-EOT - # require 'csv' - # CSV.filter do |row| - # row[0].upcase! - # row[1] = - row[1].to_i - # end - # EOT - # File.write('t.rb', ruby) - # # Put some CSV into a file. - # File.write('t.csv', "foo,0\nbar,1\nbaz,2") - # # Run the Ruby code with CSV filename as argument. - # system(Gem.ruby, "t.rb", "t.csv") - # - # Output (to STDOUT): - # - # FOO,0 - # BAR,-1 - # BAZ,-2 - # - # With headers: - # - # # Put Ruby code into a file. - # ruby = <<-EOT - # require 'csv' - # CSV.filter(headers: true) do |row| - # row[0].upcase! - # row[1] = - row[1].to_i - # end - # EOT - # File.write('t.rb', ruby) - # # Put some CSV into a file. - # File.write('t.csv', "Name,Value\nfoo,0\nbar,1\nbaz,2") - # # Run the Ruby code with CSV filename as argument. - # system(Gem.ruby, "t.rb", "t.csv") - # - # Output (to STDOUT): - # - # Name,Value - # FOO,0 - # BAR,-1 - # BAZ,-2 - # - # Arguments: - # - # * Argument +in_string_or_io+ must be a \String or an \IO stream. - # * Argument +out_string_or_io+ must be a \String or an \IO stream. - # * Arguments **options must be keyword options. - # See {Options for Parsing}[#class-CSV-label-Options+for+Parsing]. - def filter(input=nil, output=nil, **options) - # parse options for input, output, or both - in_options, out_options = Hash.new, {row_sep: InputRecordSeparator.value} - options.each do |key, value| - case key - when /\Ain(?:put)?_(.+)\Z/ - in_options[$1.to_sym] = value - when /\Aout(?:put)?_(.+)\Z/ - out_options[$1.to_sym] = value - else - in_options[key] = value - out_options[key] = value - end - end - - # build input and output wrappers - input = new(input || ARGF, **in_options) - output = new(output || $stdout, **out_options) - - # process headers - need_manual_header_output = - (in_options[:headers] and - out_options[:headers] == true and - out_options[:write_headers]) - if need_manual_header_output - first_row = input.shift - if first_row - if first_row.is_a?(Row) - headers = first_row.headers - yield headers - output << headers - end - yield first_row - output << first_row - end - end - - # read, yield, write - input.each do |row| - yield row - output << row - end - end - - # - # :call-seq: - # foreach(path_or_io, mode='r', **options) {|row| ... ) - # foreach(path_or_io, mode='r', **options) -> new_enumerator - # - # Calls the block with each row read from source +path_or_io+. - # - # \Path input without headers: - # - # string = "foo,0\nbar,1\nbaz,2\n" - # in_path = 't.csv' - # File.write(in_path, string) - # CSV.foreach(in_path) {|row| p row } - # - # Output: - # - # ["foo", "0"] - # ["bar", "1"] - # ["baz", "2"] - # - # \Path input with headers: - # - # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # in_path = 't.csv' - # File.write(in_path, string) - # CSV.foreach(in_path, headers: true) {|row| p row } - # - # Output: - # - # - # - # - # - # \IO stream input without headers: - # - # string = "foo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # File.open('t.csv') do |in_io| - # CSV.foreach(in_io) {|row| p row } - # end - # - # Output: - # - # ["foo", "0"] - # ["bar", "1"] - # ["baz", "2"] - # - # \IO stream input with headers: - # - # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # File.open('t.csv') do |in_io| - # CSV.foreach(in_io, headers: true) {|row| p row } - # end - # - # Output: - # - # - # - # - # - # With no block given, returns an \Enumerator: - # - # string = "foo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # CSV.foreach(path) # => # - # - # Arguments: - # * Argument +path_or_io+ must be a file path or an \IO stream. - # * Argument +mode+, if given, must be a \File mode. - # See {Access Modes}[rdoc-ref:File@Access+Modes]. - # * Arguments **options must be keyword options. - # See {Options for Parsing}[#class-CSV-label-Options+for+Parsing]. - # * This method optionally accepts an additional :encoding option - # that you can use to specify the Encoding of the data read from +path+ or +io+. - # You must provide this unless your data is in the encoding - # given by Encoding::default_external. - # Parsing will use this to determine how to parse the data. - # You may provide a second Encoding to - # have the data transcoded as it is read. For example, - # encoding: 'UTF-32BE:UTF-8' - # would read +UTF-32BE+ data from the file - # but transcode it to +UTF-8+ before parsing. - def foreach(path, mode="r", **options, &block) - return to_enum(__method__, path, mode, **options) unless block_given? - open(path, mode, **options) do |csv| - csv.each(&block) - end - end - - # - # :call-seq: - # generate(csv_string, **options) {|csv| ... } - # generate(**options) {|csv| ... } - # - # * Argument +csv_string+, if given, must be a \String object; - # defaults to a new empty \String. - # * Arguments +options+, if given, should be generating options. - # See {Options for Generating}[#class-CSV-label-Options+for+Generating]. - # - # --- - # - # Creates a new \CSV object via CSV.new(csv_string, **options); - # calls the block with the \CSV object, which the block may modify; - # returns the \String generated from the \CSV object. - # - # Note that a passed \String *is* modified by this method. - # Pass csv_string.dup if the \String must be preserved. - # - # This method has one additional option: :encoding, - # which sets the base Encoding for the output if no no +str+ is specified. - # CSV needs this hint if you plan to output non-ASCII compatible data. - # - # --- - # - # Add lines: - # input_string = "foo,0\nbar,1\nbaz,2\n" - # output_string = CSV.generate(input_string) do |csv| - # csv << ['bat', 3] - # csv << ['bam', 4] - # end - # output_string # => "foo,0\nbar,1\nbaz,2\nbat,3\nbam,4\n" - # input_string # => "foo,0\nbar,1\nbaz,2\nbat,3\nbam,4\n" - # output_string.equal?(input_string) # => true # Same string, modified - # - # Add lines into new string, preserving old string: - # input_string = "foo,0\nbar,1\nbaz,2\n" - # output_string = CSV.generate(input_string.dup) do |csv| - # csv << ['bat', 3] - # csv << ['bam', 4] - # end - # output_string # => "foo,0\nbar,1\nbaz,2\nbat,3\nbam,4\n" - # input_string # => "foo,0\nbar,1\nbaz,2\n" - # output_string.equal?(input_string) # => false # Different strings - # - # Create lines from nothing: - # output_string = CSV.generate do |csv| - # csv << ['foo', 0] - # csv << ['bar', 1] - # csv << ['baz', 2] - # end - # output_string # => "foo,0\nbar,1\nbaz,2\n" - # - # --- - # - # Raises an exception if +csv_string+ is not a \String object: - # # Raises TypeError (no implicit conversion of Integer into String) - # CSV.generate(0) - # - def generate(str=nil, **options) - encoding = options[:encoding] - # add a default empty String, if none was given - if str - str = StringIO.new(str) - str.seek(0, IO::SEEK_END) - str.set_encoding(encoding) if encoding - else - str = +"" - str.force_encoding(encoding) if encoding - end - csv = new(str, **options) # wrap - yield csv # yield for appending - csv.string # return final String - end - - # :call-seq: - # CSV.generate_line(ary) - # CSV.generate_line(ary, **options) - # - # Returns the \String created by generating \CSV from +ary+ - # using the specified +options+. - # - # Argument +ary+ must be an \Array. - # - # Special options: - # * Option :row_sep defaults to "\n"> on Ruby 3.0 or later - # and $INPUT_RECORD_SEPARATOR ($/) otherwise.: - # $INPUT_RECORD_SEPARATOR # => "\n" - # * This method accepts an additional option, :encoding, which sets the base - # Encoding for the output. This method will try to guess your Encoding from - # the first non-+nil+ field in +row+, if possible, but you may need to use - # this parameter as a backup plan. - # - # For other +options+, - # see {Options for Generating}[#class-CSV-label-Options+for+Generating]. - # - # --- - # - # Returns the \String generated from an \Array: - # CSV.generate_line(['foo', '0']) # => "foo,0\n" - # - # --- - # - # Raises an exception if +ary+ is not an \Array: - # # Raises NoMethodError (undefined method `find' for :foo:Symbol) - # CSV.generate_line(:foo) - # - def generate_line(row, **options) - options = {row_sep: InputRecordSeparator.value}.merge(options) - str = +"" - if options[:encoding] - str.force_encoding(options[:encoding]) - else - fallback_encoding = nil - output_encoding = nil - row.each do |field| - next unless field.is_a?(String) - fallback_encoding ||= field.encoding - next if field.ascii_only? - output_encoding = field.encoding - break - end - output_encoding ||= fallback_encoding - if output_encoding - str.force_encoding(output_encoding) - end - end - (new(str, **options) << row).string - end - - # :call-seq: - # CSV.generate_lines(rows) - # CSV.generate_lines(rows, **options) - # - # Returns the \String created by generating \CSV from - # using the specified +options+. - # - # Argument +rows+ must be an \Array of row. Row is \Array of \String or \CSV::Row. - # - # Special options: - # * Option :row_sep defaults to "\n" on Ruby 3.0 or later - # and $INPUT_RECORD_SEPARATOR ($/) otherwise.: - # $INPUT_RECORD_SEPARATOR # => "\n" - # * This method accepts an additional option, :encoding, which sets the base - # Encoding for the output. This method will try to guess your Encoding from - # the first non-+nil+ field in +row+, if possible, but you may need to use - # this parameter as a backup plan. - # - # For other +options+, - # see {Options for Generating}[#class-CSV-label-Options+for+Generating]. - # - # --- - # - # Returns the \String generated from an - # CSV.generate_lines([['foo', '0'], ['bar', '1'], ['baz', '2']]) # => "foo,0\nbar,1\nbaz,2\n" - # - # --- - # - # Raises an exception - # # Raises NoMethodError (undefined method `each' for :foo:Symbol) - # CSV.generate_lines(:foo) - # - def generate_lines(rows, **options) - self.generate(**options) do |csv| - rows.each do |row| - csv << row - end - end - end - - # - # :call-seq: - # open(file_path, mode = "rb", **options ) -> new_csv - # open(io, mode = "rb", **options ) -> new_csv - # open(file_path, mode = "rb", **options ) { |csv| ... } -> object - # open(io, mode = "rb", **options ) { |csv| ... } -> object - # - # possible options elements: - # keyword form: - # :invalid => nil # raise error on invalid byte sequence (default) - # :invalid => :replace # replace invalid byte sequence - # :undef => :replace # replace undefined conversion - # :replace => string # replacement string ("?" or "\uFFFD" if not specified) - # - # * Argument +path+, if given, must be the path to a file. - # :include: ../doc/csv/arguments/io.rdoc - # * Argument +mode+, if given, must be a \File mode. - # See {Access Modes}[rdoc-ref:File@Access+Modes]. - # * Arguments **options must be keyword options. - # See {Options for Generating}[#class-CSV-label-Options+for+Generating]. - # * This method optionally accepts an additional :encoding option - # that you can use to specify the Encoding of the data read from +path+ or +io+. - # You must provide this unless your data is in the encoding - # given by Encoding::default_external. - # Parsing will use this to determine how to parse the data. - # You may provide a second Encoding to - # have the data transcoded as it is read. For example, - # encoding: 'UTF-32BE:UTF-8' - # would read +UTF-32BE+ data from the file - # but transcode it to +UTF-8+ before parsing. - # - # --- - # - # These examples assume prior execution of: - # string = "foo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # - # --- - # - # With no block given, returns a new \CSV object. - # - # Create a \CSV object using a file path: - # csv = CSV.open(path) - # csv # => # - # - # Create a \CSV object using an open \File: - # csv = CSV.open(File.open(path)) - # csv # => # - # - # --- - # - # With a block given, calls the block with the created \CSV object; - # returns the block's return value: - # - # Using a file path: - # csv = CSV.open(path) {|csv| p csv} - # csv # => # - # Output: - # # - # - # Using an open \File: - # csv = CSV.open(File.open(path)) {|csv| p csv} - # csv # => # - # Output: - # # - # - # --- - # - # Raises an exception if the argument is not a \String object or \IO object: - # # Raises TypeError (no implicit conversion of Symbol into String) - # CSV.open(:foo) - def open(filename, mode="r", **options) - # wrap a File opened with the remaining +args+ with no newline - # decorator - file_opts = options.dup - unless file_opts.key?(:newline) - file_opts[:universal_newline] ||= false - end - options.delete(:invalid) - options.delete(:undef) - options.delete(:replace) - options.delete_if {|k, _| /newline\z/.match?(k)} - - begin - f = File.open(filename, mode, **file_opts) - rescue ArgumentError => e - raise unless /needs binmode/.match?(e.message) and mode == "r" - mode = "rb" - file_opts = {encoding: Encoding.default_external}.merge(file_opts) - retry - end - begin - csv = new(f, **options) - rescue Exception - f.close - raise - end - - # handle blocks like Ruby's open(), not like the CSV library - if block_given? - begin - yield csv - ensure - csv.close - end - else - csv - end - end - - # - # :call-seq: - # parse(string) -> array_of_arrays - # parse(io) -> array_of_arrays - # parse(string, headers: ..., **options) -> csv_table - # parse(io, headers: ..., **options) -> csv_table - # parse(string, **options) {|row| ... } - # parse(io, **options) {|row| ... } - # - # Parses +string+ or +io+ using the specified +options+. - # - # - Argument +string+ should be a \String object; - # it will be put into a new StringIO object positioned at the beginning. - # :include: ../doc/csv/arguments/io.rdoc - # - Argument +options+: see {Options for Parsing}[#class-CSV-label-Options+for+Parsing] - # - # ====== Without Option +headers+ - # - # Without {option +headers+}[#class-CSV-label-Option+headers] case. - # - # These examples assume prior execution of: - # string = "foo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # - # --- - # - # With no block given, returns an \Array of Arrays formed from the source. - # - # Parse a \String: - # a_of_a = CSV.parse(string) - # a_of_a # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] - # - # Parse an open \File: - # a_of_a = File.open(path) do |file| - # CSV.parse(file) - # end - # a_of_a # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] - # - # --- - # - # With a block given, calls the block with each parsed row: - # - # Parse a \String: - # CSV.parse(string) {|row| p row } - # - # Output: - # ["foo", "0"] - # ["bar", "1"] - # ["baz", "2"] - # - # Parse an open \File: - # File.open(path) do |file| - # CSV.parse(file) {|row| p row } - # end - # - # Output: - # ["foo", "0"] - # ["bar", "1"] - # ["baz", "2"] - # - # ====== With Option +headers+ - # - # With {option +headers+}[#class-CSV-label-Option+headers] case. - # - # These examples assume prior execution of: - # string = "Name,Count\nfoo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # - # --- - # - # With no block given, returns a CSV::Table object formed from the source. - # - # Parse a \String: - # csv_table = CSV.parse(string, headers: ['Name', 'Count']) - # csv_table # => # - # - # Parse an open \File: - # csv_table = File.open(path) do |file| - # CSV.parse(file, headers: ['Name', 'Count']) - # end - # csv_table # => # - # - # --- - # - # With a block given, calls the block with each parsed row, - # which has been formed into a CSV::Row object: - # - # Parse a \String: - # CSV.parse(string, headers: ['Name', 'Count']) {|row| p row } - # - # Output: - # # - # # - # # - # - # Parse an open \File: - # File.open(path) do |file| - # CSV.parse(file, headers: ['Name', 'Count']) {|row| p row } - # end - # - # Output: - # # - # # - # # - # - # --- - # - # Raises an exception if the argument is not a \String object or \IO object: - # # Raises NoMethodError (undefined method `close' for :foo:Symbol) - # CSV.parse(:foo) - def parse(str, **options, &block) - csv = new(str, **options) - - return csv.each(&block) if block_given? - - # slurp contents, if no block is given - begin - csv.read - ensure - csv.close - end - end - - # :call-seq: - # CSV.parse_line(string) -> new_array or nil - # CSV.parse_line(io) -> new_array or nil - # CSV.parse_line(string, **options) -> new_array or nil - # CSV.parse_line(io, **options) -> new_array or nil - # CSV.parse_line(string, headers: true, **options) -> csv_row or nil - # CSV.parse_line(io, headers: true, **options) -> csv_row or nil - # - # Returns the data created by parsing the first line of +string+ or +io+ - # using the specified +options+. - # - # - Argument +string+ should be a \String object; - # it will be put into a new StringIO object positioned at the beginning. - # :include: ../doc/csv/arguments/io.rdoc - # - Argument +options+: see {Options for Parsing}[#class-CSV-label-Options+for+Parsing] - # - # ====== Without Option +headers+ - # - # Without option +headers+, returns the first row as a new \Array. - # - # These examples assume prior execution of: - # string = "foo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # - # Parse the first line from a \String object: - # CSV.parse_line(string) # => ["foo", "0"] - # - # Parse the first line from a File object: - # File.open(path) do |file| - # CSV.parse_line(file) # => ["foo", "0"] - # end # => ["foo", "0"] - # - # Returns +nil+ if the argument is an empty \String: - # CSV.parse_line('') # => nil - # - # ====== With Option +headers+ - # - # With {option +headers+}[#class-CSV-label-Option+headers], - # returns the first row as a CSV::Row object. - # - # These examples assume prior execution of: - # string = "Name,Count\nfoo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # - # Parse the first line from a \String object: - # CSV.parse_line(string, headers: true) # => # - # - # Parse the first line from a File object: - # File.open(path) do |file| - # CSV.parse_line(file, headers: true) - # end # => # - # - # --- - # - # Raises an exception if the argument is +nil+: - # # Raises ArgumentError (Cannot parse nil as CSV): - # CSV.parse_line(nil) - # - def parse_line(line, **options) - new(line, **options).each.first - end - - # - # :call-seq: - # read(source, **options) -> array_of_arrays - # read(source, headers: true, **options) -> csv_table - # - # Opens the given +source+ with the given +options+ (see CSV.open), - # reads the source (see CSV#read), and returns the result, - # which will be either an \Array of Arrays or a CSV::Table. - # - # Without headers: - # string = "foo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # CSV.read(path) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] - # - # With headers: - # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # CSV.read(path, headers: true) # => # - def read(path, **options) - open(path, **options) { |csv| csv.read } - end - - # :call-seq: - # CSV.readlines(source, **options) - # - # Alias for CSV.read. - def readlines(path, **options) - read(path, **options) - end - - # :call-seq: - # CSV.table(source, **options) - # - # Calls CSV.read with +source+, +options+, and certain default options: - # - +headers+: +true+ - # - +converters+: +:numeric+ - # - +header_converters+: +:symbol+ - # - # Returns a CSV::Table object. - # - # Example: - # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # CSV.table(path) # => # - def table(path, **options) - default_options = { - headers: true, - converters: :numeric, - header_converters: :symbol, - } - options = default_options.merge(options) - read(path, **options) - end - end - - # :call-seq: - # CSV.new(string) - # CSV.new(io) - # CSV.new(string, **options) - # CSV.new(io, **options) - # - # Returns the new \CSV object created using +string+ or +io+ - # and the specified +options+. - # - # - Argument +string+ should be a \String object; - # it will be put into a new StringIO object positioned at the beginning. - # :include: ../doc/csv/arguments/io.rdoc - # - Argument +options+: See: - # * {Options for Parsing}[#class-CSV-label-Options+for+Parsing] - # * {Options for Generating}[#class-CSV-label-Options+for+Generating] - # For performance reasons, the options cannot be overridden - # in a \CSV object, so those specified here will endure. - # - # In addition to the \CSV instance methods, several \IO methods are delegated. - # See {Delegated Methods}[#class-CSV-label-Delegated+Methods]. - # - # --- - # - # Create a \CSV object from a \String object: - # csv = CSV.new('foo,0') - # csv # => # - # - # Create a \CSV object from a \File object: - # File.write('t.csv', 'foo,0') - # csv = CSV.new(File.open('t.csv')) - # csv # => # - # - # --- - # - # Raises an exception if the argument is +nil+: - # # Raises ArgumentError (Cannot parse nil as CSV): - # CSV.new(nil) - # - def initialize(data, - col_sep: ",", - row_sep: :auto, - quote_char: '"', - field_size_limit: nil, - max_field_size: nil, - converters: nil, - unconverted_fields: nil, - headers: false, - return_headers: false, - write_headers: nil, - header_converters: nil, - skip_blanks: false, - force_quotes: false, - skip_lines: nil, - liberal_parsing: false, - internal_encoding: nil, - external_encoding: nil, - encoding: nil, - nil_value: nil, - empty_value: "", - strip: false, - quote_empty: true, - write_converters: nil, - write_nil_value: nil, - write_empty_value: "") - raise ArgumentError.new("Cannot parse nil as CSV") if data.nil? - - if data.is_a?(String) - if encoding - if encoding.is_a?(String) - data_external_encoding, data_internal_encoding = encoding.split(":", 2) - if data_internal_encoding - data = data.encode(data_internal_encoding, data_external_encoding) - else - data = data.dup.force_encoding(data_external_encoding) - end - else - data = data.dup.force_encoding(encoding) - end - end - @io = StringIO.new(data) - else - @io = data - end - @encoding = determine_encoding(encoding, internal_encoding) - - @base_fields_converter_options = { - nil_value: nil_value, - empty_value: empty_value, - } - @write_fields_converter_options = { - nil_value: write_nil_value, - empty_value: write_empty_value, - } - @initial_converters = converters - @initial_header_converters = header_converters - @initial_write_converters = write_converters - - if max_field_size.nil? and field_size_limit - max_field_size = field_size_limit - 1 - end - @parser_options = { - column_separator: col_sep, - row_separator: row_sep, - quote_character: quote_char, - max_field_size: max_field_size, - unconverted_fields: unconverted_fields, - headers: headers, - return_headers: return_headers, - skip_blanks: skip_blanks, - skip_lines: skip_lines, - liberal_parsing: liberal_parsing, - encoding: @encoding, - nil_value: nil_value, - empty_value: empty_value, - strip: strip, - } - @parser = nil - @parser_enumerator = nil - @eof_error = nil - - @writer_options = { - encoding: @encoding, - force_encoding: (not encoding.nil?), - force_quotes: force_quotes, - headers: headers, - write_headers: write_headers, - column_separator: col_sep, - row_separator: row_sep, - quote_character: quote_char, - quote_empty: quote_empty, - } - - @writer = nil - writer if @writer_options[:write_headers] - end - - # :call-seq: - # csv.col_sep -> string - # - # Returns the encoded column separator; used for parsing and writing; - # see {Option +col_sep+}[#class-CSV-label-Option+col_sep]: - # CSV.new('').col_sep # => "," - def col_sep - parser.column_separator - end - - # :call-seq: - # csv.row_sep -> string - # - # Returns the encoded row separator; used for parsing and writing; - # see {Option +row_sep+}[#class-CSV-label-Option+row_sep]: - # CSV.new('').row_sep # => "\n" - def row_sep - parser.row_separator - end - - # :call-seq: - # csv.quote_char -> character - # - # Returns the encoded quote character; used for parsing and writing; - # see {Option +quote_char+}[#class-CSV-label-Option+quote_char]: - # CSV.new('').quote_char # => "\"" - def quote_char - parser.quote_character - end - - # :call-seq: - # csv.field_size_limit -> integer or nil - # - # Returns the limit for field size; used for parsing; - # see {Option +field_size_limit+}[#class-CSV-label-Option+field_size_limit]: - # CSV.new('').field_size_limit # => nil - # - # Deprecated since 3.2.3. Use +max_field_size+ instead. - def field_size_limit - parser.field_size_limit - end - - # :call-seq: - # csv.max_field_size -> integer or nil - # - # Returns the limit for field size; used for parsing; - # see {Option +max_field_size+}[#class-CSV-label-Option+max_field_size]: - # CSV.new('').max_field_size # => nil - # - # Since 3.2.3. - def max_field_size - parser.max_field_size - end - - # :call-seq: - # csv.skip_lines -> regexp or nil - # - # Returns the \Regexp used to identify comment lines; used for parsing; - # see {Option +skip_lines+}[#class-CSV-label-Option+skip_lines]: - # CSV.new('').skip_lines # => nil - def skip_lines - parser.skip_lines - end - - # :call-seq: - # csv.converters -> array - # - # Returns an \Array containing field converters; - # see {Field Converters}[#class-CSV-label-Field+Converters]: - # csv = CSV.new('') - # csv.converters # => [] - # csv.convert(:integer) - # csv.converters # => [:integer] - # csv.convert(proc {|x| x.to_s }) - # csv.converters - # - # Notes that you need to call - # +Ractor.make_shareable(CSV::Converters)+ on the main Ractor to use - # this method. - def converters - parser_fields_converter.map do |converter| - name = Converters.rassoc(converter) - name ? name.first : converter - end - end - - # :call-seq: - # csv.unconverted_fields? -> object - # - # Returns the value that determines whether unconverted fields are to be - # available; used for parsing; - # see {Option +unconverted_fields+}[#class-CSV-label-Option+unconverted_fields]: - # CSV.new('').unconverted_fields? # => nil - def unconverted_fields? - parser.unconverted_fields? - end - - # :call-seq: - # csv.headers -> object - # - # Returns the value that determines whether headers are used; used for parsing; - # see {Option +headers+}[#class-CSV-label-Option+headers]: - # CSV.new('').headers # => nil - def headers - if @writer - @writer.headers - else - parsed_headers = parser.headers - return parsed_headers if parsed_headers - raw_headers = @parser_options[:headers] - raw_headers = nil if raw_headers == false - raw_headers - end - end - - # :call-seq: - # csv.return_headers? -> true or false - # - # Returns the value that determines whether headers are to be returned; used for parsing; - # see {Option +return_headers+}[#class-CSV-label-Option+return_headers]: - # CSV.new('').return_headers? # => false - def return_headers? - parser.return_headers? - end - - # :call-seq: - # csv.write_headers? -> true or false - # - # Returns the value that determines whether headers are to be written; used for generating; - # see {Option +write_headers+}[#class-CSV-label-Option+write_headers]: - # CSV.new('').write_headers? # => nil - def write_headers? - @writer_options[:write_headers] - end - - # :call-seq: - # csv.header_converters -> array - # - # Returns an \Array containing header converters; used for parsing; - # see {Header Converters}[#class-CSV-label-Header+Converters]: - # CSV.new('').header_converters # => [] - # - # Notes that you need to call - # +Ractor.make_shareable(CSV::HeaderConverters)+ on the main Ractor - # to use this method. - def header_converters - header_fields_converter.map do |converter| - name = HeaderConverters.rassoc(converter) - name ? name.first : converter - end - end - - # :call-seq: - # csv.skip_blanks? -> true or false - # - # Returns the value that determines whether blank lines are to be ignored; used for parsing; - # see {Option +skip_blanks+}[#class-CSV-label-Option+skip_blanks]: - # CSV.new('').skip_blanks? # => false - def skip_blanks? - parser.skip_blanks? - end - - # :call-seq: - # csv.force_quotes? -> true or false - # - # Returns the value that determines whether all output fields are to be quoted; - # used for generating; - # see {Option +force_quotes+}[#class-CSV-label-Option+force_quotes]: - # CSV.new('').force_quotes? # => false - def force_quotes? - @writer_options[:force_quotes] - end - - # :call-seq: - # csv.liberal_parsing? -> true or false - # - # Returns the value that determines whether illegal input is to be handled; used for parsing; - # see {Option +liberal_parsing+}[#class-CSV-label-Option+liberal_parsing]: - # CSV.new('').liberal_parsing? # => false - def liberal_parsing? - parser.liberal_parsing? - end - - # :call-seq: - # csv.encoding -> encoding - # - # Returns the encoding used for parsing and generating; - # see {Character Encodings (M17n or Multilingualization)}[#class-CSV-label-Character+Encodings+-28M17n+or+Multilingualization-29]: - # CSV.new('').encoding # => # - attr_reader :encoding - - # :call-seq: - # csv.line_no -> integer - # - # Returns the count of the rows parsed or generated. - # - # Parsing: - # string = "foo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # CSV.open(path) do |csv| - # csv.each do |row| - # p [csv.lineno, row] - # end - # end - # Output: - # [1, ["foo", "0"]] - # [2, ["bar", "1"]] - # [3, ["baz", "2"]] - # - # Generating: - # CSV.generate do |csv| - # p csv.lineno; csv << ['foo', 0] - # p csv.lineno; csv << ['bar', 1] - # p csv.lineno; csv << ['baz', 2] - # end - # Output: - # 0 - # 1 - # 2 - def lineno - if @writer - @writer.lineno - else - parser.lineno - end - end - - # :call-seq: - # csv.line -> array - # - # Returns the line most recently read: - # string = "foo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # CSV.open(path) do |csv| - # csv.each do |row| - # p [csv.lineno, csv.line] - # end - # end - # Output: - # [1, "foo,0\n"] - # [2, "bar,1\n"] - # [3, "baz,2\n"] - def line - parser.line - end - - ### IO and StringIO Delegation ### - - extend Forwardable - def_delegators :@io, :binmode, :close, :close_read, :close_write, - :closed?, :external_encoding, :fcntl, - :fileno, :flush, :fsync, :internal_encoding, - :isatty, :pid, :pos, :pos=, :reopen, - :seek, :string, :sync, :sync=, :tell, - :truncate, :tty? - - def binmode? - if @io.respond_to?(:binmode?) - @io.binmode? - else - false - end - end - - def flock(*args) - raise NotImplementedError unless @io.respond_to?(:flock) - @io.flock(*args) - end - - def ioctl(*args) - raise NotImplementedError unless @io.respond_to?(:ioctl) - @io.ioctl(*args) - end - - def path - @io.path if @io.respond_to?(:path) - end - - def stat(*args) - raise NotImplementedError unless @io.respond_to?(:stat) - @io.stat(*args) - end - - def to_i - raise NotImplementedError unless @io.respond_to?(:to_i) - @io.to_i - end - - def to_io - @io.respond_to?(:to_io) ? @io.to_io : @io - end - - def eof? - return false if @eof_error - begin - parser_enumerator.peek - false - rescue MalformedCSVError => error - @eof_error = error - false - rescue StopIteration - true - end - end - alias_method :eof, :eof? - - # Rewinds the underlying IO object and resets CSV's lineno() counter. - def rewind - @parser = nil - @parser_enumerator = nil - @eof_error = nil - @writer.rewind if @writer - @io.rewind - end - - ### End Delegation ### - - # :call-seq: - # csv << row -> self - # - # Appends a row to +self+. - # - # - Argument +row+ must be an \Array object or a CSV::Row object. - # - The output stream must be open for writing. - # - # --- - # - # Append Arrays: - # CSV.generate do |csv| - # csv << ['foo', 0] - # csv << ['bar', 1] - # csv << ['baz', 2] - # end # => "foo,0\nbar,1\nbaz,2\n" - # - # Append CSV::Rows: - # headers = [] - # CSV.generate do |csv| - # csv << CSV::Row.new(headers, ['foo', 0]) - # csv << CSV::Row.new(headers, ['bar', 1]) - # csv << CSV::Row.new(headers, ['baz', 2]) - # end # => "foo,0\nbar,1\nbaz,2\n" - # - # Headers in CSV::Row objects are not appended: - # headers = ['Name', 'Count'] - # CSV.generate do |csv| - # csv << CSV::Row.new(headers, ['foo', 0]) - # csv << CSV::Row.new(headers, ['bar', 1]) - # csv << CSV::Row.new(headers, ['baz', 2]) - # end # => "foo,0\nbar,1\nbaz,2\n" - # - # --- - # - # Raises an exception if +row+ is not an \Array or \CSV::Row: - # CSV.generate do |csv| - # # Raises NoMethodError (undefined method `collect' for :foo:Symbol) - # csv << :foo - # end - # - # Raises an exception if the output stream is not opened for writing: - # path = 't.csv' - # File.write(path, '') - # File.open(path) do |file| - # CSV.open(file) do |csv| - # # Raises IOError (not opened for writing) - # csv << ['foo', 0] - # end - # end - def <<(row) - writer << row - self - end - alias_method :add_row, :<< - alias_method :puts, :<< - - # :call-seq: - # convert(converter_name) -> array_of_procs - # convert {|field, field_info| ... } -> array_of_procs - # - # - With no block, installs a field converter (a \Proc). - # - With a block, defines and installs a custom field converter. - # - Returns the \Array of installed field converters. - # - # - Argument +converter_name+, if given, should be the name - # of an existing field converter. - # - # See {Field Converters}[#class-CSV-label-Field+Converters]. - # --- - # - # With no block, installs a field converter: - # csv = CSV.new('') - # csv.convert(:integer) - # csv.convert(:float) - # csv.convert(:date) - # csv.converters # => [:integer, :float, :date] - # - # --- - # - # The block, if given, is called for each field: - # - Argument +field+ is the field value. - # - Argument +field_info+ is a CSV::FieldInfo object - # containing details about the field. - # - # The examples here assume the prior execution of: - # string = "foo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # - # Example giving a block: - # csv = CSV.open(path) - # csv.convert {|field, field_info| p [field, field_info]; field.upcase } - # csv.read # => [["FOO", "0"], ["BAR", "1"], ["BAZ", "2"]] - # - # Output: - # ["foo", #] - # ["0", #] - # ["bar", #] - # ["1", #] - # ["baz", #] - # ["2", #] - # - # The block need not return a \String object: - # csv = CSV.open(path) - # csv.convert {|field, field_info| field.to_sym } - # csv.read # => [[:foo, :"0"], [:bar, :"1"], [:baz, :"2"]] - # - # If +converter_name+ is given, the block is not called: - # csv = CSV.open(path) - # csv.convert(:integer) {|field, field_info| fail 'Cannot happen' } - # csv.read # => [["foo", 0], ["bar", 1], ["baz", 2]] - # - # --- - # - # Raises a parse-time exception if +converter_name+ is not the name of a built-in - # field converter: - # csv = CSV.open(path) - # csv.convert(:nosuch) => [nil] - # # Raises NoMethodError (undefined method `arity' for nil:NilClass) - # csv.read - def convert(name = nil, &converter) - parser_fields_converter.add_converter(name, &converter) - end - - # :call-seq: - # header_convert(converter_name) -> array_of_procs - # header_convert {|header, field_info| ... } -> array_of_procs - # - # - With no block, installs a header converter (a \Proc). - # - With a block, defines and installs a custom header converter. - # - Returns the \Array of installed header converters. - # - # - Argument +converter_name+, if given, should be the name - # of an existing header converter. - # - # See {Header Converters}[#class-CSV-label-Header+Converters]. - # --- - # - # With no block, installs a header converter: - # csv = CSV.new('') - # csv.header_convert(:symbol) - # csv.header_convert(:downcase) - # csv.header_converters # => [:symbol, :downcase] - # - # --- - # - # The block, if given, is called for each header: - # - Argument +header+ is the header value. - # - Argument +field_info+ is a CSV::FieldInfo object - # containing details about the header. - # - # The examples here assume the prior execution of: - # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # - # Example giving a block: - # csv = CSV.open(path, headers: true) - # csv.header_convert {|header, field_info| p [header, field_info]; header.upcase } - # table = csv.read - # table # => # - # table.headers # => ["NAME", "VALUE"] - # - # Output: - # ["Name", #] - # ["Value", #] - - # The block need not return a \String object: - # csv = CSV.open(path, headers: true) - # csv.header_convert {|header, field_info| header.to_sym } - # table = csv.read - # table.headers # => [:Name, :Value] - # - # If +converter_name+ is given, the block is not called: - # csv = CSV.open(path, headers: true) - # csv.header_convert(:downcase) {|header, field_info| fail 'Cannot happen' } - # table = csv.read - # table.headers # => ["name", "value"] - # --- - # - # Raises a parse-time exception if +converter_name+ is not the name of a built-in - # field converter: - # csv = CSV.open(path, headers: true) - # csv.header_convert(:nosuch) - # # Raises NoMethodError (undefined method `arity' for nil:NilClass) - # csv.read - def header_convert(name = nil, &converter) - header_fields_converter.add_converter(name, &converter) - end - - include Enumerable - - # :call-seq: - # csv.each -> enumerator - # csv.each {|row| ...} - # - # Calls the block with each successive row. - # The data source must be opened for reading. - # - # Without headers: - # string = "foo,0\nbar,1\nbaz,2\n" - # csv = CSV.new(string) - # csv.each do |row| - # p row - # end - # Output: - # ["foo", "0"] - # ["bar", "1"] - # ["baz", "2"] - # - # With headers: - # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # csv = CSV.new(string, headers: true) - # csv.each do |row| - # p row - # end - # Output: - # - # - # - # - # --- - # - # Raises an exception if the source is not opened for reading: - # string = "foo,0\nbar,1\nbaz,2\n" - # csv = CSV.new(string) - # csv.close - # # Raises IOError (not opened for reading) - # csv.each do |row| - # p row - # end - def each(&block) - return to_enum(__method__) unless block_given? - begin - while true - yield(parser_enumerator.next) - end - rescue StopIteration - end - end - - # :call-seq: - # csv.read -> array or csv_table - # - # Forms the remaining rows from +self+ into: - # - A CSV::Table object, if headers are in use. - # - An \Array of Arrays, otherwise. - # - # The data source must be opened for reading. - # - # Without headers: - # string = "foo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # csv = CSV.open(path) - # csv.read # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] - # - # With headers: - # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # csv = CSV.open(path, headers: true) - # csv.read # => # - # - # --- - # - # Raises an exception if the source is not opened for reading: - # string = "foo,0\nbar,1\nbaz,2\n" - # csv = CSV.new(string) - # csv.close - # # Raises IOError (not opened for reading) - # csv.read - def read - rows = to_a - if parser.use_headers? - Table.new(rows, headers: parser.headers) - else - rows - end - end - alias_method :readlines, :read - - # :call-seq: - # csv.header_row? -> true or false - # - # Returns +true+ if the next row to be read is a header row\; - # +false+ otherwise. - # - # Without headers: - # string = "foo,0\nbar,1\nbaz,2\n" - # csv = CSV.new(string) - # csv.header_row? # => false - # - # With headers: - # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # csv = CSV.new(string, headers: true) - # csv.header_row? # => true - # csv.shift # => # - # csv.header_row? # => false - # - # --- - # - # Raises an exception if the source is not opened for reading: - # string = "foo,0\nbar,1\nbaz,2\n" - # csv = CSV.new(string) - # csv.close - # # Raises IOError (not opened for reading) - # csv.header_row? - def header_row? - parser.header_row? - end - - # :call-seq: - # csv.shift -> array, csv_row, or nil - # - # Returns the next row of data as: - # - An \Array if no headers are used. - # - A CSV::Row object if headers are used. - # - # The data source must be opened for reading. - # - # Without headers: - # string = "foo,0\nbar,1\nbaz,2\n" - # csv = CSV.new(string) - # csv.shift # => ["foo", "0"] - # csv.shift # => ["bar", "1"] - # csv.shift # => ["baz", "2"] - # csv.shift # => nil - # - # With headers: - # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # csv = CSV.new(string, headers: true) - # csv.shift # => # - # csv.shift # => # - # csv.shift # => # - # csv.shift # => nil - # - # --- - # - # Raises an exception if the source is not opened for reading: - # string = "foo,0\nbar,1\nbaz,2\n" - # csv = CSV.new(string) - # csv.close - # # Raises IOError (not opened for reading) - # csv.shift - def shift - if @eof_error - eof_error, @eof_error = @eof_error, nil - raise eof_error - end - begin - parser_enumerator.next - rescue StopIteration - nil - end - end - alias_method :gets, :shift - alias_method :readline, :shift - - # :call-seq: - # csv.inspect -> string - # - # Returns a \String showing certain properties of +self+: - # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # csv = CSV.new(string, headers: true) - # s = csv.inspect - # s # => "#" - def inspect - str = ["#<", self.class.to_s, " io_type:"] - # show type of wrapped IO - if @io == $stdout then str << "$stdout" - elsif @io == $stdin then str << "$stdin" - elsif @io == $stderr then str << "$stderr" - else str << @io.class.to_s - end - # show IO.path(), if available - if @io.respond_to?(:path) and (p = @io.path) - str << " io_path:" << p.inspect - end - # show encoding - str << " encoding:" << @encoding.name - # show other attributes - ["lineno", "col_sep", "row_sep", "quote_char"].each do |attr_name| - if a = __send__(attr_name) - str << " " << attr_name << ":" << a.inspect - end - end - ["skip_blanks", "liberal_parsing"].each do |attr_name| - if a = __send__("#{attr_name}?") - str << " " << attr_name << ":" << a.inspect - end - end - _headers = headers - str << " headers:" << _headers.inspect if _headers - str << ">" - begin - str.join('') - rescue # any encoding error - str.map do |s| - e = Encoding::Converter.asciicompat_encoding(s.encoding) - e ? s.encode(e) : s.force_encoding("ASCII-8BIT") - end.join('') - end - end - - private - - def determine_encoding(encoding, internal_encoding) - # honor the IO encoding if we can, otherwise default to ASCII-8BIT - io_encoding = raw_encoding - return io_encoding if io_encoding - - return Encoding.find(internal_encoding) if internal_encoding - - if encoding - encoding, = encoding.split(":", 2) if encoding.is_a?(String) - return Encoding.find(encoding) - end - - Encoding.default_internal || Encoding.default_external - end - - def normalize_converters(converters) - converters ||= [] - unless converters.is_a?(Array) - converters = [converters] - end - converters.collect do |converter| - case converter - when Proc # custom code block - [nil, converter] - else # by name - [converter, nil] - end - end - end - - # - # Processes +fields+ with @converters, or @header_converters - # if +headers+ is passed as +true+, returning the converted field set. Any - # converter that changes the field into something other than a String halts - # the pipeline of conversion for that field. This is primarily an efficiency - # shortcut. - # - def convert_fields(fields, headers = false) - if headers - header_fields_converter.convert(fields, nil, 0) - else - parser_fields_converter.convert(fields, @headers, lineno) - end - end - - # - # Returns the encoding of the internal IO object. - # - def raw_encoding - if @io.respond_to? :internal_encoding - @io.internal_encoding || @io.external_encoding - elsif @io.respond_to? :encoding - @io.encoding - else - nil - end - end - - def parser_fields_converter - @parser_fields_converter ||= build_parser_fields_converter - end - - def build_parser_fields_converter - specific_options = { - builtin_converters_name: :Converters, - } - options = @base_fields_converter_options.merge(specific_options) - build_fields_converter(@initial_converters, options) - end - - def header_fields_converter - @header_fields_converter ||= build_header_fields_converter - end - - def build_header_fields_converter - specific_options = { - builtin_converters_name: :HeaderConverters, - accept_nil: true, - } - options = @base_fields_converter_options.merge(specific_options) - build_fields_converter(@initial_header_converters, options) - end - - def writer_fields_converter - @writer_fields_converter ||= build_writer_fields_converter - end - - def build_writer_fields_converter - build_fields_converter(@initial_write_converters, - @write_fields_converter_options) - end - - def build_fields_converter(initial_converters, options) - fields_converter = FieldsConverter.new(options) - normalize_converters(initial_converters).each do |name, converter| - fields_converter.add_converter(name, &converter) - end - fields_converter - end - - def parser - @parser ||= Parser.new(@io, parser_options) - end - - def parser_options - @parser_options.merge(header_fields_converter: header_fields_converter, - fields_converter: parser_fields_converter) - end - - def parser_enumerator - @parser_enumerator ||= parser.parse - end - - def writer - @writer ||= Writer.new(@io, writer_options) - end - - def writer_options - @writer_options.merge(header_fields_converter: header_fields_converter, - fields_converter: writer_fields_converter) - end -end - -# Passes +args+ to CSV::instance. -# -# CSV("CSV,data").read -# #=> [["CSV", "data"]] -# -# If a block is given, the instance is passed the block and the return value -# becomes the return value of the block. -# -# CSV("CSV,data") { |c| -# c.read.any? { |a| a.include?("data") } -# } #=> true -# -# CSV("CSV,data") { |c| -# c.read.any? { |a| a.include?("zombies") } -# } #=> false -# -# CSV options may also be given. -# -# io = StringIO.new -# CSV(io, col_sep: ";") { |csv| csv << ["a", "b", "c"] } -# -# This API is not Ractor-safe. -# -def CSV(*args, **options, &block) - CSV.instance(*args, **options, &block) -end - -require_relative "csv/version" -require_relative "csv/core_ext/array" -require_relative "csv/core_ext/string" diff --git a/lib/csv/core_ext/array.rb b/lib/csv/core_ext/array.rb deleted file mode 100644 index 8beb06b082b522..00000000000000 --- a/lib/csv/core_ext/array.rb +++ /dev/null @@ -1,9 +0,0 @@ -class Array # :nodoc: - # Equivalent to CSV::generate_line(self, options) - # - # ["CSV", "data"].to_csv - # #=> "CSV,data\n" - def to_csv(**options) - CSV.generate_line(self, **options) - end -end diff --git a/lib/csv/core_ext/string.rb b/lib/csv/core_ext/string.rb deleted file mode 100644 index 9b1d31c2a4087f..00000000000000 --- a/lib/csv/core_ext/string.rb +++ /dev/null @@ -1,9 +0,0 @@ -class String # :nodoc: - # Equivalent to CSV::parse_line(self, options) - # - # "CSV,data".parse_csv - # #=> ["CSV", "data"] - def parse_csv(**options) - CSV.parse_line(self, **options) - end -end diff --git a/lib/csv/csv.gemspec b/lib/csv/csv.gemspec deleted file mode 100644 index 11c5b0f2a6e558..00000000000000 --- a/lib/csv/csv.gemspec +++ /dev/null @@ -1,64 +0,0 @@ -# frozen_string_literal: true - -begin - require_relative "lib/csv/version" -rescue LoadError - # for Ruby core repository - require_relative "version" -end - -Gem::Specification.new do |spec| - spec.name = "csv" - spec.version = CSV::VERSION - spec.authors = ["James Edward Gray II", "Kouhei Sutou"] - spec.email = [nil, "kou@cozmixng.org"] - - spec.summary = "CSV Reading and Writing" - spec.description = "The CSV library provides a complete interface to CSV files and data. It offers tools to enable you to read and write to and from Strings or IO objects, as needed." - spec.homepage = "https://github.com/ruby/csv" - spec.licenses = ["Ruby", "BSD-2-Clause"] - - lib_path = "lib" - spec.require_paths = [lib_path] - files = [] - lib_dir = File.join(__dir__, lib_path) - if File.exist?(lib_dir) - Dir.chdir(lib_dir) do - Dir.glob("**/*.rb").each do |file| - files << "lib/#{file}" - end - end - end - doc_dir = File.join(__dir__, "doc") - if File.exist?(doc_dir) - Dir.chdir(doc_dir) do - Dir.glob("**/*.rdoc").each do |rdoc_file| - files << "doc/#{rdoc_file}" - end - end - end - spec.files = files - spec.rdoc_options.concat(["--main", "README.md"]) - rdoc_files = [ - "LICENSE.txt", - "NEWS.md", - "README.md", - ] - recipes_dir = File.join(doc_dir, "csv", "recipes") - if File.exist?(recipes_dir) - Dir.chdir(recipes_dir) do - Dir.glob("**/*.rdoc").each do |recipe_file| - rdoc_files << "doc/csv/recipes/#{recipe_file}" - end - end - end - spec.extra_rdoc_files = rdoc_files - - spec.required_ruby_version = ">= 2.5.0" - - # spec.add_dependency "stringio", ">= 0.1.3" - spec.add_development_dependency "bundler" - spec.add_development_dependency "rake" - spec.add_development_dependency "benchmark_driver" - spec.add_development_dependency "test-unit", ">= 3.4.8" -end diff --git a/lib/csv/fields_converter.rb b/lib/csv/fields_converter.rb deleted file mode 100644 index d15977d3795f0a..00000000000000 --- a/lib/csv/fields_converter.rb +++ /dev/null @@ -1,89 +0,0 @@ -# frozen_string_literal: true - -class CSV - # Note: Don't use this class directly. This is an internal class. - class FieldsConverter - include Enumerable - # - # A CSV::FieldsConverter is a data structure for storing the - # fields converter properties to be passed as a parameter - # when parsing a new file (e.g. CSV::Parser.new(@io, parser_options)) - # - - def initialize(options={}) - @converters = [] - @nil_value = options[:nil_value] - @empty_value = options[:empty_value] - @empty_value_is_empty_string = (@empty_value == "") - @accept_nil = options[:accept_nil] - @builtin_converters_name = options[:builtin_converters_name] - @need_static_convert = need_static_convert? - end - - def add_converter(name=nil, &converter) - if name.nil? # custom converter - @converters << converter - else # named converter - combo = builtin_converters[name] - case combo - when Array # combo converter - combo.each do |sub_name| - add_converter(sub_name) - end - else # individual named converter - @converters << combo - end - end - end - - def each(&block) - @converters.each(&block) - end - - def empty? - @converters.empty? - end - - def convert(fields, headers, lineno, quoted_fields) - return fields unless need_convert? - - fields.collect.with_index do |field, index| - if field.nil? - field = @nil_value - elsif field.is_a?(String) and field.empty? - field = @empty_value unless @empty_value_is_empty_string - end - @converters.each do |converter| - break if field.nil? and @accept_nil - if converter.arity == 1 # straight field converter - field = converter[field] - else # FieldInfo converter - if headers - header = headers[index] - else - header = nil - end - quoted = quoted_fields[index] - field = converter[field, FieldInfo.new(index, lineno, header, quoted)] - end - break unless field.is_a?(String) # short-circuit pipeline for speed - end - field # final state of each field, converted or original - end - end - - private - def need_static_convert? - not (@nil_value.nil? and @empty_value_is_empty_string) - end - - def need_convert? - @need_static_convert or - (not @converters.empty?) - end - - def builtin_converters - @builtin_converters ||= ::CSV.const_get(@builtin_converters_name) - end - end -end diff --git a/lib/csv/input_record_separator.rb b/lib/csv/input_record_separator.rb deleted file mode 100644 index 7a99343c0cfbe7..00000000000000 --- a/lib/csv/input_record_separator.rb +++ /dev/null @@ -1,18 +0,0 @@ -require "English" -require "stringio" - -class CSV - module InputRecordSeparator - class << self - if RUBY_VERSION >= "3.0.0" - def value - "\n" - end - else - def value - $INPUT_RECORD_SEPARATOR - end - end - end - end -end diff --git a/lib/csv/parser.rb b/lib/csv/parser.rb deleted file mode 100644 index 4da87fbac8f049..00000000000000 --- a/lib/csv/parser.rb +++ /dev/null @@ -1,1288 +0,0 @@ -# frozen_string_literal: true - -require "strscan" - -require_relative "input_record_separator" -require_relative "row" -require_relative "table" - -class CSV - # Note: Don't use this class directly. This is an internal class. - class Parser - # - # A CSV::Parser is m17n aware. The parser works in the Encoding of the IO - # or String object being read from or written to. Your data is never transcoded - # (unless you ask Ruby to transcode it for you) and will literally be parsed in - # the Encoding it is in. Thus CSV will return Arrays or Rows of Strings in the - # Encoding of your data. This is accomplished by transcoding the parser itself - # into your Encoding. - # - - # Raised when encoding is invalid. - class InvalidEncoding < StandardError - end - - # Raised when unexpected case is happen. - class UnexpectedError < StandardError - end - - # - # CSV::Scanner receives a CSV output, scans it and return the content. - # It also controls the life cycle of the object with its methods +keep_start+, - # +keep_end+, +keep_back+, +keep_drop+. - # - # Uses StringScanner (the official strscan gem). Strscan provides lexical - # scanning operations on a String. We inherit its object and take advantage - # on the methods. For more information, please visit: - # https://ruby-doc.org/stdlib-2.6.1/libdoc/strscan/rdoc/StringScanner.html - # - class Scanner < StringScanner - alias_method :scan_all, :scan - - def initialize(*args) - super - @keeps = [] - end - - def each_line(row_separator) - position = pos - rest.each_line(row_separator) do |line| - position += line.bytesize - self.pos = position - yield(line) - end - end - - def keep_start - @keeps.push(pos) - end - - def keep_end - start = @keeps.pop - string.byteslice(start, pos - start) - end - - def keep_back - self.pos = @keeps.pop - end - - def keep_drop - @keeps.pop - end - end - - # - # CSV::InputsScanner receives IO inputs, encoding and the chunk_size. - # It also controls the life cycle of the object with its methods +keep_start+, - # +keep_end+, +keep_back+, +keep_drop+. - # - # CSV::InputsScanner.scan() tries to match with pattern at the current position. - # If there's a match, the scanner advances the "scan pointer" and returns the matched string. - # Otherwise, the scanner returns nil. - # - # CSV::InputsScanner.rest() returns the "rest" of the string (i.e. everything after the scan pointer). - # If there is no more data (eos? = true), it returns "". - # - class InputsScanner - def initialize(inputs, encoding, row_separator, chunk_size: 8192) - @inputs = inputs.dup - @encoding = encoding - @row_separator = row_separator - @chunk_size = chunk_size - @last_scanner = @inputs.empty? - @keeps = [] - read_chunk - end - - def each_line(row_separator) - return enum_for(__method__, row_separator) unless block_given? - buffer = nil - input = @scanner.rest - position = @scanner.pos - offset = 0 - n_row_separator_chars = row_separator.size - # trace(__method__, :start, input) - while true - input.each_line(row_separator) do |line| - @scanner.pos += line.bytesize - if buffer - if n_row_separator_chars == 2 and - buffer.end_with?(row_separator[0]) and - line.start_with?(row_separator[1]) - buffer << line[0] - line = line[1..-1] - position += buffer.bytesize + offset - @scanner.pos = position - offset = 0 - yield(buffer) - buffer = nil - next if line.empty? - else - buffer << line - line = buffer - buffer = nil - end - end - if line.end_with?(row_separator) - position += line.bytesize + offset - @scanner.pos = position - offset = 0 - yield(line) - else - buffer = line - end - end - break unless read_chunk - input = @scanner.rest - position = @scanner.pos - offset = -buffer.bytesize if buffer - end - yield(buffer) if buffer - end - - def scan(pattern) - # trace(__method__, pattern, :start) - value = @scanner.scan(pattern) - # trace(__method__, pattern, :done, :last, value) if @last_scanner - return value if @last_scanner - - read_chunk if value and @scanner.eos? - # trace(__method__, pattern, :done, value) - value - end - - def scan_all(pattern) - # trace(__method__, pattern, :start) - value = @scanner.scan(pattern) - # trace(__method__, pattern, :done, :last, value) if @last_scanner - return value if @last_scanner - - # trace(__method__, pattern, :done, :nil) if value.nil? - return nil if value.nil? - while @scanner.eos? and read_chunk and (sub_value = @scanner.scan(pattern)) - # trace(__method__, pattern, :sub, sub_value) - value << sub_value - end - # trace(__method__, pattern, :done, value) - value - end - - def eos? - @scanner.eos? - end - - def keep_start - # trace(__method__, :start) - adjust_last_keep - @keeps.push([@scanner, @scanner.pos, nil]) - # trace(__method__, :done) - end - - def keep_end - # trace(__method__, :start) - scanner, start, buffer = @keeps.pop - if scanner == @scanner - keep = @scanner.string.byteslice(start, @scanner.pos - start) - else - keep = @scanner.string.byteslice(0, @scanner.pos) - end - if buffer - buffer << keep - keep = buffer - end - # trace(__method__, :done, keep) - keep - end - - def keep_back - # trace(__method__, :start) - scanner, start, buffer = @keeps.pop - if buffer - # trace(__method__, :rescan, start, buffer) - string = @scanner.string - if scanner == @scanner - keep = string.byteslice(start, - string.bytesize - @scanner.pos - start) - else - keep = string - end - if keep and not keep.empty? - @inputs.unshift(StringIO.new(keep)) - @last_scanner = false - end - @scanner = StringScanner.new(buffer) - else - if @scanner != scanner - message = "scanners are different but no buffer: " - message += "#{@scanner.inspect}(#{@scanner.object_id}): " - message += "#{scanner.inspect}(#{scanner.object_id})" - raise UnexpectedError, message - end - # trace(__method__, :repos, start, buffer) - @scanner.pos = start - end - read_chunk if @scanner.eos? - end - - def keep_drop - _, _, buffer = @keeps.pop - # trace(__method__, :done, :empty) unless buffer - return unless buffer - - last_keep = @keeps.last - # trace(__method__, :done, :no_last_keep) unless last_keep - return unless last_keep - - if last_keep[2] - last_keep[2] << buffer - else - last_keep[2] = buffer - end - # trace(__method__, :done) - end - - def rest - @scanner.rest - end - - def check(pattern) - @scanner.check(pattern) - end - - private - def trace(*args) - pp([*args, @scanner, @scanner&.string, @scanner&.pos, @keeps]) - end - - def adjust_last_keep - # trace(__method__, :start) - - keep = @keeps.last - # trace(__method__, :done, :empty) if keep.nil? - return if keep.nil? - - scanner, start, buffer = keep - string = @scanner.string - if @scanner != scanner - start = 0 - end - if start == 0 and @scanner.eos? - keep_data = string - else - keep_data = string.byteslice(start, @scanner.pos - start) - end - if keep_data - if buffer - buffer << keep_data - else - keep[2] = keep_data.dup - end - end - - # trace(__method__, :done) - end - - def read_chunk - return false if @last_scanner - - adjust_last_keep - - input = @inputs.first - case input - when StringIO - string = input.read - raise InvalidEncoding unless string.valid_encoding? - # trace(__method__, :stringio, string) - @scanner = StringScanner.new(string) - @inputs.shift - @last_scanner = @inputs.empty? - true - else - chunk = input.gets(@row_separator, @chunk_size) - if chunk - raise InvalidEncoding unless chunk.valid_encoding? - # trace(__method__, :chunk, chunk) - @scanner = StringScanner.new(chunk) - if input.respond_to?(:eof?) and input.eof? - @inputs.shift - @last_scanner = @inputs.empty? - end - true - else - # trace(__method__, :no_chunk) - @scanner = StringScanner.new("".encode(@encoding)) - @inputs.shift - @last_scanner = @inputs.empty? - if @last_scanner - false - else - read_chunk - end - end - end - end - end - - def initialize(input, options) - @input = input - @options = options - @samples = [] - - prepare - end - - def column_separator - @column_separator - end - - def row_separator - @row_separator - end - - def quote_character - @quote_character - end - - def field_size_limit - @max_field_size&.succ - end - - def max_field_size - @max_field_size - end - - def skip_lines - @skip_lines - end - - def unconverted_fields? - @unconverted_fields - end - - def headers - @headers - end - - def header_row? - @use_headers and @headers.nil? - end - - def return_headers? - @return_headers - end - - def skip_blanks? - @skip_blanks - end - - def liberal_parsing? - @liberal_parsing - end - - def lineno - @lineno - end - - def line - last_line - end - - def parse(&block) - return to_enum(__method__) unless block_given? - - if @return_headers and @headers and @raw_headers - headers = Row.new(@headers, @raw_headers, true) - if @unconverted_fields - headers = add_unconverted_fields(headers, []) - end - yield headers - end - - begin - @scanner ||= build_scanner - if quote_character.nil? - parse_no_quote(&block) - elsif @need_robust_parsing - parse_quotable_robust(&block) - else - parse_quotable_loose(&block) - end - rescue InvalidEncoding - if @scanner - ignore_broken_line - lineno = @lineno - else - lineno = @lineno + 1 - end - raise InvalidEncodingError.new(@encoding, lineno) - rescue UnexpectedError => error - if @scanner - ignore_broken_line - lineno = @lineno - else - lineno = @lineno + 1 - end - message = "This should not be happen: #{error.message}: " - message += "Please report this to https://github.com/ruby/csv/issues" - raise MalformedCSVError.new(message, lineno) - end - end - - def use_headers? - @use_headers - end - - private - # A set of tasks to prepare the file in order to parse it - def prepare - prepare_variable - prepare_quote_character - prepare_backslash - prepare_skip_lines - prepare_strip - prepare_separators - validate_strip_and_col_sep_options - prepare_quoted - prepare_unquoted - prepare_line - prepare_header - prepare_parser - end - - def prepare_variable - @need_robust_parsing = false - @encoding = @options[:encoding] - liberal_parsing = @options[:liberal_parsing] - if liberal_parsing - @liberal_parsing = true - if liberal_parsing.is_a?(Hash) - @double_quote_outside_quote = - liberal_parsing[:double_quote_outside_quote] - @backslash_quote = liberal_parsing[:backslash_quote] - else - @double_quote_outside_quote = false - @backslash_quote = false - end - @need_robust_parsing = true - else - @liberal_parsing = false - @backslash_quote = false - end - @unconverted_fields = @options[:unconverted_fields] - @max_field_size = @options[:max_field_size] - @skip_blanks = @options[:skip_blanks] - @fields_converter = @options[:fields_converter] - @header_fields_converter = @options[:header_fields_converter] - end - - def prepare_quote_character - @quote_character = @options[:quote_character] - if @quote_character.nil? - @escaped_quote_character = nil - @escaped_quote = nil - else - @quote_character = @quote_character.to_s.encode(@encoding) - if @quote_character.length != 1 - message = ":quote_char has to be nil or a single character String" - raise ArgumentError, message - end - @escaped_quote_character = Regexp.escape(@quote_character) - @escaped_quote = Regexp.new(@escaped_quote_character) - end - end - - def prepare_backslash - return unless @backslash_quote - - @backslash_character = "\\".encode(@encoding) - - @escaped_backslash_character = Regexp.escape(@backslash_character) - @escaped_backslash = Regexp.new(@escaped_backslash_character) - if @quote_character.nil? - @backslash_quote_character = nil - else - @backslash_quote_character = - @backslash_character + @escaped_quote_character - end - end - - def prepare_skip_lines - skip_lines = @options[:skip_lines] - case skip_lines - when String - @skip_lines = skip_lines.encode(@encoding) - when Regexp, nil - @skip_lines = skip_lines - else - unless skip_lines.respond_to?(:match) - message = - ":skip_lines has to respond to \#match: #{skip_lines.inspect}" - raise ArgumentError, message - end - @skip_lines = skip_lines - end - end - - def prepare_strip - @strip = @options[:strip] - @escaped_strip = nil - @strip_value = nil - @rstrip_value = nil - if @strip.is_a?(String) - case @strip.length - when 0 - raise ArgumentError, ":strip must not be an empty String" - when 1 - # ok - else - raise ArgumentError, ":strip doesn't support 2 or more characters yet" - end - @strip = @strip.encode(@encoding) - @escaped_strip = Regexp.escape(@strip) - if @quote_character - @strip_value = Regexp.new(@escaped_strip + - "+".encode(@encoding)) - @rstrip_value = Regexp.new(@escaped_strip + - "+\\z".encode(@encoding)) - end - @need_robust_parsing = true - elsif @strip - strip_values = " \t\f\v" - @escaped_strip = strip_values.encode(@encoding) - if @quote_character - @strip_value = Regexp.new("[#{strip_values}]+".encode(@encoding)) - @rstrip_value = Regexp.new("[#{strip_values}]+\\z".encode(@encoding)) - end - @need_robust_parsing = true - end - end - - begin - StringScanner.new("x").scan("x") - rescue TypeError - STRING_SCANNER_SCAN_ACCEPT_STRING = false - else - STRING_SCANNER_SCAN_ACCEPT_STRING = true - end - - def prepare_separators - column_separator = @options[:column_separator] - @column_separator = column_separator.to_s.encode(@encoding) - if @column_separator.size < 1 - message = ":col_sep must be 1 or more characters: " - message += column_separator.inspect - raise ArgumentError, message - end - @row_separator = - resolve_row_separator(@options[:row_separator]).encode(@encoding) - - @escaped_column_separator = Regexp.escape(@column_separator) - @escaped_first_column_separator = Regexp.escape(@column_separator[0]) - if @column_separator.size > 1 - @column_end = Regexp.new(@escaped_column_separator) - @column_ends = @column_separator.each_char.collect do |char| - Regexp.new(Regexp.escape(char)) - end - @first_column_separators = Regexp.new(@escaped_first_column_separator + - "+".encode(@encoding)) - else - if STRING_SCANNER_SCAN_ACCEPT_STRING - @column_end = @column_separator - else - @column_end = Regexp.new(@escaped_column_separator) - end - @column_ends = nil - @first_column_separators = nil - end - - escaped_row_separator = Regexp.escape(@row_separator) - @row_end = Regexp.new(escaped_row_separator) - if @row_separator.size > 1 - @row_ends = @row_separator.each_char.collect do |char| - Regexp.new(Regexp.escape(char)) - end - else - @row_ends = nil - end - - @cr = "\r".encode(@encoding) - @lf = "\n".encode(@encoding) - @line_end = Regexp.new("\r\n|\n|\r".encode(@encoding)) - @not_line_end = Regexp.new("[^\r\n]+".encode(@encoding)) - end - - # This method verifies that there are no (obvious) ambiguities with the - # provided +col_sep+ and +strip+ parsing options. For example, if +col_sep+ - # and +strip+ were both equal to +\t+, then there would be no clear way to - # parse the input. - def validate_strip_and_col_sep_options - return unless @strip - - if @strip.is_a?(String) - if @column_separator.start_with?(@strip) || @column_separator.end_with?(@strip) - raise ArgumentError, - "The provided strip (#{@escaped_strip}) and " \ - "col_sep (#{@escaped_column_separator}) options are incompatible." - end - else - if Regexp.new("\\A[#{@escaped_strip}]|[#{@escaped_strip}]\\z").match?(@column_separator) - raise ArgumentError, - "The provided strip (true) and " \ - "col_sep (#{@escaped_column_separator}) options are incompatible." - end - end - end - - def prepare_quoted - if @quote_character - @quotes = Regexp.new(@escaped_quote_character + - "+".encode(@encoding)) - no_quoted_values = @escaped_quote_character.dup - if @backslash_quote - no_quoted_values << @escaped_backslash_character - end - @quoted_value = Regexp.new("[^".encode(@encoding) + - no_quoted_values + - "]+".encode(@encoding)) - end - if @escaped_strip - @split_column_separator = Regexp.new(@escaped_strip + - "*".encode(@encoding) + - @escaped_column_separator + - @escaped_strip + - "*".encode(@encoding)) - else - if @column_separator == " ".encode(@encoding) - @split_column_separator = Regexp.new(@escaped_column_separator) - else - @split_column_separator = @column_separator - end - end - end - - def prepare_unquoted - return if @quote_character.nil? - - no_unquoted_values = "\r\n".encode(@encoding) - no_unquoted_values << @escaped_first_column_separator - unless @liberal_parsing - no_unquoted_values << @escaped_quote_character - end - @unquoted_value = Regexp.new("[^".encode(@encoding) + - no_unquoted_values + - "]+".encode(@encoding)) - end - - def resolve_row_separator(separator) - if separator == :auto - cr = "\r".encode(@encoding) - lf = "\n".encode(@encoding) - if @input.is_a?(StringIO) - pos = @input.pos - separator = detect_row_separator(@input.read, cr, lf) - @input.seek(pos) - elsif @input.respond_to?(:gets) - if @input.is_a?(File) - chunk_size = 32 * 1024 - else - chunk_size = 1024 - end - begin - while separator == :auto - # - # if we run out of data, it's probably a single line - # (ensure will set default value) - # - break unless sample = @input.gets(nil, chunk_size) - - # extend sample if we're unsure of the line ending - if sample.end_with?(cr) - sample << (@input.gets(nil, 1) || "") - end - - @samples << sample - - separator = detect_row_separator(sample, cr, lf) - end - rescue IOError - # do nothing: ensure will set default - end - end - separator = InputRecordSeparator.value if separator == :auto - end - separator.to_s.encode(@encoding) - end - - def detect_row_separator(sample, cr, lf) - lf_index = sample.index(lf) - if lf_index - cr_index = sample[0, lf_index].index(cr) - else - cr_index = sample.index(cr) - end - if cr_index and lf_index - if cr_index + 1 == lf_index - cr + lf - elsif cr_index < lf_index - cr - else - lf - end - elsif cr_index - cr - elsif lf_index - lf - else - :auto - end - end - - def prepare_line - @lineno = 0 - @last_line = nil - @scanner = nil - end - - def last_line - if @scanner - @last_line ||= @scanner.keep_end - else - @last_line - end - end - - def prepare_header - @return_headers = @options[:return_headers] - - headers = @options[:headers] - case headers - when Array - @raw_headers = headers - quoted_fields = [false] * @raw_headers.size - @use_headers = true - when String - @raw_headers, quoted_fields = parse_headers(headers) - @use_headers = true - when nil, false - @raw_headers = nil - @use_headers = false - else - @raw_headers = nil - @use_headers = true - end - if @raw_headers - @headers = adjust_headers(@raw_headers, quoted_fields) - else - @headers = nil - end - end - - def parse_headers(row) - quoted_fields = [] - converter = lambda do |field, info| - quoted_fields << info.quoted? - field - end - headers = CSV.parse_line(row, - col_sep: @column_separator, - row_sep: @row_separator, - quote_char: @quote_character, - converters: [converter]) - [headers, quoted_fields] - end - - def adjust_headers(headers, quoted_fields) - adjusted_headers = @header_fields_converter.convert(headers, nil, @lineno, quoted_fields) - adjusted_headers.each {|h| h.freeze if h.is_a? String} - adjusted_headers - end - - def prepare_parser - @may_quoted = may_quoted? - end - - def may_quoted? - return false if @quote_character.nil? - - if @input.is_a?(StringIO) - pos = @input.pos - sample = @input.read - @input.seek(pos) - else - return false if @samples.empty? - sample = @samples.first - end - sample[0, 128].index(@quote_character) - end - - class UnoptimizedStringIO # :nodoc: - def initialize(string) - @io = StringIO.new(string, "rb:#{string.encoding}") - end - - def gets(*args) - @io.gets(*args) - end - - def each_line(*args, &block) - @io.each_line(*args, &block) - end - - def eof? - @io.eof? - end - end - - SCANNER_TEST = (ENV["CSV_PARSER_SCANNER_TEST"] == "yes") - if SCANNER_TEST - SCANNER_TEST_CHUNK_SIZE_NAME = "CSV_PARSER_SCANNER_TEST_CHUNK_SIZE" - SCANNER_TEST_CHUNK_SIZE_VALUE = ENV[SCANNER_TEST_CHUNK_SIZE_NAME] - def build_scanner - inputs = @samples.collect do |sample| - UnoptimizedStringIO.new(sample) - end - if @input.is_a?(StringIO) - inputs << UnoptimizedStringIO.new(@input.read) - else - inputs << @input - end - begin - chunk_size_value = ENV[SCANNER_TEST_CHUNK_SIZE_NAME] - rescue # Ractor::IsolationError - # Ractor on Ruby 3.0 can't read ENV value. - chunk_size_value = SCANNER_TEST_CHUNK_SIZE_VALUE - end - chunk_size = Integer((chunk_size_value || "1"), 10) - InputsScanner.new(inputs, - @encoding, - @row_separator, - chunk_size: chunk_size) - end - else - def build_scanner - string = nil - if @samples.empty? and @input.is_a?(StringIO) - string = @input.read - elsif @samples.size == 1 and - @input != ARGF and - @input.respond_to?(:eof?) and - @input.eof? - string = @samples[0] - end - if string - unless string.valid_encoding? - index = string.lines(@row_separator).index do |line| - !line.valid_encoding? - end - if index - raise InvalidEncodingError.new(@encoding, @lineno + index + 1) - end - end - Scanner.new(string) - else - inputs = @samples.collect do |sample| - StringIO.new(sample) - end - inputs << @input - InputsScanner.new(inputs, @encoding, @row_separator) - end - end - end - - def skip_needless_lines - return unless @skip_lines - - until @scanner.eos? - @scanner.keep_start - line = @scanner.scan_all(@not_line_end) || "".encode(@encoding) - line << @row_separator if parse_row_end - if skip_line?(line) - @lineno += 1 - @scanner.keep_drop - else - @scanner.keep_back - return - end - end - end - - def skip_line?(line) - line = line.delete_suffix(@row_separator) - case @skip_lines - when String - line.include?(@skip_lines) - when Regexp - @skip_lines.match?(line) - else - @skip_lines.match(line) - end - end - - def validate_field_size(field) - return unless @max_field_size - return if field.size <= @max_field_size - ignore_broken_line - message = "Field size exceeded: #{field.size} > #{@max_field_size}" - raise MalformedCSVError.new(message, @lineno) - end - - def parse_no_quote(&block) - @scanner.each_line(@row_separator) do |line| - next if @skip_lines and skip_line?(line) - original_line = line - line = line.delete_suffix(@row_separator) - - if line.empty? - next if @skip_blanks - row = [] - quoted_fields = [] - else - line = strip_value(line) - row = line.split(@split_column_separator, -1) - quoted_fields = [false] * row.size - if @max_field_size - row.each do |column| - validate_field_size(column) - end - end - n_columns = row.size - i = 0 - while i < n_columns - row[i] = nil if row[i].empty? - i += 1 - end - end - @last_line = original_line - emit_row(row, quoted_fields, &block) - end - end - - def parse_quotable_loose(&block) - @scanner.keep_start - @scanner.each_line(@row_separator) do |line| - if @skip_lines and skip_line?(line) - @scanner.keep_drop - @scanner.keep_start - next - end - original_line = line - line = line.delete_suffix(@row_separator) - - if line.empty? - if @skip_blanks - @scanner.keep_drop - @scanner.keep_start - next - end - row = [] - quoted_fields = [] - elsif line.include?(@cr) or line.include?(@lf) - @scanner.keep_back - @need_robust_parsing = true - return parse_quotable_robust(&block) - else - row = line.split(@split_column_separator, -1) - quoted_fields = [] - n_columns = row.size - i = 0 - while i < n_columns - column = row[i] - if column.empty? - quoted_fields << false - row[i] = nil - else - n_quotes = column.count(@quote_character) - if n_quotes.zero? - quoted_fields << false - # no quote - elsif n_quotes == 2 and - column.start_with?(@quote_character) and - column.end_with?(@quote_character) - quoted_fields << true - row[i] = column[1..-2] - else - @scanner.keep_back - @need_robust_parsing = true - return parse_quotable_robust(&block) - end - validate_field_size(row[i]) - end - i += 1 - end - end - @scanner.keep_drop - @scanner.keep_start - @last_line = original_line - emit_row(row, quoted_fields, &block) - end - @scanner.keep_drop - end - - def parse_quotable_robust(&block) - row = [] - quoted_fields = [] - skip_needless_lines - start_row - while true - @quoted_column_value = false - @unquoted_column_value = false - @scanner.scan_all(@strip_value) if @strip_value - value = parse_column_value - if value - @scanner.scan_all(@strip_value) if @strip_value - validate_field_size(value) - end - if parse_column_end - row << value - quoted_fields << @quoted_column_value - elsif parse_row_end - if row.empty? and value.nil? - emit_row([], [], &block) unless @skip_blanks - else - row << value - quoted_fields << @quoted_column_value - emit_row(row, quoted_fields, &block) - row = [] - quoted_fields = [] - end - skip_needless_lines - start_row - elsif @scanner.eos? - break if row.empty? and value.nil? - row << value - quoted_fields << @quoted_column_value - emit_row(row, quoted_fields, &block) - break - else - if @quoted_column_value - if liberal_parsing? and (new_line = @scanner.check(@line_end)) - message = - "Illegal end-of-line sequence outside of a quoted field " + - "<#{new_line.inspect}>" - else - message = "Any value after quoted field isn't allowed" - end - ignore_broken_line - raise MalformedCSVError.new(message, @lineno) - elsif @unquoted_column_value and - (new_line = @scanner.scan(@line_end)) - ignore_broken_line - message = "Unquoted fields do not allow new line " + - "<#{new_line.inspect}>" - raise MalformedCSVError.new(message, @lineno) - elsif @scanner.rest.start_with?(@quote_character) - ignore_broken_line - message = "Illegal quoting" - raise MalformedCSVError.new(message, @lineno) - elsif (new_line = @scanner.scan(@line_end)) - ignore_broken_line - message = "New line must be <#{@row_separator.inspect}> " + - "not <#{new_line.inspect}>" - raise MalformedCSVError.new(message, @lineno) - else - ignore_broken_line - raise MalformedCSVError.new("TODO: Meaningful message", - @lineno) - end - end - end - end - - def parse_column_value - if @liberal_parsing - quoted_value = parse_quoted_column_value - if quoted_value - @scanner.scan_all(@strip_value) if @strip_value - unquoted_value = parse_unquoted_column_value - if unquoted_value - if @double_quote_outside_quote - unquoted_value = unquoted_value.gsub(@quote_character * 2, - @quote_character) - if quoted_value.empty? # %Q{""...} case - return @quote_character + unquoted_value - end - end - @quote_character + quoted_value + @quote_character + unquoted_value - else - quoted_value - end - else - parse_unquoted_column_value - end - elsif @may_quoted - parse_quoted_column_value || - parse_unquoted_column_value - else - parse_unquoted_column_value || - parse_quoted_column_value - end - end - - def parse_unquoted_column_value - value = @scanner.scan_all(@unquoted_value) - return nil unless value - - @unquoted_column_value = true - if @first_column_separators - while true - @scanner.keep_start - is_column_end = @column_ends.all? do |column_end| - @scanner.scan(column_end) - end - @scanner.keep_back - break if is_column_end - sub_separator = @scanner.scan_all(@first_column_separators) - break if sub_separator.nil? - value << sub_separator - sub_value = @scanner.scan_all(@unquoted_value) - break if sub_value.nil? - value << sub_value - end - end - value.gsub!(@backslash_quote_character, @quote_character) if @backslash_quote - if @rstrip_value - value.gsub!(@rstrip_value, "") - end - value - end - - def parse_quoted_column_value - quotes = @scanner.scan_all(@quotes) - return nil unless quotes - - @quoted_column_value = true - n_quotes = quotes.size - if (n_quotes % 2).zero? - quotes[0, (n_quotes - 2) / 2] - else - value = quotes[0, n_quotes / 2] - while true - quoted_value = @scanner.scan_all(@quoted_value) - value << quoted_value if quoted_value - if @backslash_quote - if @scanner.scan(@escaped_backslash) - if @scanner.scan(@escaped_quote) - value << @quote_character - else - value << @backslash_character - end - next - end - end - - quotes = @scanner.scan_all(@quotes) - unless quotes - ignore_broken_line - message = "Unclosed quoted field" - raise MalformedCSVError.new(message, @lineno) - end - n_quotes = quotes.size - if n_quotes == 1 - break - else - value << quotes[0, n_quotes / 2] - break if (n_quotes % 2) == 1 - end - end - value - end - end - - def parse_column_end - return true if @scanner.scan(@column_end) - return false unless @column_ends - - @scanner.keep_start - if @column_ends.all? {|column_end| @scanner.scan(column_end)} - @scanner.keep_drop - true - else - @scanner.keep_back - false - end - end - - def parse_row_end - return true if @scanner.scan(@row_end) - return false unless @row_ends - @scanner.keep_start - if @row_ends.all? {|row_end| @scanner.scan(row_end)} - @scanner.keep_drop - true - else - @scanner.keep_back - false - end - end - - def strip_value(value) - return value unless @strip - return value if value.nil? - - case @strip - when String - while value.delete_prefix!(@strip) - # do nothing - end - while value.delete_suffix!(@strip) - # do nothing - end - else - value.strip! - end - value - end - - def ignore_broken_line - @scanner.scan_all(@not_line_end) - @scanner.scan_all(@line_end) - @lineno += 1 - end - - def start_row - if @last_line - @last_line = nil - else - @scanner.keep_drop - end - @scanner.keep_start - end - - def emit_row(row, quoted_fields, &block) - @lineno += 1 - - raw_row = row - if @use_headers - if @headers.nil? - @headers = adjust_headers(row, quoted_fields) - return unless @return_headers - row = Row.new(@headers, row, true) - else - row = Row.new(@headers, - @fields_converter.convert(raw_row, @headers, @lineno, quoted_fields)) - end - else - # convert fields, if needed... - row = @fields_converter.convert(raw_row, nil, @lineno, quoted_fields) - end - - # inject unconverted fields and accessor, if requested... - if @unconverted_fields and not row.respond_to?(:unconverted_fields) - add_unconverted_fields(row, raw_row) - end - - yield(row) - end - - # This method injects an instance variable unconverted_fields into - # +row+ and an accessor method for +row+ called unconverted_fields(). The - # variable is set to the contents of +fields+. - def add_unconverted_fields(row, fields) - class << row - attr_reader :unconverted_fields - end - row.instance_variable_set(:@unconverted_fields, fields) - row - end - end -end diff --git a/lib/csv/row.rb b/lib/csv/row.rb deleted file mode 100644 index 86323f7d0a7d4c..00000000000000 --- a/lib/csv/row.rb +++ /dev/null @@ -1,757 +0,0 @@ -# frozen_string_literal: true - -require "forwardable" - -class CSV - # = \CSV::Row - # A \CSV::Row instance represents a \CSV table row. - # (see {class CSV}[../CSV.html]). - # - # The instance may have: - # - Fields: each is an object, not necessarily a \String. - # - Headers: each serves a key, and also need not be a \String. - # - # === Instance Methods - # - # \CSV::Row has three groups of instance methods: - # - Its own internally defined instance methods. - # - Methods included by module Enumerable. - # - Methods delegated to class Array.: - # * Array#empty? - # * Array#length - # * Array#size - # - # == Creating a \CSV::Row Instance - # - # Commonly, a new \CSV::Row instance is created by parsing \CSV source - # that has headers: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.each {|row| p row } - # Output: - # # - # # - # # - # - # You can also create a row directly. See ::new. - # - # == Headers - # - # Like a \CSV::Table, a \CSV::Row has headers. - # - # A \CSV::Row that was created by parsing \CSV source - # inherits its headers from the table: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # row = table.first - # row.headers # => ["Name", "Value"] - # - # You can also create a new row with headers; - # like the keys in a \Hash, the headers need not be Strings: - # row = CSV::Row.new([:name, :value], ['foo', 0]) - # row.headers # => [:name, :value] - # - # The new row retains its headers even if added to a table - # that has headers: - # table << row # => # - # row.headers # => [:name, :value] - # row[:name] # => "foo" - # row['Name'] # => nil - # - # - # - # == Accessing Fields - # - # You may access a field in a \CSV::Row with either its \Integer index - # (\Array-style) or its header (\Hash-style). - # - # Fetch a field using method #[]: - # row = CSV::Row.new(['Name', 'Value'], ['foo', 0]) - # row[1] # => 0 - # row['Value'] # => 0 - # - # Set a field using method #[]=: - # row = CSV::Row.new(['Name', 'Value'], ['foo', 0]) - # row # => # - # row[0] = 'bar' - # row['Value'] = 1 - # row # => # - # - class Row - # :call-seq: - # CSV::Row.new(headers, fields, header_row = false) -> csv_row - # - # Returns the new \CSV::Row instance constructed from - # arguments +headers+ and +fields+; both should be Arrays; - # note that the fields need not be Strings: - # row = CSV::Row.new(['Name', 'Value'], ['foo', 0]) - # row # => # - # - # If the \Array lengths are different, the shorter is +nil+-filled: - # row = CSV::Row.new(['Name', 'Value', 'Date', 'Size'], ['foo', 0]) - # row # => # - # - # Each \CSV::Row object is either a field row or a header row; - # by default, a new row is a field row; for the row created above: - # row.field_row? # => true - # row.header_row? # => false - # - # If the optional argument +header_row+ is given as +true+, - # the created row is a header row: - # row = CSV::Row.new(['Name', 'Value'], ['foo', 0], header_row = true) - # row # => # - # row.field_row? # => false - # row.header_row? # => true - def initialize(headers, fields, header_row = false) - @header_row = header_row - headers.each { |h| h.freeze if h.is_a? String } - - # handle extra headers or fields - @row = if headers.size >= fields.size - headers.zip(fields) - else - fields.zip(headers).each(&:reverse!) - end - end - - # Internal data format used to compare equality. - attr_reader :row - protected :row - - ### Array Delegation ### - - extend Forwardable - def_delegators :@row, :empty?, :length, :size - - # :call-seq: - # row.initialize_copy(other_row) -> self - # - # Calls superclass method. - def initialize_copy(other) - super_return_value = super - @row = @row.collect(&:dup) - super_return_value - end - - # :call-seq: - # row.header_row? -> true or false - # - # Returns +true+ if this is a header row, +false+ otherwise. - def header_row? - @header_row - end - - # :call-seq: - # row.field_row? -> true or false - # - # Returns +true+ if this is a field row, +false+ otherwise. - def field_row? - not header_row? - end - - # :call-seq: - # row.headers -> array_of_headers - # - # Returns the headers for this row: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # row = table.first - # row.headers # => ["Name", "Value"] - def headers - @row.map(&:first) - end - - # :call-seq: - # field(index) -> value - # field(header) -> value - # field(header, offset) -> value - # - # Returns the field value for the given +index+ or +header+. - # - # --- - # - # Fetch field value by \Integer index: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.field(0) # => "foo" - # row.field(1) # => "bar" - # - # Counts backward from the last column if +index+ is negative: - # row.field(-1) # => "0" - # row.field(-2) # => "foo" - # - # Returns +nil+ if +index+ is out of range: - # row.field(2) # => nil - # row.field(-3) # => nil - # - # --- - # - # Fetch field value by header (first found): - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.field('Name') # => "Foo" - # - # Fetch field value by header, ignoring +offset+ leading fields: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.field('Name', 2) # => "Baz" - # - # Returns +nil+ if the header does not exist. - def field(header_or_index, minimum_index = 0) - # locate the pair - finder = (header_or_index.is_a?(Integer) || header_or_index.is_a?(Range)) ? :[] : :assoc - pair = @row[minimum_index..-1].public_send(finder, header_or_index) - - # return the field if we have a pair - if pair.nil? - nil - else - header_or_index.is_a?(Range) ? pair.map(&:last) : pair.last - end - end - alias_method :[], :field - - # - # :call-seq: - # fetch(header) -> value - # fetch(header, default) -> value - # fetch(header) {|row| ... } -> value - # - # Returns the field value as specified by +header+. - # - # --- - # - # With the single argument +header+, returns the field value - # for that header (first found): - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.fetch('Name') # => "Foo" - # - # Raises exception +KeyError+ if the header does not exist. - # - # --- - # - # With arguments +header+ and +default+ given, - # returns the field value for the header (first found) - # if the header exists, otherwise returns +default+: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.fetch('Name', '') # => "Foo" - # row.fetch(:nosuch, '') # => "" - # - # --- - # - # With argument +header+ and a block given, - # returns the field value for the header (first found) - # if the header exists; otherwise calls the block - # and returns its return value: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.fetch('Name') {|header| fail 'Cannot happen' } # => "Foo" - # row.fetch(:nosuch) {|header| "Header '#{header} not found'" } # => "Header 'nosuch not found'" - def fetch(header, *varargs) - raise ArgumentError, "Too many arguments" if varargs.length > 1 - pair = @row.assoc(header) - if pair - pair.last - else - if block_given? - yield header - elsif varargs.empty? - raise KeyError, "key not found: #{header}" - else - varargs.first - end - end - end - - # :call-seq: - # row.has_key?(header) -> true or false - # - # Returns +true+ if there is a field with the given +header+, - # +false+ otherwise. - def has_key?(header) - !!@row.assoc(header) - end - alias_method :include?, :has_key? - alias_method :key?, :has_key? - alias_method :member?, :has_key? - alias_method :header?, :has_key? - - # - # :call-seq: - # row[index] = value -> value - # row[header, offset] = value -> value - # row[header] = value -> value - # - # Assigns the field value for the given +index+ or +header+; - # returns +value+. - # - # --- - # - # Assign field value by \Integer index: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row[0] = 'Bat' - # row[1] = 3 - # row # => # - # - # Counts backward from the last column if +index+ is negative: - # row[-1] = 4 - # row[-2] = 'Bam' - # row # => # - # - # Extends the row with nil:nil if positive +index+ is not in the row: - # row[4] = 5 - # row # => # - # - # Raises IndexError if negative +index+ is too small (too far from zero). - # - # --- - # - # Assign field value by header (first found): - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row['Name'] = 'Bat' - # row # => # - # - # Assign field value by header, ignoring +offset+ leading fields: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row['Name', 2] = 4 - # row # => # - # - # Append new field by (new) header: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row['New'] = 6 - # row# => # - def []=(*args) - value = args.pop - - if args.first.is_a? Integer - if @row[args.first].nil? # extending past the end with index - @row[args.first] = [nil, value] - @row.map! { |pair| pair.nil? ? [nil, nil] : pair } - else # normal index assignment - @row[args.first][1] = value - end - else - index = index(*args) - if index.nil? # appending a field - self << [args.first, value] - else # normal header assignment - @row[index][1] = value - end - end - end - - # - # :call-seq: - # row << [header, value] -> self - # row << hash -> self - # row << value -> self - # - # Adds a field to +self+; returns +self+: - # - # If the argument is a 2-element \Array [header, value], - # a field is added with the given +header+ and +value+: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row << ['NAME', 'Bat'] - # row # => # - # - # If the argument is a \Hash, each key-value pair is added - # as a field with header +key+ and value +value+. - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row << {NAME: 'Bat', name: 'Bam'} - # row # => # - # - # Otherwise, the given +value+ is added as a field with no header. - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row << 'Bag' - # row # => # - def <<(arg) - if arg.is_a?(Array) and arg.size == 2 # appending a header and name - @row << arg - elsif arg.is_a?(Hash) # append header and name pairs - arg.each { |pair| @row << pair } - else # append field value - @row << [nil, arg] - end - - self # for chaining - end - - # :call-seq: - # row.push(*values) -> self - # - # Appends each of the given +values+ to +self+ as a field; returns +self+: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.push('Bat', 'Bam') - # row # => # - def push(*args) - args.each { |arg| self << arg } - - self # for chaining - end - - # - # :call-seq: - # delete(index) -> [header, value] or nil - # delete(header) -> [header, value] or empty_array - # delete(header, offset) -> [header, value] or empty_array - # - # Removes a specified field from +self+; returns the 2-element \Array - # [header, value] if the field exists. - # - # If an \Integer argument +index+ is given, - # removes and returns the field at offset +index+, - # or returns +nil+ if the field does not exist: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.delete(1) # => ["Name", "Bar"] - # row.delete(50) # => nil - # - # Otherwise, if the single argument +header+ is given, - # removes and returns the first-found field with the given header, - # of returns a new empty \Array if the field does not exist: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.delete('Name') # => ["Name", "Foo"] - # row.delete('NAME') # => [] - # - # If argument +header+ and \Integer argument +offset+ are given, - # removes and returns the first-found field with the given header - # whose +index+ is at least as large as +offset+: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.delete('Name', 1) # => ["Name", "Bar"] - # row.delete('NAME', 1) # => [] - def delete(header_or_index, minimum_index = 0) - if header_or_index.is_a? Integer # by index - @row.delete_at(header_or_index) - elsif i = index(header_or_index, minimum_index) # by header - @row.delete_at(i) - else - [ ] - end - end - - # :call-seq: - # row.delete_if {|header, value| ... } -> self - # - # Removes fields from +self+ as selected by the block; returns +self+. - # - # Removes each field for which the block returns a truthy value: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.delete_if {|header, value| value.start_with?('B') } # => true - # row # => # - # row.delete_if {|header, value| header.start_with?('B') } # => false - # - # If no block is given, returns a new Enumerator: - # row.delete_if # => #:delete_if> - def delete_if(&block) - return enum_for(__method__) { size } unless block_given? - - @row.delete_if(&block) - - self # for chaining - end - - # :call-seq: - # self.fields(*specifiers) -> array_of_fields - # - # Returns field values per the given +specifiers+, which may be any mixture of: - # - \Integer index. - # - \Range of \Integer indexes. - # - 2-element \Array containing a header and offset. - # - Header. - # - \Range of headers. - # - # For +specifier+ in one of the first four cases above, - # returns the result of self.field(specifier); see #field. - # - # Although there may be any number of +specifiers+, - # the examples here will illustrate one at a time. - # - # When the specifier is an \Integer +index+, - # returns self.field(index)L - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.fields(1) # => ["Bar"] - # - # When the specifier is a \Range of \Integers +range+, - # returns self.field(range): - # row.fields(1..2) # => ["Bar", "Baz"] - # - # When the specifier is a 2-element \Array +array+, - # returns self.field(array)L - # row.fields('Name', 1) # => ["Foo", "Bar"] - # - # When the specifier is a header +header+, - # returns self.field(header)L - # row.fields('Name') # => ["Foo"] - # - # When the specifier is a \Range of headers +range+, - # forms a new \Range +new_range+ from the indexes of - # range.start and range.end, - # and returns self.field(new_range): - # source = "Name,NAME,name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.fields('Name'..'NAME') # => ["Foo", "Bar"] - # - # Returns all fields if no argument given: - # row.fields # => ["Foo", "Bar", "Baz"] - def fields(*headers_and_or_indices) - if headers_and_or_indices.empty? # return all fields--no arguments - @row.map(&:last) - else # or work like values_at() - all = [] - headers_and_or_indices.each do |h_or_i| - if h_or_i.is_a? Range - index_begin = h_or_i.begin.is_a?(Integer) ? h_or_i.begin : - index(h_or_i.begin) - index_end = h_or_i.end.is_a?(Integer) ? h_or_i.end : - index(h_or_i.end) - new_range = h_or_i.exclude_end? ? (index_begin...index_end) : - (index_begin..index_end) - all.concat(fields.values_at(new_range)) - else - all << field(*Array(h_or_i)) - end - end - return all - end - end - alias_method :values_at, :fields - - # :call-seq: - # index(header) -> index - # index(header, offset) -> index - # - # Returns the index for the given header, if it exists; - # otherwise returns +nil+. - # - # With the single argument +header+, returns the index - # of the first-found field with the given +header+: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.index('Name') # => 0 - # row.index('NAME') # => nil - # - # With arguments +header+ and +offset+, - # returns the index of the first-found field with given +header+, - # but ignoring the first +offset+ fields: - # row.index('Name', 1) # => 1 - # row.index('Name', 3) # => nil - def index(header, minimum_index = 0) - # find the pair - index = headers[minimum_index..-1].index(header) - # return the index at the right offset, if we found one - index.nil? ? nil : index + minimum_index - end - - # :call-seq: - # row.field?(value) -> true or false - # - # Returns +true+ if +value+ is a field in this row, +false+ otherwise: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.field?('Bar') # => true - # row.field?('BAR') # => false - def field?(data) - fields.include? data - end - - include Enumerable - - # :call-seq: - # row.each {|header, value| ... } -> self - # - # Calls the block with each header-value pair; returns +self+: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.each {|header, value| p [header, value] } - # Output: - # ["Name", "Foo"] - # ["Name", "Bar"] - # ["Name", "Baz"] - # - # If no block is given, returns a new Enumerator: - # row.each # => #:each> - def each(&block) - return enum_for(__method__) { size } unless block_given? - - @row.each(&block) - - self # for chaining - end - - alias_method :each_pair, :each - - # :call-seq: - # row == other -> true or false - # - # Returns +true+ if +other+ is a /CSV::Row that has the same - # fields (headers and values) in the same order as +self+; - # otherwise returns +false+: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # other_row = table[0] - # row == other_row # => true - # other_row = table[1] - # row == other_row # => false - def ==(other) - return @row == other.row if other.is_a? CSV::Row - @row == other - end - - # :call-seq: - # row.to_h -> hash - # - # Returns the new \Hash formed by adding each header-value pair in +self+ - # as a key-value pair in the \Hash. - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.to_h # => {"Name"=>"foo", "Value"=>"0"} - # - # Header order is preserved, but repeated headers are ignored: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.to_h # => {"Name"=>"Foo"} - def to_h - hash = {} - each do |key, _value| - hash[key] = self[key] unless hash.key?(key) - end - hash - end - alias_method :to_hash, :to_h - - # :call-seq: - # row.deconstruct_keys(keys) -> hash - # - # Returns the new \Hash suitable for pattern matching containing only the - # keys specified as an argument. - def deconstruct_keys(keys) - if keys.nil? - to_h - else - keys.to_h { |key| [key, self[key]] } - end - end - - alias_method :to_ary, :to_a - - # :call-seq: - # row.deconstruct -> array - # - # Returns the new \Array suitable for pattern matching containing the values - # of the row. - def deconstruct - fields - end - - # :call-seq: - # row.to_csv -> csv_string - # - # Returns the row as a \CSV String. Headers are not included: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.to_csv # => "foo,0\n" - def to_csv(**options) - fields.to_csv(**options) - end - alias_method :to_s, :to_csv - - # :call-seq: - # row.dig(index_or_header, *identifiers) -> object - # - # Finds and returns the object in nested object that is specified - # by +index_or_header+ and +specifiers+. - # - # The nested objects may be instances of various classes. - # See {Dig Methods}[rdoc-ref:dig_methods.rdoc]. - # - # Examples: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.dig(1) # => "0" - # row.dig('Value') # => "0" - # row.dig(5) # => nil - def dig(index_or_header, *indexes) - value = field(index_or_header) - if value.nil? - nil - elsif indexes.empty? - value - else - unless value.respond_to?(:dig) - raise TypeError, "#{value.class} does not have \#dig method" - end - value.dig(*indexes) - end - end - - # :call-seq: - # row.inspect -> string - # - # Returns an ASCII-compatible \String showing: - # - Class \CSV::Row. - # - Header-value pairs. - # Example: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.inspect # => "#" - def inspect - str = ["#<", self.class.to_s] - each do |header, field| - str << " " << (header.is_a?(Symbol) ? header.to_s : header.inspect) << - ":" << field.inspect - end - str << ">" - begin - str.join('') - rescue # any encoding error - str.map do |s| - e = Encoding::Converter.asciicompat_encoding(s.encoding) - e ? s.encode(e) : s.force_encoding("ASCII-8BIT") - end.join('') - end - end - end -end diff --git a/lib/csv/table.rb b/lib/csv/table.rb deleted file mode 100644 index fb19f5453f4435..00000000000000 --- a/lib/csv/table.rb +++ /dev/null @@ -1,1055 +0,0 @@ -# frozen_string_literal: true - -require "forwardable" - -class CSV - # = \CSV::Table - # A \CSV::Table instance represents \CSV data. - # (see {class CSV}[../CSV.html]). - # - # The instance may have: - # - Rows: each is a Table::Row object. - # - Headers: names for the columns. - # - # === Instance Methods - # - # \CSV::Table has three groups of instance methods: - # - Its own internally defined instance methods. - # - Methods included by module Enumerable. - # - Methods delegated to class Array.: - # * Array#empty? - # * Array#length - # * Array#size - # - # == Creating a \CSV::Table Instance - # - # Commonly, a new \CSV::Table instance is created by parsing \CSV source - # using headers: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.class # => CSV::Table - # - # You can also create an instance directly. See ::new. - # - # == Headers - # - # If a table has headers, the headers serve as labels for the columns of data. - # Each header serves as the label for its column. - # - # The headers for a \CSV::Table object are stored as an \Array of Strings. - # - # Commonly, headers are defined in the first row of \CSV source: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.headers # => ["Name", "Value"] - # - # If no headers are defined, the \Array is empty: - # table = CSV::Table.new([]) - # table.headers # => [] - # - # == Access Modes - # - # \CSV::Table provides three modes for accessing table data: - # - \Row mode. - # - Column mode. - # - Mixed mode (the default for a new table). - # - # The access mode for a\CSV::Table instance affects the behavior - # of some of its instance methods: - # - #[] - # - #[]= - # - #delete - # - #delete_if - # - #each - # - #values_at - # - # === \Row Mode - # - # Set a table to row mode with method #by_row!: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.by_row! # => # - # - # Specify a single row by an \Integer index: - # # Get a row. - # table[1] # => # - # # Set a row, then get it. - # table[1] = CSV::Row.new(['Name', 'Value'], ['bam', 3]) - # table[1] # => # - # - # Specify a sequence of rows by a \Range: - # # Get rows. - # table[1..2] # => [#, #] - # # Set rows, then get them. - # table[1..2] = [ - # CSV::Row.new(['Name', 'Value'], ['bat', 4]), - # CSV::Row.new(['Name', 'Value'], ['bad', 5]), - # ] - # table[1..2] # => [["Name", #], ["Value", #]] - # - # === Column Mode - # - # Set a table to column mode with method #by_col!: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.by_col! # => # - # - # Specify a column by an \Integer index: - # # Get a column. - # table[0] - # # Set a column, then get it. - # table[0] = ['FOO', 'BAR', 'BAZ'] - # table[0] # => ["FOO", "BAR", "BAZ"] - # - # Specify a column by its \String header: - # # Get a column. - # table['Name'] # => ["FOO", "BAR", "BAZ"] - # # Set a column, then get it. - # table['Name'] = ['Foo', 'Bar', 'Baz'] - # table['Name'] # => ["Foo", "Bar", "Baz"] - # - # === Mixed Mode - # - # In mixed mode, you can refer to either rows or columns: - # - An \Integer index refers to a row. - # - A \Range index refers to multiple rows. - # - A \String index refers to a column. - # - # Set a table to mixed mode with method #by_col_or_row!: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.by_col_or_row! # => # - # - # Specify a single row by an \Integer index: - # # Get a row. - # table[1] # => # - # # Set a row, then get it. - # table[1] = CSV::Row.new(['Name', 'Value'], ['bam', 3]) - # table[1] # => # - # - # Specify a sequence of rows by a \Range: - # # Get rows. - # table[1..2] # => [#, #] - # # Set rows, then get them. - # table[1] = CSV::Row.new(['Name', 'Value'], ['bat', 4]) - # table[2] = CSV::Row.new(['Name', 'Value'], ['bad', 5]) - # table[1..2] # => [["Name", #], ["Value", #]] - # - # Specify a column by its \String header: - # # Get a column. - # table['Name'] # => ["foo", "bat", "bad"] - # # Set a column, then get it. - # table['Name'] = ['Foo', 'Bar', 'Baz'] - # table['Name'] # => ["Foo", "Bar", "Baz"] - class Table - # :call-seq: - # CSV::Table.new(array_of_rows, headers = nil) -> csv_table - # - # Returns a new \CSV::Table object. - # - # - Argument +array_of_rows+ must be an \Array of CSV::Row objects. - # - Argument +headers+, if given, may be an \Array of Strings. - # - # --- - # - # Create an empty \CSV::Table object: - # table = CSV::Table.new([]) - # table # => # - # - # Create a non-empty \CSV::Table object: - # rows = [ - # CSV::Row.new([], []), - # CSV::Row.new([], []), - # CSV::Row.new([], []), - # ] - # table = CSV::Table.new(rows) - # table # => # - # - # --- - # - # If argument +headers+ is an \Array of Strings, - # those Strings become the table's headers: - # table = CSV::Table.new([], headers: ['Name', 'Age']) - # table.headers # => ["Name", "Age"] - # - # If argument +headers+ is not given and the table has rows, - # the headers are taken from the first row: - # rows = [ - # CSV::Row.new(['Foo', 'Bar'], []), - # CSV::Row.new(['foo', 'bar'], []), - # CSV::Row.new(['FOO', 'BAR'], []), - # ] - # table = CSV::Table.new(rows) - # table.headers # => ["Foo", "Bar"] - # - # If argument +headers+ is not given and the table is empty (has no rows), - # the headers are also empty: - # table = CSV::Table.new([]) - # table.headers # => [] - # - # --- - # - # Raises an exception if argument +array_of_rows+ is not an \Array object: - # # Raises NoMethodError (undefined method `first' for :foo:Symbol): - # CSV::Table.new(:foo) - # - # Raises an exception if an element of +array_of_rows+ is not a \CSV::Table object: - # # Raises NoMethodError (undefined method `headers' for :foo:Symbol): - # CSV::Table.new([:foo]) - def initialize(array_of_rows, headers: nil) - @table = array_of_rows - @headers = headers - unless @headers - if @table.empty? - @headers = [] - else - @headers = @table.first.headers - end - end - - @mode = :col_or_row - end - - # The current access mode for indexing and iteration. - attr_reader :mode - - # Internal data format used to compare equality. - attr_reader :table - protected :table - - ### Array Delegation ### - - extend Forwardable - def_delegators :@table, :empty?, :length, :size - - # :call-seq: - # table.by_col -> table_dup - # - # Returns a duplicate of +self+, in column mode - # (see {Column Mode}[#class-CSV::Table-label-Column+Mode]): - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.mode # => :col_or_row - # dup_table = table.by_col - # dup_table.mode # => :col - # dup_table.equal?(table) # => false # It's a dup - # - # This may be used to chain method calls without changing the mode - # (but also will affect performance and memory usage): - # dup_table.by_col['Name'] - # - # Also note that changes to the duplicate table will not affect the original. - def by_col - self.class.new(@table.dup).by_col! - end - - # :call-seq: - # table.by_col! -> self - # - # Sets the mode for +self+ to column mode - # (see {Column Mode}[#class-CSV::Table-label-Column+Mode]); returns +self+: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.mode # => :col_or_row - # table1 = table.by_col! - # table.mode # => :col - # table1.equal?(table) # => true # Returned self - def by_col! - @mode = :col - - self - end - - # :call-seq: - # table.by_col_or_row -> table_dup - # - # Returns a duplicate of +self+, in mixed mode - # (see {Mixed Mode}[#class-CSV::Table-label-Mixed+Mode]): - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true).by_col! - # table.mode # => :col - # dup_table = table.by_col_or_row - # dup_table.mode # => :col_or_row - # dup_table.equal?(table) # => false # It's a dup - # - # This may be used to chain method calls without changing the mode - # (but also will affect performance and memory usage): - # dup_table.by_col_or_row['Name'] - # - # Also note that changes to the duplicate table will not affect the original. - def by_col_or_row - self.class.new(@table.dup).by_col_or_row! - end - - # :call-seq: - # table.by_col_or_row! -> self - # - # Sets the mode for +self+ to mixed mode - # (see {Mixed Mode}[#class-CSV::Table-label-Mixed+Mode]); returns +self+: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true).by_col! - # table.mode # => :col - # table1 = table.by_col_or_row! - # table.mode # => :col_or_row - # table1.equal?(table) # => true # Returned self - def by_col_or_row! - @mode = :col_or_row - - self - end - - # :call-seq: - # table.by_row -> table_dup - # - # Returns a duplicate of +self+, in row mode - # (see {Row Mode}[#class-CSV::Table-label-Row+Mode]): - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.mode # => :col_or_row - # dup_table = table.by_row - # dup_table.mode # => :row - # dup_table.equal?(table) # => false # It's a dup - # - # This may be used to chain method calls without changing the mode - # (but also will affect performance and memory usage): - # dup_table.by_row[1] - # - # Also note that changes to the duplicate table will not affect the original. - def by_row - self.class.new(@table.dup).by_row! - end - - # :call-seq: - # table.by_row! -> self - # - # Sets the mode for +self+ to row mode - # (see {Row Mode}[#class-CSV::Table-label-Row+Mode]); returns +self+: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.mode # => :col_or_row - # table1 = table.by_row! - # table.mode # => :row - # table1.equal?(table) # => true # Returned self - def by_row! - @mode = :row - - self - end - - # :call-seq: - # table.headers -> array_of_headers - # - # Returns a new \Array containing the \String headers for the table. - # - # If the table is not empty, returns the headers from the first row: - # rows = [ - # CSV::Row.new(['Foo', 'Bar'], []), - # CSV::Row.new(['FOO', 'BAR'], []), - # CSV::Row.new(['foo', 'bar'], []), - # ] - # table = CSV::Table.new(rows) - # table.headers # => ["Foo", "Bar"] - # table.delete(0) - # table.headers # => ["FOO", "BAR"] - # table.delete(0) - # table.headers # => ["foo", "bar"] - # - # If the table is empty, returns a copy of the headers in the table itself: - # table.delete(0) - # table.headers # => ["Foo", "Bar"] - def headers - if @table.empty? - @headers.dup - else - @table.first.headers - end - end - - # :call-seq: - # table[n] -> row or column_data - # table[range] -> array_of_rows or array_of_column_data - # table[header] -> array_of_column_data - # - # Returns data from the table; does not modify the table. - # - # --- - # - # Fetch a \Row by Its \Integer Index:: - # - Form: table[n], +n+ an integer. - # - Access mode: :row or :col_or_row. - # - Return value: _nth_ row of the table, if that row exists; - # otherwise +nil+. - # - # Returns the _nth_ row of the table if that row exists: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.by_row! # => # - # table[1] # => # - # table.by_col_or_row! # => # - # table[1] # => # - # - # Counts backward from the last row if +n+ is negative: - # table[-1] # => # - # - # Returns +nil+ if +n+ is too large or too small: - # table[4] # => nil - # table[-4] # => nil - # - # Raises an exception if the access mode is :row - # and +n+ is not an \Integer: - # table.by_row! # => # - # # Raises TypeError (no implicit conversion of String into Integer): - # table['Name'] - # - # --- - # - # Fetch a Column by Its \Integer Index:: - # - Form: table[n], +n+ an \Integer. - # - Access mode: :col. - # - Return value: _nth_ column of the table, if that column exists; - # otherwise an \Array of +nil+ fields of length self.size. - # - # Returns the _nth_ column of the table if that column exists: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.by_col! # => # - # table[1] # => ["0", "1", "2"] - # - # Counts backward from the last column if +n+ is negative: - # table[-2] # => ["foo", "bar", "baz"] - # - # Returns an \Array of +nil+ fields if +n+ is too large or too small: - # table[4] # => [nil, nil, nil] - # table[-4] # => [nil, nil, nil] - # - # --- - # - # Fetch Rows by \Range:: - # - Form: table[range], +range+ a \Range object. - # - Access mode: :row or :col_or_row. - # - Return value: rows from the table, beginning at row range.start, - # if those rows exists. - # - # Returns rows from the table, beginning at row range.first, - # if those rows exist: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.by_row! # => # - # rows = table[1..2] # => # - # rows # => [#, #] - # table.by_col_or_row! # => # - # rows = table[1..2] # => # - # rows # => [#, #] - # - # If there are too few rows, returns all from range.start to the end: - # rows = table[1..50] # => # - # rows # => [#, #] - # - # Special case: if range.start == table.size, returns an empty \Array: - # table[table.size..50] # => [] - # - # If range.end is negative, calculates the ending index from the end: - # rows = table[0..-1] - # rows # => [#, #, #] - # - # If range.start is negative, calculates the starting index from the end: - # rows = table[-1..2] - # rows # => [#] - # - # If range.start is larger than table.size, returns +nil+: - # table[4..4] # => nil - # - # --- - # - # Fetch Columns by \Range:: - # - Form: table[range], +range+ a \Range object. - # - Access mode: :col. - # - Return value: column data from the table, beginning at column range.start, - # if those columns exist. - # - # Returns column values from the table, if the column exists; - # the values are arranged by row: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.by_col! - # table[0..1] # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] - # - # Special case: if range.start == headers.size, - # returns an \Array (size: table.size) of empty \Arrays: - # table[table.headers.size..50] # => [[], [], []] - # - # If range.end is negative, calculates the ending index from the end: - # table[0..-1] # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] - # - # If range.start is negative, calculates the starting index from the end: - # table[-2..2] # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] - # - # If range.start is larger than table.size, - # returns an \Array of +nil+ values: - # table[4..4] # => [nil, nil, nil] - # - # --- - # - # Fetch a Column by Its \String Header:: - # - Form: table[header], +header+ a \String header. - # - Access mode: :col or :col_or_row - # - Return value: column data from the table, if that +header+ exists. - # - # Returns column values from the table, if the column exists: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.by_col! # => # - # table['Name'] # => ["foo", "bar", "baz"] - # table.by_col_or_row! # => # - # col = table['Name'] - # col # => ["foo", "bar", "baz"] - # - # Modifying the returned column values does not modify the table: - # col[0] = 'bat' - # col # => ["bat", "bar", "baz"] - # table['Name'] # => ["foo", "bar", "baz"] - # - # Returns an \Array of +nil+ values if there is no such column: - # table['Nosuch'] # => [nil, nil, nil] - def [](index_or_header) - if @mode == :row or # by index - (@mode == :col_or_row and (index_or_header.is_a?(Integer) or index_or_header.is_a?(Range))) - @table[index_or_header] - else # by header - @table.map { |row| row[index_or_header] } - end - end - - # :call-seq: - # table[n] = row -> row - # table[n] = field_or_array_of_fields -> field_or_array_of_fields - # table[header] = field_or_array_of_fields -> field_or_array_of_fields - # - # Puts data onto the table. - # - # --- - # - # Set a \Row by Its \Integer Index:: - # - Form: table[n] = row, +n+ an \Integer, - # +row+ a \CSV::Row instance or an \Array of fields. - # - Access mode: :row or :col_or_row. - # - Return value: +row+. - # - # If the row exists, it is replaced: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # new_row = CSV::Row.new(['Name', 'Value'], ['bat', 3]) - # table.by_row! # => # - # return_value = table[0] = new_row - # return_value.equal?(new_row) # => true # Returned the row - # table[0].to_h # => {"Name"=>"bat", "Value"=>3} - # - # With access mode :col_or_row: - # table.by_col_or_row! # => # - # table[0] = CSV::Row.new(['Name', 'Value'], ['bam', 4]) - # table[0].to_h # => {"Name"=>"bam", "Value"=>4} - # - # With an \Array instead of a \CSV::Row, inherits headers from the table: - # array = ['bad', 5] - # return_value = table[0] = array - # return_value.equal?(array) # => true # Returned the array - # table[0].to_h # => {"Name"=>"bad", "Value"=>5} - # - # If the row does not exist, extends the table by adding rows: - # assigns rows with +nil+ as needed: - # table.size # => 3 - # table[5] = ['bag', 6] - # table.size # => 6 - # table[3] # => nil - # table[4]# => nil - # table[5].to_h # => {"Name"=>"bag", "Value"=>6} - # - # Note that the +nil+ rows are actually +nil+, not a row of +nil+ fields. - # - # --- - # - # Set a Column by Its \Integer Index:: - # - Form: table[n] = array_of_fields, +n+ an \Integer, - # +array_of_fields+ an \Array of \String fields. - # - Access mode: :col. - # - Return value: +array_of_fields+. - # - # If the column exists, it is replaced: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # new_col = [3, 4, 5] - # table.by_col! # => # - # return_value = table[1] = new_col - # return_value.equal?(new_col) # => true # Returned the column - # table[1] # => [3, 4, 5] - # # The rows, as revised: - # table.by_row! # => # - # table[0].to_h # => {"Name"=>"foo", "Value"=>3} - # table[1].to_h # => {"Name"=>"bar", "Value"=>4} - # table[2].to_h # => {"Name"=>"baz", "Value"=>5} - # table.by_col! # => # - # - # If there are too few values, fills with +nil+ values: - # table[1] = [0] - # table[1] # => [0, nil, nil] - # - # If there are too many values, ignores the extra values: - # table[1] = [0, 1, 2, 3, 4] - # table[1] # => [0, 1, 2] - # - # If a single value is given, replaces all fields in the column with that value: - # table[1] = 'bat' - # table[1] # => ["bat", "bat", "bat"] - # - # --- - # - # Set a Column by Its \String Header:: - # - Form: table[header] = field_or_array_of_fields, - # +header+ a \String header, +field_or_array_of_fields+ a field value - # or an \Array of \String fields. - # - Access mode: :col or :col_or_row. - # - Return value: +field_or_array_of_fields+. - # - # If the column exists, it is replaced: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # new_col = [3, 4, 5] - # table.by_col! # => # - # return_value = table['Value'] = new_col - # return_value.equal?(new_col) # => true # Returned the column - # table['Value'] # => [3, 4, 5] - # # The rows, as revised: - # table.by_row! # => # - # table[0].to_h # => {"Name"=>"foo", "Value"=>3} - # table[1].to_h # => {"Name"=>"bar", "Value"=>4} - # table[2].to_h # => {"Name"=>"baz", "Value"=>5} - # table.by_col! # => # - # - # If there are too few values, fills with +nil+ values: - # table['Value'] = [0] - # table['Value'] # => [0, nil, nil] - # - # If there are too many values, ignores the extra values: - # table['Value'] = [0, 1, 2, 3, 4] - # table['Value'] # => [0, 1, 2] - # - # If the column does not exist, extends the table by adding columns: - # table['Note'] = ['x', 'y', 'z'] - # table['Note'] # => ["x", "y", "z"] - # # The rows, as revised: - # table.by_row! - # table[0].to_h # => {"Name"=>"foo", "Value"=>0, "Note"=>"x"} - # table[1].to_h # => {"Name"=>"bar", "Value"=>1, "Note"=>"y"} - # table[2].to_h # => {"Name"=>"baz", "Value"=>2, "Note"=>"z"} - # table.by_col! - # - # If a single value is given, replaces all fields in the column with that value: - # table['Value'] = 'bat' - # table['Value'] # => ["bat", "bat", "bat"] - def []=(index_or_header, value) - if @mode == :row or # by index - (@mode == :col_or_row and index_or_header.is_a? Integer) - if value.is_a? Array - @table[index_or_header] = Row.new(headers, value) - else - @table[index_or_header] = value - end - else # set column - unless index_or_header.is_a? Integer - index = @headers.index(index_or_header) || @headers.size - @headers[index] = index_or_header - end - if value.is_a? Array # multiple values - @table.each_with_index do |row, i| - if row.header_row? - row[index_or_header] = index_or_header - else - row[index_or_header] = value[i] - end - end - else # repeated value - @table.each do |row| - if row.header_row? - row[index_or_header] = index_or_header - else - row[index_or_header] = value - end - end - end - end - end - - # :call-seq: - # table.values_at(*indexes) -> array_of_rows - # table.values_at(*headers) -> array_of_columns_data - # - # If the access mode is :row or :col_or_row, - # and each argument is either an \Integer or a \Range, - # returns rows. - # Otherwise, returns columns data. - # - # In either case, the returned values are in the order - # specified by the arguments. Arguments may be repeated. - # - # --- - # - # Returns rows as an \Array of \CSV::Row objects. - # - # No argument: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.values_at # => [] - # - # One index: - # values = table.values_at(0) - # values # => [#] - # - # Two indexes: - # values = table.values_at(2, 0) - # values # => [#, #] - # - # One \Range: - # values = table.values_at(1..2) - # values # => [#, #] - # - # \Ranges and indexes: - # values = table.values_at(0..1, 1..2, 0, 2) - # pp values - # Output: - # [#, - # #, - # #, - # #, - # #, - # #] - # - # --- - # - # Returns columns data as row Arrays, - # each consisting of the specified columns data for that row: - # values = table.values_at('Name') - # values # => [["foo"], ["bar"], ["baz"]] - # values = table.values_at('Value', 'Name') - # values # => [["0", "foo"], ["1", "bar"], ["2", "baz"]] - def values_at(*indices_or_headers) - if @mode == :row or # by indices - ( @mode == :col_or_row and indices_or_headers.all? do |index| - index.is_a?(Integer) or - ( index.is_a?(Range) and - index.first.is_a?(Integer) and - index.last.is_a?(Integer) ) - end ) - @table.values_at(*indices_or_headers) - else # by headers - @table.map { |row| row.values_at(*indices_or_headers) } - end - end - - # :call-seq: - # table << row_or_array -> self - # - # If +row_or_array+ is a \CSV::Row object, - # it is appended to the table: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table << CSV::Row.new(table.headers, ['bat', 3]) - # table[3] # => # - # - # If +row_or_array+ is an \Array, it is used to create a new - # \CSV::Row object which is then appended to the table: - # table << ['bam', 4] - # table[4] # => # - def <<(row_or_array) - if row_or_array.is_a? Array # append Array - @table << Row.new(headers, row_or_array) - else # append Row - @table << row_or_array - end - - self # for chaining - end - - # - # :call-seq: - # table.push(*rows_or_arrays) -> self - # - # A shortcut for appending multiple rows. Equivalent to: - # rows.each {|row| self << row } - # - # Each argument may be either a \CSV::Row object or an \Array: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # rows = [ - # CSV::Row.new(table.headers, ['bat', 3]), - # ['bam', 4] - # ] - # table.push(*rows) - # table[3..4] # => [#, #] - def push(*rows) - rows.each { |row| self << row } - - self # for chaining - end - - # :call-seq: - # table.delete(*indexes) -> deleted_values - # table.delete(*headers) -> deleted_values - # - # If the access mode is :row or :col_or_row, - # and each argument is either an \Integer or a \Range, - # returns deleted rows. - # Otherwise, returns deleted columns data. - # - # In either case, the returned values are in the order - # specified by the arguments. Arguments may be repeated. - # - # --- - # - # Returns rows as an \Array of \CSV::Row objects. - # - # One index: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # deleted_values = table.delete(0) - # deleted_values # => [#] - # - # Two indexes: - # table = CSV.parse(source, headers: true) - # deleted_values = table.delete(2, 0) - # deleted_values # => [#, #] - # - # --- - # - # Returns columns data as column Arrays. - # - # One header: - # table = CSV.parse(source, headers: true) - # deleted_values = table.delete('Name') - # deleted_values # => ["foo", "bar", "baz"] - # - # Two headers: - # table = CSV.parse(source, headers: true) - # deleted_values = table.delete('Value', 'Name') - # deleted_values # => [["0", "1", "2"], ["foo", "bar", "baz"]] - def delete(*indexes_or_headers) - if indexes_or_headers.empty? - raise ArgumentError, "wrong number of arguments (given 0, expected 1+)" - end - deleted_values = indexes_or_headers.map do |index_or_header| - if @mode == :row or # by index - (@mode == :col_or_row and index_or_header.is_a? Integer) - @table.delete_at(index_or_header) - else # by header - if index_or_header.is_a? Integer - @headers.delete_at(index_or_header) - else - @headers.delete(index_or_header) - end - @table.map { |row| row.delete(index_or_header).last } - end - end - if indexes_or_headers.size == 1 - deleted_values[0] - else - deleted_values - end - end - - # :call-seq: - # table.delete_if {|row_or_column| ... } -> self - # - # Removes rows or columns for which the block returns a truthy value; - # returns +self+. - # - # Removes rows when the access mode is :row or :col_or_row; - # calls the block with each \CSV::Row object: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.by_row! # => # - # table.size # => 3 - # table.delete_if {|row| row['Name'].start_with?('b') } - # table.size # => 1 - # - # Removes columns when the access mode is :col; - # calls the block with each column as a 2-element array - # containing the header and an \Array of column fields: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.by_col! # => # - # table.headers.size # => 2 - # table.delete_if {|column_data| column_data[1].include?('2') } - # table.headers.size # => 1 - # - # Returns a new \Enumerator if no block is given: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.delete_if # => #:delete_if> - def delete_if(&block) - return enum_for(__method__) { @mode == :row or @mode == :col_or_row ? size : headers.size } unless block_given? - - if @mode == :row or @mode == :col_or_row # by index - @table.delete_if(&block) - else # by header - headers.each do |header| - delete(header) if yield([header, self[header]]) - end - end - - self # for chaining - end - - include Enumerable - - # :call-seq: - # table.each {|row_or_column| ... ) -> self - # - # Calls the block with each row or column; returns +self+. - # - # When the access mode is :row or :col_or_row, - # calls the block with each \CSV::Row object: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.by_row! # => # - # table.each {|row| p row } - # Output: - # # - # # - # # - # - # When the access mode is :col, - # calls the block with each column as a 2-element array - # containing the header and an \Array of column fields: - # table.by_col! # => # - # table.each {|column_data| p column_data } - # Output: - # ["Name", ["foo", "bar", "baz"]] - # ["Value", ["0", "1", "2"]] - # - # Returns a new \Enumerator if no block is given: - # table.each # => #:each> - def each(&block) - return enum_for(__method__) { @mode == :col ? headers.size : size } unless block_given? - - if @mode == :col - headers.each.with_index do |header, i| - yield([header, @table.map {|row| row[header, i]}]) - end - else - @table.each(&block) - end - - self # for chaining - end - - # :call-seq: - # table == other_table -> true or false - # - # Returns +true+ if all each row of +self+ == - # the corresponding row of +other_table+, otherwise, +false+. - # - # The access mode does no affect the result. - # - # Equal tables: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # other_table = CSV.parse(source, headers: true) - # table == other_table # => true - # - # Different row count: - # other_table.delete(2) - # table == other_table # => false - # - # Different last row: - # other_table << ['bat', 3] - # table == other_table # => false - def ==(other) - return @table == other.table if other.is_a? CSV::Table - @table == other - end - - # :call-seq: - # table.to_a -> array_of_arrays - # - # Returns the table as an \Array of \Arrays; - # the headers are in the first row: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.to_a # => [["Name", "Value"], ["foo", "0"], ["bar", "1"], ["baz", "2"]] - def to_a - array = [headers] - @table.each do |row| - array.push(row.fields) unless row.header_row? - end - - array - end - - # :call-seq: - # table.to_csv(**options) -> csv_string - # - # Returns the table as \CSV string. - # See {Options for Generating}[../CSV.html#class-CSV-label-Options+for+Generating]. - # - # Defaults option +write_headers+ to +true+: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.to_csv # => "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # - # Omits the headers if option +write_headers+ is given as +false+ - # (see {Option +write_headers+}[../CSV.html#class-CSV-label-Option+write_headers]): - # table.to_csv(write_headers: false) # => "foo,0\nbar,1\nbaz,2\n" - # - # Limit rows if option +limit+ is given like +2+: - # table.to_csv(limit: 2) # => "Name,Value\nfoo,0\nbar,1\n" - def to_csv(write_headers: true, limit: nil, **options) - array = write_headers ? [headers.to_csv(**options)] : [] - limit ||= @table.size - limit = @table.size + 1 + limit if limit < 0 - limit = 0 if limit < 0 - @table.first(limit).each do |row| - array.push(row.fields.to_csv(**options)) unless row.header_row? - end - - array.join("") - end - alias_method :to_s, :to_csv - - # - # Extracts the nested value specified by the sequence of +index+ or +header+ objects by calling dig at each step, - # returning nil if any intermediate step is nil. - # - def dig(index_or_header, *index_or_headers) - value = self[index_or_header] - if value.nil? - nil - elsif index_or_headers.empty? - value - else - unless value.respond_to?(:dig) - raise TypeError, "#{value.class} does not have \#dig method" - end - value.dig(*index_or_headers) - end - end - - # :call-seq: - # table.inspect => string - # - # Returns a US-ASCII-encoded \String showing table: - # - Class: CSV::Table. - # - Access mode: :row, :col, or :col_or_row. - # - Size: Row count, including the header row. - # - # Example: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.inspect # => "#\nName,Value\nfoo,0\nbar,1\nbaz,2\n" - # - def inspect - inspected = +"#<#{self.class} mode:#{@mode} row_count:#{to_a.size}>" - summary = to_csv(limit: 5) - inspected << "\n" << summary if summary.encoding.ascii_compatible? - inspected - end - end -end diff --git a/lib/csv/version.rb b/lib/csv/version.rb deleted file mode 100644 index 100c684ac43103..00000000000000 --- a/lib/csv/version.rb +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true - -class CSV - # The version of the installed library. - VERSION = "3.2.9" -end diff --git a/lib/csv/writer.rb b/lib/csv/writer.rb deleted file mode 100644 index 030a295bc9adc0..00000000000000 --- a/lib/csv/writer.rb +++ /dev/null @@ -1,210 +0,0 @@ -# frozen_string_literal: true - -require_relative "input_record_separator" -require_relative "row" - -class CSV - # Note: Don't use this class directly. This is an internal class. - class Writer - # - # A CSV::Writer receives an output, prepares the header, format and output. - # It allows us to write new rows in the object and rewind it. - # - attr_reader :lineno - attr_reader :headers - - def initialize(output, options) - @output = output - @options = options - @lineno = 0 - @fields_converter = nil - prepare - if @options[:write_headers] and @headers - self << @headers - end - @fields_converter = @options[:fields_converter] - end - - # - # Adds a new row - # - def <<(row) - case row - when Row - row = row.fields - when Hash - row = @headers.collect {|header| row[header]} - end - - @headers ||= row if @use_headers - @lineno += 1 - - if @fields_converter - quoted_fields = [false] * row.size - row = @fields_converter.convert(row, nil, lineno, quoted_fields) - end - - i = -1 - converted_row = row.collect do |field| - i += 1 - quote(field, i) - end - line = converted_row.join(@column_separator) + @row_separator - if @output_encoding - line = line.encode(@output_encoding) - end - @output << line - - self - end - - # - # Winds back to the beginning - # - def rewind - @lineno = 0 - @headers = nil if @options[:headers].nil? - end - - private - def prepare - @encoding = @options[:encoding] - - prepare_header - prepare_format - prepare_output - end - - def prepare_header - headers = @options[:headers] - case headers - when Array - @headers = headers - @use_headers = true - when String - @headers = CSV.parse_line(headers, - col_sep: @options[:column_separator], - row_sep: @options[:row_separator], - quote_char: @options[:quote_character]) - @use_headers = true - when true - @headers = nil - @use_headers = true - else - @headers = nil - @use_headers = false - end - return unless @headers - - converter = @options[:header_fields_converter] - @headers = converter.convert(@headers, nil, 0, []) - @headers.each do |header| - header.freeze if header.is_a?(String) - end - end - - def prepare_force_quotes_fields(force_quotes) - @force_quotes_fields = {} - force_quotes.each do |name_or_index| - case name_or_index - when Integer - index = name_or_index - @force_quotes_fields[index] = true - when String, Symbol - name = name_or_index.to_s - if @headers.nil? - message = ":headers is required when you use field name " + - "in :force_quotes: " + - "#{name_or_index.inspect}: #{force_quotes.inspect}" - raise ArgumentError, message - end - index = @headers.index(name) - next if index.nil? - @force_quotes_fields[index] = true - else - message = ":force_quotes element must be " + - "field index or field name: " + - "#{name_or_index.inspect}: #{force_quotes.inspect}" - raise ArgumentError, message - end - end - end - - def prepare_format - @column_separator = @options[:column_separator].to_s.encode(@encoding) - row_separator = @options[:row_separator] - if row_separator == :auto - @row_separator = InputRecordSeparator.value.encode(@encoding) - else - @row_separator = row_separator.to_s.encode(@encoding) - end - @quote_character = @options[:quote_character] - force_quotes = @options[:force_quotes] - if force_quotes.is_a?(Array) - prepare_force_quotes_fields(force_quotes) - @force_quotes = false - elsif force_quotes - @force_quotes_fields = nil - @force_quotes = true - else - @force_quotes_fields = nil - @force_quotes = false - end - unless @force_quotes - @quotable_pattern = - Regexp.new("[\r\n".encode(@encoding) + - Regexp.escape(@column_separator) + - Regexp.escape(@quote_character.encode(@encoding)) + - "]".encode(@encoding)) - end - @quote_empty = @options.fetch(:quote_empty, true) - end - - def prepare_output - @output_encoding = nil - return unless @output.is_a?(StringIO) - - output_encoding = @output.internal_encoding || @output.external_encoding - if @encoding != output_encoding - if @options[:force_encoding] - @output_encoding = output_encoding - else - compatible_encoding = Encoding.compatible?(@encoding, output_encoding) - if compatible_encoding - @output.set_encoding(compatible_encoding) - @output.seek(0, IO::SEEK_END) - end - end - end - end - - def quote_field(field) - field = String(field) - encoded_quote_character = @quote_character.encode(field.encoding) - encoded_quote_character + - field.gsub(encoded_quote_character, - encoded_quote_character * 2) + - encoded_quote_character - end - - def quote(field, i) - if @force_quotes - quote_field(field) - elsif @force_quotes_fields and @force_quotes_fields[i] - quote_field(field) - else - if field.nil? # represent +nil+ fields as empty unquoted fields - "" - else - field = String(field) # Stringify fields - # represent empty fields as empty quoted fields - if (@quote_empty and field.empty?) or (field.valid_encoding? and @quotable_pattern.match?(field)) - quote_field(field) - else - field # unquoted field - end - end - end - end - end -end diff --git a/test/csv/helper.rb b/test/csv/helper.rb deleted file mode 100644 index ff3aa38b10290f..00000000000000 --- a/test/csv/helper.rb +++ /dev/null @@ -1,42 +0,0 @@ -require "tempfile" -require "test/unit" - -require "csv" - -require_relative "../lib/with_different_ofs" - -module CSVHelper - def with_chunk_size(chunk_size) - chunk_size_keep = ENV["CSV_PARSER_SCANNER_TEST_CHUNK_SIZE"] - begin - ENV["CSV_PARSER_SCANNER_TEST_CHUNK_SIZE"] = chunk_size - yield - ensure - ENV["CSV_PARSER_SCANNER_TEST_CHUNK_SIZE"] = chunk_size_keep - end - end - - def with_verbose(verbose) - original = $VERBOSE - begin - $VERBOSE = verbose - yield - ensure - $VERBOSE = original - end - end - - def with_default_internal(encoding) - original = Encoding.default_internal - begin - with_verbose(false) do - Encoding.default_internal = encoding - end - yield - ensure - with_verbose(false) do - Encoding.default_internal = original - end - end - end -end diff --git a/test/csv/interface/test_delegation.rb b/test/csv/interface/test_delegation.rb deleted file mode 100644 index 349257633bde05..00000000000000 --- a/test/csv/interface/test_delegation.rb +++ /dev/null @@ -1,47 +0,0 @@ -# frozen_string_literal: false - -require_relative "../helper" - -class TestCSVInterfaceDelegation < Test::Unit::TestCase - class TestStringIO < self - def setup - @csv = CSV.new("h1,h2") - end - - def test_flock - assert_raise(NotImplementedError) do - @csv.flock(File::LOCK_EX) - end - end - - def test_ioctl - assert_raise(NotImplementedError) do - @csv.ioctl(0) - end - end - - def test_stat - assert_raise(NotImplementedError) do - @csv.stat - end - end - - def test_to_i - assert_raise(NotImplementedError) do - @csv.to_i - end - end - - def test_binmode? - assert_equal(false, @csv.binmode?) - end - - def test_path - assert_equal(nil, @csv.path) - end - - def test_to_io - assert_instance_of(StringIO, @csv.to_io) - end - end -end diff --git a/test/csv/interface/test_read.rb b/test/csv/interface/test_read.rb deleted file mode 100644 index 9b35dc2e01c794..00000000000000 --- a/test/csv/interface/test_read.rb +++ /dev/null @@ -1,381 +0,0 @@ -# frozen_string_literal: false - -require_relative "../helper" - -class TestCSVInterfaceRead < Test::Unit::TestCase - extend DifferentOFS - - def setup - super - @data = "" - @data << "1\t2\t3\r\n" - @data << "4\t5\r\n" - @input = Tempfile.new(["interface-read", ".csv"], binmode: true) - @input << @data - @input.rewind - @rows = [ - ["1", "2", "3"], - ["4", "5"], - ] - end - - def teardown - @input.close(true) - super - end - - def test_foreach - rows = [] - CSV.foreach(@input.path, col_sep: "\t", row_sep: "\r\n") do |row| - rows << row - end - assert_equal(@rows, rows) - end - - if respond_to?(:ractor) - ractor - def test_foreach_in_ractor - ractor = Ractor.new(@input.path) do |path| - rows = [] - CSV.foreach(path, col_sep: "\t", row_sep: "\r\n") do |row| - rows << row - end - rows - end - rows = [ - ["1", "2", "3"], - ["4", "5"], - ] - assert_equal(rows, ractor.take) - end - end - - def test_foreach_mode - rows = [] - CSV.foreach(@input.path, "r", col_sep: "\t", row_sep: "\r\n") do |row| - rows << row - end - assert_equal(@rows, rows) - end - - def test_foreach_enumerator - rows = CSV.foreach(@input.path, col_sep: "\t", row_sep: "\r\n").to_a - assert_equal(@rows, rows) - end - - def test_closed? - csv = CSV.open(@input.path, "r+", col_sep: "\t", row_sep: "\r\n") - assert_not_predicate(csv, :closed?) - csv.close - assert_predicate(csv, :closed?) - end - - def test_open_auto_close - csv = nil - CSV.open(@input.path) do |_csv| - csv = _csv - end - assert_predicate(csv, :closed?) - end - - def test_open_closed - csv = nil - CSV.open(@input.path) do |_csv| - csv = _csv - csv.close - end - assert_predicate(csv, :closed?) - end - - def test_open_block_return_value - return_value = CSV.open(@input.path) do - "Return value." - end - assert_equal("Return value.", return_value) - end - - def test_open_encoding_valid - # U+1F600 GRINNING FACE - # U+1F601 GRINNING FACE WITH SMILING EYES - File.open(@input.path, "w") do |file| - file << "\u{1F600},\u{1F601}" - end - CSV.open(@input.path, encoding: "utf-8") do |csv| - assert_equal([["\u{1F600}", "\u{1F601}"]], - csv.to_a) - end - end - - def test_open_encoding_invalid - # U+1F600 GRINNING FACE - # U+1F601 GRINNING FACE WITH SMILING EYES - File.open(@input.path, "w") do |file| - file << "\u{1F600},\u{1F601}" - end - CSV.open(@input.path, encoding: "EUC-JP") do |csv| - error = assert_raise(CSV::InvalidEncodingError) do - csv.shift - end - assert_equal([Encoding::EUC_JP, "Invalid byte sequence in EUC-JP in line 1."], - [error.encoding, error.message]) - end - end - - def test_open_encoding_nonexistent - _output, error = capture_output do - CSV.open(@input.path, encoding: "nonexistent") do - end - end - assert_equal("path:0: warning: Unsupported encoding nonexistent ignored\n", - error.gsub(/\A.+:\d+: /, "path:0: ")) - end - - def test_open_encoding_utf_8_with_bom - # U+FEFF ZERO WIDTH NO-BREAK SPACE, BOM - # U+1F600 GRINNING FACE - # U+1F601 GRINNING FACE WITH SMILING EYES - File.open(@input.path, "w") do |file| - file << "\u{FEFF}\u{1F600},\u{1F601}" - end - CSV.open(@input.path, encoding: "bom|utf-8") do |csv| - assert_equal([["\u{1F600}", "\u{1F601}"]], - csv.to_a) - end - end - - def test_open_invalid_byte_sequence_in_utf_8 - CSV.open(@input.path, "w", encoding: Encoding::CP932) do |rows| - error = assert_raise(Encoding::InvalidByteSequenceError) do - rows << ["\x82\xa0"] - end - assert_equal('"\x82" on UTF-8', - error.message) - end - end - - def test_open_with_invalid_nil - CSV.open(@input.path, "w", encoding: Encoding::CP932, invalid: nil) do |rows| - error = assert_raise(Encoding::InvalidByteSequenceError) do - rows << ["\x82\xa0"] - end - assert_equal('"\x82" on UTF-8', - error.message) - end - end - - def test_open_with_invalid_replace - CSV.open(@input.path, "w", encoding: Encoding::CP932, invalid: :replace) do |rows| - rows << ["\x82\xa0".force_encoding(Encoding::UTF_8)] - end - CSV.open(@input.path, encoding: Encoding::CP932) do |csv| - assert_equal([["??"]], - csv.to_a) - end - end - - def test_open_with_invalid_replace_and_replace_string - CSV.open(@input.path, "w", encoding: Encoding::CP932, invalid: :replace, replace: "X") do |rows| - rows << ["\x82\xa0".force_encoding(Encoding::UTF_8)] - end - CSV.open(@input.path, encoding: Encoding::CP932) do |csv| - assert_equal([["XX"]], - csv.to_a) - end - end - - def test_open_with_undef_replace - # U+00B7 Middle Dot - CSV.open(@input.path, "w", encoding: Encoding::CP932, undef: :replace) do |rows| - rows << ["\u00B7"] - end - CSV.open(@input.path, encoding: Encoding::CP932) do |csv| - assert_equal([["?"]], - csv.to_a) - end - end - - def test_open_with_undef_replace_and_replace_string - # U+00B7 Middle Dot - CSV.open(@input.path, "w", encoding: Encoding::CP932, undef: :replace, replace: "X") do |rows| - rows << ["\u00B7"] - end - CSV.open(@input.path, encoding: Encoding::CP932) do |csv| - assert_equal([["X"]], - csv.to_a) - end - end - - def test_open_with_newline - CSV.open(@input.path, col_sep: "\t", universal_newline: true) do |csv| - assert_equal(@rows, csv.to_a) - end - File.binwrite(@input.path, "1,2,3\r\n" "4,5\n") - CSV.open(@input.path, newline: :universal) do |csv| - assert_equal(@rows, csv.to_a) - end - end - - def test_parse - assert_equal(@rows, - CSV.parse(@data, col_sep: "\t", row_sep: "\r\n")) - end - - def test_parse_block - rows = [] - CSV.parse(@data, col_sep: "\t", row_sep: "\r\n") do |row| - rows << row - end - assert_equal(@rows, rows) - end - - def test_parse_enumerator - rows = CSV.parse(@data, col_sep: "\t", row_sep: "\r\n").to_a - assert_equal(@rows, rows) - end - - def test_parse_headers_only - table = CSV.parse("a,b,c", headers: true) - assert_equal([ - ["a", "b", "c"], - [], - ], - [ - table.headers, - table.each.to_a, - ]) - end - - def test_parse_line - assert_equal(["1", "2", "3"], - CSV.parse_line("1;2;3", col_sep: ";")) - end - - def test_parse_line_shortcut - assert_equal(["1", "2", "3"], - "1;2;3".parse_csv(col_sep: ";")) - end - - def test_parse_line_empty - assert_equal(nil, CSV.parse_line("")) # to signal eof - end - - def test_parse_line_empty_line - assert_equal([], CSV.parse_line("\n1,2,3")) - end - - def test_read - assert_equal(@rows, - CSV.read(@input.path, col_sep: "\t", row_sep: "\r\n")) - end - - if respond_to?(:ractor) - ractor - def test_read_in_ractor - ractor = Ractor.new(@input.path) do |path| - CSV.read(path, col_sep: "\t", row_sep: "\r\n") - end - rows = [ - ["1", "2", "3"], - ["4", "5"], - ] - assert_equal(rows, ractor.take) - end - end - - def test_readlines - assert_equal(@rows, - CSV.readlines(@input.path, col_sep: "\t", row_sep: "\r\n")) - end - - def test_open_read - rows = CSV.open(@input.path, col_sep: "\t", row_sep: "\r\n") do |csv| - csv.read - end - assert_equal(@rows, rows) - end - - def test_open_readlines - rows = CSV.open(@input.path, col_sep: "\t", row_sep: "\r\n") do |csv| - csv.readlines - end - assert_equal(@rows, rows) - end - - def test_table - table = CSV.table(@input.path, col_sep: "\t", row_sep: "\r\n") - assert_equal(CSV::Table.new([ - CSV::Row.new([:"1", :"2", :"3"], [4, 5, nil]), - ]), - table) - end - - def test_shift # aliased as gets() and readline() - CSV.open(@input.path, "rb+", col_sep: "\t", row_sep: "\r\n") do |csv| - rows = [ - csv.shift, - csv.shift, - csv.shift, - ] - assert_equal(@rows + [nil], - rows) - end - end - - def test_enumerator - CSV.open(@input.path, col_sep: "\t", row_sep: "\r\n") do |csv| - assert_equal(@rows, csv.each.to_a) - end - end - - def test_shift_and_each - CSV.open(@input.path, col_sep: "\t", row_sep: "\r\n") do |csv| - rows = [] - rows << csv.shift - rows.concat(csv.each.to_a) - assert_equal(@rows, rows) - end - end - - def test_each_twice - CSV.open(@input.path, col_sep: "\t", row_sep: "\r\n") do |csv| - assert_equal([ - @rows, - [], - ], - [ - csv.each.to_a, - csv.each.to_a, - ]) - end - end - - def test_eof? - eofs = [] - CSV.open(@input.path, col_sep: "\t", row_sep: "\r\n") do |csv| - eofs << csv.eof? - csv.shift - eofs << csv.eof? - csv.shift - eofs << csv.eof? - end - assert_equal([false, false, true], - eofs) - end - - def test_new_nil - assert_raise_with_message ArgumentError, "Cannot parse nil as CSV" do - CSV.new(nil) - end - end - - def test_options_not_modified - options = {}.freeze - CSV.foreach(@input.path, **options) - CSV.open(@input.path, **options) {} - CSV.parse("", **options) - CSV.parse_line("", **options) - CSV.read(@input.path, **options) - CSV.readlines(@input.path, **options) - CSV.table(@input.path, **options) - end -end diff --git a/test/csv/interface/test_read_write.rb b/test/csv/interface/test_read_write.rb deleted file mode 100644 index c371e9c5fcf2aa..00000000000000 --- a/test/csv/interface/test_read_write.rb +++ /dev/null @@ -1,124 +0,0 @@ -# frozen_string_literal: false - -require_relative "../helper" - -class TestCSVInterfaceReadWrite < Test::Unit::TestCase - extend DifferentOFS - - def test_filter - input = <<-CSV.freeze -1;2;3 -4;5 - CSV - output = "" - CSV.filter(input, output, - in_col_sep: ";", - out_col_sep: ",", - converters: :all) do |row| - row.map! {|n| n * 2} - row << "Added\r" - end - assert_equal(<<-CSV, output) -2,4,6,"Added\r" -8,10,"Added\r" - CSV - end - - def test_filter_headers_true - input = <<-CSV.freeze -Name,Value -foo,0 -bar,1 -baz,2 - CSV - output = "" - CSV.filter(input, output, headers: true) do |row| - row[0] += "X" - row[1] = row[1].to_i + 1 - end - assert_equal(<<-CSV, output) -fooX,1 -barX,2 -bazX,3 - CSV - end - - def test_filter_headers_true_write_headers - input = <<-CSV.freeze -Name,Value -foo,0 -bar,1 -baz,2 - CSV - output = "" - CSV.filter(input, output, headers: true, out_write_headers: true) do |row| - if row.is_a?(Array) - row[0] += "X" - row[1] += "Y" - else - row[0] += "X" - row[1] = row[1].to_i + 1 - end - end - assert_equal(<<-CSV, output) -NameX,ValueY -fooX,1 -barX,2 -bazX,3 - CSV - end - - def test_filter_headers_array_write_headers - input = <<-CSV.freeze -foo,0 -bar,1 -baz,2 - CSV - output = "" - CSV.filter(input, output, - headers: ["Name", "Value"], - out_write_headers: true) do |row| - row[0] += "X" - row[1] = row[1].to_i + 1 - end - assert_equal(<<-CSV, output) -Name,Value -fooX,1 -barX,2 -bazX,3 - CSV - end - - def test_instance_same - data = "" - assert_equal(CSV.instance(data, col_sep: ";").object_id, - CSV.instance(data, col_sep: ";").object_id) - end - - def test_instance_append - output = "" - CSV.instance(output, col_sep: ";") << ["a", "b", "c"] - assert_equal(<<-CSV, output) -a;b;c - CSV - CSV.instance(output, col_sep: ";") << [1, 2, 3] - assert_equal(<<-CSV, output) -a;b;c -1;2;3 - CSV - end - - def test_instance_shortcut - assert_equal(CSV.instance, - CSV {|csv| csv}) - end - - def test_instance_shortcut_with_io - io = StringIO.new - from_instance = CSV.instance(io, col_sep: ";") { |csv| csv << ["a", "b", "c"] } - from_shortcut = CSV(io, col_sep: ";") { |csv| csv << ["e", "f", "g"] } - - assert_equal(from_instance, from_shortcut) - assert_equal(from_instance.string, "a;b;c\ne;f;g\n") - end -end diff --git a/test/csv/interface/test_write.rb b/test/csv/interface/test_write.rb deleted file mode 100644 index 0cd39a7663a151..00000000000000 --- a/test/csv/interface/test_write.rb +++ /dev/null @@ -1,217 +0,0 @@ -# frozen_string_literal: false - -require_relative "../helper" - -class TestCSVInterfaceWrite < Test::Unit::TestCase - extend DifferentOFS - - def setup - super - @output = Tempfile.new(["interface-write", ".csv"]) - end - - def teardown - @output.close(true) - super - end - - def test_generate_default - csv_text = CSV.generate do |csv| - csv << [1, 2, 3] << [4, nil, 5] - end - assert_equal(<<-CSV, csv_text) -1,2,3 -4,,5 - CSV - end - - if respond_to?(:ractor) - ractor - def test_generate_default_in_ractor - ractor = Ractor.new do - CSV.generate do |csv| - csv << [1, 2, 3] << [4, nil, 5] - end - end - assert_equal(<<-CSV, ractor.take) -1,2,3 -4,,5 - CSV - end - end - - def test_generate_append - csv_text = <<-CSV -1,2,3 -4,,5 - CSV - CSV.generate(csv_text) do |csv| - csv << ["last", %Q{"row"}] - end - assert_equal(<<-CSV, csv_text) -1,2,3 -4,,5 -last,"""row""" - CSV - end - - def test_generate_no_new_line - csv_text = CSV.generate("test") do |csv| - csv << ["row"] - end - assert_equal(<<-CSV, csv_text) -testrow - CSV - end - - def test_generate_line_col_sep - line = CSV.generate_line(["1", "2", "3"], col_sep: ";") - assert_equal(<<-LINE, line) -1;2;3 - LINE - end - - def test_generate_line_row_sep - line = CSV.generate_line(["1", "2"], row_sep: nil) - assert_equal(<<-LINE.chomp, line) -1,2 - LINE - end - - def test_generate_line_shortcut - line = ["1", "2", "3"].to_csv(col_sep: ";") - assert_equal(<<-LINE, line) -1;2;3 - LINE - end - - def test_generate_lines - lines = CSV.generate_lines([["foo", "bar"], [1, 2], [3, 4]]) - assert_equal(<<-LINES, lines) -foo,bar -1,2 -3,4 - LINES - end - - def test_headers_detection - headers = ["a", "b", "c"] - CSV.open(@output.path, "w", headers: true) do |csv| - csv << headers - csv << ["1", "2", "3"] - assert_equal(headers, csv.headers) - end - end - - def test_lineno - CSV.open(@output.path, "w") do |csv| - n_lines = 20 - n_lines.times do - csv << ["a", "b", "c"] - end - assert_equal(n_lines, csv.lineno) - end - end - - def test_append_row - CSV.open(@output.path, "wb") do |csv| - csv << - CSV::Row.new([], ["1", "2", "3"]) << - CSV::Row.new([], ["a", "b", "c"]) - end - assert_equal(<<-CSV, File.read(@output.path, mode: "rb")) -1,2,3 -a,b,c - CSV - end - - - if respond_to?(:ractor) - ractor - def test_append_row_in_ractor - ractor = Ractor.new(@output.path) do |path| - CSV.open(path, "wb") do |csv| - csv << - CSV::Row.new([], ["1", "2", "3"]) << - CSV::Row.new([], ["a", "b", "c"]) - end - end - ractor.take - assert_equal(<<-CSV, File.read(@output.path, mode: "rb")) -1,2,3 -a,b,c - CSV - end - end - - def test_append_hash - CSV.open(@output.path, "wb", headers: true) do |csv| - csv << [:a, :b, :c] - csv << {a: 1, b: 2, c: 3} - csv << {a: 4, b: 5, c: 6} - end - assert_equal(<<-CSV, File.read(@output.path, mode: "rb")) -a,b,c -1,2,3 -4,5,6 - CSV - end - - def test_append_hash_headers_array - CSV.open(@output.path, "wb", headers: [:b, :a, :c]) do |csv| - csv << {a: 1, b: 2, c: 3} - csv << {a: 4, b: 5, c: 6} - end - assert_equal(<<-CSV, File.read(@output.path, mode: "rb")) -2,1,3 -5,4,6 - CSV - end - - def test_append_hash_headers_string - CSV.open(@output.path, "wb", headers: "b|a|c", col_sep: "|") do |csv| - csv << {"a" => 1, "b" => 2, "c" => 3} - csv << {"a" => 4, "b" => 5, "c" => 6} - end - assert_equal(<<-CSV, File.read(@output.path, mode: "rb")) -2|1|3 -5|4|6 - CSV - end - - def test_write_headers - CSV.open(@output.path, - "wb", - headers: "b|a|c", - write_headers: true, - col_sep: "|" ) do |csv| - csv << {"a" => 1, "b" => 2, "c" => 3} - csv << {"a" => 4, "b" => 5, "c" => 6} - end - assert_equal(<<-CSV, File.read(@output.path, mode: "rb")) -b|a|c -2|1|3 -5|4|6 - CSV - end - - def test_write_headers_empty - CSV.open(@output.path, - "wb", - headers: "b|a|c", - write_headers: true, - col_sep: "|" ) do |csv| - end - assert_equal(<<-CSV, File.read(@output.path, mode: "rb")) -b|a|c - CSV - end - - def test_options_not_modified - options = {}.freeze - CSV.generate(**options) {} - CSV.generate_line([], **options) - CSV.filter("", "", **options) - CSV.instance("", **options) - end -end diff --git a/test/csv/line_endings.gz b/test/csv/line_endings.gz deleted file mode 100644 index 39e1729ee4ae6990da5fbd69793de027b6a94dfa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59 zcmV-B0L1?viwFoQdr?OK18iw-WnX1(WNB_^b1q|Zb^y!IOVueU&(|r*C`wJ`<=>A<=>B<=>C -1<=>2<=>3 - CSV - assert_equal([ - [nil, nil, "A", "B", "C"], - ["1", "2", "3"], - ], - CSV.parse(data, col_sep: "<=>")) - end -end diff --git a/test/csv/parse/test_convert.rb b/test/csv/parse/test_convert.rb deleted file mode 100644 index c9195c71d9be3c..00000000000000 --- a/test/csv/parse/test_convert.rb +++ /dev/null @@ -1,165 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false - -require_relative "../helper" - -class TestCSVParseConvert < Test::Unit::TestCase - extend DifferentOFS - - def setup - super - @data = "Numbers,:integer,1,:float,3.015" - @parser = CSV.new(@data) - - @custom = lambda {|field| /\A:(\S.*?)\s*\Z/ =~ field ? $1.to_sym : field} - - @time = Time.utc(2018, 12, 30, 6, 41, 29) - @windows_safe_time_data = @time.strftime("%a %b %d %H:%M:%S %Y") - - @preserving_converter = lambda do |field, info| - f = field.encode(CSV::ConverterEncoding) - return f if info.quoted? - begin - Integer(f, 10) - rescue - f - end - end - - @quoted_header_converter = lambda do |field, info| - f = field.encode(CSV::ConverterEncoding) - return f if info.quoted? - f.to_sym - end - end - - def test_integer - @parser.convert(:integer) - assert_equal(["Numbers", ":integer", 1, ":float", "3.015"], - @parser.shift) - end - - def test_float - @parser.convert(:float) - assert_equal(["Numbers", ":integer", 1.0, ":float", 3.015], - @parser.shift) - end - - def test_float_integer - @parser.convert(:float) - @parser.convert(:integer) - assert_equal(["Numbers", ":integer", 1.0, ":float", 3.015], - @parser.shift) - end - - def test_integer_float - @parser.convert(:integer) - @parser.convert(:float) - assert_equal(["Numbers", ":integer", 1, ":float", 3.015], - @parser.shift) - end - - def test_numeric - @parser.convert(:numeric) - assert_equal(["Numbers", ":integer", 1, ":float", 3.015], - @parser.shift) - end - - def test_all - @data << ",#{@windows_safe_time_data}" - @parser = CSV.new(@data) - @parser.convert(:all) - assert_equal(["Numbers", ":integer", 1, ":float", 3.015, @time.to_datetime], - @parser.shift) - end - - def test_custom - @parser.convert do |field| - /\A:(\S.*?)\s*\Z/ =~ field ? $1.to_sym : field - end - assert_equal(["Numbers", :integer, "1", :float, "3.015"], - @parser.shift) - end - - def test_builtin_custom - @parser.convert(:numeric) - @parser.convert(&@custom) - assert_equal(["Numbers", :integer, 1, :float, 3.015], - @parser.shift) - end - - def test_custom_field_info_line - @parser.convert do |field, info| - assert_equal(1, info.line) - info.index == 4 ? Float(field).floor : field - end - assert_equal(["Numbers", ":integer", "1", ":float", 3], - @parser.shift) - end - - def test_custom_field_info_header - headers = ["one", "two", "three", "four", "five"] - @parser = CSV.new(@data, headers: headers) - @parser.convert do |field, info| - info.header == "three" ? Integer(field) * 100 : field - end - assert_equal(CSV::Row.new(headers, - ["Numbers", ":integer", 100, ":float", "3.015"]), - @parser.shift) - end - - def test_custom_blank_field - converter = lambda {|field| field.nil?} - row = CSV.parse_line('nil,', converters: converter) - assert_equal([false, true], row) - end - - def test_nil_value - assert_equal(["nil", "", "a"], - CSV.parse_line(',"",a', nil_value: "nil")) - end - - def test_empty_value - assert_equal([nil, "empty", "a"], - CSV.parse_line(',"",a', empty_value: "empty")) - end - - def test_quoted_parse_line - row = CSV.parse_line('1,"2",3', converters: @preserving_converter) - assert_equal([1, "2", 3], row) - end - - def test_quoted_parse - expected = [["quoted", "unquoted"], ["109", 1], ["10A", 2]] - rows = CSV.parse(<<~CSV, converters: @preserving_converter) - "quoted",unquoted - "109",1 - "10A",2 - CSV - assert_equal(expected, rows) - end - - def test_quoted_alternating_quote - row = CSV.parse_line('"1",2,"3"', converters: @preserving_converter) - assert_equal(['1', 2, '3'], row) - end - - def test_quoted_parse_headers - expected = [["quoted", :unquoted], ["109", "1"], ["10A", "2"]] - table = CSV.parse(<<~CSV, headers: true, header_converters: @quoted_header_converter) - "quoted",unquoted - "109",1 - "10A",2 - CSV - assert_equal(expected, table.to_a) - end - - def test_quoted_parse_with_string_headers - expected = [["quoted", :unquoted], %w[109 1], %w[10A 2]] - table = CSV.parse(<<~CSV, headers: '"quoted",unquoted', header_converters: @quoted_header_converter) - "109",1 - "10A",2 - CSV - assert_equal(expected, table.to_a) - end -end diff --git a/test/csv/parse/test_each.rb b/test/csv/parse/test_each.rb deleted file mode 100644 index ce0b71d0581e25..00000000000000 --- a/test/csv/parse/test_each.rb +++ /dev/null @@ -1,23 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false - -require_relative "../helper" - -class TestCSVParseEach < Test::Unit::TestCase - extend DifferentOFS - - def test_twice - data = <<-CSV -Ruby,2.6.0,script - CSV - csv = CSV.new(data) - assert_equal([ - [["Ruby", "2.6.0", "script"]], - [], - ], - [ - csv.to_a, - csv.to_a, - ]) - end -end diff --git a/test/csv/parse/test_general.rb b/test/csv/parse/test_general.rb deleted file mode 100644 index a565ff2ef86e40..00000000000000 --- a/test/csv/parse/test_general.rb +++ /dev/null @@ -1,348 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false - -require "timeout" - -require_relative "../helper" - -# -# Following tests are my interpretation of the -# {CSV RCF}[https://www.ietf.org/rfc/rfc4180.txt]. I only deviate from that -# document in one place (intentionally) and that is to make the default row -# separator $/. -# -class TestCSVParseGeneral < Test::Unit::TestCase - extend DifferentOFS - - BIG_DATA = "123456789\n" * 512 - - def test_mastering_regex_example - ex = %Q{Ten Thousand,10000, 2710 ,,"10,000","It's ""10 Grand"", baby",10K} - assert_equal( [ "Ten Thousand", "10000", " 2710 ", nil, "10,000", - "It's \"10 Grand\", baby", "10K" ], - CSV.parse_line(ex) ) - end - - # Old Ruby 1.8 CSV library tests. - def test_std_lib_csv - [ ["\t", ["\t"]], - ["foo,\"\"\"\"\"\",baz", ["foo", "\"\"", "baz"]], - ["foo,\"\"\"bar\"\"\",baz", ["foo", "\"bar\"", "baz"]], - ["\"\"\"\n\",\"\"\"\n\"", ["\"\n", "\"\n"]], - ["foo,\"\r\n\",baz", ["foo", "\r\n", "baz"]], - ["\"\"", [""]], - ["foo,\"\"\"\",baz", ["foo", "\"", "baz"]], - ["foo,\"\r.\n\",baz", ["foo", "\r.\n", "baz"]], - ["foo,\"\r\",baz", ["foo", "\r", "baz"]], - ["foo,\"\",baz", ["foo", "", "baz"]], - ["\",\"", [","]], - ["foo", ["foo"]], - [",,", [nil, nil, nil]], - [",", [nil, nil]], - ["foo,\"\n\",baz", ["foo", "\n", "baz"]], - ["foo,,baz", ["foo", nil, "baz"]], - ["\"\"\"\r\",\"\"\"\r\"", ["\"\r", "\"\r"]], - ["\",\",\",\"", [",", ","]], - ["foo,bar,", ["foo", "bar", nil]], - [",foo,bar", [nil, "foo", "bar"]], - ["foo,bar", ["foo", "bar"]], - [";", [";"]], - ["\t,\t", ["\t", "\t"]], - ["foo,\"\r\n\r\",baz", ["foo", "\r\n\r", "baz"]], - ["foo,\"\r\n\n\",baz", ["foo", "\r\n\n", "baz"]], - ["foo,\"foo,bar\",baz", ["foo", "foo,bar", "baz"]], - [";,;", [";", ";"]] ].each do |csv_test| - assert_equal(csv_test.last, CSV.parse_line(csv_test.first)) - end - - [ ["foo,\"\"\"\"\"\",baz", ["foo", "\"\"", "baz"]], - ["foo,\"\"\"bar\"\"\",baz", ["foo", "\"bar\"", "baz"]], - ["foo,\"\r\n\",baz", ["foo", "\r\n", "baz"]], - ["\"\"", [""]], - ["foo,\"\"\"\",baz", ["foo", "\"", "baz"]], - ["foo,\"\r.\n\",baz", ["foo", "\r.\n", "baz"]], - ["foo,\"\r\",baz", ["foo", "\r", "baz"]], - ["foo,\"\",baz", ["foo", "", "baz"]], - ["foo", ["foo"]], - [",,", [nil, nil, nil]], - [",", [nil, nil]], - ["foo,\"\n\",baz", ["foo", "\n", "baz"]], - ["foo,,baz", ["foo", nil, "baz"]], - ["foo,bar", ["foo", "bar"]], - ["foo,\"\r\n\n\",baz", ["foo", "\r\n\n", "baz"]], - ["foo,\"foo,bar\",baz", ["foo", "foo,bar", "baz"]] ].each do |csv_test| - assert_equal(csv_test.last, CSV.parse_line(csv_test.first)) - end - end - - # From: [ruby-core:6496] - def test_aras_edge_cases - [ [%Q{a,b}, ["a", "b"]], - [%Q{a,"""b"""}, ["a", "\"b\""]], - [%Q{a,"""b"}, ["a", "\"b"]], - [%Q{a,"b"""}, ["a", "b\""]], - [%Q{a,"\nb"""}, ["a", "\nb\""]], - [%Q{a,"""\nb"}, ["a", "\"\nb"]], - [%Q{a,"""\nb\n"""}, ["a", "\"\nb\n\""]], - [%Q{a,"""\nb\n""",\nc}, ["a", "\"\nb\n\"", nil]], - [%Q{a,,,}, ["a", nil, nil, nil]], - [%Q{,}, [nil, nil]], - [%Q{"",""}, ["", ""]], - [%Q{""""}, ["\""]], - [%Q{"""",""}, ["\"",""]], - [%Q{,""}, [nil,""]], - [%Q{,"\r"}, [nil,"\r"]], - [%Q{"\r\n,"}, ["\r\n,"]], - [%Q{"\r\n,",}, ["\r\n,", nil]] ].each do |edge_case| - assert_equal(edge_case.last, CSV.parse_line(edge_case.first)) - end - end - - def test_james_edge_cases - # A read at eof? should return nil. - assert_equal(nil, CSV.parse_line("")) - # - # With Ruby 1.8 CSV it's impossible to tell an empty line from a line - # containing a single +nil+ field. The old CSV library returns - # [nil] in these cases, but Array.new makes more sense to - # me. - # - assert_equal(Array.new, CSV.parse_line("\n1,2,3\n")) - end - - def test_rob_edge_cases - [ [%Q{"a\nb"}, ["a\nb"]], - [%Q{"\n\n\n"}, ["\n\n\n"]], - [%Q{a,"b\n\nc"}, ['a', "b\n\nc"]], - [%Q{,"\r\n"}, [nil,"\r\n"]], - [%Q{,"\r\n."}, [nil,"\r\n."]], - [%Q{"a\na","one newline"}, ["a\na", 'one newline']], - [%Q{"a\n\na","two newlines"}, ["a\n\na", 'two newlines']], - [%Q{"a\r\na","one CRLF"}, ["a\r\na", 'one CRLF']], - [%Q{"a\r\n\r\na","two CRLFs"}, ["a\r\n\r\na", 'two CRLFs']], - [%Q{with blank,"start\n\nfinish"\n}, ['with blank', "start\n\nfinish"]], - ].each do |edge_case| - assert_equal(edge_case.last, CSV.parse_line(edge_case.first)) - end - end - - def test_non_regex_edge_cases - # An early version of the non-regex parser fails this test - [ [ "foo,\"foo,bar,baz,foo\",\"foo\"", - ["foo", "foo,bar,baz,foo", "foo"] ] ].each do |edge_case| - assert_equal(edge_case.last, CSV.parse_line(edge_case.first)) - end - - assert_raise(CSV::MalformedCSVError) do - CSV.parse_line("1,\"23\"4\"5\", 6") - end - end - - def test_malformed_csv_cr_first_line - error = assert_raise(CSV::MalformedCSVError) do - CSV.parse_line("1,2\r,3", row_sep: "\n") - end - assert_equal("Unquoted fields do not allow new line <\"\\r\"> in line 1.", - error.message) - end - - def test_malformed_csv_cr_middle_line - csv = <<-CSV -line,1,abc -line,2,"def\nghi" - -line,4,some\rjunk -line,5,jkl - CSV - - error = assert_raise(CSV::MalformedCSVError) do - CSV.parse(csv) - end - assert_equal("Unquoted fields do not allow new line <\"\\r\"> in line 4.", - error.message) - end - - def test_malformed_csv_unclosed_quote - error = assert_raise(CSV::MalformedCSVError) do - CSV.parse_line('1,2,"3...') - end - assert_equal("Unclosed quoted field in line 1.", - error.message) - end - - def test_malformed_csv_illegal_quote_middle_line - csv = <<-CSV -line,1,abc -line,2,"def\nghi" - -line,4,8'10" -line,5,jkl - CSV - - error = assert_raise(CSV::MalformedCSVError) do - CSV.parse(csv) - end - assert_equal("Illegal quoting in line 4.", - error.message) - end - - def test_the_parse_fails_fast_when_it_can_for_unquoted_fields - assert_parse_errors_out('valid,fields,bad start"' + BIG_DATA) - end - - def test_the_parse_fails_fast_when_it_can_for_unescaped_quotes - assert_parse_errors_out('valid,fields,"bad start"unescaped' + BIG_DATA) - end - - def test_field_size_limit_controls_lookahead - assert_parse_errors_out( 'valid,fields,"' + BIG_DATA + '"', - field_size_limit: 2048 ) - end - - def test_field_size_limit_max_allowed - column = "abcde" - assert_equal([[column]], - CSV.parse("\"#{column}\"", - field_size_limit: column.size + 1)) - end - - def test_field_size_limit_quote_simple - column = "abcde" - assert_parse_errors_out("\"#{column}\"", - field_size_limit: column.size) - end - - def test_field_size_limit_no_quote_implicitly - column = "abcde" - assert_parse_errors_out("#{column}", - field_size_limit: column.size) - end - - def test_field_size_limit_no_quote_explicitly - column = "abcde" - assert_parse_errors_out("#{column}", - field_size_limit: column.size, - quote_char: nil) - end - - def test_field_size_limit_in_extended_column_not_exceeding - data = <<~DATA - "a","b" - " - 2 - ","" - DATA - assert_nothing_raised(CSV::MalformedCSVError) do - CSV.parse(data, field_size_limit: 4) - end - end - - def test_field_size_limit_in_extended_column_exceeding - data = <<~DATA - "a","b" - " - 2345 - ","" - DATA - assert_parse_errors_out(data, field_size_limit: 5) - end - - def test_max_field_size_controls_lookahead - assert_parse_errors_out( 'valid,fields,"' + BIG_DATA + '"', - max_field_size: 2048 ) - end - - def test_max_field_size_max_allowed - column = "abcde" - assert_equal([[column]], - CSV.parse("\"#{column}\"", - max_field_size: column.size)) - end - - def test_max_field_size_quote_simple - column = "abcde" - assert_parse_errors_out("\"#{column}\"", - max_field_size: column.size - 1) - end - - def test_max_field_size_no_quote_implicitly - column = "abcde" - assert_parse_errors_out("#{column}", - max_field_size: column.size - 1) - end - - def test_max_field_size_no_quote_explicitly - column = "abcde" - assert_parse_errors_out("#{column}", - max_field_size: column.size - 1, - quote_char: nil) - end - - def test_max_field_size_in_extended_column_not_exceeding - data = <<~DATA - "a","b" - " - 2 - ","" - DATA - assert_nothing_raised(CSV::MalformedCSVError) do - CSV.parse(data, max_field_size: 3) - end - end - - def test_max_field_size_in_extended_column_exceeding - data = <<~DATA - "a","b" - " - 2345 - ","" - DATA - assert_parse_errors_out(data, max_field_size: 4) - end - - def test_row_sep_auto_cr - assert_equal([["a"]], CSV.parse("a\r")) - end - - def test_row_sep_auto_lf - assert_equal([["a"]], CSV.parse("a\n")) - end - - def test_row_sep_auto_cr_lf - assert_equal([["a"]], CSV.parse("a\r\n")) - end - - def test_seeked_string_io - input_with_bom = StringIO.new("\ufeffあ,い,う\r\na,b,c\r\n") - input_with_bom.read(3) - assert_equal([ - ["あ", "い", "う"], - ["a", "b", "c"], - ], - CSV.new(input_with_bom).each.to_a) - end - - private - - { - "YJIT"=>1, # for --yjit-call-threshold=1 - "MJIT"=>5, "RJIT"=>5, # for --jit-wait - }.any? do |jit, timeout| - if (RubyVM.const_defined?(jit) and - jit = RubyVM.const_get(jit) and - jit.respond_to?(:enabled?) and - jit.enabled?) - PARSE_ERROR_TIMEOUT = timeout - end - end - PARSE_ERROR_TIMEOUT ||= 0.2 - - def assert_parse_errors_out(data, timeout: PARSE_ERROR_TIMEOUT, **options) - assert_raise(CSV::MalformedCSVError) do - Timeout.timeout(timeout) do - CSV.parse(data, **options) - fail("Parse didn't error out") - end - end - end -end diff --git a/test/csv/parse/test_header.rb b/test/csv/parse/test_header.rb deleted file mode 100644 index e8c3786d686319..00000000000000 --- a/test/csv/parse/test_header.rb +++ /dev/null @@ -1,342 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false - -require_relative "../helper" - -class TestCSVHeaders < Test::Unit::TestCase - extend DifferentOFS - - def setup - super - @data = <<-CSV -first,second,third -A,B,C -1,2,3 - CSV - end - - def test_first_row - [:first_row, true].each do |setting| # two names for the same setting - # activate headers - csv = nil - assert_nothing_raised(Exception) do - csv = CSV.parse(@data, headers: setting) - end - - # first data row - skipping headers - row = csv[0] - assert_not_nil(row) - assert_instance_of(CSV::Row, row) - assert_equal([%w{first A}, %w{second B}, %w{third C}], row.to_a) - - # second data row - row = csv[1] - assert_not_nil(row) - assert_instance_of(CSV::Row, row) - assert_equal([%w{first 1}, %w{second 2}, %w{third 3}], row.to_a) - - # empty - assert_nil(csv[2]) - end - end - - def test_array_of_headers - # activate headers - csv = nil - assert_nothing_raised(Exception) do - csv = CSV.parse(@data, headers: [:my, :new, :headers]) - end - - # first data row - skipping headers - row = csv[0] - assert_not_nil(row) - assert_instance_of(CSV::Row, row) - assert_equal( [[:my, "first"], [:new, "second"], [:headers, "third"]], - row.to_a ) - - # second data row - row = csv[1] - assert_not_nil(row) - assert_instance_of(CSV::Row, row) - assert_equal([[:my, "A"], [:new, "B"], [:headers, "C"]], row.to_a) - - # third data row - row = csv[2] - assert_not_nil(row) - assert_instance_of(CSV::Row, row) - assert_equal([[:my, "1"], [:new, "2"], [:headers, "3"]], row.to_a) - - # empty - assert_nil(csv[3]) - - # with return and convert - assert_nothing_raised(Exception) do - csv = CSV.parse( @data, headers: [:my, :new, :headers], - return_headers: true, - header_converters: lambda { |h| h.to_s } ) - end - row = csv[0] - assert_not_nil(row) - assert_instance_of(CSV::Row, row) - assert_equal([["my", :my], ["new", :new], ["headers", :headers]], row.to_a) - assert_predicate(row, :header_row?) - assert_not_predicate(row, :field_row?) - end - - def test_csv_header_string - # activate headers - csv = nil - assert_nothing_raised(Exception) do - csv = CSV.parse(@data, headers: "my,new,headers") - end - - # first data row - skipping headers - row = csv[0] - assert_not_nil(row) - assert_instance_of(CSV::Row, row) - assert_equal([%w{my first}, %w{new second}, %w{headers third}], row.to_a) - - # second data row - row = csv[1] - assert_not_nil(row) - assert_instance_of(CSV::Row, row) - assert_equal([%w{my A}, %w{new B}, %w{headers C}], row.to_a) - - # third data row - row = csv[2] - assert_not_nil(row) - assert_instance_of(CSV::Row, row) - assert_equal([%w{my 1}, %w{new 2}, %w{headers 3}], row.to_a) - - # empty - assert_nil(csv[3]) - - # with return and convert - assert_nothing_raised(Exception) do - csv = CSV.parse( @data, headers: "my,new,headers", - return_headers: true, - header_converters: :symbol ) - end - row = csv[0] - assert_not_nil(row) - assert_instance_of(CSV::Row, row) - assert_equal([[:my, "my"], [:new, "new"], [:headers, "headers"]], row.to_a) - assert_predicate(row, :header_row?) - assert_not_predicate(row, :field_row?) - end - - def test_csv_header_string_inherits_separators - # parse with custom col_sep - csv = nil - assert_nothing_raised(Exception) do - csv = CSV.parse( @data.tr(",", "|"), col_sep: "|", - headers: "my|new|headers" ) - end - - # verify headers were recognized - row = csv[0] - assert_not_nil(row) - assert_instance_of(CSV::Row, row) - assert_equal([%w{my first}, %w{new second}, %w{headers third}], row.to_a) - end - - def test_return_headers - # activate headers and request they are returned - csv = nil - assert_nothing_raised(Exception) do - csv = CSV.parse(@data, headers: true, return_headers: true) - end - - # header row - row = csv[0] - assert_not_nil(row) - assert_instance_of(CSV::Row, row) - assert_equal( [%w{first first}, %w{second second}, %w{third third}], - row.to_a ) - assert_predicate(row, :header_row?) - assert_not_predicate(row, :field_row?) - - # first data row - skipping headers - row = csv[1] - assert_not_nil(row) - assert_instance_of(CSV::Row, row) - assert_equal([%w{first A}, %w{second B}, %w{third C}], row.to_a) - assert_not_predicate(row, :header_row?) - assert_predicate(row, :field_row?) - - # second data row - row = csv[2] - assert_not_nil(row) - assert_instance_of(CSV::Row, row) - assert_equal([%w{first 1}, %w{second 2}, %w{third 3}], row.to_a) - assert_not_predicate(row, :header_row?) - assert_predicate(row, :field_row?) - - # empty - assert_nil(csv[3]) - end - - def test_converters - # create test data where headers and fields look alike - data = <<-CSV -1,2,3 -1,2,3 - CSV - - # normal converters do not affect headers - csv = CSV.parse( data, headers: true, - return_headers: true, - converters: :numeric ) - assert_equal([%w{1 1}, %w{2 2}, %w{3 3}], csv[0].to_a) - assert_equal([["1", 1], ["2", 2], ["3", 3]], csv[1].to_a) - assert_nil(csv[2]) - - # header converters do affect headers (only) - assert_nothing_raised(Exception) do - csv = CSV.parse( data, headers: true, - return_headers: true, - converters: :numeric, - header_converters: :symbol ) - end - assert_equal([[:"1", "1"], [:"2", "2"], [:"3", "3"]], csv[0].to_a) - assert_equal([[:"1", 1], [:"2", 2], [:"3", 3]], csv[1].to_a) - assert_nil(csv[2]) - end - - def test_builtin_downcase_converter - csv = CSV.parse( "One,TWO Three", headers: true, - return_headers: true, - header_converters: :downcase ) - assert_equal(%w{one two\ three}, csv.headers) - end - - def test_builtin_symbol_converter - # Note that the trailing space is intentional - csv = CSV.parse( "One,TWO Three ", headers: true, - return_headers: true, - header_converters: :symbol ) - assert_equal([:one, :two_three], csv.headers) - end - - def test_builtin_symbol_raw_converter - csv = CSV.parse( "a b,c d", headers: true, - return_headers: true, - header_converters: :symbol_raw ) - assert_equal([:"a b", :"c d"], csv.headers) - end - - def test_builtin_symbol_converter_with_punctuation - csv = CSV.parse( "One, Two & Three ($)", headers: true, - return_headers: true, - header_converters: :symbol ) - assert_equal([:one, :two_three], csv.headers) - end - - def test_builtin_converters_with_blank_header - csv = CSV.parse( "one,,three", headers: true, - return_headers: true, - header_converters: [:downcase, :symbol, :symbol_raw] ) - assert_equal([:one, nil, :three], csv.headers) - end - - def test_custom_converter - converter = lambda { |header| header.tr(" ", "_") } - csv = CSV.parse( "One,TWO Three", - headers: true, - return_headers: true, - header_converters: converter ) - assert_equal(%w{One TWO_Three}, csv.headers) - end - - def test_table_support - csv = nil - assert_nothing_raised(Exception) do - csv = CSV.parse(@data, headers: true) - end - - assert_instance_of(CSV::Table, csv) - end - - def test_skip_blanks - @data = <<-CSV - - -A,B,C - -1,2,3 - - - - CSV - - expected = [%w[1 2 3]] - CSV.parse(@data, headers: true, skip_blanks: true) do |row| - assert_equal(expected.shift, row.fields) - end - - expected = [%w[A B C], %w[1 2 3]] - CSV.parse( @data, - headers: true, - return_headers: true, - skip_blanks: true ) do |row| - assert_equal(expected.shift, row.fields) - end - end - - def test_headers_reader - # no headers - assert_nil(CSV.new(@data).headers) - - # headers - csv = CSV.new(@data, headers: true) - assert_equal(true, csv.headers) # before headers are read - csv.shift # set headers - assert_equal(%w[first second third], csv.headers) # after headers are read - end - - def test_blank_row - @data += "\n#{@data}" # add a blank row - - # ensure that everything returned is a Row object - CSV.parse(@data, headers: true) do |row| - assert_instance_of(CSV::Row, row) - end - end - - def test_nil_row_header - @data = <<-CSV -A - -1 - CSV - - csv = CSV.parse(@data, headers: true) - - # ensure nil row creates Row object with headers - row = csv[0] - assert_equal([["A"], [nil]], - [row.headers, row.fields]) - end - - def test_parse_empty - assert_equal(CSV::Table.new([]), - CSV.parse("", headers: true)) - end - - def test_parse_empty_line - assert_equal(CSV::Table.new([]), - CSV.parse("\n", headers: true)) - end - - def test_specified_empty - assert_equal(CSV::Table.new([], - headers: ["header1"]), - CSV.parse("", headers: ["header1"])) - end - - def test_specified_empty_line - assert_equal(CSV::Table.new([CSV::Row.new(["header1"], [])], - headers: ["header1"]), - CSV.parse("\n", headers: ["header1"])) - end -end diff --git a/test/csv/parse/test_inputs_scanner.rb b/test/csv/parse/test_inputs_scanner.rb deleted file mode 100644 index 81327c187ff81b..00000000000000 --- a/test/csv/parse/test_inputs_scanner.rb +++ /dev/null @@ -1,63 +0,0 @@ -require_relative "../helper" - -class TestCSVParseInputsScanner < Test::Unit::TestCase - include CSVHelper - - def test_scan_keep_over_chunks_nested_back - input = CSV::Parser::UnoptimizedStringIO.new("abcdefghijklmnl") - scanner = CSV::Parser::InputsScanner.new([input], - Encoding::UTF_8, - nil, - chunk_size: 2) - scanner.keep_start - assert_equal("abc", scanner.scan_all(/[a-c]+/)) - scanner.keep_start - assert_equal("def", scanner.scan_all(/[d-f]+/)) - scanner.keep_back - scanner.keep_back - assert_equal("abcdefg", scanner.scan_all(/[a-g]+/)) - end - - def test_scan_keep_over_chunks_nested_drop_back - input = CSV::Parser::UnoptimizedStringIO.new("abcdefghijklmnl") - scanner = CSV::Parser::InputsScanner.new([input], - Encoding::UTF_8, - nil, - chunk_size: 3) - scanner.keep_start - assert_equal("ab", scanner.scan(/../)) - scanner.keep_start - assert_equal("c", scanner.scan(/./)) - assert_equal("d", scanner.scan(/./)) - scanner.keep_drop - scanner.keep_back - assert_equal("abcdefg", scanner.scan_all(/[a-g]+/)) - end - - def test_each_line_keep_over_chunks_multibyte - input = CSV::Parser::UnoptimizedStringIO.new("ab\n\u{3000}a\n") - scanner = CSV::Parser::InputsScanner.new([input], - Encoding::UTF_8, - nil, - chunk_size: 1) - each_line = scanner.each_line("\n") - assert_equal("ab\n", each_line.next) - scanner.keep_start - assert_equal("\u{3000}a\n", each_line.next) - scanner.keep_back - assert_equal("\u{3000}a\n", scanner.scan_all(/[^,]+/)) - end - - def test_each_line_keep_over_chunks_fit_chunk_size - input = CSV::Parser::UnoptimizedStringIO.new("\na") - scanner = CSV::Parser::InputsScanner.new([input], - Encoding::UTF_8, - nil, - chunk_size: 1) - each_line = scanner.each_line("\n") - assert_equal("\n", each_line.next) - scanner.keep_start - assert_equal("a", each_line.next) - scanner.keep_back - end -end diff --git a/test/csv/parse/test_invalid.rb b/test/csv/parse/test_invalid.rb deleted file mode 100644 index ddb59e2b9a0c45..00000000000000 --- a/test/csv/parse/test_invalid.rb +++ /dev/null @@ -1,52 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false - -require_relative "../helper" - -class TestCSVParseInvalid < Test::Unit::TestCase - def test_no_column_mixed_new_lines - error = assert_raise(CSV::MalformedCSVError) do - CSV.parse("\n" + - "\r") - end - assert_equal("New line must be <\"\\n\"> not <\"\\r\"> in line 2.", - error.message) - end - - def test_ignore_invalid_line - csv = CSV.new(<<-CSV, headers: true, return_headers: true) -head1,head2,head3 -aaa,bbb,ccc -ddd,ee"e.fff -ggg,hhh,iii - CSV - headers = ["head1", "head2", "head3"] - assert_equal(CSV::Row.new(headers, headers), - csv.shift) - assert_equal(CSV::Row.new(headers, ["aaa", "bbb", "ccc"]), - csv.shift) - assert_equal(false, csv.eof?) - error = assert_raise(CSV::MalformedCSVError) do - csv.shift - end - assert_equal("Illegal quoting in line 3.", - error.message) - assert_equal(false, csv.eof?) - assert_equal(CSV::Row.new(headers, ["ggg", "hhh", "iii"]), - csv.shift) - assert_equal(true, csv.eof?) - end - - def test_ignore_invalid_line_cr_lf - data = <<-CSV -"1","OK"\r -"2",""NOT" OK"\r -"3","OK"\r -CSV - csv = CSV.new(data) - - assert_equal(['1', 'OK'], csv.shift) - assert_raise(CSV::MalformedCSVError) { csv.shift } - assert_equal(['3', 'OK'], csv.shift) - end -end diff --git a/test/csv/parse/test_liberal_parsing.rb b/test/csv/parse/test_liberal_parsing.rb deleted file mode 100644 index 5796d10828c0ea..00000000000000 --- a/test/csv/parse/test_liberal_parsing.rb +++ /dev/null @@ -1,171 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false - -require_relative "../helper" - -class TestCSVParseLiberalParsing < Test::Unit::TestCase - extend DifferentOFS - - def test_middle_quote_start - input = '"Johnson, Dwayne",Dwayne "The Rock" Johnson' - error = assert_raise(CSV::MalformedCSVError) do - CSV.parse_line(input) - end - assert_equal("Illegal quoting in line 1.", - error.message) - assert_equal(["Johnson, Dwayne", 'Dwayne "The Rock" Johnson'], - CSV.parse_line(input, liberal_parsing: true)) - end - - def test_middle_quote_end - input = '"quoted" field' - error = assert_raise(CSV::MalformedCSVError) do - CSV.parse_line(input) - end - assert_equal("Any value after quoted field isn't allowed in line 1.", - error.message) - assert_equal(['"quoted" field'], - CSV.parse_line(input, liberal_parsing: true)) - end - - def test_endline_after_quoted_field_end - csv = CSV.new("A\r\n\"B\"\nC\r\n", liberal_parsing: true) - assert_equal(["A"], csv.gets) - error = assert_raise(CSV::MalformedCSVError) do - csv.gets - end - assert_equal('Illegal end-of-line sequence outside of a quoted field <"\n"> in line 2.', - error.message) - assert_equal(["C"], csv.gets) - end - - def test_quote_after_column_separator - error = assert_raise(CSV::MalformedCSVError) do - CSV.parse_line('is,this "three," or four,fields', liberal_parsing: true) - end - assert_equal("Unclosed quoted field in line 1.", - error.message) - end - - def test_quote_before_column_separator - assert_equal(["is", 'this "three', ' or four"', "fields"], - CSV.parse_line('is,this "three, or four",fields', - liberal_parsing: true)) - end - - def test_backslash_quote - assert_equal([ - "1", - "\"Hamlet says, \\\"Seems", - "\\\" madam! Nay it is; I know not \\\"seems.\\\"\"", - ], - CSV.parse_line('1,' + - '"Hamlet says, \"Seems,' + - '\" madam! Nay it is; I know not \"seems.\""', - liberal_parsing: true)) - end - - def test_space_quote - input = <<~CSV - Los Angeles, 34°03'N, 118°15'W - New York City, 40°42'46"N, 74°00'21"W - Paris, 48°51'24"N, 2°21'03"E - CSV - assert_equal( - [ - ["Los Angeles", " 34°03'N", " 118°15'W"], - ["New York City", " 40°42'46\"N", " 74°00'21\"W"], - ["Paris", " 48°51'24\"N", " 2°21'03\"E"], - ], - CSV.parse(input, liberal_parsing: true)) - end - - def test_double_quote_outside_quote - data = %Q{a,""b""} - error = assert_raise(CSV::MalformedCSVError) do - CSV.parse(data) - end - assert_equal("Any value after quoted field isn't allowed in line 1.", - error.message) - assert_equal([ - [["a", %Q{""b""}]], - [["a", %Q{"b"}]], - ], - [ - CSV.parse(data, liberal_parsing: true), - CSV.parse(data, - liberal_parsing: { - double_quote_outside_quote: true, - }), - ]) - end - - class TestBackslashQuote < Test::Unit::TestCase - extend ::DifferentOFS - - def test_double_quote_outside_quote - data = %Q{a,""b""} - assert_equal([ - [["a", %Q{""b""}]], - [["a", %Q{"b"}]], - ], - [ - CSV.parse(data, - liberal_parsing: { - backslash_quote: true - }), - CSV.parse(data, - liberal_parsing: { - backslash_quote: true, - double_quote_outside_quote: true - }), - ]) - end - - def test_unquoted_value - data = %q{\"\"a\"\"} - assert_equal([ - [[%q{\"\"a\"\"}]], - [[%q{""a""}]], - ], - [ - CSV.parse(data, liberal_parsing: true), - CSV.parse(data, - liberal_parsing: { - backslash_quote: true - }), - ]) - end - - def test_unquoted_value_multiple_characters_col_sep - data = %q{a<\\"b<=>x} - assert_equal([[%Q{a<"b}, "x"]], - CSV.parse(data, - col_sep: "<=>", - liberal_parsing: { - backslash_quote: true - })) - end - - def test_quoted_value - data = %q{"\"\"a\"\""} - assert_equal([ - [[%q{"\"\"a\"\""}]], - [[%q{""a""}]], - [[%q{""a""}]], - ], - [ - CSV.parse(data, liberal_parsing: true), - CSV.parse(data, - liberal_parsing: { - backslash_quote: true - }), - CSV.parse(data, - liberal_parsing: { - backslash_quote: true, - double_quote_outside_quote: true - }), - ]) - end - end -end diff --git a/test/csv/parse/test_quote_char_nil.rb b/test/csv/parse/test_quote_char_nil.rb deleted file mode 100644 index fc3b646759bffb..00000000000000 --- a/test/csv/parse/test_quote_char_nil.rb +++ /dev/null @@ -1,93 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false - -require_relative "../helper" - -class TestCSVParseQuoteCharNil < Test::Unit::TestCase - extend DifferentOFS - - def test_full - assert_equal(["a", "b"], CSV.parse_line(%Q{a,b}, quote_char: nil)) - end - - def test_end_with_nil - assert_equal(["a", nil, nil, nil], CSV.parse_line(%Q{a,,,}, quote_char: nil)) - end - - def test_nil_nil - assert_equal([nil, nil], CSV.parse_line(%Q{,}, quote_char: nil)) - end - - def test_unquoted_value_multiple_characters_col_sep - data = %q{ax} - assert_equal([[%Q{a", quote_char: nil)) - end - - def test_csv_header_string - data = <<~DATA - first,second,third - A,B,C - 1,2,3 - DATA - assert_equal( - CSV::Table.new([ - CSV::Row.new(["my", "new", "headers"], ["first", "second", "third"]), - CSV::Row.new(["my", "new", "headers"], ["A", "B", "C"]), - CSV::Row.new(["my", "new", "headers"], ["1", "2", "3"]) - ]), - CSV.parse(data, headers: "my,new,headers", quote_char: nil) - ) - end - - def test_comma - assert_equal([["a", "b", nil, "d"]], - CSV.parse("a,b,,d", col_sep: ",", quote_char: nil)) - end - - def test_space - assert_equal([["a", "b", nil, "d"]], - CSV.parse("a b d", col_sep: " ", quote_char: nil)) - end - - def encode_array(array, encoding) - array.collect do |element| - element ? element.encode(encoding) : element - end - end - - def test_space_no_ascii - encoding = Encoding::UTF_16LE - assert_equal([encode_array(["a", "b", nil, "d"], encoding)], - CSV.parse("a b d".encode(encoding), - col_sep: " ".encode(encoding), - quote_char: nil)) - end - - def test_multiple_space - assert_equal([["a b", nil, "d"]], - CSV.parse("a b d", col_sep: " ", quote_char: nil)) - end - - def test_multiple_characters_leading_empty_fields - data = <<-CSV -<=><=>A<=>B<=>C -1<=>2<=>3 - CSV - assert_equal([ - [nil, nil, "A", "B", "C"], - ["1", "2", "3"], - ], - CSV.parse(data, col_sep: "<=>", quote_char: nil)) - end - - def test_line - lines = [ - "abc,def\n", - ] - csv = CSV.new(lines.join(""), quote_char: nil) - lines.each do |line| - csv.shift - assert_equal(line, csv.line) - end - end -end diff --git a/test/csv/parse/test_read.rb b/test/csv/parse/test_read.rb deleted file mode 100644 index ba6fe985a94d36..00000000000000 --- a/test/csv/parse/test_read.rb +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false - -require_relative "../helper" - -class TestCSVParseRead < Test::Unit::TestCase - extend DifferentOFS - - def test_shift - data = <<-CSV -1 -2 -3 - CSV - csv = CSV.new(data) - assert_equal([ - ["1"], - [["2"], ["3"]], - nil, - ], - [ - csv.shift, - csv.read, - csv.shift, - ]) - end -end diff --git a/test/csv/parse/test_rewind.rb b/test/csv/parse/test_rewind.rb deleted file mode 100644 index 0aa403b75628be..00000000000000 --- a/test/csv/parse/test_rewind.rb +++ /dev/null @@ -1,40 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false - -require_relative "../helper" - -class TestCSVParseRewind < Test::Unit::TestCase - extend DifferentOFS - - def parse(data, **options) - csv = CSV.new(data, **options) - records = csv.to_a - csv.rewind - [records, csv.to_a] - end - - def test_default - data = <<-CSV -Ruby,2.6.0,script - CSV - assert_equal([ - [["Ruby", "2.6.0", "script"]], - [["Ruby", "2.6.0", "script"]], - ], - parse(data)) - end - - def test_have_headers - data = <<-CSV -Language,Version,Type -Ruby,2.6.0,script - CSV - assert_equal([ - [CSV::Row.new(["Language", "Version", "Type"], - ["Ruby", "2.6.0", "script"])], - [CSV::Row.new(["Language", "Version", "Type"], - ["Ruby", "2.6.0", "script"])], - ], - parse(data, headers: true)) - end -end diff --git a/test/csv/parse/test_row_separator.rb b/test/csv/parse/test_row_separator.rb deleted file mode 100644 index 5fd8e751528f19..00000000000000 --- a/test/csv/parse/test_row_separator.rb +++ /dev/null @@ -1,16 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false - -require_relative "../helper" - -class TestCSVParseRowSeparator < Test::Unit::TestCase - extend DifferentOFS - include CSVHelper - - def test_multiple_characters - with_chunk_size("1") do - assert_equal([["a"], ["b"]], - CSV.parse("a\r\nb\r\n", row_sep: "\r\n")) - end - end -end diff --git a/test/csv/parse/test_skip_lines.rb b/test/csv/parse/test_skip_lines.rb deleted file mode 100644 index 2fea02eb041aa7..00000000000000 --- a/test/csv/parse/test_skip_lines.rb +++ /dev/null @@ -1,126 +0,0 @@ -# frozen_string_literal: false - -require_relative "../helper" - -class TestCSVParseSkipLines < Test::Unit::TestCase - extend DifferentOFS - include CSVHelper - - def test_default - csv = CSV.new("a,b,c\n") - assert_nil(csv.skip_lines) - end - - def test_regexp - csv = <<-CSV -1 -#2 - #3 -4 - CSV - assert_equal([ - ["1"], - ["4"], - ], - CSV.parse(csv, :skip_lines => /\A\s*#/)) - end - - def test_regexp_quoted - csv = <<-CSV -1 -#2 -"#3" -4 - CSV - assert_equal([ - ["1"], - ["#3"], - ["4"], - ], - CSV.parse(csv, :skip_lines => /\A\s*#/)) - end - - def test_string - csv = <<-CSV -1 -.2 -3. -4 - CSV - assert_equal([ - ["1"], - ["4"], - ], - CSV.parse(csv, :skip_lines => ".")) - end - - class RegexStub - end - - def test_not_matchable - regex_stub = RegexStub.new - csv = CSV.new("1\n", :skip_lines => regex_stub) - error = assert_raise(ArgumentError) do - csv.shift - end - assert_equal(":skip_lines has to respond to #match: #{regex_stub.inspect}", - error.message) - end - - class Matchable - def initialize(pattern) - @pattern = pattern - end - - def match(line) - @pattern.match(line) - end - end - - def test_matchable - csv = <<-CSV -1 -# 2 -3 -# 4 - CSV - assert_equal([ - ["1"], - ["3"], - ], - CSV.parse(csv, :skip_lines => Matchable.new(/\A#/))) - end - - def test_multibyte_data - # U+3042 HIRAGANA LETTER A - # U+3044 HIRAGANA LETTER I - # U+3046 HIRAGANA LETTER U - value = "\u3042\u3044\u3046" - with_chunk_size("5") do - assert_equal([[value], [value]], - CSV.parse("#{value}\n#{value}\n", - :skip_lines => /\A#/)) - end - end - - def test_empty_line_and_liberal_parsing - assert_equal([["a", "b"]], - CSV.parse("a,b\n", - :liberal_parsing => true, - :skip_lines => /^$/)) - end - - def test_crlf - assert_equal([["a", "b"]], - CSV.parse("a,b\r\n,\r\n", - :skip_lines => /^,+$/)) - end - - def test_crlf_strip_no_last_crlf - assert_equal([["a"], ["b"]], - CSV.parse("a\r\nb", - row_sep: "\r\n", - skip_lines: /^ *$/, - strip: true)) - end -end diff --git a/test/csv/parse/test_strip.rb b/test/csv/parse/test_strip.rb deleted file mode 100644 index c5e35209cc16f6..00000000000000 --- a/test/csv/parse/test_strip.rb +++ /dev/null @@ -1,112 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false - -require_relative "../helper" - -class TestCSVParseStrip < Test::Unit::TestCase - extend DifferentOFS - - def test_both - assert_equal(["a", "b"], - CSV.parse_line(%Q{ a , b }, strip: true)) - end - - def test_left - assert_equal(["a", "b"], - CSV.parse_line(%Q{ a, b}, strip: true)) - end - - def test_right - assert_equal(["a", "b"], - CSV.parse_line(%Q{a ,b }, strip: true)) - end - - def test_middle - assert_equal(["a b"], - CSV.parse_line(%Q{a b}, strip: true)) - end - - def test_quoted - assert_equal([" a ", " b "], - CSV.parse_line(%Q{" a "," b "}, strip: true)) - end - - def test_liberal_parsing - assert_equal([" a ", "b", " c ", " d "], - CSV.parse_line(%Q{" a ", b , " c "," d " }, - strip: true, - liberal_parsing: true)) - end - - def test_string - assert_equal(["a", " b"], - CSV.parse_line(%Q{ a , " b" }, - strip: " ")) - end - - def test_no_quote - assert_equal([" a ", " b "], - CSV.parse_line(%Q{" a ", b }, - strip: %Q{"}, - quote_char: nil)) - end - - def test_do_not_strip_cr - assert_equal([ - ["a", "b "], - ["a", "b "], - ], - CSV.parse(%Q{"a" ,"b " \r} + - %Q{"a" ,"b " \r}, - strip: true)) - end - - def test_do_not_strip_lf - assert_equal([ - ["a", "b "], - ["a", "b "], - ], - CSV.parse(%Q{"a" ,"b " \n} + - %Q{"a" ,"b " \n}, - strip: true)) - end - - def test_do_not_strip_crlf - assert_equal([ - ["a", "b "], - ["a", "b "], - ], - CSV.parse(%Q{"a" ,"b " \r\n} + - %Q{"a" ,"b " \r\n}, - strip: true)) - end - - def test_col_sep_incompatible_true - message = "The provided strip (true) and " \ - "col_sep (\\t) options are incompatible." - assert_raise_with_message(ArgumentError, message) do - CSV.parse_line(%Q{"a"\t"b"\n}, - col_sep: "\t", - strip: true) - end - end - - def test_col_sep_incompatible_string - message = "The provided strip (\\t) and " \ - "col_sep (\\t) options are incompatible." - assert_raise_with_message(ArgumentError, message) do - CSV.parse_line(%Q{"a"\t"b"\n}, - col_sep: "\t", - strip: "\t") - end - end - - def test_col_sep_compatible_string - assert_equal( - ["a", "b"], - CSV.parse_line(%Q{\va\tb\v\n}, - col_sep: "\t", - strip: "\v") - ) - end -end diff --git a/test/csv/parse/test_unconverted_fields.rb b/test/csv/parse/test_unconverted_fields.rb deleted file mode 100644 index 437124ebd3c3cd..00000000000000 --- a/test/csv/parse/test_unconverted_fields.rb +++ /dev/null @@ -1,117 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false - -require_relative "../helper" - -class TestCSVParseUnconvertedFields < Test::Unit::TestCase - extend DifferentOFS - - def setup - super - @custom = lambda {|field| /\A:(\S.*?)\s*\Z/ =~ field ? $1.to_sym : field} - - @headers = ["first", "second", "third"] - @data = <<-CSV -first,second,third -1,2,3 - CSV - end - - - def test_custom - row = CSV.parse_line("Numbers,:integer,1,:float,3.015", - converters: [:numeric, @custom], - unconverted_fields: true) - assert_equal([ - ["Numbers", :integer, 1, :float, 3.015], - ["Numbers", ":integer", "1", ":float", "3.015"], - ], - [ - row, - row.unconverted_fields, - ]) - end - - def test_no_fields - row = CSV.parse_line("\n", - converters: [:numeric, @custom], - unconverted_fields: true) - assert_equal([ - [], - [], - ], - [ - row, - row.unconverted_fields, - ]) - end - - def test_parsed_header - row = CSV.parse_line(@data, - converters: :numeric, - unconverted_fields: true, - headers: :first_row) - assert_equal([ - CSV::Row.new(@headers, - [1, 2, 3]), - ["1", "2", "3"], - ], - [ - row, - row.unconverted_fields, - ]) - end - - def test_return_headers - row = CSV.parse_line(@data, - converters: :numeric, - unconverted_fields: true, - headers: :first_row, - return_headers: true) - assert_equal([ - CSV::Row.new(@headers, - @headers), - @headers, - ], - [ - row, - row.unconverted_fields, - ]) - end - - def test_header_converters - row = CSV.parse_line(@data, - converters: :numeric, - unconverted_fields: true, - headers: :first_row, - return_headers: true, - header_converters: :symbol) - assert_equal([ - CSV::Row.new(@headers.collect(&:to_sym), - @headers), - @headers, - ], - [ - row, - row.unconverted_fields, - ]) - end - - def test_specified_headers - row = CSV.parse_line("\n", - converters: :numeric, - unconverted_fields: true, - headers: %w{my new headers}, - return_headers: true, - header_converters: :symbol) - assert_equal([ - CSV::Row.new([:my, :new, :headers], - ["my", "new", "headers"]), - [], - ], - [ - row, - row.unconverted_fields, - ]) - end -end diff --git a/test/csv/test_data_converters.rb b/test/csv/test_data_converters.rb deleted file mode 100644 index c20a5d1f4bab46..00000000000000 --- a/test/csv/test_data_converters.rb +++ /dev/null @@ -1,190 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false - -require_relative "helper" - -class TestCSVDataConverters < Test::Unit::TestCase - extend DifferentOFS - - def setup - super - @win_safe_time_str = Time.now.strftime("%a %b %d %H:%M:%S %Y") - end - - def test_builtin_integer_converter - # does convert - [-5, 1, 10000000000].each do |n| - assert_equal(n, CSV::Converters[:integer][n.to_s]) - end - - # does not convert - (%w{junk 1.0} + [""]).each do |str| - assert_equal(str, CSV::Converters[:integer][str]) - end - end - - def test_builtin_float_converter - # does convert - [-5.1234, 0, 2.3e-11].each do |n| - assert_equal(n, CSV::Converters[:float][n.to_s]) - end - - # does not convert - (%w{junk 1..0 .015F} + [""]).each do |str| - assert_equal(str, CSV::Converters[:float][str]) - end - end - - def test_builtin_date_converter - # does convert - assert_instance_of( - Date, - CSV::Converters[:date][@win_safe_time_str.sub(/\d+:\d+:\d+ /, "")] - ) - - # does not convert - assert_instance_of(String, CSV::Converters[:date]["junk"]) - end - - def test_builtin_date_time_converter - # does convert - assert_instance_of( DateTime, - CSV::Converters[:date_time][@win_safe_time_str] ) - - # does not convert - assert_instance_of(String, CSV::Converters[:date_time]["junk"]) - end - - def test_builtin_date_time_converter_iso8601_date - iso8601_string = "2018-01-14" - datetime = DateTime.new(2018, 1, 14) - assert_equal(datetime, - CSV::Converters[:date_time][iso8601_string]) - end - - def test_builtin_date_time_converter_iso8601_minute - iso8601_string = "2018-01-14T22:25" - datetime = DateTime.new(2018, 1, 14, 22, 25) - assert_equal(datetime, - CSV::Converters[:date_time][iso8601_string]) - end - - def test_builtin_date_time_converter_iso8601_second - iso8601_string = "2018-01-14T22:25:19" - datetime = DateTime.new(2018, 1, 14, 22, 25, 19) - assert_equal(datetime, - CSV::Converters[:date_time][iso8601_string]) - end - - def test_builtin_date_time_converter_iso8601_under_second - iso8601_string = "2018-01-14T22:25:19.1" - datetime = DateTime.new(2018, 1, 14, 22, 25, 19.1) - assert_equal(datetime, - CSV::Converters[:date_time][iso8601_string]) - end - - def test_builtin_date_time_converter_iso8601_under_second_offset - iso8601_string = "2018-01-14T22:25:19.1+09:00" - datetime = DateTime.new(2018, 1, 14, 22, 25, 19.1, "+9") - assert_equal(datetime, - CSV::Converters[:date_time][iso8601_string]) - end - - def test_builtin_date_time_converter_iso8601_offset - iso8601_string = "2018-01-14T22:25:19+09:00" - datetime = DateTime.new(2018, 1, 14, 22, 25, 19, "+9") - assert_equal(datetime, - CSV::Converters[:date_time][iso8601_string]) - end - - def test_builtin_date_time_converter_iso8601_utc - iso8601_string = "2018-01-14T22:25:19Z" - datetime = DateTime.new(2018, 1, 14, 22, 25, 19) - assert_equal(datetime, - CSV::Converters[:date_time][iso8601_string]) - end - - def test_builtin_date_time_converter_rfc3339_minute - rfc3339_string = "2018-01-14 22:25" - datetime = DateTime.new(2018, 1, 14, 22, 25) - assert_equal(datetime, - CSV::Converters[:date_time][rfc3339_string]) - end - - def test_builtin_date_time_converter_rfc3339_second - rfc3339_string = "2018-01-14 22:25:19" - datetime = DateTime.new(2018, 1, 14, 22, 25, 19) - assert_equal(datetime, - CSV::Converters[:date_time][rfc3339_string]) - end - - def test_builtin_date_time_converter_rfc3339_under_second - rfc3339_string = "2018-01-14 22:25:19.1" - datetime = DateTime.new(2018, 1, 14, 22, 25, 19.1) - assert_equal(datetime, - CSV::Converters[:date_time][rfc3339_string]) - end - - def test_builtin_date_time_converter_rfc3339_under_second_offset - rfc3339_string = "2018-01-14 22:25:19.1+09:00" - datetime = DateTime.new(2018, 1, 14, 22, 25, 19.1, "+9") - assert_equal(datetime, - CSV::Converters[:date_time][rfc3339_string]) - end - - def test_builtin_date_time_converter_rfc3339_offset - rfc3339_string = "2018-01-14 22:25:19+09:00" - datetime = DateTime.new(2018, 1, 14, 22, 25, 19, "+9") - assert_equal(datetime, - CSV::Converters[:date_time][rfc3339_string]) - end - - def test_builtin_date_time_converter_rfc3339_utc - rfc3339_string = "2018-01-14 22:25:19Z" - datetime = DateTime.new(2018, 1, 14, 22, 25, 19) - assert_equal(datetime, - CSV::Converters[:date_time][rfc3339_string]) - end - - def test_builtin_date_time_converter_rfc3339_tab_minute - rfc3339_string = "2018-01-14\t22:25" - datetime = DateTime.new(2018, 1, 14, 22, 25) - assert_equal(datetime, - CSV::Converters[:date_time][rfc3339_string]) - end - - def test_builtin_date_time_converter_rfc3339_tab_second - rfc3339_string = "2018-01-14\t22:25:19" - datetime = DateTime.new(2018, 1, 14, 22, 25, 19) - assert_equal(datetime, - CSV::Converters[:date_time][rfc3339_string]) - end - - def test_builtin_date_time_converter_rfc3339_tab_under_second - rfc3339_string = "2018-01-14\t22:25:19.1" - datetime = DateTime.new(2018, 1, 14, 22, 25, 19.1) - assert_equal(datetime, - CSV::Converters[:date_time][rfc3339_string]) - end - - def test_builtin_date_time_converter_rfc3339_tab_under_second_offset - rfc3339_string = "2018-01-14\t22:25:19.1+09:00" - datetime = DateTime.new(2018, 1, 14, 22, 25, 19.1, "+9") - assert_equal(datetime, - CSV::Converters[:date_time][rfc3339_string]) - end - - def test_builtin_date_time_converter_rfc3339_tab_offset - rfc3339_string = "2018-01-14\t22:25:19+09:00" - datetime = DateTime.new(2018, 1, 14, 22, 25, 19, "+9") - assert_equal(datetime, - CSV::Converters[:date_time][rfc3339_string]) - end - - def test_builtin_date_time_converter_rfc3339_tab_utc - rfc3339_string = "2018-01-14\t22:25:19Z" - datetime = DateTime.new(2018, 1, 14, 22, 25, 19) - assert_equal(datetime, - CSV::Converters[:date_time][rfc3339_string]) - end -end diff --git a/test/csv/test_encodings.rb b/test/csv/test_encodings.rb deleted file mode 100644 index 55a7a60f2e54f7..00000000000000 --- a/test/csv/test_encodings.rb +++ /dev/null @@ -1,403 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false - -require_relative "helper" - -class TestCSVEncodings < Test::Unit::TestCase - extend DifferentOFS - include CSVHelper - - def setup - super - require 'tempfile' - @temp_csv_file = Tempfile.new(%w"test_csv. .csv") - @temp_csv_path = @temp_csv_file.path - @temp_csv_file.close - end - - def teardown - @temp_csv_file.close! - super - end - - ######################################## - ### Hand Test Some Popular Encodings ### - ######################################## - - def test_parses_utf8_encoding - assert_parses( [ %w[ one two … ], - %w[ 1 … 3 ], - %w[ … 5 6 ] ], "UTF-8" ) - end - - def test_parses_latin1_encoding - assert_parses( [ %w[ one two Résumé ], - %w[ 1 Résumé 3 ], - %w[ Résumé 5 6 ] ], "ISO-8859-1" ) - end - - def test_parses_utf16be_encoding - assert_parses( [ %w[ one two … ], - %w[ 1 … 3 ], - %w[ … 5 6 ] ], "UTF-16BE" ) - end - - def test_parses_shift_jis_encoding - assert_parses( [ %w[ 一 二 三 ], - %w[ 四 五 六 ], - %w[ 七 八 九 ] ], "Shift_JIS" ) - end - - ########################################################### - ### Try Simple Reading for All Non-dummy Ruby Encodings ### - ########################################################### - - def test_reading_with_most_encodings - each_encoding do |encoding| - begin - assert_parses( [ %w[ abc def ], - %w[ ghi jkl ] ], encoding ) - rescue Encoding::ConverterNotFoundError - fail("Failed to support #{encoding.name}.") - end - end - end - - def test_regular_expression_escaping - each_encoding do |encoding| - begin - assert_parses( [ %w[ abc def ], - %w[ ghi jkl ] ], encoding, col_sep: "|" ) - rescue Encoding::ConverterNotFoundError - fail("Failed to properly escape #{encoding.name}.") - end - end - end - - def test_read_with_default_encoding - data = "abc" - default_external = Encoding.default_external - each_encoding do |encoding| - File.open(@temp_csv_path, "wb", encoding: encoding) {|f| f << data} - begin - no_warnings do - Encoding.default_external = encoding - end - result = CSV.read(@temp_csv_path)[0][0] - ensure - no_warnings do - Encoding.default_external = default_external - end - end - assert_equal(encoding, result.encoding) - end - end - - ####################################################################### - ### Stress Test ASCII Compatible and Non-ASCII Compatible Encodings ### - ####################################################################### - - def test_auto_line_ending_detection - # arrange data to place a \r at the end of CSV's read ahead point - encode_for_tests([["a" * 509]], row_sep: "\r\n") do |data| - assert_equal("\r\n".encode(data.encoding), CSV.new(data).row_sep) - end - end - - def test_csv_chars_are_transcoded - encode_for_tests([%w[abc def]]) do |data| - %w[col_sep row_sep quote_char].each do |csv_char| - assert_equal( "|".encode(data.encoding), - CSV.new(data, csv_char.to_sym => "|").send(csv_char) ) - end - end - end - - def test_parser_works_with_encoded_headers - encode_for_tests([%w[one two three], %w[1 2 3]]) do |data| - parsed = CSV.parse(data, headers: true) - assert_all?(parsed.headers, "Wrong data encoding.") {|h| h.encoding == data.encoding} - parsed.each do |row| - assert_all?(row.fields, "Wrong data encoding.") {|f| f.encoding == data.encoding} - end - end - end - - def test_built_in_converters_transcode_to_utf_8_then_convert - encode_for_tests([%w[one two three], %w[1 2 3]]) do |data| - parsed = CSV.parse(data, converters: :integer) - assert_all?(parsed[0], "Wrong data encoding.") {|f| f.encoding == data.encoding} - assert_equal([1, 2, 3], parsed[1]) - end - end - - def test_built_in_header_converters_transcode_to_utf_8_then_convert - encode_for_tests([%w[one two three], %w[1 2 3]]) do |data| - parsed = CSV.parse( data, headers: true, - header_converters: :downcase ) - assert_all?(parsed.headers, "Wrong data encoding.") {|h| h.encoding.name == "UTF-8"} - assert_all?(parsed[0].fields, "Wrong data encoding.") {|f| f.encoding == data.encoding} - end - end - - def test_open_allows_you_to_set_encodings - encode_for_tests([%w[abc def]]) do |data| - # read and write in encoding - File.open(@temp_csv_path, "wb:#{data.encoding.name}") { |f| f << data } - CSV.open(@temp_csv_path, "rb:#{data.encoding.name}") do |csv| - csv.each do |row| - assert_all?(row, "Wrong data encoding.") {|f| f.encoding == data.encoding} - end - end - - # read and write with transcoding - File.open(@temp_csv_path, "wb:UTF-32BE:#{data.encoding.name}") do |f| - f << data - end - CSV.open(@temp_csv_path, "rb:UTF-32BE:#{data.encoding.name}") do |csv| - csv.each do |row| - assert_all?(row, "Wrong data encoding.") {|f| f.encoding == data.encoding} - end - end - end - end - - def test_foreach_allows_you_to_set_encodings - encode_for_tests([%w[abc def]]) do |data| - # read and write in encoding - File.open(@temp_csv_path, "wb", encoding: data.encoding) { |f| f << data } - CSV.foreach(@temp_csv_path, encoding: data.encoding) do |row| - row.each {|f| assert_equal(f.encoding, data.encoding)} - end - - # read and write with transcoding - File.open(@temp_csv_path, "wb:UTF-32BE:#{data.encoding.name}") do |f| - f << data - end - CSV.foreach( @temp_csv_path, - encoding: "UTF-32BE:#{data.encoding.name}" ) do |row| - assert_all?(row, "Wrong data encoding.") {|f| f.encoding == data.encoding} - end - end - end - - def test_read_allows_you_to_set_encodings - encode_for_tests([%w[abc def]]) do |data| - # read and write in encoding - File.open(@temp_csv_path, "wb:#{data.encoding.name}") { |f| f << data } - rows = CSV.read(@temp_csv_path, encoding: data.encoding.name) - assert_all?(rows.flatten, "Wrong data encoding.") {|f| f.encoding == data.encoding} - - # read and write with transcoding - File.open(@temp_csv_path, "wb:UTF-32BE:#{data.encoding.name}") do |f| - f << data - end - rows = CSV.read( @temp_csv_path, - encoding: "UTF-32BE:#{data.encoding.name}" ) - assert_all?(rows.flatten, "Wrong data encoding.") {|f| f.encoding == data.encoding} - end - end - - ################################# - ### Write CSV in any Encoding ### - ################################# - - def test_can_write_csv_in_any_encoding - each_encoding do |encoding| - # test generate_line with encoding hint - begin - csv = %w[abc d|ef].map { |f| f.encode(encoding) }. - to_csv(col_sep: "|", encoding: encoding.name) - rescue Encoding::ConverterNotFoundError - next - end - assert_equal(encoding, csv.encoding) - - # test generate_line with encoding guessing from fields - csv = %w[abc d|ef].map { |f| f.encode(encoding) }.to_csv(col_sep: "|") - assert_equal(encoding, csv.encoding) - - # writing to files - data = encode_ary([%w[abc d,ef], %w[123 456 ]], encoding) - CSV.open(@temp_csv_path, "wb:#{encoding.name}") do |f| - data.each { |row| f << row } - end - assert_equal(data, CSV.read(@temp_csv_path, encoding: encoding.name)) - end - end - - def test_encoding_is_upgraded_during_writing_as_needed - data = ["foo".force_encoding("US-ASCII"), "\u3042"] - assert_equal("US-ASCII", data.first.encoding.name) - assert_equal("UTF-8", data.last.encoding.name) - assert_equal("UTF-8", data.join('').encoding.name) - assert_equal("UTF-8", data.to_csv.encoding.name) - end - - def test_encoding_is_upgraded_for_ascii_content_during_writing_as_needed - data = ["foo".force_encoding("ISO-8859-1"), "\u3042"] - assert_equal("ISO-8859-1", data.first.encoding.name) - assert_equal("UTF-8", data.last.encoding.name) - assert_equal("UTF-8", data.join('').encoding.name) - assert_equal("UTF-8", data.to_csv.encoding.name) - end - - def test_encoding_is_not_upgraded_for_non_ascii_content_during_writing_as_needed - data = ["\u00c0".encode("ISO-8859-1"), "\u3042"] - assert_equal([ - "ISO-8859-1", - "UTF-8", - ], - data.collect {|field| field.encoding.name}) - assert_raise(Encoding::CompatibilityError) do - data.to_csv - end - end - - def test_explicit_encoding - bug9766 = '[ruby-core:62113] [Bug #9766]' - s = CSV.generate(encoding: "Windows-31J") do |csv| - csv << ["foo".force_encoding("ISO-8859-1"), "\u3042"] - end - assert_equal(["foo,\u3042\n".encode(Encoding::Windows_31J), Encoding::Windows_31J], [s, s.encoding], bug9766) - end - - def test_encoding_with_default_internal - with_default_internal(Encoding::UTF_8) do - s = CSV.generate(String.new(encoding: Encoding::Big5), encoding: Encoding::Big5) do |csv| - csv << ["漢字"] - end - assert_equal(["漢字\n".encode(Encoding::Big5), Encoding::Big5], [s, s.encoding]) - end - end - - def test_row_separator_detection_with_invalid_encoding - csv = CSV.new("invalid,\xF8\r\nvalid,x\r\n".force_encoding("UTF-8"), - encoding: "UTF-8") - assert_equal("\r\n", csv.row_sep) - end - - def test_invalid_encoding_row_error - csv = CSV.new("valid,x\rinvalid,\xF8\r".force_encoding("UTF-8"), - encoding: "UTF-8", row_sep: "\r") - error = assert_raise(CSV::InvalidEncodingError) do - csv.shift - csv.shift - end - assert_equal([Encoding::UTF_8, "Invalid byte sequence in UTF-8 in line 2."], - [error.encoding, error.message]) - end - - def test_string_input_transcode - # U+3042 HIRAGANA LETTER A - # U+3044 HIRAGANA LETTER I - # U+3046 HIRAGANA LETTER U - value = "\u3042\u3044\u3046" - csv = CSV.new(value, encoding: "UTF-8:EUC-JP") - assert_equal([[value.encode("EUC-JP")]], - csv.read) - end - - def test_string_input_set_encoding_string - # U+3042 HIRAGANA LETTER A - # U+3044 HIRAGANA LETTER I - # U+3046 HIRAGANA LETTER U - value = "\u3042\u3044\u3046".encode("EUC-JP") - csv = CSV.new(value.dup.force_encoding("UTF-8"), encoding: "EUC-JP") - assert_equal([[value.encode("EUC-JP")]], - csv.read) - end - - def test_string_input_set_encoding_encoding - # U+3042 HIRAGANA LETTER A - # U+3044 HIRAGANA LETTER I - # U+3046 HIRAGANA LETTER U - value = "\u3042\u3044\u3046".encode("EUC-JP") - csv = CSV.new(value.dup.force_encoding("UTF-8"), - encoding: Encoding.find("EUC-JP")) - assert_equal([[value.encode("EUC-JP")]], - csv.read) - end - - private - - def assert_parses(fields, encoding, **options) - encoding = Encoding.find(encoding) unless encoding.is_a? Encoding - orig_fields = fields - fields = encode_ary(fields, encoding) - data = ary_to_data(fields, **options) - parsed = CSV.parse(data, **options) - assert_equal(fields, parsed) - parsed.flatten.each_with_index do |field, i| - assert_equal(encoding, field.encoding, "Field[#{i + 1}] was transcoded.") - end - File.open(@temp_csv_path, "wb") {|f| f.print(data)} - CSV.open(@temp_csv_path, "rb:#{encoding}", **options) do |csv| - csv.each_with_index do |row, i| - assert_equal(fields[i], row) - end - end - begin - CSV.open(@temp_csv_path, - "rb:#{encoding}:#{__ENCODING__}", - **options) do |csv| - csv.each_with_index do |row, i| - assert_equal(orig_fields[i], row) - end - end unless encoding == __ENCODING__ - rescue Encoding::ConverterNotFoundError - end - options[:encoding] = encoding.name - CSV.open(@temp_csv_path, **options) do |csv| - csv.each_with_index do |row, i| - assert_equal(fields[i], row) - end - end - options.delete(:encoding) - options[:external_encoding] = encoding.name - options[:internal_encoding] = __ENCODING__.name - begin - CSV.open(@temp_csv_path, **options) do |csv| - csv.each_with_index do |row, i| - assert_equal(orig_fields[i], row) - end - end unless encoding == __ENCODING__ - rescue Encoding::ConverterNotFoundError - end - end - - def encode_ary(ary, encoding) - ary.map { |row| row.map { |field| field.encode(encoding) } } - end - - def ary_to_data(ary, **options) - encoding = ary.flatten.first.encoding - quote_char = (options[:quote_char] || '"').encode(encoding) - col_sep = (options[:col_sep] || ",").encode(encoding) - row_sep = (options[:row_sep] || "\n").encode(encoding) - ary.map { |row| - row.map { |field| - [quote_char, field.encode(encoding), quote_char].join('') - }.join(col_sep) + row_sep - }.join('').encode(encoding) - end - - def encode_for_tests(data, **options) - yield ary_to_data(encode_ary(data, "UTF-8"), **options) - yield ary_to_data(encode_ary(data, "UTF-16BE"), **options) - end - - def each_encoding - Encoding.list.each do |encoding| - next if encoding.dummy? # skip "dummy" encodings - yield encoding - end - end - - def no_warnings - old_verbose, $VERBOSE = $VERBOSE, nil - yield - ensure - $VERBOSE = old_verbose - end -end diff --git a/test/csv/test_features.rb b/test/csv/test_features.rb deleted file mode 100644 index d6eb2dc13be165..00000000000000 --- a/test/csv/test_features.rb +++ /dev/null @@ -1,359 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false - -begin - require "zlib" -rescue LoadError -end - -require_relative "helper" -require "tempfile" - -class TestCSVFeatures < Test::Unit::TestCase - extend DifferentOFS - - TEST_CASES = [ [%Q{a,b}, ["a", "b"]], - [%Q{a,"""b"""}, ["a", "\"b\""]], - [%Q{a,"""b"}, ["a", "\"b"]], - [%Q{a,"b"""}, ["a", "b\""]], - [%Q{a,"\nb"""}, ["a", "\nb\""]], - [%Q{a,"""\nb"}, ["a", "\"\nb"]], - [%Q{a,"""\nb\n"""}, ["a", "\"\nb\n\""]], - [%Q{a,"""\nb\n""",\nc}, ["a", "\"\nb\n\"", nil]], - [%Q{a,,,}, ["a", nil, nil, nil]], - [%Q{,}, [nil, nil]], - [%Q{"",""}, ["", ""]], - [%Q{""""}, ["\""]], - [%Q{"""",""}, ["\"",""]], - [%Q{,""}, [nil,""]], - [%Q{,"\r"}, [nil,"\r"]], - [%Q{"\r\n,"}, ["\r\n,"]], - [%Q{"\r\n,",}, ["\r\n,", nil]] ] - - def setup - super - @sample_data = <<-CSV -line,1,abc -line,2,"def\nghi" - -line,4,jkl - CSV - @csv = CSV.new(@sample_data) - end - - def test_col_sep - [";", "\t"].each do |sep| - TEST_CASES.each do |test_case| - assert_equal( test_case.last.map { |t| t.tr(",", sep) unless t.nil? }, - CSV.parse_line( test_case.first.tr(",", sep), - col_sep: sep ) ) - end - end - assert_equal([",,,", nil], CSV.parse_line(",,,;", col_sep: ";")) - end - - def test_col_sep_nil - assert_raise_with_message(ArgumentError, - ":col_sep must be 1 or more characters: nil") do - CSV.parse(@sample_data, col_sep: nil) - end - end - - def test_col_sep_empty - assert_raise_with_message(ArgumentError, - ":col_sep must be 1 or more characters: \"\"") do - CSV.parse(@sample_data, col_sep: "") - end - end - - def test_row_sep - error = assert_raise(CSV::MalformedCSVError) do - CSV.parse_line("1,2,3\n,4,5\r\n", row_sep: "\r\n") - end - assert_equal("Unquoted fields do not allow new line <\"\\n\"> in line 1.", - error.message) - assert_equal( ["1", "2", "3\n", "4", "5"], - CSV.parse_line(%Q{1,2,"3\n",4,5\r\n}, row_sep: "\r\n")) - end - - def test_quote_char - TEST_CASES.each do |test_case| - assert_equal(test_case.last.map {|t| t.tr('"', "'") unless t.nil?}, - CSV.parse_line(test_case.first.tr('"', "'"), - quote_char: "'" )) - end - end - - def test_quote_char_special_regexp_char - TEST_CASES.each do |test_case| - assert_equal(test_case.last.map {|t| t.tr('"', "|") unless t.nil?}, - CSV.parse_line(test_case.first.tr('"', "|"), - quote_char: "|")) - end - end - - def test_quote_char_special_regexp_char_liberal_parsing - TEST_CASES.each do |test_case| - assert_equal(test_case.last.map {|t| t.tr('"', "|") unless t.nil?}, - CSV.parse_line(test_case.first.tr('"', "|"), - quote_char: "|", - liberal_parsing: true)) - end - end - - def test_csv_char_readers - %w[col_sep row_sep quote_char].each do |reader| - csv = CSV.new("abc,def", reader.to_sym => "|") - assert_equal("|", csv.send(reader)) - end - end - - def test_row_sep_auto_discovery - ["\r\n", "\n", "\r"].each do |line_end| - data = "1,2,3#{line_end}4,5#{line_end}" - discovered = CSV.new(data).row_sep - assert_equal(line_end, discovered) - end - - assert_equal("\n", CSV.new("\n\r\n\r").row_sep) - - assert_equal($/, CSV.new("").row_sep) - - assert_equal($/, CSV.new(STDERR).row_sep) - end - - def test_line - lines = [ - %Q(\u{3000}abc,def\n), - %Q(\u{3000}abc,"d\nef"\n), - %Q(\u{3000}abc,"d\r\nef"\n), - %Q(\u{3000}abc,"d\ref") - ] - csv = CSV.new(lines.join('')) - lines.each do |line| - csv.shift - assert_equal(line, csv.line) - end - end - - def test_lineno - assert_equal(5, @sample_data.lines.to_a.size) - - 4.times do |line_count| - assert_equal(line_count, @csv.lineno) - assert_not_nil(@csv.shift) - assert_equal(line_count + 1, @csv.lineno) - end - assert_nil(@csv.shift) - end - - def test_readline - test_lineno - - @csv.rewind - - test_lineno - end - - def test_unknown_options - assert_raise_with_message(ArgumentError, /unknown keyword/) { - CSV.new(@sample_data, unknown: :error) - } - assert_raise_with_message(ArgumentError, /unknown keyword/) { - CSV.new(@sample_data, universal_newline: true) - } - end - - def test_skip_blanks - assert_equal(4, @csv.to_a.size) - - @csv = CSV.new(@sample_data, skip_blanks: true) - - count = 0 - @csv.each do |row| - count += 1 - assert_equal("line", row.first) - end - assert_equal(3, count) - end - - def test_csv_behavior_readers - %w[ unconverted_fields return_headers write_headers - skip_blanks force_quotes ].each do |behavior| - assert_not_predicate(CSV.new("abc,def"), "#{behavior}?", "Behavior defaulted to on.") - csv = CSV.new("abc,def", behavior.to_sym => true) - assert_predicate(csv, "#{behavior}?", "Behavior change now registered.") - end - end - - def test_converters_reader - # no change - assert_equal( [:integer], - CSV.new("abc,def", converters: [:integer]).converters ) - - # just one - assert_equal( [:integer], - CSV.new("abc,def", converters: :integer).converters ) - - # expanded - assert_equal( [:integer, :float], - CSV.new("abc,def", converters: :numeric).converters ) - - # custom - csv = CSV.new("abc,def", converters: [:integer, lambda { }]) - assert_equal(2, csv.converters.size) - assert_equal(:integer, csv.converters.first) - assert_instance_of(Proc, csv.converters.last) - end - - def test_header_converters_reader - # no change - hc = :header_converters - assert_equal([:downcase], CSV.new("abc,def", hc => [:downcase]).send(hc)) - - # just one - assert_equal([:downcase], CSV.new("abc,def", hc => :downcase).send(hc)) - - # custom - csv = CSV.new("abc,def", hc => [:symbol, lambda { }]) - assert_equal(2, csv.send(hc).size) - assert_equal(:symbol, csv.send(hc).first) - assert_instance_of(Proc, csv.send(hc).last) - end - - # reported by Kev Jackson - def test_failing_to_escape_col_sep - assert_nothing_raised(Exception) { CSV.new(String.new, col_sep: "|") } - end - - # reported by Chris Roos - def test_failing_to_reset_headers_in_rewind - csv = CSV.new("forename,surname", headers: true, return_headers: true) - csv.each {|row| assert_predicate row, :header_row?} - csv.rewind - csv.each {|row| assert_predicate row, :header_row?} - end - - def test_gzip_reader - zipped = nil - assert_nothing_raised(NoMethodError) do - zipped = CSV.new( - Zlib::GzipReader.open( - File.join(File.dirname(__FILE__), "line_endings.gz") - ) - ) - end - assert_equal("\r\n", zipped.row_sep) - ensure - zipped.close - end if defined?(Zlib::GzipReader) - - def test_gzip_writer - Tempfile.create(%w"temp .gz") {|tempfile| - tempfile.close - file = tempfile.path - zipped = nil - assert_nothing_raised(NoMethodError) do - zipped = CSV.new(Zlib::GzipWriter.open(file)) - end - zipped << %w[one two three] - zipped << [1, 2, 3] - zipped.close - - assert_include(Zlib::GzipReader.open(file) {|f| f.read}, - $INPUT_RECORD_SEPARATOR, "@row_sep did not default") - } - end if defined?(Zlib::GzipWriter) - - def test_inspect_is_smart_about_io_types - str = CSV.new("string,data").inspect - assert_include(str, "io_type:StringIO", "IO type not detected.") - - str = CSV.new($stderr).inspect - assert_include(str, "io_type:$stderr", "IO type not detected.") - - Tempfile.create(%w"temp .csv") {|tempfile| - tempfile.close - path = tempfile.path - File.open(path, "w") { |csv| csv << "one,two,three\n1,2,3\n" } - str = CSV.open(path) { |csv| csv.inspect } - assert_include(str, "io_type:File", "IO type not detected.") - } - end - - def test_inspect_shows_key_attributes - str = @csv.inspect - %w[lineno col_sep row_sep quote_char].each do |attr_name| - assert_match(/\b#{attr_name}:[^\s>]+/, str) - end - end - - def test_inspect_shows_headers_when_available - csv = CSV.new("one,two,three\n1,2,3\n", headers: true) - assert_include(csv.inspect, "headers:true", "Header hint not shown.") - csv.shift # load headers - assert_match(/headers:\[[^\]]+\]/, csv.inspect) - end - - def test_inspect_encoding_is_ascii_compatible - csv = CSV.new("one,two,three\n1,2,3\n".encode("UTF-16BE")) - assert_send([Encoding, :compatible?, - Encoding.find("US-ASCII"), csv.inspect.encoding], - "inspect() was not ASCII compatible.") - end - - def test_version - assert_not_nil(CSV::VERSION) - assert_instance_of(String, CSV::VERSION) - assert_predicate(CSV::VERSION, :frozen?) - assert_match(/\A\d\.\d\.\d\z/, CSV::VERSION) - end - - def test_table_nil_equality - assert_nothing_raised(NoMethodError) { CSV.parse("test", headers: true) == nil } - end - - # non-seekable input stream for testing https://github.com/ruby/csv/issues/44 - class DummyIO - extend Forwardable - def_delegators :@io, :gets, :read, :pos, :eof? # no seek or rewind! - def initialize(data) - @io = StringIO.new(data) - end - end - - def test_line_separator_autodetection_for_non_seekable_input_lf - c = CSV.new(DummyIO.new("one,two,three\nfoo,bar,baz\n")) - assert_equal [["one", "two", "three"], ["foo", "bar", "baz"]], c.each.to_a - end - - def test_line_separator_autodetection_for_non_seekable_input_cr - c = CSV.new(DummyIO.new("one,two,three\rfoo,bar,baz\r")) - assert_equal [["one", "two", "three"], ["foo", "bar", "baz"]], c.each.to_a - end - - def test_line_separator_autodetection_for_non_seekable_input_cr_lf - c = CSV.new(DummyIO.new("one,two,three\r\nfoo,bar,baz\r\n")) - assert_equal [["one", "two", "three"], ["foo", "bar", "baz"]], c.each.to_a - end - - def test_line_separator_autodetection_for_non_seekable_input_1024_over_lf - table = (1..10).map { |row| (1..200).map { |col| "row#{row}col#{col}" }.to_a }.to_a - input = table.map { |line| line.join(",") }.join("\n") - c = CSV.new(DummyIO.new(input)) - assert_equal table, c.each.to_a - end - - def test_line_separator_autodetection_for_non_seekable_input_1024_over_cr_lf - table = (1..10).map { |row| (1..200).map { |col| "row#{row}col#{col}" }.to_a }.to_a - input = table.map { |line| line.join(",") }.join("\r\n") - c = CSV.new(DummyIO.new(input)) - assert_equal table, c.each.to_a - end - - def test_line_separator_autodetection_for_non_seekable_input_many_cr_only - # input with lots of CRs (to make sure no bytes are lost due to look-ahead) - c = CSV.new(DummyIO.new("foo\r" + "\r" * 9999 + "bar\r")) - assert_equal [["foo"]] + [[]] * 9999 + [["bar"]], c.each.to_a - end -end diff --git a/test/csv/test_patterns.rb b/test/csv/test_patterns.rb deleted file mode 100644 index 881f03a3a4ae5e..00000000000000 --- a/test/csv/test_patterns.rb +++ /dev/null @@ -1,27 +0,0 @@ -# frozen_string_literal: true - -require_relative "helper" - -class TestCSVPatternMatching < Test::Unit::TestCase - - def test_hash - case CSV::Row.new(%i{A B C}, [1, 2, 3]) - in B: b, C: c - assert_equal([2, 3], [b, c]) - end - end - - def test_hash_rest - case CSV::Row.new(%i{A B C}, [1, 2, 3]) - in B: b, **rest - assert_equal([2, { A: 1, C: 3 }], [b, rest]) - end - end - - def test_array - case CSV::Row.new(%i{A B C}, [1, 2, 3]) - in *, matched - assert_equal(3, matched) - end - end -end diff --git a/test/csv/test_row.rb b/test/csv/test_row.rb deleted file mode 100644 index b7179450412bbd..00000000000000 --- a/test/csv/test_row.rb +++ /dev/null @@ -1,435 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false - -require_relative "helper" - -class TestCSVRow < Test::Unit::TestCase - extend DifferentOFS - - def setup - super - @row = CSV::Row.new(%w{A B C A A}, [1, 2, 3, 4]) - end - - def test_initialize - # basic - row = CSV::Row.new(%w{A B C}, [1, 2, 3]) - assert_not_nil(row) - assert_instance_of(CSV::Row, row) - assert_equal([["A", 1], ["B", 2], ["C", 3]], row.to_a) - - # missing headers - row = CSV::Row.new(%w{A}, [1, 2, 3]) - assert_not_nil(row) - assert_instance_of(CSV::Row, row) - assert_equal([["A", 1], [nil, 2], [nil, 3]], row.to_a) - - # missing fields - row = CSV::Row.new(%w{A B C}, [1, 2]) - assert_not_nil(row) - assert_instance_of(CSV::Row, row) - assert_equal([["A", 1], ["B", 2], ["C", nil]], row.to_a) - end - - def test_row_type - # field rows - row = CSV::Row.new(%w{A B C}, [1, 2, 3]) # implicit - assert_not_predicate(row, :header_row?) - assert_predicate(row, :field_row?) - row = CSV::Row.new(%w{A B C}, [1, 2, 3], false) # explicit - assert_not_predicate(row, :header_row?) - assert_predicate(row, :field_row?) - - # header row - row = CSV::Row.new(%w{A B C}, [1, 2, 3], true) - assert_predicate(row, :header_row?) - assert_not_predicate(row, :field_row?) - end - - def test_headers - assert_equal(%w{A B C A A}, @row.headers) - end - - def test_field - # by name - assert_equal(2, @row.field("B")) - assert_equal(2, @row["B"]) # alias - - # by index - assert_equal(3, @row.field(2)) - - # by range - assert_equal([2,3], @row.field(1..2)) - - # missing - assert_nil(@row.field("Missing")) - assert_nil(@row.field(10)) - - # minimum index - assert_equal(1, @row.field("A")) - assert_equal(1, @row.field("A", 0)) - assert_equal(4, @row.field("A", 1)) - assert_equal(4, @row.field("A", 2)) - assert_equal(4, @row.field("A", 3)) - assert_equal(nil, @row.field("A", 4)) - assert_equal(nil, @row.field("A", 5)) - end - - def test_fetch - # only by name - assert_equal(2, @row.fetch('B')) - - # missing header raises KeyError - assert_raise KeyError do - @row.fetch('foo') - end - - # missing header yields itself to block - assert_equal 'bar', @row.fetch('foo') { |header| - header == 'foo' ? 'bar' : false } - - # missing header returns the given default value - assert_equal 'bar', @row.fetch('foo', 'bar') - - # more than one vararg raises ArgumentError - assert_raise ArgumentError do - @row.fetch('foo', 'bar', 'baz') - end - end - - def test_has_key? - assert_equal(true, @row.has_key?('B')) - assert_equal(false, @row.has_key?('foo')) - - # aliases - assert_equal(true, @row.header?('B')) - assert_equal(false, @row.header?('foo')) - - assert_equal(true, @row.include?('B')) - assert_equal(false, @row.include?('foo')) - - assert_equal(true, @row.member?('B')) - assert_equal(false, @row.member?('foo')) - - assert_equal(true, @row.key?('B')) - assert_equal(false, @row.key?('foo')) - end - - def test_set_field - # set field by name - assert_equal(100, @row["A"] = 100) - - # set field by index - assert_equal(300, @row[3] = 300) - - # set field by name and minimum index - assert_equal([:a, :b, :c], @row["A", 4] = [:a, :b, :c]) - - # verify the changes - assert_equal( [ ["A", 100], - ["B", 2], - ["C", 3], - ["A", 300], - ["A", [:a, :b, :c]] ], @row.to_a ) - - # assigning an index past the end - assert_equal("End", @row[10] = "End") - assert_equal( [ ["A", 100], - ["B", 2], - ["C", 3], - ["A", 300], - ["A", [:a, :b, :c]], - [nil, nil], - [nil, nil], - [nil, nil], - [nil, nil], - [nil, nil], - [nil, "End"] ], @row.to_a ) - - # assigning a new field by header - assert_equal("New", @row[:new] = "New") - assert_equal( [ ["A", 100], - ["B", 2], - ["C", 3], - ["A", 300], - ["A", [:a, :b, :c]], - [nil, nil], - [nil, nil], - [nil, nil], - [nil, nil], - [nil, nil], - [nil, "End"], - [:new, "New"] ], @row.to_a ) - end - - def test_append - # add a value - assert_equal(@row, @row << "Value") - assert_equal( [ ["A", 1], - ["B", 2], - ["C", 3], - ["A", 4], - ["A", nil], - [nil, "Value"] ], @row.to_a ) - - # add a pair - assert_equal(@row, @row << %w{Header Field}) - assert_equal( [ ["A", 1], - ["B", 2], - ["C", 3], - ["A", 4], - ["A", nil], - [nil, "Value"], - %w{Header Field} ], @row.to_a ) - - # a pair with Hash syntax - assert_equal(@row, @row << {key: :value}) - assert_equal( [ ["A", 1], - ["B", 2], - ["C", 3], - ["A", 4], - ["A", nil], - [nil, "Value"], - %w{Header Field}, - [:key, :value] ], @row.to_a ) - - # multiple fields at once - assert_equal(@row, @row.push(100, 200, [:last, 300])) - assert_equal( [ ["A", 1], - ["B", 2], - ["C", 3], - ["A", 4], - ["A", nil], - [nil, "Value"], - %w{Header Field}, - [:key, :value], - [nil, 100], - [nil, 200], - [:last, 300] ], @row.to_a ) - end - - def test_delete - # by index - assert_equal(["B", 2], @row.delete(1)) - - # by header - assert_equal(["C", 3], @row.delete("C")) - - end - - def test_delete_if - assert_equal(@row, @row.delete_if { |h, f| h == "A" and not f.nil? }) - assert_equal([["B", 2], ["C", 3], ["A", nil]], @row.to_a) - end - - def test_delete_if_without_block - enum = @row.delete_if - assert_instance_of(Enumerator, enum) - assert_equal(@row.size, enum.size) - - assert_equal(@row, enum.each { |h, f| h == "A" and not f.nil? }) - assert_equal([["B", 2], ["C", 3], ["A", nil]], @row.to_a) - end - - def test_fields - # all fields - assert_equal([1, 2, 3, 4, nil], @row.fields) - - # by header - assert_equal([1, 3], @row.fields("A", "C")) - - # by index - assert_equal([2, 3, nil], @row.fields(1, 2, 10)) - - # by both - assert_equal([2, 3, 4], @row.fields("B", "C", 3)) - - # with minimum indices - assert_equal([2, 3, 4], @row.fields("B", "C", ["A", 3])) - - # by header range - assert_equal([2, 3], @row.values_at("B".."C")) - end - - def test_index - # basic usage - assert_equal(0, @row.index("A")) - assert_equal(1, @row.index("B")) - assert_equal(2, @row.index("C")) - assert_equal(nil, @row.index("Z")) - - # with minimum index - assert_equal(0, @row.index("A")) - assert_equal(0, @row.index("A", 0)) - assert_equal(3, @row.index("A", 1)) - assert_equal(3, @row.index("A", 2)) - assert_equal(3, @row.index("A", 3)) - assert_equal(4, @row.index("A", 4)) - assert_equal(nil, @row.index("A", 5)) - end - - def test_queries - # fields - assert(@row.field?(4)) - assert(@row.field?(nil)) - assert(!@row.field?(10)) - end - - def test_each - # array style - ary = @row.to_a - @row.each do |pair| - assert_equal(ary.first.first, pair.first) - assert_equal(ary.shift.last, pair.last) - end - - # hash style - ary = @row.to_a - @row.each do |header, field| - assert_equal(ary.first.first, header) - assert_equal(ary.shift.last, field) - end - - # verify that we can chain the call - assert_equal(@row, @row.each { }) - - # without block - ary = @row.to_a - enum = @row.each - assert_instance_of(Enumerator, enum) - assert_equal(@row.size, enum.size) - enum.each do |pair| - assert_equal(ary.first.first, pair.first) - assert_equal(ary.shift.last, pair.last) - end - end - - def test_each_pair - assert_equal([ - ["A", 1], - ["B", 2], - ["C", 3], - ["A", 4], - ["A", nil], - ], - @row.each_pair.to_a) - end - - def test_enumerable - assert_equal( [["A", 1], ["A", 4], ["A", nil]], - @row.select { |pair| pair.first == "A" } ) - - assert_equal(10, @row.inject(0) { |sum, (_, n)| sum + (n || 0) }) - end - - def test_to_a - row = CSV::Row.new(%w{A B C}, [1, 2, 3]).to_a - assert_instance_of(Array, row) - row.each do |pair| - assert_instance_of(Array, pair) - assert_equal(2, pair.size) - end - assert_equal([["A", 1], ["B", 2], ["C", 3]], row) - end - - def test_to_hash - hash = @row.to_hash - assert_equal({"A" => @row["A"], "B" => @row["B"], "C" => @row["C"]}, hash) - hash.keys.each_with_index do |string_key, h| - assert_predicate(string_key, :frozen?) - assert_same(string_key, @row.headers[h]) - end - end - - def test_to_csv - # normal conversion - assert_equal("1,2,3,4,\n", @row.to_csv) - assert_equal("1,2,3,4,\n", @row.to_s) # alias - - # with options - assert_equal( "1|2|3|4|\r\n", - @row.to_csv(col_sep: "|", row_sep: "\r\n") ) - end - - def test_array_delegation - assert_not_empty(@row, "Row was empty.") - - assert_equal([@row.headers.size, @row.fields.size].max, @row.size) - end - - def test_inspect_shows_header_field_pairs - str = @row.inspect - @row.each do |header, field| - assert_include(str, "#{header.inspect}:#{field.inspect}", - "Header field pair not found.") - end - end - - def test_inspect_encoding_is_ascii_compatible - assert_send([Encoding, :compatible?, - Encoding.find("US-ASCII"), - @row.inspect.encoding], - "inspect() was not ASCII compatible.") - end - - def test_inspect_shows_symbol_headers_as_bare_attributes - str = CSV::Row.new(@row.headers.map { |h| h.to_sym }, @row.fields).inspect - @row.each do |header, field| - assert_include(str, "#{header}:#{field.inspect}", - "Header field pair not found.") - end - end - - def test_can_be_compared_with_other_classes - assert_not_nil(CSV::Row.new([ ], [ ]), "The row was nil") - end - - def test_can_be_compared_when_not_a_row - r = @row == [] - assert_equal false, r - end - - def test_dig_by_index - assert_equal(2, @row.dig(1)) - - assert_nil(@row.dig(100)) - end - - def test_dig_by_header - assert_equal(2, @row.dig("B")) - - assert_nil(@row.dig("Missing")) - end - - def test_dig_cell - row = CSV::Row.new(%w{A}, [["foo", ["bar", ["baz"]]]]) - - assert_equal("foo", row.dig(0, 0)) - assert_equal("bar", row.dig(0, 1, 0)) - - assert_equal("foo", row.dig("A", 0)) - assert_equal("bar", row.dig("A", 1, 0)) - end - - def test_dig_cell_no_dig - row = CSV::Row.new(%w{A}, ["foo"]) - - assert_raise(TypeError) do - row.dig(0, 0) - end - assert_raise(TypeError) do - row.dig("A", 0) - end - end - - def test_dup - row = CSV::Row.new(["A"], ["foo"]) - dupped_row = row.dup - dupped_row["A"] = "bar" - assert_equal(["foo", "bar"], - [row["A"], dupped_row["A"]]) - dupped_row.delete("A") - assert_equal(["foo", nil], - [row["A"], dupped_row["A"]]) - end -end diff --git a/test/csv/test_table.rb b/test/csv/test_table.rb deleted file mode 100644 index e8ab74044e0913..00000000000000 --- a/test/csv/test_table.rb +++ /dev/null @@ -1,691 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false - -require_relative "helper" - -class TestCSVTable < Test::Unit::TestCase - extend DifferentOFS - - def setup - super - @rows = [ CSV::Row.new(%w{A B C}, [1, 2, 3]), - CSV::Row.new(%w{A B C}, [4, 5, 6]), - CSV::Row.new(%w{A B C}, [7, 8, 9]) ] - @table = CSV::Table.new(@rows) - - @header_table = CSV::Table.new( - [CSV::Row.new(%w{A B C}, %w{A B C}, true)] + @rows - ) - - @header_only_table = CSV::Table.new([], headers: %w{A B C}) - end - - def test_initialize - assert_not_nil(@table) - assert_instance_of(CSV::Table, @table) - end - - def test_modes - assert_equal(:col_or_row, @table.mode) - - # non-destructive changes, intended for one shot calls - cols = @table.by_col - assert_equal(:col_or_row, @table.mode) - assert_equal(:col, cols.mode) - assert_equal(@table, cols) - - rows = @table.by_row - assert_equal(:col_or_row, @table.mode) - assert_equal(:row, rows.mode) - assert_equal(@table, rows) - - col_or_row = rows.by_col_or_row - assert_equal(:row, rows.mode) - assert_equal(:col_or_row, col_or_row.mode) - assert_equal(@table, col_or_row) - - # destructive mode changing calls - assert_equal(@table, @table.by_row!) - assert_equal(:row, @table.mode) - assert_equal(@table, @table.by_col_or_row!) - assert_equal(:col_or_row, @table.mode) - end - - def test_headers - assert_equal(@rows.first.headers, @table.headers) - end - - def test_headers_empty - t = CSV::Table.new([]) - assert_equal Array.new, t.headers - end - - def test_headers_only - assert_equal(%w[A B C], @header_only_table.headers) - end - - def test_headers_modified_by_row - table = CSV::Table.new([], headers: ["A", "B"]) - table << ["a", "b"] - table.first << {"C" => "c"} - assert_equal(["A", "B", "C"], table.headers) - end - - def test_index - ################## - ### Mixed Mode ### - ################## - # by row - @rows.each_index { |i| assert_equal(@rows[i], @table[i]) } - assert_equal(nil, @table[100]) # empty row - - # by row with Range - assert_equal([@table[1], @table[2]], @table[1..2]) - - # by col - @rows.first.headers.each do |header| - assert_equal(@rows.map { |row| row[header] }, @table[header]) - end - assert_equal([nil] * @rows.size, @table["Z"]) # empty col - - # by cell, row then col - assert_equal(2, @table[0][1]) - assert_equal(6, @table[1]["C"]) - - # by cell, col then row - assert_equal(5, @table["B"][1]) - assert_equal(9, @table["C"][2]) - - # with headers (by col) - assert_equal(["B", 2, 5, 8], @header_table["B"]) - - ################### - ### Column Mode ### - ################### - @table.by_col! - - assert_equal([2, 5, 8], @table[1]) - assert_equal([2, 5, 8], @table["B"]) - - ################ - ### Row Mode ### - ################ - @table.by_row! - - assert_equal(@rows[1], @table[1]) - assert_raise(TypeError) { @table["B"] } - - ############################ - ### One Shot Mode Change ### - ############################ - assert_equal(@rows[1], @table[1]) - assert_equal([2, 5, 8], @table.by_col[1]) - assert_equal(@rows[1], @table[1]) - end - - def test_set_row_or_column - ################## - ### Mixed Mode ### - ################## - # set row - @table[2] = [10, 11, 12] - assert_equal([%w[A B C], [1, 2, 3], [4, 5, 6], [10, 11, 12]], @table.to_a) - - @table[3] = CSV::Row.new(%w[A B C], [13, 14, 15]) - assert_equal( [%w[A B C], [1, 2, 3], [4, 5, 6], [10, 11, 12], [13, 14, 15]], - @table.to_a ) - - # set col - @table["Type"] = "data" - assert_equal( [ %w[A B C Type], - [1, 2, 3, "data"], - [4, 5, 6, "data"], - [10, 11, 12, "data"], - [13, 14, 15, "data"] ], - @table.to_a ) - - @table["Index"] = [1, 2, 3] - assert_equal( [ %w[A B C Type Index], - [1, 2, 3, "data", 1], - [4, 5, 6, "data", 2], - [10, 11, 12, "data", 3], - [13, 14, 15, "data", nil] ], - @table.to_a ) - - @table["B"] = [100, 200] - assert_equal( [ %w[A B C Type Index], - [1, 100, 3, "data", 1], - [4, 200, 6, "data", 2], - [10, nil, 12, "data", 3], - [13, nil, 15, "data", nil] ], - @table.to_a ) - - # verify resulting table - assert_equal(<<-CSV, @table.to_csv) -A,B,C,Type,Index -1,100,3,data,1 -4,200,6,data,2 -10,,12,data,3 -13,,15,data, - CSV - - # with headers - @header_table["Type"] = "data" - assert_equal(%w[Type data data data], @header_table["Type"]) - - ################### - ### Column Mode ### - ################### - @table.by_col! - - @table[1] = [2, 5, 11, 14] - assert_equal( [ %w[A B C Type Index], - [1, 2, 3, "data", 1], - [4, 5, 6, "data", 2], - [10, 11, 12, "data", 3], - [13, 14, 15, "data", nil] ], - @table.to_a ) - - @table["Extra"] = "new stuff" - assert_equal( [ %w[A B C Type Index Extra], - [1, 2, 3, "data", 1, "new stuff"], - [4, 5, 6, "data", 2, "new stuff"], - [10, 11, 12, "data", 3, "new stuff"], - [13, 14, 15, "data", nil, "new stuff"] ], - @table.to_a ) - - ################ - ### Row Mode ### - ################ - @table.by_row! - - @table[1] = (1..6).to_a - assert_equal( [ %w[A B C Type Index Extra], - [1, 2, 3, "data", 1, "new stuff"], - [1, 2, 3, 4, 5, 6], - [10, 11, 12, "data", 3, "new stuff"], - [13, 14, 15, "data", nil, "new stuff"] ], - @table.to_a ) - - assert_raise(TypeError) { @table["Extra"] = nil } - end - - def test_set_by_col_with_header_row - r = [ CSV::Row.new(%w{X Y Z}, [97, 98, 99], true) ] - t = CSV::Table.new(r) - t.by_col! - t['A'] = [42] - assert_equal(['A'], t['A']) - end - - def test_each - ###################### - ### Mixed/Row Mode ### - ###################### - i = 0 - @table.each do |row| - assert_equal(@rows[i], row) - i += 1 - end - - # verify that we can chain the call - assert_equal(@table, @table.each { }) - - # without block - enum = @table.each - assert_instance_of(Enumerator, enum) - assert_equal(@table.size, enum.size) - - i = 0 - enum.each do |row| - assert_equal(@rows[i], row) - i += 1 - end - - ################### - ### Column Mode ### - ################### - @table.by_col! - - headers = @table.headers - @table.each do |header, column| - assert_equal(headers.shift, header) - assert_equal(@table[header], column) - end - - # without block - enum = @table.each - assert_instance_of(Enumerator, enum) - assert_equal(@table.headers.size, enum.size) - - headers = @table.headers - enum.each do |header, column| - assert_equal(headers.shift, header) - assert_equal(@table[header], column) - end - - ############################ - ### One Shot Mode Change ### - ############################ - @table.by_col_or_row! - - @table.each { |row| assert_instance_of(CSV::Row, row) } - @table.by_col.each { |tuple| assert_instance_of(Array, tuple) } - @table.each { |row| assert_instance_of(CSV::Row, row) } - end - - def test_each_by_col_duplicated_headers - table = CSV.parse(<<-CSV, headers: true) -a,a,,,b -1,2,3,4,5 -11,12,13,14,15 - CSV - assert_equal([ - ["a", ["1", "11"]], - ["a", ["2", "12"]], - [nil, ["3", "13"]], - [nil, ["4", "14"]], - ["b", ["5", "15"]], - ], - table.by_col.each.to_a) - end - - def test_each_split - yielded_values = [] - @table.each do |column1, column2, column3| - yielded_values << [column1, column2, column3] - end - assert_equal(@rows.collect(&:to_a), - yielded_values) - end - - def test_enumerable - assert_equal( @rows.values_at(0, 2), - @table.select { |row| (row["B"] % 2).zero? } ) - - assert_equal(@rows[1], @table.find { |row| row["C"] > 5 }) - end - - def test_to_a - assert_equal([%w[A B C], [1, 2, 3], [4, 5, 6], [7, 8, 9]], @table.to_a) - - # with headers - assert_equal( [%w[A B C], [1, 2, 3], [4, 5, 6], [7, 8, 9]], - @header_table.to_a ) - end - - def test_to_csv - csv = <<-CSV -A,B,C -1,2,3 -4,5,6 -7,8,9 - CSV - - # normal conversion - assert_equal(csv, @table.to_csv) - assert_equal(csv, @table.to_s) # alias - - # with options - assert_equal( csv.gsub(",", "|").gsub("\n", "\r\n"), - @table.to_csv(col_sep: "|", row_sep: "\r\n") ) - assert_equal( csv.lines.to_a[1..-1].join(''), - @table.to_csv(:write_headers => false) ) - - # with headers - assert_equal(csv, @header_table.to_csv) - end - - def test_to_csv_limit_positive - assert_equal(<<-CSV, @table.to_csv(limit: 2)) -A,B,C -1,2,3 -4,5,6 - CSV - end - - def test_to_csv_limit_positive_over - assert_equal(<<-CSV, @table.to_csv(limit: 5)) -A,B,C -1,2,3 -4,5,6 -7,8,9 - CSV - end - - def test_to_csv_limit_zero - assert_equal(<<-CSV, @table.to_csv(limit: 0)) -A,B,C - CSV - end - - def test_to_csv_limit_negative - assert_equal(<<-CSV, @table.to_csv(limit: -2)) -A,B,C -1,2,3 -4,5,6 - CSV - end - - def test_to_csv_limit_negative_over - assert_equal(<<-CSV, @table.to_csv(limit: -5)) -A,B,C - CSV - end - - def test_append - # verify that we can chain the call - assert_equal(@table, @table << [10, 11, 12]) - - # Array append - assert_equal(CSV::Row.new(%w[A B C], [10, 11, 12]), @table[-1]) - - # Row append - assert_equal(@table, @table << CSV::Row.new(%w[A B C], [13, 14, 15])) - assert_equal(CSV::Row.new(%w[A B C], [13, 14, 15]), @table[-1]) - end - - def test_delete_mixed_one - ################## - ### Mixed Mode ### - ################## - # delete a row - assert_equal(@rows[1], @table.delete(1)) - - # delete a col - assert_equal(@rows.map { |row| row["A"] }, @table.delete("A")) - - # verify resulting table - assert_equal(<<-CSV, @table.to_csv) -B,C -2,3 -8,9 - CSV - end - - def test_delete_mixed_multiple - ################## - ### Mixed Mode ### - ################## - # delete row and col - second_row = @rows[1] - a_col = @rows.map { |row| row["A"] } - a_col_without_second_row = a_col[0..0] + a_col[2..-1] - assert_equal([ - second_row, - a_col_without_second_row, - ], - @table.delete(1, "A")) - - # verify resulting table - assert_equal(<<-CSV, @table.to_csv) -B,C -2,3 -8,9 - CSV - end - - def test_delete_column - ################### - ### Column Mode ### - ################### - @table.by_col! - - assert_equal(@rows.map { |row| row[0] }, @table.delete(0)) - assert_equal(@rows.map { |row| row["C"] }, @table.delete("C")) - - # verify resulting table - assert_equal(<<-CSV, @table.to_csv) -B -2 -5 -8 - CSV - end - - def test_delete_row - ################ - ### Row Mode ### - ################ - @table.by_row! - - assert_equal(@rows[1], @table.delete(1)) - assert_raise(TypeError) { @table.delete("C") } - - # verify resulting table - assert_equal(<<-CSV, @table.to_csv) -A,B,C -1,2,3 -7,8,9 - CSV - end - - def test_delete_with_blank_rows - data = "col1,col2\nra1,ra2\n\nrb1,rb2" - table = CSV.parse(data, :headers => true) - assert_equal(["ra2", nil, "rb2"], table.delete("col2")) - end - - def test_delete_if_row - ###################### - ### Mixed/Row Mode ### - ###################### - # verify that we can chain the call - assert_equal(@table, @table.delete_if { |row| (row["B"] % 2).zero? }) - - # verify resulting table - assert_equal(<<-CSV, @table.to_csv) -A,B,C -4,5,6 - CSV - end - - def test_delete_if_row_without_block - ###################### - ### Mixed/Row Mode ### - ###################### - enum = @table.delete_if - assert_instance_of(Enumerator, enum) - assert_equal(@table.size, enum.size) - - # verify that we can chain the call - assert_equal(@table, enum.each { |row| (row["B"] % 2).zero? }) - - # verify resulting table - assert_equal(<<-CSV, @table.to_csv) -A,B,C -4,5,6 - CSV - end - - def test_delete_if_column - ################### - ### Column Mode ### - ################### - @table.by_col! - - assert_equal(@table, @table.delete_if { |h, v| h > "A" }) - assert_equal(<<-CSV, @table.to_csv) -A -1 -4 -7 - CSV - end - - def test_delete_if_column_without_block - ################### - ### Column Mode ### - ################### - @table.by_col! - - enum = @table.delete_if - assert_instance_of(Enumerator, enum) - assert_equal(@table.headers.size, enum.size) - - assert_equal(@table, enum.each { |h, v| h > "A" }) - assert_equal(<<-CSV, @table.to_csv) -A -1 -4 -7 - CSV - end - - def test_delete_headers_only - ################### - ### Column Mode ### - ################### - @header_only_table.by_col! - - # delete by index - assert_equal([], @header_only_table.delete(0)) - assert_equal(%w[B C], @header_only_table.headers) - - # delete by header - assert_equal([], @header_only_table.delete("C")) - assert_equal(%w[B], @header_only_table.headers) - end - - def test_values_at - ################## - ### Mixed Mode ### - ################## - # rows - assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2)) - assert_equal(@rows.values_at(1..2), @table.values_at(1..2)) - - # cols - assert_equal([[1, 3], [4, 6], [7, 9]], @table.values_at("A", "C")) - assert_equal([[2, 3], [5, 6], [8, 9]], @table.values_at("B".."C")) - - ################### - ### Column Mode ### - ################### - @table.by_col! - - assert_equal([[1, 3], [4, 6], [7, 9]], @table.values_at(0, 2)) - assert_equal([[1, 3], [4, 6], [7, 9]], @table.values_at("A", "C")) - - ################ - ### Row Mode ### - ################ - @table.by_row! - - assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2)) - assert_raise(TypeError) { @table.values_at("A", "C") } - - ############################ - ### One Shot Mode Change ### - ############################ - assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2)) - assert_equal([[1, 3], [4, 6], [7, 9]], @table.by_col.values_at(0, 2)) - assert_equal(@rows.values_at(0, 2), @table.values_at(0, 2)) - end - - def test_array_delegation - assert_not_empty(@table, "Table was empty.") - - assert_equal(@rows.size, @table.size) - end - - def test_inspect_shows_current_mode - str = @table.inspect - assert_include(str, "mode:#{@table.mode}", "Mode not shown.") - - @table.by_col! - str = @table.inspect - assert_include(str, "mode:#{@table.mode}", "Mode not shown.") - end - - def test_inspect_encoding_is_ascii_compatible - assert_send([Encoding, :compatible?, - Encoding.find("US-ASCII"), - @table.inspect.encoding], - "inspect() was not ASCII compatible." ) - end - - def test_inspect_with_rows - additional_rows = [ CSV::Row.new(%w{A B C}, [101, 102, 103]), - CSV::Row.new(%w{A B C}, [104, 105, 106]), - CSV::Row.new(%w{A B C}, [107, 108, 109]) ] - table = CSV::Table.new(@rows + additional_rows) - str_table = table.inspect - - assert_equal(<<-CSV, str_table) -# -A,B,C -1,2,3 -4,5,6 -7,8,9 -101,102,103 -104,105,106 - CSV - end - - def test_dig_mixed - # by row - assert_equal(@rows[0], @table.dig(0)) - assert_nil(@table.dig(100)) # empty row - - # by col - assert_equal([2, 5, 8], @table.dig("B")) - assert_equal([nil] * @rows.size, @table.dig("Z")) # empty col - - # by row then col - assert_equal(2, @table.dig(0, 1)) - assert_equal(6, @table.dig(1, "C")) - - # by col then row - assert_equal(5, @table.dig("B", 1)) - assert_equal(9, @table.dig("C", 2)) - end - - def test_dig_by_column - @table.by_col! - - assert_equal([2, 5, 8], @table.dig(1)) - assert_equal([2, 5, 8], @table.dig("B")) - - # by col then row - assert_equal(5, @table.dig("B", 1)) - assert_equal(9, @table.dig("C", 2)) - end - - def test_dig_by_row - @table.by_row! - - assert_equal(@rows[1], @table.dig(1)) - assert_raise(TypeError) { @table.dig("B") } - - # by row then col - assert_equal(2, @table.dig(0, 1)) - assert_equal(6, @table.dig(1, "C")) - end - - def test_dig_cell - table = CSV::Table.new([CSV::Row.new(["A"], [["foo", ["bar", ["baz"]]]])]) - - # by row, col then cell - assert_equal("foo", table.dig(0, "A", 0)) - assert_equal(["baz"], table.dig(0, "A", 1, 1)) - - # by col, row then cell - assert_equal("foo", table.dig("A", 0, 0)) - assert_equal(["baz"], table.dig("A", 0, 1, 1)) - end - - def test_dig_cell_no_dig - table = CSV::Table.new([CSV::Row.new(["A"], ["foo"])]) - - # by row, col then cell - assert_raise(TypeError) do - table.dig(0, "A", 0) - end - - # by col, row then cell - assert_raise(TypeError) do - table.dig("A", 0, 0) - end - end -end diff --git a/test/csv/write/test_converters.rb b/test/csv/write/test_converters.rb deleted file mode 100644 index 0e0080b4c5cb73..00000000000000 --- a/test/csv/write/test_converters.rb +++ /dev/null @@ -1,53 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false - -require_relative "../helper" - -module TestCSVWriteConverters - def test_one - assert_equal(%Q[=a,=b,=c\n], - generate_line(["a", "b", "c"], - write_converters: ->(value) {"=" + value})) - end - - def test_multiple - assert_equal(%Q[=a_,=b_,=c_\n], - generate_line(["a", "b", "c"], - write_converters: [ - ->(value) {"=" + value}, - ->(value) {value + "_"}, - ])) - end - - def test_nil_value - assert_equal(%Q[a,NaN,29\n], - generate_line(["a", nil, 29], - write_nil_value: "NaN")) - end - - def test_empty_value - assert_equal(%Q[a,,29\n], - generate_line(["a", "", 29], - write_empty_value: nil)) - end -end - -class TestCSVWriteConvertersGenerateLine < Test::Unit::TestCase - include TestCSVWriteConverters - extend DifferentOFS - - def generate_line(row, **kwargs) - CSV.generate_line(row, **kwargs) - end -end - -class TestCSVWriteConvertersGenerate < Test::Unit::TestCase - include TestCSVWriteConverters - extend DifferentOFS - - def generate_line(row, **kwargs) - CSV.generate(**kwargs) do |csv| - csv << row - end - end -end diff --git a/test/csv/write/test_force_quotes.rb b/test/csv/write/test_force_quotes.rb deleted file mode 100644 index 622dcb021b4e37..00000000000000 --- a/test/csv/write/test_force_quotes.rb +++ /dev/null @@ -1,78 +0,0 @@ -# frozen_string_literal: false - -require_relative "../helper" - -module TestCSVWriteForceQuotes - def test_default - assert_equal(%Q[1,2,3#{$INPUT_RECORD_SEPARATOR}], - generate_line(["1", "2", "3"])) - end - - def test_true - assert_equal(%Q["1","2","3"#{$INPUT_RECORD_SEPARATOR}], - generate_line(["1", "2", "3"], - force_quotes: true)) - end - - def test_false - assert_equal(%Q[1,2,3#{$INPUT_RECORD_SEPARATOR}], - generate_line(["1", "2", "3"], - force_quotes: false)) - end - - def test_field_name - assert_equal(%Q["1",2,"3"#{$INPUT_RECORD_SEPARATOR}], - generate_line(["1", "2", "3"], - headers: ["a", "b", "c"], - force_quotes: ["a", :c])) - end - - def test_field_name_without_headers - force_quotes = ["a", "c"] - error = assert_raise(ArgumentError) do - generate_line(["1", "2", "3"], - force_quotes: force_quotes) - end - assert_equal(":headers is required when you use field name " + - "in :force_quotes: " + - "#{force_quotes.first.inspect}: #{force_quotes.inspect}", - error.message) - end - - def test_field_index - assert_equal(%Q["1",2,"3"#{$INPUT_RECORD_SEPARATOR}], - generate_line(["1", "2", "3"], - force_quotes: [0, 2])) - end - - def test_field_unknown - force_quotes = [1.1] - error = assert_raise(ArgumentError) do - generate_line(["1", "2", "3"], - force_quotes: force_quotes) - end - assert_equal(":force_quotes element must be field index or field name: " + - "#{force_quotes.first.inspect}: #{force_quotes.inspect}", - error.message) - end -end - -class TestCSVWriteForceQuotesGenerateLine < Test::Unit::TestCase - include TestCSVWriteForceQuotes - extend DifferentOFS - - def generate_line(row, **kwargs) - CSV.generate_line(row, **kwargs) - end -end - -class TestCSVWriteForceQuotesGenerate < Test::Unit::TestCase - include TestCSVWriteForceQuotes - extend DifferentOFS - - def generate_line(row, **kwargs) - CSV.generate(**kwargs) do |csv| - csv << row - end - end -end diff --git a/test/csv/write/test_general.rb b/test/csv/write/test_general.rb deleted file mode 100644 index 4788d99e81507b..00000000000000 --- a/test/csv/write/test_general.rb +++ /dev/null @@ -1,246 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false - -require_relative "../helper" - -module TestCSVWriteGeneral - include CSVHelper - - def test_tab - assert_equal("\t#{$INPUT_RECORD_SEPARATOR}", - generate_line(["\t"])) - end - - def test_quote_character - assert_equal(%Q[foo,"""",baz#{$INPUT_RECORD_SEPARATOR}], - generate_line(["foo", %Q["], "baz"])) - end - - def test_quote_character_double - assert_equal(%Q[foo,"""""",baz#{$INPUT_RECORD_SEPARATOR}], - generate_line(["foo", %Q[""], "baz"])) - end - - def test_quote - assert_equal(%Q[foo,"""bar""",baz#{$INPUT_RECORD_SEPARATOR}], - generate_line(["foo", %Q["bar"], "baz"])) - end - - def test_quote_lf - assert_equal(%Q["""\n","""\n"#{$INPUT_RECORD_SEPARATOR}], - generate_line([%Q["\n], %Q["\n]])) - end - - def test_quote_cr - assert_equal(%Q["""\r","""\r"#{$INPUT_RECORD_SEPARATOR}], - generate_line([%Q["\r], %Q["\r]])) - end - - def test_quote_last - assert_equal(%Q[foo,"bar"""#{$INPUT_RECORD_SEPARATOR}], - generate_line(["foo", %Q[bar"]])) - end - - def test_quote_lf_last - assert_equal(%Q[foo,"\nbar"""#{$INPUT_RECORD_SEPARATOR}], - generate_line(["foo", %Q[\nbar"]])) - end - - def test_quote_lf_value_lf - assert_equal(%Q[foo,"""\nbar\n"""#{$INPUT_RECORD_SEPARATOR}], - generate_line(["foo", %Q["\nbar\n"]])) - end - - def test_quote_lf_value_lf_nil - assert_equal(%Q[foo,"""\nbar\n""",#{$INPUT_RECORD_SEPARATOR}], - generate_line(["foo", %Q["\nbar\n"], nil])) - end - - def test_cr - assert_equal(%Q[foo,"\r",baz#{$INPUT_RECORD_SEPARATOR}], - generate_line(["foo", "\r", "baz"])) - end - - def test_lf - assert_equal(%Q[foo,"\n",baz#{$INPUT_RECORD_SEPARATOR}], - generate_line(["foo", "\n", "baz"])) - end - - def test_cr_lf - assert_equal(%Q[foo,"\r\n",baz#{$INPUT_RECORD_SEPARATOR}], - generate_line(["foo", "\r\n", "baz"])) - end - - def test_cr_dot_lf - assert_equal(%Q[foo,"\r.\n",baz#{$INPUT_RECORD_SEPARATOR}], - generate_line(["foo", "\r.\n", "baz"])) - end - - def test_cr_lf_cr - assert_equal(%Q[foo,"\r\n\r",baz#{$INPUT_RECORD_SEPARATOR}], - generate_line(["foo", "\r\n\r", "baz"])) - end - - def test_cr_lf_lf - assert_equal(%Q[foo,"\r\n\n",baz#{$INPUT_RECORD_SEPARATOR}], - generate_line(["foo", "\r\n\n", "baz"])) - end - - def test_cr_lf_comma - assert_equal(%Q["\r\n,"#{$INPUT_RECORD_SEPARATOR}], - generate_line(["\r\n,"])) - end - - def test_cr_lf_comma_nil - assert_equal(%Q["\r\n,",#{$INPUT_RECORD_SEPARATOR}], - generate_line(["\r\n,", nil])) - end - - def test_comma - assert_equal(%Q[","#{$INPUT_RECORD_SEPARATOR}], - generate_line([","])) - end - - def test_comma_double - assert_equal(%Q[",",","#{$INPUT_RECORD_SEPARATOR}], - generate_line([",", ","])) - end - - def test_comma_and_value - assert_equal(%Q[foo,"foo,bar",baz#{$INPUT_RECORD_SEPARATOR}], - generate_line(["foo", "foo,bar", "baz"])) - end - - def test_one_element - assert_equal(%Q[foo#{$INPUT_RECORD_SEPARATOR}], - generate_line(["foo"])) - end - - def test_nil_values_only - assert_equal(%Q[,,#{$INPUT_RECORD_SEPARATOR}], - generate_line([nil, nil, nil])) - end - - def test_nil_double_only - assert_equal(%Q[,#{$INPUT_RECORD_SEPARATOR}], - generate_line([nil, nil])) - end - - def test_nil_values - assert_equal(%Q[foo,,,#{$INPUT_RECORD_SEPARATOR}], - generate_line(["foo", nil, nil, nil])) - end - - def test_nil_value_first - assert_equal(%Q[,foo,baz#{$INPUT_RECORD_SEPARATOR}], - generate_line([nil, "foo", "baz"])) - end - - def test_nil_value_middle - assert_equal(%Q[foo,,baz#{$INPUT_RECORD_SEPARATOR}], - generate_line(["foo", nil, "baz"])) - end - - def test_nil_value_last - assert_equal(%Q[foo,baz,#{$INPUT_RECORD_SEPARATOR}], - generate_line(["foo", "baz", nil])) - end - - def test_nil_empty - assert_equal(%Q[,""#{$INPUT_RECORD_SEPARATOR}], - generate_line([nil, ""])) - end - - def test_nil_cr - assert_equal(%Q[,"\r"#{$INPUT_RECORD_SEPARATOR}], - generate_line([nil, "\r"])) - end - - def test_values - assert_equal(%Q[foo,bar#{$INPUT_RECORD_SEPARATOR}], - generate_line(["foo", "bar"])) - end - - def test_semi_colon - assert_equal(%Q[;#{$INPUT_RECORD_SEPARATOR}], - generate_line([";"])) - end - - def test_semi_colon_values - assert_equal(%Q[;,;#{$INPUT_RECORD_SEPARATOR}], - generate_line([";", ";"])) - end - - def test_tab_values - assert_equal(%Q[\t,\t#{$INPUT_RECORD_SEPARATOR}], - generate_line(["\t", "\t"])) - end - - def test_col_sep - assert_equal(%Q[a;b;;c#{$INPUT_RECORD_SEPARATOR}], - generate_line(["a", "b", nil, "c"], - col_sep: ";")) - assert_equal(%Q[a\tb\t\tc#{$INPUT_RECORD_SEPARATOR}], - generate_line(["a", "b", nil, "c"], - col_sep: "\t")) - end - - def test_row_sep - assert_equal(%Q[a,b,,c\r\n], - generate_line(["a", "b", nil, "c"], - row_sep: "\r\n")) - end - - def test_force_quotes - assert_equal(%Q["1","b","","already ""quoted"""#{$INPUT_RECORD_SEPARATOR}], - generate_line([1, "b", nil, %Q{already "quoted"}], - force_quotes: true)) - end - - def test_encoding_utf8 - assert_equal(%Q[あ,い,う#{$INPUT_RECORD_SEPARATOR}], - generate_line(["あ" , "い", "う"])) - end - - def test_encoding_euc_jp - row = ["あ", "い", "う"].collect {|field| field.encode("EUC-JP")} - assert_equal(%Q[あ,い,う#{$INPUT_RECORD_SEPARATOR}].encode("EUC-JP"), - generate_line(row)) - end - - def test_encoding_with_default_internal - with_default_internal(Encoding::UTF_8) do - row = ["あ", "い", "う"].collect {|field| field.encode("EUC-JP")} - assert_equal(%Q[あ,い,う#{$INPUT_RECORD_SEPARATOR}].encode("EUC-JP"), - generate_line(row, encoding: Encoding::EUC_JP)) - end - end - - def test_with_default_internal - with_default_internal(Encoding::UTF_8) do - row = ["あ", "い", "う"].collect {|field| field.encode("EUC-JP")} - assert_equal(%Q[あ,い,う#{$INPUT_RECORD_SEPARATOR}].encode("EUC-JP"), - generate_line(row)) - end - end -end - -class TestCSVWriteGeneralGenerateLine < Test::Unit::TestCase - include TestCSVWriteGeneral - extend DifferentOFS - - def generate_line(row, **kwargs) - CSV.generate_line(row, **kwargs) - end -end - -class TestCSVWriteGeneralGenerate < Test::Unit::TestCase - include TestCSVWriteGeneral - extend DifferentOFS - - def generate_line(row, **kwargs) - CSV.generate(**kwargs) do |csv| - csv << row - end - end -end diff --git a/test/csv/write/test_quote_empty.rb b/test/csv/write/test_quote_empty.rb deleted file mode 100644 index 70f73dad4ab0e2..00000000000000 --- a/test/csv/write/test_quote_empty.rb +++ /dev/null @@ -1,70 +0,0 @@ -# -*- coding: utf-8 -*- -# frozen_string_literal: false - -require_relative "../helper" - -module TestCSVWriteQuoteEmpty - def test_quote_empty_default - assert_equal(%Q["""",""#{$INPUT_RECORD_SEPARATOR}], - generate_line([%Q["], ""])) - end - - def test_quote_empty_false - assert_equal(%Q["""",#{$INPUT_RECORD_SEPARATOR}], - generate_line([%Q["], ""], - quote_empty: false)) - end - - def test_empty_default - assert_equal(%Q[foo,"",baz#{$INPUT_RECORD_SEPARATOR}], - generate_line(["foo", "", "baz"])) - end - - def test_empty_false - assert_equal(%Q[foo,,baz#{$INPUT_RECORD_SEPARATOR}], - generate_line(["foo", "", "baz"], - quote_empty: false)) - end - - def test_empty_only_default - assert_equal(%Q[""#{$INPUT_RECORD_SEPARATOR}], - generate_line([""])) - end - - def test_empty_only_false - assert_equal(%Q[#{$INPUT_RECORD_SEPARATOR}], - generate_line([""], - quote_empty: false)) - end - - def test_empty_double_default - assert_equal(%Q["",""#{$INPUT_RECORD_SEPARATOR}], - generate_line(["", ""])) - end - - def test_empty_double_false - assert_equal(%Q[,#{$INPUT_RECORD_SEPARATOR}], - generate_line(["", ""], - quote_empty: false)) - end -end - -class TestCSVWriteQuoteEmptyGenerateLine < Test::Unit::TestCase - include TestCSVWriteQuoteEmpty - extend DifferentOFS - - def generate_line(row, **kwargs) - CSV.generate_line(row, **kwargs) - end -end - -class TestCSVWriteQuoteEmptyGenerate < Test::Unit::TestCase - include TestCSVWriteQuoteEmpty - extend DifferentOFS - - def generate_line(row, **kwargs) - CSV.generate(**kwargs) do |csv| - csv << row - end - end -end From f2dce4e6e07abf632357ac105f4ed201e4ee9781 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 22 Jan 2024 17:23:33 +0900 Subject: [PATCH 395/640] spec/mspec/tool/wrap_with_guard.rb 'ruby_version_is ""..."3.4"' spec/ruby/library/csv/**/*.rb --- .../basicwriter/close_on_terminate_spec.rb | 9 +- .../csv/basicwriter/initialize_spec.rb | 9 +- .../library/csv/basicwriter/terminate_spec.rb | 9 +- spec/ruby/library/csv/cell/data_spec.rb | 9 +- spec/ruby/library/csv/cell/initialize_spec.rb | 9 +- spec/ruby/library/csv/foreach_spec.rb | 9 +- spec/ruby/library/csv/generate_line_spec.rb | 45 +++-- spec/ruby/library/csv/generate_row_spec.rb | 9 +- spec/ruby/library/csv/generate_spec.rb | 47 ++--- spec/ruby/library/csv/iobuf/close_spec.rb | 9 +- .../ruby/library/csv/iobuf/initialize_spec.rb | 9 +- spec/ruby/library/csv/iobuf/read_spec.rb | 9 +- spec/ruby/library/csv/iobuf/terminate_spec.rb | 9 +- .../csv/ioreader/close_on_terminate_spec.rb | 9 +- .../ruby/library/csv/ioreader/get_row_spec.rb | 9 +- .../library/csv/ioreader/initialize_spec.rb | 9 +- .../library/csv/ioreader/terminate_spec.rb | 9 +- spec/ruby/library/csv/liberal_parsing_spec.rb | 29 +-- spec/ruby/library/csv/open_spec.rb | 9 +- spec/ruby/library/csv/parse_spec.rb | 181 +++++++++--------- spec/ruby/library/csv/read_spec.rb | 9 +- spec/ruby/library/csv/readlines_spec.rb | 53 ++--- .../library/csv/streambuf/add_buf_spec.rb | 9 +- .../library/csv/streambuf/buf_size_spec.rb | 9 +- spec/ruby/library/csv/streambuf/drop_spec.rb | 9 +- .../csv/streambuf/element_reference_spec.rb | 9 +- spec/ruby/library/csv/streambuf/get_spec.rb | 9 +- .../library/csv/streambuf/idx_is_eos_spec.rb | 9 +- .../library/csv/streambuf/initialize_spec.rb | 9 +- .../ruby/library/csv/streambuf/is_eos_spec.rb | 9 +- spec/ruby/library/csv/streambuf/read_spec.rb | 9 +- .../library/csv/streambuf/rel_buf_spec.rb | 9 +- .../library/csv/streambuf/terminate_spec.rb | 9 +- .../library/csv/stringreader/get_row_spec.rb | 9 +- .../csv/stringreader/initialize_spec.rb | 9 +- spec/ruby/library/csv/writer/add_row_spec.rb | 9 +- spec/ruby/library/csv/writer/append_spec.rb | 9 +- spec/ruby/library/csv/writer/close_spec.rb | 9 +- spec/ruby/library/csv/writer/create_spec.rb | 9 +- spec/ruby/library/csv/writer/generate_spec.rb | 9 +- .../library/csv/writer/initialize_spec.rb | 9 +- .../ruby/library/csv/writer/terminate_spec.rb | 9 +- 42 files changed, 407 insertions(+), 281 deletions(-) diff --git a/spec/ruby/library/csv/basicwriter/close_on_terminate_spec.rb b/spec/ruby/library/csv/basicwriter/close_on_terminate_spec.rb index 599e640624e6ad..d3f667c602e84e 100644 --- a/spec/ruby/library/csv/basicwriter/close_on_terminate_spec.rb +++ b/spec/ruby/library/csv/basicwriter/close_on_terminate_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::BasicWriter#close_on_terminate" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::BasicWriter#close_on_terminate" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/basicwriter/initialize_spec.rb b/spec/ruby/library/csv/basicwriter/initialize_spec.rb index 2c13c93f2eb343..af86bc177bd0f5 100644 --- a/spec/ruby/library/csv/basicwriter/initialize_spec.rb +++ b/spec/ruby/library/csv/basicwriter/initialize_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::BasicWriter#initialize" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::BasicWriter#initialize" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/basicwriter/terminate_spec.rb b/spec/ruby/library/csv/basicwriter/terminate_spec.rb index 8c53db3f0baaf4..5396295a616859 100644 --- a/spec/ruby/library/csv/basicwriter/terminate_spec.rb +++ b/spec/ruby/library/csv/basicwriter/terminate_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::BasicWriter#terminate" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::BasicWriter#terminate" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/cell/data_spec.rb b/spec/ruby/library/csv/cell/data_spec.rb index aa034b0b62e84a..14f49ace96403c 100644 --- a/spec/ruby/library/csv/cell/data_spec.rb +++ b/spec/ruby/library/csv/cell/data_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::Cell#data" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::Cell#data" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/cell/initialize_spec.rb b/spec/ruby/library/csv/cell/initialize_spec.rb index c9e506676ca9e4..ff3ac55470889b 100644 --- a/spec/ruby/library/csv/cell/initialize_spec.rb +++ b/spec/ruby/library/csv/cell/initialize_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::Cell#initialize" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::Cell#initialize" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/foreach_spec.rb b/spec/ruby/library/csv/foreach_spec.rb index 36b3cd152fa07a..c8aa1b8009157b 100644 --- a/spec/ruby/library/csv/foreach_spec.rb +++ b/spec/ruby/library/csv/foreach_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require 'csv' -describe "CSV.foreach" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV.foreach" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/generate_line_spec.rb b/spec/ruby/library/csv/generate_line_spec.rb index 656365b109e9c3..0830bbdb63fdd7 100644 --- a/spec/ruby/library/csv/generate_line_spec.rb +++ b/spec/ruby/library/csv/generate_line_spec.rb @@ -1,30 +1,33 @@ require_relative '../../spec_helper' -require 'csv' -describe "CSV.generate_line" do +ruby_version_is ""..."3.4" do + require 'csv' - it "generates an empty string" do - result = CSV.generate_line([]) - result.should == "\n" - end + describe "CSV.generate_line" do - it "generates the string 'foo,bar'" do - result = CSV.generate_line(["foo", "bar"]) - result.should == "foo,bar\n" - end + it "generates an empty string" do + result = CSV.generate_line([]) + result.should == "\n" + end - it "generates the string 'foo;bar'" do - result = CSV.generate_line(["foo", "bar"], col_sep: ?;) - result.should == "foo;bar\n" - end + it "generates the string 'foo,bar'" do + result = CSV.generate_line(["foo", "bar"]) + result.should == "foo,bar\n" + end - it "generates the string 'foo,,bar'" do - result = CSV.generate_line(["foo", nil, "bar"]) - result.should == "foo,,bar\n" - end + it "generates the string 'foo;bar'" do + result = CSV.generate_line(["foo", "bar"], col_sep: ?;) + result.should == "foo;bar\n" + end + + it "generates the string 'foo,,bar'" do + result = CSV.generate_line(["foo", nil, "bar"]) + result.should == "foo,,bar\n" + end - it "generates the string 'foo;;bar'" do - result = CSV.generate_line(["foo", nil, "bar"], col_sep: ?;) - result.should == "foo;;bar\n" + it "generates the string 'foo;;bar'" do + result = CSV.generate_line(["foo", nil, "bar"], col_sep: ?;) + result.should == "foo;;bar\n" + end end end diff --git a/spec/ruby/library/csv/generate_row_spec.rb b/spec/ruby/library/csv/generate_row_spec.rb index 79dfc34000a22a..aff5332a9e916c 100644 --- a/spec/ruby/library/csv/generate_row_spec.rb +++ b/spec/ruby/library/csv/generate_row_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require 'csv' -describe "CSV.generate_row" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV.generate_row" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/generate_spec.rb b/spec/ruby/library/csv/generate_spec.rb index 0a1e3d9604fa7b..de476d437f28e4 100644 --- a/spec/ruby/library/csv/generate_spec.rb +++ b/spec/ruby/library/csv/generate_spec.rb @@ -1,32 +1,35 @@ require_relative '../../spec_helper' -require 'csv' -require 'tempfile' -describe "CSV.generate" do +ruby_version_is ""..."3.4" do + require 'csv' + require 'tempfile' - it "returns CSV string" do - csv_str = CSV.generate do |csv| - csv.add_row [1, 2, 3] - csv << [4, 5, 6] + describe "CSV.generate" do + + it "returns CSV string" do + csv_str = CSV.generate do |csv| + csv.add_row [1, 2, 3] + csv << [4, 5, 6] + end + csv_str.should == "1,2,3\n4,5,6\n" end - csv_str.should == "1,2,3\n4,5,6\n" - end - it "accepts a col separator" do - csv_str = CSV.generate(col_sep: ";") do |csv| - csv.add_row [1, 2, 3] - csv << [4, 5, 6] + it "accepts a col separator" do + csv_str = CSV.generate(col_sep: ";") do |csv| + csv.add_row [1, 2, 3] + csv << [4, 5, 6] + end + csv_str.should == "1;2;3\n4;5;6\n" end - csv_str.should == "1;2;3\n4;5;6\n" - end - it "appends and returns the argument itself" do - str = "" - csv_str = CSV.generate(str) do |csv| - csv.add_row [1, 2, 3] - csv << [4, 5, 6] + it "appends and returns the argument itself" do + str = "" + csv_str = CSV.generate(str) do |csv| + csv.add_row [1, 2, 3] + csv << [4, 5, 6] + end + csv_str.should equal str + str.should == "1,2,3\n4,5,6\n" end - csv_str.should equal str - str.should == "1,2,3\n4,5,6\n" end end diff --git a/spec/ruby/library/csv/iobuf/close_spec.rb b/spec/ruby/library/csv/iobuf/close_spec.rb index e2fda86080dd79..5711a816ecd2b6 100644 --- a/spec/ruby/library/csv/iobuf/close_spec.rb +++ b/spec/ruby/library/csv/iobuf/close_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::IOBuf#close" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::IOBuf#close" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/iobuf/initialize_spec.rb b/spec/ruby/library/csv/iobuf/initialize_spec.rb index f08e82548a0fdb..0073bd44813be0 100644 --- a/spec/ruby/library/csv/iobuf/initialize_spec.rb +++ b/spec/ruby/library/csv/iobuf/initialize_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::IOBuf#initialize" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::IOBuf#initialize" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/iobuf/read_spec.rb b/spec/ruby/library/csv/iobuf/read_spec.rb index b45334ee2aea4d..e74d8178ddf185 100644 --- a/spec/ruby/library/csv/iobuf/read_spec.rb +++ b/spec/ruby/library/csv/iobuf/read_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::IOBuf#read" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::IOBuf#read" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/iobuf/terminate_spec.rb b/spec/ruby/library/csv/iobuf/terminate_spec.rb index 69289e960c27f1..e4ab00bc4f249c 100644 --- a/spec/ruby/library/csv/iobuf/terminate_spec.rb +++ b/spec/ruby/library/csv/iobuf/terminate_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::IOBuf#terminate" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::IOBuf#terminate" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/ioreader/close_on_terminate_spec.rb b/spec/ruby/library/csv/ioreader/close_on_terminate_spec.rb index 4887ade1a1f64e..25026091aa2ffa 100644 --- a/spec/ruby/library/csv/ioreader/close_on_terminate_spec.rb +++ b/spec/ruby/library/csv/ioreader/close_on_terminate_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::IOReader#close_on_terminate" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::IOReader#close_on_terminate" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/ioreader/get_row_spec.rb b/spec/ruby/library/csv/ioreader/get_row_spec.rb index 5fd2178b1b1002..c2258738d11c56 100644 --- a/spec/ruby/library/csv/ioreader/get_row_spec.rb +++ b/spec/ruby/library/csv/ioreader/get_row_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::IOReader#get_row" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::IOReader#get_row" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/ioreader/initialize_spec.rb b/spec/ruby/library/csv/ioreader/initialize_spec.rb index 4e8c0964dfb54c..4f3a75cc8e356c 100644 --- a/spec/ruby/library/csv/ioreader/initialize_spec.rb +++ b/spec/ruby/library/csv/ioreader/initialize_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::IOReader#initialize" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::IOReader#initialize" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/ioreader/terminate_spec.rb b/spec/ruby/library/csv/ioreader/terminate_spec.rb index 676cd03a0fff81..2403d02a9f23fd 100644 --- a/spec/ruby/library/csv/ioreader/terminate_spec.rb +++ b/spec/ruby/library/csv/ioreader/terminate_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::IOReader#terminate" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::IOReader#terminate" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/liberal_parsing_spec.rb b/spec/ruby/library/csv/liberal_parsing_spec.rb index 98786580271979..d344229d5b991f 100644 --- a/spec/ruby/library/csv/liberal_parsing_spec.rb +++ b/spec/ruby/library/csv/liberal_parsing_spec.rb @@ -1,19 +1,22 @@ require_relative '../../spec_helper' -require 'csv' -describe "CSV#liberal_parsing?" do - it "returns true if illegal input is handled" do - csv = CSV.new("", liberal_parsing: true) - csv.should.liberal_parsing? - end +ruby_version_is ""..."3.4" do + require 'csv' - it "returns false if illegal input is not handled" do - csv = CSV.new("", liberal_parsing: false) - csv.should_not.liberal_parsing? - end + describe "CSV#liberal_parsing?" do + it "returns true if illegal input is handled" do + csv = CSV.new("", liberal_parsing: true) + csv.should.liberal_parsing? + end + + it "returns false if illegal input is not handled" do + csv = CSV.new("", liberal_parsing: false) + csv.should_not.liberal_parsing? + end - it "returns false by default" do - csv = CSV.new("") - csv.should_not.liberal_parsing? + it "returns false by default" do + csv = CSV.new("") + csv.should_not.liberal_parsing? + end end end diff --git a/spec/ruby/library/csv/open_spec.rb b/spec/ruby/library/csv/open_spec.rb index 2d310cda3e58d6..4b5f934e523cc1 100644 --- a/spec/ruby/library/csv/open_spec.rb +++ b/spec/ruby/library/csv/open_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require 'csv' -describe "CSV.open" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV.open" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/parse_spec.rb b/spec/ruby/library/csv/parse_spec.rb index ef5d4ea3ca1f43..921ee0648d4481 100644 --- a/spec/ruby/library/csv/parse_spec.rb +++ b/spec/ruby/library/csv/parse_spec.rb @@ -1,93 +1,96 @@ require_relative '../../spec_helper' -require 'csv' -describe "CSV.parse" do - - it "parses '' into []" do - result = CSV.parse '' - result.should be_kind_of(Array) - result.should == [] - end - - it "parses '\n' into [[]]" do - result = CSV.parse "\n" - result.should == [[]] - end - - it "parses 'foo' into [['foo']]" do - result = CSV.parse 'foo' - result.should == [['foo']] - end - - it "parses 'foo,bar,baz' into [['foo','bar','baz']]" do - result = CSV.parse 'foo,bar,baz' - result.should == [['foo','bar','baz']] - end - - it "parses 'foo,baz' into [[foo,nil,baz]]" do - result = CSV.parse 'foo,,baz' - result.should == [['foo',nil,'baz']] - end - - it "parses '\nfoo' into [[],['foo']]" do - result = CSV.parse "\nfoo" - result.should == [[],['foo']] - end - - it "parses 'foo\n' into [['foo']]" do - result = CSV.parse "foo\n" - result.should == [['foo']] - end - - it "parses 'foo\nbar' into [['foo'],['bar']]" do - result = CSV.parse "foo\nbar" - result.should == [['foo'],['bar']] - end - - it "parses 'foo,bar\nbaz,quz' into [['foo','bar'],['baz','quz']]" do - result = CSV.parse "foo,bar\nbaz,quz" - result.should == [['foo','bar'],['baz','quz']] - end - - it "parses 'foo,bar'\nbaz' into [['foo','bar'],['baz']]" do - result = CSV.parse "foo,bar\nbaz" - result.should == [['foo','bar'],['baz']] - end - - it "parses 'foo\nbar,baz' into [['foo'],['bar','baz']]" do - result = CSV.parse "foo\nbar,baz" - result.should == [['foo'],['bar','baz']] - end - - it "parses '\n\nbar' into [[],[],'bar']]" do - result = CSV.parse "\n\nbar" - result.should == [[],[],['bar']] - end - - it "parses 'foo' into [['foo']] with a separator of ;" do - result = CSV.parse "foo", col_sep: ?; - result.should == [['foo']] - end - - it "parses 'foo;bar' into [['foo','bar']] with a separator of ;" do - result = CSV.parse "foo;bar", col_sep: ?; - result.should == [['foo','bar']] - end - - it "parses 'foo;bar\nbaz;quz' into [['foo','bar'],['baz','quz']] with a separator of ;" do - result = CSV.parse "foo;bar\nbaz;quz", col_sep: ?; - result.should == [['foo','bar'],['baz','quz']] - end - - it "raises CSV::MalformedCSVError exception if input is illegal" do - -> { - CSV.parse('"quoted" field') - }.should raise_error(CSV::MalformedCSVError) - end - - it "handles illegal input with the liberal_parsing option" do - illegal_input = '"Johnson, Dwayne",Dwayne "The Rock" Johnson' - result = CSV.parse(illegal_input, liberal_parsing: true) - result.should == [["Johnson, Dwayne", 'Dwayne "The Rock" Johnson']] +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV.parse" do + + it "parses '' into []" do + result = CSV.parse '' + result.should be_kind_of(Array) + result.should == [] + end + + it "parses '\n' into [[]]" do + result = CSV.parse "\n" + result.should == [[]] + end + + it "parses 'foo' into [['foo']]" do + result = CSV.parse 'foo' + result.should == [['foo']] + end + + it "parses 'foo,bar,baz' into [['foo','bar','baz']]" do + result = CSV.parse 'foo,bar,baz' + result.should == [['foo','bar','baz']] + end + + it "parses 'foo,baz' into [[foo,nil,baz]]" do + result = CSV.parse 'foo,,baz' + result.should == [['foo',nil,'baz']] + end + + it "parses '\nfoo' into [[],['foo']]" do + result = CSV.parse "\nfoo" + result.should == [[],['foo']] + end + + it "parses 'foo\n' into [['foo']]" do + result = CSV.parse "foo\n" + result.should == [['foo']] + end + + it "parses 'foo\nbar' into [['foo'],['bar']]" do + result = CSV.parse "foo\nbar" + result.should == [['foo'],['bar']] + end + + it "parses 'foo,bar\nbaz,quz' into [['foo','bar'],['baz','quz']]" do + result = CSV.parse "foo,bar\nbaz,quz" + result.should == [['foo','bar'],['baz','quz']] + end + + it "parses 'foo,bar'\nbaz' into [['foo','bar'],['baz']]" do + result = CSV.parse "foo,bar\nbaz" + result.should == [['foo','bar'],['baz']] + end + + it "parses 'foo\nbar,baz' into [['foo'],['bar','baz']]" do + result = CSV.parse "foo\nbar,baz" + result.should == [['foo'],['bar','baz']] + end + + it "parses '\n\nbar' into [[],[],'bar']]" do + result = CSV.parse "\n\nbar" + result.should == [[],[],['bar']] + end + + it "parses 'foo' into [['foo']] with a separator of ;" do + result = CSV.parse "foo", col_sep: ?; + result.should == [['foo']] + end + + it "parses 'foo;bar' into [['foo','bar']] with a separator of ;" do + result = CSV.parse "foo;bar", col_sep: ?; + result.should == [['foo','bar']] + end + + it "parses 'foo;bar\nbaz;quz' into [['foo','bar'],['baz','quz']] with a separator of ;" do + result = CSV.parse "foo;bar\nbaz;quz", col_sep: ?; + result.should == [['foo','bar'],['baz','quz']] + end + + it "raises CSV::MalformedCSVError exception if input is illegal" do + -> { + CSV.parse('"quoted" field') + }.should raise_error(CSV::MalformedCSVError) + end + + it "handles illegal input with the liberal_parsing option" do + illegal_input = '"Johnson, Dwayne",Dwayne "The Rock" Johnson' + result = CSV.parse(illegal_input, liberal_parsing: true) + result.should == [["Johnson, Dwayne", 'Dwayne "The Rock" Johnson']] + end end end diff --git a/spec/ruby/library/csv/read_spec.rb b/spec/ruby/library/csv/read_spec.rb index 2e6bb65d56c0d6..e455a40f739902 100644 --- a/spec/ruby/library/csv/read_spec.rb +++ b/spec/ruby/library/csv/read_spec.rb @@ -1,6 +1,9 @@ require_relative '../../spec_helper' -require 'csv' -describe "CSV.read" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV.read" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/readlines_spec.rb b/spec/ruby/library/csv/readlines_spec.rb index 14dea34381da2b..9ca08592522f1c 100644 --- a/spec/ruby/library/csv/readlines_spec.rb +++ b/spec/ruby/library/csv/readlines_spec.rb @@ -1,35 +1,38 @@ require_relative '../../spec_helper' -require 'csv' -describe "CSV.readlines" do - it "needs to be reviewed for spec completeness" -end +ruby_version_is ""..."3.4" do + require 'csv' -describe "CSV#readlines" do - it "returns an Array of Array containing each element in a one-line CSV file" do - file = CSV.new "a, b, c" - file.readlines.should == [["a", " b", " c"]] + describe "CSV.readlines" do + it "needs to be reviewed for spec completeness" end - it "returns an Array of Arrays containing each element in a multi-line CSV file" do - file = CSV.new "a, b, c\nd, e, f" - file.readlines.should == [["a", " b", " c"], ["d", " e", " f"]] - end + describe "CSV#readlines" do + it "returns an Array of Array containing each element in a one-line CSV file" do + file = CSV.new "a, b, c" + file.readlines.should == [["a", " b", " c"]] + end - it "returns nil for a missing value" do - file = CSV.new "a,, b, c" - file.readlines.should == [["a", nil, " b", " c"]] - end + it "returns an Array of Arrays containing each element in a multi-line CSV file" do + file = CSV.new "a, b, c\nd, e, f" + file.readlines.should == [["a", " b", " c"], ["d", " e", " f"]] + end - it "raises CSV::MalformedCSVError exception if input is illegal" do - csv = CSV.new('"quoted" field') - -> { csv.readlines }.should raise_error(CSV::MalformedCSVError) - end + it "returns nil for a missing value" do + file = CSV.new "a,, b, c" + file.readlines.should == [["a", nil, " b", " c"]] + end + + it "raises CSV::MalformedCSVError exception if input is illegal" do + csv = CSV.new('"quoted" field') + -> { csv.readlines }.should raise_error(CSV::MalformedCSVError) + end - it "handles illegal input with the liberal_parsing option" do - illegal_input = '"Johnson, Dwayne",Dwayne "The Rock" Johnson' - csv = CSV.new(illegal_input, liberal_parsing: true) - result = csv.readlines - result.should == [["Johnson, Dwayne", 'Dwayne "The Rock" Johnson']] + it "handles illegal input with the liberal_parsing option" do + illegal_input = '"Johnson, Dwayne",Dwayne "The Rock" Johnson' + csv = CSV.new(illegal_input, liberal_parsing: true) + result = csv.readlines + result.should == [["Johnson, Dwayne", 'Dwayne "The Rock" Johnson']] + end end end diff --git a/spec/ruby/library/csv/streambuf/add_buf_spec.rb b/spec/ruby/library/csv/streambuf/add_buf_spec.rb index 58c530c5007a23..42a9eb68beb450 100644 --- a/spec/ruby/library/csv/streambuf/add_buf_spec.rb +++ b/spec/ruby/library/csv/streambuf/add_buf_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::StreamBuf#add_buf" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::StreamBuf#add_buf" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/streambuf/buf_size_spec.rb b/spec/ruby/library/csv/streambuf/buf_size_spec.rb index 1793c8b65e3e2f..9a9d34bdefa73a 100644 --- a/spec/ruby/library/csv/streambuf/buf_size_spec.rb +++ b/spec/ruby/library/csv/streambuf/buf_size_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::StreamBuf#buf_size" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::StreamBuf#buf_size" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/streambuf/drop_spec.rb b/spec/ruby/library/csv/streambuf/drop_spec.rb index 448f0a2196bb87..befe0da2f8e5e9 100644 --- a/spec/ruby/library/csv/streambuf/drop_spec.rb +++ b/spec/ruby/library/csv/streambuf/drop_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::StreamBuf#drop" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::StreamBuf#drop" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/streambuf/element_reference_spec.rb b/spec/ruby/library/csv/streambuf/element_reference_spec.rb index 5a75901830eddd..5ff42beeeed6b3 100644 --- a/spec/ruby/library/csv/streambuf/element_reference_spec.rb +++ b/spec/ruby/library/csv/streambuf/element_reference_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::StreamBuf#[]" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::StreamBuf#[]" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/streambuf/get_spec.rb b/spec/ruby/library/csv/streambuf/get_spec.rb index 2255e55e918c6d..0aa5e72e8f1e83 100644 --- a/spec/ruby/library/csv/streambuf/get_spec.rb +++ b/spec/ruby/library/csv/streambuf/get_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::StreamBuf#get" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::StreamBuf#get" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/streambuf/idx_is_eos_spec.rb b/spec/ruby/library/csv/streambuf/idx_is_eos_spec.rb index 563b8b2d4ae288..f38cb7d8f8cbf9 100644 --- a/spec/ruby/library/csv/streambuf/idx_is_eos_spec.rb +++ b/spec/ruby/library/csv/streambuf/idx_is_eos_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::StreamBuf#idx_is_eos?" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::StreamBuf#idx_is_eos?" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/streambuf/initialize_spec.rb b/spec/ruby/library/csv/streambuf/initialize_spec.rb index 1273c98094f93a..3655b02e25bc0a 100644 --- a/spec/ruby/library/csv/streambuf/initialize_spec.rb +++ b/spec/ruby/library/csv/streambuf/initialize_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::StreamBuf#initialize" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::StreamBuf#initialize" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/streambuf/is_eos_spec.rb b/spec/ruby/library/csv/streambuf/is_eos_spec.rb index a0a3c1e0b0dc24..9891536feadf1f 100644 --- a/spec/ruby/library/csv/streambuf/is_eos_spec.rb +++ b/spec/ruby/library/csv/streambuf/is_eos_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::StreamBuf#is_eos?" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::StreamBuf#is_eos?" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/streambuf/read_spec.rb b/spec/ruby/library/csv/streambuf/read_spec.rb index cf98c5340978a6..7a82d0d13d5b0d 100644 --- a/spec/ruby/library/csv/streambuf/read_spec.rb +++ b/spec/ruby/library/csv/streambuf/read_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::StreamBuf#read" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::StreamBuf#read" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/streambuf/rel_buf_spec.rb b/spec/ruby/library/csv/streambuf/rel_buf_spec.rb index 548e347200f713..2994f5c950b8b0 100644 --- a/spec/ruby/library/csv/streambuf/rel_buf_spec.rb +++ b/spec/ruby/library/csv/streambuf/rel_buf_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::StreamBuf#rel_buf" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::StreamBuf#rel_buf" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/streambuf/terminate_spec.rb b/spec/ruby/library/csv/streambuf/terminate_spec.rb index 247b33184af995..e720d83703a7ae 100644 --- a/spec/ruby/library/csv/streambuf/terminate_spec.rb +++ b/spec/ruby/library/csv/streambuf/terminate_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::StreamBuf#terminate" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::StreamBuf#terminate" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/stringreader/get_row_spec.rb b/spec/ruby/library/csv/stringreader/get_row_spec.rb index 5cc34470613333..b4a13cf38a6c50 100644 --- a/spec/ruby/library/csv/stringreader/get_row_spec.rb +++ b/spec/ruby/library/csv/stringreader/get_row_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::StringReader#get_row" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::StringReader#get_row" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/stringreader/initialize_spec.rb b/spec/ruby/library/csv/stringreader/initialize_spec.rb index 4e3634847e0e5a..2c71d8a8b80701 100644 --- a/spec/ruby/library/csv/stringreader/initialize_spec.rb +++ b/spec/ruby/library/csv/stringreader/initialize_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::StringReader#initialize" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::StringReader#initialize" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/writer/add_row_spec.rb b/spec/ruby/library/csv/writer/add_row_spec.rb index 2f074b45db627a..27af76a6372408 100644 --- a/spec/ruby/library/csv/writer/add_row_spec.rb +++ b/spec/ruby/library/csv/writer/add_row_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::Writer#add_row" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::Writer#add_row" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/writer/append_spec.rb b/spec/ruby/library/csv/writer/append_spec.rb index 4e1f6728c2b8f8..1c968e2b97da3b 100644 --- a/spec/ruby/library/csv/writer/append_spec.rb +++ b/spec/ruby/library/csv/writer/append_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::Writer#<<" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::Writer#<<" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/writer/close_spec.rb b/spec/ruby/library/csv/writer/close_spec.rb index 1a87094bb7c150..65292dc4d0ebae 100644 --- a/spec/ruby/library/csv/writer/close_spec.rb +++ b/spec/ruby/library/csv/writer/close_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::Writer#close" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::Writer#close" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/writer/create_spec.rb b/spec/ruby/library/csv/writer/create_spec.rb index a4514d55780e33..0af9f44ff4e3d0 100644 --- a/spec/ruby/library/csv/writer/create_spec.rb +++ b/spec/ruby/library/csv/writer/create_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::Writer.create" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::Writer.create" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/writer/generate_spec.rb b/spec/ruby/library/csv/writer/generate_spec.rb index 6ea916177728d9..8200ae566d3535 100644 --- a/spec/ruby/library/csv/writer/generate_spec.rb +++ b/spec/ruby/library/csv/writer/generate_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::Writer.generate" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::Writer.generate" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/writer/initialize_spec.rb b/spec/ruby/library/csv/writer/initialize_spec.rb index 6bba8f8d0a2996..574f39978a0fd0 100644 --- a/spec/ruby/library/csv/writer/initialize_spec.rb +++ b/spec/ruby/library/csv/writer/initialize_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::Writer#initialize" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::Writer#initialize" do + it "needs to be reviewed for spec completeness" + end end diff --git a/spec/ruby/library/csv/writer/terminate_spec.rb b/spec/ruby/library/csv/writer/terminate_spec.rb index 77136dd018d249..56b78e10888b43 100644 --- a/spec/ruby/library/csv/writer/terminate_spec.rb +++ b/spec/ruby/library/csv/writer/terminate_spec.rb @@ -1,6 +1,9 @@ require_relative '../../../spec_helper' -require 'csv' -describe "CSV::Writer#terminate" do - it "needs to be reviewed for spec completeness" +ruby_version_is ""..."3.4" do + require 'csv' + + describe "CSV::Writer#terminate" do + it "needs to be reviewed for spec completeness" + end end From 92141d6269f845a3125f6c833398722904603cd4 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 22 Jan 2024 17:24:16 +0900 Subject: [PATCH 396/640] Document about csv at Ruby 3.4 --- doc/maintainers.md | 9 +++------ doc/standard_library.rdoc | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/doc/maintainers.md b/doc/maintainers.md index 65ae8f74e5e431..9e738a6bdd74b5 100644 --- a/doc/maintainers.md +++ b/doc/maintainers.md @@ -88,12 +88,6 @@ have commit right, others don't. * https://github.com/ruby/cgi * https://rubygems.org/gems/cgi -#### lib/csv.rb -* Kenta Murata (mrkn) -* Kouhei Sutou (kou) -* https://github.com/ruby/csv -* https://rubygems.org/gems/csv - #### lib/English.rb * *unmaintained* * https://github.com/ruby/English @@ -468,6 +462,9 @@ have commit right, others don't. #### syslog * https://github.com/ruby/syslog +#### csv +* https://github.com/ruby/csv + ## Platform Maintainers ### mswin64 (Microsoft Windows) * NAKAMURA Usaku (usa) diff --git a/doc/standard_library.rdoc b/doc/standard_library.rdoc index 709358fcda4e0b..a9fca632f8d2af 100644 --- a/doc/standard_library.rdoc +++ b/doc/standard_library.rdoc @@ -36,7 +36,6 @@ Socket:: Access underlying OS socket implementations 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 Delegator:: Provides three abilities to delegate method calls to an object DidYouMean:: "Did you mean?" experience in Ruby English:: Provides references to special global variables with less cryptic names @@ -130,3 +129,4 @@ Rinda:: The Linda distributed computing paradigm in Ruby DRb:: Distributed object system for Ruby NKF:: Ruby extension for Network Kanji Filter Syslog:: Ruby interface for the POSIX system logging facility +CSV:: Provides an interface to read and write CSV files and data From 2e69137dbe9fd7c03dac9b8adc30a7eba3ecb10b Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 22 Jan 2024 17:55:03 +0900 Subject: [PATCH 397/640] Use version dependant library for completion test --- test/irb/test_completion.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/irb/test_completion.rb b/test/irb/test_completion.rb index 348cd4b6dca625..2f97d99faa5b02 100644 --- a/test/irb/test_completion.rb +++ b/test/irb/test_completion.rb @@ -124,8 +124,8 @@ def object.to_s; raise; end end def test_complete_require_library_name_first - candidates = IRB::RegexpCompletor.new.completion_candidates("require ", "'csv", "", bind: binding) - assert_equal "'csv", candidates.first + candidates = IRB::RegexpCompletor.new.completion_candidates("require ", "'coverage", "", bind: binding) + assert_equal "'coverage", candidates.first end def test_complete_require_relative From 754e4e0c9cab9d5a71c33831f7cad531e7d35caa Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 22 Jan 2024 17:55:44 +0900 Subject: [PATCH 398/640] Stop sync csv repo --- tool/sync_default_gems.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb index 7cf98bbd9fc3ba..4ccad7c9425e2f 100755 --- a/tool/sync_default_gems.rb +++ b/tool/sync_default_gems.rb @@ -20,7 +20,6 @@ module SyncDefaultGems English: "ruby/English", benchmark: "ruby/benchmark", cgi: "ruby/cgi", - csv: 'ruby/csv', date: 'ruby/date', delegate: "ruby/delegate", did_you_mean: "ruby/did_you_mean", From 15f6ee057d800d54f803449d6bd4a8aadea524c1 Mon Sep 17 00:00:00 2001 From: git Date: Mon, 22 Jan 2024 09:23:58 +0000 Subject: [PATCH 399/640] Update bundled gems list at 754e4e0c9cab9d5a71c33831f7cad5 [ci skip] --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index ef8dab37d45972..9675e8b1e666e2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -57,6 +57,7 @@ The following bundled gems are promoted from default gems. * drb 2.2.0 * nkf 0.2.0 * syslog 0.1.2 +* csv 3.2.8 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. From 127b19ab561b5365884b465d50356a1e4019713c Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 17 Jan 2024 16:45:57 +0900 Subject: [PATCH 400/640] Use line numbers as builtin-index The order of iseq may differ from the order of tokens, typically `while`/`until` conditions are put after the body. These orders can match by using line numbers as builtin-indexes, but at the same time, it introduces the restriction that multiple `cexpr!` and `cstmt!` cannot appear in the same line. Another possible idea is to use `RubyVM::AbstractSyntaxTree` and `node_id` instead of ripper, with making BASERUBY 3.1 or later. --- builtin.c | 1 - compile.c | 6 +----- mini_builtin.c | 1 - tool/mk_builtin_loader.rb | 4 ++-- vm_core.h | 1 - 5 files changed, 3 insertions(+), 10 deletions(-) diff --git a/builtin.c b/builtin.c index 4fc2ab43d1477f..fbc11bf1b47ad4 100644 --- a/builtin.c +++ b/builtin.c @@ -46,7 +46,6 @@ rb_load_with_builtin_functions(const char *feature_name, const struct rb_builtin rb_vm_t *vm = GET_VM(); if (vm->builtin_function_table != NULL) rb_bug("vm->builtin_function_table should be NULL."); vm->builtin_function_table = table; - vm->builtin_inline_index = 0; const rb_iseq_t *iseq = rb_iseq_ibf_load_bytes((const char *)bin, size); ASSUME(iseq); // otherwise an exception should have raised vm->builtin_function_table = NULL; diff --git a/compile.c b/compile.c index 8d3588c81bec5b..b15c04a37ad3af 100644 --- a/compile.c +++ b/compile.c @@ -8787,7 +8787,6 @@ compile_builtin_function_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NOD } else if (strcmp("cinit!", builtin_func) == 0) { // ignore - GET_VM()->builtin_inline_index++; return COMPILE_OK; } else if (strcmp("attr!", builtin_func) == 0) { @@ -8815,10 +8814,7 @@ compile_builtin_function_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NOD return COMPILE_NG; } - if (GET_VM()->builtin_inline_index == INT_MAX) { - rb_bug("builtin inline function index overflow:%s", builtin_func); - } - int inline_index = GET_VM()->builtin_inline_index++; + int inline_index = nd_line(node); snprintf(inline_func, sizeof(inline_func), BUILTIN_INLINE_PREFIX "%d", inline_index); builtin_func = inline_func; args_node = NULL; diff --git a/mini_builtin.c b/mini_builtin.c index 457327ee06cfbe..8371073f283058 100644 --- a/mini_builtin.c +++ b/mini_builtin.c @@ -27,7 +27,6 @@ builtin_iseq_load(const char *feature_name, const struct rb_builtin_function *ta feature_name); } vm->builtin_function_table = table; - vm->builtin_inline_index = 0; static const rb_compile_option_t optimization = { TRUE, /* unsigned int inline_const_cache; */ TRUE, /* unsigned int peephole_optimization; */ diff --git a/tool/mk_builtin_loader.rb b/tool/mk_builtin_loader.rb index 8cfae1380240ce..871ac87006c3cd 100644 --- a/tool/mk_builtin_loader.rb +++ b/tool/mk_builtin_loader.rb @@ -166,7 +166,7 @@ def collect_builtin base, tree, name, bs, inlines, locals = nil when 'cstmt' text = inline_text argc, args.first - func_name = "_bi#{inlines.size}" + func_name = "_bi#{lineno}" cfunc_name = make_cfunc_name(inlines, name, lineno) inlines[cfunc_name] = [lineno, text, locals, func_name] argc -= 1 @@ -174,7 +174,7 @@ def collect_builtin base, tree, name, bs, inlines, locals = nil text = inline_text argc, args.first code = "return #{text};" - func_name = "_bi#{inlines.size}" + func_name = "_bi#{lineno}" cfunc_name = make_cfunc_name(inlines, name, lineno) locals = [] if $1 == 'cconst' diff --git a/vm_core.h b/vm_core.h index 743071ac85fd64..881e1beaacb306 100644 --- a/vm_core.h +++ b/vm_core.h @@ -747,7 +747,6 @@ typedef struct rb_vm_struct { st_table *frozen_strings; const struct rb_builtin_function *builtin_function_table; - int builtin_inline_index; struct rb_id_table *negative_cme_table; st_table *overloaded_cme_table; // cme -> overloaded_cme From d940e3b2c3c413b697c415718d4ef0991e75383f Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 17 Jan 2024 16:46:38 +0900 Subject: [PATCH 401/640] `cexpr!` must be up to one per line now --- rjit_c.rb | 6 ++++-- tool/rjit/bindgen.rb | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/rjit_c.rb b/rjit_c.rb index 67ac8729d4f574..ce718717beef4a 100644 --- a/rjit_c.rb +++ b/rjit_c.rb @@ -1541,11 +1541,13 @@ def C.rb_thread_struct end def C.VALUE - @VALUE ||= CType::Immediate.find(Primitive.cexpr!("SIZEOF(VALUE)"), Primitive.cexpr!("SIGNED_TYPE_P(VALUE)")) + @VALUE ||= CType::Immediate.find(Primitive.cexpr!("SIZEOF(VALUE)"), + Primitive.cexpr!("SIGNED_TYPE_P(VALUE)")) end def C.shape_id_t - @shape_id_t ||= CType::Immediate.find(Primitive.cexpr!("SIZEOF(shape_id_t)"), Primitive.cexpr!("SIGNED_TYPE_P(shape_id_t)")) + @shape_id_t ||= CType::Immediate.find(Primitive.cexpr!("SIZEOF(shape_id_t)"), + Primitive.cexpr!("SIGNED_TYPE_P(shape_id_t)")) end def C.rb_id_table diff --git a/tool/rjit/bindgen.rb b/tool/rjit/bindgen.rb index 4022726302b5ff..fb26b94aa47642 100755 --- a/tool/rjit/bindgen.rb +++ b/tool/rjit/bindgen.rb @@ -183,7 +183,8 @@ def generate(nodes) raise "Non-immediate type is given to dynamic_types: #{type}" end println " def C.#{type}" - println " @#{type} ||= CType::Immediate.find(Primitive.cexpr!(\"SIZEOF(#{type})\"), Primitive.cexpr!(\"SIGNED_TYPE_P(#{type})\"))" + println " @#{type} ||= CType::Immediate.find(Primitive.cexpr!(\"SIZEOF(#{type})\")," + println " Primitive.cexpr!(\"SIGNED_TYPE_P(#{type})\"))" println " end" println end From b841e32bbba92b552d15abaca6219eff075f51f2 Mon Sep 17 00:00:00 2001 From: git Date: Mon, 22 Jan 2024 10:40:26 +0000 Subject: [PATCH 402/640] Update default gems list at d940e3b2c3c413b697c415718d4ef0 [ci skip] --- NEWS.md | 1 - 1 file changed, 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 9675e8b1e666e2..accab09e1c6c6f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -24,7 +24,6 @@ The following default gems are updated. * RubyGems 3.6.0.dev * bundler 2.6.0.dev -* csv 3.2.9 * erb 4.0.4 * fiddle 1.1.3 * io-console 0.7.2 From b4b35b1468f2a28caf9c778944be6bc555a11fbb Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Fri, 19 Jan 2024 14:06:44 +0100 Subject: [PATCH 403/640] Add an autoload spec for the behavior inside autoload but after the constant is defined --- spec/ruby/core/module/autoload_spec.rb | 91 +++++++++++++------ .../autoload_during_autoload_after_define.rb | 6 ++ 2 files changed, 70 insertions(+), 27 deletions(-) create mode 100644 spec/ruby/core/module/fixtures/autoload_during_autoload_after_define.rb diff --git a/spec/ruby/core/module/autoload_spec.rb b/spec/ruby/core/module/autoload_spec.rb index af04ab26c87405..ab4df7600e71b3 100644 --- a/spec/ruby/core/module/autoload_spec.rb +++ b/spec/ruby/core/module/autoload_spec.rb @@ -343,6 +343,29 @@ module ModuleSpecs::Autoload end end + def check_before_during_thread_after(const, &check) + before = check.call + to_autoload_thread, from_autoload_thread = Queue.new, Queue.new + ScratchPad.record -> { + from_autoload_thread.push check.call + to_autoload_thread.pop + } + t = Thread.new { + in_loading_thread = from_autoload_thread.pop + in_other_thread = check.call + to_autoload_thread.push :done + [in_loading_thread, in_other_thread] + } + in_loading_thread, in_other_thread = nil + begin + ModuleSpecs::Autoload.const_get(const) + ensure + in_loading_thread, in_other_thread = t.value + end + after = check.call + [before, in_loading_thread, in_other_thread, after] + end + describe "during the autoload before the constant is assigned" do before :each do @path = fixture(__FILE__, "autoload_during_autoload.rb") @@ -351,58 +374,72 @@ module ModuleSpecs::Autoload raise unless ModuleSpecs::Autoload.autoload?(:DuringAutoload) == @path end - def check_before_during_thread_after(&check) - before = check.call - to_autoload_thread, from_autoload_thread = Queue.new, Queue.new - ScratchPad.record -> { - from_autoload_thread.push check.call - to_autoload_thread.pop - } - t = Thread.new { - in_loading_thread = from_autoload_thread.pop - in_other_thread = check.call - to_autoload_thread.push :done - [in_loading_thread, in_other_thread] - } - in_loading_thread, in_other_thread = nil - begin - ModuleSpecs::Autoload::DuringAutoload - ensure - in_loading_thread, in_other_thread = t.value - end - after = check.call - [before, in_loading_thread, in_other_thread, after] - end - it "returns nil in autoload thread and 'constant' otherwise for defined?" do - results = check_before_during_thread_after { + results = check_before_during_thread_after(:DuringAutoload) { defined?(ModuleSpecs::Autoload::DuringAutoload) } results.should == ['constant', nil, 'constant', 'constant'] end it "keeps the constant in Module#constants" do - results = check_before_during_thread_after { + results = check_before_during_thread_after(:DuringAutoload) { ModuleSpecs::Autoload.constants(false).include?(:DuringAutoload) } results.should == [true, true, true, true] end it "returns false in autoload thread and true otherwise for Module#const_defined?" do - results = check_before_during_thread_after { + results = check_before_during_thread_after(:DuringAutoload) { ModuleSpecs::Autoload.const_defined?(:DuringAutoload, false) } results.should == [true, false, true, true] end it "returns nil in autoload thread and returns the path in other threads for Module#autoload?" do - results = check_before_during_thread_after { + results = check_before_during_thread_after(:DuringAutoload) { ModuleSpecs::Autoload.autoload?(:DuringAutoload) } results.should == [@path, nil, @path, nil] end end + describe "during the autoload after the constant is assigned" do + before :each do + @path = fixture(__FILE__, "autoload_during_autoload_after_define.rb") + ModuleSpecs::Autoload.autoload :DuringAutoloadAfterDefine, @path + @remove << :DuringAutoloadAfterDefine + raise unless ModuleSpecs::Autoload.autoload?(:DuringAutoloadAfterDefine) == @path + end + + it "returns 'constant' in both threads" do + results = check_before_during_thread_after(:DuringAutoloadAfterDefine) { + defined?(ModuleSpecs::Autoload::DuringAutoloadAfterDefine) + } + results.should == ['constant', 'constant', 'constant', 'constant'] + end + + it "Module#constants include the autoloaded in both threads" do + results = check_before_during_thread_after(:DuringAutoloadAfterDefine) { + ModuleSpecs::Autoload.constants(false).include?(:DuringAutoloadAfterDefine) + } + results.should == [true, true, true, true] + end + + it "Module#const_defined? returns true in both threads" do + results = check_before_during_thread_after(:DuringAutoloadAfterDefine) { + ModuleSpecs::Autoload.const_defined?(:DuringAutoloadAfterDefine, false) + } + results.should == [true, true, true, true] + end + + it "returns nil in autoload thread and returns the path in other threads for Module#autoload?" do + results = check_before_during_thread_after(:DuringAutoloadAfterDefine) { + ModuleSpecs::Autoload.autoload?(:DuringAutoloadAfterDefine) + } + results.should == [@path, nil, @path, nil] + end + end + it "does not remove the constant from Module#constants if load fails and keeps it as an autoload" do ModuleSpecs::Autoload.autoload :Fail, @non_existent diff --git a/spec/ruby/core/module/fixtures/autoload_during_autoload_after_define.rb b/spec/ruby/core/module/fixtures/autoload_during_autoload_after_define.rb new file mode 100644 index 00000000000000..a9d886dfd6d8b7 --- /dev/null +++ b/spec/ruby/core/module/fixtures/autoload_during_autoload_after_define.rb @@ -0,0 +1,6 @@ +module ModuleSpecs::Autoload + class DuringAutoloadAfterDefine + block = ScratchPad.recorded + ScratchPad.record(block.call) + end +end From b8495048fb60d422072809b0b99762b46cafd3ea Mon Sep 17 00:00:00 2001 From: Matt Valentine-House Date: Thu, 18 Jan 2024 19:51:25 +0000 Subject: [PATCH 404/640] [ruby/prism] Unescape method name for unary methods. https://github.com/ruby/prism/commit/4386a4c0da --- prism/prism.c | 29 +++++++++++++------ .../snapshots/seattlerb/defn_unary_not.txt | 4 +-- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 161744e4ba2281..a078100e3b0e08 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -12719,20 +12719,24 @@ parse_string_part(pm_parser_t *parser) { * automatically drop trailing `@` characters. This happens at the parser level, * such that `~@` is parsed as `~` and `!@` is parsed as `!`. We do that here. */ +static const uint8_t * +parse_operator_symbol_name(const pm_token_t *name) { + switch (name->type) { + case PM_TOKEN_TILDE: + case PM_TOKEN_BANG: + if (name->end[-1] == '@') return name->end - 1; + /* fallthrough */ + default: + return name->end; + } +} + static pm_node_t * parse_operator_symbol(pm_parser_t *parser, const pm_token_t *opening, pm_lex_state_t next_state) { pm_token_t closing = not_provided(parser); pm_symbol_node_t *symbol = pm_symbol_node_create(parser, opening, &parser->current, &closing); - const uint8_t *end = parser->current.end; - switch (parser->current.type) { - case PM_TOKEN_TILDE: - case PM_TOKEN_BANG: - if (parser->current.end[-1] == '@') end--; - break; - default: - break; - } + const uint8_t *end = parse_operator_symbol_name(&parser->current); if (next_state != PM_LEX_STATE_NONE) lex_state_set(parser, next_state); parser_lex(parser); @@ -15379,6 +15383,13 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_parser_scope_pop(parser); pm_parser_current_param_name_restore(parser, saved_param_name); + /** + * If the final character is @. As is the case when defining + * methods to override the unary operators, we should ignore + * the @ in the same way we do for symbols. + */ + name.end = parse_operator_symbol_name(&name); + return (pm_node_t *) pm_def_node_create( parser, &name, diff --git a/test/prism/snapshots/seattlerb/defn_unary_not.txt b/test/prism/snapshots/seattlerb/defn_unary_not.txt index 9f3fc271714a8e..a10614fd2acb03 100644 --- a/test/prism/snapshots/seattlerb/defn_unary_not.txt +++ b/test/prism/snapshots/seattlerb/defn_unary_not.txt @@ -4,8 +4,8 @@ @ StatementsNode (location: (1,0)-(1,17)) └── body: (length: 1) └── @ DefNode (location: (1,0)-(1,17)) - ├── name: :"!@" - ├── name_loc: (1,4)-(1,6) = "!@" + ├── name: :! + ├── name_loc: (1,4)-(1,5) = "!" ├── receiver: ∅ ├── parameters: ∅ ├── body: From ee8f92673b52761ce133bd0f4c42d6784ece7ba6 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 22 Jan 2024 08:23:05 -0500 Subject: [PATCH 405/640] Enable test_syntax.rb --- tool/prism_btests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tool/prism_btests b/tool/prism_btests index e6777540f91cfe..04e58ae85c395b 100644 --- a/tool/prism_btests +++ b/tool/prism_btests @@ -23,6 +23,7 @@ ../src/bootstraptest/test_rjit.rb ../src/bootstraptest/test_string.rb ../src/bootstraptest/test_struct.rb +../src/bootstraptest/test_syntax.rb ../src/bootstraptest/test_thread.rb ../src/bootstraptest/test_yjit_30k_ifelse.rb ../src/bootstraptest/test_yjit_30k_methods.rb @@ -31,5 +32,4 @@ # ../src/bootstraptest/test_insns.rb # ../src/bootstraptest/test_method.rb # ../src/bootstraptest/test_ractor.rb -# ../src/bootstraptest/test_syntax.rb # ../src/bootstraptest/test_yjit.rb From 2abf153016088605ea6dc77d9f6ba61f619cc273 Mon Sep 17 00:00:00 2001 From: Matt Valentine-House Date: Mon, 22 Jan 2024 11:26:04 +0000 Subject: [PATCH 406/640] [PRISM] Add TP call/return events to method ISEQs --- prism_compile.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index ddb1a0c54cedcb..3945c50ca97182 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -6867,6 +6867,17 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, ADD_INSN1(ret, &dummy_line_node, throw, INT2FIX(0)); return; } + case ISEQ_TYPE_METHOD: { + ADD_TRACE(ret, RUBY_EVENT_CALL); + if (scope_node->body) { + PM_COMPILE((pm_node_t *)scope_node->body); + } else { + PM_PUTNIL; + } + ADD_TRACE(ret, RUBY_EVENT_RETURN); + + break; + } case ISEQ_TYPE_RESCUE: { iseq_set_exception_local_table(iseq); if (PM_NODE_TYPE_P(scope_node->ast_node, PM_RESCUE_MODIFIER_NODE)) { From 6bcbb9a02baa8585c2d65e29c0a65d791b077611 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 22 Jan 2024 09:39:59 -0500 Subject: [PATCH 407/640] Make prism respect dump_without_opt --- iseq.c | 8 ++++---- iseq.h | 2 +- load.c | 2 +- ruby.c | 3 ++- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/iseq.c b/iseq.c index 046a1434c48ba4..170fe444657a01 100644 --- a/iseq.c +++ b/iseq.c @@ -1399,7 +1399,7 @@ iseqw_s_compile(int argc, VALUE *argv, VALUE self) } static void -iseqw_s_compile_prism_compile(pm_parser_t *parser, VALUE opt, rb_iseq_t *iseq, VALUE file, VALUE path, int first_lineno) +iseqw_s_compile_prism_compile(pm_parser_t *parser, VALUE optimize, rb_iseq_t *iseq, VALUE file, VALUE path, int first_lineno) { pm_node_t *node = pm_parse(parser); @@ -1422,7 +1422,7 @@ iseqw_s_compile_prism_compile(pm_parser_t *parser, VALUE opt, rb_iseq_t *iseq, V pm_code_location(&code_location, &parser->newline_list, &node->location); rb_compile_option_t option; - make_compile_option(&option, opt); + make_compile_option(&option, optimize); prepare_iseq_build(iseq, rb_fstring_lit(""), file, path, first_lineno, &code_location, -1, NULL, 0, ISEQ_TYPE_TOP, Qnil, &option); pm_scope_node_t scope_node; @@ -1533,7 +1533,7 @@ iseqw_s_compile_file_prism(int argc, VALUE *argv, VALUE self) } rb_iseq_t * -rb_iseq_new_main_prism(pm_string_t *input, pm_options_t *options, VALUE path) +rb_iseq_new_main_prism(pm_string_t *input, pm_options_t *options, VALUE path, VALUE optimize) { pm_parser_t parser; pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options); @@ -1543,7 +1543,7 @@ rb_iseq_new_main_prism(pm_string_t *input, pm_options_t *options, VALUE path) pm_options_line_set(options, start_line); rb_iseq_t *iseq = iseq_alloc(); - iseqw_s_compile_prism_compile(&parser, Qnil, iseq, path, path, start_line); + iseqw_s_compile_prism_compile(&parser, optimize, iseq, path, path, start_line); pm_parser_free(&parser); return iseq; diff --git a/iseq.h b/iseq.h index 35780f2862a05b..e5774d098c572d 100644 --- a/iseq.h +++ b/iseq.h @@ -172,7 +172,7 @@ void rb_iseq_init_trace(rb_iseq_t *iseq); int rb_iseq_add_local_tracepoint_recursively(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, VALUE tpval, unsigned int target_line, bool target_bmethod); int rb_iseq_remove_local_tracepoint_recursively(const rb_iseq_t *iseq, VALUE tpval); const rb_iseq_t *rb_iseq_load_iseq(VALUE fname); -rb_iseq_t * rb_iseq_new_main_prism(pm_string_t *input, pm_options_t *options, VALUE path); +rb_iseq_t * rb_iseq_new_main_prism(pm_string_t *input, pm_options_t *options, VALUE path, VALUE optimize); #if VM_INSN_INFO_TABLE_IMPL == 2 unsigned int *rb_iseq_insns_info_decode_positions(const struct rb_iseq_constant_body *body); diff --git a/load.c b/load.c index f0c62dc7071460..a35042e5f56605 100644 --- a/load.c +++ b/load.c @@ -747,7 +747,7 @@ load_iseq_eval(rb_execution_context_t *ec, VALUE fname) pm_parser_t parser; pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), &options); - iseq = rb_iseq_new_main_prism(&input, &options, fname); + iseq = rb_iseq_new_main_prism(&input, &options, fname, Qnil); pm_string_free(&input); pm_options_free(&options); diff --git a/ruby.c b/ruby.c index 047a90c3a1441b..bccc6504a0ccc9 100644 --- a/ruby.c +++ b/ruby.c @@ -2427,7 +2427,8 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) pm_options_filepath_set(&options, RSTRING_PTR(opt->script_name)); } - iseq = rb_iseq_new_main_prism(&input, &options, path); + VALUE optimize = dump & DUMP_BIT(insns_without_opt) ? Qfalse : Qnil; + iseq = rb_iseq_new_main_prism(&input, &options, path, optimize); ruby_opt_init(opt); pm_string_free(&input); From 580429d27ce320b1615a03878d1fa8e2df6b80e2 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Fri, 19 Jan 2024 14:33:49 -0500 Subject: [PATCH 408/640] [PRISM] Fix incorrect ordering of MultiTargetNode Fixes ruby/prism#2218. --- prism_compile.c | 5 ++--- test/ruby/test_compile_prism.rb | 3 +++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 3945c50ca97182..a9f441e35c4b05 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -6302,7 +6302,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // We will assign these values now, if applicable, and use them for // the ISEQs on these multis - int required_multis_hidden_index = 0; + int required_multis_hidden_index = local_index; int post_multis_hidden_index = 0; // Here we figure out local table indices and insert them in to the @@ -6321,7 +6321,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n) // ^^^^^^^^^^ case PM_MULTI_TARGET_NODE: { - required_multis_hidden_index = local_index; local = rb_make_temporary_id(local_index); local_table_for_iseq->ids[local_index] = local; break; @@ -6770,7 +6769,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // We want to account for this in our table size pm_node_t *required = requireds_list->nodes[i]; if (PM_NODE_TYPE_P(required, PM_MULTI_TARGET_NODE)) { - ADD_GETLOCAL(ret, &dummy_line_node, table_size - required_multis_hidden_index, 0); + ADD_GETLOCAL(ret, &dummy_line_node, table_size - required_multis_hidden_index - (int)i, 0); PM_COMPILE(required); } } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 917d16381e2101..4cd7bff60afd0f 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1354,6 +1354,9 @@ def test_BlockNode assert_prism_eval("[[]].map { |a,b=1| a }") assert_prism_eval("[{}].map { |a,| }") assert_prism_eval("[{}].map { |a| a }") + + # Test blocks with MultiTargetNode + assert_prism_eval("[[1, 2]].each.map { |(a), (b)| [a, b] }") end def test_ClassNode From d68aaa66726b8fe929709521844e46dc20d61d08 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 22 Jan 2024 10:29:09 -0500 Subject: [PATCH 409/640] [PRISM] Freeze regex literals in iseqs --- prism_compile.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/prism_compile.c b/prism_compile.c index a9f441e35c4b05..9ec9e524e06f18 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -317,7 +317,10 @@ pm_new_regex(pm_regular_expression_node_t * cast, const pm_parser_t * parser) { VALUE regex_str = parse_string(&cast->unescaped, parser); rb_encoding * enc = pm_reg_enc(cast, parser); - return rb_enc_reg_new(RSTRING_PTR(regex_str), RSTRING_LEN(regex_str), enc, pm_reg_flags((const pm_node_t *)cast)); + VALUE regex = rb_enc_reg_new(RSTRING_PTR(regex_str), RSTRING_LEN(regex_str), enc, pm_reg_flags((const pm_node_t *)cast)); + rb_obj_freeze(regex); + + return regex; } /** From e00f42e5d345ca742dec6f27b851b753ce45ca85 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 22 Jan 2024 10:37:45 -0500 Subject: [PATCH 410/640] [ruby/prism] Return 1-indexed line numbers https://github.com/ruby/prism/commit/ad17f58729 --- prism/extension.c | 8 ++++---- prism/prism.c | 18 +++++++++--------- prism/templates/src/prettyprint.c.erb | 2 +- prism/util/pm_newline_list.c | 4 ++-- test/prism/format_errors_test.rb | 17 +++++++++++++++++ 5 files changed, 33 insertions(+), 16 deletions(-) create mode 100644 test/prism/format_errors_test.rb diff --git a/prism/extension.c b/prism/extension.c index b7c59e514ec86c..416e682f762a03 100644 --- a/prism/extension.c +++ b/prism/extension.c @@ -987,12 +987,12 @@ inspect_node(VALUE self, VALUE source) { /** * call-seq: - * Debug::format_errors(source) -> String + * Debug::format_errors(source, colorize) -> String * * Format the errors that are found when parsing the given source string. */ static VALUE -format_errors(VALUE self, VALUE source) { +format_errors(VALUE self, VALUE source, VALUE colorize) { pm_string_t input; input_load_string(&input, source); @@ -1002,7 +1002,7 @@ format_errors(VALUE self, VALUE source) { pm_node_t *node = pm_parse(&parser); pm_buffer_t buffer = { 0 }; - pm_parser_errors_format(&parser, &buffer, true); + pm_parser_errors_format(&parser, &buffer, RTEST(colorize)); rb_encoding *encoding = rb_enc_find(parser.encoding->name); VALUE result = rb_enc_str_new(pm_buffer_value(&buffer), pm_buffer_length(&buffer), encoding); @@ -1093,7 +1093,7 @@ Init_prism(void) { rb_define_singleton_method(rb_cPrismDebug, "memsize", memsize, 1); rb_define_singleton_method(rb_cPrismDebug, "profile_file", profile_file, 1); rb_define_singleton_method(rb_cPrismDebug, "inspect_node", inspect_node, 1); - rb_define_singleton_method(rb_cPrismDebug, "format_errors", format_errors, 1); + rb_define_singleton_method(rb_cPrismDebug, "format_errors", format_errors, 2); // Next, initialize the other APIs. Init_prism_api_node(); diff --git a/prism/prism.c b/prism/prism.c index a078100e3b0e08..4a6797896b1390 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -17873,7 +17873,7 @@ pm_parser_errors_format_sort(const pm_list_t *error_list, const pm_newline_list_ if (start.line == end.line) { column_end = (uint32_t) end.column; } else { - column_end = (uint32_t) (newline_list->offsets[start.line + 1] - newline_list->offsets[start.line] - 1); + column_end = (uint32_t) (newline_list->offsets[start.line] - newline_list->offsets[start.line - 1] - 1); } // Ensure we have at least one column of error. @@ -17892,16 +17892,16 @@ pm_parser_errors_format_sort(const pm_list_t *error_list, const pm_newline_list_ static inline void pm_parser_errors_format_line(const pm_parser_t *parser, const pm_newline_list_t *newline_list, const char *number_prefix, size_t line, pm_buffer_t *buffer) { - const uint8_t *start = &parser->start[newline_list->offsets[line]]; + const uint8_t *start = &parser->start[newline_list->offsets[line - 1]]; const uint8_t *end; - if (line + 1 >= newline_list->size) { + if (line >= newline_list->size) { end = parser->end; } else { - end = &parser->start[newline_list->offsets[line + 1]]; + end = &parser->start[newline_list->offsets[line]]; } - pm_buffer_append_format(buffer, number_prefix, (uint32_t) (line + 1)); + pm_buffer_append_format(buffer, number_prefix, (uint32_t) line); pm_buffer_append_string(buffer, (const char *) start, (size_t) (end - start)); if (end == parser->end && end[-1] != '\n') { @@ -17926,7 +17926,7 @@ pm_parser_errors_format(const pm_parser_t *parser, pm_buffer_t *buffer, bool col // blank lines based on the maximum number of digits in the line numbers // that are going to be displayed. pm_error_format_t error_format; - size_t max_line_number = errors[error_list->size - 1].line + 1; + size_t max_line_number = errors[error_list->size - 1].line; if (max_line_number < 10) { if (colorize) { @@ -18008,7 +18008,7 @@ pm_parser_errors_format(const pm_parser_t *parser, pm_buffer_t *buffer, bool col // the source before the error to give some context. We'll be careful not to // display the same line twice in case the errors are close enough in the // source. - uint32_t last_line = (uint32_t) -1; + uint32_t last_line = 0; const pm_encoding_t *encoding = parser->encoding; for (size_t index = 0; index < error_list->size; index++) { @@ -18054,7 +18054,7 @@ pm_parser_errors_format(const pm_parser_t *parser, pm_buffer_t *buffer, bool col pm_buffer_append_string(buffer, error_format.blank_prefix, error_format.blank_prefix_length); size_t column = 0; - const uint8_t *start = &parser->start[newline_list->offsets[error->line]]; + const uint8_t *start = &parser->start[newline_list->offsets[error->line - 1]]; while (column < error->column_end) { if (column < error->column_start) { @@ -18078,7 +18078,7 @@ pm_parser_errors_format(const pm_parser_t *parser, pm_buffer_t *buffer, bool col // Here we determine how many lines of padding to display after the // error, depending on where the next error is in source. last_line = error->line; - size_t next_line = (index == error_list->size - 1) ? newline_list->size - 1 : errors[index + 1].line; + size_t next_line = (index == error_list->size - 1) ? newline_list->size : errors[index + 1].line; if (next_line - last_line > 1) { pm_buffer_append_string(buffer, " ", 2); diff --git a/prism/templates/src/prettyprint.c.erb b/prism/templates/src/prettyprint.c.erb index 02b89758b80140..605795b64ad237 100644 --- a/prism/templates/src/prettyprint.c.erb +++ b/prism/templates/src/prettyprint.c.erb @@ -40,7 +40,7 @@ static inline void prettyprint_location(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm_location_t *location) { pm_line_column_t start = pm_newline_list_line_column(&parser->newline_list, location->start); pm_line_column_t end = pm_newline_list_line_column(&parser->newline_list, location->end); - pm_buffer_append_format(output_buffer, "(%lu,%lu)-(%lu,%lu)", (unsigned long) (start.line + 1), (unsigned long) start.column, (unsigned long) (end.line + 1), (unsigned long) end.column); + pm_buffer_append_format(output_buffer, "(%lu,%lu)-(%lu,%lu)", (unsigned long) start.line, (unsigned long) start.column, (unsigned long) end.line, (unsigned long) end.column); } static inline void diff --git a/prism/util/pm_newline_list.c b/prism/util/pm_newline_list.c index 32a4a050fe6cf2..724d840dd27905 100644 --- a/prism/util/pm_newline_list.c +++ b/prism/util/pm_newline_list.c @@ -62,7 +62,7 @@ pm_newline_list_line_column(const pm_newline_list_t *list, const uint8_t *cursor size_t mid = left + (right - left) / 2; if (list->offsets[mid] == offset) { - return ((pm_line_column_t) { mid, 0 }); + return ((pm_line_column_t) { mid + 1, 0 }); } if (list->offsets[mid] < offset) { @@ -72,7 +72,7 @@ pm_newline_list_line_column(const pm_newline_list_t *list, const uint8_t *cursor } } - return ((pm_line_column_t) { left - 1, offset - list->offsets[left - 1] }); + return ((pm_line_column_t) { left, offset - list->offsets[left - 1] }); } /** diff --git a/test/prism/format_errors_test.rb b/test/prism/format_errors_test.rb new file mode 100644 index 00000000000000..62b24723b80e65 --- /dev/null +++ b/test/prism/format_errors_test.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +return if Prism::BACKEND == :FFI + +require_relative "test_helper" + +module Prism + class FormatErrorsTest < TestCase + def test_format_errors + assert_equal <<~ERROR, Debug.format_errors("<>", false) + > 1 | <> + | ^ cannot parse the expression + | ^ cannot parse the expression + ERROR + end + end +end From eb5797062a947ebbaeb154b9c1f6fcab7972c033 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 22 Jan 2024 11:16:26 -0500 Subject: [PATCH 411/640] [ruby/prism] Reference prism after require https://github.com/ruby/prism/commit/0a8ff431df --- test/prism/format_errors_test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/prism/format_errors_test.rb b/test/prism/format_errors_test.rb index 62b24723b80e65..3533a73863a4be 100644 --- a/test/prism/format_errors_test.rb +++ b/test/prism/format_errors_test.rb @@ -1,9 +1,9 @@ # frozen_string_literal: true -return if Prism::BACKEND == :FFI - require_relative "test_helper" +return if Prism::BACKEND == :FFI + module Prism class FormatErrorsTest < TestCase def test_format_errors From 6401f282d25fa89823c9360b43e377c55e9ff7a5 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 22 Jan 2024 11:21:04 -0500 Subject: [PATCH 412/640] [PRISM] Fix up source line for 1-indexed line numbers --- prism_compile.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 9ec9e524e06f18..df3a12ceb2638e 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -396,9 +396,7 @@ pm_static_literal_value(const pm_node_t *node, const pm_scope_node_t *scope_node } case PM_SOURCE_LINE_NODE: { int source_line = (int) pm_newline_list_line_column(&scope_node->parser->newline_list, node->location.start).line; - // Ruby treats file lines as 1-indexed // TODO: Incorporate options which allow for passing a line number - source_line += 1; return INT2FIX(source_line); } case PM_STRING_NODE: From 5906ce42fe04e8d4a4fe4b68b8ac54193598db56 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 22 Jan 2024 11:19:27 -0500 Subject: [PATCH 413/640] [ruby/prism] Static literal flag for string hash keys https://github.com/ruby/prism/commit/26a2d774cd --- prism/prism.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 4a6797896b1390..6b534175236e68 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -1352,6 +1352,13 @@ pm_assoc_node_create(pm_parser_t *parser, pm_node_t *key, const pm_token_t *oper end = key->location.end; } + // Hash string keys will be frozen, so we can mark them as frozen here so + // that the compiler picks them up and also when we check for static literal + // on the keys it gets factored in. + if (PM_NODE_TYPE_P(key, PM_STRING_NODE)) { + key->flags |= PM_STRING_FLAGS_FROZEN | PM_NODE_FLAG_STATIC_LITERAL; + } + // If the key and value of this assoc node are both static literals, then // we can mark this node as a static literal. pm_node_flags_t flags = 0; @@ -1359,11 +1366,6 @@ pm_assoc_node_create(pm_parser_t *parser, pm_node_t *key, const pm_token_t *oper flags = key->flags & value->flags & PM_NODE_FLAG_STATIC_LITERAL; } - // Hash string keys should be frozen - if (PM_NODE_TYPE_P(key, PM_STRING_NODE)) { - key->flags |= PM_STRING_FLAGS_FROZEN; - } - *node = (pm_assoc_node_t) { { .type = PM_ASSOC_NODE, From a7af34fa8b6f1f370f8fa6c66086fc5669a9d0a2 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 22 Jan 2024 10:46:12 -0500 Subject: [PATCH 414/640] [PRISM] Fix keywords arguments in IndexAndWriteNode Fixes ruby/prism#2233. --- prism_compile.c | 20 +++++++++++++------- test/ruby/test_compile_prism.rb | 9 +++++++++ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index df3a12ceb2638e..6ae9e094b2ee21 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -932,10 +932,10 @@ pm_compile_call_and_or_write_node(bool and_node, pm_node_t *receiver, pm_node_t } static void -pm_compile_index_write_nodes_add_send(bool popped, LINK_ANCHOR *const ret, rb_iseq_t *iseq, NODE dummy_line_node, VALUE argc, int flag, int block_offset) +pm_compile_index_write_nodes_add_send(bool popped, LINK_ANCHOR *const ret, rb_iseq_t *iseq, NODE dummy_line_node, VALUE argc, int flag, int block_offset, struct rb_callinfo_kwarg *keywords) { if (!popped) { - ADD_INSN1(ret, &dummy_line_node, setn, FIXNUM_INC(argc, 2 + block_offset)); + ADD_INSN1(ret, &dummy_line_node, setn, FIXNUM_INC(argc, 2 + block_offset + (keywords ? keywords->keyword_len : 0))); } if (flag & VM_CALL_ARGS_SPLAT) { @@ -952,6 +952,11 @@ pm_compile_index_write_nodes_add_send(bool popped, LINK_ANCHOR *const ret, rb_is } ADD_SEND_WITH_FLAG(ret, &dummy_line_node, idASET, argc, INT2FIX(flag)); } + else if (keywords && keywords->keyword_len) { + ADD_INSN1(ret, &dummy_line_node, opt_reverse, INT2FIX(keywords->keyword_len + block_offset + 1)); + ADD_INSN1(ret, &dummy_line_node, opt_reverse, INT2FIX(keywords->keyword_len + block_offset + 0)); + ADD_SEND_R(ret, &dummy_line_node, idASET, FIXNUM_INC(argc, 1), NULL, INT2FIX(flag), keywords); + } else { if (block_offset > 0) { PM_SWAP; @@ -1241,9 +1246,10 @@ pm_compile_index_and_or_write_node(bool and_node, pm_node_t *receiver, pm_node_t int flag = 0; int argc_int = 0; + struct rb_callinfo_kwarg *keywords = NULL; if (arguments) { // Get any arguments, and set the appropriate values for flag - argc_int = pm_setup_args(arguments, &flag, NULL, iseq, ret, src, popped, scope_node, dummy_line_node, parser); + argc_int = pm_setup_args(arguments, &flag, &keywords, iseq, ret, src, popped, scope_node, dummy_line_node, parser); } VALUE argc = INT2FIX(argc_int); @@ -1255,9 +1261,9 @@ pm_compile_index_and_or_write_node(bool and_node, pm_node_t *receiver, pm_node_t block_offset = 1; } - ADD_INSN1(ret, &dummy_line_node, dupn, FIXNUM_INC(argc, 1 + block_offset)); + ADD_INSN1(ret, &dummy_line_node, dupn, FIXNUM_INC(argc, 1 + block_offset + (keywords ? keywords->keyword_len : 0))); - ADD_SEND_WITH_FLAG(ret, &dummy_line_node, idAREF, argc, INT2FIX(flag)); + ADD_SEND_R(ret, &dummy_line_node, idAREF, argc, NULL, INT2FIX(flag), keywords); LABEL *label = NEW_LABEL(lineno); LABEL *lfin = NEW_LABEL(lineno); @@ -1276,7 +1282,7 @@ pm_compile_index_and_or_write_node(bool and_node, pm_node_t *receiver, pm_node_t PM_COMPILE_NOT_POPPED(value); - pm_compile_index_write_nodes_add_send(popped, ret, iseq, dummy_line_node, argc, flag, block_offset); + pm_compile_index_write_nodes_add_send(popped, ret, iseq, dummy_line_node, argc, flag, block_offset, keywords); ADD_INSNL(ret, &dummy_line_node, jump, lfin); ADD_LABEL(ret, label); @@ -5028,7 +5034,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, ID method_id = pm_constant_id_lookup(scope_node, index_operator_write_node->operator); ADD_SEND(ret, &dummy_line_node, method_id, INT2FIX(1)); - pm_compile_index_write_nodes_add_send(popped, ret, iseq, dummy_line_node, argc, flag, block_offset); + pm_compile_index_write_nodes_add_send(popped, ret, iseq, dummy_line_node, argc, flag, block_offset, NULL); return; } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 4cd7bff60afd0f..0998c8fa5da2e8 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -385,6 +385,15 @@ def []=(key, value, &block) hash["key", &(Proc.new { _1.upcase })] &&= "value" hash CODE + + # Test with keyword arguments + assert_prism_eval(<<~RUBY) + h = Object.new + def h.[](**b) = 0 + def h.[]=(*a, **b); end + + h[foo: 1] &&= 2 + RUBY end def test_IndexOrWriteNode From c7e87b21188386b2e9b9f2c8cf3b6c31ffff46c3 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Tue, 23 Jan 2024 01:42:32 +0900 Subject: [PATCH 415/640] Fix up [Bug #20001] --- thread.c | 2 -- thread_pthread.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/thread.c b/thread.c index 27a6ffb95589d1..9314cd5499fbc9 100644 --- a/thread.c +++ b/thread.c @@ -639,8 +639,6 @@ void rb_ec_clear_current_thread_trace_func(const rb_execution_context_t *ec); static int thread_start_func_2(rb_thread_t *th, VALUE *stack_start) { - STACK_GROW_DIR_DETECTION; - RUBY_DEBUG_LOG("th:%u", rb_th_serial(th)); VM_ASSERT(th != th->vm->ractor.main_thread); diff --git a/thread_pthread.c b/thread_pthread.c index 1b518721991ec5..332e50f6e1d748 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -1989,7 +1989,7 @@ native_thread_init_main_thread_stack(void *addr) #else if (!native_main_thread.stack_start || STACK_UPPER((VALUE *)(void *)&addr, - native_main_thread.stack_start > addr, + native_main_thread.stack_start > (VALUE *)addr, native_main_thread.stack_start < (VALUE *)addr)) { native_main_thread.stack_start = (VALUE *)addr; } From 703eee7745935c54e7b80b22b9b695e99f53fc5e Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Mon, 22 Jan 2024 11:55:44 -0500 Subject: [PATCH 416/640] YJIT: Drop extra arguments passed by yield (#9596) Support dropping extra arguments passed by `yield` in blocks. For example `10.times { work }` drops the count argument. This is common enough that it's about 3% of fallback reasons in `lobsters`. Only support simple cases where the surplus arguments are at the top of the stack, that way they just need to be popped, which takes no work. --- bootstraptest/test_yjit.rb | 39 +++++++++++++++ yjit/src/codegen.rs | 97 ++++++++++++++++++++++++-------------- yjit/src/stats.rs | 2 +- 3 files changed, 101 insertions(+), 37 deletions(-) diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index 3bf715f8886506..926eaaf8f61f17 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -1,3 +1,42 @@ +# test discarding extra yield arguments +assert_equal "2210150001501015", %q{ + def splat_kw(ary) = yield *ary, a: 1 + + def splat(ary) = yield *ary + + def kw = yield 1, 2, a: 0 + + def simple = yield 0, 1 + + def calls + [ + splat([1, 1, 2]) { |x, y| x + y }, + splat([1, 1, 2]) { |y, opt = raise| opt + y}, + splat_kw([0, 1]) { |a:| a }, + kw { |a:| a }, + kw { |a| a }, + simple { 5.itself }, + simple { |a| a }, + simple { |opt = raise| opt }, + simple { |*rest| rest }, + simple { |opt_kw: 5| opt_kw }, + # autosplat ineractions + [0, 1, 2].yield_self { |a, b| [a, b] }, + [0, 1, 2].yield_self { |a, opt = raise| [a, opt] }, + [1].yield_self { |a, opt = 4| a + opt }, + ] + end + + calls.join +} + +# test autosplat with empty splat +assert_equal "ok", %q{ + def m(pos, splat) = yield pos, *splat + + m([:ok], []) {|v0,| v0 } +} + # regression test for send stack shifting assert_normal_exit %q{ def foo(a, b) diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index b50cd101634f8e..fcb4c47608f92f 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -6117,6 +6117,7 @@ fn gen_send_iseq( let supplying_kws = unsafe { vm_ci_flag(ci) & VM_CALL_KWARG } != 0; let iseq_has_rest = unsafe { get_iseq_flags_has_rest(iseq) }; let iseq_has_block_param = unsafe { get_iseq_flags_has_block(iseq) }; + let arg_setup_block = captured_opnd.is_some(); // arg_setup_type: arg_setup_block (invokeblock) // For computing offsets to callee locals let num_params = unsafe { get_iseq_body_param_size(iseq) }; @@ -6137,10 +6138,10 @@ fn gen_send_iseq( // Arity handling and optional parameter setup let mut opts_filled = argc - required_num - kw_arg_num; let opt_num = unsafe { get_iseq_body_param_opt_num(iseq) }; - // We have a rest parameter so there could be more args - // than are required + optional. Those will go in rest. + // With a rest parameter or a yield to a block, + // callers can pass more than required + optional. // So we cap ops_filled at opt_num. - if iseq_has_rest { + if iseq_has_rest || arg_setup_block { opts_filled = min(opts_filled, opt_num); } let mut opts_missing: i32 = opt_num - opts_filled; @@ -6159,11 +6160,17 @@ fn gen_send_iseq( exit_if_supplying_kws_and_accept_no_kwargs(asm, supplying_kws, iseq)?; exit_if_splat_and_zsuper(asm, flags)?; exit_if_doing_kw_and_splat(asm, doing_kw_call, flags)?; - exit_if_wrong_number_arguments(asm, opts_filled, flags, opt_num, iseq_has_rest)?; + exit_if_wrong_number_arguments(asm, arg_setup_block, opts_filled, flags, opt_num, iseq_has_rest)?; exit_if_doing_kw_and_opts_missing(asm, doing_kw_call, opts_missing)?; exit_if_has_rest_and_optional_and_block(asm, iseq_has_rest, opt_num, iseq, block_arg)?; let block_arg_type = exit_if_unsupported_block_arg_type(jit, asm, block_arg)?; + // Bail if we can't drop extra arguments for a yield by just popping them + if supplying_kws && arg_setup_block && argc > (kw_arg_num + required_num + opt_num) { + gen_counter_incr(asm, Counter::send_iseq_complex_discard_extras); + return None; + } + // Block parameter handling. This mirrors setup_parameters_complex(). if iseq_has_block_param { if unsafe { get_iseq_body_local_iseq(iseq) == iseq } { @@ -6249,35 +6256,6 @@ fn gen_send_iseq( } } - // Check if we need the arg0 splat handling of vm_callee_setup_block_arg() - // Also known as "autosplat" inside setup_parameters_complex() - let arg_setup_block = captured_opnd.is_some(); // arg_setup_type: arg_setup_block (invokeblock) - let block_arg0_splat = arg_setup_block && argc == 1 && unsafe { - (get_iseq_flags_has_lead(iseq) || opt_num > 1) - && !get_iseq_flags_ambiguous_param0(iseq) - }; - if block_arg0_splat { - // If block_arg0_splat, we still need side exits after splat, but - // doing push_splat_args here disallows it. So bail out. - if flags & VM_CALL_ARGS_SPLAT != 0 && !iseq_has_rest { - gen_counter_incr(asm, Counter::invokeblock_iseq_arg0_args_splat); - return None; - } - // The block_arg0_splat implementation is for the rb_simple_iseq_p case, - // but doing_kw_call means it's not a simple ISEQ. - if doing_kw_call { - gen_counter_incr(asm, Counter::invokeblock_iseq_arg0_has_kw); - return None; - } - // The block_arg0_splat implementation cannot deal with optional parameters. - // This is a setup_parameters_complex() situation and interacts with the - // starting position of the callee. - if opt_num > 1 { - gen_counter_incr(asm, Counter::invokeblock_iseq_arg0_optional); - return None; - } - } - let splat_array_length = if flags & VM_CALL_ARGS_SPLAT != 0 { let array = jit.peek_at_stack(&asm.ctx, if block_arg { 1 } else { 0 }) ; let array_length = if array == Qnil { @@ -6318,6 +6296,33 @@ fn gen_send_iseq( None }; + // Check if we need the arg0 splat handling of vm_callee_setup_block_arg() + // Also known as "autosplat" inside setup_parameters_complex(). + // Autosplat checks argc == 1 after splat and kwsplat processing, so make + // sure to amend this if we start support kw_splat. + let block_arg0_splat = arg_setup_block + && (argc == 1 || (argc == 2 && splat_array_length == Some(0))) + && !supplying_kws && !doing_kw_call + && unsafe { + (get_iseq_flags_has_lead(iseq) || opt_num > 1) + && !get_iseq_flags_ambiguous_param0(iseq) + }; + if block_arg0_splat { + // If block_arg0_splat, we still need side exits after splat, but + // the splat modifies the stack which breaks side exits. So bail out. + if flags & VM_CALL_ARGS_SPLAT != 0 { + gen_counter_incr(asm, Counter::invokeblock_iseq_arg0_args_splat); + return None; + } + // The block_arg0_splat implementation cannot deal with optional parameters. + // This is a setup_parameters_complex() situation and interacts with the + // starting position of the callee. + if opt_num > 1 { + gen_counter_incr(asm, Counter::invokeblock_iseq_arg0_optional); + return None; + } + } + // Adjust `opts_filled` and `opts_missing` taking // into account the size of the splat expansion. if let Some(len) = splat_array_length { @@ -6605,6 +6610,19 @@ fn gen_send_iseq( asm.store(rest_param, rest_param_array); } + // Pop surplus positional arguments when yielding + if arg_setup_block { + let extras = argc - required_num - opt_num; + if extras > 0 { + // Checked earlier. If there are keyword args, then + // the positional arguments are not at the stack top. + assert_eq!(0, kw_arg_num); + + asm.stack_pop(extras as usize); + argc = required_num + opt_num; + } + } + if doing_kw_call { // Here we're calling a method with keyword arguments and specifying // keyword arguments at this call site. @@ -7034,11 +7052,18 @@ fn exit_if_doing_kw_and_splat(asm: &mut Assembler, doing_kw_call: bool, flags: u } #[must_use] -fn exit_if_wrong_number_arguments(asm: &mut Assembler, opts_filled: i32, flags: u32, opt_num: i32, iseq_has_rest: bool) -> Option<()> { +fn exit_if_wrong_number_arguments( + asm: &mut Assembler, + args_setup_block: bool, + opts_filled: i32, + flags: u32, + opt_num: i32, + iseq_has_rest: bool, +) -> Option<()> { // Too few arguments and no splat to make up for it let too_few = opts_filled < 0 && flags & VM_CALL_ARGS_SPLAT == 0; - // Too many arguments and no place to put them (i.e. rest arg) - let too_many = opts_filled > opt_num && !iseq_has_rest; + // Too many arguments and no sink that take them + let too_many = opts_filled > opt_num && !(iseq_has_rest || args_setup_block); exit_if(asm, too_few || too_many, Counter::send_iseq_arity_error) } diff --git a/yjit/src/stats.rs b/yjit/src/stats.rs index 1dd5f57b2bb16f..7df01448a46d1a 100644 --- a/yjit/src/stats.rs +++ b/yjit/src/stats.rs @@ -331,6 +331,7 @@ make_counters! { send_iseq_arity_error, send_iseq_block_arg_type, send_iseq_clobbering_block_arg, + send_iseq_complex_discard_extras, send_iseq_leaf_builtin_block_arg_block_param, send_iseq_only_keywords, send_iseq_kw_splat, @@ -391,7 +392,6 @@ make_counters! { invokeblock_megamorphic, invokeblock_none, invokeblock_iseq_arg0_optional, - invokeblock_iseq_arg0_has_kw, invokeblock_iseq_arg0_args_splat, invokeblock_iseq_arg0_not_array, invokeblock_iseq_arg0_wrong_len, From 4fc0a901ac683eaebc39db1948f8f0db6d8bd19f Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Mon, 22 Jan 2024 09:49:52 -0800 Subject: [PATCH 417/640] Set a cached Ruby path using setup-ruby (#9645) --- .github/workflows/windows.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 098d709bb7dc46..1f251b06cdf57c 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -96,6 +96,12 @@ jobs: ${{ steps.find-tools.outputs.needs }} if: ${{ steps.find-tools.outputs.needs != '' }} + - uses: ruby/setup-ruby@5daca165445f0ae10478593083f72ca2625e241d # v1.169.0 + with: + ruby-version: '2.7' + bundler: none + windows-toolchain: none + - uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 with: path: C:\vcpkg\downloads @@ -147,7 +153,6 @@ jobs: set TEMP=%USERPROFILE%\AppData\Local\Temp set MAKEFLAGS=l set /a TEST_JOBS=(15 * %NUMBER_OF_PROCESSORS% / 10) > nul - set PATH=C:\hostedtoolcache\windows\Ruby\2.7.8\x64\bin;%PATH% set | C:\msys64\usr\bin\sort > new.env C:\msys64\usr\bin\comm -13 old.env new.env >> %GITHUB_ENV% del *.env From e5f8585a2999bff59e8b79605db7868bf702f84b Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 22 Jan 2024 11:55:50 -0500 Subject: [PATCH 418/640] [PRISM] Fix line for leave instructions --- prism_compile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 6ae9e094b2ee21..8f86b92975fe51 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -3358,8 +3358,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, int lineno = (int)pm_newline_list_line_column(&newline_list, node->location.start).line; NODE dummy_line_node = generate_dummy_line_node(lineno, lineno); - if (node->flags & PM_NODE_FLAG_NEWLINE && - ISEQ_COMPILE_DATA(iseq)->last_line != lineno) { + if (node->flags & PM_NODE_FLAG_NEWLINE && ISEQ_COMPILE_DATA(iseq)->last_line != lineno) { int event = RUBY_EVENT_LINE; ISEQ_COMPILE_DATA(iseq)->last_line = lineno; @@ -6917,6 +6916,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } if (!PM_NODE_TYPE_P(scope_node->ast_node, PM_ENSURE_NODE)) { + NODE dummy_line_node = generate_dummy_line_node(ISEQ_COMPILE_DATA(iseq)->last_line, -1); ADD_INSN(ret, &dummy_line_node, leave); } return; From ab99ce910ce9a7aeb0b8a3224a1ed1e3e5faf71f Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 22 Jan 2024 11:36:55 -0500 Subject: [PATCH 419/640] [PRISM] Insert concatarray for index targets with splat --- prism_compile.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 8f86b92975fe51..40d2eb9806a21b 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -1147,7 +1147,7 @@ pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinf } else { // If this is not the first splat array seen and it is also - // the last parameter, we don't want splayarray to dup it + // the last parameter, we don't want splatarray to dup it // and we need to concat the array. // // foo(a, *b, *c) @@ -3110,7 +3110,7 @@ pm_compile_target_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *cons if (cast->block != NULL) { flags |= VM_CALL_ARGS_BLOCKARG; - if (cast->block != NULL) pm_compile_node(iseq, cast->block, writes, src, false, scope_node); + if (cast->block != NULL) pm_compile_node(iseq, cast->block, parents, src, false, scope_node); } if (state != NULL) { @@ -3127,7 +3127,18 @@ pm_compile_target_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *cons } } - ADD_SEND_R(writes, &dummy_line_node, idASET, INT2NUM(argc + 1), NULL, INT2FIX(flags), kwargs); + // The argc that we're going to pass to the send instruction is the + // number of arguments + 1 for the value being written. If there's a + // splat, then we need to insert newarray and concatarray instructions + // after the arguments have been written. + int ci_argc = argc + 1; + if (flags & VM_CALL_ARGS_SPLAT) { + ci_argc--; + ADD_INSN1(writes, &dummy_line_node, newarray, INT2FIX(1)); + ADD_INSN(writes, &dummy_line_node, concatarray); + } + + ADD_SEND_R(writes, &dummy_line_node, idASET, INT2NUM(ci_argc), NULL, INT2FIX(flags), kwargs); ADD_INSN(writes, &dummy_line_node, pop); if (state != NULL) { From dbd76d9101cfb35b483ad5e173fc153102c9d03e Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 22 Jan 2024 11:43:00 -0500 Subject: [PATCH 420/640] [PRISM] Fix keyword splat in IndexAndWriteNode and IndexOrWriteNode Fixes ruby/prism#2232 and ruby/prism#2234. --- prism_compile.c | 11 +++++++++++ test/ruby/test_compile_prism.rb | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 40d2eb9806a21b..4d139a57b3713c 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -952,6 +952,17 @@ pm_compile_index_write_nodes_add_send(bool popped, LINK_ANCHOR *const ret, rb_is } ADD_SEND_WITH_FLAG(ret, &dummy_line_node, idASET, argc, INT2FIX(flag)); } + else if (flag & VM_CALL_KW_SPLAT) { + if (block_offset > 0) { + ADD_INSN1(ret, &dummy_line_node, topn, INT2FIX(2)); + PM_SWAP; + ADD_INSN1(ret, &dummy_line_node, setn, INT2FIX(3)); + PM_POP; + } + + ADD_INSN(ret, &dummy_line_node, swap); + ADD_SEND_R(ret, &dummy_line_node, idASET, FIXNUM_INC(argc, 1), NULL, INT2FIX(flag), keywords); + } else if (keywords && keywords->keyword_len) { ADD_INSN1(ret, &dummy_line_node, opt_reverse, INT2FIX(keywords->keyword_len + block_offset + 1)); ADD_INSN1(ret, &dummy_line_node, opt_reverse, INT2FIX(keywords->keyword_len + block_offset + 0)); diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 0998c8fa5da2e8..8f42fb585174fa 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -394,6 +394,15 @@ def h.[]=(*a, **b); end h[foo: 1] &&= 2 RUBY + + # Test with keyword splat + assert_prism_eval(<<~RUBY) + h = Object.new + def h.[](**b) = 1 + def h.[]=(*a, **b); end + + h[**{}] &&= 2 + RUBY end def test_IndexOrWriteNode @@ -415,6 +424,15 @@ def []=(key, value, &block) hash["key", &(Proc.new { _1.upcase })] ||= "value" hash CODE + + # Test with keyword splat + assert_prism_eval(<<~RUBY) + h = Object.new + def h.[](**b) = nil + def h.[]=(*a, **b); end + + h[**{}] ||= 2 + RUBY end def test_IndexOperatorWriteNode From 2918e43deebbc270c75a3af2c46630e5a7c91586 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Mon, 22 Jan 2024 10:31:18 -0800 Subject: [PATCH 421/640] Skip a flaky Ractor test for YJIT `[BUG] pthread_mutex_lock: Invalid argument (EINVAL)` doesn't seem like a fault of YJIT? https://github.com/ruby/ruby/actions/runs/7614455181/job/20736754975 https://github.com/ruby/ruby/actions/runs/7615316673/job/20739572487 --- bootstraptest/runner.rb | 4 ++++ bootstraptest/test_ractor.rb | 5 ++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/bootstraptest/runner.rb b/bootstraptest/runner.rb index a34527d2fa0963..039a15148d2c43 100755 --- a/bootstraptest/runner.rb +++ b/bootstraptest/runner.rb @@ -789,6 +789,10 @@ def check_coredump end end +def yjit_enabled? + ENV.key?('RUBY_YJIT_ENABLE') || ENV.fetch('RUN_OPTS', '').include?('yjit') || BT.ruby.include?('yjit') +end + def rjit_enabled? # Don't check `RubyVM::RJIT.enabled?`. On btest-bruby, target Ruby != runner Ruby. ENV.fetch('RUN_OPTS', '').include?('rjit') diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb index 0308ed80cad14e..4db203503cad1e 100644 --- a/bootstraptest/test_ractor.rb +++ b/bootstraptest/test_ractor.rb @@ -1553,7 +1553,7 @@ class C 1_000.times { idle_worker, tmp_reporter = Ractor.select(*workers) } "ok" -} unless ENV['RUN_OPTS'] =~ /rjit/ # flaky +} unless yjit_enabled? || rjit_enabled? # flaky assert_equal "ok", %q{ def foo(*); ->{ super }; end @@ -1750,7 +1750,6 @@ class C8; def self.foo = 17; end } if defined? Ractor::Selector # Selector#wait can support dynamic addition -yjit_enabled = ENV.key?('RUBY_YJIT_ENABLE') || ENV.fetch('RUN_OPTS', '').include?('yjit') || BT.ruby.include?('yjit') assert_equal '600', %q{ skip 600 unless defined? Ractor::Selector @@ -1779,7 +1778,7 @@ class C8; def self.foo = 17; end end h.sum{|k, v| v} -} unless yjit_enabled # http://ci.rvm.jp/results/trunk-yjit@ruby-sp2-docker/4466770 +} unless yjit_enabled? # http://ci.rvm.jp/results/trunk-yjit@ruby-sp2-docker/4466770 # Selector should be GCed (free'ed) without trouble assert_equal 'ok', %q{ From 1236cad92d509c299f0199c69ed752ea92f21023 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 15:16:44 +0000 Subject: [PATCH 422/640] [rubygems/rubygems] Bump rb-sys Bumps [rb-sys](https://github.com/oxidize-rb/rb-sys) from 0.9.86 to 0.9.87. - [Release notes](https://github.com/oxidize-rb/rb-sys/releases) - [Commits](https://github.com/oxidize-rb/rb-sys/compare/v0.9.86...v0.9.87) --- updated-dependencies: - dependency-name: rb-sys dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] https://github.com/rubygems/rubygems/commit/d86482f0b0 --- .../rust_ruby_example/Cargo.lock | 8 ++++---- .../rust_ruby_example/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock index 8c394aec20f8c7..5f161882145444 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock +++ b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock @@ -145,18 +145,18 @@ dependencies = [ [[package]] name = "rb-sys" -version = "0.9.86" +version = "0.9.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7285f2a7b92f58ab198e3fd59a71d2861478f9c4642f41e83582385818941697" +checksum = "225103e3d69bbfe8831f9fd0d2461335f3a9dd06aa6e88bcb6d6970383494d06" dependencies = [ "rb-sys-build", ] [[package]] name = "rb-sys-build" -version = "0.9.86" +version = "0.9.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71583945f94dabb6c0dfa63f1b71e929c1901e1e288ef3739ab8bed3b7069550" +checksum = "bacce8095a5167d5ede618bbd9353e9d9e2f32ddaf54be911106f0ee6baacf09" dependencies = [ "bindgen", "lazy_static", diff --git a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml index 39b2ae39192a31..391a4de571b3ce 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml +++ b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -rb-sys = "0.9.86" +rb-sys = "0.9.87" From 7db683222528ca4850fed57529679e5aa14b0a88 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 22 Jan 2024 11:24:34 -0800 Subject: [PATCH 423/640] Fix compiling rescue + ensure When we're compiling begin / rescue / ensure nodes, we need to "wrap" the code in the begin statements correctly. The wrapping is like this: (ensure code (rescue code (begin code))) This patch pulls the each leg in to its own function, then calls the appropriate wrapping function depending on whether there are ensure / rescue legs. Fixes: https://github.com/ruby/prism/issues/2221 --- prism_compile.c | 210 +++++++++++++++++--------------- test/ruby/test_compile_prism.rb | 16 +++ tool/prism_btests | 2 +- 3 files changed, 131 insertions(+), 97 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 4d139a57b3713c..359396567ae1d9 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -3362,6 +3362,111 @@ pm_compile_for_node_index(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *c } } +static void +pm_compile_rescue(rb_iseq_t *iseq, pm_begin_node_t *begin_node, LINK_ANCHOR *const ret, const uint8_t *src, int lineno, bool popped, pm_scope_node_t *scope_node) +{ + NODE dummy_line_node = generate_dummy_line_node(lineno, lineno); + pm_parser_t *parser = scope_node->parser; + LABEL *lstart = NEW_LABEL(lineno); + LABEL *lend = NEW_LABEL(lineno); + LABEL *lcont = NEW_LABEL(lineno); + + pm_scope_node_t rescue_scope_node; + pm_scope_node_init((pm_node_t *)begin_node->rescue_clause, &rescue_scope_node, scope_node, parser); + rb_iseq_t *rescue_iseq = NEW_CHILD_ISEQ(&rescue_scope_node, + rb_str_concat(rb_str_new2("rescue in"), + ISEQ_BODY(iseq)->location.label), + ISEQ_TYPE_RESCUE, 1); + pm_scope_node_destroy(&rescue_scope_node); + + lstart->rescued = LABEL_RESCUE_BEG; + lend->rescued = LABEL_RESCUE_END; + ADD_LABEL(ret, lstart); + bool prev_in_rescue = ISEQ_COMPILE_DATA(iseq)->in_rescue; + ISEQ_COMPILE_DATA(iseq)->in_rescue = true; + if (begin_node->statements) { + PM_COMPILE_NOT_POPPED((pm_node_t *)begin_node->statements); + } + else { + PM_PUTNIL; + } + ISEQ_COMPILE_DATA(iseq)->in_rescue = prev_in_rescue; + + if (begin_node->else_clause) { + PM_POP_UNLESS_POPPED; + PM_COMPILE((pm_node_t *)begin_node->else_clause); + } + + ADD_LABEL(ret, lend); + PM_NOP; + ADD_LABEL(ret, lcont); + + PM_POP_IF_POPPED; + ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue_iseq, lcont); + ADD_CATCH_ENTRY(CATCH_TYPE_RETRY, lend, lcont, NULL, lstart); +} + +static void +pm_compile_ensure(rb_iseq_t *iseq, pm_begin_node_t *begin_node, LINK_ANCHOR *const ret, const uint8_t *src, int lineno, bool popped, pm_scope_node_t *scope_node) +{ + NODE dummy_line_node = generate_dummy_line_node(lineno, lineno); + pm_parser_t *parser = scope_node->parser; + + LABEL *estart = NEW_LABEL(lineno); + LABEL *eend = NEW_LABEL(lineno); + LABEL *econt = NEW_LABEL(lineno); + + struct ensure_range er; + struct iseq_compile_data_ensure_node_stack enl; + struct ensure_range *erange; + + er.begin = estart; + er.end = eend; + er.next = 0; + push_ensure_entry(iseq, &enl, &er, (void *)begin_node->ensure_clause); + + ADD_LABEL(ret, estart); + if (begin_node->rescue_clause) { + pm_compile_rescue(iseq, begin_node, ret, src, lineno, popped, scope_node); + } + else { + if (begin_node->statements) { + PM_COMPILE((pm_node_t *)begin_node->statements); + } + else { + PM_PUTNIL_UNLESS_POPPED; + } + } + + ADD_LABEL(ret, eend); + ADD_LABEL(ret, econt); + + pm_scope_node_t next_scope_node; + pm_scope_node_init((pm_node_t *)begin_node->ensure_clause, &next_scope_node, scope_node, parser); + rb_iseq_t * child_iseq = NEW_CHILD_ISEQ(&next_scope_node, + rb_str_new2("ensure in"), + ISEQ_TYPE_ENSURE, lineno); + pm_scope_node_destroy(&next_scope_node); + + ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq; + + erange = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack->erange; + if (estart->link.next != &eend->link) { + while (erange) { + ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE, erange->begin, erange->end, child_iseq, econt); + erange = erange->next; + } + } + ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = enl.prev; + + // Compile the ensure entry + pm_statements_node_t *statements = begin_node->ensure_clause->statements; + if (statements) { + PM_COMPILE((pm_node_t *)statements); + PM_POP_UNLESS_POPPED; + } +} + /* * Compiles a prism node into instruction sequences * @@ -3598,105 +3703,18 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } case PM_BEGIN_NODE: { pm_begin_node_t *begin_node = (pm_begin_node_t *) node; - rb_iseq_t *child_iseq; - - if (begin_node->rescue_clause) { - LABEL *lstart = NEW_LABEL(lineno); - LABEL *lend = NEW_LABEL(lineno); - LABEL *lcont = NEW_LABEL(lineno); - - pm_scope_node_t rescue_scope_node; - pm_scope_node_init((pm_node_t *)begin_node->rescue_clause, &rescue_scope_node, scope_node, parser); - rb_iseq_t *rescue_iseq = NEW_CHILD_ISEQ(&rescue_scope_node, - rb_str_concat(rb_str_new2("rescue in"), - ISEQ_BODY(iseq)->location.label), - ISEQ_TYPE_RESCUE, 1); - pm_scope_node_destroy(&rescue_scope_node); - - lstart->rescued = LABEL_RESCUE_BEG; - lend->rescued = LABEL_RESCUE_END; - ADD_LABEL(ret, lstart); - bool prev_in_rescue = ISEQ_COMPILE_DATA(iseq)->in_rescue; - ISEQ_COMPILE_DATA(iseq)->in_rescue = true; - if (begin_node->statements) { - PM_COMPILE_NOT_POPPED((pm_node_t *)begin_node->statements); - } - else { - PM_PUTNIL; - } - ISEQ_COMPILE_DATA(iseq)->in_rescue = prev_in_rescue; - if (begin_node->else_clause) { - PM_POP_UNLESS_POPPED; - PM_COMPILE((pm_node_t *)begin_node->else_clause); - } - - ADD_LABEL(ret, lend); - PM_NOP; - ADD_LABEL(ret, lcont); - - PM_POP_IF_POPPED; - ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue_iseq, lcont); - ADD_CATCH_ENTRY(CATCH_TYPE_RETRY, lend, lcont, NULL, lstart); - } if (begin_node->ensure_clause) { - LABEL *estart = NEW_LABEL(lineno); - LABEL *eend = NEW_LABEL(lineno); - LABEL *econt = NEW_LABEL(lineno); - - struct ensure_range er; - struct iseq_compile_data_ensure_node_stack enl; - struct ensure_range *erange; - - er.begin = estart; - er.end = eend; - er.next = 0; - push_ensure_entry(iseq, &enl, &er, (void *)begin_node->ensure_clause); - - ADD_LABEL(ret, estart); - if (!begin_node->rescue_clause) { - if (begin_node->statements) { - PM_COMPILE((pm_node_t *)begin_node->statements); - } - else { - PM_PUTNIL_UNLESS_POPPED; - } - } - - ADD_LABEL(ret, eend); - ADD_LABEL(ret, econt); - - if (!popped) { - PM_NOP; - } - - pm_scope_node_t next_scope_node; - pm_scope_node_init((pm_node_t *)begin_node->ensure_clause, &next_scope_node, scope_node, parser); - child_iseq = NEW_CHILD_ISEQ(&next_scope_node, - rb_str_new2("ensure in"), - ISEQ_TYPE_ENSURE, lineno); - pm_scope_node_destroy(&next_scope_node); - - ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq; - - erange = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack->erange; - if (estart->link.next != &eend->link) { - while (erange) { - ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE, erange->begin, erange->end, child_iseq, econt); - erange = erange->next; - } - } - ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = enl.prev; - - // Compile the ensure entry - pm_statements_node_t *statements = begin_node->ensure_clause->statements; - if (statements) { - PM_COMPILE((pm_node_t *)statements); - PM_POP_UNLESS_POPPED; - } + // Compiling the ensure clause will compile the rescue clause (if + // there is one), which will compile the begin statements + pm_compile_ensure(iseq, begin_node, ret, src, lineno, popped, scope_node); } - - if (!begin_node->rescue_clause && !begin_node->ensure_clause) { + else if (begin_node->rescue_clause) { + // Compiling rescue will compile begin statements (if applicable) + pm_compile_rescue(iseq, begin_node, ret, src, lineno, popped, scope_node); + } + else { + // If there is neither ensure or rescue, the just compile statements if (begin_node->statements) { PM_COMPILE((pm_node_t *)begin_node->statements); } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 8f42fb585174fa..29f0530462b820 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1506,6 +1506,22 @@ def self.prism_test_def_node(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, CODE end + def test_rescue_with_ensure + assert_prism_eval(<<-CODE) +begin + begin + raise "a" + rescue + raise "b" + ensure + raise "c" + end +rescue => e + e.message +end + CODE + end + def test_required_kwarg_ordering assert_prism_eval("def self.foo(a: 1, b:); [a, b]; end; foo(b: 2)") end diff --git a/tool/prism_btests b/tool/prism_btests index 04e58ae85c395b..aa6806a2b10fae 100644 --- a/tool/prism_btests +++ b/tool/prism_btests @@ -28,7 +28,7 @@ ../src/bootstraptest/test_yjit_30k_ifelse.rb ../src/bootstraptest/test_yjit_30k_methods.rb ../src/bootstraptest/test_yjit_rust_port.rb -# ../src/bootstraptest/test_exception.rb +../src/bootstraptest/test_exception.rb # ../src/bootstraptest/test_insns.rb # ../src/bootstraptest/test_method.rb # ../src/bootstraptest/test_ractor.rb From 789de5972bef671ff820a52dd97121c8984819a9 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 22 Jan 2024 15:16:14 -0500 Subject: [PATCH 424/640] [PRISM] Use PM_POP macro --- prism_compile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 359396567ae1d9..a700eb22625cf9 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2716,7 +2716,7 @@ pm_compile_call(rb_iseq_t *iseq, const pm_call_node_t *call_node, LINK_ANCHOR *c ADD_INSN1(ret, &dummy_line_node, putobject, INT2FIX(-1)); ADD_SEND_WITH_FLAG(ret, &dummy_line_node, idAREF, INT2FIX(1), INT2FIX(0)); ADD_INSN1(ret, &dummy_line_node, setn, INT2FIX(orig_argc + 2)); - ADD_INSN (ret, &dummy_line_node, pop); + PM_POP; } else if (!popped) { ADD_INSN1(ret, &dummy_line_node, setn, INT2FIX(orig_argc + 1)); @@ -3349,7 +3349,7 @@ pm_compile_for_node_index(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *c ADD_INSN(ret, &dummy_line_node, swap); ADD_LABEL(ret, not_ary); - ADD_INSN(ret, &dummy_line_node, pop); + PM_POP; ADD_LABEL(ret, not_single); ADD_SEQ(ret, writes); From 263094169671b9f87ab7c0a2f79b3aff5cdf995c Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 22 Jan 2024 15:21:09 -0500 Subject: [PATCH 425/640] [PRISM] Use PM_SWAP macro --- prism_compile.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index a700eb22625cf9..be4e5d47fc4c0d 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -960,7 +960,7 @@ pm_compile_index_write_nodes_add_send(bool popped, LINK_ANCHOR *const ret, rb_is PM_POP; } - ADD_INSN(ret, &dummy_line_node, swap); + PM_SWAP; ADD_SEND_R(ret, &dummy_line_node, idASET, FIXNUM_INC(argc, 1), NULL, INT2FIX(flag), keywords); } else if (keywords && keywords->keyword_len) { @@ -3342,11 +3342,11 @@ pm_compile_for_node_index(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *c ADD_INSN1(ret, &dummy_line_node, putobject, INT2FIX(0)); ADD_CALL(ret, &dummy_line_node, idAREF, INT2FIX(1)); ADD_INSN1(ret, &dummy_line_node, putobject, rb_cArray); - ADD_INSN(ret, &dummy_line_node, swap); + PM_SWAP; ADD_CALL(ret, &dummy_line_node, rb_intern("try_convert"), INT2FIX(1)); ADD_INSN(ret, &dummy_line_node, dup); ADD_INSNL(ret, &dummy_line_node, branchunless, not_ary); - ADD_INSN(ret, &dummy_line_node, swap); + PM_SWAP; ADD_LABEL(ret, not_ary); PM_POP; From 8065672d9978e4ed7ed6895556e462b50508ec8a Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 22 Jan 2024 15:22:12 -0500 Subject: [PATCH 426/640] [PRISM] Force semicolon at the end of PM macros --- prism_compile.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index be4e5d47fc4c0d..be47806fbd9c8e 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -25,37 +25,37 @@ pm_compile_node(iseq, (node), ret, src, false, scope_node) #define PM_POP \ - ADD_INSN(ret, &dummy_line_node, pop); + ADD_INSN(ret, &dummy_line_node, pop) #define PM_POP_IF_POPPED \ - if (popped) PM_POP; + if (popped) PM_POP #define PM_POP_UNLESS_POPPED \ - if (!popped) PM_POP; + if (!popped) PM_POP #define PM_DUP \ - ADD_INSN(ret, &dummy_line_node, dup); + ADD_INSN(ret, &dummy_line_node, dup) #define PM_DUP_UNLESS_POPPED \ - if (!popped) PM_DUP; + if (!popped) PM_DUP #define PM_PUTSELF \ - ADD_INSN(ret, &dummy_line_node, putself); + ADD_INSN(ret, &dummy_line_node, putself) #define PM_PUTNIL \ - ADD_INSN(ret, &dummy_line_node, putnil); + ADD_INSN(ret, &dummy_line_node, putnil) #define PM_PUTNIL_UNLESS_POPPED \ - if (!popped) PM_PUTNIL; + if (!popped) PM_PUTNIL #define PM_SWAP \ - ADD_INSN(ret, &dummy_line_node, swap); + ADD_INSN(ret, &dummy_line_node, swap) #define PM_SWAP_UNLESS_POPPED \ - if (!popped) PM_SWAP; + if (!popped) PM_SWAP #define PM_NOP \ - ADD_INSN(ret, &dummy_line_node, nop); + ADD_INSN(ret, &dummy_line_node, nop) /** * We're using the top most bit of a pm_constant_id_t as a tag to represent an @@ -5797,7 +5797,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, return; } case PM_NIL_NODE: - PM_PUTNIL_UNLESS_POPPED + PM_PUTNIL_UNLESS_POPPED; return; case PM_NO_KEYWORDS_PARAMETER_NODE: { ISEQ_BODY(iseq)->param.flags.accepts_no_kwarg = TRUE; From 47264b78c2e1be441d043a404f8b0d0bf7d8f62b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 21:36:58 +0000 Subject: [PATCH 427/640] Bump shlex Bumps [shlex](https://github.com/comex/rust-shlex) from 1.1.0 to 1.3.0. - [Changelog](https://github.com/comex/rust-shlex/blob/master/CHANGELOG.md) - [Commits](https://github.com/comex/rust-shlex/commits) --- updated-dependencies: - dependency-name: shlex dependency-type: indirect ... Signed-off-by: dependabot[bot] --- .../test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock index 5f161882145444..7583bb7822e94f 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock +++ b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock @@ -205,9 +205,9 @@ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] name = "shlex" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "syn" From bd1895990ce060feda7cd2f68e1199a761136d98 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 14:11:07 -0800 Subject: [PATCH 428/640] Bump shlex from 1.1.0 to 1.3.0 in /yjit/bindgen (#9652) Bumps [shlex](https://github.com/comex/rust-shlex) from 1.1.0 to 1.3.0. - [Changelog](https://github.com/comex/rust-shlex/blob/master/CHANGELOG.md) - [Commits](https://github.com/comex/rust-shlex/commits) --- updated-dependencies: - dependency-name: shlex dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yjit/bindgen/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yjit/bindgen/Cargo.lock b/yjit/bindgen/Cargo.lock index fc8d3927c49a58..6338d9fea8ad4d 100644 --- a/yjit/bindgen/Cargo.lock +++ b/yjit/bindgen/Cargo.lock @@ -279,9 +279,9 @@ dependencies = [ [[package]] name = "shlex" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "syn" From dcabe87fc8b8523cabea533df18d2b3b616e78da Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 21:43:56 +0000 Subject: [PATCH 429/640] Bump shlex Bumps [shlex](https://github.com/comex/rust-shlex) from 1.1.0 to 1.3.0. - [Changelog](https://github.com/comex/rust-shlex/blob/master/CHANGELOG.md) - [Commits](https://github.com/comex/rust-shlex/commits) --- updated-dependencies: - dependency-name: shlex dependency-type: indirect ... Signed-off-by: dependabot[bot] --- .../custom_name/ext/custom_name_lib/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock index aa9587b2313e9d..6059798dba979f 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock +++ b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock @@ -205,9 +205,9 @@ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] name = "shlex" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "syn" From cffa54acad13fb633739fadd51f5ff79484f9aa8 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Mon, 22 Jan 2024 14:33:51 -0800 Subject: [PATCH 430/640] Try to exclude rubygems Rust stuff from dependabot It should be managed in rubygems/rubygems and sync-ed to ruby/ruby. We shouldn't get PRs to rubygems in ruby/ruby. --- .github/dependabot.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ef07b0fa3f2b04..426893be2af281 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -12,3 +12,7 @@ updates: directory: '/.github/actions/setup/directories' schedule: interval: 'daily' + - package-ecosystem: 'cargo' + directory: '/yjit' + schedule: + interval: 'daily' From 28fc7fa852e6543cdd74c66c1130348085d7f241 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Mon, 22 Jan 2024 14:34:38 -0800 Subject: [PATCH 431/640] Revert "Bump shlex" This reverts commit dcabe87fc8b8523cabea533df18d2b3b616e78da. Revert "Bump shlex" This reverts commit 47264b78c2e1be441d043a404f8b0d0bf7d8f62b. Avoid diversion in gem sync. They should be managed in rubygems/rubygems and then sync-ed to ruby/ruby. --- .../custom_name/ext/custom_name_lib/Cargo.lock | 4 ++-- .../test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock index 6059798dba979f..aa9587b2313e9d 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock +++ b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock @@ -205,9 +205,9 @@ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] name = "shlex" -version = "1.3.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" [[package]] name = "syn" diff --git a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock index 7583bb7822e94f..5f161882145444 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock +++ b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock @@ -205,9 +205,9 @@ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] name = "shlex" -version = "1.3.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" [[package]] name = "syn" From a64e26c5d5363719c91e5db2a0c9946c7b2e85f9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 14:44:00 -0800 Subject: [PATCH 432/640] Bump capstone from 0.10.0 to 0.11.0 in /yjit (#9653) Bumps [capstone](https://github.com/capstone-rust/capstone-rs) from 0.10.0 to 0.11.0. - [Release notes](https://github.com/capstone-rust/capstone-rs/releases) - [Changelog](https://github.com/capstone-rust/capstone-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/capstone-rust/capstone-rs/compare/capstone-v0.10.0...capstone-v0.11.0) --- updated-dependencies: - dependency-name: capstone dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yjit/Cargo.lock | 8 ++++---- yjit/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/yjit/Cargo.lock b/yjit/Cargo.lock index e9a59cb771eca5..efcac306768278 100644 --- a/yjit/Cargo.lock +++ b/yjit/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "capstone" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66b5d1f14c3539b6ff22fcb602fea5f1c4416148c8b7965a2e74860aa169b7b5" +checksum = "1097e608594dad3bad608295567f757742b883606fe150faf7a9740b849730d8" dependencies = [ "capstone-sys", "libc", @@ -14,9 +14,9 @@ dependencies = [ [[package]] name = "capstone-sys" -version = "0.14.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df653a22d0ad34b0d91cc92a6289d96e44aac1c9a96250a094c9aeec4a91084f" +checksum = "2e7f651d5ec4c2a2e6c508f2c8032655003cd728ec85663e9796616990e25b5a" dependencies = [ "cc", "libc", diff --git a/yjit/Cargo.toml b/yjit/Cargo.toml index 2194402cdd4389..f1a80b9c8ca518 100644 --- a/yjit/Cargo.toml +++ b/yjit/Cargo.toml @@ -15,7 +15,7 @@ crate-type = ["staticlib"] [dependencies] # No required dependencies to simplify build process. TODO: Link to yet to be # written rationale. Optional For development and testing purposes -capstone = { version = "0.10.0", optional = true } +capstone = { version = "0.11.0", optional = true } [features] # NOTE: Development builds select a set of these via configure.ac From 18471923660a5314e0543f0600a4a2278ed399cf Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 22 Jan 2024 15:00:36 -0500 Subject: [PATCH 433/640] [PRISM] Fix block in aset Fixes ruby/prism#2223. --- prism_compile.c | 7 ++++++- test/ruby/test_compile_prism.rb | 9 +++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/prism_compile.c b/prism_compile.c index be47806fbd9c8e..8c4f0fed0a4dd2 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2711,7 +2711,12 @@ pm_compile_call(rb_iseq_t *iseq, const pm_call_node_t *call_node, LINK_ANCHOR *c } if (pm_node->flags & PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE) { - if (flags & VM_CALL_ARGS_SPLAT) { + if (flags & VM_CALL_ARGS_BLOCKARG) { + ADD_INSN1(ret, &dummy_line_node, topn, INT2FIX(1)); + ADD_INSN1(ret, &dummy_line_node, setn, INT2FIX(orig_argc + 3)); + PM_POP; + } + else if (flags & VM_CALL_ARGS_SPLAT) { ADD_INSN(ret, &dummy_line_node, dup); ADD_INSN1(ret, &dummy_line_node, putobject, INT2FIX(-1)); ADD_SEND_WITH_FLAG(ret, &dummy_line_node, idAREF, INT2FIX(1), INT2FIX(0)); diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 29f0530462b820..7705959f4cf78d 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1762,6 +1762,15 @@ def obj.[]=(a, b); 10; end obj[*[1]] = 3 RUBY + # Test passing block inside of []= + assert_prism_eval(<<~RUBY) + obj = Object.new + def obj.[]=(a); end + + p = proc {} + obj[&p] = 4 + RUBY + assert_prism_eval(<<-CODE) def self.prism_opt_var_trail_hash(a = nil, *b, c, **d); end prism_opt_var_trail_hash("a") From 1838dbf6e7f9335e5ad23d9856bd014d18446f07 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 22 Jan 2024 15:13:33 -0500 Subject: [PATCH 434/640] [PRISM] Fix splat and block in aset --- prism_compile.c | 4 ++++ test/ruby/test_compile_prism.rb | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 8c4f0fed0a4dd2..e5ba24115d94f1 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2713,6 +2713,10 @@ pm_compile_call(rb_iseq_t *iseq, const pm_call_node_t *call_node, LINK_ANCHOR *c if (pm_node->flags & PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE) { if (flags & VM_CALL_ARGS_BLOCKARG) { ADD_INSN1(ret, &dummy_line_node, topn, INT2FIX(1)); + if (flags & VM_CALL_ARGS_SPLAT) { + ADD_INSN1(ret, &dummy_line_node, putobject, INT2FIX(-1)); + ADD_SEND_WITH_FLAG(ret, &dummy_line_node, idAREF, INT2FIX(1), INT2FIX(0)); + } ADD_INSN1(ret, &dummy_line_node, setn, INT2FIX(orig_argc + 3)); PM_POP; } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 7705959f4cf78d..fd5787e467e7e4 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1771,6 +1771,15 @@ def obj.[]=(a); end obj[&p] = 4 RUBY + # Test splat and block inside of []= + assert_prism_eval(<<~RUBY) + obj = Object.new + def obj.[]=(a, b); end + + p = proc {} + obj[*[1], &p] = 4 + RUBY + assert_prism_eval(<<-CODE) def self.prism_opt_var_trail_hash(a = nil, *b, c, **d); end prism_opt_var_trail_hash("a") From 708fa7740479823e0758623d43afee7b13beba21 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 22 Jan 2024 13:52:41 -0500 Subject: [PATCH 435/640] [PRISM] Fix keyword arguments in IndexOrWriteNode Fixes ruby/prism#2236. --- prism_compile.c | 4 ++-- test/ruby/test_compile_prism.rb | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index e5ba24115d94f1..3fd9efbf0d7f2b 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -1298,9 +1298,9 @@ pm_compile_index_and_or_write_node(bool and_node, pm_node_t *receiver, pm_node_t ADD_INSNL(ret, &dummy_line_node, jump, lfin); ADD_LABEL(ret, label); if (!popped) { - ADD_INSN1(ret, &dummy_line_node, setn, FIXNUM_INC(argc, 2 + block_offset)); + ADD_INSN1(ret, &dummy_line_node, setn, FIXNUM_INC(argc, 2 + block_offset + (keywords ? keywords->keyword_len : 0))); } - ADD_INSN1(ret, &dummy_line_node, adjuststack, FIXNUM_INC(argc, 2 + block_offset)); + ADD_INSN1(ret, &dummy_line_node, adjuststack, FIXNUM_INC(argc, 2 + block_offset + (keywords ? keywords->keyword_len : 0))); ADD_LABEL(ret, lfin); return; diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index fd5787e467e7e4..f54097ab665a03 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -425,6 +425,15 @@ def []=(key, value, &block) hash CODE + # Test with keyword arguments + assert_prism_eval(<<~RUBY) + h = Object.new + def h.[](**b) = 0 + def h.[]=(*a, **b); end + + h[foo: 1] ||= 2 + RUBY + # Test with keyword splat assert_prism_eval(<<~RUBY) h = Object.new From 2e2dfc46231f8b48518b109a10260933e8be523d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 22:36:44 +0000 Subject: [PATCH 436/640] Bump ruby/setup-ruby from 1.168.0 to 1.169.0 Bumps [ruby/setup-ruby](https://github.com/ruby/setup-ruby) from 1.168.0 to 1.169.0. - [Release notes](https://github.com/ruby/setup-ruby/releases) - [Commits](https://github.com/ruby/setup-ruby/compare/v1.168.0...5daca165445f0ae10478593083f72ca2625e241d) --- updated-dependencies: - dependency-name: ruby/setup-ruby dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/baseruby.yml | 2 +- .github/workflows/mingw.yml | 2 +- .github/workflows/rjit-bindgen.yml | 2 +- .github/workflows/spec_guards.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/baseruby.yml b/.github/workflows/baseruby.yml index 020d181adc25dd..6a42522b41a62e 100644 --- a/.github/workflows/baseruby.yml +++ b/.github/workflows/baseruby.yml @@ -57,7 +57,7 @@ jobs: - ruby-3.3 steps: - - uses: ruby/setup-ruby@432702e864cadc1b56247e31aa341be5be3e129a # v1.168.0 + - uses: ruby/setup-ruby@5daca165445f0ae10478593083f72ca2625e241d # v1.169.0 with: ruby-version: ${{ matrix.ruby }} bundler: none diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml index e05c410db4415b..6d506d18e83360 100644 --- a/.github/workflows/mingw.yml +++ b/.github/workflows/mingw.yml @@ -74,7 +74,7 @@ jobs: steps: - name: Set up Ruby & MSYS2 - uses: ruby/setup-ruby@432702e864cadc1b56247e31aa341be5be3e129a # v1.168.0 + uses: ruby/setup-ruby@5daca165445f0ae10478593083f72ca2625e241d # v1.169.0 with: ruby-version: ${{ matrix.baseruby }} diff --git a/.github/workflows/rjit-bindgen.yml b/.github/workflows/rjit-bindgen.yml index c7303827583e26..6e2cbe4ccf76e1 100644 --- a/.github/workflows/rjit-bindgen.yml +++ b/.github/workflows/rjit-bindgen.yml @@ -52,7 +52,7 @@ jobs: steps: - name: Set up Ruby - uses: ruby/setup-ruby@432702e864cadc1b56247e31aa341be5be3e129a # v1.168.0 + uses: ruby/setup-ruby@5daca165445f0ae10478593083f72ca2625e241d # v1.169.0 with: ruby-version: '3.1' diff --git a/.github/workflows/spec_guards.yml b/.github/workflows/spec_guards.yml index 230ada8f09b815..7f59a0f8dbd81d 100644 --- a/.github/workflows/spec_guards.yml +++ b/.github/workflows/spec_guards.yml @@ -48,7 +48,7 @@ jobs: steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - uses: ruby/setup-ruby@432702e864cadc1b56247e31aa341be5be3e129a # v1.168.0 + - uses: ruby/setup-ruby@5daca165445f0ae10478593083f72ca2625e241d # v1.169.0 with: ruby-version: ${{ matrix.ruby }} bundler: none From 4592fdc545284a0cbf55bd1ada17d0b98a3ae685 Mon Sep 17 00:00:00 2001 From: Matt Valentine-House Date: Mon, 22 Jan 2024 22:24:42 +0000 Subject: [PATCH 437/640] [Prism] path and script name are not the same When loading Ruby from a file, or parsing using RubyVM::InstructionSequence. --- iseq.c | 4 ++-- iseq.h | 2 +- load.c | 2 +- ruby.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/iseq.c b/iseq.c index 170fe444657a01..706629d52b043a 100644 --- a/iseq.c +++ b/iseq.c @@ -1533,7 +1533,7 @@ iseqw_s_compile_file_prism(int argc, VALUE *argv, VALUE self) } rb_iseq_t * -rb_iseq_new_main_prism(pm_string_t *input, pm_options_t *options, VALUE path, VALUE optimize) +rb_iseq_new_main_prism(pm_string_t *input, pm_options_t *options, VALUE script_name, VALUE path, VALUE optimize) { pm_parser_t parser; pm_parser_init(&parser, pm_string_source(input), pm_string_length(input), options); @@ -1543,7 +1543,7 @@ rb_iseq_new_main_prism(pm_string_t *input, pm_options_t *options, VALUE path, VA pm_options_line_set(options, start_line); rb_iseq_t *iseq = iseq_alloc(); - iseqw_s_compile_prism_compile(&parser, optimize, iseq, path, path, start_line); + iseqw_s_compile_prism_compile(&parser, optimize, iseq, script_name, path, start_line); pm_parser_free(&parser); return iseq; diff --git a/iseq.h b/iseq.h index e5774d098c572d..94e723ea7d5574 100644 --- a/iseq.h +++ b/iseq.h @@ -172,7 +172,7 @@ void rb_iseq_init_trace(rb_iseq_t *iseq); int rb_iseq_add_local_tracepoint_recursively(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, VALUE tpval, unsigned int target_line, bool target_bmethod); int rb_iseq_remove_local_tracepoint_recursively(const rb_iseq_t *iseq, VALUE tpval); const rb_iseq_t *rb_iseq_load_iseq(VALUE fname); -rb_iseq_t * rb_iseq_new_main_prism(pm_string_t *input, pm_options_t *options, VALUE path, VALUE optimize); +rb_iseq_t * rb_iseq_new_main_prism(pm_string_t *input, pm_options_t *options, VALUE script_name, VALUE path, VALUE optimize); #if VM_INSN_INFO_TABLE_IMPL == 2 unsigned int *rb_iseq_insns_info_decode_positions(const struct rb_iseq_constant_body *body); diff --git a/load.c b/load.c index a35042e5f56605..3b9b940ad912b0 100644 --- a/load.c +++ b/load.c @@ -747,7 +747,7 @@ load_iseq_eval(rb_execution_context_t *ec, VALUE fname) pm_parser_t parser; pm_parser_init(&parser, pm_string_source(&input), pm_string_length(&input), &options); - iseq = rb_iseq_new_main_prism(&input, &options, fname, Qnil); + iseq = rb_iseq_new_main_prism(&input, &options, fname, fname, Qnil); pm_string_free(&input); pm_options_free(&options); diff --git a/ruby.c b/ruby.c index bccc6504a0ccc9..cf82d3e0a1a69f 100644 --- a/ruby.c +++ b/ruby.c @@ -2428,7 +2428,7 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) } VALUE optimize = dump & DUMP_BIT(insns_without_opt) ? Qfalse : Qnil; - iseq = rb_iseq_new_main_prism(&input, &options, path, optimize); + iseq = rb_iseq_new_main_prism(&input, &options, opt->script_name, path, optimize); ruby_opt_init(opt); pm_string_free(&input); From d054904cad7f0889f545d47bc637829a510c1d4b Mon Sep 17 00:00:00 2001 From: Matt Valentine-House Date: Mon, 22 Jan 2024 22:28:51 +0000 Subject: [PATCH 438/640] [Prism] Don't change file after setting it. This causes the Iseq file names to be wrong, which is affecting Tracepoint events in certain cases. because we're taking a pointer to the string and using it in `pm_string_mapped_pointer` we also need to `RB_GC_GUARD` the relevant Ruby object to ensure it's not moved or swept before the parser has been free'd. --- iseq.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/iseq.c b/iseq.c index 706629d52b043a..babc7948dedc95 100644 --- a/iseq.c +++ b/iseq.c @@ -1475,12 +1475,12 @@ iseqw_s_compile_prism(int argc, VALUE *argv, VALUE self) pm_parser_t parser; + VALUE file_path = Qnil; pm_string_t input; if (RB_TYPE_P(src, T_FILE)) { - FilePathValue(src); - file = rb_fstring(src); /* rb_io_t->pathv gets frozen anyways */ + file_path = rb_io_path(src); /* rb_io_t->pathv gets frozen anyways */ - pm_string_mapped_init(&input, RSTRING_PTR(file)); + pm_string_mapped_init(&input, RSTRING_PTR(file_path)); } else { Check_Type(src, T_STRING); @@ -1493,6 +1493,7 @@ iseqw_s_compile_prism(int argc, VALUE *argv, VALUE self) rb_iseq_t *iseq = iseq_alloc(); iseqw_s_compile_prism_compile(&parser, opt, iseq, file, path, start_line); + RB_GC_GUARD(file_path); pm_parser_free(&parser); pm_options_free(&options); pm_string_free(&input); From d8af85ad145a803776bdc61ce0ae486c3dcb9b2b Mon Sep 17 00:00:00 2001 From: Matt Valentine-House Date: Mon, 22 Jan 2024 22:31:23 +0000 Subject: [PATCH 439/640] [Prism] Uncomment tests that now pass --- tool/prism_btests | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tool/prism_btests b/tool/prism_btests index aa6806a2b10fae..d2fc4e1d0c0ff6 100644 --- a/tool/prism_btests +++ b/tool/prism_btests @@ -29,7 +29,7 @@ ../src/bootstraptest/test_yjit_30k_methods.rb ../src/bootstraptest/test_yjit_rust_port.rb ../src/bootstraptest/test_exception.rb -# ../src/bootstraptest/test_insns.rb +../src/bootstraptest/test_insns.rb +../src/bootstraptest/test_ractor.rb # ../src/bootstraptest/test_method.rb -# ../src/bootstraptest/test_ractor.rb # ../src/bootstraptest/test_yjit.rb From 706eea9d3c27b9785fc7f650ff9b5d6669908768 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 23 Jan 2024 07:54:54 +0900 Subject: [PATCH 440/640] Fixup 2e69137dbe9fd7c03dac9b8adc30a7eba3ecb10b --- test/irb/test_completion.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/irb/test_completion.rb b/test/irb/test_completion.rb index 2f97d99faa5b02..4500fedb0b6c4b 100644 --- a/test/irb/test_completion.rb +++ b/test/irb/test_completion.rb @@ -124,8 +124,9 @@ def object.to_s; raise; end end def test_complete_require_library_name_first - candidates = IRB::RegexpCompletor.new.completion_candidates("require ", "'coverage", "", bind: binding) - assert_equal "'coverage", candidates.first + # Test that library name is completed first with subdirectories + candidates = IRB::RegexpCompletor.new.completion_candidates("require ", "'rubygems", "", bind: binding) + assert_equal "'rubygems", candidates.first end def test_complete_require_relative From ee7f63ebba542f87e6fa28709e67ace0fefcae90 Mon Sep 17 00:00:00 2001 From: yui-knk Date: Fri, 12 Jan 2024 22:26:54 +0900 Subject: [PATCH 441/640] Make lastline and nextline to be rb_parser_string This commit changes `struct parser_params` lastline and nextline from `VALUE` (String object) to `rb_parser_string_t *` so that dependency on Ruby Object is reduced. `parser_string_buffer_t string_buffer` is added to `struct parser_params` to manage `rb_parser_string_t` pointers of each line. All allocated line strings are freed in `rb_ruby_parser_free`. --- ext/ripper/ripper_init.c.tmpl | 4 +- internal/parse.h | 5 +- internal/ruby_parser.h | 4 + parse.y | 185 ++++++++++++++++++++++++++-------- ruby_parser.c | 9 +- 5 files changed, 158 insertions(+), 49 deletions(-) diff --git a/ext/ripper/ripper_init.c.tmpl b/ext/ripper/ripper_init.c.tmpl index b2caef2bd5bbc8..a2a5e4b4cf8869 100644 --- a/ext/ripper/ripper_init.c.tmpl +++ b/ext/ripper/ripper_init.c.tmpl @@ -471,11 +471,13 @@ ripper_token(VALUE self) { struct parser_params *p = ripper_parser_params(self, true); long pos, len; + VALUE str; if (NIL_P(rb_ruby_parser_parsing_thread(p))) return Qnil; pos = rb_ruby_ripper_column(p); len = rb_ruby_ripper_token_len(p); - return rb_str_subseq(rb_ruby_ripper_lex_lastline(p), pos, len); + str = rb_str_new_parser_string(rb_ruby_ripper_lex_lastline(p)); + return rb_str_subseq(str, pos, len); } #ifdef RIPPER_DEBUG diff --git a/internal/parse.h b/internal/parse.h index bd6d295be1a688..3c6e48090e5b2e 100644 --- a/internal/parse.h +++ b/internal/parse.h @@ -29,7 +29,7 @@ typedef struct rb_strterm_literal_struct { } rb_strterm_literal_t; typedef struct rb_strterm_heredoc_struct { - VALUE lastline; /* the string of line that contains `<<"END"` */ + rb_parser_string_t *lastline; /* the string of line that contains `<<"END"` */ long offset; /* the column of END in `<<"END"` */ int sourceline; /* lineno of the line that contains `<<"END"` */ unsigned length; /* the length of END in `<<"END"` */ @@ -65,6 +65,7 @@ RUBY_SYMBOL_EXPORT_BEGIN VALUE rb_ruby_parser_encoding(rb_parser_t *p); int rb_ruby_parser_end_seen_p(rb_parser_t *p); int rb_ruby_parser_set_yydebug(rb_parser_t *p, int flag); +rb_parser_string_t *rb_str_to_parser_string(rb_parser_t *p, VALUE str); RUBY_SYMBOL_EXPORT_END @@ -96,7 +97,7 @@ int rb_ruby_ripper_initialized_p(rb_parser_t *p); void rb_ruby_ripper_parser_initialize(rb_parser_t *p); long rb_ruby_ripper_column(rb_parser_t *p); long rb_ruby_ripper_token_len(rb_parser_t *p); -VALUE rb_ruby_ripper_lex_lastline(rb_parser_t *p); +rb_parser_string_t *rb_ruby_ripper_lex_lastline(rb_parser_t *p); VALUE rb_ruby_ripper_lex_state_name(struct parser_params *p, int state); struct parser_params *rb_ruby_ripper_parser_allocate(void); #endif diff --git a/internal/ruby_parser.h b/internal/ruby_parser.h index ddff2c364d7dee..018a1865ded68d 100644 --- a/internal/ruby_parser.h +++ b/internal/ruby_parser.h @@ -72,6 +72,10 @@ enum lex_state_e { EXPR_NONE = 0 }; +RUBY_SYMBOL_EXPORT_BEGIN +VALUE rb_str_new_parser_string(rb_parser_string_t *str); +RUBY_SYMBOL_EXPORT_END + VALUE rb_node_sym_string_val(const NODE *); VALUE rb_node_line_lineno_val(const NODE *); VALUE rb_node_file_path_val(const NODE *); diff --git a/parse.y b/parse.y index 66f8545e6d3f83..71b7507d272d92 100644 --- a/parse.y +++ b/parse.y @@ -532,6 +532,20 @@ typedef struct end_expect_token_locations { struct end_expect_token_locations *prev; } end_expect_token_locations_t; +typedef struct parser_string_buffer_elem { + struct parser_string_buffer_elem *next; + long len; /* Total length of allocated buf */ + long used; /* Current usage of buf */ + rb_parser_string_t *buf[FLEX_ARY_LEN]; +} parser_string_buffer_elem_t; + +typedef struct parser_string_buffer { + parser_string_buffer_elem_t *head; + parser_string_buffer_elem_t *last; +} parser_string_buffer_t; + +#define AFTER_HEREDOC_WITHOUT_TERMINTOR ((rb_parser_string_t *)1) + /* Structure of Lexer Buffer: @@ -551,8 +565,9 @@ struct parser_params { rb_strterm_t *strterm; VALUE (*gets)(struct parser_params*,VALUE); VALUE input; - VALUE lastline; - VALUE nextline; + parser_string_buffer_t string_buffer; + rb_parser_string_t *lastline; + rb_parser_string_t *nextline; const char *pbeg; const char *pcur; const char *pend; @@ -704,6 +719,59 @@ pop_pktbl(struct parser_params *p, st_table *tbl) p->pktbl = tbl; } +#define STRING_BUF_DEFAULT_LEN 16 + +static void +string_buffer_init(struct parser_params *p) +{ + parser_string_buffer_t *buf = &p->lex.string_buffer; + const size_t size = offsetof(parser_string_buffer_elem_t, buf) + sizeof(rb_parser_string_t *) * STRING_BUF_DEFAULT_LEN; + + buf->head = buf->last = xmalloc(size); + buf->head->len = STRING_BUF_DEFAULT_LEN; + buf->head->used = 0; + buf->head->next = NULL; +} + +static void +string_buffer_append(struct parser_params *p, rb_parser_string_t *str) +{ + parser_string_buffer_t *buf = &p->lex.string_buffer; + + if (buf->head->used >= buf->head->len) { + parser_string_buffer_elem_t *elem; + long n = buf->head->len * 2; + const size_t size = offsetof(parser_string_buffer_elem_t, buf) + sizeof(rb_parser_string_t *) * n; + + elem = xmalloc(size); + elem->len = n; + elem->used = 0; + elem->next = NULL; + buf->last->next = elem; + buf->last = elem; + } + buf->last->buf[buf->last->used++] = str; +} + +static void rb_parser_string_free(rb_parser_t *p, rb_parser_string_t *str); + +static void +string_buffer_free(struct parser_params *p) +{ + parser_string_buffer_elem_t *elem = p->lex.string_buffer.head; + + while (elem) { + parser_string_buffer_elem_t *next_elem = elem->next; + + for (long i = 0; i < elem->used; i++) { + rb_parser_string_free(p, elem->buf[i]); + } + + xfree(elem); + elem = next_elem; + } +} + #ifndef RIPPER static void flush_debug_buffer(struct parser_params *p, VALUE out, VALUE str); @@ -2089,6 +2157,26 @@ rb_parser_encoding_string_new(rb_parser_t *p, const char *ptr, long len, rb_enco str->enc = enc; return str; } +#endif + +static void +rb_parser_string_free(rb_parser_t *p, rb_parser_string_t *str) +{ + xfree(str); +} + +#ifndef RIPPER +static char * +rb_parser_string_end(rb_parser_string_t *str) +{ + return &str->ptr[str->len]; +} + +static void +rb_parser_string_set_encoding(rb_parser_string_t *str, rb_encoding *enc) +{ + str->enc = enc; +} long rb_parser_string_length(rb_parser_string_t *str) @@ -2101,7 +2189,15 @@ rb_parser_string_pointer(rb_parser_string_t *str) { return str->ptr; } +#endif +static rb_encoding * +rb_parser_string_encoding(rb_parser_string_t *str) +{ + return str->enc; +} + +#ifndef RIPPER #ifndef UNIVERSAL_PARSER # define PARSER_STRING_GETMEM(str, ptrvar, lenvar, encvar) \ ((ptrvar) = str->ptr, \ @@ -2124,8 +2220,8 @@ rb_parser_string_hash_cmp(rb_parser_string_t *str1, rb_parser_string_t *str2) } #endif -static rb_parser_string_t * -rb_str_to_parser_encoding_string(rb_parser_t *p, VALUE str) +rb_parser_string_t * +rb_str_to_parser_string(rb_parser_t *p, VALUE str) { /* Type check */ return rb_parser_encoding_string_new(p, RSTRING_PTR(str), RSTRING_LEN(str), rb_enc_get(str)); @@ -7304,12 +7400,12 @@ parser_precise_mbclen(struct parser_params *p, const char *ptr) } #ifndef RIPPER -static void ruby_show_error_line(struct parser_params *p, VALUE errbuf, const YYLTYPE *yylloc, int lineno, VALUE str); +static void ruby_show_error_line(struct parser_params *p, VALUE errbuf, const YYLTYPE *yylloc, int lineno, rb_parser_string_t *str); static inline void parser_show_error_line(struct parser_params *p, const YYLTYPE *yylloc) { - VALUE str; + rb_parser_string_t *str; int lineno = p->ruby_sourceline; if (!yylloc) { return; @@ -7350,7 +7446,7 @@ parser_yyerror0(struct parser_params *p, const char *msg) } static void -ruby_show_error_line(struct parser_params *p, VALUE errbuf, const YYLTYPE *yylloc, int lineno, VALUE str) +ruby_show_error_line(struct parser_params *p, VALUE errbuf, const YYLTYPE *yylloc, int lineno, rb_parser_string_t *str) { VALUE mesg; const int max_line_margin = 30; @@ -7358,13 +7454,13 @@ ruby_show_error_line(struct parser_params *p, VALUE errbuf, const YYLTYPE *yyllo const char *pre = "", *post = "", *pend; const char *code = "", *caret = ""; const char *lim; - const char *const pbeg = RSTRING_PTR(str); + const char *const pbeg = rb_parser_string_pointer(str); char *buf; long len; int i; if (!yylloc) return; - pend = RSTRING_END(str); + pend = rb_parser_string_end(str); if (pend > pbeg && pend[-1] == '\n') { if (--pend > pbeg && pend[-1] == '\r') --pend; } @@ -7385,11 +7481,11 @@ ruby_show_error_line(struct parser_params *p, VALUE errbuf, const YYLTYPE *yyllo len = ptr_end - ptr; if (len > 4) { if (ptr > pbeg) { - ptr = rb_enc_prev_char(pbeg, ptr, pt, rb_enc_get(str)); + ptr = rb_enc_prev_char(pbeg, ptr, pt, rb_parser_string_encoding(str)); if (ptr > pbeg) pre = "..."; } if (ptr_end < pend) { - ptr_end = rb_enc_prev_char(pt, ptr_end, pend, rb_enc_get(str)); + ptr_end = rb_enc_prev_char(pt, ptr_end, pend, rb_parser_string_encoding(str)); if (ptr_end < pend) post = "..."; } } @@ -7408,7 +7504,7 @@ ruby_show_error_line(struct parser_params *p, VALUE errbuf, const YYLTYPE *yyllo rb_str_cat_cstr(mesg, "\n"); } else { - mesg = rb_enc_str_new(0, 0, rb_enc_get(str)); + mesg = rb_enc_str_new(0, 0, rb_parser_string_encoding(str)); } if (!errbuf && rb_stderr_tty_p()) { #define CSI_BEGIN "\033[" @@ -7730,15 +7826,17 @@ lex_get_str(struct parser_params *p, VALUE s) return rb_str_subseq(s, beg - start, len); } -static VALUE +static rb_parser_string_t * lex_getline(struct parser_params *p) { + rb_parser_string_t *str; VALUE line = (*p->lex.gets)(p, p->lex.input); - if (NIL_P(line)) return line; + if (NIL_P(line)) return 0; must_be_ascii_compatible(p, line); - if (RB_OBJ_FROZEN(line)) line = rb_str_dup(line); // needed for RubyVM::AST.of because script_lines in iseq is deep-frozen p->line_count++; - return line; + str = rb_str_to_parser_string(p, line); + string_buffer_append(p, str); + return str; } #ifndef RIPPER @@ -7898,19 +7996,19 @@ add_delayed_token(struct parser_params *p, const char *tok, const char *end, int } static void -set_lastline(struct parser_params *p, VALUE v) +set_lastline(struct parser_params *p, rb_parser_string_t *str) { - p->lex.pbeg = p->lex.pcur = RSTRING_PTR(v); - p->lex.pend = p->lex.pcur + RSTRING_LEN(v); - p->lex.lastline = v; + p->lex.pbeg = p->lex.pcur = rb_parser_string_pointer(str); + p->lex.pend = p->lex.pcur + rb_parser_string_length(str); + p->lex.lastline = str; } static int nextline(struct parser_params *p, int set_encoding) { - VALUE v = p->lex.nextline; + rb_parser_string_t *str = p->lex.nextline; p->lex.nextline = 0; - if (!v) { + if (!str) { if (p->eofp) return -1; @@ -7918,7 +8016,7 @@ nextline(struct parser_params *p, int set_encoding) goto end_of_input; } - if (!p->lex.input || NIL_P(v = lex_getline(p))) { + if (!p->lex.input || !(str = lex_getline(p))) { end_of_input: p->eofp = 1; lex_goto_eol(p); @@ -7926,13 +8024,14 @@ nextline(struct parser_params *p, int set_encoding) } #ifndef RIPPER if (p->debug_lines) { + VALUE v = rb_str_new_parser_string(str); if (set_encoding) rb_enc_associate(v, p->enc); rb_ary_push(p->debug_lines, v); } #endif p->cr_seen = FALSE; } - else if (NIL_P(v)) { + else if (str == AFTER_HEREDOC_WITHOUT_TERMINTOR) { /* after here-document without terminator */ goto end_of_input; } @@ -7942,7 +8041,7 @@ nextline(struct parser_params *p, int set_encoding) p->heredoc_end = 0; } p->ruby_sourceline++; - set_lastline(p, v); + set_lastline(p, str); token_flush(p); return 0; } @@ -7962,7 +8061,7 @@ nextc0(struct parser_params *p, int set_encoding) { int c; - if (UNLIKELY(lex_eol_p(p) || p->eofp || RTEST(p->lex.nextline))) { + if (UNLIKELY(lex_eol_p(p) || p->eofp || p->lex.nextline > AFTER_HEREDOC_WITHOUT_TERMINTOR)) { if (nextline(p, set_encoding)) return -1; } c = (unsigned char)*p->lex.pcur++; @@ -8983,7 +9082,6 @@ heredoc_identifier(struct parser_params *p) here->quote = quote; here->func = func; here->lastline = p->lex.lastline; - rb_ast_add_mark_object(p->ast, p->lex.lastline); token_flush(p); p->heredoc_indent = indent; @@ -8994,22 +9092,21 @@ heredoc_identifier(struct parser_params *p) static void heredoc_restore(struct parser_params *p, rb_strterm_heredoc_t *here) { - VALUE line; + rb_parser_string_t *line; rb_strterm_t *term = p->lex.strterm; p->lex.strterm = 0; line = here->lastline; p->lex.lastline = line; - p->lex.pbeg = RSTRING_PTR(line); - p->lex.pend = p->lex.pbeg + RSTRING_LEN(line); + p->lex.pbeg = rb_parser_string_pointer(line); + p->lex.pend = p->lex.pbeg + rb_parser_string_length(line); p->lex.pcur = p->lex.pbeg + here->offset + here->length + here->quote; p->lex.ptok = p->lex.pbeg + here->offset - here->quote; p->heredoc_end = p->ruby_sourceline; p->ruby_sourceline = (int)here->sourceline; - if (p->eofp) p->lex.nextline = Qnil; + if (p->eofp) p->lex.nextline = AFTER_HEREDOC_WITHOUT_TERMINTOR; p->eofp = 0; xfree(term); - rb_ast_delete_mark_object(p->ast, line); } static int @@ -9256,7 +9353,7 @@ here_document(struct parser_params *p, rb_strterm_heredoc_t *here) rb_encoding *base_enc = 0; int bol; - eos = RSTRING_PTR(here->lastline) + here->offset; + eos = rb_parser_string_pointer(here->lastline) + here->offset; len = here->length; indent = (func = here->func) & STR_FUNC_INDENT; @@ -9312,7 +9409,7 @@ here_document(struct parser_params *p, rb_strterm_heredoc_t *here) if (!(func & STR_FUNC_EXPAND)) { do { - ptr = RSTRING_PTR(p->lex.lastline); + ptr = rb_parser_string_pointer(p->lex.lastline); ptr_end = p->lex.pend; if (ptr_end > ptr) { switch (ptr_end[-1]) { @@ -9869,7 +9966,7 @@ parser_prepare(struct parser_params *p) p->lex.pcur += 2; #ifndef RIPPER if (p->debug_lines) { - rb_enc_associate(p->lex.lastline, p->enc); + rb_parser_string_set_encoding(p->lex.lastline, p->enc); } #endif p->lex.pbeg = p->lex.pcur; @@ -9877,11 +9974,11 @@ parser_prepare(struct parser_params *p) return; } break; - case EOF: + case -1: /* end of script. */ return; } pushback(p, c); - p->enc = rb_enc_get(p->lex.lastline); + p->enc = rb_parser_string_encoding(p->lex.lastline); } #ifndef RIPPER @@ -10714,7 +10811,7 @@ parser_yylex(struct parser_params *p) case '\004': /* ^D */ case '\032': /* ^Z */ case -1: /* end of script. */ - p->eofp = 1; + p->eofp = 1; #ifndef RIPPER if (p->end_expect_token_locations) { pop_end_expect_token_locations(p); @@ -10767,7 +10864,7 @@ parser_yylex(struct parser_params *p) /* fall through */ case '\n': p->token_seen = token_seen; - VALUE prevline = p->lex.lastline; + rb_parser_string_t *prevline = p->lex.lastline; c = (IS_lex_state(EXPR_BEG|EXPR_CLASS|EXPR_FNAME|EXPR_DOT) && !IS_lex_state(EXPR_LABELED)); if (c || IS_lex_state_all(EXPR_ARG|EXPR_LABELED)) { @@ -12205,7 +12302,7 @@ static rb_node_sym_t * rb_node_sym_new(struct parser_params *p, VALUE str, const YYLTYPE *loc) { rb_node_sym_t *n = NODE_NEWNODE(NODE_SYM, rb_node_sym_t, loc); - n->string = rb_str_to_parser_encoding_string(p, str); + n->string = rb_str_to_parser_string(p, str); return n; } @@ -12493,7 +12590,7 @@ static rb_node_file_t * rb_node_file_new(struct parser_params *p, VALUE str, const YYLTYPE *loc) { rb_node_file_t *n = NODE_NEWNODE(NODE_FILE, rb_node_file_t, loc); - n->path = rb_str_to_parser_encoding_string(p, str); + n->path = rb_str_to_parser_string(p, str); return n; } @@ -15872,6 +15969,7 @@ parser_initialize(struct parser_params *p) p->command_start = TRUE; p->ruby_sourcefile_string = Qnil; p->lex.lpar_beg = -1; /* make lambda_beginning_p() == FALSE at first */ + string_buffer_init(p); p->node_id = 0; p->delayed.token = Qnil; p->frozen_string_literal = -1; /* not specified */ @@ -15902,8 +16000,6 @@ rb_ruby_parser_mark(void *ptr) struct parser_params *p = (struct parser_params*)ptr; rb_gc_mark(p->lex.input); - rb_gc_mark(p->lex.lastline); - rb_gc_mark(p->lex.nextline); rb_gc_mark(p->ruby_sourcefile_string); rb_gc_mark((VALUE)p->ast); rb_gc_mark(p->case_labels); @@ -15946,6 +16042,7 @@ rb_ruby_parser_free(void *ptr) xfree(ptinfo); } } + string_buffer_free(p); xfree(ptr); } @@ -16321,7 +16418,7 @@ rb_ruby_ripper_token_len(rb_parser_t *p) return p->lex.pcur - p->lex.ptok; } -VALUE +rb_parser_string_t * rb_ruby_ripper_lex_lastline(rb_parser_t *p) { return p->lex.lastline; diff --git a/ruby_parser.c b/ruby_parser.c index d932b0f7bef9ba..965fe2cc1ae552 100644 --- a/ruby_parser.c +++ b/ruby_parser.c @@ -848,6 +848,12 @@ rb_parser_set_yydebug(VALUE vparser, VALUE flag) } #endif +VALUE +rb_str_new_parser_string(rb_parser_string_t *str) +{ + return rb_enc_str_new(str->ptr, str->len, str->enc); +} + static VALUE negative_numeric(VALUE val) { @@ -1000,6 +1006,5 @@ rb_node_line_lineno_val(const NODE *node) VALUE rb_node_file_path_val(const NODE *node) { - rb_parser_string_t *str = RNODE_FILE(node)->path; - return rb_enc_str_new(str->ptr, str->len, str->enc); + return rb_str_new_parser_string(RNODE_FILE(node)->path); } From 270a46e392dab13e422b2b9f27f2893a3fecd77b Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 22 Jan 2024 14:51:12 -0800 Subject: [PATCH 442/640] Check keyword parameters correctly We weren't checking the right offsets when compiling methods with keyword parameters that had complex code. Fixes: https://github.com/ruby/prism/issues/2228 --- prism_compile.c | 4 +++- test/ruby/test_compile_prism.rb | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/prism_compile.c b/prism_compile.c index 3fd9efbf0d7f2b..ce08c56c7b68e1 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -6751,6 +6751,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, //********STEP 5************ // Goal: compile anything that needed to be compiled if (keywords_list && keywords_list->size) { + size_t optional_index = 0; for (size_t i = 0; i < keywords_list->size; i++, local_index++) { pm_node_t *keyword_parameter_node = keywords_list->nodes[i]; pm_constant_id_t name; @@ -6772,13 +6773,14 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, name, 0); int kw_bits_idx = table_size - body->param.keyword->bits_start; - ADD_INSN2(ret, &dummy_line_node, checkkeyword, INT2FIX(kw_bits_idx + VM_ENV_DATA_SIZE - 1), INT2FIX(i)); + ADD_INSN2(ret, &dummy_line_node, checkkeyword, INT2FIX(kw_bits_idx + VM_ENV_DATA_SIZE - 1), INT2FIX(optional_index)); ADD_INSNL(ret, &dummy_line_node, branchif, end_label); PM_COMPILE(value); ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); ADD_LABEL(ret, end_label); } + optional_index++; break; } // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n) diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index f54097ab665a03..328074fc5221d7 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1515,6 +1515,11 @@ def self.prism_test_def_node(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, CODE end + def test_complex_default_params + assert_prism_eval("def self.foo(a:, b: '2'.to_i); [a, b]; end; foo(a: 1)") + assert_prism_eval("def self.foo(a:, b: 2, c: '3'.to_i); [a, b, c]; end; foo(a: 1)") + end + def test_rescue_with_ensure assert_prism_eval(<<-CODE) begin From f423ced5abdfce0dde3c71a72b12f5865f38ee43 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 22 Jan 2024 15:35:05 -0800 Subject: [PATCH 443/640] update tests --- tool/prism_btests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tool/prism_btests b/tool/prism_btests index d2fc4e1d0c0ff6..deb20eb5007dd0 100644 --- a/tool/prism_btests +++ b/tool/prism_btests @@ -31,5 +31,5 @@ ../src/bootstraptest/test_exception.rb ../src/bootstraptest/test_insns.rb ../src/bootstraptest/test_ractor.rb -# ../src/bootstraptest/test_method.rb +../src/bootstraptest/test_method.rb # ../src/bootstraptest/test_yjit.rb From 7811dd169bad766b64587b0669d13010d62ee94d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 21:37:07 +0000 Subject: [PATCH 444/640] [rubygems/rubygems] Bump shlex Bumps [shlex](https://github.com/comex/rust-shlex) from 1.1.0 to 1.3.0. - [Changelog](https://github.com/comex/rust-shlex/blob/master/CHANGELOG.md) - [Commits](https://github.com/comex/rust-shlex/commits) --- updated-dependencies: - dependency-name: shlex dependency-type: indirect ... Signed-off-by: dependabot[bot] https://github.com/rubygems/rubygems/commit/70812aeeb1 --- .../test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock index 5f161882145444..7583bb7822e94f 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock +++ b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock @@ -205,9 +205,9 @@ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] name = "shlex" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "syn" From cb8235c9c95f4d3b48df77240c2363c5441ffbe5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 15:56:53 +0000 Subject: [PATCH 445/640] [rubygems/rubygems] Bump rb-sys Bumps [rb-sys](https://github.com/oxidize-rb/rb-sys) from 0.9.86 to 0.9.87. - [Release notes](https://github.com/oxidize-rb/rb-sys/releases) - [Commits](https://github.com/oxidize-rb/rb-sys/compare/v0.9.86...v0.9.87) --- updated-dependencies: - dependency-name: rb-sys dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] https://github.com/rubygems/rubygems/commit/40292944e8 --- .../custom_name/ext/custom_name_lib/Cargo.lock | 8 ++++---- .../custom_name/ext/custom_name_lib/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock index aa9587b2313e9d..159c1387f85c2c 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock +++ b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock @@ -152,18 +152,18 @@ dependencies = [ [[package]] name = "rb-sys" -version = "0.9.86" +version = "0.9.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7285f2a7b92f58ab198e3fd59a71d2861478f9c4642f41e83582385818941697" +checksum = "225103e3d69bbfe8831f9fd0d2461335f3a9dd06aa6e88bcb6d6970383494d06" dependencies = [ "rb-sys-build", ] [[package]] name = "rb-sys-build" -version = "0.9.86" +version = "0.9.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71583945f94dabb6c0dfa63f1b71e929c1901e1e288ef3739ab8bed3b7069550" +checksum = "bacce8095a5167d5ede618bbd9353e9d9e2f32ddaf54be911106f0ee6baacf09" dependencies = [ "bindgen", "lazy_static", diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml index 56a4188f1547e4..f99bc584667899 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml +++ b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml @@ -7,4 +7,4 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -rb-sys = "0.9.86" +rb-sys = "0.9.87" From 6fb9dc5089e970ab977c76e9c13562e516b677ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 21:43:54 +0000 Subject: [PATCH 446/640] [rubygems/rubygems] Bump shlex Bumps [shlex](https://github.com/comex/rust-shlex) from 1.1.0 to 1.3.0. - [Changelog](https://github.com/comex/rust-shlex/blob/master/CHANGELOG.md) - [Commits](https://github.com/comex/rust-shlex/commits) --- updated-dependencies: - dependency-name: shlex dependency-type: indirect ... Signed-off-by: dependabot[bot] https://github.com/rubygems/rubygems/commit/ca4efb9e9d --- .../custom_name/ext/custom_name_lib/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock index 159c1387f85c2c..9a62aee1fa4359 100644 --- a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock +++ b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock @@ -205,9 +205,9 @@ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] name = "shlex" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "syn" From cfa15bb173723b8bb6110a81241bcdffa18193fb Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 22 Jan 2024 16:03:58 -0800 Subject: [PATCH 447/640] Handle trailing commas on blocks We need to set a special flag on block iseqs when there is a trailing comma. Fixes: https://github.com/ruby/prism/issues/2244 --- prism_compile.c | 6 +++++- test/ruby/test_compile_prism.rb | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/prism_compile.c b/prism_compile.c index ce08c56c7b68e1..cf9bc746253855 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -6218,6 +6218,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_node_list_t *requireds_list = NULL; pm_node_list_t *block_locals = NULL; pm_node_t *block_param_keyword_rest = NULL; + bool trailing_comma = false; struct rb_iseq_constant_body *body = ISEQ_BODY(iseq); @@ -6229,6 +6230,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, block_locals = &block_parameters_node->locals; if (parameters_node) { block_param_keyword_rest = parameters_node->keyword_rest; + if (parameters_node->rest && PM_NODE_TYPE_P(parameters_node->rest, PM_IMPLICIT_REST_NODE)) { + trailing_comma = true; + } } break; } @@ -6558,7 +6562,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, local_index++; } - if (body->type == ISEQ_TYPE_BLOCK && local_index == 1 && requireds_list && requireds_list->size == 1) { + if (body->type == ISEQ_TYPE_BLOCK && local_index == 1 && requireds_list && requireds_list->size == 1 && !trailing_comma) { body->param.flags.ambiguous_param0 = true; } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 328074fc5221d7..10def69ff2434c 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1515,6 +1515,10 @@ def self.prism_test_def_node(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, CODE end + def test_trailing_comma_on_block + assert_prism_eval("def self.m; yield [:ok]; end; m {|v0,| v0 }") + end + def test_complex_default_params assert_prism_eval("def self.foo(a:, b: '2'.to_i); [a, b]; end; foo(a: 1)") assert_prism_eval("def self.foo(a:, b: 2, c: '3'.to_i); [a, b, c]; end; foo(a: 1)") From 8c3eb47fffc6d274ad9c65f507676f8ae906a948 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 22 Jan 2024 16:06:32 -0800 Subject: [PATCH 448/640] All btests are passing with Prism We can remove the exclusion list now --- .github/workflows/prism.yml | 2 +- tool/prism_btests | 35 ----------------------------------- 2 files changed, 1 insertion(+), 36 deletions(-) delete mode 100644 tool/prism_btests diff --git a/.github/workflows/prism.yml b/.github/workflows/prism.yml index 4bfaf92544af24..5c0148e8b55268 100644 --- a/.github/workflows/prism.yml +++ b/.github/workflows/prism.yml @@ -85,7 +85,7 @@ jobs: - name: make btest run: | - make -s btest RUN_OPTS="$RUN_OPTS" BTESTS="$(cat ../src/tool/prism_btests | grep -v '^#' | tr '\n' ' ')" + make -s btest RUN_OPTS="$RUN_OPTS" timeout-minutes: 30 env: GNUMAKEFLAGS: '' diff --git a/tool/prism_btests b/tool/prism_btests deleted file mode 100644 index deb20eb5007dd0..00000000000000 --- a/tool/prism_btests +++ /dev/null @@ -1,35 +0,0 @@ -../src/bootstraptest/test_attr.rb -../src/bootstraptest/test_autoload.rb -../src/bootstraptest/test_block.rb -../src/bootstraptest/test_class.rb -../src/bootstraptest/test_constant_cache.rb -../src/bootstraptest/test_env.rb -../src/bootstraptest/test_eval.rb -../src/bootstraptest/test_fiber.rb -../src/bootstraptest/test_finalizer.rb -../src/bootstraptest/test_flip.rb -../src/bootstraptest/test_flow.rb -../src/bootstraptest/test_fork.rb -../src/bootstraptest/test_gc.rb -../src/bootstraptest/test_io.rb -../src/bootstraptest/test_jump.rb -../src/bootstraptest/test_literal_suffix.rb -../src/bootstraptest/test_literal.rb -../src/bootstraptest/test_load.rb -../src/bootstraptest/test_marshal.rb -../src/bootstraptest/test_massign.rb -../src/bootstraptest/test_objectspace.rb -../src/bootstraptest/test_proc.rb -../src/bootstraptest/test_rjit.rb -../src/bootstraptest/test_string.rb -../src/bootstraptest/test_struct.rb -../src/bootstraptest/test_syntax.rb -../src/bootstraptest/test_thread.rb -../src/bootstraptest/test_yjit_30k_ifelse.rb -../src/bootstraptest/test_yjit_30k_methods.rb -../src/bootstraptest/test_yjit_rust_port.rb -../src/bootstraptest/test_exception.rb -../src/bootstraptest/test_insns.rb -../src/bootstraptest/test_ractor.rb -../src/bootstraptest/test_method.rb -# ../src/bootstraptest/test_yjit.rb From 5987f0b7c8545824efdbdd501ef4e9d57fc92808 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 23 Jan 2024 15:39:42 +0900 Subject: [PATCH 449/640] Retired macos-11 because this version is EOL, and added macos-13(beta) --- .github/workflows/macos.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 6411a02d2bcdae..030778ee47f546 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -33,10 +33,10 @@ jobs: matrix: test_task: ['check'] configure: [''] - os: ${{ fromJSON(format('["macos-11","macos-12"{0}]', (github.repository == 'ruby/ruby' && ',"macos-arm-oss"' || ''))) }} + os: ${{ fromJSON(format('["macos-12","macos-13"{0}]', (github.repository == 'ruby/ruby' && ',"macos-arm-oss"' || ''))) }} include: - test_task: test-all TESTS=--repeat-count=2 - os: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-12' }} + os: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-13' }} fail-fast: false env: From 7cf74a2ff28b1b4c26e367d0d67521f7e1fed239 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 23 Jan 2024 15:40:12 +0900 Subject: [PATCH 450/640] Run test-bundled-gems again with macos-arm-oss runner --- .github/workflows/macos.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 030778ee47f546..f665085f1d0feb 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -37,6 +37,8 @@ jobs: include: - test_task: test-all TESTS=--repeat-count=2 os: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-13' }} + - test_task: test-bundled-gems + os: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-13' }} fail-fast: false env: From b14674b236445fb70f484603e678722760f678f4 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Fri, 19 Jan 2024 10:26:24 -0500 Subject: [PATCH 451/640] Memory leak with TracePoint on bmethod [Bug #20194] When disabling the TracePoint on bmethod, the hooks list is not freed. For example: obj = Object.new obj.define_singleton_method(:foo) {} bmethod = obj.method(:foo) tp = TracePoint.new(:return) {} 10.times do 100_000.times do tp.enable(target: bmethod) {} end puts `ps -o rss= -p #{$$}` end Before: 18208 22832 26528 29728 34000 37776 40864 44400 47680 51504 After: 16688 17168 17168 17248 17696 17760 17824 17824 17856 17920 --- test/ruby/test_settracefunc.rb | 13 +++++++++++++ vm_trace.c | 1 + 2 files changed, 14 insertions(+) diff --git a/test/ruby/test_settracefunc.rb b/test/ruby/test_settracefunc.rb index b7711e191dfb84..dbaf0aaf096920 100644 --- a/test/ruby/test_settracefunc.rb +++ b/test/ruby/test_settracefunc.rb @@ -625,6 +625,19 @@ def test_tracepoint_memory_leak CODE end + def test_tracepoint_bmethod_memory_leak + assert_no_memory_leak([], '', "#{<<~"begin;"}\n#{<<~'end;'}", "[Bug #20194]", rss: true) + obj = Object.new + obj.define_singleton_method(:foo) {} + bmethod = obj.method(:foo) + tp = TracePoint.new(:return) {} + begin; + 1_000_000.times do + tp.enable(target: bmethod) {} + end + end; + end + def trace_by_set_trace_func events = [] trace = nil diff --git a/vm_trace.c b/vm_trace.c index fb896fd423486a..9d0507879fe55a 100644 --- a/vm_trace.c +++ b/vm_trace.c @@ -1259,6 +1259,7 @@ rb_tracepoint_enable_for_target(VALUE tpval, VALUE target, VALUE target_line) (tp->events & (RUBY_EVENT_CALL | RUBY_EVENT_RETURN))) { if (def->body.bmethod.hooks == NULL) { def->body.bmethod.hooks = ZALLOC(rb_hook_list_t); + def->body.bmethod.hooks->is_local = true; } rb_hook_list_connect_tracepoint(target, def->body.bmethod.hooks, tpval, 0); rb_hash_aset(tp->local_target_set, target, Qfalse); From 7f51959ff14fbe06bc1afd283d1af17b26161cf4 Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Mon, 22 Jan 2024 17:58:05 -0500 Subject: [PATCH 452/640] YJIT: Move guard up for a case of splat+rest Previously, YJIT put the guard for having enough items to extract from splat array at a place where the side exit is invalid, so if the guard fails, YJIT could raise something other than ArgumentError. Move the guard up to a place before any stack manipulation. [Bug #20204] --- bootstraptest/test_yjit.rb | 35 +++++++++++++++++++++++++++++++++++ yjit/src/codegen.rs | 34 +++++++++++++++++++++++++--------- 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index 926eaaf8f61f17..8ae3399dc20058 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -1,3 +1,38 @@ +# regression test for popping before side exit +assert_equal "ok", %q{ + def foo(a, *) = a + + def call(args, &) + foo(1) # spill at where the block arg will be + foo(*args, &) + end + + call([1, 2]) + + begin + call([]) + rescue ArgumentError + :ok + end +} + +# regression test for send processing before side exit +assert_equal "ok", %q{ + def foo(a, *) = :foo + + def call(args) + send(:foo, *args) + end + + call([1, 2]) + + begin + call([]) + rescue ArgumentError + :ok + end +} + # test discarding extra yield arguments assert_equal "2210150001501015", %q{ def splat_kw(ary) = yield *ary, a: 1 diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index fcb4c47608f92f..5d26e58fa77bc0 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -5893,12 +5893,6 @@ fn get_array_ptr(asm: &mut Assembler, array_reg: Opnd) -> Opnd { fn copy_splat_args_for_rest_callee(array: Opnd, num_args: u32, asm: &mut Assembler) { asm_comment!(asm, "copy_splat_args_for_rest_callee"); - let array_len_opnd = get_array_len(asm, array); - - asm_comment!(asm, "guard splat array large enough"); - asm.cmp(array_len_opnd, num_args.into()); - asm.jl(Target::side_exit(Counter::guard_send_iseq_has_rest_and_splat_too_few)); - // Unused operands cause the backend to panic if num_args == 0 { return; @@ -6431,6 +6425,28 @@ fn gen_send_iseq( asm.cmp(CFP, stack_limit); asm.jbe(Target::side_exit(Counter::guard_send_se_cf_overflow)); + if iseq_has_rest && flags & VM_CALL_ARGS_SPLAT != 0 { + // Insert length guard for a call to copy_splat_args_for_rest_callee() + // that will come later. We will have made changes to + // the stack by spilling or handling __send__ shifting + // by the time we get to that code, so we need the + // guard here where we can still side exit. + let non_rest_arg_count = argc - 1; + if non_rest_arg_count < required_num + opt_num { + let take_count: u32 = (required_num - non_rest_arg_count + opts_filled) + .try_into().unwrap(); + + if take_count > 0 { + asm_comment!(asm, "guard splat_array_length >= {take_count}"); + + let splat_array = asm.stack_opnd(i32::from(block_arg) + kw_arg_num); + let array_len_opnd = get_array_len(asm, splat_array); + asm.cmp(array_len_opnd, take_count.into()); + asm.jl(Target::side_exit(Counter::guard_send_iseq_has_rest_and_splat_too_few)); + } + } + } + match block_arg_type { Some(Type::Nil) => { // We have a nil block arg, so let's pop it off the args @@ -6541,14 +6557,14 @@ fn gen_send_iseq( // from the array and move them to the stack. asm_comment!(asm, "take items from splat array"); - let diff: u32 = (required_num - non_rest_arg_count + opts_filled) + let take_count: u32 = (required_num - non_rest_arg_count + opts_filled) .try_into().unwrap(); // Copy required arguments to the stack without modifying the array - copy_splat_args_for_rest_callee(array, diff, asm); + copy_splat_args_for_rest_callee(array, take_count, asm); // We will now slice the array to give us a new array of the correct size - let sliced = asm.ccall(rb_yjit_rb_ary_subseq_length as *const u8, vec![array, Opnd::UImm(diff as u64)]); + let sliced = asm.ccall(rb_yjit_rb_ary_subseq_length as *const u8, vec![array, Opnd::UImm(take_count.into())]); sliced } else { From a846d391d38b34fcc4f90adef967c166c923bd56 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Mon, 22 Jan 2024 21:57:22 +0100 Subject: [PATCH 453/640] List branch maintainers in maintainers.md I'm not aware of this information being available anywhere else. --- doc/maintainers.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/doc/maintainers.md b/doc/maintainers.md index 9e738a6bdd74b5..dabbdc0cb6e687 100644 --- a/doc/maintainers.md +++ b/doc/maintainers.md @@ -1,5 +1,12 @@ # Maintainers -This page describes the current module, library, and extension maintainers of Ruby. +This page describes the current branch, module, library, and extension maintainers of Ruby. + +## Branch Maintainers + +A branch maintainer is responsible for backporting commits into stable branches +and publishing Ruby patch releases. + +[The list of current branch maintainers is available in the wiki](https://github.com/ruby/ruby/wiki/Release-Engineering). ## Module Maintainers A module maintainer is responsible for a certain part of Ruby. From 557b69e83b27dafea435719fc3afc2e67e155962 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Tue, 23 Jan 2024 11:00:00 -0800 Subject: [PATCH 454/640] Skip a failing test for Prism This should be reverted once https://github.com/ruby/prism/issues/2249 is closed. --- bootstraptest/runner.rb | 4 ++++ bootstraptest/test_yjit.rb | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/bootstraptest/runner.rb b/bootstraptest/runner.rb index 039a15148d2c43..9dc3950f07882e 100755 --- a/bootstraptest/runner.rb +++ b/bootstraptest/runner.rb @@ -798,4 +798,8 @@ def rjit_enabled? ENV.fetch('RUN_OPTS', '').include?('rjit') end +def prism_enabled? + ENV.fetch('RUN_OPTS', '').include?('--parser=prism') +end + exit main diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index 8ae3399dc20058..b320322d84a15e 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -14,7 +14,7 @@ def call(args, &) rescue ArgumentError :ok end -} +} unless prism_enabled? # https://github.com/ruby/prism/issues/2249 # regression test for send processing before side exit assert_equal "ok", %q{ From 27c1dd8634d34bfe3592151d66b410f28ca749ce Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Tue, 23 Jan 2024 11:36:23 -0800 Subject: [PATCH 455/640] YJIT: Allow inlining ISEQ calls with a block (#9622) * YJIT: Allow inlining ISEQ calls with a block * Leave a TODO comment about u16 inline_block --- benchmark/loop_times_megamorphic.yml | 7 +++ compile.c | 3 ++ kernel.rb | 4 ++ numeric.rb | 1 + tool/mk_builtin_loader.rb | 2 +- vm_core.h | 2 + yjit.rb | 1 + yjit/src/codegen.rs | 15 +++++- yjit/src/core.rs | 68 ++++++++++++++++++++++++---- yjit/src/cruby_bindings.inc.rs | 1 + yjit/src/stats.rs | 23 +++++++++- 11 files changed, 115 insertions(+), 12 deletions(-) create mode 100644 benchmark/loop_times_megamorphic.yml diff --git a/benchmark/loop_times_megamorphic.yml b/benchmark/loop_times_megamorphic.yml new file mode 100644 index 00000000000000..f9343ba8973b79 --- /dev/null +++ b/benchmark/loop_times_megamorphic.yml @@ -0,0 +1,7 @@ +prelude: | + eval(<<~EOS) + def loop_times_megamorphic + #{"1.times {|i|};" * 1000} + end + EOS +benchmark: loop_times_megamorphic diff --git a/compile.c b/compile.c index b15c04a37ad3af..e9c66bd62dad7d 100644 --- a/compile.c +++ b/compile.c @@ -8637,6 +8637,9 @@ compile_builtin_attr(rb_iseq_t *iseq, const NODE *node) if (strcmp(RSTRING_PTR(string), "leaf") == 0) { ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_LEAF; } + else if (strcmp(RSTRING_PTR(string), "inline_block") == 0) { + ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_INLINE_BLOCK; + } else { goto unknown_arg; } diff --git a/kernel.rb b/kernel.rb index c6b3e44000edc6..5fa8a0d82628c9 100644 --- a/kernel.rb +++ b/kernel.rb @@ -87,6 +87,7 @@ def frozen? #++ # def tap + Primitive.attr! :inline_block yield(self) self end @@ -127,6 +128,7 @@ def tap # then {|response| JSON.parse(response) } # def then + Primitive.attr! :inline_block unless block_given? return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, rb_obj_size)' end @@ -142,6 +144,7 @@ def then # "my string".yield_self {|s| s.upcase } #=> "MY STRING" # def yield_self + Primitive.attr! :inline_block unless block_given? return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, rb_obj_size)' end @@ -178,6 +181,7 @@ def yield_self # puts enum.next # } #=> :ok def loop + Primitive.attr! :inline_block unless block_given? return enum_for(:loop) { Float::INFINITY } end diff --git a/numeric.rb b/numeric.rb index 3c059a58a4881f..c99a75a9101277 100644 --- a/numeric.rb +++ b/numeric.rb @@ -229,6 +229,7 @@ def size # # With no block given, returns an Enumerator. def times + Primitive.attr! :inline_block unless block_given? return to_enum(:times) { self < 0 ? 0 : self } end diff --git a/tool/mk_builtin_loader.rb b/tool/mk_builtin_loader.rb index 871ac87006c3cd..989c8c5957a433 100644 --- a/tool/mk_builtin_loader.rb +++ b/tool/mk_builtin_loader.rb @@ -6,7 +6,7 @@ SUBLIBS = {} REQUIRED = {} -BUILTIN_ATTRS = %w[leaf] +BUILTIN_ATTRS = %w[leaf inline_block] def string_literal(lit, str = []) while lit diff --git a/vm_core.h b/vm_core.h index 881e1beaacb306..6532c6b038c3c8 100644 --- a/vm_core.h +++ b/vm_core.h @@ -368,6 +368,8 @@ enum rb_builtin_attr { BUILTIN_ATTR_LEAF = 0x01, // This iseq only contains single `opt_invokebuiltin_delegate_leave` instruction with 0 arguments. BUILTIN_ATTR_SINGLE_NOARG_LEAF = 0x02, + // This attribute signals JIT to duplicate the iseq for each block iseq so that its `yield` will be monomorphic. + BUILTIN_ATTR_INLINE_BLOCK = 0x04, }; typedef VALUE (*rb_jit_func_t)(struct rb_execution_context_struct *, struct rb_control_frame_struct *); diff --git a/yjit.rb b/yjit.rb index 485b4062fa0a4d..c25ea8997d7710 100644 --- a/yjit.rb +++ b/yjit.rb @@ -345,6 +345,7 @@ def _print_stats(out: $stderr) # :nodoc: if stats[:compiled_blockid_count] != 0 out.puts "versions_per_block: " + format_number(13, "%4.3f" % (stats[:compiled_block_count].fdiv(stats[:compiled_blockid_count]))) end + out.puts "max_inline_versions: " + format_number(13, stats[:max_inline_versions]) out.puts "compiled_branch_count: " + format_number(13, stats[:compiled_branch_count]) out.puts "compile_time_ms: " + format_number(13, stats[:compile_time_ns] / (1000 * 1000)) out.puts "block_next_count: " + format_number(13, stats[:block_next_count]) diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 5d26e58fa77bc0..8847affd2be4b5 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -1810,7 +1810,7 @@ fn gen_get_ep(asm: &mut Assembler, level: u32) -> Opnd { // Gets the EP of the ISeq of the containing method, or "local level". // Equivalent of GET_LEP() macro. -fn gen_get_lep(jit: &mut JITState, asm: &mut Assembler) -> Opnd { +fn gen_get_lep(jit: &JITState, asm: &mut Assembler) -> Opnd { // Equivalent of get_lvar_level() in compile.c fn get_lvar_level(iseq: IseqPtr) -> u32 { if iseq == unsafe { rb_get_iseq_body_local_iseq(iseq) } { @@ -6910,6 +6910,12 @@ fn gen_send_iseq( // Create a context for the callee let mut callee_ctx = Context::default(); + // If the callee has :inline_block annotation and the callsite has a block ISEQ, + // duplicate a callee block for each block ISEQ to make its `yield` monomorphic. + if let (Some(BlockHandler::BlockISeq(iseq)), true) = (block, builtin_attrs & BUILTIN_ATTR_INLINE_BLOCK != 0) { + callee_ctx.set_inline_block(iseq); + } + // Set the argument types in the callee's context for arg_idx in 0..argc { let stack_offs: u8 = (argc - arg_idx - 1).try_into().unwrap(); @@ -7904,6 +7910,13 @@ fn gen_invokeblock_specialized( Counter::guard_invokeblock_tag_changed, ); + // If the current ISEQ is annotated to be inlined but it's not being inlined here, + // generate a dynamic dispatch to avoid making this yield megamorphic. + if unsafe { rb_yjit_iseq_builtin_attrs(jit.iseq) } & BUILTIN_ATTR_INLINE_BLOCK != 0 && !asm.ctx.inline() { + gen_counter_incr(asm, Counter::invokeblock_iseq_not_inlined); + return None; + } + let comptime_captured = unsafe { ((comptime_handler.0 & !0x3) as *const rb_captured_block).as_ref().unwrap() }; let comptime_iseq = unsafe { *comptime_captured.code.iseq.as_ref() }; diff --git a/yjit/src/core.rs b/yjit/src/core.rs index 27c3541b59407c..9929ecb9a66478 100644 --- a/yjit/src/core.rs +++ b/yjit/src/core.rs @@ -480,6 +480,13 @@ pub struct Context { // Stack slot type/local_idx we track // 8 temp types * 4 bits, total 32 bits temp_payload: u32, + + /// A pointer to a block ISEQ supplied by the caller. 0 if not inlined. + /// Not using IseqPtr to satisfy Default trait, and not using Option for #[repr(packed)] + /// TODO: This could be u16 if we have a global or per-ISEQ HashMap to convert IseqPtr + /// to serial indexes. We're thinking of overhauling Context structure in Ruby 3.4 which + /// could allow this to consume no bytes, so we're leaving this as is. + inline_block: u64, } /// Tuple of (iseq, idx) used to identify basic blocks @@ -1400,14 +1407,19 @@ pub fn take_version_list(blockid: BlockId) -> VersionList { } /// Count the number of block versions matching a given blockid -fn get_num_versions(blockid: BlockId) -> usize { +/// `inlined: true` counts inlined versions, and `inlined: false` counts other versions. +fn get_num_versions(blockid: BlockId, inlined: bool) -> usize { let insn_idx = blockid.idx.as_usize(); match get_iseq_payload(blockid.iseq) { Some(payload) => { payload .version_map .get(insn_idx) - .map(|versions| versions.len()) + .map(|versions| { + versions.iter().filter(|&&version| + unsafe { version.as_ref() }.ctx.inline() == inlined + ).count() + }) .unwrap_or(0) } None => 0, @@ -1465,6 +1477,9 @@ fn find_block_version(blockid: BlockId, ctx: &Context) -> Option { return best_version; } +/// Allow inlining a Block up to MAX_INLINE_VERSIONS times. +const MAX_INLINE_VERSIONS: usize = 1000; + /// Produce a generic context when the block version limit is hit for a blockid pub fn limit_block_versions(blockid: BlockId, ctx: &Context) -> Context { // Guard chains implement limits separately, do nothing @@ -1472,21 +1487,39 @@ pub fn limit_block_versions(blockid: BlockId, ctx: &Context) -> Context { return *ctx; } + let next_versions = get_num_versions(blockid, ctx.inline()) + 1; + let max_versions = if ctx.inline() { + MAX_INLINE_VERSIONS + } else { + get_option!(max_versions) + }; + // If this block version we're about to add will hit the version limit - if get_num_versions(blockid) + 1 >= get_option!(max_versions) { + if next_versions >= max_versions { // Produce a generic context that stores no type information, // but still respects the stack_size and sp_offset constraints. // This new context will then match all future requests. let generic_ctx = ctx.get_generic_ctx(); - debug_assert_ne!( - TypeDiff::Incompatible, - ctx.diff(&generic_ctx), - "should substitute a compatible context", - ); + if cfg!(debug_assertions) { + let mut ctx = ctx.clone(); + if ctx.inline() { + // Suppress TypeDiff::Incompatible from ctx.diff(). We return TypeDiff::Incompatible + // to keep inlining blocks until we hit the limit, but it's safe to give up inlining. + ctx.inline_block = 0; + assert!(generic_ctx.inline_block == 0); + } + + assert_ne!( + TypeDiff::Incompatible, + ctx.diff(&generic_ctx), + "should substitute a compatible context", + ); + } return generic_ctx; } + incr_counter_to!(max_inline_versions, next_versions); return *ctx; } @@ -2020,6 +2053,16 @@ impl Context { self.local_types = 0; } + /// Return true if the code is inlined by the caller + pub fn inline(&self) -> bool { + self.inline_block != 0 + } + + /// Set a block ISEQ given to the Block of this Context + pub fn set_inline_block(&mut self, iseq: IseqPtr) { + self.inline_block = iseq as u64 + } + /// Compute a difference score for two context objects pub fn diff(&self, dst: &Context) -> TypeDiff { // Self is the source context (at the end of the predecessor) @@ -2065,6 +2108,13 @@ impl Context { TypeDiff::Incompatible => return TypeDiff::Incompatible, }; + // Check the block to inline + if src.inline_block != dst.inline_block { + // find_block_version should not find existing blocks with different + // inline_block so that their yield will not be megamorphic. + return TypeDiff::Incompatible; + } + // For each local type we track for i in 0.. MAX_LOCAL_TYPES { let t_src = src.get_local_type(i); @@ -3456,7 +3506,7 @@ mod tests { #[test] fn context_size() { - assert_eq!(mem::size_of::(), 15); + assert_eq!(mem::size_of::(), 23); } #[test] diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs index d67653890c9ea5..e6dba2b59df2a5 100644 --- a/yjit/src/cruby_bindings.inc.rs +++ b/yjit/src/cruby_bindings.inc.rs @@ -449,6 +449,7 @@ pub struct iseq_inline_cvar_cache_entry { } pub const BUILTIN_ATTR_LEAF: rb_builtin_attr = 1; pub const BUILTIN_ATTR_SINGLE_NOARG_LEAF: rb_builtin_attr = 2; +pub const BUILTIN_ATTR_INLINE_BLOCK: rb_builtin_attr = 4; pub type rb_builtin_attr = u32; #[repr(C)] #[derive(Debug, Copy, Clone)] diff --git a/yjit/src/stats.rs b/yjit/src/stats.rs index 7df01448a46d1a..d8dd4b93893a85 100644 --- a/yjit/src/stats.rs +++ b/yjit/src/stats.rs @@ -245,7 +245,7 @@ macro_rules! make_counters { /// The list of counters that are available without --yjit-stats. /// They are incremented only by `incr_counter!` and don't use `gen_counter_incr`. -pub const DEFAULT_COUNTERS: [Counter; 8] = [ +pub const DEFAULT_COUNTERS: [Counter; 9] = [ Counter::code_gc_count, Counter::compiled_iseq_entry, Counter::cold_iseq_entry, @@ -254,6 +254,7 @@ pub const DEFAULT_COUNTERS: [Counter; 8] = [ Counter::compiled_block_count, Counter::compiled_branch_count, Counter::compile_time_ns, + Counter::max_inline_versions, ]; /// Macro to increase a counter by name and count @@ -269,6 +270,24 @@ macro_rules! incr_counter_by { } pub(crate) use incr_counter_by; +/// Macro to increase a counter if the given value is larger +macro_rules! incr_counter_to { + // Unsafe is ok here because options are initialized + // once before any Ruby code executes + ($counter_name:ident, $count:expr) => { + #[allow(unused_unsafe)] + { + unsafe { + $crate::stats::COUNTERS.$counter_name = u64::max( + $crate::stats::COUNTERS.$counter_name, + $count as u64, + ) + } + } + }; +} +pub(crate) use incr_counter_to; + /// Macro to increment a counter by name macro_rules! incr_counter { // Unsafe is ok here because options are initialized @@ -395,6 +414,7 @@ make_counters! { invokeblock_iseq_arg0_args_splat, invokeblock_iseq_arg0_not_array, invokeblock_iseq_arg0_wrong_len, + invokeblock_iseq_not_inlined, invokeblock_ifunc_args_splat, invokeblock_ifunc_kw_splat, invokeblock_proc, @@ -518,6 +538,7 @@ make_counters! { defer_empty_count, branch_insn_count, branch_known_count, + max_inline_versions, freed_iseq_count, From c84237f9531aed3b204d3fdacc2dd9d2bd4c7d81 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Tue, 23 Jan 2024 12:09:57 -0800 Subject: [PATCH 456/640] Rewrite Array#each in Ruby using Primitive (#9533) --- array.c | 59 ++++++++-------------------------- array.rb | 55 +++++++++++++++++++++++++++++++ benchmark/loop_each.yml | 4 +++ builtin.h | 2 ++ gems/bundled_gems | 2 +- test/ruby/test_process.rb | 1 + test/ruby/test_settracefunc.rb | 6 ++-- tool/mk_builtin_loader.rb | 3 +- 8 files changed, 82 insertions(+), 50 deletions(-) create mode 100644 benchmark/loop_each.yml diff --git a/array.c b/array.c index 93e0cc9be42651..951de5297f6764 100644 --- a/array.c +++ b/array.c @@ -28,6 +28,7 @@ #include "ruby/encoding.h" #include "ruby/st.h" #include "ruby/util.h" +#include "vm_core.h" #include "builtin.h" #if !ARRAY_DEBUG @@ -2484,50 +2485,19 @@ ary_enum_length(VALUE ary, VALUE args, VALUE eobj) return rb_ary_length(ary); } -/* - * call-seq: - * array.each {|element| ... } -> self - * array.each -> Enumerator - * - * Iterates over array elements. - * - * When a block given, passes each successive array element to the block; - * returns +self+: - * - * a = [:foo, 'bar', 2] - * a.each {|element| puts "#{element.class} #{element}" } - * - * 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 # => # - * a1 = e.each {|element| puts "#{element.class} #{element}" } - * - * Output: - * - * Symbol foo - * String bar - * Integer 2 - * - * Related: #each_index, #reverse_each. - */ +// Primitive to avoid a race condition in Array#each. +// Return `true` and write `value` and `index` if the element exists. +static VALUE +ary_fetch_next(VALUE self, VALUE *index, VALUE *value) +{ + long i = NUM2LONG(*index); + if (i >= RARRAY_LEN(self)) { + return Qfalse; + } + *value = RARRAY_AREF(self, i); + *index = LONG2NUM(i + 1); + return Qtrue; +} VALUE rb_ary_each(VALUE ary) @@ -8644,7 +8614,6 @@ Init_Array(void) rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1); rb_define_alias(rb_cArray, "prepend", "unshift"); rb_define_method(rb_cArray, "insert", rb_ary_insert, -1); - rb_define_method(rb_cArray, "each", rb_ary_each, 0); rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0); rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0); rb_define_method(rb_cArray, "length", rb_ary_length, 0); diff --git a/array.rb b/array.rb index d17f3742357613..e1ce6f49f91536 100644 --- a/array.rb +++ b/array.rb @@ -1,4 +1,59 @@ class Array + # call-seq: + # array.each {|element| ... } -> self + # array.each -> Enumerator + # + # Iterates over array elements. + # + # When a block given, passes each successive array element to the block; + # returns +self+: + # + # a = [:foo, 'bar', 2] + # a.each {|element| puts "#{element.class} #{element}" } + # + # 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 # => # + # a1 = e.each {|element| puts "#{element.class} #{element}" } + # + # Output: + # + # Symbol foo + # String bar + # Integer 2 + # + # Related: #each_index, #reverse_each. + def each + Primitive.attr! :inline_block + unless defined?(yield) + return to_enum(:each) { self.length } + end + _i = 0 + value = nil + while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) }) + yield value + end + self + end + # call-seq: # array.shuffle!(random: Random) -> array # diff --git a/benchmark/loop_each.yml b/benchmark/loop_each.yml new file mode 100644 index 00000000000000..1c757185a8a7e9 --- /dev/null +++ b/benchmark/loop_each.yml @@ -0,0 +1,4 @@ +prelude: | + arr = [nil] * 30_000_000 +benchmark: + loop_each: arr.each{|e|} diff --git a/builtin.h b/builtin.h index 85fd1a009a24f5..24aa7c2fdb2fca 100644 --- a/builtin.h +++ b/builtin.h @@ -106,6 +106,8 @@ rb_vm_lvar(rb_execution_context_t *ec, int index) #endif } +#define LOCAL_PTR(local) local ## __ptr + // dump/load struct builtin_binary { diff --git a/gems/bundled_gems b/gems/bundled_gems index 4d9e6cbf942480..8f2ff3f624a20d 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -19,7 +19,7 @@ matrix 0.4.2 https://github.com/ruby/matrix prime 0.1.2 https://github.com/ruby/prime rbs 3.4.2 https://github.com/ruby/rbs typeprof 0.21.9 https://github.com/ruby/typeprof -debug 1.9.1 https://github.com/ruby/debug +debug 1.9.1 https://github.com/ruby/debug 19b91b14ce814a0eb615abb8d2bef0594c61c5c8 racc 1.7.3 https://github.com/ruby/racc mutex_m 0.2.0 https://github.com/ruby/mutex_m getoptlong 0.2.1 https://github.com/ruby/getoptlong diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb index 3d20d6eff5bbcb..8fb3a9df0caad9 100644 --- a/test/ruby/test_process.rb +++ b/test/ruby/test_process.rb @@ -2841,6 +2841,7 @@ def test_concurrent_group_and_pid_wait def test_low_memory_startup omit "JIT enabled" if %w[YJIT RJIT].any? {|n| RubyVM.const_defined?(n) and RubyVM.const_get(n).enabled?} + omit "flaky on Travis arm32" if /armv8l-linux-eabihf/ =~ RUBY_PLATFORM as = 1<<25 _, _, status = EnvUtil.invoke_ruby(%W'-W0', "", true, :merge_to_stdout, rlimit_as: as) omit sprintf("Crashed with AS: %#x: %s", as, status) if status.signaled? diff --git a/test/ruby/test_settracefunc.rb b/test/ruby/test_settracefunc.rb index dbaf0aaf096920..6c17f279d4092b 100644 --- a/test/ruby/test_settracefunc.rb +++ b/test/ruby/test_settracefunc.rb @@ -504,7 +504,7 @@ def trace_by_tracepoint *trace_events 1: trace = TracePoint.trace(*trace_events){|tp| next if !target_thread? 2: events << [tp.event, tp.lineno, tp.path, _defined_class.(tp), tp.method_id, tp.self, tp.binding&.eval("_local_var"), _get_data.(tp)] if tp.path == 'xyzzy' 3: } - 4: [1].each{|;_local_var| _local_var = :inner + 4: [1].reverse_each{|;_local_var| _local_var = :inner 5: tap{} 6: } 7: class XYZZY @@ -531,10 +531,10 @@ def trace_by_tracepoint *trace_events answer_events = [ # [:line, 4, 'xyzzy', self.class, method, self, :outer, :nothing], - [:c_call, 4, 'xyzzy', Array, :each, [1], nil, :nothing], + [:c_call, 4, 'xyzzy', Array, :reverse_each, [1], nil, :nothing], [:line, 4, 'xyzzy', self.class, method, self, nil, :nothing], [:line, 5, 'xyzzy', self.class, method, self, :inner, :nothing], - [:c_return, 4, "xyzzy", Array, :each, [1], nil, [1]], + [:c_return, 4, "xyzzy", Array, :reverse_each, [1], nil, [1]], [:line, 7, 'xyzzy', self.class, method, self, :outer, :nothing], [:c_call, 7, "xyzzy", Module, :const_added, TestSetTraceFunc, nil, :nothing], [:c_return, 7, "xyzzy", Module, :const_added, TestSetTraceFunc, nil, nil], diff --git a/tool/mk_builtin_loader.rb b/tool/mk_builtin_loader.rb index 989c8c5957a433..07c829124948a1 100644 --- a/tool/mk_builtin_loader.rb +++ b/tool/mk_builtin_loader.rb @@ -274,7 +274,8 @@ def generate_cexpr(ofile, lineno, line_file, body_lineno, text, locals, func_nam locals&.reverse_each&.with_index{|param, i| next unless Symbol === param next unless local_candidates.include?(param.to_s) - f.puts "MAYBE_UNUSED(const VALUE) #{param} = rb_vm_lvar(ec, #{-3 - i});" + f.puts "VALUE *const #{param}__ptr = (VALUE *)&ec->cfp->ep[#{-3 - i}];" + f.puts "MAYBE_UNUSED(const VALUE) #{param} = *#{param}__ptr;" lineno += 1 } f.puts "#line #{body_lineno} \"#{line_file}\"" From 333f4b4930bf397f87bd99767b53fcce4f9a3e43 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 23 Jan 2024 12:11:14 -0500 Subject: [PATCH 457/640] [PRISM] Support block parameters with no name Fixes ruby/prism#2249. --- prism_compile.c | 6 ++++-- test/ruby/test_compile_prism.rb | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index cf9bc746253855..9ddd502117005c 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -6632,8 +6632,10 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, body->param.flags.has_block = true; pm_constant_id_t name = ((pm_block_parameter_node_t *)parameters_node->block)->name; - pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node); - local_index++; + if (name != 0) { + pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node); + local_index++; + } } } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 10def69ff2434c..66fbefd27bd1a4 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -2055,6 +2055,10 @@ def test_AliasMethodNode def test_BlockParameterNode assert_prism_eval("def prism_test_block_parameter_node(&bar) end") assert_prism_eval("->(b, c=1, *d, e, &f){}") + + # Test BlockParameterNode with no name + assert_prism_eval("->(&){}") + assert_prism_eval("def prism_test_block_parameter_node(&); end") end def test_BlockParametersNode From cecf42601aa4170aa2336dbb3ffc7753e86e6115 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 23 Jan 2024 14:43:53 -0500 Subject: [PATCH 458/640] [PRISM] Fix block fowarding --- prism_compile.c | 29 +++++++++++++++-------------- test/ruby/test_compile_prism.rb | 9 +++++++++ 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 9ddd502117005c..4ebfca9c1edd6c 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -57,18 +57,8 @@ #define PM_NOP \ ADD_INSN(ret, &dummy_line_node, nop) -/** - * We're using the top most bit of a pm_constant_id_t as a tag to represent an - * anonymous local. When a child iseq is created and needs access to a value - * that has yet to be defined, or is defined by the parent node's iseq. This can - * be added to it's local table and then handled accordingly when compiling the - * scope node associated with the child iseq. - * - * See the compilation process for PM_FOR_NODE: as an example, where the - * variable referenced inside the StatementsNode is defined as part of the top - * level ForLoop node. -*/ -#define TEMP_CONSTANT_IDENTIFIER ((pm_constant_id_t)(1 << 31)) +#define PM_SPECIAL_CONSTANT_FLAG ((pm_constant_id_t)(1 << 31)) +#define PM_CONSTANT_AND ((pm_constant_id_t)(idAnd | PM_SPECIAL_CONSTANT_FLAG)) rb_iseq_t * pm_iseq_new_with_opt(pm_scope_node_t *scope_node, pm_parser_t *parser, VALUE name, VALUE path, VALUE realpath, @@ -2790,6 +2780,8 @@ pm_add_ensure_iseq(LINK_ANCHOR *const ret, rb_iseq_t *iseq, int is_return, const static void pm_insert_local_index(pm_constant_id_t constant_id, int local_index, st_table *index_lookup_table, rb_ast_id_table_t *local_table_for_iseq, pm_scope_node_t *scope_node) { + RUBY_ASSERT((constant_id & PM_SPECIAL_CONSTANT_FLAG) == 0); + ID local = pm_constant_id_lookup(scope_node, constant_id); local_table_for_iseq->ids[local_index] = local; st_insert(index_lookup_table, constant_id, local_index); @@ -3738,6 +3730,10 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, if (block_argument_node->expression) { PM_COMPILE(block_argument_node->expression); } + else { + pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_AND, 0); + ADD_GETLOCAL(ret, &dummy_line_node, index.index, index.level); + } return; } case PM_BREAK_NODE: { @@ -6632,10 +6628,15 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, body->param.flags.has_block = true; pm_constant_id_t name = ((pm_block_parameter_node_t *)parameters_node->block)->name; - if (name != 0) { + if (name == 0) { + local_table_for_iseq->ids[local_index] = PM_CONSTANT_AND; + st_insert(index_lookup_table, PM_CONSTANT_AND, local_index); + } + else { pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node); - local_index++; } + + local_index++; } } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 66fbefd27bd1a4..8357914ce22084 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1690,6 +1690,15 @@ def test_ArgumentsNode def test_BlockArgumentNode assert_prism_eval("1.then(&:to_s)") + + # Test forwarding with no name + assert_prism_eval(<<~RUBY) + o = Object.new + def o.foo(&) = yield + def o.bar(&) = foo(&) + + o.bar { :ok } + RUBY end def test_BlockLocalVariableNode From 7ac74f5c771cef2f94eee9a75a9f96e92da4f5fd Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 23 Jan 2024 15:23:48 -0500 Subject: [PATCH 459/640] Revert "Skip a failing test for Prism" This reverts commit 557b69e83b27dafea435719fc3afc2e67e155962. --- bootstraptest/runner.rb | 4 ---- bootstraptest/test_yjit.rb | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/bootstraptest/runner.rb b/bootstraptest/runner.rb index 9dc3950f07882e..039a15148d2c43 100755 --- a/bootstraptest/runner.rb +++ b/bootstraptest/runner.rb @@ -798,8 +798,4 @@ def rjit_enabled? ENV.fetch('RUN_OPTS', '').include?('rjit') end -def prism_enabled? - ENV.fetch('RUN_OPTS', '').include?('--parser=prism') -end - exit main diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index b320322d84a15e..8ae3399dc20058 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -14,7 +14,7 @@ def call(args, &) rescue ArgumentError :ok end -} unless prism_enabled? # https://github.com/ruby/prism/issues/2249 +} # regression test for send processing before side exit assert_equal "ok", %q{ From 996776e936ac274946a359195ef3fa6a0dca7669 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Tue, 23 Jan 2024 14:37:22 -0800 Subject: [PATCH 460/640] Leave a comment about the limitation of Primitive and adjust some code styling from that PR. --- rjit_c.rb | 12 ++++++++---- tool/rjit/bindgen.rb | 7 +++++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/rjit_c.rb b/rjit_c.rb index ce718717beef4a..92674643c6ea6a 100644 --- a/rjit_c.rb +++ b/rjit_c.rb @@ -1541,13 +1541,17 @@ def C.rb_thread_struct end def C.VALUE - @VALUE ||= CType::Immediate.find(Primitive.cexpr!("SIZEOF(VALUE)"), - Primitive.cexpr!("SIGNED_TYPE_P(VALUE)")) + @VALUE ||= CType::Immediate.find( + Primitive.cexpr!("SIZEOF(VALUE)"), + Primitive.cexpr!("SIGNED_TYPE_P(VALUE)"), + ) end def C.shape_id_t - @shape_id_t ||= CType::Immediate.find(Primitive.cexpr!("SIZEOF(shape_id_t)"), - Primitive.cexpr!("SIGNED_TYPE_P(shape_id_t)")) + @shape_id_t ||= CType::Immediate.find( + Primitive.cexpr!("SIZEOF(shape_id_t)"), + Primitive.cexpr!("SIGNED_TYPE_P(shape_id_t)"), + ) end def C.rb_id_table diff --git a/tool/rjit/bindgen.rb b/tool/rjit/bindgen.rb index fb26b94aa47642..fa68cbc1085c29 100755 --- a/tool/rjit/bindgen.rb +++ b/tool/rjit/bindgen.rb @@ -182,9 +182,12 @@ def generate(nodes) unless generate_node(nodes_index[type])&.start_with?('CType::Immediate') raise "Non-immediate type is given to dynamic_types: #{type}" end + # Only one Primitive.cexpr! is allowed for each line: https://github.com/ruby/ruby/pull/9612 println " def C.#{type}" - println " @#{type} ||= CType::Immediate.find(Primitive.cexpr!(\"SIZEOF(#{type})\")," - println " Primitive.cexpr!(\"SIGNED_TYPE_P(#{type})\"))" + println " @#{type} ||= CType::Immediate.find(" + println " Primitive.cexpr!(\"SIZEOF(#{type})\")," + println " Primitive.cexpr!(\"SIGNED_TYPE_P(#{type})\")," + println " )" println " end" println end From 909a710a695654d13bf6ae824d0a62e682588583 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 23 Jan 2024 16:13:18 -0500 Subject: [PATCH 461/640] [PRISM] Fix anonymous splat nodes Fixes ruby/prism#2257. --- prism_compile.c | 8 +++++++- test/ruby/test_compile_prism.rb | 7 +++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/prism_compile.c b/prism_compile.c index 4ebfca9c1edd6c..df3e0c86593161 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -59,6 +59,7 @@ #define PM_SPECIAL_CONSTANT_FLAG ((pm_constant_id_t)(1 << 31)) #define PM_CONSTANT_AND ((pm_constant_id_t)(idAnd | PM_SPECIAL_CONSTANT_FLAG)) +#define PM_CONSTANT_MULT ((pm_constant_id_t)(idMULT | PM_SPECIAL_CONSTANT_FLAG)) rb_iseq_t * pm_iseq_new_with_opt(pm_scope_node_t *scope_node, pm_parser_t *parser, VALUE name, VALUE path, VALUE realpath, @@ -1125,6 +1126,10 @@ pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinf if (splat_node->expression) { PM_COMPILE_NOT_POPPED(splat_node->expression); } + else { + pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_MULT, 0); + ADD_GETLOCAL(ret, &dummy_line_node, index.index, index.level); + } bool first_splat = !has_splat; @@ -6431,7 +6436,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, else { // def foo(a, (b, *c, d), e = 1, *, g, (h, *i, j), k:, l: 1, **m, &n) // ^ - local_table_for_iseq->ids[local_index] = idMULT; + local_table_for_iseq->ids[local_index] = PM_CONSTANT_MULT; + st_insert(index_lookup_table, PM_CONSTANT_MULT, local_index); } local_index++; } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 8357914ce22084..682f50d1d623db 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -849,6 +849,13 @@ def test_SplatNode assert_prism_eval("*b, c = [1, 2, 3]; c") assert_prism_eval("a, *, c = [1, 2, 3]; a") assert_prism_eval("a, *, c = [1, 2, 3]; c") + + # Test anonymous splat node + assert_prism_eval(<<~RUBY) + def self.bar(*) = Array(*) + + bar([1, 2, 3]) + RUBY end ############################################################################ From c0cabc0a699b2c8b0fded6d0ed85aff4bf102c03 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Tue, 23 Jan 2024 14:54:39 -0800 Subject: [PATCH 462/640] Dump annotations on RubyVM::ISeq.disasm (#9667) Make it easier to check what annotations an ISEQ has. SINGLE_NOARG_LEAF is added automatically, so it's hard to be sure about the annotation by just reading code. It's also unclear to me what happens to it with Primitive.mandatory_only?, but this at least explains that LEAF annotation is not added to the non-mandatory_only ISEQ. --- iseq.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/iseq.c b/iseq.c index babc7948dedc95..87cca58468a23e 100644 --- a/iseq.c +++ b/iseq.c @@ -2526,6 +2526,15 @@ rb_iseq_disasm_recursive(const rb_iseq_t *iseq, VALUE indent) rb_str_modify_expand(str, header_minlen - l); memset(RSTRING_END(str), '=', header_minlen - l); } + if (iseq->body->builtin_attrs) { +#define disasm_builtin_attr(str, iseq, attr) \ + if (iseq->body->builtin_attrs & BUILTIN_ATTR_ ## attr) { \ + rb_str_cat2(str, " " #attr); \ + } + disasm_builtin_attr(str, iseq, LEAF); + disasm_builtin_attr(str, iseq, SINGLE_NOARG_LEAF); + disasm_builtin_attr(str, iseq, INLINE_BLOCK); + } rb_str_cat2(str, "\n"); /* show catch table information */ From ac1e9e443a0d6a4d4c0801c26d1d8bd33d9eb431 Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Tue, 23 Jan 2024 12:35:34 -0500 Subject: [PATCH 463/640] YJIT: Fix ruby2_keywords splat+rest and drop bogus checks YJIT didn't guard for ruby2_keywords hash in case of splat calls that land in methods with a rest parameter, creating incorrect results. The compile-time checks didn't correspond to any actual effects of ruby2_keywords, so it was masking this bug and YJIT was needlessly refusing to compile some code. About 16% of fallback reasons in `lobsters` was due to the ISeq check. We already handle the tagging part with exit_if_supplying_kw_and_has_no_kw() and should now have a dynamic guard for all splat cases. Note for backporting: You also need 7f51959ff1. [Bug #20195] --- bootstraptest/test_yjit.rb | 16 ++++++++++++++ yjit.c | 13 ++++++++++++ yjit/bindgen/src/main.rs | 1 + yjit/src/codegen.rs | 38 +++++++++------------------------- yjit/src/cruby.rs | 1 - yjit/src/cruby_bindings.inc.rs | 1 + yjit/src/stats.rs | 2 -- 7 files changed, 41 insertions(+), 31 deletions(-) diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index 8ae3399dc20058..6832a0d76c513f 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -4443,3 +4443,19 @@ def entry def defined_yield = defined?(yield) [defined_yield, defined_yield {}] } + +# splat with ruby2_keywords into rest parameter +assert_equal '[[{:a=>1}], {}]', %q{ + ruby2_keywords def foo(*args) = args + + def bar(*args, **kw) = [args, kw] + + def pass_bar(*args) = bar(*args) + + def body + args = foo(a: 1) + pass_bar(*args) + end + + body +} diff --git a/yjit.c b/yjit.c index d5071cb952858e..cf6d81092fae33 100644 --- a/yjit.c +++ b/yjit.c @@ -871,6 +871,19 @@ rb_yjit_fix_mod_fix(VALUE recv, VALUE obj) return rb_fix_mod_fix(recv, obj); } +// Return non-zero when `obj` is an array and its last item is a +// `ruby2_keywords` hash. We don't support this kind of splat. +size_t +rb_yjit_ruby2_keywords_splat_p(VALUE obj) +{ + if (!RB_TYPE_P(obj, T_ARRAY)) return 0; + long len = RARRAY_LEN(obj); + if (len == 0) return 0; + VALUE last = RARRAY_AREF(obj, len - 1); + if (!RB_TYPE_P(last, T_HASH)) return 0; + return FL_TEST_RAW(last, RHASH_PASS_AS_KEYWORDS); +} + // Print the Ruby source location of some ISEQ for debugging purposes void rb_yjit_dump_iseq_loc(const rb_iseq_t *iseq, uint32_t insn_idx) diff --git a/yjit/bindgen/src/main.rs b/yjit/bindgen/src/main.rs index e249181d515275..742885de3b53ff 100644 --- a/yjit/bindgen/src/main.rs +++ b/yjit/bindgen/src/main.rs @@ -426,6 +426,7 @@ fn main() { .allowlist_function("rb_yarv_str_eql_internal") .allowlist_function("rb_str_neq_internal") .allowlist_function("rb_yarv_ary_entry_internal") + .allowlist_function("rb_yjit_ruby2_keywords_splat_p") .allowlist_function("rb_yjit_fix_div_fix") .allowlist_function("rb_yjit_fix_mod_fix") .allowlist_function("rb_FL_TEST") diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 8847affd2be4b5..344150b025623a 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -5555,18 +5555,6 @@ fn gen_send_cfunc( return None; } - // In order to handle backwards compatibility between ruby 3 and 2 - // ruby2_keywords was introduced. It is called only on methods - // with splat and changes they way they handle them. - // We are just going to not compile these. - // https://docs.ruby-lang.org/en/3.2/Module.html#method-i-ruby2_keywords - if unsafe { - get_iseq_flags_ruby2_keywords(jit.iseq) && flags & VM_CALL_ARGS_SPLAT != 0 - } { - gen_counter_incr(asm, Counter::send_args_splat_cfunc_ruby2_keywords); - return None; - } - let kw_arg = unsafe { vm_ci_kwarg(ci) }; let kw_arg_num = if kw_arg.is_null() { 0 @@ -6147,7 +6135,6 @@ fn gen_send_iseq( exit_if_has_post(asm, iseq)?; exit_if_has_kwrest(asm, iseq)?; exit_if_kw_splat(asm, flags)?; - exit_if_splat_and_ruby2_keywords(asm, jit, flags)?; exit_if_has_rest_and_captured(asm, iseq_has_rest, captured_opnd)?; exit_if_has_rest_and_supplying_kws(asm, iseq_has_rest, iseq, supplying_kws)?; exit_if_supplying_kw_and_has_no_kw(asm, supplying_kws, iseq)?; @@ -6426,6 +6413,8 @@ fn gen_send_iseq( asm.jbe(Target::side_exit(Counter::guard_send_se_cf_overflow)); if iseq_has_rest && flags & VM_CALL_ARGS_SPLAT != 0 { + let splat_pos = i32::from(block_arg) + kw_arg_num; + // Insert length guard for a call to copy_splat_args_for_rest_callee() // that will come later. We will have made changes to // the stack by spilling or handling __send__ shifting @@ -6439,12 +6428,19 @@ fn gen_send_iseq( if take_count > 0 { asm_comment!(asm, "guard splat_array_length >= {take_count}"); - let splat_array = asm.stack_opnd(i32::from(block_arg) + kw_arg_num); + let splat_array = asm.stack_opnd(splat_pos); let array_len_opnd = get_array_len(asm, splat_array); asm.cmp(array_len_opnd, take_count.into()); asm.jl(Target::side_exit(Counter::guard_send_iseq_has_rest_and_splat_too_few)); } } + + // All splats need to guard for ruby2_keywords hash. Check with a function call when + // splatting into a rest param since the index for the last item in the array is dynamic. + asm_comment!(asm, "guard no ruby2_keywords hash in splat"); + let bad_splat = asm.ccall(rb_yjit_ruby2_keywords_splat_p as _, vec![asm.stack_opnd(splat_pos)]); + asm.cmp(bad_splat, 0.into()); + asm.jnz(Target::side_exit(Counter::guard_send_splatarray_last_ruby_2_keywords)); } match block_arg_type { @@ -7008,20 +7004,6 @@ fn exit_if_kw_splat(asm: &mut Assembler, flags: u32) -> Option<()> { exit_if(asm, flags & VM_CALL_KW_SPLAT != 0, Counter::send_iseq_kw_splat) } -#[must_use] -fn exit_if_splat_and_ruby2_keywords(asm: &mut Assembler, jit: &mut JITState, flags: u32) -> Option<()> { - // In order to handle backwards compatibility between ruby 3 and 2 - // ruby2_keywords was introduced. It is called only on methods - // with splat and changes they way they handle them. - // We are just going to not compile these. - // https://www.rubydoc.info/stdlib/core/Proc:ruby2_keywords - exit_if( - asm, - unsafe { get_iseq_flags_ruby2_keywords(jit.iseq) } && flags & VM_CALL_ARGS_SPLAT != 0, - Counter::send_iseq_ruby2_keywords, - ) -} - #[must_use] fn exit_if_has_rest_and_captured(asm: &mut Assembler, iseq_has_rest: bool, captured_opnd: Option) -> Option<()> { exit_if(asm, iseq_has_rest && captured_opnd.is_some(), Counter::send_iseq_has_rest_and_captured) diff --git a/yjit/src/cruby.rs b/yjit/src/cruby.rs index ac0bdf68856f1d..9f289e93dda4ae 100644 --- a/yjit/src/cruby.rs +++ b/yjit/src/cruby.rs @@ -165,7 +165,6 @@ pub use rb_get_iseq_flags_has_lead as get_iseq_flags_has_lead; pub use rb_get_iseq_flags_has_opt as get_iseq_flags_has_opt; pub use rb_get_iseq_flags_has_kw as get_iseq_flags_has_kw; pub use rb_get_iseq_flags_has_rest as get_iseq_flags_has_rest; -pub use rb_get_iseq_flags_ruby2_keywords as get_iseq_flags_ruby2_keywords; pub use rb_get_iseq_flags_has_post as get_iseq_flags_has_post; pub use rb_get_iseq_flags_has_kwrest as get_iseq_flags_has_kwrest; pub use rb_get_iseq_flags_has_block as get_iseq_flags_has_block; diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs index e6dba2b59df2a5..7b0f5678977897 100644 --- a/yjit/src/cruby_bindings.inc.rs +++ b/yjit/src/cruby_bindings.inc.rs @@ -1140,6 +1140,7 @@ extern "C" { pub fn rb_yjit_rb_ary_subseq_length(ary: VALUE, beg: ::std::os::raw::c_long) -> VALUE; pub fn rb_yjit_fix_div_fix(recv: VALUE, obj: VALUE) -> VALUE; pub fn rb_yjit_fix_mod_fix(recv: VALUE, obj: VALUE) -> VALUE; + pub fn rb_yjit_ruby2_keywords_splat_p(obj: VALUE) -> usize; pub fn rb_yjit_dump_iseq_loc(iseq: *const rb_iseq_t, insn_idx: u32); pub fn rb_FL_TEST(obj: VALUE, flags: VALUE) -> VALUE; pub fn rb_FL_TEST_RAW(obj: VALUE, flags: VALUE) -> VALUE; diff --git a/yjit/src/stats.rs b/yjit/src/stats.rs index d8dd4b93893a85..98e33f23757c94 100644 --- a/yjit/src/stats.rs +++ b/yjit/src/stats.rs @@ -378,10 +378,8 @@ make_counters! { send_args_splat_opt_call, send_args_splat_cfunc_var_args, send_args_splat_cfunc_zuper, - send_args_splat_cfunc_ruby2_keywords, send_iseq_splat_arity_error, send_splat_too_long, - send_iseq_ruby2_keywords, send_send_not_imm, send_send_wrong_args, send_send_null_mid, From 974b141ffe69a56bc9d8d4c75ea6e5852df19f36 Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Tue, 23 Jan 2024 18:45:07 -0500 Subject: [PATCH 464/640] YJIT: Reuse get_array_{ptr,len} --- yjit/src/codegen.rs | 63 +++------------------------------------------ 1 file changed, 4 insertions(+), 59 deletions(-) diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 344150b025623a..0f9e15b513b57b 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -5888,24 +5888,8 @@ fn copy_splat_args_for_rest_callee(array: Opnd, num_args: u32, asm: &mut Assembl asm_comment!(asm, "Push arguments from array"); - // Load the address of the embedded array - // (struct RArray *)(obj)->as.ary let array_reg = asm.load(array); - - // Conditionally load the address of the heap array - // (struct RArray *)(obj)->as.heap.ptr - let flags_opnd = Opnd::mem(VALUE_BITS, array_reg, RUBY_OFFSET_RBASIC_FLAGS); - asm.test(flags_opnd, Opnd::UImm(RARRAY_EMBED_FLAG as u64)); - let heap_ptr_opnd = Opnd::mem( - usize::BITS as u8, - array_reg, - RUBY_OFFSET_RARRAY_AS_HEAP_PTR, - ); - // Load the address of the embedded array - // (struct RArray *)(obj)->as.ary - let ary_opnd = asm.lea(Opnd::mem(VALUE_BITS, array_reg, RUBY_OFFSET_RARRAY_AS_ARY)); - let ary_opnd = asm.csel_nz(ary_opnd, heap_ptr_opnd); - + let ary_opnd = get_array_ptr(asm, array_reg); for i in 0..num_args { let top = asm.stack_push(Type::Unknown); asm.mov(top, Opnd::mem(64, ary_opnd, i as i32 * SIZEOF_VALUE_I32)); @@ -5919,38 +5903,14 @@ fn push_splat_args(required_args: u32, asm: &mut Assembler) { asm_comment!(asm, "push_splat_args"); let array_opnd = asm.stack_opnd(0); - let array_reg = asm.load(array_opnd); - guard_object_is_array( asm, - array_reg, + array_opnd, array_opnd.into(), Counter::guard_send_splat_not_array, ); - asm_comment!(asm, "Get array length for embedded or heap"); - - // Pull out the embed flag to check if it's an embedded array. - let flags_opnd = Opnd::mem(VALUE_BITS, array_reg, RUBY_OFFSET_RBASIC_FLAGS); - - // Get the length of the array - let emb_len_opnd = asm.and(flags_opnd, (RARRAY_EMBED_LEN_MASK as u64).into()); - let emb_len_opnd = asm.rshift(emb_len_opnd, (RARRAY_EMBED_LEN_SHIFT as u64).into()); - - // Conditionally move the length of the heap array - let flags_opnd = Opnd::mem(VALUE_BITS, array_reg, RUBY_OFFSET_RBASIC_FLAGS); - asm.test(flags_opnd, (RARRAY_EMBED_FLAG as u64).into()); - - // Need to repeat this here to deal with register allocation - let array_opnd = asm.stack_opnd(0); - let array_reg = asm.load(array_opnd); - - let array_len_opnd = Opnd::mem( - std::os::raw::c_long::BITS as u8, - array_reg, - RUBY_OFFSET_RARRAY_AS_HEAP_LEN, - ); - let array_len_opnd = asm.csel_nz(emb_len_opnd, array_len_opnd); + let array_len_opnd = get_array_len(asm, array_opnd); asm_comment!(asm, "Guard for expected splat length"); asm.cmp(array_len_opnd, required_args.into()); @@ -5975,23 +5935,8 @@ fn push_splat_args(required_args: u32, asm: &mut Assembler) { let array_opnd = asm.stack_pop(1); if required_args > 0 { - // Load the address of the embedded array - // (struct RArray *)(obj)->as.ary let array_reg = asm.load(array_opnd); - - // Conditionally load the address of the heap array - // (struct RArray *)(obj)->as.heap.ptr - let flags_opnd = Opnd::mem(VALUE_BITS, array_reg, RUBY_OFFSET_RBASIC_FLAGS); - asm.test(flags_opnd, Opnd::UImm(RARRAY_EMBED_FLAG as u64)); - let heap_ptr_opnd = Opnd::mem( - usize::BITS as u8, - array_reg, - RUBY_OFFSET_RARRAY_AS_HEAP_PTR, - ); - // Load the address of the embedded array - // (struct RArray *)(obj)->as.ary - let ary_opnd = asm.lea(Opnd::mem(VALUE_BITS, array_reg, RUBY_OFFSET_RARRAY_AS_ARY)); - let ary_opnd = asm.csel_nz(ary_opnd, heap_ptr_opnd); + let ary_opnd = get_array_ptr(asm, array_reg); for i in 0..required_args { let top = asm.stack_push(Type::Unknown); From d914f82a3c042f411241a287f9c931b4b2eed7bd Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 24 Jan 2024 09:53:38 +0900 Subject: [PATCH 465/640] Use test fixed version of debug gem https://github.com/ruby/debug/pull/1067 --- gems/bundled_gems | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gems/bundled_gems b/gems/bundled_gems index 8f2ff3f624a20d..02d583ebf656a2 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -19,7 +19,7 @@ matrix 0.4.2 https://github.com/ruby/matrix prime 0.1.2 https://github.com/ruby/prime rbs 3.4.2 https://github.com/ruby/rbs typeprof 0.21.9 https://github.com/ruby/typeprof -debug 1.9.1 https://github.com/ruby/debug 19b91b14ce814a0eb615abb8d2bef0594c61c5c8 +debug 1.9.1 https://github.com/ruby/debug 91fe870eeceb9ffbbc7f1bb4673f9e2f6a2c1f60 racc 1.7.3 https://github.com/ruby/racc mutex_m 0.2.0 https://github.com/ruby/mutex_m getoptlong 0.2.1 https://github.com/ruby/getoptlong From a170f1859b47c59bb0d80531086bbc6f5e812f8a Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 24 Jan 2024 10:44:18 +0900 Subject: [PATCH 466/640] No longer needed to sync syslog --- tool/sync_default_gems.rb | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb index 4ccad7c9425e2f..45824cd1e4db86 100755 --- a/tool/sync_default_gems.rb +++ b/tool/sync_default_gems.rb @@ -58,7 +58,6 @@ module SyncDefaultGems stringio: 'ruby/stringio', strscan: 'ruby/strscan', syntax_suggest: ["ruby/syntax_suggest", "main"], - syslog: "ruby/syslog", tempfile: "ruby/tempfile", time: "ruby/time", timeout: "ruby/timeout", @@ -316,14 +315,6 @@ def sync_default_gems(gem) cp_r("#{upstream}/test/erb", "test") cp_r("#{upstream}/erb.gemspec", "lib") cp_r("#{upstream}/libexec/erb", "libexec") - when "syslog" - rm_rf(%w[ext/syslog test/syslog test/test_syslog.rb]) - cp_r("#{upstream}/ext/syslog", "ext") - cp_r("#{upstream}/lib", "ext/syslog") - cp_r("#{upstream}/test/syslog", "test") - cp_r("#{upstream}/test/test_syslog.rb", "test") - cp_r("#{upstream}/syslog.gemspec", "ext/syslog") - `git checkout ext/syslog/depend` when "pathname" rm_rf(%w[ext/pathname test/pathname]) cp_r("#{upstream}/ext/pathname", "ext") From c16aaf119a8bac0d78b4124ecc097735a7c6ed83 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Jan 2024 02:36:11 +0000 Subject: [PATCH 467/640] Bump actions/upload-artifact from 4.2.0 to 4.3.0 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.2.0 to 4.3.0. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/694cdabd8bdb0f10b2cea11669e1bf5453eed0a6...26f96dfa697d77e81fd5907df203aa23a56210a8) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/wasm.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml index 3586e3ebe223e0..b5cf7f1abf917b 100644 --- a/.github/workflows/wasm.yml +++ b/.github/workflows/wasm.yml @@ -136,7 +136,7 @@ jobs: - run: tar cfz ../install.tar.gz -C ../install . - name: Upload artifacts - uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: ruby-wasm-install path: ${{ github.workspace }}/install.tar.gz @@ -164,7 +164,7 @@ jobs: - name: Save Pull Request number if: ${{ github.event_name == 'pull_request' }} run: echo "${{ github.event.pull_request.number }}" >> ${{ github.workspace }}/github-pr-info.txt - - uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 + - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 if: ${{ github.event_name == 'pull_request' }} with: name: github-pr-info From df5f2fab938cd020dfdeeb8db46cfaefe57aa6bc Mon Sep 17 00:00:00 2001 From: Burdette Lamar Date: Tue, 23 Jan 2024 21:43:52 -0600 Subject: [PATCH 468/640] [DOC] Correction for Process.spawn doc --- process.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/process.c b/process.c index df284a135c0318..8a28a9e760bab7 100644 --- a/process.c +++ b/process.c @@ -4991,7 +4991,9 @@ rb_f_system(int argc, VALUE *argv, VALUE _) * * "Hello! 1\n" * - * Ruby invokes the executable directly, with no shell and no shell expansion. + * Ruby invokes the executable directly. + * This form does not use the shell; + * see below for caveats. * * If one or more +args+ is given, each is an argument or option * to be passed to the executable: @@ -5006,6 +5008,14 @@ rb_f_system(int argc, VALUE *argv, VALUE _) * C* * hello world * + * The 'cmdname, arg1, ...' form does not use the shell. However, + * on different OSes, different things are provided as built-in + * commands. An example of this is 'echo', which is a built-in + * on Windows, but is a normal program on Linux and Mac OS X. + * This means that `Process.spawn 'echo', '%Path%'` will display + * the contents of the `%Path%` environment variable on Windows, + * but `Process.spawn 'echo', '$PATH'` prints the literal '$PATH'. + * * Raises an exception if the new process could not execute. */ From 828f3ecfcdbc740bc9eedbfc946576ad9aeaa43f Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 21 Jan 2024 19:14:41 +0900 Subject: [PATCH 469/640] [DOC] Move `exe_path` example to `Process` module document Exchanged with `Kernel.spawn`, like as `Kernel.exec` and `Kernel.system`. This description should be common for these methods. --- process.c | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/process.c b/process.c index 8a28a9e760bab7..8ea7bb888aff67 100644 --- a/process.c +++ b/process.c @@ -4972,24 +4972,16 @@ rb_f_system(int argc, VALUE *argv, VALUE _) * * Argument +exe_path+ is one of the following: * - * - The string path to an executable to be called: + * - The string path to an executable to be called. + * - A 2-element array containing the path to an executable to be called, + * and the string to be used as the name of the executing process. * * spawn('/usr/bin/date') # Path to date on Unix-style system. * Process.wait * * Output: * - * Thu Aug 31 10:06:48 AM CDT 2023 - * - * - A 2-element array containing the path to an executable - * and the string to be used as the name of the executing process: - * - * pid = spawn(['sleep', 'Hello!'], '1') # 2-element array. - * p `ps -p #{pid} -o command=` - * - * Output: - * - * "Hello! 1\n" + * Mon Aug 28 11:43:10 AM CDT 2023 * * Ruby invokes the executable directly. * This form does not use the shell; @@ -8877,18 +8869,28 @@ proc_warmup(VALUE _) * * Argument +exe_path+ is one of the following: * - * - The string path to an executable to be called. - * - A 2-element array containing the path to an executable to be called, - * and the string to be used as the name of the executing process. + * - The string path to an executable to be called: * - * Example: + * Example: * - * system('/usr/bin/date') # => true # Path to date on Unix-style system. - * system('foo') # => nil # Command failed. + * system('/usr/bin/date') # => true # Path to date on Unix-style system. + * system('foo') # => nil # Command execlution failed. * - * Output: + * Output: + * + * Thu Aug 31 10:06:48 AM CDT 2023 + * + * - A 2-element array containing the path to an executable + * and the string to be used as the name of the executing process: + * + * Example: + * + * pid = spawn(['sleep', 'Hello!'], '1') # 2-element array. + * p `ps -p #{pid} -o command=` + * + * Output: * - * Mon Aug 28 11:43:10 AM CDT 2023 + * "Hello! 1\n" * * === Execution Options * From be6e06ef740e0d5198a4c3b59b13b944809f5ab6 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 21 Jan 2024 19:29:11 +0900 Subject: [PATCH 470/640] [DOC] Separate standard shells per platforms --- process.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/process.c b/process.c index 8ea7bb888aff67..c1579c3714031a 100644 --- a/process.c +++ b/process.c @@ -9025,21 +9025,31 @@ proc_warmup(VALUE _) * === Execution Shell * * On a Unix-like system, the shell invoked is /bin/sh; - * otherwise the shell invoked is determined by environment variable - * ENV['RUBYSHELL'], if defined, or ENV['COMSPEC'] otherwise. - * - * Except for the +COMSPEC+ case, * the entire string +command_line+ is passed as an argument * to {shell option -c}[https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/utilities/sh.html]. * * The shell performs normal shell expansion on the command line: * - * spawn('echo C*') # => 799139 - * Process.wait # => 799139 + * Example: + * + * system('echo $SHELL: C*') # => true + * + * Output: + * + * /bin/bash: CONTRIBUTING.md COPYING COPYING.ja + * + * On Windows, the shell invoked is determined by environment variable + * +RUBYSHELL+, if defined, or +COMSPEC+ otherwise. The standard + * shell +cmd.exe+ performs environment variable expansion but does + * not have globbing functionality: + * + * Example: + * + * system("echo %COMSPEC%: C*")' # => true * * Output: * - * CONTRIBUTING.md COPYING COPYING.ja + * C:\WINDOWS\system32\cmd.exe: C* * * == What's Here * From 623058649e18e7a65b8ba3498b6524fad482b3e0 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 21 Jan 2024 20:01:10 +0900 Subject: [PATCH 471/640] [DOC] Add Argument `args` subsection --- process.c | 56 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/process.c b/process.c index c1579c3714031a..31810d96694a04 100644 --- a/process.c +++ b/process.c @@ -3114,7 +3114,9 @@ NORETURN(static VALUE f_exec(int c, const VALUE *a, VALUE _)); * * Sat Aug 26 09:38:00 AM CDT 2023 * - * Ruby invokes the executable directly, with no shell and no shell expansion: + * Ruby invokes the executable directly. + * This form does not use the shell; + * see {Arguments args}[rdoc-ref:Process@Arguments+args] for caveats. * * exec('doesnt_exist') # Raises Errno::ENOENT * @@ -4820,7 +4822,9 @@ rb_spawn(int argc, const VALUE *argv) * system('foo') # => nil * $? # => # * - * Ruby invokes the executable directly, with no shell and no shell expansion: + * Ruby invokes the executable directly. + * This form does not use the shell; + * see {Arguments args}[rdoc-ref:Process@Arguments+args] for caveats. * * system('doesnt_exist') # => nil * @@ -4985,7 +4989,7 @@ rb_f_system(int argc, VALUE *argv, VALUE _) * * Ruby invokes the executable directly. * This form does not use the shell; - * see below for caveats. + * see {Arguments args}[rdoc-ref:Process@Arguments+args] for caveats. * * If one or more +args+ is given, each is an argument or option * to be passed to the executable: @@ -5000,14 +5004,6 @@ rb_f_system(int argc, VALUE *argv, VALUE _) * C* * hello world * - * The 'cmdname, arg1, ...' form does not use the shell. However, - * on different OSes, different things are provided as built-in - * commands. An example of this is 'echo', which is a built-in - * on Windows, but is a normal program on Linux and Mac OS X. - * This means that `Process.spawn 'echo', '%Path%'` will display - * the contents of the `%Path%` environment variable on Windows, - * but `Process.spawn 'echo', '$PATH'` prints the literal '$PATH'. - * * Raises an exception if the new process could not execute. */ @@ -8843,7 +8839,7 @@ proc_warmup(VALUE _) * or if it contains one or more meta characters. * - +exe_path+ otherwise. * - * Argument +command_line+ + * ==== Argument +command_line+ * * \String argument +command_line+ is a command line to be passed to a shell; * it must begin with a shell reserved word, begin with a special built-in, @@ -8865,7 +8861,7 @@ proc_warmup(VALUE _) * * See {Execution Shell}[rdoc-ref:Process@Execution+Shell] for details about the shell. * - * Argument +exe_path+ + * ==== Argument +exe_path+ * * Argument +exe_path+ is one of the following: * @@ -8892,6 +8888,40 @@ proc_warmup(VALUE _) * * "Hello! 1\n" * + * === Arguments +args+ + * + * If +command_line+ does not contain shell meta characters except for + * spaces and tabs, or +exe_path+ is given, Ruby invokes the + * executable directly. This form does not use the shell: + * + * spawn("doesnt_exist") # Raises Errno::ENOENT + * spawn("doesnt_exist", "\n") # Raises Errno::ENOENT + * + * spawn("doesnt_exist\n") # => false + * # sh: 1: doesnot_exist: not found + * + * The error message is from a shell and would vary depending on your + * system. + * + * If one or more +args+ is given after +exe_path+, each is an + * argument or option to be passed to the executable: + * + * Example: + * + * system('echo', '<', 'C*', '|', '$SHELL', '>') # => true + * + * Output: + * + * < C* | $SHELL > + * + * However, on different OSes, different things are provided as + * built-in commands. An example of this is +'echo'+, which is a + * built-in on Windows, but is a normal program on Linux and Mac OS X. + * This means that Process.spawn 'echo', '%Path%' will + * display the contents of the %Path% environment variable on + * Windows, but Process.spawn 'echo', '$PATH' prints the + * literal $PATH. + * * === Execution Options * * Optional trailing argument +options+ is a hash of execution options. From 769bb924b2e4ece7c1884f4adeb29a49d03bd45a Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 21 Jan 2024 20:02:34 +0900 Subject: [PATCH 472/640] [DOC] Tips for space containing `exe_path` --- process.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/process.c b/process.c index 31810d96694a04..3eb1ca40925304 100644 --- a/process.c +++ b/process.c @@ -8876,6 +8876,11 @@ proc_warmup(VALUE _) * * Thu Aug 31 10:06:48 AM CDT 2023 * + * A path or command name containing spaces without arguments cannot + * be distinguished from +command_line+ above, so you must quote or + * escape the entire command name using a shell in platform + * dependent manner, or use the array form below. + * * - A 2-element array containing the path to an executable * and the string to be used as the name of the executing process: * @@ -8922,6 +8927,15 @@ proc_warmup(VALUE _) * Windows, but Process.spawn 'echo', '$PATH' prints the * literal $PATH. * + * If you want to invoke a path containing spaces with no arguments + * without shell, you will need to use a 2-element array +exe_path+. + * + * Example: + * + * path = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome' + * spawn(path) # Raises Errno::ENOENT; No such file or directory - /Applications/Google + * spawn([path] * 2) + * * === Execution Options * * Optional trailing argument +options+ is a hash of execution options. From 2defa9f4ae52c99e64a02b7f78362fbd788a1fd0 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 22 Jan 2024 19:37:04 +0900 Subject: [PATCH 473/640] [DOC] Elaborate exceptional behaviors on Windows --- process.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/process.c b/process.c index 3eb1ca40925304..c2ef3979d85776 100644 --- a/process.c +++ b/process.c @@ -8919,13 +8919,8 @@ proc_warmup(VALUE _) * * < C* | $SHELL > * - * However, on different OSes, different things are provided as - * built-in commands. An example of this is +'echo'+, which is a - * built-in on Windows, but is a normal program on Linux and Mac OS X. - * This means that Process.spawn 'echo', '%Path%' will - * display the contents of the %Path% environment variable on - * Windows, but Process.spawn 'echo', '$PATH' prints the - * literal $PATH. + * However, there are exceptions on Windows. See {Execution Shell on + * Windows}[rdoc-ref:Process@Execution+Shell+on+Windows]. * * If you want to invoke a path containing spaces with no arguments * without shell, you will need to use a 2-element array +exe_path+. @@ -9082,10 +9077,27 @@ proc_warmup(VALUE _) * * /bin/bash: CONTRIBUTING.md COPYING COPYING.ja * + * === Execution Shell on Windows + * * On Windows, the shell invoked is determined by environment variable - * +RUBYSHELL+, if defined, or +COMSPEC+ otherwise. The standard - * shell +cmd.exe+ performs environment variable expansion but does - * not have globbing functionality: + * +RUBYSHELL+, if defined, or +COMSPEC+ otherwise; the entire string + * +command_line+ is passed as an argument to -c option for + * +RUBYSHELL+, as well as /bin/sh, and {/c + * option}[https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/cmd] + * for +COMSPEC+. The shell is invoked automatically in the following + * cases: + * + * - The command is a built-in of +cmd.exe+, such as +echo+. + * - The executable file is a batch file; its name ends with +.bat+ or + * +.cmd+. + * + * Note that the command will still be invoked as +command_line+ form + * even when called in +exe_path+ form, because +cmd.exe+ does not + * accept a script name like /bin/sh does but only works with + * /c option. + * + * The standard shell +cmd.exe+ performs environment variable + * expansion but does not have globbing functionality: * * Example: * From 01f9766aa05182a7bbdc914a5dcd8a36ebade861 Mon Sep 17 00:00:00 2001 From: Martin Emde Date: Sun, 17 Dec 2023 13:22:38 -0800 Subject: [PATCH 474/640] Ensure File.open applies default umask on gem extract --- lib/rubygems/package.rb | 8 ++++--- test/rubygems/test_gem.rb | 8 +++++-- test/rubygems/test_gem_package.rb | 37 ++++++++++++++++++++++++++++++- 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/lib/rubygems/package.rb b/lib/rubygems/package.rb index 387e40ffd753bb..7b4cab79645ec2 100644 --- a/lib/rubygems/package.rb +++ b/lib/rubygems/package.rb @@ -448,13 +448,15 @@ def extract_tar_gz(io, destination_dir, pattern = "*") # :nodoc: end unless directories.include?(mkdir) - FileUtils.mkdir_p mkdir, mode: dir_mode ? 0o755 : (entry.header.mode if entry.directory?) + mkdir_mode = 0o755 if dir_mode + mkdir_mode ||= entry.header.mode if entry.directory? + mkdir_mode &= ~File.umask if mkdir_mode + FileUtils.mkdir_p mkdir, mode: mkdir_mode directories << mkdir end if entry.file? - File.open(destination, "wb") {|out| copy_stream(entry, out) } - FileUtils.chmod file_mode(entry.header.mode), destination + File.open(destination, "wb", file_mode(entry.header.mode)) {|out| copy_stream(entry, out) } end verbose destination diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index d4c307978e7c5d..8dc8563aaf649b 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -161,13 +161,17 @@ def assert_self_install_permissions(format_executable: false) format_executable: format_executable, } Dir.chdir @tempdir do + # use chmod to set global permissions (so umask doesn't bypass our choice) to ensure they are masked on install Dir.mkdir "bin" + File.chmod 0o777, "bin" Dir.mkdir "data" + File.chmod 0o777, "data" File.write "bin/foo", "#!/usr/bin/env ruby\n" - File.chmod 0o755, "bin/foo" + File.chmod 0o777, "bin/foo" File.write "data/foo.txt", "blah\n" + File.chmod 0o666, "data/foo.txt" spec_fetcher do |f| f.gem "foo", 1 do |s| @@ -180,7 +184,7 @@ def assert_self_install_permissions(format_executable: false) prog_mode = (options[:prog_mode] & mask).to_s(8) dir_mode = (options[:dir_mode] & mask).to_s(8) - data_mode = (options[:data_mode] & mask).to_s(8) + data_mode = (options[:data_mode] & mask & (~File.umask)).to_s(8) prog_name = "foo" prog_name = RbConfig::CONFIG["ruby_install_name"].sub("ruby", "foo") if options[:format_executable] expected = { diff --git a/test/rubygems/test_gem_package.rb b/test/rubygems/test_gem_package.rb index 2065864107715a..7adbc695ec2fc2 100644 --- a/test/rubygems/test_gem_package.rb +++ b/test/rubygems/test_gem_package.rb @@ -523,7 +523,42 @@ def test_extract_file_permissions filepath = File.join @destination, "README.rdoc" assert_path_exist filepath - assert_equal 0o104444, File.stat(filepath).mode + assert_equal 0o100444.to_s(8), File.stat(filepath).mode.to_s(8) + end + + def test_extract_file_umask_global_permissions + pend "chmod not supported" if Gem.win_platform? + + package = Gem::Package.new @gem + + tgz_io = util_tar_gz do |tar| + tar.mkdir "lib", 0o777 + tar.add_file "bin/global", 0o777 do |io| + io.write "#!/bin/ruby\nputs 'hello world'" + end + tar.add_file "lib/global.rb", 0o666 do |io| + io.write "puts 'hello world'" + end + end + + package.extract_tar_gz tgz_io, @destination + + dirpath = File.join @destination, "lib" + assert_path_exist dirpath + mode = 0o40755 & (~File.umask) + assert_equal mode.to_s(8), File.stat(dirpath).mode.to_s(8) + + filepath = File.join @destination, "lib", "global.rb" + assert_path_exist filepath + assert_equal "puts 'hello world'", File.read(filepath) + mode = 0o100644 & (~File.umask) + assert_equal mode.to_s(8), File.stat(filepath).mode.to_s(8) + + filepath = File.join @destination, "bin", "global" + assert_path_exist filepath + assert_equal "#!/bin/ruby\nputs 'hello world'", File.read(filepath) + mode = 0o100755 & (~File.umask) + assert_equal mode.to_s(8), File.stat(filepath).mode.to_s(8) end def test_extract_tar_gz_absolute From 772afa00b5109f55c1d8359c688aca4063818549 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 24 Jan 2024 13:01:39 +0900 Subject: [PATCH 475/640] Pend tests on Travis CI --- test/rubygems/test_gem_package.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/rubygems/test_gem_package.rb b/test/rubygems/test_gem_package.rb index 7adbc695ec2fc2..f762b24b0bc00d 100644 --- a/test/rubygems/test_gem_package.rb +++ b/test/rubygems/test_gem_package.rb @@ -513,6 +513,7 @@ def test_extract_files_empty def test_extract_file_permissions pend "chmod not supported" if Gem.win_platform? + pend "Travis CI enable writable permission to group" if ENV['TRAVIS'] gem_with_long_permissions = File.expand_path("packages/Bluebie-legs-0.6.2.gem", __dir__) @@ -528,6 +529,7 @@ def test_extract_file_permissions def test_extract_file_umask_global_permissions pend "chmod not supported" if Gem.win_platform? + pend "Travis CI enable writable permission to group" if ENV['TRAVIS'] package = Gem::Package.new @gem From 1e519abe21466c3846be7da37c3c8e461fc4efb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=AA=E3=81=A4=E3=81=8D?= Date: Wed, 17 Jan 2024 14:57:09 -0800 Subject: [PATCH 476/640] [rubygems/rubygems] Fix rake extension warning https://github.com/rubygems/rubygems/commit/04973e349c --- lib/rubygems/specification_policy.rb | 4 ++-- test/rubygems/test_gem_specification.rb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/rubygems/specification_policy.rb b/lib/rubygems/specification_policy.rb index 77d58638192dd5..4088fb621ad6e9 100644 --- a/lib/rubygems/specification_policy.rb +++ b/lib/rubygems/specification_policy.rb @@ -497,10 +497,10 @@ def validate_rust_extensions(builder) # :nodoc: def validate_rake_extensions(builder) # :nodoc: rake_extension = @specification.extensions.any? {|s| builder.builder_for(s) == Gem::Ext::RakeBuilder } - rake_dependency = @specification.dependencies.any? {|d| d.name == "rake" } + rake_dependency = @specification.dependencies.any? {|d| d.name == "rake" && d.type == :runtime } warning <<-WARNING if rake_extension && !rake_dependency -You have specified rake based extension, but rake is not added as dependency. It is recommended to add rake as a dependency in gemspec since there's no guarantee rake will be already installed. +You have specified rake based extension, but rake is not added as runtime dependency. It is recommended to add rake as a runtime dependency in gemspec since there's no guarantee rake will be already installed. WARNING end diff --git a/test/rubygems/test_gem_specification.rb b/test/rubygems/test_gem_specification.rb index 5f0546b93da9e9..ca5e8cef3bfe19 100644 --- a/test/rubygems/test_gem_specification.rb +++ b/test/rubygems/test_gem_specification.rb @@ -2727,7 +2727,7 @@ def test_validate_rake_extension_have_rake_dependency_warning @a1.validate end - assert_match(/add rake as a dependency/, @ui.error) + assert_match(/add rake as a runtime dependency/, @ui.error) end end @@ -2743,7 +2743,7 @@ def test_validate_rake_extension_have_rake_dependency_no_warning @a1.validate end - refute_match(/add rake as a dependency/, @ui.error) + refute_match(/add rake as a runtime dependency/, @ui.error) end end From 6bd997ecfded267d968915076606f3ae0888957a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 17 Jan 2024 12:43:35 +0100 Subject: [PATCH 477/640] [rubygems/rubygems] Remove no longer necessary code https://github.com/rubygems/rubygems/commit/b7d2de2ba8 --- lib/rubygems/commands/rdoc_command.rb | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/lib/rubygems/commands/rdoc_command.rb b/lib/rubygems/commands/rdoc_command.rb index b9470411ef82c7..977c90b8c4aafa 100644 --- a/lib/rubygems/commands/rdoc_command.rb +++ b/lib/rubygems/commands/rdoc_command.rb @@ -84,14 +84,7 @@ def execute FileUtils.rm_rf File.join(spec.doc_dir, "rdoc") end - begin - doc.generate - rescue Errno::ENOENT => e - match = e.message.include?(" - ") - alert_error "Unable to document #{spec.full_name}, " \ - " #{match.post_match} is missing, skipping" - terminate_interaction 1 if specs.length == 1 - end + doc.generate end end end From 2f06e4f73998141292ee2a08146af3e63a717dae Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 24 Jan 2024 14:09:58 +0900 Subject: [PATCH 478/640] Revert "Pend tests on Travis CI" This reverts commit 772afa00b5109f55c1d8359c688aca4063818549. --- test/rubygems/test_gem_package.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/rubygems/test_gem_package.rb b/test/rubygems/test_gem_package.rb index f762b24b0bc00d..7adbc695ec2fc2 100644 --- a/test/rubygems/test_gem_package.rb +++ b/test/rubygems/test_gem_package.rb @@ -513,7 +513,6 @@ def test_extract_files_empty def test_extract_file_permissions pend "chmod not supported" if Gem.win_platform? - pend "Travis CI enable writable permission to group" if ENV['TRAVIS'] gem_with_long_permissions = File.expand_path("packages/Bluebie-legs-0.6.2.gem", __dir__) @@ -529,7 +528,6 @@ def test_extract_file_permissions def test_extract_file_umask_global_permissions pend "chmod not supported" if Gem.win_platform? - pend "Travis CI enable writable permission to group" if ENV['TRAVIS'] package = Gem::Package.new @gem From 270ad763594023b87a09027e52deee561ecd3b62 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 24 Jan 2024 14:10:05 +0900 Subject: [PATCH 479/640] Revert "Ensure File.open applies default umask on gem extract" This reverts commit 01f9766aa05182a7bbdc914a5dcd8a36ebade861. --- lib/rubygems/package.rb | 8 +++---- test/rubygems/test_gem.rb | 8 ++----- test/rubygems/test_gem_package.rb | 37 +------------------------------ 3 files changed, 6 insertions(+), 47 deletions(-) diff --git a/lib/rubygems/package.rb b/lib/rubygems/package.rb index 7b4cab79645ec2..387e40ffd753bb 100644 --- a/lib/rubygems/package.rb +++ b/lib/rubygems/package.rb @@ -448,15 +448,13 @@ def extract_tar_gz(io, destination_dir, pattern = "*") # :nodoc: end unless directories.include?(mkdir) - mkdir_mode = 0o755 if dir_mode - mkdir_mode ||= entry.header.mode if entry.directory? - mkdir_mode &= ~File.umask if mkdir_mode - FileUtils.mkdir_p mkdir, mode: mkdir_mode + FileUtils.mkdir_p mkdir, mode: dir_mode ? 0o755 : (entry.header.mode if entry.directory?) directories << mkdir end if entry.file? - File.open(destination, "wb", file_mode(entry.header.mode)) {|out| copy_stream(entry, out) } + File.open(destination, "wb") {|out| copy_stream(entry, out) } + FileUtils.chmod file_mode(entry.header.mode), destination end verbose destination diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 8dc8563aaf649b..d4c307978e7c5d 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -161,17 +161,13 @@ def assert_self_install_permissions(format_executable: false) format_executable: format_executable, } Dir.chdir @tempdir do - # use chmod to set global permissions (so umask doesn't bypass our choice) to ensure they are masked on install Dir.mkdir "bin" - File.chmod 0o777, "bin" Dir.mkdir "data" - File.chmod 0o777, "data" File.write "bin/foo", "#!/usr/bin/env ruby\n" - File.chmod 0o777, "bin/foo" + File.chmod 0o755, "bin/foo" File.write "data/foo.txt", "blah\n" - File.chmod 0o666, "data/foo.txt" spec_fetcher do |f| f.gem "foo", 1 do |s| @@ -184,7 +180,7 @@ def assert_self_install_permissions(format_executable: false) prog_mode = (options[:prog_mode] & mask).to_s(8) dir_mode = (options[:dir_mode] & mask).to_s(8) - data_mode = (options[:data_mode] & mask & (~File.umask)).to_s(8) + data_mode = (options[:data_mode] & mask).to_s(8) prog_name = "foo" prog_name = RbConfig::CONFIG["ruby_install_name"].sub("ruby", "foo") if options[:format_executable] expected = { diff --git a/test/rubygems/test_gem_package.rb b/test/rubygems/test_gem_package.rb index 7adbc695ec2fc2..2065864107715a 100644 --- a/test/rubygems/test_gem_package.rb +++ b/test/rubygems/test_gem_package.rb @@ -523,42 +523,7 @@ def test_extract_file_permissions filepath = File.join @destination, "README.rdoc" assert_path_exist filepath - assert_equal 0o100444.to_s(8), File.stat(filepath).mode.to_s(8) - end - - def test_extract_file_umask_global_permissions - pend "chmod not supported" if Gem.win_platform? - - package = Gem::Package.new @gem - - tgz_io = util_tar_gz do |tar| - tar.mkdir "lib", 0o777 - tar.add_file "bin/global", 0o777 do |io| - io.write "#!/bin/ruby\nputs 'hello world'" - end - tar.add_file "lib/global.rb", 0o666 do |io| - io.write "puts 'hello world'" - end - end - - package.extract_tar_gz tgz_io, @destination - - dirpath = File.join @destination, "lib" - assert_path_exist dirpath - mode = 0o40755 & (~File.umask) - assert_equal mode.to_s(8), File.stat(dirpath).mode.to_s(8) - - filepath = File.join @destination, "lib", "global.rb" - assert_path_exist filepath - assert_equal "puts 'hello world'", File.read(filepath) - mode = 0o100644 & (~File.umask) - assert_equal mode.to_s(8), File.stat(filepath).mode.to_s(8) - - filepath = File.join @destination, "bin", "global" - assert_path_exist filepath - assert_equal "#!/bin/ruby\nputs 'hello world'", File.read(filepath) - mode = 0o100755 & (~File.umask) - assert_equal mode.to_s(8), File.stat(filepath).mode.to_s(8) + assert_equal 0o104444, File.stat(filepath).mode end def test_extract_tar_gz_absolute From c8355a8d1ff99ecd4f6ddd9db9013c365f002cf4 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 24 Jan 2024 15:55:30 +0900 Subject: [PATCH 480/640] syslog is already extracted as bundled gems --- test/test_syslog.rb | 193 -------------------------------------------- 1 file changed, 193 deletions(-) delete mode 100644 test/test_syslog.rb diff --git a/test/test_syslog.rb b/test/test_syslog.rb deleted file mode 100644 index 842ae8df49f917..00000000000000 --- a/test/test_syslog.rb +++ /dev/null @@ -1,193 +0,0 @@ -# frozen_string_literal: false -# Please only run this test on machines reasonable for testing. -# If in doubt, ask your admin. - -require 'test/unit' - -begin - require 'syslog' -rescue LoadError - # suppress error messages. -end - -class TestSyslog < Test::Unit::TestCase - def test_new - assert_raise(NoMethodError) { - Syslog.new - } - end - - def test_instance - sl1 = Syslog.instance - sl2 = Syslog.open - sl3 = Syslog.instance - - assert_equal(Syslog, sl1) - assert_equal(Syslog, sl2) - assert_equal(Syslog, sl3) - ensure - Syslog.close if Syslog.opened? - end - - def test_open - # default parameters - Syslog.open - - assert_equal($0, Syslog.ident) - assert_equal(Syslog::LOG_PID | Syslog::LOG_CONS, Syslog.options) - assert_equal(Syslog::LOG_USER, Syslog.facility) - - # open without close - assert_raise(RuntimeError) { - Syslog.open - } - - Syslog.close - - # given parameters - options = Syslog::LOG_NDELAY | Syslog::LOG_PID - Syslog.open("foo", options, Syslog::LOG_DAEMON) - - assert_equal('foo', Syslog.ident) - assert_equal(options, Syslog.options) - assert_equal(Syslog::LOG_DAEMON, Syslog.facility) - - Syslog.close - - # default parameters again (after close) - Syslog.open - Syslog.close - - assert_equal(nil, Syslog.ident) - assert_equal(nil, Syslog.options) - assert_equal(nil, Syslog.facility) - - # block - param = nil - Syslog.open { |syslog| - param = syslog - } - assert_equal(Syslog, param) - ensure - Syslog.close if Syslog.opened? - end - - def test_opened? - assert_equal(false, Syslog.opened?) - - Syslog.open - assert_equal(true, Syslog.opened?) - - Syslog.close - assert_equal(false, Syslog.opened?) - - Syslog.open { - assert_equal(true, Syslog.opened?) - } - - assert_equal(false, Syslog.opened?) - end - - def test_close - assert_raise(RuntimeError) { - Syslog.close - } - end - - def test_mask - assert_equal(nil, Syslog.mask) - - Syslog.open - - orig = Syslog.mask - - Syslog.mask = Syslog.LOG_UPTO(Syslog::LOG_ERR) - assert_equal(Syslog.LOG_UPTO(Syslog::LOG_ERR), Syslog.mask) - - Syslog.mask = Syslog.LOG_MASK(Syslog::LOG_CRIT) - assert_equal(Syslog.LOG_MASK(Syslog::LOG_CRIT), Syslog.mask) - - Syslog.mask = orig - ensure - Syslog.close if Syslog.opened? - end - - def syslog_line_regex(ident, message) - /(?:^| )#{Regexp.quote(ident)}(?:\[([1-9][0-9]*)\])?(?: | ([1-9][0-9]*) - - ||[: ].* )#{Regexp.quote(message)}$/ - end - - def test_log - IO.pipe {|stderr| - pid = fork { - stderr[0].close - STDERR.reopen(stderr[1]) - stderr[1].close - - options = Syslog::LOG_PERROR | Syslog::LOG_NDELAY - - Syslog.open("syslog_test", options) { |sl| - sl.log(Syslog::LOG_NOTICE, "test1 - hello, %s!", "world") - sl.notice("test1 - hello, %s!", "world") - } - - Syslog.open("syslog_test", options | Syslog::LOG_PID) { |sl| - sl.log(Syslog::LOG_CRIT, "test2 - pid") - sl.crit("test2 - pid") - } - exit! - } - - stderr[1].close - Process.waitpid(pid) - - # LOG_PERROR is not implemented on Cygwin or Solaris. Only test - # these on systems that define it. - return unless Syslog.const_defined?(:LOG_PERROR) - # LOG_PERROR is defined but not supported yet on Android. - return if RUBY_PLATFORM =~ /android/ - - 2.times { - re = syslog_line_regex("syslog_test", "test1 - hello, world!") - line = stderr[0].gets - # In AIX, each LOG_PERROR output line has an appended empty line. - if /aix/ =~ RUBY_PLATFORM && line =~ /^$/ - line = stderr[0].gets - end - m = re.match(line) - assert_not_nil(m) - if m[1] - # pid is written regardless of LOG_PID on OS X 10.7+ - assert_equal(pid, m[1].to_i) - end - } - - 2.times { - re = syslog_line_regex("syslog_test", "test2 - pid") - line = stderr[0].gets - # In AIX, each LOG_PERROR output line has an appended empty line. - if /aix/ =~ RUBY_PLATFORM && line =~ /^$/ - line = stderr[0].gets - end - m = re.match(line) - assert_not_nil(m) - output_pid = m[1] || m[2] - assert_not_nil(output_pid) - assert_equal(pid, output_pid.to_i) - } - } - end - - def test_inspect - Syslog.open { |sl| - assert_equal(format('<#%s: opened=true, ident="%s", options=%d, facility=%d, mask=%d>', - Syslog, - sl.ident, - sl.options, - sl.facility, - sl.mask), - sl.inspect) - } - - assert_equal(format('<#%s: opened=false>', Syslog), Syslog.inspect) - end -end if defined?(Syslog) From 53d0cf442a1dfc1616a3870a65d5c867e0fec2dd Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 24 Jan 2024 17:05:50 +0900 Subject: [PATCH 481/640] Use exit 0 instead of true on windows platform --- test/fiber/test_process.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/fiber/test_process.rb b/test/fiber/test_process.rb index cc1694576eb9cd..a09b070c0a6614 100644 --- a/test/fiber/test_process.rb +++ b/test/fiber/test_process.rb @@ -3,13 +3,15 @@ require_relative 'scheduler' class TestFiberProcess < Test::Unit::TestCase + TRUE_CMD = RUBY_PLATFORM =~ /mswin|mingw/ ? "exit 0" : "true" + def test_process_wait Thread.new do scheduler = Scheduler.new Fiber.set_scheduler scheduler Fiber.schedule do - pid = Process.spawn("true") + pid = Process.spawn(TRUE_CMD) Process.wait(pid) # TODO test that scheduler was invoked. @@ -25,7 +27,7 @@ def test_system Fiber.set_scheduler scheduler Fiber.schedule do - system("true") + system(TRUE_CMD) # TODO test that scheduler was invoked (currently it's not). @@ -49,7 +51,7 @@ def scheduler.process_wait(pid, flags) Fiber.schedule do assert_raise TypeError do - system("true") + system(TRUE_CMD) end end end.join From 1018dca09a55e7b21d701cfee0171b44ba26fe4a Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 23 Jan 2024 19:14:39 +0900 Subject: [PATCH 482/640] [rubygems/rubygems] Skip to load commented out words https://github.com/rubygems/rubygems/commit/e6a9148ba2 --- lib/bundler/yaml_serializer.rb | 1 + lib/rubygems/yaml_serializer.rb | 1 + spec/bundler/bundler/yaml_serializer_spec.rb | 15 +++++++++++++++ spec/bundler/commands/config_spec.rb | 2 +- 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/bundler/yaml_serializer.rb b/lib/bundler/yaml_serializer.rb index 37ccc46c262809..abc931dc67fa07 100644 --- a/lib/bundler/yaml_serializer.rb +++ b/lib/bundler/yaml_serializer.rb @@ -56,6 +56,7 @@ def load(str) last_hash = nil last_empty_key = nil str.split(/\r?\n/) do |line| + line = line.split("#", 2).first.strip if line.include?("#") if match = HASH_REGEX.match(line) indent, key, quote, val = match.captures convert_to_backward_compatible_key!(key) diff --git a/lib/rubygems/yaml_serializer.rb b/lib/rubygems/yaml_serializer.rb index 947fda09114665..7555c83d6bcfd8 100644 --- a/lib/rubygems/yaml_serializer.rb +++ b/lib/rubygems/yaml_serializer.rb @@ -56,6 +56,7 @@ def load(str) last_hash = nil last_empty_key = nil str.split(/\r?\n/) do |line| + line = line.split("#", 2).first.strip if line.include?("#") if match = HASH_REGEX.match(line) indent, key, quote, val = match.captures convert_to_backward_compatible_key!(key) diff --git a/spec/bundler/bundler/yaml_serializer_spec.rb b/spec/bundler/bundler/yaml_serializer_spec.rb index 913b0235b8c32a..0b2c8e167c89fb 100644 --- a/spec/bundler/bundler/yaml_serializer_spec.rb +++ b/spec/bundler/bundler/yaml_serializer_spec.rb @@ -174,6 +174,21 @@ expect(serializer.load(yaml)).to eq(hash) end + + it "skip commented out words" do + yaml = <<~YAML + --- + foo: "bar" + buzz: # "foo" + YAML + + hash = { + "foo" => "bar", + "buzz" => {}, + } + + expect(serializer.load(yaml)).to eq(hash) + end end describe "against yaml lib" do diff --git a/spec/bundler/commands/config_spec.rb b/spec/bundler/commands/config_spec.rb index 547fd2d869432b..c849384ff2994c 100644 --- a/spec/bundler/commands/config_spec.rb +++ b/spec/bundler/commands/config_spec.rb @@ -439,7 +439,7 @@ it "does not make bundler crash and ignores the configuration" do bundle "config list --parseable" - expect(out).to eq("#mirror.https://rails-assets.org/=http://localhost:9292") + expect(out).to be_empty expect(err).to be_empty ruby(<<~RUBY) From 723deec9cf84342332896e48f50b4bf519492652 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 23 Jan 2024 20:19:02 +0900 Subject: [PATCH 483/640] [rubygems/rubygems] Keep compatibility of past versions https://github.com/rubygems/rubygems/commit/54b67fb251 --- lib/bundler/yaml_serializer.rb | 13 ++++++++++++- lib/rubygems/yaml_serializer.rb | 13 ++++++++++++- spec/bundler/bundler/yaml_serializer_spec.rb | 4 ++-- spec/bundler/commands/config_spec.rb | 2 +- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/lib/bundler/yaml_serializer.rb b/lib/bundler/yaml_serializer.rb index abc931dc67fa07..42e6aaf89d33b9 100644 --- a/lib/bundler/yaml_serializer.rb +++ b/lib/bundler/yaml_serializer.rb @@ -56,9 +56,10 @@ def load(str) last_hash = nil last_empty_key = nil str.split(/\r?\n/) do |line| - line = line.split("#", 2).first.strip if line.include?("#") if match = HASH_REGEX.match(line) indent, key, quote, val = match.captures + val = strip_comment(val) + convert_to_backward_compatible_key!(key) depth = indent.size / 2 if quote.empty? && val.empty? @@ -73,6 +74,8 @@ def load(str) end elsif match = ARRAY_REGEX.match(line) _, val = match.captures + val = strip_comment(val) + last_hash[last_empty_key] = [] unless last_hash[last_empty_key].is_a?(Array) last_hash[last_empty_key].push(val) @@ -81,6 +84,14 @@ def load(str) res end + def strip_comment(val) + if val.include?("#") && !val.start_with?("#") + val.split("#", 2).first.strip + else + val + end + end + # for settings' keys def convert_to_backward_compatible_key!(key) key << "/" if /https?:/i.match?(key) && !%r{/\Z}.match?(key) diff --git a/lib/rubygems/yaml_serializer.rb b/lib/rubygems/yaml_serializer.rb index 7555c83d6bcfd8..128becc1ce7fbd 100644 --- a/lib/rubygems/yaml_serializer.rb +++ b/lib/rubygems/yaml_serializer.rb @@ -56,9 +56,10 @@ def load(str) last_hash = nil last_empty_key = nil str.split(/\r?\n/) do |line| - line = line.split("#", 2).first.strip if line.include?("#") if match = HASH_REGEX.match(line) indent, key, quote, val = match.captures + val = strip_comment(val) + convert_to_backward_compatible_key!(key) depth = indent.size / 2 if quote.empty? && val.empty? @@ -73,6 +74,8 @@ def load(str) end elsif match = ARRAY_REGEX.match(line) _, val = match.captures + val = strip_comment(val) + last_hash[last_empty_key] = [] unless last_hash[last_empty_key].is_a?(Array) last_hash[last_empty_key].push(val) @@ -81,6 +84,14 @@ def load(str) res end + def strip_comment(val) + if val.include?("#") && !val.start_with?("#") + val.split("#", 2).first.strip + else + val + end + end + # for settings' keys def convert_to_backward_compatible_key!(key) key << "/" if /https?:/i.match?(key) && !%r{/\Z}.match?(key) diff --git a/spec/bundler/bundler/yaml_serializer_spec.rb b/spec/bundler/bundler/yaml_serializer_spec.rb index 0b2c8e167c89fb..316eaf1ca70a4c 100644 --- a/spec/bundler/bundler/yaml_serializer_spec.rb +++ b/spec/bundler/bundler/yaml_serializer_spec.rb @@ -179,12 +179,12 @@ yaml = <<~YAML --- foo: "bar" - buzz: # "foo" + buzz: "foo" # "bar" YAML hash = { "foo" => "bar", - "buzz" => {}, + "buzz" => "foo", } expect(serializer.load(yaml)).to eq(hash) diff --git a/spec/bundler/commands/config_spec.rb b/spec/bundler/commands/config_spec.rb index c849384ff2994c..547fd2d869432b 100644 --- a/spec/bundler/commands/config_spec.rb +++ b/spec/bundler/commands/config_spec.rb @@ -439,7 +439,7 @@ it "does not make bundler crash and ignores the configuration" do bundle "config list --parseable" - expect(out).to be_empty + expect(out).to eq("#mirror.https://rails-assets.org/=http://localhost:9292") expect(err).to be_empty ruby(<<~RUBY) From 6191f4a1697f2ac4288181f32257f95273ecfbb7 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 23 Jan 2024 22:31:07 +0900 Subject: [PATCH 484/640] [rubygems/rubygems] Simplified test-case for original issue https://github.com/rubygems/rubygems/commit/89086c5458 --- spec/bundler/bundler/yaml_serializer_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/bundler/bundler/yaml_serializer_spec.rb b/spec/bundler/bundler/yaml_serializer_spec.rb index 316eaf1ca70a4c..de437f764ad7b1 100644 --- a/spec/bundler/bundler/yaml_serializer_spec.rb +++ b/spec/bundler/bundler/yaml_serializer_spec.rb @@ -178,8 +178,8 @@ it "skip commented out words" do yaml = <<~YAML --- - foo: "bar" - buzz: "foo" # "bar" + foo: bar + buzz: foo # bar YAML hash = { From fb39128dce7babcb1b8c6d92bfa9e85eb7f7118e Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 24 Jan 2024 10:51:21 +0900 Subject: [PATCH 485/640] [rubygems/rubygems] Added test for rubygems https://github.com/rubygems/rubygems/commit/64405147c9 --- test/rubygems/test_gem_config_file.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/rubygems/test_gem_config_file.rb b/test/rubygems/test_gem_config_file.rb index ad120d2aaa20b3..ae6739db9890f4 100644 --- a/test/rubygems/test_gem_config_file.rb +++ b/test/rubygems/test_gem_config_file.rb @@ -548,4 +548,14 @@ def test_dump_with_rubygems_yaml assert_equal("---\n:foo: \"bar\"\n", actual) end + + def test_handle_comment + yaml = <<~YAML + --- + :foo: bar # buzz + YAML + + actual = Gem::ConfigFile.load_with_rubygems_config_hash(yaml) + assert_equal("bar", actual[:foo]) + end end From 4099b04c099899d92dab3f34f1152038ed718d79 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 24 Jan 2024 17:33:50 +0900 Subject: [PATCH 486/640] Pend make option test on mswin platform --- test/rubygems/test_gem_ext_builder.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/rubygems/test_gem_ext_builder.rb b/test/rubygems/test_gem_ext_builder.rb index 493aaa1b530385..baf61404685540 100644 --- a/test/rubygems/test_gem_ext_builder.rb +++ b/test/rubygems/test_gem_ext_builder.rb @@ -83,6 +83,8 @@ def test_class_make_no_clean end def test_custom_make_with_options + pend "native windows platform only provides nmake" if vc_windows? + ENV["make"] = "make V=1" results = [] File.open File.join(@ext, "Makefile"), "w" do |io| From 0f417d640de16339c85ba8f4bd60e6ac2ce506eb Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 24 Jan 2024 19:33:25 +0900 Subject: [PATCH 487/640] Initialize errno variables and fix maybe-uninitialized warnings --- ext/socket/raddrinfo.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/socket/raddrinfo.c b/ext/socket/raddrinfo.c index cdb785f268fee5..e79bcfa3329532 100644 --- a/ext/socket/raddrinfo.c +++ b/ext/socket/raddrinfo.c @@ -481,7 +481,7 @@ rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hint { int retry; struct getaddrinfo_arg *arg; - int err, gai_errno; + int err, gai_errno = 0; start: retry = 0; @@ -531,7 +531,7 @@ rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hint /* Because errno is threadlocal, the errno value we got from the call to getaddrinfo() in the thread * (in case of EAI_SYSTEM return value) is not propagated to the caller of _this_ function. Set errno * explicitly, as round-tripped through struct getaddrinfo_arg, to deal with that */ - errno = gai_errno; + if (gai_errno) errno = gai_errno; return err; } @@ -700,7 +700,7 @@ rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, { int retry; struct getnameinfo_arg *arg; - int err, gni_errno; + int err, gni_errno = 0; start: retry = 0; @@ -750,7 +750,7 @@ rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, /* Make sure we copy the thread-local errno value from the getnameinfo thread back to this thread, so * calling code sees the correct errno */ - errno = gni_errno; + if (gni_errno) errno = gni_errno; return err; } From d86c4e553ee8ff899a103a49db0b66c73c01135f Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 24 Jan 2024 20:51:50 +0900 Subject: [PATCH 488/640] Define `IO_WITHOUT_GVL` macro --- dir.c | 17 +++++++---------- file.c | 28 ++++++++++------------------ internal/io.h | 3 +++ io.c | 9 ++++----- 4 files changed, 24 insertions(+), 33 deletions(-) diff --git a/dir.c b/dir.c index c972a6ce401da2..01cef9503be793 100644 --- a/dir.c +++ b/dir.c @@ -519,7 +519,7 @@ opendir_without_gvl(const char *path) u.in = path; - return rb_thread_call_without_gvl(nogvl_opendir, u.out, RUBY_UBF_IO, 0); + return IO_WITHOUT_GVL(nogvl_opendir, u.out); } else return opendir(path); @@ -1096,8 +1096,7 @@ chdir_path(VALUE path, bool yield_path) } else { char *p = RSTRING_PTR(path); - int r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_chdir, p, - RUBY_UBF_IO, 0); + int r = IO_WITHOUT_GVL_INT(nogvl_chdir, p); if (r < 0) rb_sys_fail_path(path); } @@ -1309,8 +1308,7 @@ dir_s_fchdir(VALUE klass, VALUE fd_value) return rb_ensure(fchdir_yield, (VALUE)&args, fchdir_restore, (VALUE)&args); } else { - int r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_fchdir, &fd, - RUBY_UBF_IO, 0); + int r = IO_WITHOUT_GVL_INT(nogvl_fchdir, &fd); if (r < 0) rb_sys_fail("fchdir"); } @@ -1506,7 +1504,7 @@ dir_s_mkdir(int argc, VALUE *argv, VALUE obj) path = check_dirname(path); m.path = RSTRING_PTR(path); - r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_mkdir, &m, RUBY_UBF_IO, 0); + r = IO_WITHOUT_GVL_INT(nogvl_mkdir, &m); if (r < 0) rb_sys_fail_path(path); @@ -1539,7 +1537,7 @@ dir_s_rmdir(VALUE obj, VALUE dir) dir = check_dirname(dir); p = RSTRING_PTR(dir); - r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_rmdir, (void *)p, RUBY_UBF_IO, 0); + r = IO_WITHOUT_GVL_INT(nogvl_rmdir, (void *)p); if (r < 0) rb_sys_fail_path(dir); @@ -1758,7 +1756,7 @@ 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 IO_WITHOUT_GVL(nogvl_opendir_at, &oaa); else return nogvl_opendir_at(&oaa); } @@ -3618,8 +3616,7 @@ rb_dir_s_empty_p(VALUE obj, VALUE dirname) } #endif - result = (VALUE)rb_thread_call_without_gvl(nogvl_dir_empty_p, (void *)path, - RUBY_UBF_IO, 0); + result = (VALUE)IO_WITHOUT_GVL(nogvl_dir_empty_p, (void *)path); if (FIXNUM_P(result)) { rb_syserr_fail_path((int)FIX2LONG(result), orig); } diff --git a/file.c b/file.c index 6ca65fb732771a..c2a78cc75df4a2 100644 --- a/file.c +++ b/file.c @@ -468,7 +468,7 @@ apply2files(int (*func)(const char *, void *), int argc, VALUE *argv, void *arg) aa->fn[aa->i].path = path; } - rb_thread_call_without_gvl(no_gvl_apply2files, aa, RUBY_UBF_IO, 0); + IO_WITHOUT_GVL(no_gvl_apply2files, aa); if (aa->errnum) { #ifdef UTIME_EINVAL if (func == utime_internal) { @@ -1168,8 +1168,7 @@ stat_without_gvl(const char *path, struct stat *st) data.file.path = path; data.st = st; - return (int)(VALUE)rb_thread_call_without_gvl(no_gvl_stat, &data, - RUBY_UBF_IO, NULL); + return IO_WITHOUT_GVL_INT(no_gvl_stat, &data); } #if !defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC) && \ @@ -1219,8 +1218,7 @@ statx_without_gvl(const char *path, struct statx *stx, unsigned int mask) no_gvl_statx_data data = {stx, AT_FDCWD, path, 0, mask}; /* call statx(2) with pathname */ - return (int)(VALUE)rb_thread_call_without_gvl(no_gvl_statx, &data, - RUBY_UBF_IO, NULL); + return IO_WITHOUT_GVL_INT(no_gvl_statx, &data); } static int @@ -1382,8 +1380,7 @@ lstat_without_gvl(const char *path, struct stat *st) data.file.path = path; data.st = st; - return (int)(VALUE)rb_thread_call_without_gvl(no_gvl_lstat, &data, - RUBY_UBF_IO, NULL); + return IO_WITHOUT_GVL_INT(no_gvl_lstat, &data); } #endif /* HAVE_LSTAT */ @@ -1557,8 +1554,7 @@ rb_eaccess(VALUE fname, int mode) aa.path = StringValueCStr(fname); aa.mode = mode; - return (int)(VALUE)rb_thread_call_without_gvl(nogvl_eaccess, &aa, - RUBY_UBF_IO, 0); + return IO_WITHOUT_GVL_INT(nogvl_eaccess, &aa); } static void * @@ -1579,8 +1575,7 @@ rb_access(VALUE fname, int mode) aa.path = StringValueCStr(fname); aa.mode = mode; - return (int)(VALUE)rb_thread_call_without_gvl(nogvl_access, &aa, - RUBY_UBF_IO, 0); + return IO_WITHOUT_GVL_INT(nogvl_access, &aa); } /* @@ -3140,8 +3135,7 @@ readlink_without_gvl(VALUE path, VALUE buf, size_t size) ra.buf = RSTRING_PTR(buf); ra.size = size; - return (ssize_t)rb_thread_call_without_gvl(nogvl_readlink, &ra, - RUBY_UBF_IO, 0); + return (ssize_t)IO_WITHOUT_GVL(nogvl_readlink, &ra); } VALUE @@ -3242,8 +3236,7 @@ rb_file_s_rename(VALUE klass, VALUE from, VALUE to) #if defined __CYGWIN__ errno = 0; #endif - if ((int)(VALUE)rb_thread_call_without_gvl(no_gvl_rename, &ra, - RUBY_UBF_IO, 0) < 0) { + if (IO_WITHOUT_GVL_INT(no_gvl_rename, &ra) < 0) { int e = errno; #if defined DOSISH switch (e) { @@ -5128,8 +5121,7 @@ rb_file_s_truncate(VALUE klass, VALUE path, VALUE len) path = rb_str_encode_ospath(path); ta.path = StringValueCStr(path); - r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_truncate, &ta, - RUBY_UBF_IO, NULL); + r = IO_WITHOUT_GVL_INT(nogvl_truncate, &ta); if (r < 0) rb_sys_fail_path(path); return INT2FIX(0); @@ -6201,7 +6193,7 @@ rb_file_s_mkfifo(int argc, VALUE *argv, VALUE _) FilePathValue(path); path = rb_str_encode_ospath(path); ma.path = RSTRING_PTR(path); - if (rb_thread_call_without_gvl(nogvl_mkfifo, &ma, RUBY_UBF_IO, 0)) { + if (IO_WITHOUT_GVL(nogvl_mkfifo, &ma)) { rb_sys_fail_path(path); } return INT2FIX(0); diff --git a/internal/io.h b/internal/io.h index f16d9efc9c4483..1891248a19ee08 100644 --- a/internal/io.h +++ b/internal/io.h @@ -15,6 +15,9 @@ struct rb_io; #include "ruby/io.h" /* for rb_io_t */ +#define IO_WITHOUT_GVL(func, arg) rb_thread_call_without_gvl(func, arg, RUBY_UBF_IO, 0) +#define IO_WITHOUT_GVL_INT(func, arg) (int)(VALUE)IO_WITHOUT_GVL(func, arg) + /** Ruby's IO, metadata and buffers. */ struct rb_io { diff --git a/io.c b/io.c index f8963b504f6063..54952c1a2f6c85 100644 --- a/io.c +++ b/io.c @@ -5429,7 +5429,7 @@ maygvl_close(int fd, int keepgvl) * close() may block for certain file types (NFS, SO_LINGER sockets, * inotify), so let other threads run. */ - return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_close, &fd, RUBY_UBF_IO, 0); + return IO_WITHOUT_GVL_INT(nogvl_close, &fd); } static void* @@ -5446,7 +5446,7 @@ maygvl_fclose(FILE *file, int keepgvl) if (keepgvl) return fclose(file); - return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_fclose, file, RUBY_UBF_IO, 0); + return IO_WITHOUT_GVL_INT(nogvl_fclose, file); } static void free_io_buffer(rb_io_buffer_t *buf); @@ -6967,8 +6967,7 @@ sysopen_func(void *ptr) static inline int rb_sysopen_internal(struct sysopen_struct *data) { - int fd; - fd = (int)(VALUE)rb_thread_call_without_gvl(sysopen_func, data, RUBY_UBF_IO, 0); + int fd = IO_WITHOUT_GVL_INT(sysopen_func, data); if (0 <= fd) rb_update_max_fd(fd); return fd; @@ -13260,7 +13259,7 @@ copy_stream_body(VALUE arg) return copy_stream_fallback(stp); } - rb_thread_call_without_gvl(nogvl_copy_stream_func, (void*)stp, RUBY_UBF_IO, 0); + IO_WITHOUT_GVL(nogvl_copy_stream_func, stp); return Qnil; } From 529700d3145cc77271a70bc75ab91528b7a7b084 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 23 Jan 2024 11:32:35 -0500 Subject: [PATCH 489/640] [PRISM] Nested MultiWriteNode with method calls Fixes ruby/prism#2247. --- prism_compile.c | 5 +++++ test/ruby/test_compile_prism.rb | 15 +++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index df3e0c86593161..654291170dccba 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -3177,7 +3177,9 @@ pm_compile_target_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *cons // // for i, j in []; end // + if (state != NULL) state->position--; pm_compile_multi_target_node(iseq, node, parents, writes, cleanup, src, scope_node, state); + if (state != NULL) state->position++; break; } default: @@ -3270,6 +3272,9 @@ pm_compile_multi_target_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR // Now, we need to go back and modify the topn instructions in order to // ensure they can correctly retrieve the parent expressions. pm_multi_target_state_update(&target_state); + + if (state != NULL) state->stack_size += target_state.stack_size; + return target_state.stack_size; } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 682f50d1d623db..6a30854ba8facc 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -653,6 +653,21 @@ def baz=(c); end foo = Foo.new _, foo.bar, _, foo.baz = 1 CODE + + # Test nested writes with method calls + assert_prism_eval(<<~RUBY) + class Foo + attr_accessor :bar + end + + a = Foo.new + + (a.bar, a.bar), b = [1], 2 + RUBY + assert_prism_eval(<<~RUBY) + h = {} + (h[:foo], h[:bar]), a = [1], 2 + RUBY end ############################################################################ From 767f5d045f76ff07336c1f55608247a2d1a5b45c Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 23 Jan 2024 15:33:45 -0500 Subject: [PATCH 490/640] [PRISM] Use lvar depths for starting --- prism_compile.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 654291170dccba..baa41bc0312b00 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -786,23 +786,27 @@ pm_interpolated_node_compile(pm_node_list_t *parts, rb_iseq_t *iseq, NODE dummy_ static pm_local_index_t pm_lookup_local_index(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm_constant_id_t constant_id, int start_depth) { - pm_local_index_t lindex = {0}; - int level = (start_depth) ? start_depth : 0; + pm_local_index_t lindex = { 0 }; st_data_t local_index; - while(!st_lookup(scope_node->index_lookup_table, constant_id, &local_index)) { + int level; + for (level = 0; level < start_depth; level++) { + scope_node = scope_node->previous; + } + + while (!st_lookup(scope_node->index_lookup_table, constant_id, &local_index)) { level++; if (scope_node->previous) { scope_node = scope_node->previous; } else { // We have recursed up all scope nodes // and have not found the local yet - rb_bug("Local with constant_id %u does not exist", (unsigned int)constant_id); + rb_bug("Local with constant_id %u does not exist", (unsigned int) constant_id); } } lindex.level = level; - lindex.index = scope_node->local_table_for_iseq_size - (int)local_index; + lindex.index = scope_node->local_table_for_iseq_size - (int) local_index; return lindex; } @@ -2991,7 +2995,7 @@ pm_compile_target_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *cons // for i in []; end // pm_local_variable_target_node_t *cast = (pm_local_variable_target_node_t *) node; - pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, cast->name, 0); + pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, cast->name, cast->depth); ADD_SETLOCAL(writes, &dummy_line_node, index.index, index.level); break; @@ -5368,7 +5372,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_local_variable_operator_write_node_t *local_variable_operator_write_node = (pm_local_variable_operator_write_node_t*) node; pm_constant_id_t constant_id = local_variable_operator_write_node->name; - pm_local_index_t local_index = pm_lookup_local_index(iseq, scope_node, constant_id, 0); + pm_local_index_t local_index = pm_lookup_local_index(iseq, scope_node, constant_id, local_variable_operator_write_node->depth); ADD_GETLOCAL(ret, &dummy_line_node, local_index.index, local_index.level); @@ -5394,7 +5398,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, ADD_INSNL(ret, &dummy_line_node, branchunless, set_label); pm_constant_id_t constant_id = local_variable_or_write_node->name; - pm_local_index_t local_index = pm_lookup_local_index(iseq, scope_node, constant_id, 0); + pm_local_index_t local_index = pm_lookup_local_index(iseq, scope_node, constant_id, local_variable_or_write_node->depth); ADD_GETLOCAL(ret, &dummy_line_node, local_index.index, local_index.level); PM_DUP_UNLESS_POPPED; @@ -5417,7 +5421,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_local_variable_read_node_t *local_read_node = (pm_local_variable_read_node_t *) node; if (!popped) { - pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, local_read_node->name, 0); + pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, local_read_node->name, local_read_node->depth); ADD_GETLOCAL(ret, &dummy_line_node, index.index, index.level); } return; @@ -5426,7 +5430,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_local_variable_target_node_t *local_write_node = (pm_local_variable_target_node_t *) node; pm_constant_id_t constant_id = local_write_node->name; - pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, constant_id, 0); + pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, constant_id, local_write_node->depth); ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); return; @@ -5439,7 +5443,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_constant_id_t constant_id = local_write_node->name; - pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, constant_id, 0); + pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, constant_id, local_write_node->depth); ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); return; @@ -5580,7 +5584,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_TARGET_NODE)); pm_local_variable_target_node_t *local_target = (pm_local_variable_target_node_t *) target; - pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, local_target->name, 0); + pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, local_target->name, local_target->depth); ADD_INSN1(ret, &dummy_line_node, putobject, rb_id2sym(pm_constant_id_lookup(scope_node, local_target->name))); ADD_SEND(ret, &dummy_line_node, idAREF, INT2FIX(1)); @@ -5597,7 +5601,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_TARGET_NODE)); pm_local_variable_target_node_t *local_target = (pm_local_variable_target_node_t *) target; - pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, local_target->name, 0); + pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, local_target->name, local_target->depth); if (((size_t) targets_index) < (targets_count - 1)) { PM_DUP; @@ -5620,7 +5624,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_TARGET_NODE)); pm_local_variable_target_node_t *local_target = (pm_local_variable_target_node_t *) target; - pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, local_target->name, 0); + pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, local_target->name, local_target->depth); PM_PUTNIL; ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); From 4220bdba395cff7d4e933b319a186e889ed9b921 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 24 Jan 2024 10:39:40 -0500 Subject: [PATCH 491/640] [PRISM] Remove dead code from prism_compile.c Previously, we were using the main pm_compile_node switch to compile target nodes. Eventually we switched to pm_compile_target_node and updated all the call sites. As such, all of this has become dead code. However, the multi target code was reused for both parameters and multi writes (it was just incorrect for multi writes). So that code has now been moved into its own function that is more specific to destructured parameters (and has more assertions to that effect). Overall now you should not see target nodes when you call into pm_compile_node, since they are more specialized and require more special handling. --- prism_compile.c | 270 +++++++++++++++++++++++------------------------- 1 file changed, 128 insertions(+), 142 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index baa41bc0312b00..17e0cf08a07fcb 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -784,7 +784,7 @@ pm_interpolated_node_compile(pm_node_list_t *parts, rb_iseq_t *iseq, NODE dummy_ // It also takes a pointer to depth, and increments depth appropriately // according to the depth of the local static pm_local_index_t -pm_lookup_local_index(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm_constant_id_t constant_id, int start_depth) +pm_lookup_local_index(rb_iseq_t *iseq, const pm_scope_node_t *scope_node, pm_constant_id_t constant_id, int start_depth) { pm_local_index_t lindex = { 0 }; st_data_t local_index; @@ -2796,61 +2796,130 @@ pm_insert_local_index(pm_constant_id_t constant_id, int local_index, st_table *i st_insert(index_lookup_table, constant_id, local_index); } +/** + * Compile the locals of a multi target node that is used as a positional + * parameter in a method, block, or lambda definition. Note that this doesn't + * actually add any instructions to the iseq. Instead, it adds locals to the + * local and index lookup tables and increments the local index as necessary. + */ static int -pm_compile_multi_assign_params(pm_multi_target_node_t *multi, st_table *index_lookup_table, rb_ast_id_table_t *local_table_for_iseq, pm_scope_node_t *scope_node, int local_index) +pm_compile_destructured_param_locals(const pm_multi_target_node_t *node, st_table *index_lookup_table, rb_ast_id_table_t *local_table_for_iseq, pm_scope_node_t *scope_node, int local_index) { - for (size_t m = 0; m < multi->lefts.size; m++) { - pm_node_t *multi_node = multi->lefts.nodes[m]; + for (size_t index = 0; index < node->lefts.size; index++) { + const pm_node_t *left = node->lefts.nodes[index]; - switch (PM_NODE_TYPE(multi_node)) { - case PM_REQUIRED_PARAMETER_NODE: { - pm_required_parameter_node_t *req = (pm_required_parameter_node_t *)multi_node; - pm_insert_local_index(req->name, local_index, index_lookup_table, local_table_for_iseq, scope_node); + if (PM_NODE_TYPE_P(left, PM_REQUIRED_PARAMETER_NODE)) { + pm_insert_local_index(((const pm_required_parameter_node_t *) left)->name, local_index, index_lookup_table, local_table_for_iseq, scope_node); local_index++; - break; - } - case PM_MULTI_TARGET_NODE: { - local_index = pm_compile_multi_assign_params((pm_multi_target_node_t *)multi_node, index_lookup_table, local_table_for_iseq, scope_node, local_index); - break; - } - default: { - rb_bug("Parameter of type %s within a MultiTargetNode isn't allowed", pm_node_type_to_str(PM_NODE_TYPE(multi_node))); - } + } else { + RUBY_ASSERT(PM_NODE_TYPE_P(left, PM_MULTI_TARGET_NODE)); + local_index = pm_compile_destructured_param_locals((const pm_multi_target_node_t *) left, index_lookup_table, local_table_for_iseq, scope_node, local_index); } } - if (multi->rest && PM_NODE_TYPE_P(multi->rest, PM_SPLAT_NODE)) { - pm_splat_node_t *rest = (pm_splat_node_t *)multi->rest; - if (rest->expression && PM_NODE_TYPE_P(rest->expression, PM_REQUIRED_PARAMETER_NODE)) { - pm_required_parameter_node_t *req = (pm_required_parameter_node_t *)rest->expression; - pm_insert_local_index(req->name, local_index, index_lookup_table, local_table_for_iseq, scope_node); + if (node->rest != NULL && PM_NODE_TYPE_P(node->rest, PM_SPLAT_NODE)) { + const pm_splat_node_t *rest = (const pm_splat_node_t *) node->rest; + + if (rest->expression != NULL) { + RUBY_ASSERT(PM_NODE_TYPE_P(rest->expression, PM_REQUIRED_PARAMETER_NODE)); + pm_insert_local_index(((const pm_required_parameter_node_t *) rest->expression)->name, local_index, index_lookup_table, local_table_for_iseq, scope_node); local_index++; } } - for (size_t m = 0; m < multi->rights.size; m++) { - pm_node_t *multi_node = multi->rights.nodes[m]; + for (size_t index = 0; index < node->rights.size; index++) { + const pm_node_t *right = node->rights.nodes[index]; - switch (PM_NODE_TYPE(multi_node)) { - case PM_REQUIRED_PARAMETER_NODE: { - pm_required_parameter_node_t *req = (pm_required_parameter_node_t *)multi_node; - pm_insert_local_index(req->name, local_index, index_lookup_table, local_table_for_iseq, scope_node); + if (PM_NODE_TYPE_P(right, PM_REQUIRED_PARAMETER_NODE)) { + pm_insert_local_index(((const pm_required_parameter_node_t *) right)->name, local_index, index_lookup_table, local_table_for_iseq, scope_node); local_index++; - break; - } - case PM_MULTI_TARGET_NODE: { - local_index = pm_compile_multi_assign_params((pm_multi_target_node_t *)multi_node, index_lookup_table, local_table_for_iseq, scope_node, local_index); - break; - } - default: { - rb_bug("Parameter of type %s within a MultiTargetNode isn't allowed", pm_node_type_to_str(PM_NODE_TYPE(multi_node))); - } + } else { + RUBY_ASSERT(PM_NODE_TYPE_P(right, PM_MULTI_TARGET_NODE)); + local_index = pm_compile_destructured_param_locals((const pm_multi_target_node_t *) right, index_lookup_table, local_table_for_iseq, scope_node, local_index); } } return local_index; } +/** + * Compile a required parameter node that is part of a destructure that is used + * as a positional parameter in a method, block, or lambda definition. + */ +static inline void +pm_compile_destructured_param_write(rb_iseq_t *iseq, const pm_required_parameter_node_t *node, LINK_ANCHOR *const ret, const pm_scope_node_t *scope_node) +{ + int lineno = (int) pm_newline_list_line_column(&scope_node->parser->newline_list, node->base.location.start).line; + NODE dummy_line_node = generate_dummy_line_node(lineno, lineno); + + pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, node->name, 0); + ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); +} + +/** + * Compile a multi target node that is used as a positional parameter in a + * method, block, or lambda definition. Note that this is effectively the same + * as a multi write, but with the added context that all of the targets + * contained in the write are required parameter nodes. With this context, we + * know they won't have any parent expressions so we build a separate code path + * for this simplified case. + */ +static void +pm_compile_destructured_param_writes(rb_iseq_t *iseq, const pm_multi_target_node_t *node, LINK_ANCHOR *const ret, const pm_scope_node_t *scope_node) +{ + int lineno = (int) pm_newline_list_line_column(&scope_node->parser->newline_list, node->base.location.start).line; + NODE dummy_line_node = generate_dummy_line_node(lineno, lineno); + + bool has_rest = (node->rest && PM_NODE_TYPE_P(node->rest, PM_SPLAT_NODE) && (((pm_splat_node_t *) node->rest)->expression) != NULL); + bool has_rights = node->rights.size > 0; + + int flag = (has_rest || has_rights) ? 1 : 0; + ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(node->lefts.size), INT2FIX(flag)); + + for (size_t index = 0; index < node->lefts.size; index++) { + const pm_node_t *left = node->lefts.nodes[index]; + + if (PM_NODE_TYPE_P(left, PM_REQUIRED_PARAMETER_NODE)) { + pm_compile_destructured_param_write(iseq, (const pm_required_parameter_node_t *) left, ret, scope_node); + } else { + RUBY_ASSERT(PM_NODE_TYPE_P(left, PM_MULTI_TARGET_NODE)); + pm_compile_destructured_param_writes(iseq, (const pm_multi_target_node_t *) left, ret, scope_node); + } + } + + if (has_rest) { + if (has_rights) { + ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(node->rights.size), INT2FIX(3)); + } + + const pm_node_t *rest = ((pm_splat_node_t *) node->rest)->expression; + RUBY_ASSERT(PM_NODE_TYPE_P(rest, PM_REQUIRED_PARAMETER_NODE)); + + pm_compile_destructured_param_write(iseq, (const pm_required_parameter_node_t *) rest, ret, scope_node); + } + + if (has_rights) { + if (!has_rest) { + ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(node->rights.size), INT2FIX(2)); + } + + for (size_t index = 0; index < node->rights.size; index++) { + const pm_node_t *right = node->rights.nodes[index]; + + if (PM_NODE_TYPE_P(right, PM_REQUIRED_PARAMETER_NODE)) { + pm_compile_destructured_param_write(iseq, (const pm_required_parameter_node_t *) right, ret, scope_node); + } else { + RUBY_ASSERT(PM_NODE_TYPE_P(right, PM_MULTI_TARGET_NODE)); + pm_compile_destructured_param_writes(iseq, (const pm_multi_target_node_t *) right, ret, scope_node); + } + } + } +} + +/** + * This is a node in the multi target state linked list. It tracks the + * information for a particular target that necessarily has a parent expression. + */ typedef struct pm_multi_target_state_node { // The pointer to the topn instruction that will need to be modified after // we know the total stack size of all of the targets. @@ -2870,6 +2939,13 @@ typedef struct pm_multi_target_state_node { struct pm_multi_target_state_node *next; } pm_multi_target_state_node_t; +/** + * As we're compiling a multi target, we need to track additional information + * whenever there is a parent expression on the left hand side of the target. + * This is because we need to go back and tell the expression where to fetch its + * parent expression from the stack. We use a linked list of nodes to track this + * information. + */ typedef struct { // The total number of slots in the stack that this multi target occupies. size_t stack_size; @@ -4256,12 +4332,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } return; } - case PM_CLASS_VARIABLE_TARGET_NODE: { - pm_class_variable_target_node_t *write_node = (pm_class_variable_target_node_t *) node; - ID cvar_name = pm_constant_id_lookup(scope_node, write_node->name); - ADD_INSN2(ret, &dummy_line_node, setclassvariable, ID2SYM(cvar_name), get_cvar_ic_value(iseq, cvar_name)); - return; - } case PM_CLASS_VARIABLE_WRITE_NODE: { pm_class_variable_write_node_t *write_node = (pm_class_variable_write_node_t *) node; PM_COMPILE_NOT_POPPED(write_node->value); @@ -4535,12 +4605,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, return; } - case PM_CONSTANT_TARGET_NODE: { - pm_constant_target_node_t *constant_write_node = (pm_constant_target_node_t *) node; - ADD_INSN1(ret, &dummy_line_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE)); - ADD_INSN1(ret, &dummy_line_node, setconstant, ID2SYM(pm_constant_id_lookup(scope_node, constant_write_node->name))); - return; - } case PM_CONSTANT_WRITE_NODE: { pm_constant_write_node_t *constant_write_node = (pm_constant_write_node_t *) node; PM_COMPILE_NOT_POPPED(constant_write_node->value); @@ -4909,13 +4973,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, PM_POP_IF_POPPED; return; } - case PM_GLOBAL_VARIABLE_TARGET_NODE: { - pm_global_variable_target_node_t *write_node = (pm_global_variable_target_node_t *) node; - - ID ivar_name = pm_constant_id_lookup(scope_node, write_node->name); - ADD_INSN1(ret, &dummy_line_node, setglobal, ID2SYM(ivar_name)); - return; - } case PM_GLOBAL_VARIABLE_WRITE_NODE: { pm_global_variable_write_node_t *write_node = (pm_global_variable_write_node_t *) node; PM_COMPILE_NOT_POPPED(write_node->value); @@ -5096,33 +5153,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, return; } - case PM_INDEX_TARGET_NODE: { - // Index targets can be used to indirectly call a method in places like - // rescue references, for loops, and multiple assignment. In those - // circumstances, it's necessary to first compile the receiver and - // arguments, then to compile the method call itself. - // - // Therefore in the main switch case here where we're compiling a index - // target, we're only going to compile the receiver and arguments. Then - // wherever we've called into pm_compile_node when we're compiling index - // targets, we'll need to make sure we compile the method call as well. - // - // Note that index target nodes can have blocks attached to them in the - // form of the & operator. These blocks should almost always be compiled - // _after_ the value that is being written is added to the argument - // list, so we don't compile them here. Therefore at the places where - // these nodes are handled, blocks also need to be handled. - pm_index_target_node_t *cast = (pm_index_target_node_t*) node; - PM_COMPILE_NOT_POPPED(cast->receiver); - - if (cast->arguments != NULL) { - int flags; - struct rb_callinfo_kwarg *keywords = NULL; - pm_setup_args(cast->arguments, &flags, &keywords, iseq, ret, src, false, scope_node, dummy_line_node, parser); - } - - return; - } case PM_INSTANCE_VARIABLE_AND_WRITE_NODE: { pm_instance_variable_and_write_node_t *instance_variable_and_write_node = (pm_instance_variable_and_write_node_t*) node; @@ -5198,13 +5228,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } return; } - case PM_INSTANCE_VARIABLE_TARGET_NODE: { - pm_instance_variable_target_node_t *write_node = (pm_instance_variable_target_node_t *) node; - - ID ivar_name = pm_constant_id_lookup(scope_node, write_node->name); - ADD_INSN2(ret, &dummy_line_node, setinstancevariable, ID2SYM(ivar_name), get_ivar_ic_value(iseq, ivar_name)); - return; - } case PM_INSTANCE_VARIABLE_WRITE_NODE: { pm_instance_variable_write_node_t *write_node = (pm_instance_variable_write_node_t *) node; PM_COMPILE_NOT_POPPED(write_node->value); @@ -5426,15 +5449,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } return; } - case PM_LOCAL_VARIABLE_TARGET_NODE: { - pm_local_variable_target_node_t *local_write_node = (pm_local_variable_target_node_t *) node; - - pm_constant_id_t constant_id = local_write_node->name; - pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, constant_id, local_write_node->depth); - - ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); - return; - } case PM_LOCAL_VARIABLE_WRITE_NODE: { pm_local_variable_write_node_t *local_write_node = (pm_local_variable_write_node_t *) node; PM_COMPILE_NOT_POPPED(local_write_node->value); @@ -5667,36 +5681,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, ADD_SETLOCAL(ret, &dummy_line_node, index.index, index.level); return; } - case PM_MULTI_TARGET_NODE: { - pm_multi_target_node_t *cast = (pm_multi_target_node_t *) node; - bool has_rest_expression = (cast->rest && - PM_NODE_TYPE_P(cast->rest, PM_SPLAT_NODE) && - (((pm_splat_node_t *)cast->rest)->expression)); - - int flag = (int) (bool) cast->rights.size || has_rest_expression; - ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(cast->lefts.size), INT2FIX(flag)); - for (size_t index = 0; index < cast->lefts.size; index++) { - PM_COMPILE_NOT_POPPED(cast->lefts.nodes[index]); - } - - if (has_rest_expression) { - if (cast->rights.size) { - ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(cast->rights.size), INT2FIX(3)); - } - pm_node_t *expression = ((pm_splat_node_t *)cast->rest)->expression; - PM_COMPILE_NOT_POPPED(expression); - } - - if (cast->rights.size) { - if (!has_rest_expression) { - ADD_INSN2(ret, &dummy_line_node, expandarray, INT2FIX(cast->rights.size), INT2FIX(2)); - } - for (size_t index = 0; index < cast->rights.size; index++) { - PM_COMPILE_NOT_POPPED(cast->rights.nodes[index]); - } - } - return; - } case PM_MULTI_WRITE_NODE: { // A multi write node represents writing to multiple values using an = // operator. Importantly these nodes are only parsed when the left-hand @@ -6674,7 +6658,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // We want to account for this in our table size pm_node_t *required = requireds_list->nodes[i]; if (PM_NODE_TYPE_P(required, PM_MULTI_TARGET_NODE)) { - local_index = pm_compile_multi_assign_params((pm_multi_target_node_t *)required, index_lookup_table, local_table_for_iseq, scope_node, local_index); + local_index = pm_compile_destructured_param_locals((pm_multi_target_node_t *)required, index_lookup_table, local_table_for_iseq, scope_node, local_index); } } } @@ -6687,7 +6671,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // We want to account for this in our table size pm_node_t *post= posts_list->nodes[i]; if (PM_NODE_TYPE_P(post, PM_MULTI_TARGET_NODE)) { - local_index = pm_compile_multi_assign_params((pm_multi_target_node_t *)post, index_lookup_table, local_table_for_iseq, scope_node, local_index); + local_index = pm_compile_destructured_param_locals((pm_multi_target_node_t *)post, index_lookup_table, local_table_for_iseq, scope_node, local_index); } } } @@ -6843,26 +6827,28 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, if (requireds_list && requireds_list->size) { for (size_t i = 0; i < requireds_list->size; i++) { - // For each MultiTargetNode, we're going to have one - // additional anonymous local not represented in the locals table - // We want to account for this in our table size - pm_node_t *required = requireds_list->nodes[i]; + // For each MultiTargetNode, we're going to have one additional + // anonymous local not represented in the locals table. We want + // to account for this in our table size. + const pm_node_t *required = requireds_list->nodes[i]; + if (PM_NODE_TYPE_P(required, PM_MULTI_TARGET_NODE)) { - ADD_GETLOCAL(ret, &dummy_line_node, table_size - required_multis_hidden_index - (int)i, 0); - PM_COMPILE(required); + ADD_GETLOCAL(ret, &dummy_line_node, table_size - required_multis_hidden_index - (int) i, 0); + pm_compile_destructured_param_writes(iseq, (const pm_multi_target_node_t *) required, ret, scope_node); } } } if (posts_list && posts_list->size) { for (size_t i = 0; i < posts_list->size; i++) { - // For each MultiTargetNode, we're going to have one - // additional anonymous local not represented in the locals table - // We want to account for this in our table size - pm_node_t *post = posts_list->nodes[i]; + // For each MultiTargetNode, we're going to have one additional + // anonymous local not represented in the locals table. We want + // to account for this in our table size. + const pm_node_t *post = posts_list->nodes[i]; + if (PM_NODE_TYPE_P(post, PM_MULTI_TARGET_NODE)) { ADD_GETLOCAL(ret, &dummy_line_node, table_size - post_multis_hidden_index, 0); - PM_COMPILE(post); + pm_compile_destructured_param_writes(iseq, (const pm_multi_target_node_t *) post, ret, scope_node); } } } From 927928badb1a53aae6b29e65627720d7cb6cfdd7 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Wed, 24 Jan 2024 10:22:46 -0500 Subject: [PATCH 492/640] [PRISM] Fix anonymous keyword arguments Fixes ruby/prism#2256. --- prism_compile.c | 12 ++++++++++-- test/ruby/test_compile_prism.rb | 8 ++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 17e0cf08a07fcb..d8da5caaa1f991 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -60,6 +60,7 @@ #define PM_SPECIAL_CONSTANT_FLAG ((pm_constant_id_t)(1 << 31)) #define PM_CONSTANT_AND ((pm_constant_id_t)(idAnd | PM_SPECIAL_CONSTANT_FLAG)) #define PM_CONSTANT_MULT ((pm_constant_id_t)(idMULT | PM_SPECIAL_CONSTANT_FLAG)) +#define PM_CONSTANT_POW ((pm_constant_id_t)(idPow | PM_SPECIAL_CONSTANT_FLAG)) rb_iseq_t * pm_iseq_new_with_opt(pm_scope_node_t *scope_node, pm_parser_t *parser, VALUE name, VALUE path, VALUE realpath, @@ -1025,7 +1026,13 @@ pm_arg_compile_keyword_hash_node(pm_keyword_hash_node_t *node, rb_iseq_t *iseq, } pm_assoc_splat_node_t *assoc_splat = (pm_assoc_splat_node_t *)cur_node; - PM_COMPILE(assoc_splat->value); + if (assoc_splat->value != NULL) { + PM_COMPILE(assoc_splat->value); + } + else { + pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_POW, 0); + ADD_GETLOCAL(ret, &dummy_line_node, index.index, index.level); + } if (len > 1) { ADD_SEND(ret, &dummy_line_node, id_core_hash_merge_kwd, INT2FIX(2)); @@ -6589,7 +6596,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_insert_local_index(constant_id, local_index, index_lookup_table, local_table_for_iseq, scope_node); } else { - local_table_for_iseq->ids[local_index] = idPow; + local_table_for_iseq->ids[local_index] = PM_CONSTANT_POW; + st_insert(index_lookup_table, PM_CONSTANT_POW, local_index); } local_index++; break; diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 6a30854ba8facc..5425f2c730c796 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -825,6 +825,14 @@ def test_AssocSplatNode assert_prism_eval("foo = { a: 1 }; { **foo }") assert_prism_eval("foo = { a: 1 }; bar = foo; { **foo, b: 2, **bar, c: 3 }") assert_prism_eval("foo = { a: 1 }; { b: 2, **foo, c: 3}") + + # Test anonymous AssocSplatNode + assert_prism_eval(<<~RUBY) + o = Object.new + def o.bar(**) = Hash(**) + + o.bar(hello: "world") + RUBY end def test_HashNode From 7a33a1aee2739598fc5b17cfd6f31e20769fee28 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 23 Jan 2024 12:11:21 -0800 Subject: [PATCH 493/640] Insert all locals in the locals index table Prism provides an index (local_body_index) which is supposed to point at the start of locals declared in the method body. Prism assumed that method body locals would only occur _after_ parameter names. Unfortunately this assumption is not correct, which meant that we would in some cases not insert all locals in the local table. This commit iterates over locals a second time, inserting any that didn't get inserted on the first pass. Fixes: https://github.com/ruby/prism/issues/2245 Co-Authored-By: Matt Valentine-House --- prism_compile.c | 59 +++++++++++++++++++++------------ test/ruby/test_compile_prism.rb | 4 +++ 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index d8da5caaa1f991..5339d0ec9834f1 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2793,6 +2793,34 @@ pm_add_ensure_iseq(LINK_ANCHOR *const ret, rb_iseq_t *iseq, int is_return, const ADD_SEQ(ret, ensure); } +struct pm_local_table_insert_ctx { + pm_scope_node_t *scope_node; + rb_ast_id_table_t *local_table_for_iseq; + int local_index; +}; + +static int +pm_local_table_insert_func(st_data_t *key, st_data_t *value, st_data_t arg, int existing) +{ + if (!existing) { + pm_constant_id_t constant_id = *(pm_constant_id_t *)key; + struct pm_local_table_insert_ctx * ctx = (struct pm_local_table_insert_ctx *)arg; + + pm_scope_node_t *scope_node = ctx->scope_node; + rb_ast_id_table_t *local_table_for_iseq = ctx->local_table_for_iseq; + int local_index = ctx->local_index; + + ID local = pm_constant_id_lookup(scope_node, constant_id); + local_table_for_iseq->ids[local_index] = local; + + *value = local_index; + + ctx->local_index++; + } + + return ST_CONTINUE; +} + static void pm_insert_local_index(pm_constant_id_t constant_id, int local_index, st_table *index_lookup_table, rb_ast_id_table_t *local_table_for_iseq, pm_scope_node_t *scope_node) { @@ -6711,31 +6739,18 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, //********STEP 4********** // Goal: fill in the method body locals // To be explicit, these are the non-parameter locals - uint32_t locals_body_index = 0; - - switch (PM_NODE_TYPE(scope_node->ast_node)) { - case PM_BLOCK_NODE: { - locals_body_index = ((pm_block_node_t *)scope_node->ast_node)->locals_body_index; - break; - } - case PM_DEF_NODE: { - locals_body_index = ((pm_def_node_t *)scope_node->ast_node)->locals_body_index; - break; - } - case PM_LAMBDA_NODE: { - locals_body_index = ((pm_lambda_node_t *)scope_node->ast_node)->locals_body_index; - break; - } - default: { - } - } - if (scope_node->locals.size) { - for (size_t i = locals_body_index; i < scope_node->locals.size; i++) { + for (size_t i = 0; i < scope_node->locals.size; i++) { pm_constant_id_t constant_id = locals->ids[i]; if (constant_id) { - pm_insert_local_index(constant_id, local_index, index_lookup_table, local_table_for_iseq, scope_node); - local_index++; + struct pm_local_table_insert_ctx ctx; + ctx.scope_node = scope_node; + ctx.local_table_for_iseq = local_table_for_iseq; + ctx.local_index = local_index; + + st_update(index_lookup_table, constant_id, pm_local_table_insert_func, (st_data_t)&ctx); + + local_index = ctx.local_index; } } } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 5425f2c730c796..f2a01c96840050 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1545,6 +1545,10 @@ def self.prism_test_def_node(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, CODE end + def test_locals_in_parameters + assert_prism_eval("def self.m(a = b = c = 1); [a, b, c]; end; self.m") + end + def test_trailing_comma_on_block assert_prism_eval("def self.m; yield [:ok]; end; m {|v0,| v0 }") end From 578ff32611a88920f60b162d1fe2e0d48ed20450 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 23 Jan 2024 16:48:28 -0800 Subject: [PATCH 494/640] Move filling in the rest of the locals to the end --- prism_compile.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 5339d0ec9834f1..90c70849fb9506 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -6739,6 +6739,17 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, //********STEP 4********** // Goal: fill in the method body locals // To be explicit, these are the non-parameter locals + // We fill in the block_locals, if they exist + // lambda { |x; y| y } + // ^ + if (block_locals && block_locals->size) { + for (size_t i = 0; i < block_locals->size; i++, local_index++) { + pm_constant_id_t constant_id = ((pm_block_local_variable_node_t *)block_locals->nodes[i])->name; + pm_insert_local_index(constant_id, local_index, index_lookup_table, local_table_for_iseq, scope_node); + } + } + + // Fill in any locals we missed if (scope_node->locals.size) { for (size_t i = 0; i < scope_node->locals.size; i++) { pm_constant_id_t constant_id = locals->ids[i]; @@ -6755,16 +6766,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } } - // We fill in the block_locals, if they exist - // lambda { |x; y| y } - // ^ - if (block_locals && block_locals->size) { - for (size_t i = 0; i < block_locals->size; i++, local_index++) { - pm_constant_id_t constant_id = ((pm_block_local_variable_node_t *)block_locals->nodes[i])->name; - pm_insert_local_index(constant_id, local_index, index_lookup_table, local_table_for_iseq, scope_node); - } - } - //********END OF STEP 4********** // We set the index_lookup_table on the scope node so we can @@ -6781,7 +6782,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // Goal: compile anything that needed to be compiled if (keywords_list && keywords_list->size) { size_t optional_index = 0; - for (size_t i = 0; i < keywords_list->size; i++, local_index++) { + for (size_t i = 0; i < keywords_list->size; i++) { pm_node_t *keyword_parameter_node = keywords_list->nodes[i]; pm_constant_id_t name; @@ -6832,7 +6833,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // a pointer to the label it should fill out? We already // have a list of labels allocated above so it seems wasteful // to do the copies. - for (size_t i = 0; i < optionals_list->size; i++, local_index++) { + for (size_t i = 0; i < optionals_list->size; i++) { label = NEW_LABEL(lineno); opt_table[i] = label; ADD_LABEL(ret, label); From 23d46829264e21ec542c099d61922efa58cac916 Mon Sep 17 00:00:00 2001 From: Maxime Chevalier-Boisvert Date: Wed, 24 Jan 2024 13:09:08 -0500 Subject: [PATCH 495/640] YJIT: fix small bug causing jit_rb_int_rshift to side-exit (#9684) YJIT: fix bug causing jit_rb_int_rshift to side-exit The nqueens benchmark was showing zero performance improvement because we immediately side-exited as soon as the shift amount changed. If the amount changes, we want to fall back to the C function call, not side-exit. --- yjit/src/codegen.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 0f9e15b513b57b..576a9888797853 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -4712,6 +4712,8 @@ fn jit_rb_int_lshift( } // Fallback to a C call if the shift amount varies + // This check is needed because the chain guard will side-exit + // if its max depth is reached if asm.ctx.get_chain_depth() > 0 { return false; } @@ -4771,7 +4773,9 @@ fn jit_rb_int_rshift( } // Fallback to a C call if the shift amount varies - if asm.ctx.get_chain_depth() > 1 { + // This check is needed because the chain guard will side-exit + // if its max depth is reached + if asm.ctx.get_chain_depth() > 0 { return false; } From 6b9317c9d566329cc87969c722ed221283ddc8f7 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Wed, 24 Jan 2024 12:19:40 -0500 Subject: [PATCH 496/640] [PRISM] Don't skip test_ForwardingArgumentsNode It seems to work with RUBY_ISEQ_DUMP_DEBUG=to_binary so we can try this test again on CI. --- test/ruby/test_compile_prism.rb | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index f2a01c96840050..bcbd5449e018a1 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -2011,31 +2011,6 @@ def PrismTestSubclass.test_call_operator_write_node=(val) end def test_ForwardingArgumentsNode - # http://ci.rvm.jp/results/trunk-iseq_binary@ruby-sp2-docker/4779277 - # - # expected: - # == disasm: #:2 (2,8)-(4,11)> - # local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: 1]) - # [ 1] "..."@0 - # 0000 putself ( 3) - # 0001 getlocal_WC_0 ?@-2 - # 0003 splatarray false - # 0005 getblockparamproxy ?@-1, 0 - # 0008 send , nil - # 0011 leave ( 2) - # actual: - # == disasm: #:2 (2,8)-(4,11)> - # local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: 1]) - # [ 1] "..."@0 - # 0000 putself ( 3) - # 0001 getlocal_WC_0 ?@-2 - # 0003 splatarray false - # 0005 getblockparamproxy "!"@-1, 0 - # 0008 send , nil - # 0011 leave ( 2) - - omit "fails on trunk-iseq_binary" - assert_prism_eval(<<-CODE) def prism_test_forwarding_arguments_node(...); end; def prism_test_forwarding_arguments_node1(...) From 1702528258c2b2a87dcf5673a80d999de35d0b71 Mon Sep 17 00:00:00 2001 From: Maxime Chevalier-Boisvert Date: Wed, 24 Jan 2024 13:14:36 -0500 Subject: [PATCH 497/640] YJIT: reduce default exec mem size to 48MiB (#9685) YJIT: reduce default exec mem size to 48MiB based Based on user feedback from @jhawthorn and others. Better for small and memory-constrained deployments. NOTE: This commit should be included in the next Ruby 3.3.x point release. @xrxr should we tag someone specific? --- doc/yjit/yjit.md | 2 +- yjit/src/options.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/yjit/yjit.md b/doc/yjit/yjit.md index ba6772727fe64f..02f8dd794888b2 100644 --- a/doc/yjit/yjit.md +++ b/doc/yjit/yjit.md @@ -165,7 +165,7 @@ The machine code generated for a given method can be printed by adding `puts Rub YJIT supports all command-line options supported by upstream CRuby, but also adds a few YJIT-specific options: - `--yjit`: enable YJIT (disabled by default) -- `--yjit-exec-mem-size=N`: size of the executable memory block to allocate, in MiB (default 64 MiB) +- `--yjit-exec-mem-size=N`: size of the executable memory block to allocate, in MiB (default 48 MiB) - `--yjit-call-threshold=N`: number of calls after which YJIT begins to compile a function. It defaults to 30, and it's then increased to 120 when the number of ISEQs in the process reaches 40,000. - `--yjit-cold-threshold=N`: number of global calls after which an ISEQ is considered cold and not diff --git a/yjit/src/options.rs b/yjit/src/options.rs index 72db51303099aa..5a60bc8f4990c5 100644 --- a/yjit/src/options.rs +++ b/yjit/src/options.rs @@ -81,7 +81,7 @@ pub struct Options { // Initialize the options to default values pub static mut OPTIONS: Options = Options { - exec_mem_size: 64 * 1024 * 1024, + exec_mem_size: 48 * 1024 * 1024, no_type_prop: false, max_versions: 4, num_temp_regs: 5, @@ -101,7 +101,7 @@ pub static mut OPTIONS: Options = Options { /// YJIT option descriptions for `ruby --help`. static YJIT_OPTIONS: [(&str, &str); 9] = [ - ("--yjit-exec-mem-size=num", "Size of executable memory block in MiB (default: 64)"), + ("--yjit-exec-mem-size=num", "Size of executable memory block in MiB (default: 48)"), ("--yjit-call-threshold=num", "Number of calls to trigger JIT"), ("--yjit-cold-threshold=num", "Global calls after which ISEQs not compiled (default: 200K)"), ("--yjit-stats", "Enable collecting YJIT statistics"), From 303fef875240b19fc582ab80897f5e15df784eca Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Wed, 24 Jan 2024 10:26:57 -0800 Subject: [PATCH 498/640] YJIT: Update yjit.md about mem size (#9687) --- doc/yjit/yjit.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/yjit/yjit.md b/doc/yjit/yjit.md index 02f8dd794888b2..e6446e3ed1b66b 100644 --- a/doc/yjit/yjit.md +++ b/doc/yjit/yjit.md @@ -243,8 +243,8 @@ which often consumes more memory than JIT code. Generally, YJIT adds memory over 3-4x of `--yjit-exec-mem-size` in production as of Ruby 3.3. You should multiply that by the number of worker processes to estimate the worst case memory overhead. -We use `--yjit-exec-mem-size=64` for Shopify's Rails monolith, which is Ruby 3.3's default, -but smaller values like 32 MiB or 48 MiB might make sense for your application. +`--yjit-exec-mem-size=48` is the default since Ruby 3.3.1, +but smaller values like 32 MiB might make sense for your application. While doing so, you may want to monitor `RubyVM::YJIT.runtime_stats[:ratio_in_yjit]` as explained above. ### Enabling YJIT lazily From 455fb320384a597bc195adcee6bc1071fc64a245 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 24 Jan 2024 12:11:45 -0500 Subject: [PATCH 499/640] [ruby/prism] Add an implicit node for the target of a hash pattern This simplifies compiling it, since you can now compile the value as if it were always there. https://github.com/ruby/prism/commit/bcfc74aacb --- prism/config.yml | 7 +- prism/prism.c | 124 ++++++++++-------- test/prism/snapshots/patterns.txt | 7 +- test/prism/snapshots/seattlerb/case_in.txt | 14 +- .../seattlerb/case_in_hash_pat_assign.txt | 7 +- .../snapshots/seattlerb/parse_pattern_058.txt | 7 +- .../seattlerb/parse_pattern_058_2.txt | 7 +- .../unparser/corpus/literal/pattern.txt | 7 +- .../whitequark/multiple_pattern_matches.txt | 28 +++- .../whitequark/newline_in_hash_argument.txt | 14 +- ...e_line_allowed_omission_of_parentheses.txt | 14 +- 11 files changed, 165 insertions(+), 71 deletions(-) diff --git a/prism/config.yml b/prism/config.yml index 35a3f29ef450bb..2a4c2cd9517ce6 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -580,9 +580,9 @@ nodes: { def a; end => 1 } ^^^^^^^^^^ - name: value - type: node? + type: node comment: | - The value of the association, if present. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). It can be optionally omitted if this node is an element in a `HashPatternNode`. + The value of the association, if present. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). { foo => bar } ^^^ @@ -1634,6 +1634,9 @@ nodes: { Foo: } ^^^^ + + foo in { bar: } + ^^^^ - name: ImplicitRestNode comment: | Represents using a trailing comma to indicate an implicit rest parameter. diff --git a/prism/prism.c b/prism/prism.c index 6b534175236e68..19cd1e6d649114 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -1344,7 +1344,7 @@ pm_assoc_node_create(pm_parser_t *parser, pm_node_t *key, const pm_token_t *oper pm_assoc_node_t *node = PM_ALLOC_NODE(parser, pm_assoc_node_t); const uint8_t *end; - if (value != NULL) { + if (value != NULL && value->location.end > key->location.end) { end = value->location.end; } else if (operator->type != PM_TOKEN_NOT_PROVIDED) { end = operator->end; @@ -13332,43 +13332,77 @@ parse_pattern_keyword_rest(pm_parser_t *parser) { return (pm_node_t *) pm_assoc_splat_node_create(parser, value, &operator); } +/** + * Create an implicit node for the value of a hash pattern that has omitted the + * value. This will use an implicit local variable target. + */ +static pm_node_t * +parse_pattern_hash_implicit_value(pm_parser_t *parser, pm_symbol_node_t *key) { + const pm_location_t *value_loc = &((pm_symbol_node_t *) key)->value_loc; + pm_constant_id_t name = pm_parser_constant_id_location(parser, value_loc->start, value_loc->end); + + int current_depth = pm_parser_local_depth_constant_id(parser, name); + uint32_t depth; + + if (current_depth == -1) { + pm_parser_local_add_location(parser, value_loc->start, value_loc->end); + depth = 0; + } else { + depth = (uint32_t) current_depth; + } + + pm_local_variable_target_node_t *target = pm_local_variable_target_node_create_values(parser, value_loc, name, depth); + return (pm_node_t *) pm_implicit_node_create(parser, (pm_node_t *) target); +} + /** * Parse a hash pattern. */ static pm_hash_pattern_node_t * -parse_pattern_hash(pm_parser_t *parser, pm_node_t *first_assoc) { +parse_pattern_hash(pm_parser_t *parser, pm_node_t *first_node) { pm_node_list_t assocs = { 0 }; pm_node_t *rest = NULL; - switch (PM_NODE_TYPE(first_assoc)) { - case PM_ASSOC_NODE: { - if (!match7(parser, PM_TOKEN_COMMA, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)) { - // Here we have a value for the first assoc in the list, so we will - // parse it now and update the first assoc. - pm_node_t *value = parse_pattern(parser, false, PM_ERR_PATTERN_EXPRESSION_AFTER_KEY); + switch (PM_NODE_TYPE(first_node)) { + case PM_ASSOC_SPLAT_NODE: + case PM_NO_KEYWORDS_PARAMETER_NODE: + rest = first_node; + break; + case PM_SYMBOL_NODE: { + if (pm_symbol_node_label_p(first_node)) { + pm_node_t *value; + + if (!match7(parser, PM_TOKEN_COMMA, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)) { + // Here we have a value for the first assoc in the list, so + // we will parse it now. + value = parse_pattern(parser, false, PM_ERR_PATTERN_EXPRESSION_AFTER_KEY); + } else { + // Otherwise, we will create an implicit local variable + // target for the value. + value = parse_pattern_hash_implicit_value(parser, (pm_symbol_node_t *) first_node); + } - pm_assoc_node_t *assoc = (pm_assoc_node_t *) first_assoc; - assoc->base.location.end = value->location.end; - assoc->value = value; - } else { - pm_node_t *key = ((pm_assoc_node_t *) first_assoc)->key; + pm_token_t operator = not_provided(parser); + pm_node_t *assoc = (pm_node_t *) pm_assoc_node_create(parser, first_node, &operator, value); - if (PM_NODE_TYPE_P(key, PM_SYMBOL_NODE)) { - const pm_location_t *value_loc = &((pm_symbol_node_t *) key)->value_loc; - pm_parser_local_add_location(parser, value_loc->start, value_loc->end); - } + pm_node_list_append(&assocs, assoc); + break; } + } + /* fallthrough */ + default: { + // If we get anything else, then this is an error. For this we'll + // create a missing node for the value and create an assoc node for + // the first node in the list. + pm_parser_err_node(parser, first_node, PM_ERR_PATTERN_HASH_KEY_LABEL); - pm_node_list_append(&assocs, first_assoc); + pm_token_t operator = not_provided(parser); + pm_node_t *value = (pm_node_t *) pm_missing_node_create(parser, first_node->location.start, first_node->location.end); + pm_node_t *assoc = (pm_node_t *) pm_assoc_node_create(parser, first_node, &operator, value); + + pm_node_list_append(&assocs, assoc); break; } - case PM_ASSOC_SPLAT_NODE: - case PM_NO_KEYWORDS_PARAMETER_NODE: - rest = first_assoc; - break; - default: - assert(false); - break; } // If there are any other assocs, then we'll parse them now. @@ -13397,6 +13431,7 @@ parse_pattern_hash(pm_parser_t *parser, pm_node_t *first_assoc) { } else { const pm_location_t *value_loc = &((pm_symbol_node_t *) key)->value_loc; pm_parser_local_add_location(parser, value_loc->start, value_loc->end); + value = parse_pattern_hash_implicit_value(parser, (pm_symbol_node_t *) key); } pm_token_t operator = not_provided(parser); @@ -13502,45 +13537,29 @@ parse_pattern_primitive(pm_parser_t *parser, pm_diagnostic_id_t diag_id) { // pattern node. node = pm_hash_pattern_node_empty_create(parser, &opening, &parser->previous); } else { - pm_node_t *first_assoc; + pm_node_t *first_node; switch (parser->current.type) { - case PM_TOKEN_LABEL: { + case PM_TOKEN_LABEL: parser_lex(parser); - - pm_symbol_node_t *key = pm_symbol_node_label_create(parser, &parser->previous); - pm_token_t operator = not_provided(parser); - - first_assoc = (pm_node_t *) pm_assoc_node_create(parser, (pm_node_t *) key, &operator, NULL); + first_node = (pm_node_t *) pm_symbol_node_label_create(parser, &parser->previous); break; - } case PM_TOKEN_USTAR_STAR: - first_assoc = parse_pattern_keyword_rest(parser); + first_node = parse_pattern_keyword_rest(parser); break; - case PM_TOKEN_STRING_BEGIN: { - pm_node_t *key = parse_expression(parser, PM_BINDING_POWER_MAX, false, PM_ERR_PATTERN_HASH_KEY); - pm_token_t operator = not_provided(parser); - - if (!pm_symbol_node_label_p(key)) { - pm_parser_err_node(parser, key, PM_ERR_PATTERN_HASH_KEY_LABEL); - } - - first_assoc = (pm_node_t *) pm_assoc_node_create(parser, key, &operator, NULL); + case PM_TOKEN_STRING_BEGIN: + first_node = parse_expression(parser, PM_BINDING_POWER_MAX, false, PM_ERR_PATTERN_HASH_KEY); break; - } default: { parser_lex(parser); pm_parser_err_previous(parser, PM_ERR_PATTERN_HASH_KEY); - pm_missing_node_t *key = pm_missing_node_create(parser, parser->previous.start, parser->previous.end); - pm_token_t operator = not_provided(parser); - - first_assoc = (pm_node_t *) pm_assoc_node_create(parser, (pm_node_t *) key, &operator, NULL); + first_node = (pm_node_t *) pm_missing_node_create(parser, parser->previous.start, parser->previous.end); break; } } - node = parse_pattern_hash(parser, first_assoc); + node = parse_pattern_hash(parser, first_node); accept1(parser, PM_TOKEN_NEWLINE); expect1(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_PATTERN_TERM_BRACE); @@ -13784,9 +13803,7 @@ parse_pattern(pm_parser_t *parser, bool top_pattern, pm_diagnostic_id_t diag_id) case PM_TOKEN_LABEL: { parser_lex(parser); pm_node_t *key = (pm_node_t *) pm_symbol_node_label_create(parser, &parser->previous); - pm_token_t operator = not_provided(parser); - - return (pm_node_t *) parse_pattern_hash(parser, (pm_node_t *) pm_assoc_node_create(parser, key, &operator, NULL)); + return (pm_node_t *) parse_pattern_hash(parser, key); } case PM_TOKEN_USTAR_STAR: { node = parse_pattern_keyword_rest(parser); @@ -13809,8 +13826,7 @@ parse_pattern(pm_parser_t *parser, bool top_pattern, pm_diagnostic_id_t diag_id) // If we got a dynamic label symbol, then we need to treat it like the // beginning of a hash pattern. if (pm_symbol_node_label_p(node)) { - pm_token_t operator = not_provided(parser); - return (pm_node_t *) parse_pattern_hash(parser, (pm_node_t *) pm_assoc_node_create(parser, node, &operator, NULL)); + return (pm_node_t *) parse_pattern_hash(parser, node); } if (top_pattern && match1(parser, PM_TOKEN_COMMA)) { diff --git a/test/prism/snapshots/patterns.txt b/test/prism/snapshots/patterns.txt index 17bd04f3bc3cfb..eed0a8e2b7b58c 100644 --- a/test/prism/snapshots/patterns.txt +++ b/test/prism/snapshots/patterns.txt @@ -4757,7 +4757,12 @@ │ │ │ │ │ ├── value_loc: (202,15)-(202,16) = "x" │ │ │ │ │ ├── closing_loc: (202,16)-(202,17) = ":" │ │ │ │ │ └── unescaped: "x" - │ │ │ │ ├── value: ∅ + │ │ │ │ ├── value: + │ │ │ │ │ @ ImplicitNode (location: (202,15)-(202,16)) + │ │ │ │ │ └── value: + │ │ │ │ │ @ LocalVariableTargetNode (location: (202,15)-(202,16)) + │ │ │ │ │ ├── name: :x + │ │ │ │ │ └── depth: 0 │ │ │ │ └── operator_loc: ∅ │ │ │ ├── rest: ∅ │ │ │ ├── opening_loc: (202,14)-(202,15) = "{" diff --git a/test/prism/snapshots/seattlerb/case_in.txt b/test/prism/snapshots/seattlerb/case_in.txt index 94ff42b8b27635..96a76174d2ef59 100644 --- a/test/prism/snapshots/seattlerb/case_in.txt +++ b/test/prism/snapshots/seattlerb/case_in.txt @@ -25,7 +25,12 @@ │ │ │ │ │ ├── value_loc: (2,5)-(2,6) = "b" │ │ │ │ │ ├── closing_loc: (2,6)-(2,8) = "\":" │ │ │ │ │ └── unescaped: "b" - │ │ │ │ ├── value: ∅ + │ │ │ │ ├── value: + │ │ │ │ │ @ ImplicitNode (location: (2,5)-(2,6)) + │ │ │ │ │ └── value: + │ │ │ │ │ @ LocalVariableTargetNode (location: (2,5)-(2,6)) + │ │ │ │ │ ├── name: :b + │ │ │ │ │ └── depth: 0 │ │ │ │ └── operator_loc: ∅ │ │ │ ├── rest: ∅ │ │ │ ├── opening_loc: ∅ @@ -905,7 +910,12 @@ │ │ │ │ │ ├── value_loc: (106,6)-(106,7) = "b" │ │ │ │ │ ├── closing_loc: (106,7)-(106,9) = "\":" │ │ │ │ │ └── unescaped: "b" - │ │ │ │ ├── value: ∅ + │ │ │ │ ├── value: + │ │ │ │ │ @ ImplicitNode (location: (106,6)-(106,7)) + │ │ │ │ │ └── value: + │ │ │ │ │ @ LocalVariableTargetNode (location: (106,6)-(106,7)) + │ │ │ │ │ ├── name: :b + │ │ │ │ │ └── depth: 0 │ │ │ │ └── operator_loc: ∅ │ │ │ ├── rest: ∅ │ │ │ ├── opening_loc: (106,3)-(106,4) = "{" diff --git a/test/prism/snapshots/seattlerb/case_in_hash_pat_assign.txt b/test/prism/snapshots/seattlerb/case_in_hash_pat_assign.txt index 17136fd0bc4dd5..9863dfbc3f3a6c 100644 --- a/test/prism/snapshots/seattlerb/case_in_hash_pat_assign.txt +++ b/test/prism/snapshots/seattlerb/case_in_hash_pat_assign.txt @@ -60,7 +60,12 @@ │ │ │ │ ├── value_loc: (2,30)-(2,31) = "f" │ │ │ │ ├── closing_loc: (2,31)-(2,32) = ":" │ │ │ │ └── unescaped: "f" - │ │ │ ├── value: ∅ + │ │ │ ├── value: + │ │ │ │ @ ImplicitNode (location: (2,30)-(2,31)) + │ │ │ │ └── value: + │ │ │ │ @ LocalVariableTargetNode (location: (2,30)-(2,31)) + │ │ │ │ ├── name: :f + │ │ │ │ └── depth: 0 │ │ │ └── operator_loc: ∅ │ │ ├── rest: ∅ │ │ ├── opening_loc: (2,3)-(2,4) = "{" diff --git a/test/prism/snapshots/seattlerb/parse_pattern_058.txt b/test/prism/snapshots/seattlerb/parse_pattern_058.txt index d372ece2d4021f..66db776bcb6d8e 100644 --- a/test/prism/snapshots/seattlerb/parse_pattern_058.txt +++ b/test/prism/snapshots/seattlerb/parse_pattern_058.txt @@ -35,7 +35,12 @@ │ │ │ │ ├── value_loc: (2,4)-(2,5) = "a" │ │ │ │ ├── closing_loc: (2,5)-(2,6) = ":" │ │ │ │ └── unescaped: "a" - │ │ │ ├── value: ∅ + │ │ │ ├── value: + │ │ │ │ @ ImplicitNode (location: (2,4)-(2,5)) + │ │ │ │ └── value: + │ │ │ │ @ LocalVariableTargetNode (location: (2,4)-(2,5)) + │ │ │ │ ├── name: :a + │ │ │ │ └── depth: 0 │ │ │ └── operator_loc: ∅ │ │ ├── rest: │ │ │ @ AssocSplatNode (location: (2,8)-(2,14)) diff --git a/test/prism/snapshots/seattlerb/parse_pattern_058_2.txt b/test/prism/snapshots/seattlerb/parse_pattern_058_2.txt index b75b198907a9e2..075084ed962efe 100644 --- a/test/prism/snapshots/seattlerb/parse_pattern_058_2.txt +++ b/test/prism/snapshots/seattlerb/parse_pattern_058_2.txt @@ -35,7 +35,12 @@ │ │ │ │ ├── value_loc: (2,4)-(2,5) = "a" │ │ │ │ ├── closing_loc: (2,5)-(2,6) = ":" │ │ │ │ └── unescaped: "a" - │ │ │ ├── value: ∅ + │ │ │ ├── value: + │ │ │ │ @ ImplicitNode (location: (2,4)-(2,5)) + │ │ │ │ └── value: + │ │ │ │ @ LocalVariableTargetNode (location: (2,4)-(2,5)) + │ │ │ │ ├── name: :a + │ │ │ │ └── depth: 0 │ │ │ └── operator_loc: ∅ │ │ ├── rest: │ │ │ @ AssocSplatNode (location: (2,8)-(2,10)) diff --git a/test/prism/snapshots/unparser/corpus/literal/pattern.txt b/test/prism/snapshots/unparser/corpus/literal/pattern.txt index 1a5113160d81d1..b55309472aeb64 100644 --- a/test/prism/snapshots/unparser/corpus/literal/pattern.txt +++ b/test/prism/snapshots/unparser/corpus/literal/pattern.txt @@ -89,7 +89,12 @@ │ │ │ │ │ │ ├── value_loc: (6,5)-(6,6) = "x" │ │ │ │ │ │ ├── closing_loc: (6,6)-(6,7) = ":" │ │ │ │ │ │ └── unescaped: "x" - │ │ │ │ │ ├── value: ∅ + │ │ │ │ │ ├── value: + │ │ │ │ │ │ @ ImplicitNode (location: (6,5)-(6,6)) + │ │ │ │ │ │ └── value: + │ │ │ │ │ │ @ LocalVariableTargetNode (location: (6,5)-(6,6)) + │ │ │ │ │ │ ├── name: :x + │ │ │ │ │ │ └── depth: 0 │ │ │ │ │ └── operator_loc: ∅ │ │ │ │ ├── rest: ∅ │ │ │ │ ├── opening_loc: (6,4)-(6,5) = "(" diff --git a/test/prism/snapshots/whitequark/multiple_pattern_matches.txt b/test/prism/snapshots/whitequark/multiple_pattern_matches.txt index 856ecc8c6797f9..3150bfb8e22a67 100644 --- a/test/prism/snapshots/whitequark/multiple_pattern_matches.txt +++ b/test/prism/snapshots/whitequark/multiple_pattern_matches.txt @@ -33,7 +33,12 @@ │ │ │ │ ├── value_loc: (1,10)-(1,11) = "a" │ │ │ │ ├── closing_loc: (1,11)-(1,12) = ":" │ │ │ │ └── unescaped: "a" - │ │ │ ├── value: ∅ + │ │ │ ├── value: + │ │ │ │ @ ImplicitNode (location: (1,10)-(1,11)) + │ │ │ │ └── value: + │ │ │ │ @ LocalVariableTargetNode (location: (1,10)-(1,11)) + │ │ │ │ ├── name: :a + │ │ │ │ └── depth: 0 │ │ │ └── operator_loc: ∅ │ │ ├── rest: ∅ │ │ ├── opening_loc: ∅ @@ -69,7 +74,12 @@ │ │ │ │ ├── value_loc: (2,10)-(2,11) = "a" │ │ │ │ ├── closing_loc: (2,11)-(2,12) = ":" │ │ │ │ └── unescaped: "a" - │ │ │ ├── value: ∅ + │ │ │ ├── value: + │ │ │ │ @ ImplicitNode (location: (2,10)-(2,11)) + │ │ │ │ └── value: + │ │ │ │ @ LocalVariableTargetNode (location: (2,10)-(2,11)) + │ │ │ │ ├── name: :a + │ │ │ │ └── depth: 0 │ │ │ └── operator_loc: ∅ │ │ ├── rest: ∅ │ │ ├── opening_loc: ∅ @@ -105,7 +115,12 @@ │ │ │ │ ├── value_loc: (4,10)-(4,11) = "a" │ │ │ │ ├── closing_loc: (4,11)-(4,12) = ":" │ │ │ │ └── unescaped: "a" - │ │ │ ├── value: ∅ + │ │ │ ├── value: + │ │ │ │ @ ImplicitNode (location: (4,10)-(4,11)) + │ │ │ │ └── value: + │ │ │ │ @ LocalVariableTargetNode (location: (4,10)-(4,11)) + │ │ │ │ ├── name: :a + │ │ │ │ └── depth: 0 │ │ │ └── operator_loc: ∅ │ │ ├── rest: ∅ │ │ ├── opening_loc: ∅ @@ -141,7 +156,12 @@ │ │ │ ├── value_loc: (5,10)-(5,11) = "a" │ │ │ ├── closing_loc: (5,11)-(5,12) = ":" │ │ │ └── unescaped: "a" - │ │ ├── value: ∅ + │ │ ├── value: + │ │ │ @ ImplicitNode (location: (5,10)-(5,11)) + │ │ │ └── value: + │ │ │ @ LocalVariableTargetNode (location: (5,10)-(5,11)) + │ │ │ ├── name: :a + │ │ │ └── depth: 0 │ │ └── operator_loc: ∅ │ ├── rest: ∅ │ ├── opening_loc: ∅ diff --git a/test/prism/snapshots/whitequark/newline_in_hash_argument.txt b/test/prism/snapshots/whitequark/newline_in_hash_argument.txt index 4daf1ebce58a2b..554d3108cd7176 100644 --- a/test/prism/snapshots/whitequark/newline_in_hash_argument.txt +++ b/test/prism/snapshots/whitequark/newline_in_hash_argument.txt @@ -29,7 +29,12 @@ │ │ │ │ │ │ ├── value_loc: (2,3)-(2,4) = "a" │ │ │ │ │ │ ├── closing_loc: (2,4)-(2,5) = ":" │ │ │ │ │ │ └── unescaped: "a" - │ │ │ │ │ ├── value: ∅ + │ │ │ │ │ ├── value: + │ │ │ │ │ │ @ ImplicitNode (location: (2,3)-(2,4)) + │ │ │ │ │ │ └── value: + │ │ │ │ │ │ @ LocalVariableTargetNode (location: (2,3)-(2,4)) + │ │ │ │ │ │ ├── name: :a + │ │ │ │ │ │ └── depth: 0 │ │ │ │ │ └── operator_loc: ∅ │ │ │ │ ├── rest: ∅ │ │ │ │ ├── opening_loc: ∅ @@ -55,7 +60,12 @@ │ │ │ │ │ ├── value_loc: (5,4)-(5,5) = "b" │ │ │ │ │ ├── closing_loc: (5,5)-(5,7) = "\":" │ │ │ │ │ └── unescaped: "b" - │ │ │ │ ├── value: ∅ + │ │ │ │ ├── value: + │ │ │ │ │ @ ImplicitNode (location: (5,4)-(5,5)) + │ │ │ │ │ └── value: + │ │ │ │ │ @ LocalVariableTargetNode (location: (5,4)-(5,5)) + │ │ │ │ │ ├── name: :b + │ │ │ │ │ └── depth: 0 │ │ │ │ └── operator_loc: ∅ │ │ │ ├── rest: ∅ │ │ │ ├── opening_loc: ∅ diff --git a/test/prism/snapshots/whitequark/pattern_matching_single_line_allowed_omission_of_parentheses.txt b/test/prism/snapshots/whitequark/pattern_matching_single_line_allowed_omission_of_parentheses.txt index dad320593ad835..99d1cdc25b8c14 100644 --- a/test/prism/snapshots/whitequark/pattern_matching_single_line_allowed_omission_of_parentheses.txt +++ b/test/prism/snapshots/whitequark/pattern_matching_single_line_allowed_omission_of_parentheses.txt @@ -91,7 +91,12 @@ │ │ │ │ ├── value_loc: (5,10)-(5,11) = "a" │ │ │ │ ├── closing_loc: (5,11)-(5,12) = ":" │ │ │ │ └── unescaped: "a" - │ │ │ ├── value: ∅ + │ │ │ ├── value: + │ │ │ │ @ ImplicitNode (location: (5,10)-(5,11)) + │ │ │ │ └── value: + │ │ │ │ @ LocalVariableTargetNode (location: (5,10)-(5,11)) + │ │ │ │ ├── name: :a + │ │ │ │ └── depth: 0 │ │ │ └── operator_loc: ∅ │ │ ├── rest: ∅ │ │ ├── opening_loc: ∅ @@ -130,7 +135,12 @@ │ │ │ │ ├── value_loc: (7,10)-(7,11) = "a" │ │ │ │ ├── closing_loc: (7,11)-(7,12) = ":" │ │ │ │ └── unescaped: "a" - │ │ │ ├── value: ∅ + │ │ │ ├── value: + │ │ │ │ @ ImplicitNode (location: (7,10)-(7,11)) + │ │ │ │ └── value: + │ │ │ │ @ LocalVariableTargetNode (location: (7,10)-(7,11)) + │ │ │ │ ├── name: :a + │ │ │ │ └── depth: 0 │ │ │ └── operator_loc: ∅ │ │ ├── rest: ∅ │ │ ├── opening_loc: ∅ From dc8fb7d97ff0113c738bded825a37b3196eeaaae Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Wed, 24 Jan 2024 11:45:53 -0500 Subject: [PATCH 500/640] [PRISM] Fix crash in anonymous block with forwarding arguments Fixes ruby/prism#2262. --- prism_compile.c | 4 ++-- test/ruby/test_compile_prism.rb | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 90c70849fb9506..bad18f069210fb 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -6641,8 +6641,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, body->param.block_start = local_index; body->param.flags.has_block = true; - local = idAnd; - local_table_for_iseq->ids[local_index] = local; + local_table_for_iseq->ids[local_index] = PM_CONSTANT_AND; + st_insert(index_lookup_table, PM_CONSTANT_AND, local_index); local_index++; local = idDot3; diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index bcbd5449e018a1..b7aa75a5b06f2b 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1725,7 +1725,7 @@ def test_ArgumentsNode def test_BlockArgumentNode assert_prism_eval("1.then(&:to_s)") - # Test forwarding with no name + # Test anonymous block forwarding assert_prism_eval(<<~RUBY) o = Object.new def o.foo(&) = yield @@ -1733,6 +1733,15 @@ def o.bar(&) = foo(&) o.bar { :ok } RUBY + + # Test anonymous block forwarding from argument forwarding + assert_prism_eval(<<~RUBY) + o = Object.new + def o.foo = yield + def o.bar(...) = foo(&) + + o.bar { :ok } + RUBY end def test_BlockLocalVariableNode From 020fe6e0ca3b7f3b0b35466e7086e809f2ccbcd0 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Wed, 24 Jan 2024 13:43:26 -0500 Subject: [PATCH 501/640] [PRISM] Fix forwarding from within block Fixes ruby/prism#2253. --- prism_compile.c | 19 +++++++++++++------ test/ruby/test_compile_prism.rb | 8 ++++++++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index bad18f069210fb..c526a1b3b70ffd 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -59,6 +59,7 @@ #define PM_SPECIAL_CONSTANT_FLAG ((pm_constant_id_t)(1 << 31)) #define PM_CONSTANT_AND ((pm_constant_id_t)(idAnd | PM_SPECIAL_CONSTANT_FLAG)) +#define PM_CONSTANT_DOT3 ((pm_constant_id_t)(idDot3 | PM_SPECIAL_CONSTANT_FLAG)) #define PM_CONSTANT_MULT ((pm_constant_id_t)(idMULT | PM_SPECIAL_CONSTANT_FLAG)) #define PM_CONSTANT_POW ((pm_constant_id_t)(idPow | PM_SPECIAL_CONSTANT_FLAG)) @@ -1181,9 +1182,15 @@ pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinf case PM_FORWARDING_ARGUMENTS_NODE: { orig_argc++; *flags |= VM_CALL_ARGS_BLOCKARG | VM_CALL_ARGS_SPLAT; - ADD_GETLOCAL(ret, &dummy_line_node, 3, 0); + + pm_local_index_t mult_index = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_MULT, 0); + ADD_GETLOCAL(ret, &dummy_line_node, mult_index.index, mult_index.level); + ADD_INSN1(ret, &dummy_line_node, splatarray, RBOOL(arguments_node_list.size > 1)); - ADD_INSN2(ret, &dummy_line_node, getblockparamproxy, INT2FIX(4), INT2FIX(0)); + + pm_local_index_t dot3_index = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_DOT3, 0); + ADD_INSN2(ret, &dummy_line_node, getblockparamproxy, INT2FIX(dot3_index.index), INT2FIX(dot3_index.level)); + break; } default: { @@ -6635,8 +6642,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, case PM_FORWARDING_PARAMETER_NODE: { body->param.rest_start = local_index; body->param.flags.has_rest = true; - ID local = idMULT; - local_table_for_iseq->ids[local_index] = local; + local_table_for_iseq->ids[local_index] = PM_CONSTANT_MULT; + st_insert(index_lookup_table, PM_CONSTANT_MULT, local_index); local_index++; body->param.block_start = local_index; @@ -6645,8 +6652,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, st_insert(index_lookup_table, PM_CONSTANT_AND, local_index); local_index++; - local = idDot3; - local_table_for_iseq->ids[local_index] = local; + local_table_for_iseq->ids[local_index] = PM_CONSTANT_DOT3; + st_insert(index_lookup_table, PM_CONSTANT_DOT3, local_index); local_index++; break; } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index b7aa75a5b06f2b..5ed41569f5fb0f 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -2033,6 +2033,14 @@ def prism_test_forwarding_arguments_node1(a, ...) prism_test_forwarding_arguments_node(1,2, 3, ...) end CODE + + assert_prism_eval(<<~RUBY) + o = Object.new + def o.bar(a, b, c) = [a, b, c] + def o.foo(...) = 1.times { bar(...) } + + o.foo(1, 2, 3) + RUBY end def test_ForwardingSuperNode From c888b8d63b714d5ccf107272b10d723c75fbe7dd Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 24 Jan 2024 13:43:04 -0500 Subject: [PATCH 502/640] [PRISM] Handle implicit lvar write in hash pattern --- prism_compile.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/prism_compile.c b/prism_compile.c index c526a1b3b70ffd..20eb457bfbcb93 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -1944,7 +1944,12 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t ADD_INSN1(match_values, &line.node, putobject, symbol); ADD_SEND(match_values, &line.node, has_rest ? rb_intern("delete") : idAREF, INT2FIX(1)); - CHECK(pm_compile_pattern_match(iseq, scope_node, assoc->value, match_values, src, match_failed_label, in_single_pattern, in_alternation_pattern, false, base_index + 1)); + const pm_node_t *value = assoc->value; + if (PM_NODE_TYPE_P(value, PM_IMPLICIT_NODE)) { + value = ((const pm_implicit_node_t *) value)->value; + } + + CHECK(pm_compile_pattern_match(iseq, scope_node, value, match_values, src, match_failed_label, in_single_pattern, in_alternation_pattern, false, base_index + 1)); } ADD_SEQ(ret, match_values); From 44c337a397b1159c7bc843a501d6a0a51e65430f Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 24 Jan 2024 14:24:13 -0500 Subject: [PATCH 503/640] [PRISM] Support __LINE__, __FILE__, and __ENCODING__ in patterns, fix pinned expressions --- prism_compile.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 20eb457bfbcb93..b88d90bae0ac14 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2078,6 +2078,13 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t CHECK(pm_compile_pattern(iseq, scope_node, cast->right, ret, src, matched_label, unmatched_label, in_single_pattern, true, true, base_index)); break; } + case PM_PINNED_EXPRESSION_NODE: + // Pinned expressions are a way to match against the value of an + // expression that should be evaluated at runtime. This looks like: + // foo in ^(bar). To compile these, we compile the expression as if it + // were a literal value by falling through to the literal case. + node = ((pm_pinned_expression_node_t *) node)->expression; + /* fallthrough */ case PM_ARRAY_NODE: case PM_CLASS_VARIABLE_READ_NODE: case PM_CONSTANT_PATH_NODE: @@ -2095,6 +2102,9 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t case PM_LAMBDA_NODE: case PM_LOCAL_VARIABLE_READ_NODE: case PM_NIL_NODE: + case PM_SOURCE_ENCODING_NODE: + case PM_SOURCE_FILE_NODE: + case PM_SOURCE_LINE_NODE: case PM_RANGE_NODE: case PM_RATIONAL_NODE: case PM_REGULAR_EXPRESSION_NODE: @@ -2130,15 +2140,6 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t CHECK(pm_compile_pattern(iseq, scope_node, cast->variable, ret, src, matched_label, unmatched_label, in_single_pattern, in_alternation_pattern, true, base_index)); break; } - case PM_PINNED_EXPRESSION_NODE: { - // Pinned expressions are a way to match against the value of an - // expression that should be evaluated at runtime. This looks like: - // foo in ^(bar). To compile these, we compile the expression that they - // hold. - pm_pinned_expression_node_t *cast = (pm_pinned_expression_node_t *) node; - CHECK(pm_compile_pattern(iseq, scope_node, cast->expression, ret, src, matched_label, unmatched_label, in_single_pattern, in_alternation_pattern, true, base_index)); - break; - } case PM_IF_NODE: case PM_UNLESS_NODE: { // If and unless nodes can show up here as guards on `in` clauses. This From 29c3ec3d49ad66c4ec9ea13735481cca598bcbcd Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 23 Jan 2024 12:55:00 -0800 Subject: [PATCH 504/640] Fix required positional repeated _ parameters Co-Authored-By: Matt Valentine-House --- prism_compile.c | 6 +++++- test/ruby/test_compile_prism.rb | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/prism_compile.c b/prism_compile.c index b88d90bae0ac14..4e2984c065b391 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -6431,7 +6431,11 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, case PM_REQUIRED_PARAMETER_NODE: { pm_required_parameter_node_t * param = (pm_required_parameter_node_t *)required; - if (!PM_NODE_FLAG_P(required, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + if (PM_NODE_FLAG_P(required, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + ID local = pm_constant_id_lookup(scope_node, param->name); + local_table_for_iseq->ids[local_index] = local; + } + else { pm_insert_local_index(param->name, local_index, index_lookup_table, local_table_for_iseq, scope_node); } break; diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 5ed41569f5fb0f..bccc4d4695fe13 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1545,6 +1545,10 @@ def self.prism_test_def_node(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, CODE end + def test_repeated_required_underscore + assert_prism_eval("def self.m(a, _, _, b); end; method(:m).parameters") + end + def test_locals_in_parameters assert_prism_eval("def self.m(a = b = c = 1); [a, b, c]; end; self.m") end From 03f76f098ada081c8ce1db25ddc9b9fc21608877 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 23 Jan 2024 13:13:56 -0800 Subject: [PATCH 505/640] Fix repeated optional _ parameters Ensure there is enough space in the local table for repeated optional parameters. Co-Authored-By: Matt Valentine-House --- prism_compile.c | 25 +++++++++++++++++++++++-- test/ruby/test_compile_prism.rb | 4 ++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 4e2984c065b391..4e54a494d80537 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -6341,6 +6341,19 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } } + // Ensure there is enough room in the local table for any + // parameters that have been repeated + // ex: def underscore_parameters(_, _ = 1, _ = 2); _; end + // ^^^^^^^^^^^^ + if (optionals_list && optionals_list->size) { + for (size_t i = 0; i < optionals_list->size; i++) { + pm_node_t * node = optionals_list->nodes[i]; + if (PM_NODE_FLAG_P(node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + table_size++; + } + } + } + // If we have an anonymous "rest" node, we'll need to increase the local // table size to take it in to account. // def m(foo, *, bar) @@ -6457,8 +6470,16 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, body->param.flags.has_opt = true; for (size_t i = 0; i < optionals_list->size; i++, local_index++) { - pm_constant_id_t name = ((pm_optional_parameter_node_t *)optionals_list->nodes[i])->name; - pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node); + pm_node_t * node = optionals_list->nodes[i]; + pm_constant_id_t name = ((pm_optional_parameter_node_t *)node)->name; + + if (PM_NODE_FLAG_P(node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + ID local = pm_constant_id_lookup(scope_node, name); + local_table_for_iseq->ids[local_index] = local; + } + else { + pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node); + } } } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index bccc4d4695fe13..e5401fab9dc46f 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1545,6 +1545,10 @@ def self.prism_test_def_node(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, CODE end + def test_repeated_optional_underscore + assert_prism_eval("def self.m(a, _, _, _ = 1, _ = 2, b); end; method(:m).parameters") + end + def test_repeated_required_underscore assert_prism_eval("def self.m(a, _, _, b); end; method(:m).parameters") end From bb6af9287b2002c736e1f50a74a57922f61e8a53 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 23 Jan 2024 13:20:49 -0800 Subject: [PATCH 506/640] Fix local table space for `*_` We need to make sure there is enough room in the local table for repeated `*_` parameters Co-Authored-By: Matt Valentine-House --- prism_compile.c | 10 ++++++++-- test/ruby/test_compile_prism.rb | 4 ++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 4e54a494d80537..163eaf1b09656a 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -6360,7 +6360,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // ^ if (parameters_node && parameters_node->rest) { if (!(PM_NODE_TYPE_P(parameters_node->rest, PM_IMPLICIT_REST_NODE))) { - if (!((pm_rest_parameter_node_t *)parameters_node->rest)->name) { + if (!((pm_rest_parameter_node_t *)parameters_node->rest)->name || PM_NODE_FLAG_P(parameters_node->rest, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { table_size++; } } @@ -6497,7 +6497,13 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, if (name) { // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n) // ^^ - pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node); + if (PM_NODE_FLAG_P(parameters_node->rest, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + ID local = pm_constant_id_lookup(scope_node, name); + local_table_for_iseq->ids[local_index] = local; + } + else { + pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node); + } } else { // def foo(a, (b, *c, d), e = 1, *, g, (h, *i, j), k:, l: 1, **m, &n) diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index e5401fab9dc46f..7f4cf49bb4e117 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1545,6 +1545,10 @@ def self.prism_test_def_node(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, CODE end + def test_repeated_splat_underscore + assert_prism_eval("def self.m(_, _, _ = 1, _ = 2, *_); end; method(:m).parameters") + end + def test_repeated_optional_underscore assert_prism_eval("def self.m(a, _, _, _ = 1, _ = 2, b); end; method(:m).parameters") end From 8b7e78f156fb566b47ea3ff7701e18486b0e2dac Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 23 Jan 2024 13:33:31 -0800 Subject: [PATCH 507/640] Fix local table size and index for required post underscore Co-Authored-By: Matt Valentine-House --- prism_compile.c | 10 ++++++++-- test/ruby/test_compile_prism.rb | 4 ++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 163eaf1b09656a..e15d0627edbe83 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -6372,7 +6372,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // additional anonymous local not represented in the locals table // We want to account for this in our table size pm_node_t *required = posts_list->nodes[i]; - if (PM_NODE_TYPE_P(required, PM_MULTI_TARGET_NODE)) { + if (PM_NODE_TYPE_P(required, PM_MULTI_TARGET_NODE) || PM_NODE_FLAG_P(required, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { table_size++; } } @@ -6541,8 +6541,14 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // ^ case PM_REQUIRED_PARAMETER_NODE: { pm_required_parameter_node_t * param = (pm_required_parameter_node_t *)post_node; + if (PM_NODE_FLAG_P(param, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + ID local = pm_constant_id_lookup(scope_node, param->name); + local_table_for_iseq->ids[local_index] = local; + } + else { - pm_insert_local_index(param->name, local_index, index_lookup_table, local_table_for_iseq, scope_node); + pm_insert_local_index(param->name, local_index, index_lookup_table, local_table_for_iseq, scope_node); + } break; } default: { diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 7f4cf49bb4e117..e9bf819ea61709 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1545,6 +1545,10 @@ def self.prism_test_def_node(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, CODE end + def test_repeated_required_post_underscore + assert_prism_eval("def self.m(_, _, *_, _); _; end; method(:m).parameters") + end + def test_repeated_splat_underscore assert_prism_eval("def self.m(_, _, _ = 1, _ = 2, *_); end; method(:m).parameters") end From 13c76e40d3cbd79ccd8d340fa8b85f5778484f20 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 23 Jan 2024 13:41:34 -0800 Subject: [PATCH 508/640] Fix local table size and variable offset for repeated keywords Co-Authored-By: Matt Valentine-House --- prism_compile.c | 24 ++++++++++++++++++++++-- test/ruby/test_compile_prism.rb | 5 +++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index e15d0627edbe83..0e30dc9c9ca0c3 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -6378,6 +6378,15 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } } + if (keywords_list && keywords_list->size) { + for (size_t i = 0; i < keywords_list->size; i++) { + pm_node_t *keyword_parameter_node = keywords_list->nodes[i]; + if (PM_NODE_FLAG_P(keyword_parameter_node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + table_size++; + } + } + } + if (block_param_keyword_rest) { table_size++; } @@ -6583,7 +6592,13 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, name = ((pm_required_keyword_parameter_node_t *)keyword_parameter_node)->name; keyword->required_num++; ID local = pm_constant_id_lookup(scope_node, name); - pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node); + + if (PM_NODE_FLAG_P(keyword_parameter_node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + local_table_for_iseq->ids[local_index] = local; + } + else { + pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node); + } local_index++; ids[kw_index++] = local; } @@ -6613,7 +6628,12 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } ID local = pm_constant_id_lookup(scope_node, name); - pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node); + if (PM_NODE_FLAG_P(keyword_parameter_node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + local_table_for_iseq->ids[local_index] = local; + } + else { + pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node); + } ids[kw_index++] = local; local_index++; } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index e9bf819ea61709..a5ab94cbc1d855 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1545,6 +1545,11 @@ def self.prism_test_def_node(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, CODE end + def test_repeated_required_keyword_underscore + assert_prism_eval("def self.m(_, _, *_, _, _:); _; end; method(:m).parameters") + assert_prism_eval("def self.m(_, _, *_, _, _:, _: 2); _; end; method(:m).parameters") + end + def test_repeated_required_post_underscore assert_prism_eval("def self.m(_, _, *_, _); _; end; method(:m).parameters") end From 1817af507466ace78f4bc02d77e1f16c70e3a087 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 23 Jan 2024 13:50:27 -0800 Subject: [PATCH 509/640] Fix local table size / index for repeated kwrest Co-Authored-By: Matt Valentine-House --- prism_compile.c | 24 +++++++++++++++++++----- test/ruby/test_compile_prism.rb | 4 ++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 0e30dc9c9ca0c3..2f9de3e63a619f 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -6358,12 +6358,20 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // table size to take it in to account. // def m(foo, *, bar) // ^ - if (parameters_node && parameters_node->rest) { - if (!(PM_NODE_TYPE_P(parameters_node->rest, PM_IMPLICIT_REST_NODE))) { - if (!((pm_rest_parameter_node_t *)parameters_node->rest)->name || PM_NODE_FLAG_P(parameters_node->rest, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { - table_size++; + if (parameters_node) { + if (parameters_node->rest) { + if (!(PM_NODE_TYPE_P(parameters_node->rest, PM_IMPLICIT_REST_NODE))) { + if (!((pm_rest_parameter_node_t *)parameters_node->rest)->name || PM_NODE_FLAG_P(parameters_node->rest, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + table_size++; + } } } + + // def underscore_parameters(_, **_); _; end + // ^^^ + if (parameters_node->keyword_rest && PM_NODE_FLAG_P(parameters_node->keyword_rest, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + table_size++; + } } if (posts_list) { @@ -6691,7 +6699,13 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_constant_id_t constant_id = kw_rest_node->name; if (constant_id) { - pm_insert_local_index(constant_id, local_index, index_lookup_table, local_table_for_iseq, scope_node); + if (PM_NODE_FLAG_P(kw_rest_node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + ID local = pm_constant_id_lookup(scope_node, constant_id); + local_table_for_iseq->ids[local_index] = local; + } + else { + pm_insert_local_index(constant_id, local_index, index_lookup_table, local_table_for_iseq, scope_node); + } } else { local_table_for_iseq->ids[local_index] = PM_CONSTANT_POW; diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index a5ab94cbc1d855..d122969cd357c7 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1545,6 +1545,10 @@ def self.prism_test_def_node(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, CODE end + def test_repeated_kw_rest_underscore + assert_prism_eval("def self.m(_, **_); _; end; method(:m).parameters") + end + def test_repeated_required_keyword_underscore assert_prism_eval("def self.m(_, _, *_, _, _:); _; end; method(:m).parameters") assert_prism_eval("def self.m(_, _, *_, _, _:, _: 2); _; end; method(:m).parameters") From 94f3f9502c4b0a87392f85672cbc01c7167207d5 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 23 Jan 2024 13:55:46 -0800 Subject: [PATCH 510/640] Fix repeated block param Co-Authored-By: Matt Valentine-House --- prism_compile.c | 16 ++++++++++++++-- test/ruby/test_compile_prism.rb | 4 ++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 2f9de3e63a619f..352bcc23a2ba4d 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -6399,6 +6399,12 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, table_size++; } + if (parameters_node && parameters_node->block) { + if (PM_NODE_FLAG_P(parameters_node->block, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + table_size++; + } + } + // When we have a `...` as the keyword_rest, it's a forwarding_parameter_node and // we need to leave space for 2 more locals on the locals table (`*` and `&`) if (parameters_node && parameters_node->keyword_rest && @@ -6747,14 +6753,20 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, body->param.flags.has_block = true; pm_constant_id_t name = ((pm_block_parameter_node_t *)parameters_node->block)->name; + if (name == 0) { local_table_for_iseq->ids[local_index] = PM_CONSTANT_AND; st_insert(index_lookup_table, PM_CONSTANT_AND, local_index); } else { - pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node); + if (PM_NODE_FLAG_P(parameters_node->block, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + ID local = pm_constant_id_lookup(scope_node, name); + local_table_for_iseq->ids[local_index] = local; + } + else { + pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node); + } } - local_index++; } } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index d122969cd357c7..7542f0e2201832 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1545,6 +1545,10 @@ def self.prism_test_def_node(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, CODE end + def test_repeated_block_underscore + assert_prism_eval("def self.m(_, **_, &_); _; end; method(:m).parameters") + end + def test_repeated_kw_rest_underscore assert_prism_eval("def self.m(_, **_); _; end; method(:m).parameters") end From 7d61454f2e4dafa19d879b48508bcedba6f28e43 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Wed, 24 Jan 2024 14:41:43 -0500 Subject: [PATCH 511/640] [PRISM] Fix method calls in keyword arguments Fixes ruby/prism#2248. --- prism_compile.c | 48 ++++++++++++++++----------------- test/ruby/test_compile_prism.rb | 8 ++++++ 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 352bcc23a2ba4d..2df3e27e24258c 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -6876,6 +6876,30 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, //********STEP 5************ // Goal: compile anything that needed to be compiled + if (optionals_list && optionals_list->size) { + LABEL **opt_table = (LABEL **)ALLOC_N(VALUE, optionals_list->size + 1); + LABEL *label; + + // TODO: Should we make an api for NEW_LABEL where you can pass + // a pointer to the label it should fill out? We already + // have a list of labels allocated above so it seems wasteful + // to do the copies. + for (size_t i = 0; i < optionals_list->size; i++) { + label = NEW_LABEL(lineno); + opt_table[i] = label; + ADD_LABEL(ret, label); + pm_node_t *optional_node = optionals_list->nodes[i]; + PM_COMPILE_NOT_POPPED(optional_node); + } + + // Set the last label + label = NEW_LABEL(lineno); + opt_table[optionals_list->size] = label; + ADD_LABEL(ret, label); + + body->param.opt_table = (const VALUE *)opt_table; + } + if (keywords_list && keywords_list->size) { size_t optional_index = 0; for (size_t i = 0; i < keywords_list->size; i++) { @@ -6921,30 +6945,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } } - if (optionals_list && optionals_list->size) { - LABEL **opt_table = (LABEL **)ALLOC_N(VALUE, optionals_list->size + 1); - LABEL *label; - - // TODO: Should we make an api for NEW_LABEL where you can pass - // a pointer to the label it should fill out? We already - // have a list of labels allocated above so it seems wasteful - // to do the copies. - for (size_t i = 0; i < optionals_list->size; i++) { - label = NEW_LABEL(lineno); - opt_table[i] = label; - ADD_LABEL(ret, label); - pm_node_t *optional_node = optionals_list->nodes[i]; - PM_COMPILE_NOT_POPPED(optional_node); - } - - // Set the last label - label = NEW_LABEL(lineno); - opt_table[optionals_list->size] = label; - ADD_LABEL(ret, label); - - body->param.opt_table = (const VALUE *)opt_table; - } - if (requireds_list && requireds_list->size) { for (size_t i = 0; i < requireds_list->size; i++) { // For each MultiTargetNode, we're going to have one additional diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 7542f0e2201832..c5b8bd46474d35 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -2151,6 +2151,14 @@ def test_OptionalParameterNode def test_OptionalKeywordParameterNode assert_prism_eval("def prism_test_optional_keyword_param_node(bar: nil); end") + + # Test with optional argument and method call in OptionalKeywordParameterNode + assert_prism_eval(<<~RUBY) + o = Object.new + def o.foo = 1 + def o.bar(a = nil, b: foo) = b + o.bar + RUBY end def test_ParametersNode From 6a63aaade9cf08e51920698372e8973f1580d8d7 Mon Sep 17 00:00:00 2001 From: Max Prokopiev Date: Wed, 24 Jan 2024 20:34:29 +0100 Subject: [PATCH 512/640] [ruby/prism] Use char_is_identifier_start() to check for valid method name alnum_char() only checks for alphanumeric characters while ignoring other valid cases (like emoji codepoints for example) https://github.com/ruby/prism/commit/d15958fd28 --- prism/prism.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prism/prism.c b/prism/prism.c index 19cd1e6d649114..1c1b53f78713db 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -11021,7 +11021,7 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod return target; } - if (*call->message_loc.start == '_' || parser->encoding->alnum_char(call->message_loc.start, call->message_loc.end - call->message_loc.start)) { + if (char_is_identifier_start(parser, call->message_loc.start)) { // When we get here, we have a method call, because it was // previously marked as a method call but now we have an =. This // looks like: From 91a5093c15f5fe5e51f0f5ba3183ea44688b49ea Mon Sep 17 00:00:00 2001 From: Max Prokopiev Date: Wed, 24 Jan 2024 20:36:37 +0100 Subject: [PATCH 513/640] [ruby/prism] Force encoding during deserialization of constants otherwise we get failing tests if we have non-ascii characters in fixtures/**/*.txt https://github.com/ruby/prism/commit/9323243569 --- prism/templates/lib/prism/serialize.rb.erb | 4 +- test/prism/fixtures/method_calls.txt | 2 + test/prism/snapshots/method_calls.txt | 1563 ++++++++++---------- 3 files changed, 798 insertions(+), 771 deletions(-) diff --git a/prism/templates/lib/prism/serialize.rb.erb b/prism/templates/lib/prism/serialize.rb.erb index 7cbbfb63c5916c..0b5300c4c55df1 100644 --- a/prism/templates/lib/prism/serialize.rb.erb +++ b/prism/templates/lib/prism/serialize.rb.erb @@ -211,9 +211,9 @@ module Prism constant = if start.nobits?(1 << 31) - input.byteslice(start, length).to_sym + input.byteslice(start, length).force_encoding(@encoding).to_sym else - serialized.byteslice(start & ((1 << 31) - 1), length).to_sym + serialized.byteslice(start & ((1 << 31) - 1), length).force_encoding(@encoding).to_sym end constant_pool[index] = constant diff --git a/test/prism/fixtures/method_calls.txt b/test/prism/fixtures/method_calls.txt index d30780771f7376..ad70c70aa0c480 100644 --- a/test/prism/fixtures/method_calls.txt +++ b/test/prism/fixtures/method_calls.txt @@ -20,6 +20,8 @@ a::b c foo.bar = 1 +foo.🌊 = 1 + a? a(&block) diff --git a/test/prism/snapshots/method_calls.txt b/test/prism/snapshots/method_calls.txt index ff6e0dd7df1381..4a76fe5e131bcb 100644 --- a/test/prism/snapshots/method_calls.txt +++ b/test/prism/snapshots/method_calls.txt @@ -1,8 +1,8 @@ -@ ProgramNode (location: (1,0)-(154,6)) +@ ProgramNode (location: (1,0)-(156,6)) ├── locals: [:foo] └── statements: - @ StatementsNode (location: (1,0)-(154,6)) - └── body: (length: 66) + @ StatementsNode (location: (1,0)-(156,6)) + └── body: (length: 67) ├── @ CallNode (location: (1,0)-(1,14)) │ ├── flags: ∅ │ ├── receiver: @@ -262,685 +262,710 @@ │ │ └── flags: decimal │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (23,0)-(23,2)) + ├── @ CallNode (location: (23,0)-(23,12)) + │ ├── flags: attribute_write + │ ├── receiver: + │ │ @ CallNode (location: (23,0)-(23,3)) + │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :foo + │ │ ├── message_loc: (23,0)-(23,3) = "foo" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ └── block: ∅ + │ ├── call_operator_loc: (23,3)-(23,4) = "." + │ ├── name: :🌊= + │ ├── message_loc: (23,4)-(23,8) = "🌊" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (23,11)-(23,12)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ IntegerNode (location: (23,11)-(23,12)) + │ │ └── flags: decimal + │ ├── closing_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (25,0)-(25,2)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a? - │ ├── message_loc: (23,0)-(23,2) = "a?" + │ ├── message_loc: (25,0)-(25,2) = "a?" │ ├── opening_loc: ∅ │ ├── arguments: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (25,0)-(25,8)) + ├── @ CallNode (location: (27,0)-(27,8)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a - │ ├── message_loc: (25,0)-(25,1) = "a" - │ ├── opening_loc: (25,1)-(25,2) = "(" + │ ├── message_loc: (27,0)-(27,1) = "a" + │ ├── opening_loc: (27,1)-(27,2) = "(" │ ├── arguments: ∅ - │ ├── closing_loc: (25,8)-(25,9) = ")" + │ ├── closing_loc: (27,8)-(27,9) = ")" │ └── block: - │ @ BlockArgumentNode (location: (25,2)-(25,8)) + │ @ BlockArgumentNode (location: (27,2)-(27,8)) │ ├── expression: - │ │ @ CallNode (location: (25,3)-(25,8)) + │ │ @ CallNode (location: (27,3)-(27,8)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :block - │ │ ├── message_loc: (25,3)-(25,8) = "block" + │ │ ├── message_loc: (27,3)-(27,8) = "block" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ └── operator_loc: (25,2)-(25,3) = "&" - ├── @ CallNode (location: (27,0)-(27,11)) + │ └── operator_loc: (27,2)-(27,3) = "&" + ├── @ CallNode (location: (29,0)-(29,11)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a - │ ├── message_loc: (27,0)-(27,1) = "a" - │ ├── opening_loc: (27,1)-(27,2) = "(" + │ ├── message_loc: (29,0)-(29,1) = "a" + │ ├── opening_loc: (29,1)-(29,2) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (27,2)-(27,10)) + │ │ @ ArgumentsNode (location: (29,2)-(29,10)) │ │ ├── flags: contains_keyword_splat │ │ └── arguments: (length: 1) - │ │ └── @ KeywordHashNode (location: (27,2)-(27,10)) + │ │ └── @ KeywordHashNode (location: (29,2)-(29,10)) │ │ ├── flags: ∅ │ │ └── elements: (length: 1) - │ │ └── @ AssocSplatNode (location: (27,2)-(27,10)) + │ │ └── @ AssocSplatNode (location: (29,2)-(29,10)) │ │ ├── value: - │ │ │ @ CallNode (location: (27,4)-(27,10)) + │ │ │ @ CallNode (location: (29,4)-(29,10)) │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :kwargs - │ │ │ ├── message_loc: (27,4)-(27,10) = "kwargs" + │ │ │ ├── message_loc: (29,4)-(29,10) = "kwargs" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── operator_loc: (27,2)-(27,4) = "**" - │ ├── closing_loc: (27,10)-(27,11) = ")" + │ │ └── operator_loc: (29,2)-(29,4) = "**" + │ ├── closing_loc: (29,10)-(29,11) = ")" │ └── block: ∅ - ├── @ CallNode (location: (29,0)-(29,5)) + ├── @ CallNode (location: (31,0)-(31,5)) │ ├── flags: ∅ │ ├── receiver: - │ │ @ CallNode (location: (29,0)-(29,3)) + │ │ @ CallNode (location: (31,0)-(31,3)) │ │ ├── flags: ∅ │ │ ├── receiver: - │ │ │ @ CallNode (location: (29,0)-(29,1)) + │ │ │ @ CallNode (location: (31,0)-(31,1)) │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :a - │ │ │ ├── message_loc: (29,0)-(29,1) = "a" + │ │ │ ├── message_loc: (31,0)-(31,1) = "a" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ ├── call_operator_loc: (29,1)-(29,2) = "." + │ │ ├── call_operator_loc: (31,1)-(31,2) = "." │ │ ├── name: :b - │ │ ├── message_loc: (29,2)-(29,3) = "b" + │ │ ├── message_loc: (31,2)-(31,3) = "b" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── call_operator_loc: (29,3)-(29,4) = "." + │ ├── call_operator_loc: (31,3)-(31,4) = "." │ ├── name: :c - │ ├── message_loc: (29,4)-(29,5) = "c" + │ ├── message_loc: (31,4)-(31,5) = "c" │ ├── opening_loc: ∅ │ ├── arguments: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (31,0)-(31,7)) + ├── @ CallNode (location: (33,0)-(33,7)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a - │ ├── message_loc: (31,0)-(31,1) = "a" - │ ├── opening_loc: (31,1)-(31,2) = "(" + │ ├── message_loc: (33,0)-(33,1) = "a" + │ ├── opening_loc: (33,1)-(33,2) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (31,2)-(31,6)) + │ │ @ ArgumentsNode (location: (33,2)-(33,6)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ CallNode (location: (31,2)-(31,3)) + │ │ ├── @ CallNode (location: (33,2)-(33,3)) │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b - │ │ │ ├── message_loc: (31,2)-(31,3) = "b" + │ │ │ ├── message_loc: (33,2)-(33,3) = "b" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── @ CallNode (location: (31,5)-(31,6)) + │ │ └── @ CallNode (location: (33,5)-(33,6)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :c - │ │ ├── message_loc: (31,5)-(31,6) = "c" + │ │ ├── message_loc: (33,5)-(33,6) = "c" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── closing_loc: (31,6)-(31,7) = ")" + │ ├── closing_loc: (33,6)-(33,7) = ")" │ └── block: ∅ - ├── @ CallNode (location: (33,0)-(33,3)) + ├── @ CallNode (location: (35,0)-(35,3)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a - │ ├── message_loc: (33,0)-(33,1) = "a" - │ ├── opening_loc: (33,1)-(33,2) = "(" + │ ├── message_loc: (35,0)-(35,1) = "a" + │ ├── opening_loc: (35,1)-(35,2) = "(" │ ├── arguments: ∅ - │ ├── closing_loc: (33,2)-(33,3) = ")" + │ ├── closing_loc: (35,2)-(35,3) = ")" │ └── block: ∅ - ├── @ CallNode (location: (35,0)-(35,8)) + ├── @ CallNode (location: (37,0)-(37,8)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a - │ ├── message_loc: (35,0)-(35,1) = "a" - │ ├── opening_loc: (35,1)-(35,2) = "(" + │ ├── message_loc: (37,0)-(37,1) = "a" + │ ├── opening_loc: (37,1)-(37,2) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (35,2)-(35,7)) + │ │ @ ArgumentsNode (location: (37,2)-(37,7)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ SplatNode (location: (35,2)-(35,7)) - │ │ ├── operator_loc: (35,2)-(35,3) = "*" + │ │ └── @ SplatNode (location: (37,2)-(37,7)) + │ │ ├── operator_loc: (37,2)-(37,3) = "*" │ │ └── expression: - │ │ @ CallNode (location: (35,3)-(35,7)) + │ │ @ CallNode (location: (37,3)-(37,7)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :args - │ │ ├── message_loc: (35,3)-(35,7) = "args" + │ │ ├── message_loc: (37,3)-(37,7) = "args" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── closing_loc: (35,7)-(35,8) = ")" + │ ├── closing_loc: (37,7)-(37,8) = ")" │ └── block: ∅ - ├── @ CallNode (location: (37,0)-(37,6)) + ├── @ CallNode (location: (39,0)-(39,6)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a - │ ├── message_loc: (37,0)-(37,1) = "a" + │ ├── message_loc: (39,0)-(39,1) = "a" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (37,2)-(37,6)) + │ │ @ ArgumentsNode (location: (39,2)-(39,6)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ CallNode (location: (37,2)-(37,3)) + │ │ ├── @ CallNode (location: (39,2)-(39,3)) │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b - │ │ │ ├── message_loc: (37,2)-(37,3) = "b" + │ │ │ ├── message_loc: (39,2)-(39,3) = "b" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── @ CallNode (location: (37,5)-(37,6)) + │ │ └── @ CallNode (location: (39,5)-(39,6)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :c - │ │ ├── message_loc: (37,5)-(37,6) = "c" + │ │ ├── message_loc: (39,5)-(39,6) = "c" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (39,0)-(39,8)) + ├── @ CallNode (location: (41,0)-(41,8)) │ ├── flags: ∅ │ ├── receiver: - │ │ @ CallNode (location: (39,0)-(39,1)) + │ │ @ CallNode (location: (41,0)-(41,1)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a - │ │ ├── message_loc: (39,0)-(39,1) = "a" + │ │ ├── message_loc: (41,0)-(41,1) = "a" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── call_operator_loc: (39,1)-(39,2) = "." + │ ├── call_operator_loc: (41,1)-(41,2) = "." │ ├── name: :b - │ ├── message_loc: (39,2)-(39,3) = "b" + │ ├── message_loc: (41,2)-(41,3) = "b" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (39,4)-(39,8)) + │ │ @ ArgumentsNode (location: (41,4)-(41,8)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ CallNode (location: (39,4)-(39,5)) + │ │ ├── @ CallNode (location: (41,4)-(41,5)) │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :c - │ │ │ ├── message_loc: (39,4)-(39,5) = "c" + │ │ │ ├── message_loc: (41,4)-(41,5) = "c" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── @ CallNode (location: (39,7)-(39,8)) + │ │ └── @ CallNode (location: (41,7)-(41,8)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :d - │ │ ├── message_loc: (39,7)-(39,8) = "d" + │ │ ├── message_loc: (41,7)-(41,8) = "d" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ MultiWriteNode (location: (41,0)-(41,23)) + ├── @ MultiWriteNode (location: (43,0)-(43,23)) │ ├── lefts: (length: 2) - │ │ ├── @ CallTargetNode (location: (41,0)-(41,7)) + │ │ ├── @ CallTargetNode (location: (43,0)-(43,7)) │ │ │ ├── flags: ∅ │ │ │ ├── receiver: - │ │ │ │ @ CallNode (location: (41,0)-(41,3)) + │ │ │ │ @ CallNode (location: (43,0)-(43,3)) │ │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :foo - │ │ │ │ ├── message_loc: (41,0)-(41,3) = "foo" + │ │ │ │ ├── message_loc: (43,0)-(43,3) = "foo" │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── arguments: ∅ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ - │ │ │ ├── call_operator_loc: (41,3)-(41,4) = "." + │ │ │ ├── call_operator_loc: (43,3)-(43,4) = "." │ │ │ ├── name: :foo= - │ │ │ └── message_loc: (41,4)-(41,7) = "foo" - │ │ └── @ CallTargetNode (location: (41,9)-(41,16)) + │ │ │ └── message_loc: (43,4)-(43,7) = "foo" + │ │ └── @ CallTargetNode (location: (43,9)-(43,16)) │ │ ├── flags: ∅ │ │ ├── receiver: - │ │ │ @ CallNode (location: (41,9)-(41,12)) + │ │ │ @ CallNode (location: (43,9)-(43,12)) │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :bar - │ │ │ ├── message_loc: (41,9)-(41,12) = "bar" + │ │ │ ├── message_loc: (43,9)-(43,12) = "bar" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ ├── call_operator_loc: (41,12)-(41,13) = "." + │ │ ├── call_operator_loc: (43,12)-(43,13) = "." │ │ ├── name: :bar= - │ │ └── message_loc: (41,13)-(41,16) = "bar" + │ │ └── message_loc: (43,13)-(43,16) = "bar" │ ├── rest: ∅ │ ├── rights: (length: 0) │ ├── lparen_loc: ∅ │ ├── rparen_loc: ∅ - │ ├── operator_loc: (41,17)-(41,18) = "=" + │ ├── operator_loc: (43,17)-(43,18) = "=" │ └── value: - │ @ ArrayNode (location: (41,19)-(41,23)) + │ @ ArrayNode (location: (43,19)-(43,23)) │ ├── flags: ∅ │ ├── elements: (length: 2) - │ │ ├── @ IntegerNode (location: (41,19)-(41,20)) + │ │ ├── @ IntegerNode (location: (43,19)-(43,20)) │ │ │ └── flags: decimal - │ │ └── @ IntegerNode (location: (41,22)-(41,23)) + │ │ └── @ IntegerNode (location: (43,22)-(43,23)) │ │ └── flags: decimal │ ├── opening_loc: ∅ │ └── closing_loc: ∅ - ├── @ CallNode (location: (43,0)-(43,4)) + ├── @ CallNode (location: (45,0)-(45,4)) │ ├── flags: safe_navigation │ ├── receiver: - │ │ @ CallNode (location: (43,0)-(43,1)) + │ │ @ CallNode (location: (45,0)-(45,1)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a - │ │ ├── message_loc: (43,0)-(43,1) = "a" + │ │ ├── message_loc: (45,0)-(45,1) = "a" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── call_operator_loc: (43,1)-(43,3) = "&." + │ ├── call_operator_loc: (45,1)-(45,3) = "&." │ ├── name: :b - │ ├── message_loc: (43,3)-(43,4) = "b" + │ ├── message_loc: (45,3)-(45,4) = "b" │ ├── opening_loc: ∅ │ ├── arguments: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (45,0)-(45,5)) + ├── @ CallNode (location: (47,0)-(47,5)) │ ├── flags: safe_navigation │ ├── receiver: - │ │ @ CallNode (location: (45,0)-(45,1)) + │ │ @ CallNode (location: (47,0)-(47,1)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a - │ │ ├── message_loc: (45,0)-(45,1) = "a" + │ │ ├── message_loc: (47,0)-(47,1) = "a" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── call_operator_loc: (45,1)-(45,3) = "&." + │ ├── call_operator_loc: (47,1)-(47,3) = "&." │ ├── name: :call │ ├── message_loc: ∅ - │ ├── opening_loc: (45,3)-(45,4) = "(" + │ ├── opening_loc: (47,3)-(47,4) = "(" │ ├── arguments: ∅ - │ ├── closing_loc: (45,4)-(45,5) = ")" + │ ├── closing_loc: (47,4)-(47,5) = ")" │ └── block: ∅ - ├── @ CallNode (location: (47,0)-(47,7)) + ├── @ CallNode (location: (49,0)-(49,7)) │ ├── flags: safe_navigation │ ├── receiver: - │ │ @ CallNode (location: (47,0)-(47,1)) + │ │ @ CallNode (location: (49,0)-(49,1)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a - │ │ ├── message_loc: (47,0)-(47,1) = "a" + │ │ ├── message_loc: (49,0)-(49,1) = "a" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── call_operator_loc: (47,1)-(47,3) = "&." + │ ├── call_operator_loc: (49,1)-(49,3) = "&." │ ├── name: :b - │ ├── message_loc: (47,3)-(47,4) = "b" - │ ├── opening_loc: (47,4)-(47,5) = "(" + │ ├── message_loc: (49,3)-(49,4) = "b" + │ ├── opening_loc: (49,4)-(49,5) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (47,5)-(47,6)) + │ │ @ ArgumentsNode (location: (49,5)-(49,6)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ CallNode (location: (47,5)-(47,6)) + │ │ └── @ CallNode (location: (49,5)-(49,6)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :c - │ │ ├── message_loc: (47,5)-(47,6) = "c" + │ │ ├── message_loc: (49,5)-(49,6) = "c" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── closing_loc: (47,6)-(47,7) = ")" + │ ├── closing_loc: (49,6)-(49,7) = ")" │ └── block: ∅ - ├── @ CallNode (location: (49,0)-(49,6)) + ├── @ CallNode (location: (51,0)-(51,6)) │ ├── flags: safe_navigation │ ├── receiver: - │ │ @ CallNode (location: (49,0)-(49,1)) + │ │ @ CallNode (location: (51,0)-(51,1)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a - │ │ ├── message_loc: (49,0)-(49,1) = "a" + │ │ ├── message_loc: (51,0)-(51,1) = "a" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── call_operator_loc: (49,1)-(49,3) = "&." + │ ├── call_operator_loc: (51,1)-(51,3) = "&." │ ├── name: :b - │ ├── message_loc: (49,3)-(49,4) = "b" - │ ├── opening_loc: (49,4)-(49,5) = "(" + │ ├── message_loc: (51,3)-(51,4) = "b" + │ ├── opening_loc: (51,4)-(51,5) = "(" │ ├── arguments: ∅ - │ ├── closing_loc: (49,5)-(49,6) = ")" + │ ├── closing_loc: (51,5)-(51,6) = ")" │ └── block: ∅ - ├── @ IfNode (location: (51,0)-(51,33)) - │ ├── if_keyword_loc: (51,11)-(51,13) = "if" + ├── @ IfNode (location: (53,0)-(53,33)) + │ ├── if_keyword_loc: (53,11)-(53,13) = "if" │ ├── predicate: - │ │ @ AndNode (location: (51,14)-(51,33)) + │ │ @ AndNode (location: (53,14)-(53,33)) │ │ ├── left: - │ │ │ @ OrNode (location: (51,14)-(51,25)) + │ │ │ @ OrNode (location: (53,14)-(53,25)) │ │ │ ├── left: - │ │ │ │ @ CallNode (location: (51,14)-(51,18)) + │ │ │ │ @ CallNode (location: (53,14)-(53,18)) │ │ │ │ ├── flags: ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :bar? - │ │ │ │ ├── message_loc: (51,14)-(51,18) = "bar?" + │ │ │ │ ├── message_loc: (53,14)-(53,18) = "bar?" │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── arguments: ∅ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ │ │ │ ├── right: - │ │ │ │ @ CallNode (location: (51,22)-(51,25)) + │ │ │ │ @ CallNode (location: (53,22)-(53,25)) │ │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :baz - │ │ │ │ ├── message_loc: (51,22)-(51,25) = "baz" + │ │ │ │ ├── message_loc: (53,22)-(53,25) = "baz" │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── arguments: ∅ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ - │ │ │ └── operator_loc: (51,19)-(51,21) = "or" + │ │ │ └── operator_loc: (53,19)-(53,21) = "or" │ │ ├── right: - │ │ │ @ CallNode (location: (51,30)-(51,33)) + │ │ │ @ CallNode (location: (53,30)-(53,33)) │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :qux - │ │ │ ├── message_loc: (51,30)-(51,33) = "qux" + │ │ │ ├── message_loc: (53,30)-(53,33) = "qux" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── operator_loc: (51,26)-(51,29) = "and" + │ │ └── operator_loc: (53,26)-(53,29) = "and" │ ├── then_keyword_loc: ∅ │ ├── statements: - │ │ @ StatementsNode (location: (51,0)-(51,10)) + │ │ @ StatementsNode (location: (53,0)-(53,10)) │ │ └── body: (length: 1) - │ │ └── @ CallNode (location: (51,0)-(51,10)) + │ │ └── @ CallNode (location: (53,0)-(53,10)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo - │ │ ├── message_loc: (51,0)-(51,3) = "foo" + │ │ ├── message_loc: (53,0)-(53,3) = "foo" │ │ ├── opening_loc: ∅ │ │ ├── arguments: - │ │ │ @ ArgumentsNode (location: (51,4)-(51,10)) + │ │ │ @ ArgumentsNode (location: (53,4)-(53,10)) │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 2) - │ │ │ ├── @ SymbolNode (location: (51,4)-(51,6)) + │ │ │ ├── @ SymbolNode (location: (53,4)-(53,6)) │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── opening_loc: (51,4)-(51,5) = ":" - │ │ │ │ ├── value_loc: (51,5)-(51,6) = "a" + │ │ │ │ ├── opening_loc: (53,4)-(53,5) = ":" + │ │ │ │ ├── value_loc: (53,5)-(53,6) = "a" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "a" - │ │ │ └── @ SymbolNode (location: (51,8)-(51,10)) + │ │ │ └── @ SymbolNode (location: (53,8)-(53,10)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (51,8)-(51,9) = ":" - │ │ │ ├── value_loc: (51,9)-(51,10) = "b" + │ │ │ ├── opening_loc: (53,8)-(53,9) = ":" + │ │ │ ├── value_loc: (53,9)-(53,10) = "b" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "b" │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── consequent: ∅ │ └── end_keyword_loc: ∅ - ├── @ CallNode (location: (53,0)-(56,1)) + ├── @ CallNode (location: (55,0)-(58,1)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (53,0)-(53,3) = "foo" - │ ├── opening_loc: (53,3)-(53,4) = "(" + │ ├── message_loc: (55,0)-(55,3) = "foo" + │ ├── opening_loc: (55,3)-(55,4) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (53,4)-(55,4)) + │ │ @ ArgumentsNode (location: (55,4)-(57,4)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ SymbolNode (location: (53,4)-(53,6)) + │ │ ├── @ SymbolNode (location: (55,4)-(55,6)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (53,4)-(53,5) = ":" - │ │ │ ├── value_loc: (53,5)-(53,6) = "a" + │ │ │ ├── opening_loc: (55,4)-(55,5) = ":" + │ │ │ ├── value_loc: (55,5)-(55,6) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" - │ │ └── @ SymbolNode (location: (55,2)-(55,4)) + │ │ └── @ SymbolNode (location: (57,2)-(57,4)) │ │ ├── flags: ∅ - │ │ ├── opening_loc: (55,2)-(55,3) = ":" - │ │ ├── value_loc: (55,3)-(55,4) = "b" + │ │ ├── opening_loc: (57,2)-(57,3) = ":" + │ │ ├── value_loc: (57,3)-(57,4) = "b" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "b" - │ ├── closing_loc: (56,0)-(56,1) = ")" + │ ├── closing_loc: (58,0)-(58,1) = ")" │ └── block: ∅ - ├── @ CallNode (location: (58,0)-(58,10)) + ├── @ CallNode (location: (60,0)-(60,10)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (58,0)-(58,3) = "foo" - │ ├── opening_loc: (58,3)-(58,4) = "(" + │ ├── message_loc: (60,0)-(60,3) = "foo" + │ ├── opening_loc: (60,3)-(60,4) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (58,4)-(58,9)) + │ │ @ ArgumentsNode (location: (60,4)-(60,9)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ SplatNode (location: (58,4)-(58,9)) - │ │ ├── operator_loc: (58,4)-(58,5) = "*" + │ │ └── @ SplatNode (location: (60,4)-(60,9)) + │ │ ├── operator_loc: (60,4)-(60,5) = "*" │ │ └── expression: - │ │ @ CallNode (location: (58,5)-(58,9)) + │ │ @ CallNode (location: (60,5)-(60,9)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :rest - │ │ ├── message_loc: (58,5)-(58,9) = "rest" + │ │ ├── message_loc: (60,5)-(60,9) = "rest" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── closing_loc: (58,9)-(58,10) = ")" + │ ├── closing_loc: (60,9)-(60,10) = ")" │ └── block: ∅ - ├── @ CallNode (location: (60,0)-(60,39)) + ├── @ CallNode (location: (62,0)-(62,39)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (60,0)-(60,3) = "foo" - │ ├── opening_loc: (60,3)-(60,4) = "(" + │ ├── message_loc: (62,0)-(62,3) = "foo" + │ ├── opening_loc: (62,3)-(62,4) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (60,4)-(60,32)) + │ │ @ ArgumentsNode (location: (62,4)-(62,32)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ SymbolNode (location: (60,4)-(60,6)) + │ │ ├── @ SymbolNode (location: (62,4)-(62,6)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (60,4)-(60,5) = ":" - │ │ │ ├── value_loc: (60,5)-(60,6) = "a" + │ │ │ ├── opening_loc: (62,4)-(62,5) = ":" + │ │ │ ├── value_loc: (62,5)-(62,6) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" - │ │ └── @ KeywordHashNode (location: (60,8)-(60,32)) + │ │ └── @ KeywordHashNode (location: (62,8)-(62,32)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 2) - │ │ ├── @ AssocNode (location: (60,8)-(60,22)) + │ │ ├── @ AssocNode (location: (62,8)-(62,22)) │ │ │ ├── key: - │ │ │ │ @ SymbolNode (location: (60,8)-(60,10)) + │ │ │ │ @ SymbolNode (location: (62,8)-(62,10)) │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── opening_loc: (60,8)-(60,9) = ":" - │ │ │ │ ├── value_loc: (60,9)-(60,10) = "h" + │ │ │ │ ├── opening_loc: (62,8)-(62,9) = ":" + │ │ │ │ ├── value_loc: (62,9)-(62,10) = "h" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "h" │ │ │ ├── value: - │ │ │ │ @ ArrayNode (location: (60,14)-(60,22)) + │ │ │ │ @ ArrayNode (location: (62,14)-(62,22)) │ │ │ │ ├── flags: ∅ │ │ │ │ ├── elements: (length: 2) - │ │ │ │ │ ├── @ SymbolNode (location: (60,15)-(60,17)) + │ │ │ │ │ ├── @ SymbolNode (location: (62,15)-(62,17)) │ │ │ │ │ │ ├── flags: ∅ - │ │ │ │ │ │ ├── opening_loc: (60,15)-(60,16) = ":" - │ │ │ │ │ │ ├── value_loc: (60,16)-(60,17) = "x" + │ │ │ │ │ │ ├── opening_loc: (62,15)-(62,16) = ":" + │ │ │ │ │ │ ├── value_loc: (62,16)-(62,17) = "x" │ │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ │ └── unescaped: "x" - │ │ │ │ │ └── @ SymbolNode (location: (60,19)-(60,21)) + │ │ │ │ │ └── @ SymbolNode (location: (62,19)-(62,21)) │ │ │ │ │ ├── flags: ∅ - │ │ │ │ │ ├── opening_loc: (60,19)-(60,20) = ":" - │ │ │ │ │ ├── value_loc: (60,20)-(60,21) = "y" + │ │ │ │ │ ├── opening_loc: (62,19)-(62,20) = ":" + │ │ │ │ │ ├── value_loc: (62,20)-(62,21) = "y" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "y" - │ │ │ │ ├── opening_loc: (60,14)-(60,15) = "[" - │ │ │ │ └── closing_loc: (60,21)-(60,22) = "]" - │ │ │ └── operator_loc: (60,11)-(60,13) = "=>" - │ │ └── @ AssocNode (location: (60,24)-(60,32)) + │ │ │ │ ├── opening_loc: (62,14)-(62,15) = "[" + │ │ │ │ └── closing_loc: (62,21)-(62,22) = "]" + │ │ │ └── operator_loc: (62,11)-(62,13) = "=>" + │ │ └── @ AssocNode (location: (62,24)-(62,32)) │ │ ├── key: - │ │ │ @ SymbolNode (location: (60,24)-(60,26)) + │ │ │ @ SymbolNode (location: (62,24)-(62,26)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (60,24)-(60,25) = ":" - │ │ │ ├── value_loc: (60,25)-(60,26) = "a" + │ │ │ ├── opening_loc: (62,24)-(62,25) = ":" + │ │ │ ├── value_loc: (62,25)-(62,26) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ ├── value: - │ │ │ @ SymbolNode (location: (60,30)-(60,32)) + │ │ │ @ SymbolNode (location: (62,30)-(62,32)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (60,30)-(60,31) = ":" - │ │ │ ├── value_loc: (60,31)-(60,32) = "b" + │ │ │ ├── opening_loc: (62,30)-(62,31) = ":" + │ │ │ ├── value_loc: (62,31)-(62,32) = "b" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "b" - │ │ └── operator_loc: (60,27)-(60,29) = "=>" - │ ├── closing_loc: (60,39)-(60,40) = ")" + │ │ └── operator_loc: (62,27)-(62,29) = "=>" + │ ├── closing_loc: (62,39)-(62,40) = ")" │ └── block: - │ @ BlockArgumentNode (location: (60,34)-(60,39)) + │ @ BlockArgumentNode (location: (62,34)-(62,39)) │ ├── expression: - │ │ @ SymbolNode (location: (60,35)-(60,39)) + │ │ @ SymbolNode (location: (62,35)-(62,39)) │ │ ├── flags: ∅ - │ │ ├── opening_loc: (60,35)-(60,36) = ":" - │ │ ├── value_loc: (60,36)-(60,39) = "bar" + │ │ ├── opening_loc: (62,35)-(62,36) = ":" + │ │ ├── value_loc: (62,36)-(62,39) = "bar" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "bar" - │ └── operator_loc: (60,34)-(60,35) = "&" - ├── @ CallNode (location: (62,0)-(62,49)) + │ └── operator_loc: (62,34)-(62,35) = "&" + ├── @ CallNode (location: (64,0)-(64,49)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :hi - │ ├── message_loc: (62,0)-(62,2) = "hi" + │ ├── message_loc: (64,0)-(64,2) = "hi" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (62,3)-(62,49)) + │ │ @ ArgumentsNode (location: (64,3)-(64,49)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ IntegerNode (location: (62,3)-(62,6)) + │ │ ├── @ IntegerNode (location: (64,3)-(64,6)) │ │ │ └── flags: decimal - │ │ └── @ HashNode (location: (62,8)-(62,49)) - │ │ ├── opening_loc: (62,8)-(62,9) = "{" + │ │ └── @ HashNode (location: (64,8)-(64,49)) + │ │ ├── opening_loc: (64,8)-(64,9) = "{" │ │ ├── elements: (length: 3) - │ │ │ ├── @ AssocNode (location: (62,10)-(62,27)) + │ │ │ ├── @ AssocNode (location: (64,10)-(64,27)) │ │ │ │ ├── key: - │ │ │ │ │ @ SymbolNode (location: (62,10)-(62,16)) + │ │ │ │ │ @ SymbolNode (location: (64,10)-(64,16)) │ │ │ │ │ ├── flags: ∅ - │ │ │ │ │ ├── opening_loc: (62,10)-(62,11) = ":" - │ │ │ │ │ ├── value_loc: (62,11)-(62,16) = "there" + │ │ │ │ │ ├── opening_loc: (64,10)-(64,11) = ":" + │ │ │ │ │ ├── value_loc: (64,11)-(64,16) = "there" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "there" │ │ │ │ ├── value: - │ │ │ │ │ @ SymbolNode (location: (62,20)-(62,27)) + │ │ │ │ │ @ SymbolNode (location: (64,20)-(64,27)) │ │ │ │ │ ├── flags: ∅ - │ │ │ │ │ ├── opening_loc: (62,20)-(62,21) = ":" - │ │ │ │ │ ├── value_loc: (62,21)-(62,27) = "friend" + │ │ │ │ │ ├── opening_loc: (64,20)-(64,21) = ":" + │ │ │ │ │ ├── value_loc: (64,21)-(64,27) = "friend" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "friend" - │ │ │ │ └── operator_loc: (62,17)-(62,19) = "=>" - │ │ │ ├── @ AssocSplatNode (location: (62,29)-(62,33)) + │ │ │ │ └── operator_loc: (64,17)-(64,19) = "=>" + │ │ │ ├── @ AssocSplatNode (location: (64,29)-(64,33)) │ │ │ │ ├── value: - │ │ │ │ │ @ HashNode (location: (62,31)-(62,33)) - │ │ │ │ │ ├── opening_loc: (62,31)-(62,32) = "{" + │ │ │ │ │ @ HashNode (location: (64,31)-(64,33)) + │ │ │ │ │ ├── opening_loc: (64,31)-(64,32) = "{" │ │ │ │ │ ├── elements: (length: 0) - │ │ │ │ │ └── closing_loc: (62,32)-(62,33) = "}" - │ │ │ │ └── operator_loc: (62,29)-(62,31) = "**" - │ │ │ └── @ AssocNode (location: (62,35)-(62,47)) + │ │ │ │ │ └── closing_loc: (64,32)-(64,33) = "}" + │ │ │ │ └── operator_loc: (64,29)-(64,31) = "**" + │ │ │ └── @ AssocNode (location: (64,35)-(64,47)) │ │ │ ├── key: - │ │ │ │ @ SymbolNode (location: (62,35)-(62,42)) + │ │ │ │ @ SymbolNode (location: (64,35)-(64,42)) │ │ │ │ ├── flags: ∅ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ ├── value_loc: (62,35)-(62,41) = "whatup" - │ │ │ │ ├── closing_loc: (62,41)-(62,42) = ":" + │ │ │ │ ├── value_loc: (64,35)-(64,41) = "whatup" + │ │ │ │ ├── closing_loc: (64,41)-(64,42) = ":" │ │ │ │ └── unescaped: "whatup" │ │ │ ├── value: - │ │ │ │ @ SymbolNode (location: (62,43)-(62,47)) + │ │ │ │ @ SymbolNode (location: (64,43)-(64,47)) │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── opening_loc: (62,43)-(62,44) = ":" - │ │ │ │ ├── value_loc: (62,44)-(62,47) = "dog" + │ │ │ │ ├── opening_loc: (64,43)-(64,44) = ":" + │ │ │ │ ├── value_loc: (64,44)-(64,47) = "dog" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "dog" │ │ │ └── operator_loc: ∅ - │ │ └── closing_loc: (62,48)-(62,49) = "}" + │ │ └── closing_loc: (64,48)-(64,49) = "}" │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (64,0)-(64,36)) + ├── @ CallNode (location: (66,0)-(66,36)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (64,0)-(64,3) = "foo" + │ ├── message_loc: (66,0)-(66,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (64,4)-(64,15)) + │ │ @ ArgumentsNode (location: (66,4)-(66,15)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ SymbolNode (location: (64,4)-(64,6)) + │ │ ├── @ SymbolNode (location: (66,4)-(66,6)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (64,4)-(64,5) = ":" - │ │ │ ├── value_loc: (64,5)-(64,6) = "a" + │ │ │ ├── opening_loc: (66,4)-(66,5) = ":" + │ │ │ ├── value_loc: (66,5)-(66,6) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" - │ │ └── @ KeywordHashNode (location: (64,8)-(64,15)) + │ │ └── @ KeywordHashNode (location: (66,8)-(66,15)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) - │ │ └── @ AssocNode (location: (64,8)-(64,15)) + │ │ └── @ AssocNode (location: (66,8)-(66,15)) │ │ ├── key: - │ │ │ @ SymbolNode (location: (64,8)-(64,10)) + │ │ │ @ SymbolNode (location: (66,8)-(66,10)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── value_loc: (64,8)-(64,9) = "b" - │ │ │ ├── closing_loc: (64,9)-(64,10) = ":" + │ │ │ ├── value_loc: (66,8)-(66,9) = "b" + │ │ │ ├── closing_loc: (66,9)-(66,10) = ":" │ │ │ └── unescaped: "b" │ │ ├── value: - │ │ │ @ TrueNode (location: (64,11)-(64,15)) + │ │ │ @ TrueNode (location: (66,11)-(66,15)) │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: - │ @ BlockNode (location: (64,16)-(64,36)) + │ @ BlockNode (location: (66,16)-(66,36)) │ ├── locals: [:a, :b] │ ├── locals_body_index: 2 │ ├── parameters: - │ │ @ BlockParametersNode (location: (64,19)-(64,25)) + │ │ @ BlockParametersNode (location: (66,19)-(66,25)) │ │ ├── parameters: - │ │ │ @ ParametersNode (location: (64,20)-(64,24)) + │ │ │ @ ParametersNode (location: (66,20)-(66,24)) │ │ │ ├── requireds: (length: 2) - │ │ │ │ ├── @ RequiredParameterNode (location: (64,20)-(64,21)) + │ │ │ │ ├── @ RequiredParameterNode (location: (66,20)-(66,21)) │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :a - │ │ │ │ └── @ RequiredParameterNode (location: (64,23)-(64,24)) + │ │ │ │ └── @ RequiredParameterNode (location: (66,23)-(66,24)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── optionals: (length: 0) @@ -950,513 +975,486 @@ │ │ │ ├── keyword_rest: ∅ │ │ │ └── block: ∅ │ │ ├── locals: (length: 0) - │ │ ├── opening_loc: (64,19)-(64,20) = "|" - │ │ └── closing_loc: (64,24)-(64,25) = "|" + │ │ ├── opening_loc: (66,19)-(66,20) = "|" + │ │ └── closing_loc: (66,24)-(66,25) = "|" │ ├── body: - │ │ @ StatementsNode (location: (64,26)-(64,32)) + │ │ @ StatementsNode (location: (66,26)-(66,32)) │ │ └── body: (length: 1) - │ │ └── @ CallNode (location: (64,26)-(64,32)) + │ │ └── @ CallNode (location: (66,26)-(66,32)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :puts - │ │ ├── message_loc: (64,26)-(64,30) = "puts" + │ │ ├── message_loc: (66,26)-(66,30) = "puts" │ │ ├── opening_loc: ∅ │ │ ├── arguments: - │ │ │ @ ArgumentsNode (location: (64,31)-(64,32)) + │ │ │ @ ArgumentsNode (location: (66,31)-(66,32)) │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) - │ │ │ └── @ LocalVariableReadNode (location: (64,31)-(64,32)) + │ │ │ └── @ LocalVariableReadNode (location: (66,31)-(66,32)) │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── opening_loc: (64,16)-(64,18) = "do" - │ └── closing_loc: (64,33)-(64,36) = "end" - ├── @ CallNode (location: (66,0)-(66,17)) + │ ├── opening_loc: (66,16)-(66,18) = "do" + │ └── closing_loc: (66,33)-(66,36) = "end" + ├── @ CallNode (location: (68,0)-(68,17)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :hi - │ ├── message_loc: (66,0)-(66,2) = "hi" + │ ├── message_loc: (68,0)-(68,2) = "hi" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (66,3)-(66,17)) + │ │ @ ArgumentsNode (location: (68,3)-(68,17)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ KeywordHashNode (location: (66,3)-(66,17)) + │ │ └── @ KeywordHashNode (location: (68,3)-(68,17)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) - │ │ └── @ AssocNode (location: (66,3)-(66,17)) + │ │ └── @ AssocNode (location: (68,3)-(68,17)) │ │ ├── key: - │ │ │ @ SymbolNode (location: (66,3)-(66,9)) + │ │ │ @ SymbolNode (location: (68,3)-(68,9)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── value_loc: (66,3)-(66,8) = "there" - │ │ │ ├── closing_loc: (66,8)-(66,9) = ":" + │ │ │ ├── value_loc: (68,3)-(68,8) = "there" + │ │ │ ├── closing_loc: (68,8)-(68,9) = ":" │ │ │ └── unescaped: "there" │ │ ├── value: - │ │ │ @ SymbolNode (location: (66,10)-(66,17)) + │ │ │ @ SymbolNode (location: (68,10)-(68,17)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (66,10)-(66,11) = ":" - │ │ │ ├── value_loc: (66,11)-(66,17) = "friend" + │ │ │ ├── opening_loc: (68,10)-(68,11) = ":" + │ │ │ ├── value_loc: (68,11)-(68,17) = "friend" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "friend" │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (68,0)-(68,40)) + ├── @ CallNode (location: (70,0)-(70,40)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :hi - │ ├── message_loc: (68,0)-(68,2) = "hi" + │ ├── message_loc: (70,0)-(70,2) = "hi" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (68,3)-(68,40)) + │ │ @ ArgumentsNode (location: (70,3)-(70,40)) │ │ ├── flags: contains_keyword_splat │ │ └── arguments: (length: 1) - │ │ └── @ KeywordHashNode (location: (68,3)-(68,40)) + │ │ └── @ KeywordHashNode (location: (70,3)-(70,40)) │ │ ├── flags: ∅ │ │ └── elements: (length: 3) - │ │ ├── @ AssocNode (location: (68,3)-(68,20)) + │ │ ├── @ AssocNode (location: (70,3)-(70,20)) │ │ │ ├── key: - │ │ │ │ @ SymbolNode (location: (68,3)-(68,9)) + │ │ │ │ @ SymbolNode (location: (70,3)-(70,9)) │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── opening_loc: (68,3)-(68,4) = ":" - │ │ │ │ ├── value_loc: (68,4)-(68,9) = "there" + │ │ │ │ ├── opening_loc: (70,3)-(70,4) = ":" + │ │ │ │ ├── value_loc: (70,4)-(70,9) = "there" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "there" │ │ │ ├── value: - │ │ │ │ @ SymbolNode (location: (68,13)-(68,20)) + │ │ │ │ @ SymbolNode (location: (70,13)-(70,20)) │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── opening_loc: (68,13)-(68,14) = ":" - │ │ │ │ ├── value_loc: (68,14)-(68,20) = "friend" + │ │ │ │ ├── opening_loc: (70,13)-(70,14) = ":" + │ │ │ │ ├── value_loc: (70,14)-(70,20) = "friend" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "friend" - │ │ │ └── operator_loc: (68,10)-(68,12) = "=>" - │ │ ├── @ AssocSplatNode (location: (68,22)-(68,26)) + │ │ │ └── operator_loc: (70,10)-(70,12) = "=>" + │ │ ├── @ AssocSplatNode (location: (70,22)-(70,26)) │ │ │ ├── value: - │ │ │ │ @ HashNode (location: (68,24)-(68,26)) - │ │ │ │ ├── opening_loc: (68,24)-(68,25) = "{" + │ │ │ │ @ HashNode (location: (70,24)-(70,26)) + │ │ │ │ ├── opening_loc: (70,24)-(70,25) = "{" │ │ │ │ ├── elements: (length: 0) - │ │ │ │ └── closing_loc: (68,25)-(68,26) = "}" - │ │ │ └── operator_loc: (68,22)-(68,24) = "**" - │ │ └── @ AssocNode (location: (68,28)-(68,40)) + │ │ │ │ └── closing_loc: (70,25)-(70,26) = "}" + │ │ │ └── operator_loc: (70,22)-(70,24) = "**" + │ │ └── @ AssocNode (location: (70,28)-(70,40)) │ │ ├── key: - │ │ │ @ SymbolNode (location: (68,28)-(68,35)) + │ │ │ @ SymbolNode (location: (70,28)-(70,35)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── value_loc: (68,28)-(68,34) = "whatup" - │ │ │ ├── closing_loc: (68,34)-(68,35) = ":" + │ │ │ ├── value_loc: (70,28)-(70,34) = "whatup" + │ │ │ ├── closing_loc: (70,34)-(70,35) = ":" │ │ │ └── unescaped: "whatup" │ │ ├── value: - │ │ │ @ SymbolNode (location: (68,36)-(68,40)) + │ │ │ @ SymbolNode (location: (70,36)-(70,40)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (68,36)-(68,37) = ":" - │ │ │ ├── value_loc: (68,37)-(68,40) = "dog" + │ │ │ ├── opening_loc: (70,36)-(70,37) = ":" + │ │ │ ├── value_loc: (70,37)-(70,40) = "dog" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "dog" │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (70,0)-(70,41)) + ├── @ CallNode (location: (72,0)-(72,41)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :hi - │ ├── message_loc: (70,0)-(70,2) = "hi" - │ ├── opening_loc: (70,2)-(70,3) = "(" + │ ├── message_loc: (72,0)-(72,2) = "hi" + │ ├── opening_loc: (72,2)-(72,3) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (70,3)-(70,40)) + │ │ @ ArgumentsNode (location: (72,3)-(72,40)) │ │ ├── flags: contains_keyword_splat │ │ └── arguments: (length: 1) - │ │ └── @ KeywordHashNode (location: (70,3)-(70,40)) + │ │ └── @ KeywordHashNode (location: (72,3)-(72,40)) │ │ ├── flags: ∅ │ │ └── elements: (length: 3) - │ │ ├── @ AssocNode (location: (70,3)-(70,20)) + │ │ ├── @ AssocNode (location: (72,3)-(72,20)) │ │ │ ├── key: - │ │ │ │ @ SymbolNode (location: (70,3)-(70,9)) + │ │ │ │ @ SymbolNode (location: (72,3)-(72,9)) │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── opening_loc: (70,3)-(70,4) = ":" - │ │ │ │ ├── value_loc: (70,4)-(70,9) = "there" + │ │ │ │ ├── opening_loc: (72,3)-(72,4) = ":" + │ │ │ │ ├── value_loc: (72,4)-(72,9) = "there" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "there" │ │ │ ├── value: - │ │ │ │ @ SymbolNode (location: (70,13)-(70,20)) + │ │ │ │ @ SymbolNode (location: (72,13)-(72,20)) │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── opening_loc: (70,13)-(70,14) = ":" - │ │ │ │ ├── value_loc: (70,14)-(70,20) = "friend" + │ │ │ │ ├── opening_loc: (72,13)-(72,14) = ":" + │ │ │ │ ├── value_loc: (72,14)-(72,20) = "friend" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "friend" - │ │ │ └── operator_loc: (70,10)-(70,12) = "=>" - │ │ ├── @ AssocSplatNode (location: (70,22)-(70,26)) + │ │ │ └── operator_loc: (72,10)-(72,12) = "=>" + │ │ ├── @ AssocSplatNode (location: (72,22)-(72,26)) │ │ │ ├── value: - │ │ │ │ @ HashNode (location: (70,24)-(70,26)) - │ │ │ │ ├── opening_loc: (70,24)-(70,25) = "{" + │ │ │ │ @ HashNode (location: (72,24)-(72,26)) + │ │ │ │ ├── opening_loc: (72,24)-(72,25) = "{" │ │ │ │ ├── elements: (length: 0) - │ │ │ │ └── closing_loc: (70,25)-(70,26) = "}" - │ │ │ └── operator_loc: (70,22)-(70,24) = "**" - │ │ └── @ AssocNode (location: (70,28)-(70,40)) + │ │ │ │ └── closing_loc: (72,25)-(72,26) = "}" + │ │ │ └── operator_loc: (72,22)-(72,24) = "**" + │ │ └── @ AssocNode (location: (72,28)-(72,40)) │ │ ├── key: - │ │ │ @ SymbolNode (location: (70,28)-(70,35)) + │ │ │ @ SymbolNode (location: (72,28)-(72,35)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── value_loc: (70,28)-(70,34) = "whatup" - │ │ │ ├── closing_loc: (70,34)-(70,35) = ":" + │ │ │ ├── value_loc: (72,28)-(72,34) = "whatup" + │ │ │ ├── closing_loc: (72,34)-(72,35) = ":" │ │ │ └── unescaped: "whatup" │ │ ├── value: - │ │ │ @ SymbolNode (location: (70,36)-(70,40)) + │ │ │ @ SymbolNode (location: (72,36)-(72,40)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (70,36)-(70,37) = ":" - │ │ │ ├── value_loc: (70,37)-(70,40) = "dog" + │ │ │ ├── opening_loc: (72,36)-(72,37) = ":" + │ │ │ ├── value_loc: (72,37)-(72,40) = "dog" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "dog" │ │ └── operator_loc: ∅ - │ ├── closing_loc: (70,40)-(70,41) = ")" + │ ├── closing_loc: (72,40)-(72,41) = ")" │ └── block: ∅ - ├── @ CallNode (location: (72,0)-(72,35)) + ├── @ CallNode (location: (74,0)-(74,35)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (72,0)-(72,3) = "foo" - │ ├── opening_loc: (72,3)-(72,4) = "(" + │ ├── message_loc: (74,0)-(74,3) = "foo" + │ ├── opening_loc: (74,3)-(74,4) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (72,4)-(72,26)) + │ │ @ ArgumentsNode (location: (74,4)-(74,26)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ HashNode (location: (72,4)-(72,26)) - │ │ ├── opening_loc: (72,4)-(72,5) = "{" + │ │ └── @ HashNode (location: (74,4)-(74,26)) + │ │ ├── opening_loc: (74,4)-(74,5) = "{" │ │ ├── elements: (length: 2) - │ │ │ ├── @ AssocNode (location: (72,6)-(72,13)) + │ │ │ ├── @ AssocNode (location: (74,6)-(74,13)) │ │ │ │ ├── key: - │ │ │ │ │ @ SymbolNode (location: (72,6)-(72,8)) + │ │ │ │ │ @ SymbolNode (location: (74,6)-(74,8)) │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ │ ├── value_loc: (72,6)-(72,7) = "a" - │ │ │ │ │ ├── closing_loc: (72,7)-(72,8) = ":" + │ │ │ │ │ ├── value_loc: (74,6)-(74,7) = "a" + │ │ │ │ │ ├── closing_loc: (74,7)-(74,8) = ":" │ │ │ │ │ └── unescaped: "a" │ │ │ │ ├── value: - │ │ │ │ │ @ TrueNode (location: (72,9)-(72,13)) + │ │ │ │ │ @ TrueNode (location: (74,9)-(74,13)) │ │ │ │ └── operator_loc: ∅ - │ │ │ └── @ AssocNode (location: (72,15)-(72,23)) + │ │ │ └── @ AssocNode (location: (74,15)-(74,23)) │ │ │ ├── key: - │ │ │ │ @ SymbolNode (location: (72,15)-(72,17)) + │ │ │ │ @ SymbolNode (location: (74,15)-(74,17)) │ │ │ │ ├── flags: ∅ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ ├── value_loc: (72,15)-(72,16) = "b" - │ │ │ │ ├── closing_loc: (72,16)-(72,17) = ":" + │ │ │ │ ├── value_loc: (74,15)-(74,16) = "b" + │ │ │ │ ├── closing_loc: (74,16)-(74,17) = ":" │ │ │ │ └── unescaped: "b" │ │ │ ├── value: - │ │ │ │ @ FalseNode (location: (72,18)-(72,23)) + │ │ │ │ @ FalseNode (location: (74,18)-(74,23)) │ │ │ └── operator_loc: ∅ - │ │ └── closing_loc: (72,25)-(72,26) = "}" - │ ├── closing_loc: (72,35)-(72,36) = ")" + │ │ └── closing_loc: (74,25)-(74,26) = "}" + │ ├── closing_loc: (74,35)-(74,36) = ")" │ └── block: - │ @ BlockArgumentNode (location: (72,28)-(72,35)) + │ @ BlockArgumentNode (location: (74,28)-(74,35)) │ ├── expression: - │ │ @ SymbolNode (location: (72,29)-(72,35)) + │ │ @ SymbolNode (location: (74,29)-(74,35)) │ │ ├── flags: ∅ - │ │ ├── opening_loc: (72,29)-(72,30) = ":" - │ │ ├── value_loc: (72,30)-(72,35) = "block" + │ │ ├── opening_loc: (74,29)-(74,30) = ":" + │ │ ├── value_loc: (74,30)-(74,35) = "block" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "block" - │ └── operator_loc: (72,28)-(72,29) = "&" - ├── @ CallNode (location: (74,0)-(74,20)) + │ └── operator_loc: (74,28)-(74,29) = "&" + ├── @ CallNode (location: (76,0)-(76,20)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :hi - │ ├── message_loc: (74,0)-(74,2) = "hi" + │ ├── message_loc: (76,0)-(76,2) = "hi" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (74,3)-(74,20)) + │ │ @ ArgumentsNode (location: (76,3)-(76,20)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ KeywordHashNode (location: (74,3)-(74,20)) + │ │ └── @ KeywordHashNode (location: (76,3)-(76,20)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) - │ │ └── @ AssocNode (location: (74,3)-(74,20)) + │ │ └── @ AssocNode (location: (76,3)-(76,20)) │ │ ├── key: - │ │ │ @ SymbolNode (location: (74,3)-(74,9)) + │ │ │ @ SymbolNode (location: (76,3)-(76,9)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (74,3)-(74,4) = ":" - │ │ │ ├── value_loc: (74,4)-(74,9) = "there" + │ │ │ ├── opening_loc: (76,3)-(76,4) = ":" + │ │ │ ├── value_loc: (76,4)-(76,9) = "there" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "there" │ │ ├── value: - │ │ │ @ SymbolNode (location: (74,13)-(74,20)) + │ │ │ @ SymbolNode (location: (76,13)-(76,20)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (74,13)-(74,14) = ":" - │ │ │ ├── value_loc: (74,14)-(74,20) = "friend" + │ │ │ ├── opening_loc: (76,13)-(76,14) = ":" + │ │ │ ├── value_loc: (76,14)-(76,20) = "friend" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "friend" - │ │ └── operator_loc: (74,10)-(74,12) = "=>" + │ │ └── operator_loc: (76,10)-(76,12) = "=>" │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (76,0)-(78,1)) + ├── @ CallNode (location: (78,0)-(80,1)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (76,0)-(76,3) = "foo" - │ ├── opening_loc: (76,3)-(76,4) = "(" + │ ├── message_loc: (78,0)-(78,3) = "foo" + │ ├── opening_loc: (78,3)-(78,4) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (76,4)-(77,2)) + │ │ @ ArgumentsNode (location: (78,4)-(79,2)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ SymbolNode (location: (76,4)-(76,6)) + │ │ ├── @ SymbolNode (location: (78,4)-(78,6)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (76,4)-(76,5) = ":" - │ │ │ ├── value_loc: (76,5)-(76,6) = "a" + │ │ │ ├── opening_loc: (78,4)-(78,5) = ":" + │ │ │ ├── value_loc: (78,5)-(78,6) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" - │ │ └── @ SymbolNode (location: (77,0)-(77,2)) + │ │ └── @ SymbolNode (location: (79,0)-(79,2)) │ │ ├── flags: ∅ - │ │ ├── opening_loc: (77,0)-(77,1) = ":" - │ │ ├── value_loc: (77,1)-(77,2) = "b" + │ │ ├── opening_loc: (79,0)-(79,1) = ":" + │ │ ├── value_loc: (79,1)-(79,2) = "b" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "b" - │ ├── closing_loc: (78,0)-(78,1) = ")" + │ ├── closing_loc: (80,0)-(80,1) = ")" │ └── block: ∅ - ├── @ CallNode (location: (80,0)-(83,1)) + ├── @ CallNode (location: (82,0)-(85,1)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (80,0)-(80,3) = "foo" - │ ├── opening_loc: (80,3)-(80,4) = "(" + │ ├── message_loc: (82,0)-(82,3) = "foo" + │ ├── opening_loc: (82,3)-(82,4) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (81,0)-(82,5)) + │ │ @ ArgumentsNode (location: (83,0)-(84,5)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ SymbolNode (location: (81,0)-(81,2)) + │ │ ├── @ SymbolNode (location: (83,0)-(83,2)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (81,0)-(81,1) = ":" - │ │ │ ├── value_loc: (81,1)-(81,2) = "a" + │ │ │ ├── opening_loc: (83,0)-(83,1) = ":" + │ │ │ ├── value_loc: (83,1)-(83,2) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" - │ │ └── @ KeywordHashNode (location: (82,0)-(82,5)) + │ │ └── @ KeywordHashNode (location: (84,0)-(84,5)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) - │ │ └── @ AssocNode (location: (82,0)-(82,5)) + │ │ └── @ AssocNode (location: (84,0)-(84,5)) │ │ ├── key: - │ │ │ @ SymbolNode (location: (82,0)-(82,2)) + │ │ │ @ SymbolNode (location: (84,0)-(84,2)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── value_loc: (82,0)-(82,1) = "b" - │ │ │ ├── closing_loc: (82,1)-(82,2) = ":" + │ │ │ ├── value_loc: (84,0)-(84,1) = "b" + │ │ │ ├── closing_loc: (84,1)-(84,2) = ":" │ │ │ └── unescaped: "b" │ │ ├── value: - │ │ │ @ SymbolNode (location: (82,3)-(82,5)) + │ │ │ @ SymbolNode (location: (84,3)-(84,5)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (82,3)-(82,4) = ":" - │ │ │ ├── value_loc: (82,4)-(82,5) = "c" + │ │ │ ├── opening_loc: (84,3)-(84,4) = ":" + │ │ │ ├── value_loc: (84,4)-(84,5) = "c" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "c" │ │ └── operator_loc: ∅ - │ ├── closing_loc: (83,0)-(83,1) = ")" + │ ├── closing_loc: (85,0)-(85,1) = ")" │ └── block: ∅ - ├── @ CallNode (location: (85,0)-(85,11)) + ├── @ CallNode (location: (87,0)-(87,11)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (85,0)-(85,3) = "foo" + │ ├── message_loc: (87,0)-(87,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: ∅ │ ├── closing_loc: ∅ │ └── block: - │ @ BlockArgumentNode (location: (85,4)-(85,11)) + │ @ BlockArgumentNode (location: (87,4)-(87,11)) │ ├── expression: - │ │ @ SymbolNode (location: (85,5)-(85,11)) + │ │ @ SymbolNode (location: (87,5)-(87,11)) │ │ ├── flags: ∅ - │ │ ├── opening_loc: (85,5)-(85,6) = ":" - │ │ ├── value_loc: (85,6)-(85,11) = "block" + │ │ ├── opening_loc: (87,5)-(87,6) = ":" + │ │ ├── value_loc: (87,6)-(87,11) = "block" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "block" - │ └── operator_loc: (85,4)-(85,5) = "&" - ├── @ CallNode (location: (87,0)-(87,30)) + │ └── operator_loc: (87,4)-(87,5) = "&" + ├── @ CallNode (location: (89,0)-(89,30)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (87,0)-(87,3) = "foo" + │ ├── message_loc: (89,0)-(89,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (87,4)-(87,21)) + │ │ @ ArgumentsNode (location: (89,4)-(89,21)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ KeywordHashNode (location: (87,4)-(87,21)) + │ │ └── @ KeywordHashNode (location: (89,4)-(89,21)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 2) - │ │ ├── @ AssocNode (location: (87,4)-(87,11)) + │ │ ├── @ AssocNode (location: (89,4)-(89,11)) │ │ │ ├── key: - │ │ │ │ @ SymbolNode (location: (87,4)-(87,6)) + │ │ │ │ @ SymbolNode (location: (89,4)-(89,6)) │ │ │ │ ├── flags: ∅ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ ├── value_loc: (87,4)-(87,5) = "a" - │ │ │ │ ├── closing_loc: (87,5)-(87,6) = ":" + │ │ │ │ ├── value_loc: (89,4)-(89,5) = "a" + │ │ │ │ ├── closing_loc: (89,5)-(89,6) = ":" │ │ │ │ └── unescaped: "a" │ │ │ ├── value: - │ │ │ │ @ TrueNode (location: (87,7)-(87,11)) + │ │ │ │ @ TrueNode (location: (89,7)-(89,11)) │ │ │ └── operator_loc: ∅ - │ │ └── @ AssocNode (location: (87,13)-(87,21)) + │ │ └── @ AssocNode (location: (89,13)-(89,21)) │ │ ├── key: - │ │ │ @ SymbolNode (location: (87,13)-(87,15)) + │ │ │ @ SymbolNode (location: (89,13)-(89,15)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── value_loc: (87,13)-(87,14) = "b" - │ │ │ ├── closing_loc: (87,14)-(87,15) = ":" + │ │ │ ├── value_loc: (89,13)-(89,14) = "b" + │ │ │ ├── closing_loc: (89,14)-(89,15) = ":" │ │ │ └── unescaped: "b" │ │ ├── value: - │ │ │ @ FalseNode (location: (87,16)-(87,21)) + │ │ │ @ FalseNode (location: (89,16)-(89,21)) │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: - │ @ BlockArgumentNode (location: (87,23)-(87,30)) + │ @ BlockArgumentNode (location: (89,23)-(89,30)) │ ├── expression: - │ │ @ SymbolNode (location: (87,24)-(87,30)) + │ │ @ SymbolNode (location: (89,24)-(89,30)) │ │ ├── flags: ∅ - │ │ ├── opening_loc: (87,24)-(87,25) = ":" - │ │ ├── value_loc: (87,25)-(87,30) = "block" + │ │ ├── opening_loc: (89,24)-(89,25) = ":" + │ │ ├── value_loc: (89,25)-(89,30) = "block" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "block" - │ └── operator_loc: (87,23)-(87,24) = "&" - ├── @ CallNode (location: (89,0)-(89,21)) + │ └── operator_loc: (89,23)-(89,24) = "&" + ├── @ CallNode (location: (91,0)-(91,21)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :some_func - │ ├── message_loc: (89,0)-(89,9) = "some_func" + │ ├── message_loc: (91,0)-(91,9) = "some_func" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (89,10)-(89,21)) + │ │ @ ArgumentsNode (location: (91,10)-(91,21)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ IntegerNode (location: (89,10)-(89,11)) + │ │ ├── @ IntegerNode (location: (91,10)-(91,11)) │ │ │ └── flags: decimal - │ │ └── @ KeywordHashNode (location: (89,13)-(89,21)) + │ │ └── @ KeywordHashNode (location: (91,13)-(91,21)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) - │ │ └── @ AssocNode (location: (89,13)-(89,21)) + │ │ └── @ AssocNode (location: (91,13)-(91,21)) │ │ ├── key: - │ │ │ @ SymbolNode (location: (89,13)-(89,19)) + │ │ │ @ SymbolNode (location: (91,13)-(91,19)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── value_loc: (89,13)-(89,18) = "kwarg" - │ │ │ ├── closing_loc: (89,18)-(89,19) = ":" + │ │ │ ├── value_loc: (91,13)-(91,18) = "kwarg" + │ │ │ ├── closing_loc: (91,18)-(91,19) = ":" │ │ │ └── unescaped: "kwarg" │ │ ├── value: - │ │ │ @ IntegerNode (location: (89,20)-(89,21)) + │ │ │ @ IntegerNode (location: (91,20)-(91,21)) │ │ │ └── flags: decimal │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (91,0)-(91,18)) + ├── @ CallNode (location: (93,0)-(93,18)) │ ├── flags: ∅ │ ├── receiver: - │ │ @ ConstantReadNode (location: (91,0)-(91,6)) + │ │ @ ConstantReadNode (location: (93,0)-(93,6)) │ │ └── name: :Kernel - │ ├── call_operator_loc: (91,6)-(91,7) = "." + │ ├── call_operator_loc: (93,6)-(93,7) = "." │ ├── name: :Integer - │ ├── message_loc: (91,7)-(91,14) = "Integer" - │ ├── opening_loc: (91,14)-(91,15) = "(" + │ ├── message_loc: (93,7)-(93,14) = "Integer" + │ ├── opening_loc: (93,14)-(93,15) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (91,15)-(91,17)) + │ │ @ ArgumentsNode (location: (93,15)-(93,17)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ IntegerNode (location: (91,15)-(91,17)) + │ │ └── @ IntegerNode (location: (93,15)-(93,17)) │ │ └── flags: decimal - │ ├── closing_loc: (91,17)-(91,18) = ")" + │ ├── closing_loc: (93,17)-(93,18) = ")" │ └── block: ∅ - ├── @ CallNode (location: (93,0)-(93,10)) + ├── @ CallNode (location: (95,0)-(95,10)) │ ├── flags: ∅ │ ├── receiver: - │ │ @ CallNode (location: (93,0)-(93,1)) + │ │ @ CallNode (location: (95,0)-(95,1)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :x - │ │ ├── message_loc: (93,0)-(93,1) = "x" + │ │ ├── message_loc: (95,0)-(95,1) = "x" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── call_operator_loc: (93,1)-(93,2) = "." + │ ├── call_operator_loc: (95,1)-(95,2) = "." │ ├── name: :each - │ ├── message_loc: (93,2)-(93,6) = "each" + │ ├── message_loc: (95,2)-(95,6) = "each" │ ├── opening_loc: ∅ │ ├── arguments: ∅ │ ├── closing_loc: ∅ │ └── block: - │ @ BlockNode (location: (93,7)-(93,10)) + │ @ BlockNode (location: (95,7)-(95,10)) │ ├── locals: [] │ ├── locals_body_index: 0 │ ├── parameters: ∅ │ ├── body: ∅ - │ ├── opening_loc: (93,7)-(93,8) = "{" - │ └── closing_loc: (93,9)-(93,10) = "}" - ├── @ CallNode (location: (95,0)-(95,14)) + │ ├── opening_loc: (95,7)-(95,8) = "{" + │ └── closing_loc: (95,9)-(95,10) = "}" + ├── @ CallNode (location: (97,0)-(97,14)) │ ├── flags: ∅ │ ├── receiver: - │ │ @ CallNode (location: (95,0)-(95,3)) + │ │ @ CallNode (location: (97,0)-(97,3)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo - │ │ ├── message_loc: (95,0)-(95,3) = "foo" + │ │ ├── message_loc: (97,0)-(97,3) = "foo" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── call_operator_loc: (95,3)-(95,4) = "." + │ ├── call_operator_loc: (97,3)-(97,4) = "." │ ├── name: :map - │ ├── message_loc: (95,4)-(95,7) = "map" + │ ├── message_loc: (97,4)-(97,7) = "map" │ ├── opening_loc: ∅ │ ├── arguments: ∅ │ ├── closing_loc: ∅ │ └── block: - │ @ BlockNode (location: (95,8)-(95,14)) + │ @ BlockNode (location: (97,8)-(97,14)) │ ├── locals: [] │ ├── locals_body_index: 0 │ ├── parameters: ∅ │ ├── body: - │ │ @ StatementsNode (location: (95,10)-(95,12)) + │ │ @ StatementsNode (location: (97,10)-(97,12)) │ │ └── body: (length: 1) - │ │ └── @ BackReferenceReadNode (location: (95,10)-(95,12)) + │ │ └── @ BackReferenceReadNode (location: (97,10)-(97,12)) │ │ └── name: :$& - │ ├── opening_loc: (95,8)-(95,9) = "{" - │ └── closing_loc: (95,13)-(95,14) = "}" - ├── @ CallNode (location: (97,0)-(97,12)) - │ ├── flags: ∅ - │ ├── receiver: - │ │ @ ConstantPathNode (location: (97,0)-(97,4)) - │ │ ├── parent: - │ │ │ @ ConstantReadNode (location: (97,0)-(97,1)) - │ │ │ └── name: :A - │ │ ├── child: - │ │ │ @ ConstantReadNode (location: (97,3)-(97,4)) - │ │ │ └── name: :B - │ │ └── delimiter_loc: (97,1)-(97,3) = "::" - │ ├── call_operator_loc: (97,4)-(97,6) = "::" - │ ├── name: :C - │ ├── message_loc: (97,6)-(97,7) = "C" - │ ├── opening_loc: ∅ - │ ├── arguments: - │ │ @ ArgumentsNode (location: (97,8)-(97,12)) - │ │ ├── flags: ∅ - │ │ └── arguments: (length: 1) - │ │ └── @ SymbolNode (location: (97,8)-(97,12)) - │ │ ├── flags: ∅ - │ │ ├── opening_loc: (97,8)-(97,9) = ":" - │ │ ├── value_loc: (97,9)-(97,12) = "foo" - │ │ ├── closing_loc: ∅ - │ │ └── unescaped: "foo" - │ ├── closing_loc: ∅ - │ └── block: ∅ - ├── @ CallNode (location: (99,0)-(99,13)) + │ ├── opening_loc: (97,8)-(97,9) = "{" + │ └── closing_loc: (97,13)-(97,14) = "}" + ├── @ CallNode (location: (99,0)-(99,12)) │ ├── flags: ∅ │ ├── receiver: │ │ @ ConstantPathNode (location: (99,0)-(99,4)) @@ -1470,7 +1468,7 @@ │ ├── call_operator_loc: (99,4)-(99,6) = "::" │ ├── name: :C │ ├── message_loc: (99,6)-(99,7) = "C" - │ ├── opening_loc: (99,7)-(99,8) = "(" + │ ├── opening_loc: ∅ │ ├── arguments: │ │ @ ArgumentsNode (location: (99,8)-(99,12)) │ │ ├── flags: ∅ @@ -1481,9 +1479,9 @@ │ │ ├── value_loc: (99,9)-(99,12) = "foo" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "foo" - │ ├── closing_loc: (99,12)-(99,13) = ")" + │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (101,0)-(101,17)) + ├── @ CallNode (location: (101,0)-(101,13)) │ ├── flags: ∅ │ ├── receiver: │ │ @ ConstantPathNode (location: (101,0)-(101,4)) @@ -1509,431 +1507,458 @@ │ │ ├── closing_loc: ∅ │ │ └── unescaped: "foo" │ ├── closing_loc: (101,12)-(101,13) = ")" + │ └── block: ∅ + ├── @ CallNode (location: (103,0)-(103,17)) + │ ├── flags: ∅ + │ ├── receiver: + │ │ @ ConstantPathNode (location: (103,0)-(103,4)) + │ │ ├── parent: + │ │ │ @ ConstantReadNode (location: (103,0)-(103,1)) + │ │ │ └── name: :A + │ │ ├── child: + │ │ │ @ ConstantReadNode (location: (103,3)-(103,4)) + │ │ │ └── name: :B + │ │ └── delimiter_loc: (103,1)-(103,3) = "::" + │ ├── call_operator_loc: (103,4)-(103,6) = "::" + │ ├── name: :C + │ ├── message_loc: (103,6)-(103,7) = "C" + │ ├── opening_loc: (103,7)-(103,8) = "(" + │ ├── arguments: + │ │ @ ArgumentsNode (location: (103,8)-(103,12)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ SymbolNode (location: (103,8)-(103,12)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: (103,8)-(103,9) = ":" + │ │ ├── value_loc: (103,9)-(103,12) = "foo" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "foo" + │ ├── closing_loc: (103,12)-(103,13) = ")" │ └── block: - │ @ BlockNode (location: (101,14)-(101,17)) + │ @ BlockNode (location: (103,14)-(103,17)) │ ├── locals: [] │ ├── locals_body_index: 0 │ ├── parameters: ∅ │ ├── body: ∅ - │ ├── opening_loc: (101,14)-(101,15) = "{" - │ └── closing_loc: (101,16)-(101,17) = "}" - ├── @ CallNode (location: (103,0)-(103,12)) + │ ├── opening_loc: (103,14)-(103,15) = "{" + │ └── closing_loc: (103,16)-(103,17) = "}" + ├── @ CallNode (location: (105,0)-(105,12)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (103,0)-(103,3) = "foo" - │ ├── opening_loc: (103,3)-(103,4) = "(" + │ ├── message_loc: (105,0)-(105,3) = "foo" + │ ├── opening_loc: (105,3)-(105,4) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (103,4)-(103,11)) + │ │ @ ArgumentsNode (location: (105,4)-(105,11)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ KeywordHashNode (location: (103,4)-(103,11)) + │ │ └── @ KeywordHashNode (location: (105,4)-(105,11)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) - │ │ └── @ AssocNode (location: (103,4)-(103,11)) + │ │ └── @ AssocNode (location: (105,4)-(105,11)) │ │ ├── key: - │ │ │ @ SymbolNode (location: (103,4)-(103,8)) + │ │ │ @ SymbolNode (location: (105,4)-(105,8)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (103,4)-(103,5) = "\"" - │ │ │ ├── value_loc: (103,5)-(103,6) = "a" - │ │ │ ├── closing_loc: (103,6)-(103,8) = "\":" + │ │ │ ├── opening_loc: (105,4)-(105,5) = "\"" + │ │ │ ├── value_loc: (105,5)-(105,6) = "a" + │ │ │ ├── closing_loc: (105,6)-(105,8) = "\":" │ │ │ └── unescaped: "a" │ │ ├── value: - │ │ │ @ IntegerNode (location: (103,9)-(103,11)) + │ │ │ @ IntegerNode (location: (105,9)-(105,11)) │ │ │ └── flags: decimal │ │ └── operator_loc: ∅ - │ ├── closing_loc: (103,11)-(103,12) = ")" + │ ├── closing_loc: (105,11)-(105,12) = ")" │ └── block: ∅ - ├── @ CallNode (location: (105,0)-(105,28)) + ├── @ CallNode (location: (107,0)-(107,28)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (105,0)-(105,3) = "foo" + │ ├── message_loc: (107,0)-(107,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (105,4)-(105,28)) + │ │ @ ArgumentsNode (location: (107,4)-(107,28)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ KeywordHashNode (location: (105,4)-(105,28)) + │ │ └── @ KeywordHashNode (location: (107,4)-(107,28)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) - │ │ └── @ AssocNode (location: (105,4)-(105,28)) + │ │ └── @ AssocNode (location: (107,4)-(107,28)) │ │ ├── key: - │ │ │ @ SymbolNode (location: (105,4)-(105,8)) + │ │ │ @ SymbolNode (location: (107,4)-(107,8)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── value_loc: (105,4)-(105,7) = "bar" - │ │ │ ├── closing_loc: (105,7)-(105,8) = ":" + │ │ │ ├── value_loc: (107,4)-(107,7) = "bar" + │ │ │ ├── closing_loc: (107,7)-(107,8) = ":" │ │ │ └── unescaped: "bar" │ │ ├── value: - │ │ │ @ HashNode (location: (105,9)-(105,28)) - │ │ │ ├── opening_loc: (105,9)-(105,10) = "{" + │ │ │ @ HashNode (location: (107,9)-(107,28)) + │ │ │ ├── opening_loc: (107,9)-(107,10) = "{" │ │ │ ├── elements: (length: 1) - │ │ │ │ └── @ AssocNode (location: (105,11)-(105,26)) + │ │ │ │ └── @ AssocNode (location: (107,11)-(107,26)) │ │ │ │ ├── key: - │ │ │ │ │ @ SymbolNode (location: (105,11)-(105,15)) + │ │ │ │ │ @ SymbolNode (location: (107,11)-(107,15)) │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ │ ├── value_loc: (105,11)-(105,14) = "baz" - │ │ │ │ │ ├── closing_loc: (105,14)-(105,15) = ":" + │ │ │ │ │ ├── value_loc: (107,11)-(107,14) = "baz" + │ │ │ │ │ ├── closing_loc: (107,14)-(107,15) = ":" │ │ │ │ │ └── unescaped: "baz" │ │ │ │ ├── value: - │ │ │ │ │ @ CallNode (location: (105,16)-(105,26)) + │ │ │ │ │ @ CallNode (location: (107,16)-(107,26)) │ │ │ │ │ ├── flags: ignore_visibility │ │ │ │ │ ├── receiver: ∅ │ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ │ ├── name: :qux - │ │ │ │ │ ├── message_loc: (105,16)-(105,19) = "qux" + │ │ │ │ │ ├── message_loc: (107,16)-(107,19) = "qux" │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── arguments: ∅ │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── block: - │ │ │ │ │ @ BlockNode (location: (105,20)-(105,26)) + │ │ │ │ │ @ BlockNode (location: (107,20)-(107,26)) │ │ │ │ │ ├── locals: [] │ │ │ │ │ ├── locals_body_index: 0 │ │ │ │ │ ├── parameters: ∅ │ │ │ │ │ ├── body: ∅ - │ │ │ │ │ ├── opening_loc: (105,20)-(105,22) = "do" - │ │ │ │ │ └── closing_loc: (105,23)-(105,26) = "end" + │ │ │ │ │ ├── opening_loc: (107,20)-(107,22) = "do" + │ │ │ │ │ └── closing_loc: (107,23)-(107,26) = "end" │ │ │ │ └── operator_loc: ∅ - │ │ │ └── closing_loc: (105,27)-(105,28) = "}" + │ │ │ └── closing_loc: (107,27)-(107,28) = "}" │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (107,0)-(107,24)) + ├── @ CallNode (location: (109,0)-(109,24)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (107,0)-(107,3) = "foo" + │ ├── message_loc: (109,0)-(109,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (107,4)-(107,24)) + │ │ @ ArgumentsNode (location: (109,4)-(109,24)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ KeywordHashNode (location: (107,4)-(107,24)) + │ │ └── @ KeywordHashNode (location: (109,4)-(109,24)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) - │ │ └── @ AssocNode (location: (107,4)-(107,24)) + │ │ └── @ AssocNode (location: (109,4)-(109,24)) │ │ ├── key: - │ │ │ @ SymbolNode (location: (107,4)-(107,8)) + │ │ │ @ SymbolNode (location: (109,4)-(109,8)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── value_loc: (107,4)-(107,7) = "bar" - │ │ │ ├── closing_loc: (107,7)-(107,8) = ":" + │ │ │ ├── value_loc: (109,4)-(109,7) = "bar" + │ │ │ ├── closing_loc: (109,7)-(109,8) = ":" │ │ │ └── unescaped: "bar" │ │ ├── value: - │ │ │ @ HashNode (location: (107,9)-(107,24)) - │ │ │ ├── opening_loc: (107,9)-(107,10) = "{" + │ │ │ @ HashNode (location: (109,9)-(109,24)) + │ │ │ ├── opening_loc: (109,9)-(109,10) = "{" │ │ │ ├── elements: (length: 1) - │ │ │ │ └── @ AssocSplatNode (location: (107,11)-(107,22)) + │ │ │ │ └── @ AssocSplatNode (location: (109,11)-(109,22)) │ │ │ │ ├── value: - │ │ │ │ │ @ CallNode (location: (107,13)-(107,22)) + │ │ │ │ │ @ CallNode (location: (109,13)-(109,22)) │ │ │ │ │ ├── flags: ignore_visibility │ │ │ │ │ ├── receiver: ∅ │ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ │ ├── name: :kw - │ │ │ │ │ ├── message_loc: (107,13)-(107,15) = "kw" + │ │ │ │ │ ├── message_loc: (109,13)-(109,15) = "kw" │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── arguments: ∅ │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── block: - │ │ │ │ │ @ BlockNode (location: (107,16)-(107,22)) + │ │ │ │ │ @ BlockNode (location: (109,16)-(109,22)) │ │ │ │ │ ├── locals: [] │ │ │ │ │ ├── locals_body_index: 0 │ │ │ │ │ ├── parameters: ∅ │ │ │ │ │ ├── body: ∅ - │ │ │ │ │ ├── opening_loc: (107,16)-(107,18) = "do" - │ │ │ │ │ └── closing_loc: (107,19)-(107,22) = "end" - │ │ │ │ └── operator_loc: (107,11)-(107,13) = "**" - │ │ │ └── closing_loc: (107,23)-(107,24) = "}" + │ │ │ │ │ ├── opening_loc: (109,16)-(109,18) = "do" + │ │ │ │ │ └── closing_loc: (109,19)-(109,22) = "end" + │ │ │ │ └── operator_loc: (109,11)-(109,13) = "**" + │ │ │ └── closing_loc: (109,23)-(109,24) = "}" │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (109,0)-(109,36)) + ├── @ CallNode (location: (111,0)-(111,36)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (109,0)-(109,3) = "foo" + │ ├── message_loc: (111,0)-(111,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (109,4)-(109,29)) + │ │ @ ArgumentsNode (location: (111,4)-(111,29)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ InterpolatedStringNode (location: (109,4)-(109,29)) - │ │ ├── opening_loc: (109,4)-(109,5) = "\"" + │ │ └── @ InterpolatedStringNode (location: (111,4)-(111,29)) + │ │ ├── opening_loc: (111,4)-(111,5) = "\"" │ │ ├── parts: (length: 1) - │ │ │ └── @ EmbeddedStatementsNode (location: (109,5)-(109,28)) - │ │ │ ├── opening_loc: (109,5)-(109,7) = "\#{" + │ │ │ └── @ EmbeddedStatementsNode (location: (111,5)-(111,28)) + │ │ │ ├── opening_loc: (111,5)-(111,7) = "\#{" │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (109,7)-(109,27)) + │ │ │ │ @ StatementsNode (location: (111,7)-(111,27)) │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ CallNode (location: (109,7)-(109,27)) + │ │ │ │ └── @ CallNode (location: (111,7)-(111,27)) │ │ │ │ ├── flags: ∅ │ │ │ │ ├── receiver: - │ │ │ │ │ @ CallNode (location: (109,7)-(109,10)) + │ │ │ │ │ @ CallNode (location: (111,7)-(111,10)) │ │ │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ │ │ ├── receiver: ∅ │ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ │ ├── name: :bar - │ │ │ │ │ ├── message_loc: (109,7)-(109,10) = "bar" + │ │ │ │ │ ├── message_loc: (111,7)-(111,10) = "bar" │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── arguments: ∅ │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── block: ∅ - │ │ │ │ ├── call_operator_loc: (109,10)-(109,11) = "." + │ │ │ │ ├── call_operator_loc: (111,10)-(111,11) = "." │ │ │ │ ├── name: :map - │ │ │ │ ├── message_loc: (109,11)-(109,14) = "map" + │ │ │ │ ├── message_loc: (111,11)-(111,14) = "map" │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── arguments: ∅ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: - │ │ │ │ @ BlockNode (location: (109,15)-(109,27)) + │ │ │ │ @ BlockNode (location: (111,15)-(111,27)) │ │ │ │ ├── locals: [] │ │ │ │ ├── locals_body_index: 0 │ │ │ │ ├── parameters: ∅ │ │ │ │ ├── body: - │ │ │ │ │ @ StatementsNode (location: (109,18)-(109,23)) + │ │ │ │ │ @ StatementsNode (location: (111,18)-(111,23)) │ │ │ │ │ └── body: (length: 1) - │ │ │ │ │ └── @ StringNode (location: (109,18)-(109,23)) + │ │ │ │ │ └── @ StringNode (location: (111,18)-(111,23)) │ │ │ │ │ ├── flags: ∅ - │ │ │ │ │ ├── opening_loc: (109,18)-(109,19) = "\"" - │ │ │ │ │ ├── content_loc: (109,19)-(109,22) = "baz" - │ │ │ │ │ ├── closing_loc: (109,22)-(109,23) = "\"" + │ │ │ │ │ ├── opening_loc: (111,18)-(111,19) = "\"" + │ │ │ │ │ ├── content_loc: (111,19)-(111,22) = "baz" + │ │ │ │ │ ├── closing_loc: (111,22)-(111,23) = "\"" │ │ │ │ │ └── unescaped: "baz" - │ │ │ │ ├── opening_loc: (109,15)-(109,17) = "do" - │ │ │ │ └── closing_loc: (109,24)-(109,27) = "end" - │ │ │ └── closing_loc: (109,27)-(109,28) = "}" - │ │ └── closing_loc: (109,28)-(109,29) = "\"" + │ │ │ │ ├── opening_loc: (111,15)-(111,17) = "do" + │ │ │ │ └── closing_loc: (111,24)-(111,27) = "end" + │ │ │ └── closing_loc: (111,27)-(111,28) = "}" + │ │ └── closing_loc: (111,28)-(111,29) = "\"" │ ├── closing_loc: ∅ │ └── block: - │ @ BlockNode (location: (109,30)-(109,36)) + │ @ BlockNode (location: (111,30)-(111,36)) │ ├── locals: [] │ ├── locals_body_index: 0 │ ├── parameters: ∅ │ ├── body: ∅ - │ ├── opening_loc: (109,30)-(109,32) = "do" - │ └── closing_loc: (109,33)-(109,36) = "end" - ├── @ CallNode (location: (111,0)-(111,28)) + │ ├── opening_loc: (111,30)-(111,32) = "do" + │ └── closing_loc: (111,33)-(111,36) = "end" + ├── @ CallNode (location: (113,0)-(113,28)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (111,0)-(111,3) = "foo" + │ ├── message_loc: (113,0)-(113,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (111,4)-(111,28)) + │ │ @ ArgumentsNode (location: (113,4)-(113,28)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ ClassNode (location: (111,4)-(111,28)) + │ │ └── @ ClassNode (location: (113,4)-(113,28)) │ │ ├── locals: [] - │ │ ├── class_keyword_loc: (111,4)-(111,9) = "class" + │ │ ├── class_keyword_loc: (113,4)-(113,9) = "class" │ │ ├── constant_path: - │ │ │ @ ConstantReadNode (location: (111,10)-(111,13)) + │ │ │ @ ConstantReadNode (location: (113,10)-(113,13)) │ │ │ └── name: :Bar │ │ ├── inheritance_operator_loc: ∅ │ │ ├── superclass: ∅ │ │ ├── body: - │ │ │ @ StatementsNode (location: (111,14)-(111,24)) + │ │ │ @ StatementsNode (location: (113,14)-(113,24)) │ │ │ └── body: (length: 1) - │ │ │ └── @ CallNode (location: (111,14)-(111,24)) + │ │ │ └── @ CallNode (location: (113,14)-(113,24)) │ │ │ ├── flags: ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :baz - │ │ │ ├── message_loc: (111,14)-(111,17) = "baz" + │ │ │ ├── message_loc: (113,14)-(113,17) = "baz" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: - │ │ │ @ BlockNode (location: (111,18)-(111,24)) + │ │ │ @ BlockNode (location: (113,18)-(113,24)) │ │ │ ├── locals: [] │ │ │ ├── locals_body_index: 0 │ │ │ ├── parameters: ∅ │ │ │ ├── body: ∅ - │ │ │ ├── opening_loc: (111,18)-(111,20) = "do" - │ │ │ └── closing_loc: (111,21)-(111,24) = "end" - │ │ ├── end_keyword_loc: (111,25)-(111,28) = "end" + │ │ │ ├── opening_loc: (113,18)-(113,20) = "do" + │ │ │ └── closing_loc: (113,21)-(113,24) = "end" + │ │ ├── end_keyword_loc: (113,25)-(113,28) = "end" │ │ └── name: :Bar │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (113,0)-(113,29)) + ├── @ CallNode (location: (115,0)-(115,29)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (113,0)-(113,3) = "foo" + │ ├── message_loc: (115,0)-(115,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (113,4)-(113,29)) + │ │ @ ArgumentsNode (location: (115,4)-(115,29)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ ModuleNode (location: (113,4)-(113,29)) + │ │ └── @ ModuleNode (location: (115,4)-(115,29)) │ │ ├── locals: [] - │ │ ├── module_keyword_loc: (113,4)-(113,10) = "module" + │ │ ├── module_keyword_loc: (115,4)-(115,10) = "module" │ │ ├── constant_path: - │ │ │ @ ConstantReadNode (location: (113,11)-(113,14)) + │ │ │ @ ConstantReadNode (location: (115,11)-(115,14)) │ │ │ └── name: :Bar │ │ ├── body: - │ │ │ @ StatementsNode (location: (113,15)-(113,25)) + │ │ │ @ StatementsNode (location: (115,15)-(115,25)) │ │ │ └── body: (length: 1) - │ │ │ └── @ CallNode (location: (113,15)-(113,25)) + │ │ │ └── @ CallNode (location: (115,15)-(115,25)) │ │ │ ├── flags: ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :baz - │ │ │ ├── message_loc: (113,15)-(113,18) = "baz" + │ │ │ ├── message_loc: (115,15)-(115,18) = "baz" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: - │ │ │ @ BlockNode (location: (113,19)-(113,25)) + │ │ │ @ BlockNode (location: (115,19)-(115,25)) │ │ │ ├── locals: [] │ │ │ ├── locals_body_index: 0 │ │ │ ├── parameters: ∅ │ │ │ ├── body: ∅ - │ │ │ ├── opening_loc: (113,19)-(113,21) = "do" - │ │ │ └── closing_loc: (113,22)-(113,25) = "end" - │ │ ├── end_keyword_loc: (113,26)-(113,29) = "end" + │ │ │ ├── opening_loc: (115,19)-(115,21) = "do" + │ │ │ └── closing_loc: (115,22)-(115,25) = "end" + │ │ ├── end_keyword_loc: (115,26)-(115,29) = "end" │ │ └── name: :Bar │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (115,0)-(115,16)) + ├── @ CallNode (location: (117,0)-(117,16)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (115,0)-(115,3) = "foo" + │ ├── message_loc: (117,0)-(117,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (115,4)-(115,16)) + │ │ @ ArgumentsNode (location: (117,4)-(117,16)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ ArrayNode (location: (115,4)-(115,16)) + │ │ └── @ ArrayNode (location: (117,4)-(117,16)) │ │ ├── flags: ∅ │ │ ├── elements: (length: 1) - │ │ │ └── @ CallNode (location: (115,5)-(115,15)) + │ │ │ └── @ CallNode (location: (117,5)-(117,15)) │ │ │ ├── flags: ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :baz - │ │ │ ├── message_loc: (115,5)-(115,8) = "baz" + │ │ │ ├── message_loc: (117,5)-(117,8) = "baz" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: - │ │ │ @ BlockNode (location: (115,9)-(115,15)) + │ │ │ @ BlockNode (location: (117,9)-(117,15)) │ │ │ ├── locals: [] │ │ │ ├── locals_body_index: 0 │ │ │ ├── parameters: ∅ │ │ │ ├── body: ∅ - │ │ │ ├── opening_loc: (115,9)-(115,11) = "do" - │ │ │ └── closing_loc: (115,12)-(115,15) = "end" - │ │ ├── opening_loc: (115,4)-(115,5) = "[" - │ │ └── closing_loc: (115,15)-(115,16) = "]" + │ │ │ ├── opening_loc: (117,9)-(117,11) = "do" + │ │ │ └── closing_loc: (117,12)-(117,15) = "end" + │ │ ├── opening_loc: (117,4)-(117,5) = "[" + │ │ └── closing_loc: (117,15)-(117,16) = "]" │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (117,0)-(117,28)) + ├── @ CallNode (location: (119,0)-(119,28)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :p - │ ├── message_loc: (117,0)-(117,1) = "p" + │ ├── message_loc: (119,0)-(119,1) = "p" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (117,2)-(117,28)) + │ │ @ ArgumentsNode (location: (119,2)-(119,28)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ BeginNode (location: (117,2)-(117,28)) - │ │ ├── begin_keyword_loc: (117,2)-(117,7) = "begin" + │ │ └── @ BeginNode (location: (119,2)-(119,28)) + │ │ ├── begin_keyword_loc: (119,2)-(119,7) = "begin" │ │ ├── statements: - │ │ │ @ StatementsNode (location: (117,8)-(117,24)) + │ │ │ @ StatementsNode (location: (119,8)-(119,24)) │ │ │ └── body: (length: 1) - │ │ │ └── @ CallNode (location: (117,8)-(117,24)) + │ │ │ └── @ CallNode (location: (119,8)-(119,24)) │ │ │ ├── flags: ∅ │ │ │ ├── receiver: - │ │ │ │ @ IntegerNode (location: (117,8)-(117,9)) + │ │ │ │ @ IntegerNode (location: (119,8)-(119,9)) │ │ │ │ └── flags: decimal - │ │ │ ├── call_operator_loc: (117,9)-(117,10) = "." + │ │ │ ├── call_operator_loc: (119,9)-(119,10) = "." │ │ │ ├── name: :times - │ │ │ ├── message_loc: (117,10)-(117,15) = "times" + │ │ │ ├── message_loc: (119,10)-(119,15) = "times" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: - │ │ │ @ BlockNode (location: (117,16)-(117,24)) + │ │ │ @ BlockNode (location: (119,16)-(119,24)) │ │ │ ├── locals: [] │ │ │ ├── locals_body_index: 0 │ │ │ ├── parameters: ∅ │ │ │ ├── body: - │ │ │ │ @ StatementsNode (location: (117,19)-(117,20)) + │ │ │ │ @ StatementsNode (location: (119,19)-(119,20)) │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ IntegerNode (location: (117,19)-(117,20)) + │ │ │ │ └── @ IntegerNode (location: (119,19)-(119,20)) │ │ │ │ └── flags: decimal - │ │ │ ├── opening_loc: (117,16)-(117,18) = "do" - │ │ │ └── closing_loc: (117,21)-(117,24) = "end" + │ │ │ ├── opening_loc: (119,16)-(119,18) = "do" + │ │ │ └── closing_loc: (119,21)-(119,24) = "end" │ │ ├── rescue_clause: ∅ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: ∅ - │ │ └── end_keyword_loc: (117,25)-(117,28) = "end" + │ │ └── end_keyword_loc: (119,25)-(119,28) = "end" │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (119,0)-(124,5)) + ├── @ CallNode (location: (121,0)-(126,5)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (119,0)-(119,3) = "foo" + │ ├── message_loc: (121,0)-(121,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (119,4)-(124,5)) + │ │ @ ArgumentsNode (location: (121,4)-(126,5)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ SymbolNode (location: (119,4)-(119,6)) + │ │ ├── @ SymbolNode (location: (121,4)-(121,6)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (119,4)-(119,5) = ":" - │ │ │ ├── value_loc: (119,5)-(119,6) = "a" + │ │ │ ├── opening_loc: (121,4)-(121,5) = ":" + │ │ │ ├── value_loc: (121,5)-(121,6) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" - │ │ └── @ IfNode (location: (120,2)-(124,5)) - │ │ ├── if_keyword_loc: (120,2)-(120,4) = "if" + │ │ └── @ IfNode (location: (122,2)-(126,5)) + │ │ ├── if_keyword_loc: (122,2)-(122,4) = "if" │ │ ├── predicate: - │ │ │ @ CallNode (location: (120,5)-(120,6)) + │ │ │ @ CallNode (location: (122,5)-(122,6)) │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :x - │ │ │ ├── message_loc: (120,5)-(120,6) = "x" + │ │ │ ├── message_loc: (122,5)-(122,6) = "x" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ ├── then_keyword_loc: ∅ │ │ ├── statements: - │ │ │ @ StatementsNode (location: (121,4)-(123,7)) + │ │ │ @ StatementsNode (location: (123,4)-(125,7)) │ │ │ └── body: (length: 1) - │ │ │ └── @ CallNode (location: (121,4)-(123,7)) + │ │ │ └── @ CallNode (location: (123,4)-(125,7)) │ │ │ ├── flags: ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :bar - │ │ │ ├── message_loc: (121,4)-(121,7) = "bar" + │ │ │ ├── message_loc: (123,4)-(123,7) = "bar" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: - │ │ │ @ BlockNode (location: (121,8)-(123,7)) + │ │ │ @ BlockNode (location: (123,8)-(125,7)) │ │ │ ├── locals: [:a] │ │ │ ├── locals_body_index: 1 │ │ │ ├── parameters: - │ │ │ │ @ BlockParametersNode (location: (121,11)-(121,14)) + │ │ │ │ @ BlockParametersNode (location: (123,11)-(123,14)) │ │ │ │ ├── parameters: - │ │ │ │ │ @ ParametersNode (location: (121,12)-(121,13)) + │ │ │ │ │ @ ParametersNode (location: (123,12)-(123,13)) │ │ │ │ │ ├── requireds: (length: 1) - │ │ │ │ │ │ └── @ RequiredParameterNode (location: (121,12)-(121,13)) + │ │ │ │ │ │ └── @ RequiredParameterNode (location: (123,12)-(123,13)) │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── name: :a │ │ │ │ │ ├── optionals: (length: 0) @@ -1943,74 +1968,74 @@ │ │ │ │ │ ├── keyword_rest: ∅ │ │ │ │ │ └── block: ∅ │ │ │ │ ├── locals: (length: 0) - │ │ │ │ ├── opening_loc: (121,11)-(121,12) = "|" - │ │ │ │ └── closing_loc: (121,13)-(121,14) = "|" + │ │ │ │ ├── opening_loc: (123,11)-(123,12) = "|" + │ │ │ │ └── closing_loc: (123,13)-(123,14) = "|" │ │ │ ├── body: - │ │ │ │ @ StatementsNode (location: (122,6)-(122,7)) + │ │ │ │ @ StatementsNode (location: (124,6)-(124,7)) │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ LocalVariableReadNode (location: (122,6)-(122,7)) + │ │ │ │ └── @ LocalVariableReadNode (location: (124,6)-(124,7)) │ │ │ │ ├── name: :a │ │ │ │ └── depth: 0 - │ │ │ ├── opening_loc: (121,8)-(121,10) = "do" - │ │ │ └── closing_loc: (123,4)-(123,7) = "end" + │ │ │ ├── opening_loc: (123,8)-(123,10) = "do" + │ │ │ └── closing_loc: (125,4)-(125,7) = "end" │ │ ├── consequent: ∅ - │ │ └── end_keyword_loc: (124,2)-(124,5) = "end" + │ │ └── end_keyword_loc: (126,2)-(126,5) = "end" │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (126,0)-(135,5)) + ├── @ CallNode (location: (128,0)-(137,5)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (126,0)-(126,3) = "foo" + │ ├── message_loc: (128,0)-(128,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (126,4)-(135,5)) + │ │ @ ArgumentsNode (location: (128,4)-(137,5)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 3) - │ │ ├── @ SymbolNode (location: (126,4)-(126,6)) + │ │ ├── @ SymbolNode (location: (128,4)-(128,6)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (126,4)-(126,5) = ":" - │ │ │ ├── value_loc: (126,5)-(126,6) = "a" + │ │ │ ├── opening_loc: (128,4)-(128,5) = ":" + │ │ │ ├── value_loc: (128,5)-(128,6) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" - │ │ ├── @ WhileNode (location: (127,2)-(131,5)) + │ │ ├── @ WhileNode (location: (129,2)-(133,5)) │ │ │ ├── flags: ∅ - │ │ │ ├── keyword_loc: (127,2)-(127,7) = "while" - │ │ │ ├── closing_loc: (131,2)-(131,5) = "end" + │ │ │ ├── keyword_loc: (129,2)-(129,7) = "while" + │ │ │ ├── closing_loc: (133,2)-(133,5) = "end" │ │ │ ├── predicate: - │ │ │ │ @ CallNode (location: (127,8)-(127,9)) + │ │ │ │ @ CallNode (location: (129,8)-(129,9)) │ │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :x - │ │ │ │ ├── message_loc: (127,8)-(127,9) = "x" + │ │ │ │ ├── message_loc: (129,8)-(129,9) = "x" │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── arguments: ∅ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ │ │ │ └── statements: - │ │ │ @ StatementsNode (location: (128,4)-(130,7)) + │ │ │ @ StatementsNode (location: (130,4)-(132,7)) │ │ │ └── body: (length: 1) - │ │ │ └── @ CallNode (location: (128,4)-(130,7)) + │ │ │ └── @ CallNode (location: (130,4)-(132,7)) │ │ │ ├── flags: ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :bar - │ │ │ ├── message_loc: (128,4)-(128,7) = "bar" + │ │ │ ├── message_loc: (130,4)-(130,7) = "bar" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: - │ │ │ @ BlockNode (location: (128,8)-(130,7)) + │ │ │ @ BlockNode (location: (130,8)-(132,7)) │ │ │ ├── locals: [:a] │ │ │ ├── locals_body_index: 1 │ │ │ ├── parameters: - │ │ │ │ @ BlockParametersNode (location: (128,11)-(128,14)) + │ │ │ │ @ BlockParametersNode (location: (130,11)-(130,14)) │ │ │ │ ├── parameters: - │ │ │ │ │ @ ParametersNode (location: (128,12)-(128,13)) + │ │ │ │ │ @ ParametersNode (location: (130,12)-(130,13)) │ │ │ │ │ ├── requireds: (length: 1) - │ │ │ │ │ │ └── @ RequiredParameterNode (location: (128,12)-(128,13)) + │ │ │ │ │ │ └── @ RequiredParameterNode (location: (130,12)-(130,13)) │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── name: :a │ │ │ │ │ ├── optionals: (length: 0) @@ -2020,121 +2045,121 @@ │ │ │ │ │ ├── keyword_rest: ∅ │ │ │ │ │ └── block: ∅ │ │ │ │ ├── locals: (length: 0) - │ │ │ │ ├── opening_loc: (128,11)-(128,12) = "|" - │ │ │ │ └── closing_loc: (128,13)-(128,14) = "|" + │ │ │ │ ├── opening_loc: (130,11)-(130,12) = "|" + │ │ │ │ └── closing_loc: (130,13)-(130,14) = "|" │ │ │ ├── body: - │ │ │ │ @ StatementsNode (location: (129,6)-(129,7)) + │ │ │ │ @ StatementsNode (location: (131,6)-(131,7)) │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ LocalVariableReadNode (location: (129,6)-(129,7)) + │ │ │ │ └── @ LocalVariableReadNode (location: (131,6)-(131,7)) │ │ │ │ ├── name: :a │ │ │ │ └── depth: 0 - │ │ │ ├── opening_loc: (128,8)-(128,10) = "do" - │ │ │ └── closing_loc: (130,4)-(130,7) = "end" - │ │ └── @ UntilNode (location: (132,2)-(135,5)) + │ │ │ ├── opening_loc: (130,8)-(130,10) = "do" + │ │ │ └── closing_loc: (132,4)-(132,7) = "end" + │ │ └── @ UntilNode (location: (134,2)-(137,5)) │ │ ├── flags: ∅ - │ │ ├── keyword_loc: (132,2)-(132,7) = "until" - │ │ ├── closing_loc: (135,2)-(135,5) = "end" + │ │ ├── keyword_loc: (134,2)-(134,7) = "until" + │ │ ├── closing_loc: (137,2)-(137,5) = "end" │ │ ├── predicate: - │ │ │ @ CallNode (location: (132,8)-(132,9)) + │ │ │ @ CallNode (location: (134,8)-(134,9)) │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :x - │ │ │ ├── message_loc: (132,8)-(132,9) = "x" + │ │ │ ├── message_loc: (134,8)-(134,9) = "x" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ └── statements: - │ │ @ StatementsNode (location: (133,4)-(134,7)) + │ │ @ StatementsNode (location: (135,4)-(136,7)) │ │ └── body: (length: 1) - │ │ └── @ CallNode (location: (133,4)-(134,7)) + │ │ └── @ CallNode (location: (135,4)-(136,7)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :baz - │ │ ├── message_loc: (133,4)-(133,7) = "baz" + │ │ ├── message_loc: (135,4)-(135,7) = "baz" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: - │ │ @ BlockNode (location: (133,8)-(134,7)) + │ │ @ BlockNode (location: (135,8)-(136,7)) │ │ ├── locals: [] │ │ ├── locals_body_index: 0 │ │ ├── parameters: ∅ │ │ ├── body: ∅ - │ │ ├── opening_loc: (133,8)-(133,10) = "do" - │ │ └── closing_loc: (134,4)-(134,7) = "end" + │ │ ├── opening_loc: (135,8)-(135,10) = "do" + │ │ └── closing_loc: (136,4)-(136,7) = "end" │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (137,0)-(137,9)) + ├── @ CallNode (location: (139,0)-(139,9)) │ ├── flags: ∅ │ ├── receiver: - │ │ @ HashNode (location: (137,0)-(137,2)) - │ │ ├── opening_loc: (137,0)-(137,1) = "{" + │ │ @ HashNode (location: (139,0)-(139,2)) + │ │ ├── opening_loc: (139,0)-(139,1) = "{" │ │ ├── elements: (length: 0) - │ │ └── closing_loc: (137,1)-(137,2) = "}" + │ │ └── closing_loc: (139,1)-(139,2) = "}" │ ├── call_operator_loc: ∅ │ ├── name: :+ - │ ├── message_loc: (137,3)-(137,4) = "+" + │ ├── message_loc: (139,3)-(139,4) = "+" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (137,5)-(137,9)) + │ │ @ ArgumentsNode (location: (139,5)-(139,9)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ CallNode (location: (137,5)-(137,9)) + │ │ └── @ CallNode (location: (139,5)-(139,9)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :A - │ │ ├── message_loc: (137,5)-(137,6) = "A" + │ │ ├── message_loc: (139,5)-(139,6) = "A" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: - │ │ @ BlockNode (location: (137,7)-(137,9)) + │ │ @ BlockNode (location: (139,7)-(139,9)) │ │ ├── locals: [] │ │ ├── locals_body_index: 0 │ │ ├── parameters: ∅ │ │ ├── body: ∅ - │ │ ├── opening_loc: (137,7)-(137,8) = "{" - │ │ └── closing_loc: (137,8)-(137,9) = "}" + │ │ ├── opening_loc: (139,7)-(139,8) = "{" + │ │ └── closing_loc: (139,8)-(139,9) = "}" │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (139,0)-(139,16)) + ├── @ CallNode (location: (141,0)-(141,16)) │ ├── flags: ∅ │ ├── receiver: - │ │ @ HashNode (location: (139,0)-(139,2)) - │ │ ├── opening_loc: (139,0)-(139,1) = "{" + │ │ @ HashNode (location: (141,0)-(141,2)) + │ │ ├── opening_loc: (141,0)-(141,1) = "{" │ │ ├── elements: (length: 0) - │ │ └── closing_loc: (139,1)-(139,2) = "}" + │ │ └── closing_loc: (141,1)-(141,2) = "}" │ ├── call_operator_loc: ∅ │ ├── name: :+ - │ ├── message_loc: (139,3)-(139,4) = "+" + │ ├── message_loc: (141,3)-(141,4) = "+" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (139,5)-(139,16)) + │ │ @ ArgumentsNode (location: (141,5)-(141,16)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ CallNode (location: (139,5)-(139,16)) + │ │ └── @ CallNode (location: (141,5)-(141,16)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :A - │ │ ├── message_loc: (139,5)-(139,6) = "A" + │ │ ├── message_loc: (141,5)-(141,6) = "A" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: - │ │ @ BlockNode (location: (139,7)-(139,16)) + │ │ @ BlockNode (location: (141,7)-(141,16)) │ │ ├── locals: [:a] │ │ ├── locals_body_index: 1 │ │ ├── parameters: - │ │ │ @ BlockParametersNode (location: (139,9)-(139,12)) + │ │ │ @ BlockParametersNode (location: (141,9)-(141,12)) │ │ │ ├── parameters: - │ │ │ │ @ ParametersNode (location: (139,10)-(139,11)) + │ │ │ │ @ ParametersNode (location: (141,10)-(141,11)) │ │ │ │ ├── requireds: (length: 1) - │ │ │ │ │ └── @ RequiredParameterNode (location: (139,10)-(139,11)) + │ │ │ │ │ └── @ RequiredParameterNode (location: (141,10)-(141,11)) │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :a │ │ │ │ ├── optionals: (length: 0) @@ -2144,269 +2169,269 @@ │ │ │ │ ├── keyword_rest: ∅ │ │ │ │ └── block: ∅ │ │ │ ├── locals: (length: 0) - │ │ │ ├── opening_loc: (139,9)-(139,10) = "|" - │ │ │ └── closing_loc: (139,11)-(139,12) = "|" + │ │ │ ├── opening_loc: (141,9)-(141,10) = "|" + │ │ │ └── closing_loc: (141,11)-(141,12) = "|" │ │ ├── body: - │ │ │ @ StatementsNode (location: (139,13)-(139,14)) + │ │ │ @ StatementsNode (location: (141,13)-(141,14)) │ │ │ └── body: (length: 1) - │ │ │ └── @ LocalVariableReadNode (location: (139,13)-(139,14)) + │ │ │ └── @ LocalVariableReadNode (location: (141,13)-(141,14)) │ │ │ ├── name: :a │ │ │ └── depth: 0 - │ │ ├── opening_loc: (139,7)-(139,8) = "{" - │ │ └── closing_loc: (139,15)-(139,16) = "}" + │ │ ├── opening_loc: (141,7)-(141,8) = "{" + │ │ └── closing_loc: (141,15)-(141,16) = "}" │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (141,0)-(141,11)) + ├── @ CallNode (location: (143,0)-(143,11)) │ ├── flags: ∅ │ ├── receiver: - │ │ @ CallNode (location: (141,0)-(141,4)) + │ │ @ CallNode (location: (143,0)-(143,4)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :A - │ │ ├── message_loc: (141,0)-(141,1) = "A" + │ │ ├── message_loc: (143,0)-(143,1) = "A" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: - │ │ @ BlockNode (location: (141,2)-(141,4)) + │ │ @ BlockNode (location: (143,2)-(143,4)) │ │ ├── locals: [] │ │ ├── locals_body_index: 0 │ │ ├── parameters: ∅ │ │ ├── body: ∅ - │ │ ├── opening_loc: (141,2)-(141,3) = "{" - │ │ └── closing_loc: (141,3)-(141,4) = "}" + │ │ ├── opening_loc: (143,2)-(143,3) = "{" + │ │ └── closing_loc: (143,3)-(143,4) = "}" │ ├── call_operator_loc: ∅ │ ├── name: :+ - │ ├── message_loc: (141,5)-(141,6) = "+" + │ ├── message_loc: (143,5)-(143,6) = "+" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (141,7)-(141,11)) + │ │ @ ArgumentsNode (location: (143,7)-(143,11)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ CallNode (location: (141,7)-(141,11)) + │ │ └── @ CallNode (location: (143,7)-(143,11)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :A - │ │ ├── message_loc: (141,7)-(141,8) = "A" + │ │ ├── message_loc: (143,7)-(143,8) = "A" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: - │ │ @ BlockNode (location: (141,9)-(141,11)) + │ │ @ BlockNode (location: (143,9)-(143,11)) │ │ ├── locals: [] │ │ ├── locals_body_index: 0 │ │ ├── parameters: ∅ │ │ ├── body: ∅ - │ │ ├── opening_loc: (141,9)-(141,10) = "{" - │ │ └── closing_loc: (141,10)-(141,11) = "}" + │ │ ├── opening_loc: (143,9)-(143,10) = "{" + │ │ └── closing_loc: (143,10)-(143,11) = "}" │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (143,0)-(143,11)) + ├── @ CallNode (location: (145,0)-(145,11)) │ ├── flags: ∅ │ ├── receiver: - │ │ @ CallNode (location: (143,0)-(143,3)) + │ │ @ CallNode (location: (145,0)-(145,3)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :lst - │ │ ├── message_loc: (143,0)-(143,3) = "lst" + │ │ ├── message_loc: (145,0)-(145,3) = "lst" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :<< - │ ├── message_loc: (143,4)-(143,6) = "<<" + │ ├── message_loc: (145,4)-(145,6) = "<<" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (143,7)-(143,11)) + │ │ @ ArgumentsNode (location: (145,7)-(145,11)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ CallNode (location: (143,7)-(143,11)) + │ │ └── @ CallNode (location: (145,7)-(145,11)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :A - │ │ ├── message_loc: (143,7)-(143,8) = "A" + │ │ ├── message_loc: (145,7)-(145,8) = "A" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: - │ │ @ BlockNode (location: (143,9)-(143,11)) + │ │ @ BlockNode (location: (145,9)-(145,11)) │ │ ├── locals: [] │ │ ├── locals_body_index: 0 │ │ ├── parameters: ∅ │ │ ├── body: ∅ - │ │ ├── opening_loc: (143,9)-(143,10) = "{" - │ │ └── closing_loc: (143,10)-(143,11) = "}" + │ │ ├── opening_loc: (145,9)-(145,10) = "{" + │ │ └── closing_loc: (145,10)-(145,11) = "}" │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ InterpolatedStringNode (location: (145,0)-(145,17)) - │ ├── opening_loc: (145,0)-(145,1) = "\"" + ├── @ InterpolatedStringNode (location: (147,0)-(147,17)) + │ ├── opening_loc: (147,0)-(147,1) = "\"" │ ├── parts: (length: 1) - │ │ └── @ EmbeddedStatementsNode (location: (145,1)-(145,16)) - │ │ ├── opening_loc: (145,1)-(145,3) = "\#{" + │ │ └── @ EmbeddedStatementsNode (location: (147,1)-(147,16)) + │ │ ├── opening_loc: (147,1)-(147,3) = "\#{" │ │ ├── statements: - │ │ │ @ StatementsNode (location: (145,4)-(145,14)) + │ │ │ @ StatementsNode (location: (147,4)-(147,14)) │ │ │ └── body: (length: 1) - │ │ │ └── @ CallNode (location: (145,4)-(145,14)) + │ │ │ └── @ CallNode (location: (147,4)-(147,14)) │ │ │ ├── flags: ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :join - │ │ │ ├── message_loc: (145,4)-(145,8) = "join" + │ │ │ ├── message_loc: (147,4)-(147,8) = "join" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: - │ │ │ │ @ ArgumentsNode (location: (145,9)-(145,14)) + │ │ │ │ @ ArgumentsNode (location: (147,9)-(147,14)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) - │ │ │ │ └── @ ParenthesesNode (location: (145,9)-(145,14)) + │ │ │ │ └── @ ParenthesesNode (location: (147,9)-(147,14)) │ │ │ │ ├── body: - │ │ │ │ │ @ StatementsNode (location: (145,10)-(145,13)) + │ │ │ │ │ @ StatementsNode (location: (147,10)-(147,13)) │ │ │ │ │ └── body: (length: 1) - │ │ │ │ │ └── @ StringNode (location: (145,10)-(145,13)) + │ │ │ │ │ └── @ StringNode (location: (147,10)-(147,13)) │ │ │ │ │ ├── flags: ∅ - │ │ │ │ │ ├── opening_loc: (145,10)-(145,11) = "\"" - │ │ │ │ │ ├── content_loc: (145,11)-(145,12) = " " - │ │ │ │ │ ├── closing_loc: (145,12)-(145,13) = "\"" + │ │ │ │ │ ├── opening_loc: (147,10)-(147,11) = "\"" + │ │ │ │ │ ├── content_loc: (147,11)-(147,12) = " " + │ │ │ │ │ ├── closing_loc: (147,12)-(147,13) = "\"" │ │ │ │ │ └── unescaped: " " - │ │ │ │ ├── opening_loc: (145,9)-(145,10) = "(" - │ │ │ │ └── closing_loc: (145,13)-(145,14) = ")" + │ │ │ │ ├── opening_loc: (147,9)-(147,10) = "(" + │ │ │ │ └── closing_loc: (147,13)-(147,14) = ")" │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── closing_loc: (145,15)-(145,16) = "}" - │ └── closing_loc: (145,16)-(145,17) = "\"" - ├── @ InterpolatedStringNode (location: (147,0)-(147,8)) - │ ├── opening_loc: (147,0)-(147,1) = "\"" + │ │ └── closing_loc: (147,15)-(147,16) = "}" + │ └── closing_loc: (147,16)-(147,17) = "\"" + ├── @ InterpolatedStringNode (location: (149,0)-(149,8)) + │ ├── opening_loc: (149,0)-(149,1) = "\"" │ ├── parts: (length: 1) - │ │ └── @ EmbeddedStatementsNode (location: (147,1)-(147,7)) - │ │ ├── opening_loc: (147,1)-(147,3) = "\#{" + │ │ └── @ EmbeddedStatementsNode (location: (149,1)-(149,7)) + │ │ ├── opening_loc: (149,1)-(149,3) = "\#{" │ │ ├── statements: - │ │ │ @ StatementsNode (location: (147,3)-(147,6)) + │ │ │ @ StatementsNode (location: (149,3)-(149,6)) │ │ │ └── body: (length: 1) - │ │ │ └── @ ParenthesesNode (location: (147,3)-(147,6)) + │ │ │ └── @ ParenthesesNode (location: (149,3)-(149,6)) │ │ │ ├── body: - │ │ │ │ @ StatementsNode (location: (147,4)-(147,5)) + │ │ │ │ @ StatementsNode (location: (149,4)-(149,5)) │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ CallNode (location: (147,4)-(147,5)) + │ │ │ │ └── @ CallNode (location: (149,4)-(149,5)) │ │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :v - │ │ │ │ ├── message_loc: (147,4)-(147,5) = "v" + │ │ │ │ ├── message_loc: (149,4)-(149,5) = "v" │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── arguments: ∅ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ - │ │ │ ├── opening_loc: (147,3)-(147,4) = "(" - │ │ │ └── closing_loc: (147,5)-(147,6) = ")" - │ │ └── closing_loc: (147,6)-(147,7) = "}" - │ └── closing_loc: (147,7)-(147,8) = "\"" - ├── @ DefNode (location: (149,0)-(149,18)) + │ │ │ ├── opening_loc: (149,3)-(149,4) = "(" + │ │ │ └── closing_loc: (149,5)-(149,6) = ")" + │ │ └── closing_loc: (149,6)-(149,7) = "}" + │ └── closing_loc: (149,7)-(149,8) = "\"" + ├── @ DefNode (location: (151,0)-(151,18)) │ ├── name: :f - │ ├── name_loc: (149,4)-(149,5) = "f" + │ ├── name_loc: (151,4)-(151,5) = "f" │ ├── receiver: ∅ │ ├── parameters: - │ │ @ ParametersNode (location: (149,6)-(149,7)) + │ │ @ ParametersNode (location: (151,6)-(151,7)) │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: - │ │ │ @ RestParameterNode (location: (149,6)-(149,7)) + │ │ │ @ RestParameterNode (location: (151,6)-(151,7)) │ │ │ ├── flags: ∅ │ │ │ ├── name: ∅ │ │ │ ├── name_loc: ∅ - │ │ │ └── operator_loc: (149,6)-(149,7) = "*" + │ │ │ └── operator_loc: (151,6)-(151,7) = "*" │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ │ │ └── block: ∅ │ ├── body: - │ │ @ StatementsNode (location: (149,10)-(149,13)) + │ │ @ StatementsNode (location: (151,10)-(151,13)) │ │ └── body: (length: 1) - │ │ └── @ CallNode (location: (149,10)-(149,13)) + │ │ └── @ CallNode (location: (151,10)-(151,13)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :p - │ │ ├── message_loc: (149,10)-(149,11) = "p" + │ │ ├── message_loc: (151,10)-(151,11) = "p" │ │ ├── opening_loc: ∅ │ │ ├── arguments: - │ │ │ @ ArgumentsNode (location: (149,12)-(149,13)) + │ │ │ @ ArgumentsNode (location: (151,12)-(151,13)) │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) - │ │ │ └── @ SplatNode (location: (149,12)-(149,13)) - │ │ │ ├── operator_loc: (149,12)-(149,13) = "*" + │ │ │ └── @ SplatNode (location: (151,12)-(151,13)) + │ │ │ ├── operator_loc: (151,12)-(151,13) = "*" │ │ │ └── expression: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── locals: [:*] │ ├── locals_body_index: 1 - │ ├── def_keyword_loc: (149,0)-(149,3) = "def" + │ ├── def_keyword_loc: (151,0)-(151,3) = "def" │ ├── operator_loc: ∅ - │ ├── lparen_loc: (149,5)-(149,6) = "(" - │ ├── rparen_loc: (149,7)-(149,8) = ")" + │ ├── lparen_loc: (151,5)-(151,6) = "(" + │ ├── rparen_loc: (151,7)-(151,8) = ")" │ ├── equal_loc: ∅ - │ └── end_keyword_loc: (149,15)-(149,18) = "end" - ├── @ CallNode (location: (151,0)-(151,16)) + │ └── end_keyword_loc: (151,15)-(151,18) = "end" + ├── @ CallNode (location: (153,0)-(153,16)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (151,0)-(151,3) = "foo" + │ ├── message_loc: (153,0)-(153,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (151,4)-(151,16)) + │ │ @ ArgumentsNode (location: (153,4)-(153,16)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ IntegerNode (location: (151,4)-(151,5)) + │ │ ├── @ IntegerNode (location: (153,4)-(153,5)) │ │ │ └── flags: decimal - │ │ └── @ CallNode (location: (151,7)-(151,16)) + │ │ └── @ CallNode (location: (153,7)-(153,16)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :Bar - │ │ ├── message_loc: (151,7)-(151,10) = "Bar" + │ │ ├── message_loc: (153,7)-(153,10) = "Bar" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: - │ │ @ BlockNode (location: (151,11)-(151,16)) + │ │ @ BlockNode (location: (153,11)-(153,16)) │ │ ├── locals: [] │ │ ├── locals_body_index: 0 │ │ ├── parameters: ∅ │ │ ├── body: - │ │ │ @ StatementsNode (location: (151,13)-(151,14)) + │ │ │ @ StatementsNode (location: (153,13)-(153,14)) │ │ │ └── body: (length: 1) - │ │ │ └── @ IntegerNode (location: (151,13)-(151,14)) + │ │ │ └── @ IntegerNode (location: (153,13)-(153,14)) │ │ │ └── flags: decimal - │ │ ├── opening_loc: (151,11)-(151,12) = "{" - │ │ └── closing_loc: (151,15)-(151,16) = "}" + │ │ ├── opening_loc: (153,11)-(153,12) = "{" + │ │ └── closing_loc: (153,15)-(153,16) = "}" │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ LocalVariableWriteNode (location: (153,0)-(153,7)) + ├── @ LocalVariableWriteNode (location: (155,0)-(155,7)) │ ├── name: :foo │ ├── depth: 0 - │ ├── name_loc: (153,0)-(153,3) = "foo" + │ ├── name_loc: (155,0)-(155,3) = "foo" │ ├── value: - │ │ @ IntegerNode (location: (153,6)-(153,7)) + │ │ @ IntegerNode (location: (155,6)-(155,7)) │ │ └── flags: decimal - │ └── operator_loc: (153,4)-(153,5) = "=" - └── @ CallNode (location: (154,0)-(154,6)) + │ └── operator_loc: (155,4)-(155,5) = "=" + └── @ CallNode (location: (156,0)-(156,6)) ├── flags: ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :foo - ├── message_loc: (154,0)-(154,3) = "foo" + ├── message_loc: (156,0)-(156,3) = "foo" ├── opening_loc: ∅ ├── arguments: ∅ ├── closing_loc: ∅ └── block: - @ BlockNode (location: (154,4)-(154,6)) + @ BlockNode (location: (156,4)-(156,6)) ├── locals: [] ├── locals_body_index: 0 ├── parameters: ∅ ├── body: ∅ - ├── opening_loc: (154,4)-(154,5) = "{" - └── closing_loc: (154,5)-(154,6) = "}" + ├── opening_loc: (156,4)-(156,5) = "{" + └── closing_loc: (156,5)-(156,6) = "}" From e9f936df71b68515210b6040766987d1b94ec4df Mon Sep 17 00:00:00 2001 From: Max Prokopiev Date: Wed, 24 Jan 2024 21:08:33 +0100 Subject: [PATCH 514/640] [ruby/prism] Extract snippet into its own file and skip in TruffleRuby https://github.com/ruby/prism/commit/12649ee74c --- test/prism/fixtures/emoji_method_calls.txt | 1 + test/prism/fixtures/method_calls.txt | 2 - test/prism/parse_test.rb | 2 +- test/prism/snapshots/method_calls.txt | 1563 ++++++++++---------- 4 files changed, 771 insertions(+), 797 deletions(-) create mode 100644 test/prism/fixtures/emoji_method_calls.txt diff --git a/test/prism/fixtures/emoji_method_calls.txt b/test/prism/fixtures/emoji_method_calls.txt new file mode 100644 index 00000000000000..96d0daba33079e --- /dev/null +++ b/test/prism/fixtures/emoji_method_calls.txt @@ -0,0 +1 @@ +foo.🌊 = 1 diff --git a/test/prism/fixtures/method_calls.txt b/test/prism/fixtures/method_calls.txt index ad70c70aa0c480..d30780771f7376 100644 --- a/test/prism/fixtures/method_calls.txt +++ b/test/prism/fixtures/method_calls.txt @@ -20,8 +20,6 @@ a::b c foo.bar = 1 -foo.🌊 = 1 - a? a(&block) diff --git a/test/prism/parse_test.rb b/test/prism/parse_test.rb index 6c5d125c3d5e8d..26243150084dc0 100644 --- a/test/prism/parse_test.rb +++ b/test/prism/parse_test.rb @@ -87,7 +87,7 @@ def test_parse_lex_file relatives.each do |relative| # These fail on TruffleRuby due to a difference in Symbol#inspect: :测试 vs :"测试" - next if RUBY_ENGINE == "truffleruby" and %w[seattlerb/bug202.txt seattlerb/magic_encoding_comment.txt].include?(relative) + next if RUBY_ENGINE == "truffleruby" and %w[emoji_method_calls.txt seattlerb/bug202.txt seattlerb/magic_encoding_comment.txt].include?(relative) filepath = File.join(base, relative) snapshot = File.expand_path(File.join("snapshots", relative), __dir__) diff --git a/test/prism/snapshots/method_calls.txt b/test/prism/snapshots/method_calls.txt index 4a76fe5e131bcb..ff6e0dd7df1381 100644 --- a/test/prism/snapshots/method_calls.txt +++ b/test/prism/snapshots/method_calls.txt @@ -1,8 +1,8 @@ -@ ProgramNode (location: (1,0)-(156,6)) +@ ProgramNode (location: (1,0)-(154,6)) ├── locals: [:foo] └── statements: - @ StatementsNode (location: (1,0)-(156,6)) - └── body: (length: 67) + @ StatementsNode (location: (1,0)-(154,6)) + └── body: (length: 66) ├── @ CallNode (location: (1,0)-(1,14)) │ ├── flags: ∅ │ ├── receiver: @@ -262,710 +262,685 @@ │ │ └── flags: decimal │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (23,0)-(23,12)) - │ ├── flags: attribute_write - │ ├── receiver: - │ │ @ CallNode (location: (23,0)-(23,3)) - │ │ ├── flags: variable_call, ignore_visibility - │ │ ├── receiver: ∅ - │ │ ├── call_operator_loc: ∅ - │ │ ├── name: :foo - │ │ ├── message_loc: (23,0)-(23,3) = "foo" - │ │ ├── opening_loc: ∅ - │ │ ├── arguments: ∅ - │ │ ├── closing_loc: ∅ - │ │ └── block: ∅ - │ ├── call_operator_loc: (23,3)-(23,4) = "." - │ ├── name: :🌊= - │ ├── message_loc: (23,4)-(23,8) = "🌊" - │ ├── opening_loc: ∅ - │ ├── arguments: - │ │ @ ArgumentsNode (location: (23,11)-(23,12)) - │ │ ├── flags: ∅ - │ │ └── arguments: (length: 1) - │ │ └── @ IntegerNode (location: (23,11)-(23,12)) - │ │ └── flags: decimal - │ ├── closing_loc: ∅ - │ └── block: ∅ - ├── @ CallNode (location: (25,0)-(25,2)) + ├── @ CallNode (location: (23,0)-(23,2)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a? - │ ├── message_loc: (25,0)-(25,2) = "a?" + │ ├── message_loc: (23,0)-(23,2) = "a?" │ ├── opening_loc: ∅ │ ├── arguments: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (27,0)-(27,8)) + ├── @ CallNode (location: (25,0)-(25,8)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a - │ ├── message_loc: (27,0)-(27,1) = "a" - │ ├── opening_loc: (27,1)-(27,2) = "(" + │ ├── message_loc: (25,0)-(25,1) = "a" + │ ├── opening_loc: (25,1)-(25,2) = "(" │ ├── arguments: ∅ - │ ├── closing_loc: (27,8)-(27,9) = ")" + │ ├── closing_loc: (25,8)-(25,9) = ")" │ └── block: - │ @ BlockArgumentNode (location: (27,2)-(27,8)) + │ @ BlockArgumentNode (location: (25,2)-(25,8)) │ ├── expression: - │ │ @ CallNode (location: (27,3)-(27,8)) + │ │ @ CallNode (location: (25,3)-(25,8)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :block - │ │ ├── message_loc: (27,3)-(27,8) = "block" + │ │ ├── message_loc: (25,3)-(25,8) = "block" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ └── operator_loc: (27,2)-(27,3) = "&" - ├── @ CallNode (location: (29,0)-(29,11)) + │ └── operator_loc: (25,2)-(25,3) = "&" + ├── @ CallNode (location: (27,0)-(27,11)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a - │ ├── message_loc: (29,0)-(29,1) = "a" - │ ├── opening_loc: (29,1)-(29,2) = "(" + │ ├── message_loc: (27,0)-(27,1) = "a" + │ ├── opening_loc: (27,1)-(27,2) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (29,2)-(29,10)) + │ │ @ ArgumentsNode (location: (27,2)-(27,10)) │ │ ├── flags: contains_keyword_splat │ │ └── arguments: (length: 1) - │ │ └── @ KeywordHashNode (location: (29,2)-(29,10)) + │ │ └── @ KeywordHashNode (location: (27,2)-(27,10)) │ │ ├── flags: ∅ │ │ └── elements: (length: 1) - │ │ └── @ AssocSplatNode (location: (29,2)-(29,10)) + │ │ └── @ AssocSplatNode (location: (27,2)-(27,10)) │ │ ├── value: - │ │ │ @ CallNode (location: (29,4)-(29,10)) + │ │ │ @ CallNode (location: (27,4)-(27,10)) │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :kwargs - │ │ │ ├── message_loc: (29,4)-(29,10) = "kwargs" + │ │ │ ├── message_loc: (27,4)-(27,10) = "kwargs" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── operator_loc: (29,2)-(29,4) = "**" - │ ├── closing_loc: (29,10)-(29,11) = ")" + │ │ └── operator_loc: (27,2)-(27,4) = "**" + │ ├── closing_loc: (27,10)-(27,11) = ")" │ └── block: ∅ - ├── @ CallNode (location: (31,0)-(31,5)) + ├── @ CallNode (location: (29,0)-(29,5)) │ ├── flags: ∅ │ ├── receiver: - │ │ @ CallNode (location: (31,0)-(31,3)) + │ │ @ CallNode (location: (29,0)-(29,3)) │ │ ├── flags: ∅ │ │ ├── receiver: - │ │ │ @ CallNode (location: (31,0)-(31,1)) + │ │ │ @ CallNode (location: (29,0)-(29,1)) │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :a - │ │ │ ├── message_loc: (31,0)-(31,1) = "a" + │ │ │ ├── message_loc: (29,0)-(29,1) = "a" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ ├── call_operator_loc: (31,1)-(31,2) = "." + │ │ ├── call_operator_loc: (29,1)-(29,2) = "." │ │ ├── name: :b - │ │ ├── message_loc: (31,2)-(31,3) = "b" + │ │ ├── message_loc: (29,2)-(29,3) = "b" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── call_operator_loc: (31,3)-(31,4) = "." + │ ├── call_operator_loc: (29,3)-(29,4) = "." │ ├── name: :c - │ ├── message_loc: (31,4)-(31,5) = "c" + │ ├── message_loc: (29,4)-(29,5) = "c" │ ├── opening_loc: ∅ │ ├── arguments: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (33,0)-(33,7)) + ├── @ CallNode (location: (31,0)-(31,7)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a - │ ├── message_loc: (33,0)-(33,1) = "a" - │ ├── opening_loc: (33,1)-(33,2) = "(" + │ ├── message_loc: (31,0)-(31,1) = "a" + │ ├── opening_loc: (31,1)-(31,2) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (33,2)-(33,6)) + │ │ @ ArgumentsNode (location: (31,2)-(31,6)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ CallNode (location: (33,2)-(33,3)) + │ │ ├── @ CallNode (location: (31,2)-(31,3)) │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b - │ │ │ ├── message_loc: (33,2)-(33,3) = "b" + │ │ │ ├── message_loc: (31,2)-(31,3) = "b" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── @ CallNode (location: (33,5)-(33,6)) + │ │ └── @ CallNode (location: (31,5)-(31,6)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :c - │ │ ├── message_loc: (33,5)-(33,6) = "c" + │ │ ├── message_loc: (31,5)-(31,6) = "c" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── closing_loc: (33,6)-(33,7) = ")" + │ ├── closing_loc: (31,6)-(31,7) = ")" │ └── block: ∅ - ├── @ CallNode (location: (35,0)-(35,3)) + ├── @ CallNode (location: (33,0)-(33,3)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a - │ ├── message_loc: (35,0)-(35,1) = "a" - │ ├── opening_loc: (35,1)-(35,2) = "(" + │ ├── message_loc: (33,0)-(33,1) = "a" + │ ├── opening_loc: (33,1)-(33,2) = "(" │ ├── arguments: ∅ - │ ├── closing_loc: (35,2)-(35,3) = ")" + │ ├── closing_loc: (33,2)-(33,3) = ")" │ └── block: ∅ - ├── @ CallNode (location: (37,0)-(37,8)) + ├── @ CallNode (location: (35,0)-(35,8)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a - │ ├── message_loc: (37,0)-(37,1) = "a" - │ ├── opening_loc: (37,1)-(37,2) = "(" + │ ├── message_loc: (35,0)-(35,1) = "a" + │ ├── opening_loc: (35,1)-(35,2) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (37,2)-(37,7)) + │ │ @ ArgumentsNode (location: (35,2)-(35,7)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ SplatNode (location: (37,2)-(37,7)) - │ │ ├── operator_loc: (37,2)-(37,3) = "*" + │ │ └── @ SplatNode (location: (35,2)-(35,7)) + │ │ ├── operator_loc: (35,2)-(35,3) = "*" │ │ └── expression: - │ │ @ CallNode (location: (37,3)-(37,7)) + │ │ @ CallNode (location: (35,3)-(35,7)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :args - │ │ ├── message_loc: (37,3)-(37,7) = "args" + │ │ ├── message_loc: (35,3)-(35,7) = "args" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── closing_loc: (37,7)-(37,8) = ")" + │ ├── closing_loc: (35,7)-(35,8) = ")" │ └── block: ∅ - ├── @ CallNode (location: (39,0)-(39,6)) + ├── @ CallNode (location: (37,0)-(37,6)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :a - │ ├── message_loc: (39,0)-(39,1) = "a" + │ ├── message_loc: (37,0)-(37,1) = "a" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (39,2)-(39,6)) + │ │ @ ArgumentsNode (location: (37,2)-(37,6)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ CallNode (location: (39,2)-(39,3)) + │ │ ├── @ CallNode (location: (37,2)-(37,3)) │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :b - │ │ │ ├── message_loc: (39,2)-(39,3) = "b" + │ │ │ ├── message_loc: (37,2)-(37,3) = "b" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── @ CallNode (location: (39,5)-(39,6)) + │ │ └── @ CallNode (location: (37,5)-(37,6)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :c - │ │ ├── message_loc: (39,5)-(39,6) = "c" + │ │ ├── message_loc: (37,5)-(37,6) = "c" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (41,0)-(41,8)) + ├── @ CallNode (location: (39,0)-(39,8)) │ ├── flags: ∅ │ ├── receiver: - │ │ @ CallNode (location: (41,0)-(41,1)) + │ │ @ CallNode (location: (39,0)-(39,1)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a - │ │ ├── message_loc: (41,0)-(41,1) = "a" + │ │ ├── message_loc: (39,0)-(39,1) = "a" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── call_operator_loc: (41,1)-(41,2) = "." + │ ├── call_operator_loc: (39,1)-(39,2) = "." │ ├── name: :b - │ ├── message_loc: (41,2)-(41,3) = "b" + │ ├── message_loc: (39,2)-(39,3) = "b" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (41,4)-(41,8)) + │ │ @ ArgumentsNode (location: (39,4)-(39,8)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ CallNode (location: (41,4)-(41,5)) + │ │ ├── @ CallNode (location: (39,4)-(39,5)) │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :c - │ │ │ ├── message_loc: (41,4)-(41,5) = "c" + │ │ │ ├── message_loc: (39,4)-(39,5) = "c" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── @ CallNode (location: (41,7)-(41,8)) + │ │ └── @ CallNode (location: (39,7)-(39,8)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :d - │ │ ├── message_loc: (41,7)-(41,8) = "d" + │ │ ├── message_loc: (39,7)-(39,8) = "d" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ MultiWriteNode (location: (43,0)-(43,23)) + ├── @ MultiWriteNode (location: (41,0)-(41,23)) │ ├── lefts: (length: 2) - │ │ ├── @ CallTargetNode (location: (43,0)-(43,7)) + │ │ ├── @ CallTargetNode (location: (41,0)-(41,7)) │ │ │ ├── flags: ∅ │ │ │ ├── receiver: - │ │ │ │ @ CallNode (location: (43,0)-(43,3)) + │ │ │ │ @ CallNode (location: (41,0)-(41,3)) │ │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :foo - │ │ │ │ ├── message_loc: (43,0)-(43,3) = "foo" + │ │ │ │ ├── message_loc: (41,0)-(41,3) = "foo" │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── arguments: ∅ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ - │ │ │ ├── call_operator_loc: (43,3)-(43,4) = "." + │ │ │ ├── call_operator_loc: (41,3)-(41,4) = "." │ │ │ ├── name: :foo= - │ │ │ └── message_loc: (43,4)-(43,7) = "foo" - │ │ └── @ CallTargetNode (location: (43,9)-(43,16)) + │ │ │ └── message_loc: (41,4)-(41,7) = "foo" + │ │ └── @ CallTargetNode (location: (41,9)-(41,16)) │ │ ├── flags: ∅ │ │ ├── receiver: - │ │ │ @ CallNode (location: (43,9)-(43,12)) + │ │ │ @ CallNode (location: (41,9)-(41,12)) │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :bar - │ │ │ ├── message_loc: (43,9)-(43,12) = "bar" + │ │ │ ├── message_loc: (41,9)-(41,12) = "bar" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ ├── call_operator_loc: (43,12)-(43,13) = "." + │ │ ├── call_operator_loc: (41,12)-(41,13) = "." │ │ ├── name: :bar= - │ │ └── message_loc: (43,13)-(43,16) = "bar" + │ │ └── message_loc: (41,13)-(41,16) = "bar" │ ├── rest: ∅ │ ├── rights: (length: 0) │ ├── lparen_loc: ∅ │ ├── rparen_loc: ∅ - │ ├── operator_loc: (43,17)-(43,18) = "=" + │ ├── operator_loc: (41,17)-(41,18) = "=" │ └── value: - │ @ ArrayNode (location: (43,19)-(43,23)) + │ @ ArrayNode (location: (41,19)-(41,23)) │ ├── flags: ∅ │ ├── elements: (length: 2) - │ │ ├── @ IntegerNode (location: (43,19)-(43,20)) + │ │ ├── @ IntegerNode (location: (41,19)-(41,20)) │ │ │ └── flags: decimal - │ │ └── @ IntegerNode (location: (43,22)-(43,23)) + │ │ └── @ IntegerNode (location: (41,22)-(41,23)) │ │ └── flags: decimal │ ├── opening_loc: ∅ │ └── closing_loc: ∅ - ├── @ CallNode (location: (45,0)-(45,4)) + ├── @ CallNode (location: (43,0)-(43,4)) │ ├── flags: safe_navigation │ ├── receiver: - │ │ @ CallNode (location: (45,0)-(45,1)) + │ │ @ CallNode (location: (43,0)-(43,1)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a - │ │ ├── message_loc: (45,0)-(45,1) = "a" + │ │ ├── message_loc: (43,0)-(43,1) = "a" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── call_operator_loc: (45,1)-(45,3) = "&." + │ ├── call_operator_loc: (43,1)-(43,3) = "&." │ ├── name: :b - │ ├── message_loc: (45,3)-(45,4) = "b" + │ ├── message_loc: (43,3)-(43,4) = "b" │ ├── opening_loc: ∅ │ ├── arguments: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (47,0)-(47,5)) + ├── @ CallNode (location: (45,0)-(45,5)) │ ├── flags: safe_navigation │ ├── receiver: - │ │ @ CallNode (location: (47,0)-(47,1)) + │ │ @ CallNode (location: (45,0)-(45,1)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a - │ │ ├── message_loc: (47,0)-(47,1) = "a" + │ │ ├── message_loc: (45,0)-(45,1) = "a" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── call_operator_loc: (47,1)-(47,3) = "&." + │ ├── call_operator_loc: (45,1)-(45,3) = "&." │ ├── name: :call │ ├── message_loc: ∅ - │ ├── opening_loc: (47,3)-(47,4) = "(" + │ ├── opening_loc: (45,3)-(45,4) = "(" │ ├── arguments: ∅ - │ ├── closing_loc: (47,4)-(47,5) = ")" + │ ├── closing_loc: (45,4)-(45,5) = ")" │ └── block: ∅ - ├── @ CallNode (location: (49,0)-(49,7)) + ├── @ CallNode (location: (47,0)-(47,7)) │ ├── flags: safe_navigation │ ├── receiver: - │ │ @ CallNode (location: (49,0)-(49,1)) + │ │ @ CallNode (location: (47,0)-(47,1)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a - │ │ ├── message_loc: (49,0)-(49,1) = "a" + │ │ ├── message_loc: (47,0)-(47,1) = "a" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── call_operator_loc: (49,1)-(49,3) = "&." + │ ├── call_operator_loc: (47,1)-(47,3) = "&." │ ├── name: :b - │ ├── message_loc: (49,3)-(49,4) = "b" - │ ├── opening_loc: (49,4)-(49,5) = "(" + │ ├── message_loc: (47,3)-(47,4) = "b" + │ ├── opening_loc: (47,4)-(47,5) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (49,5)-(49,6)) + │ │ @ ArgumentsNode (location: (47,5)-(47,6)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ CallNode (location: (49,5)-(49,6)) + │ │ └── @ CallNode (location: (47,5)-(47,6)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :c - │ │ ├── message_loc: (49,5)-(49,6) = "c" + │ │ ├── message_loc: (47,5)-(47,6) = "c" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── closing_loc: (49,6)-(49,7) = ")" + │ ├── closing_loc: (47,6)-(47,7) = ")" │ └── block: ∅ - ├── @ CallNode (location: (51,0)-(51,6)) + ├── @ CallNode (location: (49,0)-(49,6)) │ ├── flags: safe_navigation │ ├── receiver: - │ │ @ CallNode (location: (51,0)-(51,1)) + │ │ @ CallNode (location: (49,0)-(49,1)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :a - │ │ ├── message_loc: (51,0)-(51,1) = "a" + │ │ ├── message_loc: (49,0)-(49,1) = "a" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── call_operator_loc: (51,1)-(51,3) = "&." + │ ├── call_operator_loc: (49,1)-(49,3) = "&." │ ├── name: :b - │ ├── message_loc: (51,3)-(51,4) = "b" - │ ├── opening_loc: (51,4)-(51,5) = "(" + │ ├── message_loc: (49,3)-(49,4) = "b" + │ ├── opening_loc: (49,4)-(49,5) = "(" │ ├── arguments: ∅ - │ ├── closing_loc: (51,5)-(51,6) = ")" + │ ├── closing_loc: (49,5)-(49,6) = ")" │ └── block: ∅ - ├── @ IfNode (location: (53,0)-(53,33)) - │ ├── if_keyword_loc: (53,11)-(53,13) = "if" + ├── @ IfNode (location: (51,0)-(51,33)) + │ ├── if_keyword_loc: (51,11)-(51,13) = "if" │ ├── predicate: - │ │ @ AndNode (location: (53,14)-(53,33)) + │ │ @ AndNode (location: (51,14)-(51,33)) │ │ ├── left: - │ │ │ @ OrNode (location: (53,14)-(53,25)) + │ │ │ @ OrNode (location: (51,14)-(51,25)) │ │ │ ├── left: - │ │ │ │ @ CallNode (location: (53,14)-(53,18)) + │ │ │ │ @ CallNode (location: (51,14)-(51,18)) │ │ │ │ ├── flags: ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :bar? - │ │ │ │ ├── message_loc: (53,14)-(53,18) = "bar?" + │ │ │ │ ├── message_loc: (51,14)-(51,18) = "bar?" │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── arguments: ∅ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ │ │ │ ├── right: - │ │ │ │ @ CallNode (location: (53,22)-(53,25)) + │ │ │ │ @ CallNode (location: (51,22)-(51,25)) │ │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :baz - │ │ │ │ ├── message_loc: (53,22)-(53,25) = "baz" + │ │ │ │ ├── message_loc: (51,22)-(51,25) = "baz" │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── arguments: ∅ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ - │ │ │ └── operator_loc: (53,19)-(53,21) = "or" + │ │ │ └── operator_loc: (51,19)-(51,21) = "or" │ │ ├── right: - │ │ │ @ CallNode (location: (53,30)-(53,33)) + │ │ │ @ CallNode (location: (51,30)-(51,33)) │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :qux - │ │ │ ├── message_loc: (53,30)-(53,33) = "qux" + │ │ │ ├── message_loc: (51,30)-(51,33) = "qux" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── operator_loc: (53,26)-(53,29) = "and" + │ │ └── operator_loc: (51,26)-(51,29) = "and" │ ├── then_keyword_loc: ∅ │ ├── statements: - │ │ @ StatementsNode (location: (53,0)-(53,10)) + │ │ @ StatementsNode (location: (51,0)-(51,10)) │ │ └── body: (length: 1) - │ │ └── @ CallNode (location: (53,0)-(53,10)) + │ │ └── @ CallNode (location: (51,0)-(51,10)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo - │ │ ├── message_loc: (53,0)-(53,3) = "foo" + │ │ ├── message_loc: (51,0)-(51,3) = "foo" │ │ ├── opening_loc: ∅ │ │ ├── arguments: - │ │ │ @ ArgumentsNode (location: (53,4)-(53,10)) + │ │ │ @ ArgumentsNode (location: (51,4)-(51,10)) │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 2) - │ │ │ ├── @ SymbolNode (location: (53,4)-(53,6)) + │ │ │ ├── @ SymbolNode (location: (51,4)-(51,6)) │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── opening_loc: (53,4)-(53,5) = ":" - │ │ │ │ ├── value_loc: (53,5)-(53,6) = "a" + │ │ │ │ ├── opening_loc: (51,4)-(51,5) = ":" + │ │ │ │ ├── value_loc: (51,5)-(51,6) = "a" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "a" - │ │ │ └── @ SymbolNode (location: (53,8)-(53,10)) + │ │ │ └── @ SymbolNode (location: (51,8)-(51,10)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (53,8)-(53,9) = ":" - │ │ │ ├── value_loc: (53,9)-(53,10) = "b" + │ │ │ ├── opening_loc: (51,8)-(51,9) = ":" + │ │ │ ├── value_loc: (51,9)-(51,10) = "b" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "b" │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── consequent: ∅ │ └── end_keyword_loc: ∅ - ├── @ CallNode (location: (55,0)-(58,1)) + ├── @ CallNode (location: (53,0)-(56,1)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (55,0)-(55,3) = "foo" - │ ├── opening_loc: (55,3)-(55,4) = "(" + │ ├── message_loc: (53,0)-(53,3) = "foo" + │ ├── opening_loc: (53,3)-(53,4) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (55,4)-(57,4)) + │ │ @ ArgumentsNode (location: (53,4)-(55,4)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ SymbolNode (location: (55,4)-(55,6)) + │ │ ├── @ SymbolNode (location: (53,4)-(53,6)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (55,4)-(55,5) = ":" - │ │ │ ├── value_loc: (55,5)-(55,6) = "a" + │ │ │ ├── opening_loc: (53,4)-(53,5) = ":" + │ │ │ ├── value_loc: (53,5)-(53,6) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" - │ │ └── @ SymbolNode (location: (57,2)-(57,4)) + │ │ └── @ SymbolNode (location: (55,2)-(55,4)) │ │ ├── flags: ∅ - │ │ ├── opening_loc: (57,2)-(57,3) = ":" - │ │ ├── value_loc: (57,3)-(57,4) = "b" + │ │ ├── opening_loc: (55,2)-(55,3) = ":" + │ │ ├── value_loc: (55,3)-(55,4) = "b" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "b" - │ ├── closing_loc: (58,0)-(58,1) = ")" + │ ├── closing_loc: (56,0)-(56,1) = ")" │ └── block: ∅ - ├── @ CallNode (location: (60,0)-(60,10)) + ├── @ CallNode (location: (58,0)-(58,10)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (60,0)-(60,3) = "foo" - │ ├── opening_loc: (60,3)-(60,4) = "(" + │ ├── message_loc: (58,0)-(58,3) = "foo" + │ ├── opening_loc: (58,3)-(58,4) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (60,4)-(60,9)) + │ │ @ ArgumentsNode (location: (58,4)-(58,9)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ SplatNode (location: (60,4)-(60,9)) - │ │ ├── operator_loc: (60,4)-(60,5) = "*" + │ │ └── @ SplatNode (location: (58,4)-(58,9)) + │ │ ├── operator_loc: (58,4)-(58,5) = "*" │ │ └── expression: - │ │ @ CallNode (location: (60,5)-(60,9)) + │ │ @ CallNode (location: (58,5)-(58,9)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :rest - │ │ ├── message_loc: (60,5)-(60,9) = "rest" + │ │ ├── message_loc: (58,5)-(58,9) = "rest" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── closing_loc: (60,9)-(60,10) = ")" + │ ├── closing_loc: (58,9)-(58,10) = ")" │ └── block: ∅ - ├── @ CallNode (location: (62,0)-(62,39)) + ├── @ CallNode (location: (60,0)-(60,39)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (62,0)-(62,3) = "foo" - │ ├── opening_loc: (62,3)-(62,4) = "(" + │ ├── message_loc: (60,0)-(60,3) = "foo" + │ ├── opening_loc: (60,3)-(60,4) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (62,4)-(62,32)) + │ │ @ ArgumentsNode (location: (60,4)-(60,32)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ SymbolNode (location: (62,4)-(62,6)) + │ │ ├── @ SymbolNode (location: (60,4)-(60,6)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (62,4)-(62,5) = ":" - │ │ │ ├── value_loc: (62,5)-(62,6) = "a" + │ │ │ ├── opening_loc: (60,4)-(60,5) = ":" + │ │ │ ├── value_loc: (60,5)-(60,6) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" - │ │ └── @ KeywordHashNode (location: (62,8)-(62,32)) + │ │ └── @ KeywordHashNode (location: (60,8)-(60,32)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 2) - │ │ ├── @ AssocNode (location: (62,8)-(62,22)) + │ │ ├── @ AssocNode (location: (60,8)-(60,22)) │ │ │ ├── key: - │ │ │ │ @ SymbolNode (location: (62,8)-(62,10)) + │ │ │ │ @ SymbolNode (location: (60,8)-(60,10)) │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── opening_loc: (62,8)-(62,9) = ":" - │ │ │ │ ├── value_loc: (62,9)-(62,10) = "h" + │ │ │ │ ├── opening_loc: (60,8)-(60,9) = ":" + │ │ │ │ ├── value_loc: (60,9)-(60,10) = "h" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "h" │ │ │ ├── value: - │ │ │ │ @ ArrayNode (location: (62,14)-(62,22)) + │ │ │ │ @ ArrayNode (location: (60,14)-(60,22)) │ │ │ │ ├── flags: ∅ │ │ │ │ ├── elements: (length: 2) - │ │ │ │ │ ├── @ SymbolNode (location: (62,15)-(62,17)) + │ │ │ │ │ ├── @ SymbolNode (location: (60,15)-(60,17)) │ │ │ │ │ │ ├── flags: ∅ - │ │ │ │ │ │ ├── opening_loc: (62,15)-(62,16) = ":" - │ │ │ │ │ │ ├── value_loc: (62,16)-(62,17) = "x" + │ │ │ │ │ │ ├── opening_loc: (60,15)-(60,16) = ":" + │ │ │ │ │ │ ├── value_loc: (60,16)-(60,17) = "x" │ │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ │ └── unescaped: "x" - │ │ │ │ │ └── @ SymbolNode (location: (62,19)-(62,21)) + │ │ │ │ │ └── @ SymbolNode (location: (60,19)-(60,21)) │ │ │ │ │ ├── flags: ∅ - │ │ │ │ │ ├── opening_loc: (62,19)-(62,20) = ":" - │ │ │ │ │ ├── value_loc: (62,20)-(62,21) = "y" + │ │ │ │ │ ├── opening_loc: (60,19)-(60,20) = ":" + │ │ │ │ │ ├── value_loc: (60,20)-(60,21) = "y" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "y" - │ │ │ │ ├── opening_loc: (62,14)-(62,15) = "[" - │ │ │ │ └── closing_loc: (62,21)-(62,22) = "]" - │ │ │ └── operator_loc: (62,11)-(62,13) = "=>" - │ │ └── @ AssocNode (location: (62,24)-(62,32)) + │ │ │ │ ├── opening_loc: (60,14)-(60,15) = "[" + │ │ │ │ └── closing_loc: (60,21)-(60,22) = "]" + │ │ │ └── operator_loc: (60,11)-(60,13) = "=>" + │ │ └── @ AssocNode (location: (60,24)-(60,32)) │ │ ├── key: - │ │ │ @ SymbolNode (location: (62,24)-(62,26)) + │ │ │ @ SymbolNode (location: (60,24)-(60,26)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (62,24)-(62,25) = ":" - │ │ │ ├── value_loc: (62,25)-(62,26) = "a" + │ │ │ ├── opening_loc: (60,24)-(60,25) = ":" + │ │ │ ├── value_loc: (60,25)-(60,26) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ ├── value: - │ │ │ @ SymbolNode (location: (62,30)-(62,32)) + │ │ │ @ SymbolNode (location: (60,30)-(60,32)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (62,30)-(62,31) = ":" - │ │ │ ├── value_loc: (62,31)-(62,32) = "b" + │ │ │ ├── opening_loc: (60,30)-(60,31) = ":" + │ │ │ ├── value_loc: (60,31)-(60,32) = "b" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "b" - │ │ └── operator_loc: (62,27)-(62,29) = "=>" - │ ├── closing_loc: (62,39)-(62,40) = ")" + │ │ └── operator_loc: (60,27)-(60,29) = "=>" + │ ├── closing_loc: (60,39)-(60,40) = ")" │ └── block: - │ @ BlockArgumentNode (location: (62,34)-(62,39)) + │ @ BlockArgumentNode (location: (60,34)-(60,39)) │ ├── expression: - │ │ @ SymbolNode (location: (62,35)-(62,39)) + │ │ @ SymbolNode (location: (60,35)-(60,39)) │ │ ├── flags: ∅ - │ │ ├── opening_loc: (62,35)-(62,36) = ":" - │ │ ├── value_loc: (62,36)-(62,39) = "bar" + │ │ ├── opening_loc: (60,35)-(60,36) = ":" + │ │ ├── value_loc: (60,36)-(60,39) = "bar" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "bar" - │ └── operator_loc: (62,34)-(62,35) = "&" - ├── @ CallNode (location: (64,0)-(64,49)) + │ └── operator_loc: (60,34)-(60,35) = "&" + ├── @ CallNode (location: (62,0)-(62,49)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :hi - │ ├── message_loc: (64,0)-(64,2) = "hi" + │ ├── message_loc: (62,0)-(62,2) = "hi" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (64,3)-(64,49)) + │ │ @ ArgumentsNode (location: (62,3)-(62,49)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ IntegerNode (location: (64,3)-(64,6)) + │ │ ├── @ IntegerNode (location: (62,3)-(62,6)) │ │ │ └── flags: decimal - │ │ └── @ HashNode (location: (64,8)-(64,49)) - │ │ ├── opening_loc: (64,8)-(64,9) = "{" + │ │ └── @ HashNode (location: (62,8)-(62,49)) + │ │ ├── opening_loc: (62,8)-(62,9) = "{" │ │ ├── elements: (length: 3) - │ │ │ ├── @ AssocNode (location: (64,10)-(64,27)) + │ │ │ ├── @ AssocNode (location: (62,10)-(62,27)) │ │ │ │ ├── key: - │ │ │ │ │ @ SymbolNode (location: (64,10)-(64,16)) + │ │ │ │ │ @ SymbolNode (location: (62,10)-(62,16)) │ │ │ │ │ ├── flags: ∅ - │ │ │ │ │ ├── opening_loc: (64,10)-(64,11) = ":" - │ │ │ │ │ ├── value_loc: (64,11)-(64,16) = "there" + │ │ │ │ │ ├── opening_loc: (62,10)-(62,11) = ":" + │ │ │ │ │ ├── value_loc: (62,11)-(62,16) = "there" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "there" │ │ │ │ ├── value: - │ │ │ │ │ @ SymbolNode (location: (64,20)-(64,27)) + │ │ │ │ │ @ SymbolNode (location: (62,20)-(62,27)) │ │ │ │ │ ├── flags: ∅ - │ │ │ │ │ ├── opening_loc: (64,20)-(64,21) = ":" - │ │ │ │ │ ├── value_loc: (64,21)-(64,27) = "friend" + │ │ │ │ │ ├── opening_loc: (62,20)-(62,21) = ":" + │ │ │ │ │ ├── value_loc: (62,21)-(62,27) = "friend" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "friend" - │ │ │ │ └── operator_loc: (64,17)-(64,19) = "=>" - │ │ │ ├── @ AssocSplatNode (location: (64,29)-(64,33)) + │ │ │ │ └── operator_loc: (62,17)-(62,19) = "=>" + │ │ │ ├── @ AssocSplatNode (location: (62,29)-(62,33)) │ │ │ │ ├── value: - │ │ │ │ │ @ HashNode (location: (64,31)-(64,33)) - │ │ │ │ │ ├── opening_loc: (64,31)-(64,32) = "{" + │ │ │ │ │ @ HashNode (location: (62,31)-(62,33)) + │ │ │ │ │ ├── opening_loc: (62,31)-(62,32) = "{" │ │ │ │ │ ├── elements: (length: 0) - │ │ │ │ │ └── closing_loc: (64,32)-(64,33) = "}" - │ │ │ │ └── operator_loc: (64,29)-(64,31) = "**" - │ │ │ └── @ AssocNode (location: (64,35)-(64,47)) + │ │ │ │ │ └── closing_loc: (62,32)-(62,33) = "}" + │ │ │ │ └── operator_loc: (62,29)-(62,31) = "**" + │ │ │ └── @ AssocNode (location: (62,35)-(62,47)) │ │ │ ├── key: - │ │ │ │ @ SymbolNode (location: (64,35)-(64,42)) + │ │ │ │ @ SymbolNode (location: (62,35)-(62,42)) │ │ │ │ ├── flags: ∅ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ ├── value_loc: (64,35)-(64,41) = "whatup" - │ │ │ │ ├── closing_loc: (64,41)-(64,42) = ":" + │ │ │ │ ├── value_loc: (62,35)-(62,41) = "whatup" + │ │ │ │ ├── closing_loc: (62,41)-(62,42) = ":" │ │ │ │ └── unescaped: "whatup" │ │ │ ├── value: - │ │ │ │ @ SymbolNode (location: (64,43)-(64,47)) + │ │ │ │ @ SymbolNode (location: (62,43)-(62,47)) │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── opening_loc: (64,43)-(64,44) = ":" - │ │ │ │ ├── value_loc: (64,44)-(64,47) = "dog" + │ │ │ │ ├── opening_loc: (62,43)-(62,44) = ":" + │ │ │ │ ├── value_loc: (62,44)-(62,47) = "dog" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "dog" │ │ │ └── operator_loc: ∅ - │ │ └── closing_loc: (64,48)-(64,49) = "}" + │ │ └── closing_loc: (62,48)-(62,49) = "}" │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (66,0)-(66,36)) + ├── @ CallNode (location: (64,0)-(64,36)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (66,0)-(66,3) = "foo" + │ ├── message_loc: (64,0)-(64,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (66,4)-(66,15)) + │ │ @ ArgumentsNode (location: (64,4)-(64,15)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ SymbolNode (location: (66,4)-(66,6)) + │ │ ├── @ SymbolNode (location: (64,4)-(64,6)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (66,4)-(66,5) = ":" - │ │ │ ├── value_loc: (66,5)-(66,6) = "a" + │ │ │ ├── opening_loc: (64,4)-(64,5) = ":" + │ │ │ ├── value_loc: (64,5)-(64,6) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" - │ │ └── @ KeywordHashNode (location: (66,8)-(66,15)) + │ │ └── @ KeywordHashNode (location: (64,8)-(64,15)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) - │ │ └── @ AssocNode (location: (66,8)-(66,15)) + │ │ └── @ AssocNode (location: (64,8)-(64,15)) │ │ ├── key: - │ │ │ @ SymbolNode (location: (66,8)-(66,10)) + │ │ │ @ SymbolNode (location: (64,8)-(64,10)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── value_loc: (66,8)-(66,9) = "b" - │ │ │ ├── closing_loc: (66,9)-(66,10) = ":" + │ │ │ ├── value_loc: (64,8)-(64,9) = "b" + │ │ │ ├── closing_loc: (64,9)-(64,10) = ":" │ │ │ └── unescaped: "b" │ │ ├── value: - │ │ │ @ TrueNode (location: (66,11)-(66,15)) + │ │ │ @ TrueNode (location: (64,11)-(64,15)) │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: - │ @ BlockNode (location: (66,16)-(66,36)) + │ @ BlockNode (location: (64,16)-(64,36)) │ ├── locals: [:a, :b] │ ├── locals_body_index: 2 │ ├── parameters: - │ │ @ BlockParametersNode (location: (66,19)-(66,25)) + │ │ @ BlockParametersNode (location: (64,19)-(64,25)) │ │ ├── parameters: - │ │ │ @ ParametersNode (location: (66,20)-(66,24)) + │ │ │ @ ParametersNode (location: (64,20)-(64,24)) │ │ │ ├── requireds: (length: 2) - │ │ │ │ ├── @ RequiredParameterNode (location: (66,20)-(66,21)) + │ │ │ │ ├── @ RequiredParameterNode (location: (64,20)-(64,21)) │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :a - │ │ │ │ └── @ RequiredParameterNode (location: (66,23)-(66,24)) + │ │ │ │ └── @ RequiredParameterNode (location: (64,23)-(64,24)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── name: :b │ │ │ ├── optionals: (length: 0) @@ -975,486 +950,513 @@ │ │ │ ├── keyword_rest: ∅ │ │ │ └── block: ∅ │ │ ├── locals: (length: 0) - │ │ ├── opening_loc: (66,19)-(66,20) = "|" - │ │ └── closing_loc: (66,24)-(66,25) = "|" + │ │ ├── opening_loc: (64,19)-(64,20) = "|" + │ │ └── closing_loc: (64,24)-(64,25) = "|" │ ├── body: - │ │ @ StatementsNode (location: (66,26)-(66,32)) + │ │ @ StatementsNode (location: (64,26)-(64,32)) │ │ └── body: (length: 1) - │ │ └── @ CallNode (location: (66,26)-(66,32)) + │ │ └── @ CallNode (location: (64,26)-(64,32)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :puts - │ │ ├── message_loc: (66,26)-(66,30) = "puts" + │ │ ├── message_loc: (64,26)-(64,30) = "puts" │ │ ├── opening_loc: ∅ │ │ ├── arguments: - │ │ │ @ ArgumentsNode (location: (66,31)-(66,32)) + │ │ │ @ ArgumentsNode (location: (64,31)-(64,32)) │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) - │ │ │ └── @ LocalVariableReadNode (location: (66,31)-(66,32)) + │ │ │ └── @ LocalVariableReadNode (location: (64,31)-(64,32)) │ │ │ ├── name: :a │ │ │ └── depth: 0 │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── opening_loc: (66,16)-(66,18) = "do" - │ └── closing_loc: (66,33)-(66,36) = "end" - ├── @ CallNode (location: (68,0)-(68,17)) + │ ├── opening_loc: (64,16)-(64,18) = "do" + │ └── closing_loc: (64,33)-(64,36) = "end" + ├── @ CallNode (location: (66,0)-(66,17)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :hi - │ ├── message_loc: (68,0)-(68,2) = "hi" + │ ├── message_loc: (66,0)-(66,2) = "hi" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (68,3)-(68,17)) + │ │ @ ArgumentsNode (location: (66,3)-(66,17)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ KeywordHashNode (location: (68,3)-(68,17)) + │ │ └── @ KeywordHashNode (location: (66,3)-(66,17)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) - │ │ └── @ AssocNode (location: (68,3)-(68,17)) + │ │ └── @ AssocNode (location: (66,3)-(66,17)) │ │ ├── key: - │ │ │ @ SymbolNode (location: (68,3)-(68,9)) + │ │ │ @ SymbolNode (location: (66,3)-(66,9)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── value_loc: (68,3)-(68,8) = "there" - │ │ │ ├── closing_loc: (68,8)-(68,9) = ":" + │ │ │ ├── value_loc: (66,3)-(66,8) = "there" + │ │ │ ├── closing_loc: (66,8)-(66,9) = ":" │ │ │ └── unescaped: "there" │ │ ├── value: - │ │ │ @ SymbolNode (location: (68,10)-(68,17)) + │ │ │ @ SymbolNode (location: (66,10)-(66,17)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (68,10)-(68,11) = ":" - │ │ │ ├── value_loc: (68,11)-(68,17) = "friend" + │ │ │ ├── opening_loc: (66,10)-(66,11) = ":" + │ │ │ ├── value_loc: (66,11)-(66,17) = "friend" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "friend" │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (70,0)-(70,40)) + ├── @ CallNode (location: (68,0)-(68,40)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :hi - │ ├── message_loc: (70,0)-(70,2) = "hi" + │ ├── message_loc: (68,0)-(68,2) = "hi" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (70,3)-(70,40)) + │ │ @ ArgumentsNode (location: (68,3)-(68,40)) │ │ ├── flags: contains_keyword_splat │ │ └── arguments: (length: 1) - │ │ └── @ KeywordHashNode (location: (70,3)-(70,40)) + │ │ └── @ KeywordHashNode (location: (68,3)-(68,40)) │ │ ├── flags: ∅ │ │ └── elements: (length: 3) - │ │ ├── @ AssocNode (location: (70,3)-(70,20)) + │ │ ├── @ AssocNode (location: (68,3)-(68,20)) │ │ │ ├── key: - │ │ │ │ @ SymbolNode (location: (70,3)-(70,9)) + │ │ │ │ @ SymbolNode (location: (68,3)-(68,9)) │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── opening_loc: (70,3)-(70,4) = ":" - │ │ │ │ ├── value_loc: (70,4)-(70,9) = "there" + │ │ │ │ ├── opening_loc: (68,3)-(68,4) = ":" + │ │ │ │ ├── value_loc: (68,4)-(68,9) = "there" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "there" │ │ │ ├── value: - │ │ │ │ @ SymbolNode (location: (70,13)-(70,20)) + │ │ │ │ @ SymbolNode (location: (68,13)-(68,20)) │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── opening_loc: (70,13)-(70,14) = ":" - │ │ │ │ ├── value_loc: (70,14)-(70,20) = "friend" + │ │ │ │ ├── opening_loc: (68,13)-(68,14) = ":" + │ │ │ │ ├── value_loc: (68,14)-(68,20) = "friend" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "friend" - │ │ │ └── operator_loc: (70,10)-(70,12) = "=>" - │ │ ├── @ AssocSplatNode (location: (70,22)-(70,26)) + │ │ │ └── operator_loc: (68,10)-(68,12) = "=>" + │ │ ├── @ AssocSplatNode (location: (68,22)-(68,26)) │ │ │ ├── value: - │ │ │ │ @ HashNode (location: (70,24)-(70,26)) - │ │ │ │ ├── opening_loc: (70,24)-(70,25) = "{" + │ │ │ │ @ HashNode (location: (68,24)-(68,26)) + │ │ │ │ ├── opening_loc: (68,24)-(68,25) = "{" │ │ │ │ ├── elements: (length: 0) - │ │ │ │ └── closing_loc: (70,25)-(70,26) = "}" - │ │ │ └── operator_loc: (70,22)-(70,24) = "**" - │ │ └── @ AssocNode (location: (70,28)-(70,40)) + │ │ │ │ └── closing_loc: (68,25)-(68,26) = "}" + │ │ │ └── operator_loc: (68,22)-(68,24) = "**" + │ │ └── @ AssocNode (location: (68,28)-(68,40)) │ │ ├── key: - │ │ │ @ SymbolNode (location: (70,28)-(70,35)) + │ │ │ @ SymbolNode (location: (68,28)-(68,35)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── value_loc: (70,28)-(70,34) = "whatup" - │ │ │ ├── closing_loc: (70,34)-(70,35) = ":" + │ │ │ ├── value_loc: (68,28)-(68,34) = "whatup" + │ │ │ ├── closing_loc: (68,34)-(68,35) = ":" │ │ │ └── unescaped: "whatup" │ │ ├── value: - │ │ │ @ SymbolNode (location: (70,36)-(70,40)) + │ │ │ @ SymbolNode (location: (68,36)-(68,40)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (70,36)-(70,37) = ":" - │ │ │ ├── value_loc: (70,37)-(70,40) = "dog" + │ │ │ ├── opening_loc: (68,36)-(68,37) = ":" + │ │ │ ├── value_loc: (68,37)-(68,40) = "dog" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "dog" │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (72,0)-(72,41)) + ├── @ CallNode (location: (70,0)-(70,41)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :hi - │ ├── message_loc: (72,0)-(72,2) = "hi" - │ ├── opening_loc: (72,2)-(72,3) = "(" + │ ├── message_loc: (70,0)-(70,2) = "hi" + │ ├── opening_loc: (70,2)-(70,3) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (72,3)-(72,40)) + │ │ @ ArgumentsNode (location: (70,3)-(70,40)) │ │ ├── flags: contains_keyword_splat │ │ └── arguments: (length: 1) - │ │ └── @ KeywordHashNode (location: (72,3)-(72,40)) + │ │ └── @ KeywordHashNode (location: (70,3)-(70,40)) │ │ ├── flags: ∅ │ │ └── elements: (length: 3) - │ │ ├── @ AssocNode (location: (72,3)-(72,20)) + │ │ ├── @ AssocNode (location: (70,3)-(70,20)) │ │ │ ├── key: - │ │ │ │ @ SymbolNode (location: (72,3)-(72,9)) + │ │ │ │ @ SymbolNode (location: (70,3)-(70,9)) │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── opening_loc: (72,3)-(72,4) = ":" - │ │ │ │ ├── value_loc: (72,4)-(72,9) = "there" + │ │ │ │ ├── opening_loc: (70,3)-(70,4) = ":" + │ │ │ │ ├── value_loc: (70,4)-(70,9) = "there" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "there" │ │ │ ├── value: - │ │ │ │ @ SymbolNode (location: (72,13)-(72,20)) + │ │ │ │ @ SymbolNode (location: (70,13)-(70,20)) │ │ │ │ ├── flags: ∅ - │ │ │ │ ├── opening_loc: (72,13)-(72,14) = ":" - │ │ │ │ ├── value_loc: (72,14)-(72,20) = "friend" + │ │ │ │ ├── opening_loc: (70,13)-(70,14) = ":" + │ │ │ │ ├── value_loc: (70,14)-(70,20) = "friend" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "friend" - │ │ │ └── operator_loc: (72,10)-(72,12) = "=>" - │ │ ├── @ AssocSplatNode (location: (72,22)-(72,26)) + │ │ │ └── operator_loc: (70,10)-(70,12) = "=>" + │ │ ├── @ AssocSplatNode (location: (70,22)-(70,26)) │ │ │ ├── value: - │ │ │ │ @ HashNode (location: (72,24)-(72,26)) - │ │ │ │ ├── opening_loc: (72,24)-(72,25) = "{" + │ │ │ │ @ HashNode (location: (70,24)-(70,26)) + │ │ │ │ ├── opening_loc: (70,24)-(70,25) = "{" │ │ │ │ ├── elements: (length: 0) - │ │ │ │ └── closing_loc: (72,25)-(72,26) = "}" - │ │ │ └── operator_loc: (72,22)-(72,24) = "**" - │ │ └── @ AssocNode (location: (72,28)-(72,40)) + │ │ │ │ └── closing_loc: (70,25)-(70,26) = "}" + │ │ │ └── operator_loc: (70,22)-(70,24) = "**" + │ │ └── @ AssocNode (location: (70,28)-(70,40)) │ │ ├── key: - │ │ │ @ SymbolNode (location: (72,28)-(72,35)) + │ │ │ @ SymbolNode (location: (70,28)-(70,35)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── value_loc: (72,28)-(72,34) = "whatup" - │ │ │ ├── closing_loc: (72,34)-(72,35) = ":" + │ │ │ ├── value_loc: (70,28)-(70,34) = "whatup" + │ │ │ ├── closing_loc: (70,34)-(70,35) = ":" │ │ │ └── unescaped: "whatup" │ │ ├── value: - │ │ │ @ SymbolNode (location: (72,36)-(72,40)) + │ │ │ @ SymbolNode (location: (70,36)-(70,40)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (72,36)-(72,37) = ":" - │ │ │ ├── value_loc: (72,37)-(72,40) = "dog" + │ │ │ ├── opening_loc: (70,36)-(70,37) = ":" + │ │ │ ├── value_loc: (70,37)-(70,40) = "dog" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "dog" │ │ └── operator_loc: ∅ - │ ├── closing_loc: (72,40)-(72,41) = ")" + │ ├── closing_loc: (70,40)-(70,41) = ")" │ └── block: ∅ - ├── @ CallNode (location: (74,0)-(74,35)) + ├── @ CallNode (location: (72,0)-(72,35)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (74,0)-(74,3) = "foo" - │ ├── opening_loc: (74,3)-(74,4) = "(" + │ ├── message_loc: (72,0)-(72,3) = "foo" + │ ├── opening_loc: (72,3)-(72,4) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (74,4)-(74,26)) + │ │ @ ArgumentsNode (location: (72,4)-(72,26)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ HashNode (location: (74,4)-(74,26)) - │ │ ├── opening_loc: (74,4)-(74,5) = "{" + │ │ └── @ HashNode (location: (72,4)-(72,26)) + │ │ ├── opening_loc: (72,4)-(72,5) = "{" │ │ ├── elements: (length: 2) - │ │ │ ├── @ AssocNode (location: (74,6)-(74,13)) + │ │ │ ├── @ AssocNode (location: (72,6)-(72,13)) │ │ │ │ ├── key: - │ │ │ │ │ @ SymbolNode (location: (74,6)-(74,8)) + │ │ │ │ │ @ SymbolNode (location: (72,6)-(72,8)) │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ │ ├── value_loc: (74,6)-(74,7) = "a" - │ │ │ │ │ ├── closing_loc: (74,7)-(74,8) = ":" + │ │ │ │ │ ├── value_loc: (72,6)-(72,7) = "a" + │ │ │ │ │ ├── closing_loc: (72,7)-(72,8) = ":" │ │ │ │ │ └── unescaped: "a" │ │ │ │ ├── value: - │ │ │ │ │ @ TrueNode (location: (74,9)-(74,13)) + │ │ │ │ │ @ TrueNode (location: (72,9)-(72,13)) │ │ │ │ └── operator_loc: ∅ - │ │ │ └── @ AssocNode (location: (74,15)-(74,23)) + │ │ │ └── @ AssocNode (location: (72,15)-(72,23)) │ │ │ ├── key: - │ │ │ │ @ SymbolNode (location: (74,15)-(74,17)) + │ │ │ │ @ SymbolNode (location: (72,15)-(72,17)) │ │ │ │ ├── flags: ∅ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ ├── value_loc: (74,15)-(74,16) = "b" - │ │ │ │ ├── closing_loc: (74,16)-(74,17) = ":" + │ │ │ │ ├── value_loc: (72,15)-(72,16) = "b" + │ │ │ │ ├── closing_loc: (72,16)-(72,17) = ":" │ │ │ │ └── unescaped: "b" │ │ │ ├── value: - │ │ │ │ @ FalseNode (location: (74,18)-(74,23)) + │ │ │ │ @ FalseNode (location: (72,18)-(72,23)) │ │ │ └── operator_loc: ∅ - │ │ └── closing_loc: (74,25)-(74,26) = "}" - │ ├── closing_loc: (74,35)-(74,36) = ")" + │ │ └── closing_loc: (72,25)-(72,26) = "}" + │ ├── closing_loc: (72,35)-(72,36) = ")" │ └── block: - │ @ BlockArgumentNode (location: (74,28)-(74,35)) + │ @ BlockArgumentNode (location: (72,28)-(72,35)) │ ├── expression: - │ │ @ SymbolNode (location: (74,29)-(74,35)) + │ │ @ SymbolNode (location: (72,29)-(72,35)) │ │ ├── flags: ∅ - │ │ ├── opening_loc: (74,29)-(74,30) = ":" - │ │ ├── value_loc: (74,30)-(74,35) = "block" + │ │ ├── opening_loc: (72,29)-(72,30) = ":" + │ │ ├── value_loc: (72,30)-(72,35) = "block" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "block" - │ └── operator_loc: (74,28)-(74,29) = "&" - ├── @ CallNode (location: (76,0)-(76,20)) + │ └── operator_loc: (72,28)-(72,29) = "&" + ├── @ CallNode (location: (74,0)-(74,20)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :hi - │ ├── message_loc: (76,0)-(76,2) = "hi" + │ ├── message_loc: (74,0)-(74,2) = "hi" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (76,3)-(76,20)) + │ │ @ ArgumentsNode (location: (74,3)-(74,20)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ KeywordHashNode (location: (76,3)-(76,20)) + │ │ └── @ KeywordHashNode (location: (74,3)-(74,20)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) - │ │ └── @ AssocNode (location: (76,3)-(76,20)) + │ │ └── @ AssocNode (location: (74,3)-(74,20)) │ │ ├── key: - │ │ │ @ SymbolNode (location: (76,3)-(76,9)) + │ │ │ @ SymbolNode (location: (74,3)-(74,9)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (76,3)-(76,4) = ":" - │ │ │ ├── value_loc: (76,4)-(76,9) = "there" + │ │ │ ├── opening_loc: (74,3)-(74,4) = ":" + │ │ │ ├── value_loc: (74,4)-(74,9) = "there" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "there" │ │ ├── value: - │ │ │ @ SymbolNode (location: (76,13)-(76,20)) + │ │ │ @ SymbolNode (location: (74,13)-(74,20)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (76,13)-(76,14) = ":" - │ │ │ ├── value_loc: (76,14)-(76,20) = "friend" + │ │ │ ├── opening_loc: (74,13)-(74,14) = ":" + │ │ │ ├── value_loc: (74,14)-(74,20) = "friend" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "friend" - │ │ └── operator_loc: (76,10)-(76,12) = "=>" + │ │ └── operator_loc: (74,10)-(74,12) = "=>" │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (78,0)-(80,1)) + ├── @ CallNode (location: (76,0)-(78,1)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (78,0)-(78,3) = "foo" - │ ├── opening_loc: (78,3)-(78,4) = "(" + │ ├── message_loc: (76,0)-(76,3) = "foo" + │ ├── opening_loc: (76,3)-(76,4) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (78,4)-(79,2)) + │ │ @ ArgumentsNode (location: (76,4)-(77,2)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ SymbolNode (location: (78,4)-(78,6)) + │ │ ├── @ SymbolNode (location: (76,4)-(76,6)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (78,4)-(78,5) = ":" - │ │ │ ├── value_loc: (78,5)-(78,6) = "a" + │ │ │ ├── opening_loc: (76,4)-(76,5) = ":" + │ │ │ ├── value_loc: (76,5)-(76,6) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" - │ │ └── @ SymbolNode (location: (79,0)-(79,2)) + │ │ └── @ SymbolNode (location: (77,0)-(77,2)) │ │ ├── flags: ∅ - │ │ ├── opening_loc: (79,0)-(79,1) = ":" - │ │ ├── value_loc: (79,1)-(79,2) = "b" + │ │ ├── opening_loc: (77,0)-(77,1) = ":" + │ │ ├── value_loc: (77,1)-(77,2) = "b" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "b" - │ ├── closing_loc: (80,0)-(80,1) = ")" + │ ├── closing_loc: (78,0)-(78,1) = ")" │ └── block: ∅ - ├── @ CallNode (location: (82,0)-(85,1)) + ├── @ CallNode (location: (80,0)-(83,1)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (82,0)-(82,3) = "foo" - │ ├── opening_loc: (82,3)-(82,4) = "(" + │ ├── message_loc: (80,0)-(80,3) = "foo" + │ ├── opening_loc: (80,3)-(80,4) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (83,0)-(84,5)) + │ │ @ ArgumentsNode (location: (81,0)-(82,5)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ SymbolNode (location: (83,0)-(83,2)) + │ │ ├── @ SymbolNode (location: (81,0)-(81,2)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (83,0)-(83,1) = ":" - │ │ │ ├── value_loc: (83,1)-(83,2) = "a" + │ │ │ ├── opening_loc: (81,0)-(81,1) = ":" + │ │ │ ├── value_loc: (81,1)-(81,2) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" - │ │ └── @ KeywordHashNode (location: (84,0)-(84,5)) + │ │ └── @ KeywordHashNode (location: (82,0)-(82,5)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) - │ │ └── @ AssocNode (location: (84,0)-(84,5)) + │ │ └── @ AssocNode (location: (82,0)-(82,5)) │ │ ├── key: - │ │ │ @ SymbolNode (location: (84,0)-(84,2)) + │ │ │ @ SymbolNode (location: (82,0)-(82,2)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── value_loc: (84,0)-(84,1) = "b" - │ │ │ ├── closing_loc: (84,1)-(84,2) = ":" + │ │ │ ├── value_loc: (82,0)-(82,1) = "b" + │ │ │ ├── closing_loc: (82,1)-(82,2) = ":" │ │ │ └── unescaped: "b" │ │ ├── value: - │ │ │ @ SymbolNode (location: (84,3)-(84,5)) + │ │ │ @ SymbolNode (location: (82,3)-(82,5)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (84,3)-(84,4) = ":" - │ │ │ ├── value_loc: (84,4)-(84,5) = "c" + │ │ │ ├── opening_loc: (82,3)-(82,4) = ":" + │ │ │ ├── value_loc: (82,4)-(82,5) = "c" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "c" │ │ └── operator_loc: ∅ - │ ├── closing_loc: (85,0)-(85,1) = ")" + │ ├── closing_loc: (83,0)-(83,1) = ")" │ └── block: ∅ - ├── @ CallNode (location: (87,0)-(87,11)) + ├── @ CallNode (location: (85,0)-(85,11)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (87,0)-(87,3) = "foo" + │ ├── message_loc: (85,0)-(85,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: ∅ │ ├── closing_loc: ∅ │ └── block: - │ @ BlockArgumentNode (location: (87,4)-(87,11)) + │ @ BlockArgumentNode (location: (85,4)-(85,11)) │ ├── expression: - │ │ @ SymbolNode (location: (87,5)-(87,11)) + │ │ @ SymbolNode (location: (85,5)-(85,11)) │ │ ├── flags: ∅ - │ │ ├── opening_loc: (87,5)-(87,6) = ":" - │ │ ├── value_loc: (87,6)-(87,11) = "block" + │ │ ├── opening_loc: (85,5)-(85,6) = ":" + │ │ ├── value_loc: (85,6)-(85,11) = "block" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "block" - │ └── operator_loc: (87,4)-(87,5) = "&" - ├── @ CallNode (location: (89,0)-(89,30)) + │ └── operator_loc: (85,4)-(85,5) = "&" + ├── @ CallNode (location: (87,0)-(87,30)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (89,0)-(89,3) = "foo" + │ ├── message_loc: (87,0)-(87,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (89,4)-(89,21)) + │ │ @ ArgumentsNode (location: (87,4)-(87,21)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ KeywordHashNode (location: (89,4)-(89,21)) + │ │ └── @ KeywordHashNode (location: (87,4)-(87,21)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 2) - │ │ ├── @ AssocNode (location: (89,4)-(89,11)) + │ │ ├── @ AssocNode (location: (87,4)-(87,11)) │ │ │ ├── key: - │ │ │ │ @ SymbolNode (location: (89,4)-(89,6)) + │ │ │ │ @ SymbolNode (location: (87,4)-(87,6)) │ │ │ │ ├── flags: ∅ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ ├── value_loc: (89,4)-(89,5) = "a" - │ │ │ │ ├── closing_loc: (89,5)-(89,6) = ":" + │ │ │ │ ├── value_loc: (87,4)-(87,5) = "a" + │ │ │ │ ├── closing_loc: (87,5)-(87,6) = ":" │ │ │ │ └── unescaped: "a" │ │ │ ├── value: - │ │ │ │ @ TrueNode (location: (89,7)-(89,11)) + │ │ │ │ @ TrueNode (location: (87,7)-(87,11)) │ │ │ └── operator_loc: ∅ - │ │ └── @ AssocNode (location: (89,13)-(89,21)) + │ │ └── @ AssocNode (location: (87,13)-(87,21)) │ │ ├── key: - │ │ │ @ SymbolNode (location: (89,13)-(89,15)) + │ │ │ @ SymbolNode (location: (87,13)-(87,15)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── value_loc: (89,13)-(89,14) = "b" - │ │ │ ├── closing_loc: (89,14)-(89,15) = ":" + │ │ │ ├── value_loc: (87,13)-(87,14) = "b" + │ │ │ ├── closing_loc: (87,14)-(87,15) = ":" │ │ │ └── unescaped: "b" │ │ ├── value: - │ │ │ @ FalseNode (location: (89,16)-(89,21)) + │ │ │ @ FalseNode (location: (87,16)-(87,21)) │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: - │ @ BlockArgumentNode (location: (89,23)-(89,30)) + │ @ BlockArgumentNode (location: (87,23)-(87,30)) │ ├── expression: - │ │ @ SymbolNode (location: (89,24)-(89,30)) + │ │ @ SymbolNode (location: (87,24)-(87,30)) │ │ ├── flags: ∅ - │ │ ├── opening_loc: (89,24)-(89,25) = ":" - │ │ ├── value_loc: (89,25)-(89,30) = "block" + │ │ ├── opening_loc: (87,24)-(87,25) = ":" + │ │ ├── value_loc: (87,25)-(87,30) = "block" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "block" - │ └── operator_loc: (89,23)-(89,24) = "&" - ├── @ CallNode (location: (91,0)-(91,21)) + │ └── operator_loc: (87,23)-(87,24) = "&" + ├── @ CallNode (location: (89,0)-(89,21)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :some_func - │ ├── message_loc: (91,0)-(91,9) = "some_func" + │ ├── message_loc: (89,0)-(89,9) = "some_func" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (91,10)-(91,21)) + │ │ @ ArgumentsNode (location: (89,10)-(89,21)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ IntegerNode (location: (91,10)-(91,11)) + │ │ ├── @ IntegerNode (location: (89,10)-(89,11)) │ │ │ └── flags: decimal - │ │ └── @ KeywordHashNode (location: (91,13)-(91,21)) + │ │ └── @ KeywordHashNode (location: (89,13)-(89,21)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) - │ │ └── @ AssocNode (location: (91,13)-(91,21)) + │ │ └── @ AssocNode (location: (89,13)-(89,21)) │ │ ├── key: - │ │ │ @ SymbolNode (location: (91,13)-(91,19)) + │ │ │ @ SymbolNode (location: (89,13)-(89,19)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── value_loc: (91,13)-(91,18) = "kwarg" - │ │ │ ├── closing_loc: (91,18)-(91,19) = ":" + │ │ │ ├── value_loc: (89,13)-(89,18) = "kwarg" + │ │ │ ├── closing_loc: (89,18)-(89,19) = ":" │ │ │ └── unescaped: "kwarg" │ │ ├── value: - │ │ │ @ IntegerNode (location: (91,20)-(91,21)) + │ │ │ @ IntegerNode (location: (89,20)-(89,21)) │ │ │ └── flags: decimal │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (93,0)-(93,18)) + ├── @ CallNode (location: (91,0)-(91,18)) │ ├── flags: ∅ │ ├── receiver: - │ │ @ ConstantReadNode (location: (93,0)-(93,6)) + │ │ @ ConstantReadNode (location: (91,0)-(91,6)) │ │ └── name: :Kernel - │ ├── call_operator_loc: (93,6)-(93,7) = "." + │ ├── call_operator_loc: (91,6)-(91,7) = "." │ ├── name: :Integer - │ ├── message_loc: (93,7)-(93,14) = "Integer" - │ ├── opening_loc: (93,14)-(93,15) = "(" + │ ├── message_loc: (91,7)-(91,14) = "Integer" + │ ├── opening_loc: (91,14)-(91,15) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (93,15)-(93,17)) + │ │ @ ArgumentsNode (location: (91,15)-(91,17)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ IntegerNode (location: (93,15)-(93,17)) + │ │ └── @ IntegerNode (location: (91,15)-(91,17)) │ │ └── flags: decimal - │ ├── closing_loc: (93,17)-(93,18) = ")" + │ ├── closing_loc: (91,17)-(91,18) = ")" │ └── block: ∅ - ├── @ CallNode (location: (95,0)-(95,10)) + ├── @ CallNode (location: (93,0)-(93,10)) │ ├── flags: ∅ │ ├── receiver: - │ │ @ CallNode (location: (95,0)-(95,1)) + │ │ @ CallNode (location: (93,0)-(93,1)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :x - │ │ ├── message_loc: (95,0)-(95,1) = "x" + │ │ ├── message_loc: (93,0)-(93,1) = "x" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── call_operator_loc: (95,1)-(95,2) = "." + │ ├── call_operator_loc: (93,1)-(93,2) = "." │ ├── name: :each - │ ├── message_loc: (95,2)-(95,6) = "each" + │ ├── message_loc: (93,2)-(93,6) = "each" │ ├── opening_loc: ∅ │ ├── arguments: ∅ │ ├── closing_loc: ∅ │ └── block: - │ @ BlockNode (location: (95,7)-(95,10)) + │ @ BlockNode (location: (93,7)-(93,10)) │ ├── locals: [] │ ├── locals_body_index: 0 │ ├── parameters: ∅ │ ├── body: ∅ - │ ├── opening_loc: (95,7)-(95,8) = "{" - │ └── closing_loc: (95,9)-(95,10) = "}" - ├── @ CallNode (location: (97,0)-(97,14)) + │ ├── opening_loc: (93,7)-(93,8) = "{" + │ └── closing_loc: (93,9)-(93,10) = "}" + ├── @ CallNode (location: (95,0)-(95,14)) │ ├── flags: ∅ │ ├── receiver: - │ │ @ CallNode (location: (97,0)-(97,3)) + │ │ @ CallNode (location: (95,0)-(95,3)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :foo - │ │ ├── message_loc: (97,0)-(97,3) = "foo" + │ │ ├── message_loc: (95,0)-(95,3) = "foo" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── call_operator_loc: (97,3)-(97,4) = "." + │ ├── call_operator_loc: (95,3)-(95,4) = "." │ ├── name: :map - │ ├── message_loc: (97,4)-(97,7) = "map" + │ ├── message_loc: (95,4)-(95,7) = "map" │ ├── opening_loc: ∅ │ ├── arguments: ∅ │ ├── closing_loc: ∅ │ └── block: - │ @ BlockNode (location: (97,8)-(97,14)) + │ @ BlockNode (location: (95,8)-(95,14)) │ ├── locals: [] │ ├── locals_body_index: 0 │ ├── parameters: ∅ │ ├── body: - │ │ @ StatementsNode (location: (97,10)-(97,12)) + │ │ @ StatementsNode (location: (95,10)-(95,12)) │ │ └── body: (length: 1) - │ │ └── @ BackReferenceReadNode (location: (97,10)-(97,12)) + │ │ └── @ BackReferenceReadNode (location: (95,10)-(95,12)) │ │ └── name: :$& - │ ├── opening_loc: (97,8)-(97,9) = "{" - │ └── closing_loc: (97,13)-(97,14) = "}" - ├── @ CallNode (location: (99,0)-(99,12)) + │ ├── opening_loc: (95,8)-(95,9) = "{" + │ └── closing_loc: (95,13)-(95,14) = "}" + ├── @ CallNode (location: (97,0)-(97,12)) + │ ├── flags: ∅ + │ ├── receiver: + │ │ @ ConstantPathNode (location: (97,0)-(97,4)) + │ │ ├── parent: + │ │ │ @ ConstantReadNode (location: (97,0)-(97,1)) + │ │ │ └── name: :A + │ │ ├── child: + │ │ │ @ ConstantReadNode (location: (97,3)-(97,4)) + │ │ │ └── name: :B + │ │ └── delimiter_loc: (97,1)-(97,3) = "::" + │ ├── call_operator_loc: (97,4)-(97,6) = "::" + │ ├── name: :C + │ ├── message_loc: (97,6)-(97,7) = "C" + │ ├── opening_loc: ∅ + │ ├── arguments: + │ │ @ ArgumentsNode (location: (97,8)-(97,12)) + │ │ ├── flags: ∅ + │ │ └── arguments: (length: 1) + │ │ └── @ SymbolNode (location: (97,8)-(97,12)) + │ │ ├── flags: ∅ + │ │ ├── opening_loc: (97,8)-(97,9) = ":" + │ │ ├── value_loc: (97,9)-(97,12) = "foo" + │ │ ├── closing_loc: ∅ + │ │ └── unescaped: "foo" + │ ├── closing_loc: ∅ + │ └── block: ∅ + ├── @ CallNode (location: (99,0)-(99,13)) │ ├── flags: ∅ │ ├── receiver: │ │ @ ConstantPathNode (location: (99,0)-(99,4)) @@ -1468,7 +1470,7 @@ │ ├── call_operator_loc: (99,4)-(99,6) = "::" │ ├── name: :C │ ├── message_loc: (99,6)-(99,7) = "C" - │ ├── opening_loc: ∅ + │ ├── opening_loc: (99,7)-(99,8) = "(" │ ├── arguments: │ │ @ ArgumentsNode (location: (99,8)-(99,12)) │ │ ├── flags: ∅ @@ -1479,9 +1481,9 @@ │ │ ├── value_loc: (99,9)-(99,12) = "foo" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "foo" - │ ├── closing_loc: ∅ + │ ├── closing_loc: (99,12)-(99,13) = ")" │ └── block: ∅ - ├── @ CallNode (location: (101,0)-(101,13)) + ├── @ CallNode (location: (101,0)-(101,17)) │ ├── flags: ∅ │ ├── receiver: │ │ @ ConstantPathNode (location: (101,0)-(101,4)) @@ -1507,458 +1509,431 @@ │ │ ├── closing_loc: ∅ │ │ └── unescaped: "foo" │ ├── closing_loc: (101,12)-(101,13) = ")" - │ └── block: ∅ - ├── @ CallNode (location: (103,0)-(103,17)) - │ ├── flags: ∅ - │ ├── receiver: - │ │ @ ConstantPathNode (location: (103,0)-(103,4)) - │ │ ├── parent: - │ │ │ @ ConstantReadNode (location: (103,0)-(103,1)) - │ │ │ └── name: :A - │ │ ├── child: - │ │ │ @ ConstantReadNode (location: (103,3)-(103,4)) - │ │ │ └── name: :B - │ │ └── delimiter_loc: (103,1)-(103,3) = "::" - │ ├── call_operator_loc: (103,4)-(103,6) = "::" - │ ├── name: :C - │ ├── message_loc: (103,6)-(103,7) = "C" - │ ├── opening_loc: (103,7)-(103,8) = "(" - │ ├── arguments: - │ │ @ ArgumentsNode (location: (103,8)-(103,12)) - │ │ ├── flags: ∅ - │ │ └── arguments: (length: 1) - │ │ └── @ SymbolNode (location: (103,8)-(103,12)) - │ │ ├── flags: ∅ - │ │ ├── opening_loc: (103,8)-(103,9) = ":" - │ │ ├── value_loc: (103,9)-(103,12) = "foo" - │ │ ├── closing_loc: ∅ - │ │ └── unescaped: "foo" - │ ├── closing_loc: (103,12)-(103,13) = ")" │ └── block: - │ @ BlockNode (location: (103,14)-(103,17)) + │ @ BlockNode (location: (101,14)-(101,17)) │ ├── locals: [] │ ├── locals_body_index: 0 │ ├── parameters: ∅ │ ├── body: ∅ - │ ├── opening_loc: (103,14)-(103,15) = "{" - │ └── closing_loc: (103,16)-(103,17) = "}" - ├── @ CallNode (location: (105,0)-(105,12)) + │ ├── opening_loc: (101,14)-(101,15) = "{" + │ └── closing_loc: (101,16)-(101,17) = "}" + ├── @ CallNode (location: (103,0)-(103,12)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (105,0)-(105,3) = "foo" - │ ├── opening_loc: (105,3)-(105,4) = "(" + │ ├── message_loc: (103,0)-(103,3) = "foo" + │ ├── opening_loc: (103,3)-(103,4) = "(" │ ├── arguments: - │ │ @ ArgumentsNode (location: (105,4)-(105,11)) + │ │ @ ArgumentsNode (location: (103,4)-(103,11)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ KeywordHashNode (location: (105,4)-(105,11)) + │ │ └── @ KeywordHashNode (location: (103,4)-(103,11)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) - │ │ └── @ AssocNode (location: (105,4)-(105,11)) + │ │ └── @ AssocNode (location: (103,4)-(103,11)) │ │ ├── key: - │ │ │ @ SymbolNode (location: (105,4)-(105,8)) + │ │ │ @ SymbolNode (location: (103,4)-(103,8)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (105,4)-(105,5) = "\"" - │ │ │ ├── value_loc: (105,5)-(105,6) = "a" - │ │ │ ├── closing_loc: (105,6)-(105,8) = "\":" + │ │ │ ├── opening_loc: (103,4)-(103,5) = "\"" + │ │ │ ├── value_loc: (103,5)-(103,6) = "a" + │ │ │ ├── closing_loc: (103,6)-(103,8) = "\":" │ │ │ └── unescaped: "a" │ │ ├── value: - │ │ │ @ IntegerNode (location: (105,9)-(105,11)) + │ │ │ @ IntegerNode (location: (103,9)-(103,11)) │ │ │ └── flags: decimal │ │ └── operator_loc: ∅ - │ ├── closing_loc: (105,11)-(105,12) = ")" + │ ├── closing_loc: (103,11)-(103,12) = ")" │ └── block: ∅ - ├── @ CallNode (location: (107,0)-(107,28)) + ├── @ CallNode (location: (105,0)-(105,28)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (107,0)-(107,3) = "foo" + │ ├── message_loc: (105,0)-(105,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (107,4)-(107,28)) + │ │ @ ArgumentsNode (location: (105,4)-(105,28)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ KeywordHashNode (location: (107,4)-(107,28)) + │ │ └── @ KeywordHashNode (location: (105,4)-(105,28)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) - │ │ └── @ AssocNode (location: (107,4)-(107,28)) + │ │ └── @ AssocNode (location: (105,4)-(105,28)) │ │ ├── key: - │ │ │ @ SymbolNode (location: (107,4)-(107,8)) + │ │ │ @ SymbolNode (location: (105,4)-(105,8)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── value_loc: (107,4)-(107,7) = "bar" - │ │ │ ├── closing_loc: (107,7)-(107,8) = ":" + │ │ │ ├── value_loc: (105,4)-(105,7) = "bar" + │ │ │ ├── closing_loc: (105,7)-(105,8) = ":" │ │ │ └── unescaped: "bar" │ │ ├── value: - │ │ │ @ HashNode (location: (107,9)-(107,28)) - │ │ │ ├── opening_loc: (107,9)-(107,10) = "{" + │ │ │ @ HashNode (location: (105,9)-(105,28)) + │ │ │ ├── opening_loc: (105,9)-(105,10) = "{" │ │ │ ├── elements: (length: 1) - │ │ │ │ └── @ AssocNode (location: (107,11)-(107,26)) + │ │ │ │ └── @ AssocNode (location: (105,11)-(105,26)) │ │ │ │ ├── key: - │ │ │ │ │ @ SymbolNode (location: (107,11)-(107,15)) + │ │ │ │ │ @ SymbolNode (location: (105,11)-(105,15)) │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ │ ├── value_loc: (107,11)-(107,14) = "baz" - │ │ │ │ │ ├── closing_loc: (107,14)-(107,15) = ":" + │ │ │ │ │ ├── value_loc: (105,11)-(105,14) = "baz" + │ │ │ │ │ ├── closing_loc: (105,14)-(105,15) = ":" │ │ │ │ │ └── unescaped: "baz" │ │ │ │ ├── value: - │ │ │ │ │ @ CallNode (location: (107,16)-(107,26)) + │ │ │ │ │ @ CallNode (location: (105,16)-(105,26)) │ │ │ │ │ ├── flags: ignore_visibility │ │ │ │ │ ├── receiver: ∅ │ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ │ ├── name: :qux - │ │ │ │ │ ├── message_loc: (107,16)-(107,19) = "qux" + │ │ │ │ │ ├── message_loc: (105,16)-(105,19) = "qux" │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── arguments: ∅ │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── block: - │ │ │ │ │ @ BlockNode (location: (107,20)-(107,26)) + │ │ │ │ │ @ BlockNode (location: (105,20)-(105,26)) │ │ │ │ │ ├── locals: [] │ │ │ │ │ ├── locals_body_index: 0 │ │ │ │ │ ├── parameters: ∅ │ │ │ │ │ ├── body: ∅ - │ │ │ │ │ ├── opening_loc: (107,20)-(107,22) = "do" - │ │ │ │ │ └── closing_loc: (107,23)-(107,26) = "end" + │ │ │ │ │ ├── opening_loc: (105,20)-(105,22) = "do" + │ │ │ │ │ └── closing_loc: (105,23)-(105,26) = "end" │ │ │ │ └── operator_loc: ∅ - │ │ │ └── closing_loc: (107,27)-(107,28) = "}" + │ │ │ └── closing_loc: (105,27)-(105,28) = "}" │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (109,0)-(109,24)) + ├── @ CallNode (location: (107,0)-(107,24)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (109,0)-(109,3) = "foo" + │ ├── message_loc: (107,0)-(107,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (109,4)-(109,24)) + │ │ @ ArgumentsNode (location: (107,4)-(107,24)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ KeywordHashNode (location: (109,4)-(109,24)) + │ │ └── @ KeywordHashNode (location: (107,4)-(107,24)) │ │ ├── flags: symbol_keys │ │ └── elements: (length: 1) - │ │ └── @ AssocNode (location: (109,4)-(109,24)) + │ │ └── @ AssocNode (location: (107,4)-(107,24)) │ │ ├── key: - │ │ │ @ SymbolNode (location: (109,4)-(109,8)) + │ │ │ @ SymbolNode (location: (107,4)-(107,8)) │ │ │ ├── flags: ∅ │ │ │ ├── opening_loc: ∅ - │ │ │ ├── value_loc: (109,4)-(109,7) = "bar" - │ │ │ ├── closing_loc: (109,7)-(109,8) = ":" + │ │ │ ├── value_loc: (107,4)-(107,7) = "bar" + │ │ │ ├── closing_loc: (107,7)-(107,8) = ":" │ │ │ └── unescaped: "bar" │ │ ├── value: - │ │ │ @ HashNode (location: (109,9)-(109,24)) - │ │ │ ├── opening_loc: (109,9)-(109,10) = "{" + │ │ │ @ HashNode (location: (107,9)-(107,24)) + │ │ │ ├── opening_loc: (107,9)-(107,10) = "{" │ │ │ ├── elements: (length: 1) - │ │ │ │ └── @ AssocSplatNode (location: (109,11)-(109,22)) + │ │ │ │ └── @ AssocSplatNode (location: (107,11)-(107,22)) │ │ │ │ ├── value: - │ │ │ │ │ @ CallNode (location: (109,13)-(109,22)) + │ │ │ │ │ @ CallNode (location: (107,13)-(107,22)) │ │ │ │ │ ├── flags: ignore_visibility │ │ │ │ │ ├── receiver: ∅ │ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ │ ├── name: :kw - │ │ │ │ │ ├── message_loc: (109,13)-(109,15) = "kw" + │ │ │ │ │ ├── message_loc: (107,13)-(107,15) = "kw" │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── arguments: ∅ │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── block: - │ │ │ │ │ @ BlockNode (location: (109,16)-(109,22)) + │ │ │ │ │ @ BlockNode (location: (107,16)-(107,22)) │ │ │ │ │ ├── locals: [] │ │ │ │ │ ├── locals_body_index: 0 │ │ │ │ │ ├── parameters: ∅ │ │ │ │ │ ├── body: ∅ - │ │ │ │ │ ├── opening_loc: (109,16)-(109,18) = "do" - │ │ │ │ │ └── closing_loc: (109,19)-(109,22) = "end" - │ │ │ │ └── operator_loc: (109,11)-(109,13) = "**" - │ │ │ └── closing_loc: (109,23)-(109,24) = "}" + │ │ │ │ │ ├── opening_loc: (107,16)-(107,18) = "do" + │ │ │ │ │ └── closing_loc: (107,19)-(107,22) = "end" + │ │ │ │ └── operator_loc: (107,11)-(107,13) = "**" + │ │ │ └── closing_loc: (107,23)-(107,24) = "}" │ │ └── operator_loc: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (111,0)-(111,36)) + ├── @ CallNode (location: (109,0)-(109,36)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (111,0)-(111,3) = "foo" + │ ├── message_loc: (109,0)-(109,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (111,4)-(111,29)) + │ │ @ ArgumentsNode (location: (109,4)-(109,29)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ InterpolatedStringNode (location: (111,4)-(111,29)) - │ │ ├── opening_loc: (111,4)-(111,5) = "\"" + │ │ └── @ InterpolatedStringNode (location: (109,4)-(109,29)) + │ │ ├── opening_loc: (109,4)-(109,5) = "\"" │ │ ├── parts: (length: 1) - │ │ │ └── @ EmbeddedStatementsNode (location: (111,5)-(111,28)) - │ │ │ ├── opening_loc: (111,5)-(111,7) = "\#{" + │ │ │ └── @ EmbeddedStatementsNode (location: (109,5)-(109,28)) + │ │ │ ├── opening_loc: (109,5)-(109,7) = "\#{" │ │ │ ├── statements: - │ │ │ │ @ StatementsNode (location: (111,7)-(111,27)) + │ │ │ │ @ StatementsNode (location: (109,7)-(109,27)) │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ CallNode (location: (111,7)-(111,27)) + │ │ │ │ └── @ CallNode (location: (109,7)-(109,27)) │ │ │ │ ├── flags: ∅ │ │ │ │ ├── receiver: - │ │ │ │ │ @ CallNode (location: (111,7)-(111,10)) + │ │ │ │ │ @ CallNode (location: (109,7)-(109,10)) │ │ │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ │ │ ├── receiver: ∅ │ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ │ ├── name: :bar - │ │ │ │ │ ├── message_loc: (111,7)-(111,10) = "bar" + │ │ │ │ │ ├── message_loc: (109,7)-(109,10) = "bar" │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── arguments: ∅ │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── block: ∅ - │ │ │ │ ├── call_operator_loc: (111,10)-(111,11) = "." + │ │ │ │ ├── call_operator_loc: (109,10)-(109,11) = "." │ │ │ │ ├── name: :map - │ │ │ │ ├── message_loc: (111,11)-(111,14) = "map" + │ │ │ │ ├── message_loc: (109,11)-(109,14) = "map" │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── arguments: ∅ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: - │ │ │ │ @ BlockNode (location: (111,15)-(111,27)) + │ │ │ │ @ BlockNode (location: (109,15)-(109,27)) │ │ │ │ ├── locals: [] │ │ │ │ ├── locals_body_index: 0 │ │ │ │ ├── parameters: ∅ │ │ │ │ ├── body: - │ │ │ │ │ @ StatementsNode (location: (111,18)-(111,23)) + │ │ │ │ │ @ StatementsNode (location: (109,18)-(109,23)) │ │ │ │ │ └── body: (length: 1) - │ │ │ │ │ └── @ StringNode (location: (111,18)-(111,23)) + │ │ │ │ │ └── @ StringNode (location: (109,18)-(109,23)) │ │ │ │ │ ├── flags: ∅ - │ │ │ │ │ ├── opening_loc: (111,18)-(111,19) = "\"" - │ │ │ │ │ ├── content_loc: (111,19)-(111,22) = "baz" - │ │ │ │ │ ├── closing_loc: (111,22)-(111,23) = "\"" + │ │ │ │ │ ├── opening_loc: (109,18)-(109,19) = "\"" + │ │ │ │ │ ├── content_loc: (109,19)-(109,22) = "baz" + │ │ │ │ │ ├── closing_loc: (109,22)-(109,23) = "\"" │ │ │ │ │ └── unescaped: "baz" - │ │ │ │ ├── opening_loc: (111,15)-(111,17) = "do" - │ │ │ │ └── closing_loc: (111,24)-(111,27) = "end" - │ │ │ └── closing_loc: (111,27)-(111,28) = "}" - │ │ └── closing_loc: (111,28)-(111,29) = "\"" + │ │ │ │ ├── opening_loc: (109,15)-(109,17) = "do" + │ │ │ │ └── closing_loc: (109,24)-(109,27) = "end" + │ │ │ └── closing_loc: (109,27)-(109,28) = "}" + │ │ └── closing_loc: (109,28)-(109,29) = "\"" │ ├── closing_loc: ∅ │ └── block: - │ @ BlockNode (location: (111,30)-(111,36)) + │ @ BlockNode (location: (109,30)-(109,36)) │ ├── locals: [] │ ├── locals_body_index: 0 │ ├── parameters: ∅ │ ├── body: ∅ - │ ├── opening_loc: (111,30)-(111,32) = "do" - │ └── closing_loc: (111,33)-(111,36) = "end" - ├── @ CallNode (location: (113,0)-(113,28)) + │ ├── opening_loc: (109,30)-(109,32) = "do" + │ └── closing_loc: (109,33)-(109,36) = "end" + ├── @ CallNode (location: (111,0)-(111,28)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (113,0)-(113,3) = "foo" + │ ├── message_loc: (111,0)-(111,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (113,4)-(113,28)) + │ │ @ ArgumentsNode (location: (111,4)-(111,28)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ ClassNode (location: (113,4)-(113,28)) + │ │ └── @ ClassNode (location: (111,4)-(111,28)) │ │ ├── locals: [] - │ │ ├── class_keyword_loc: (113,4)-(113,9) = "class" + │ │ ├── class_keyword_loc: (111,4)-(111,9) = "class" │ │ ├── constant_path: - │ │ │ @ ConstantReadNode (location: (113,10)-(113,13)) + │ │ │ @ ConstantReadNode (location: (111,10)-(111,13)) │ │ │ └── name: :Bar │ │ ├── inheritance_operator_loc: ∅ │ │ ├── superclass: ∅ │ │ ├── body: - │ │ │ @ StatementsNode (location: (113,14)-(113,24)) + │ │ │ @ StatementsNode (location: (111,14)-(111,24)) │ │ │ └── body: (length: 1) - │ │ │ └── @ CallNode (location: (113,14)-(113,24)) + │ │ │ └── @ CallNode (location: (111,14)-(111,24)) │ │ │ ├── flags: ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :baz - │ │ │ ├── message_loc: (113,14)-(113,17) = "baz" + │ │ │ ├── message_loc: (111,14)-(111,17) = "baz" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: - │ │ │ @ BlockNode (location: (113,18)-(113,24)) + │ │ │ @ BlockNode (location: (111,18)-(111,24)) │ │ │ ├── locals: [] │ │ │ ├── locals_body_index: 0 │ │ │ ├── parameters: ∅ │ │ │ ├── body: ∅ - │ │ │ ├── opening_loc: (113,18)-(113,20) = "do" - │ │ │ └── closing_loc: (113,21)-(113,24) = "end" - │ │ ├── end_keyword_loc: (113,25)-(113,28) = "end" + │ │ │ ├── opening_loc: (111,18)-(111,20) = "do" + │ │ │ └── closing_loc: (111,21)-(111,24) = "end" + │ │ ├── end_keyword_loc: (111,25)-(111,28) = "end" │ │ └── name: :Bar │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (115,0)-(115,29)) + ├── @ CallNode (location: (113,0)-(113,29)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (115,0)-(115,3) = "foo" + │ ├── message_loc: (113,0)-(113,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (115,4)-(115,29)) + │ │ @ ArgumentsNode (location: (113,4)-(113,29)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ ModuleNode (location: (115,4)-(115,29)) + │ │ └── @ ModuleNode (location: (113,4)-(113,29)) │ │ ├── locals: [] - │ │ ├── module_keyword_loc: (115,4)-(115,10) = "module" + │ │ ├── module_keyword_loc: (113,4)-(113,10) = "module" │ │ ├── constant_path: - │ │ │ @ ConstantReadNode (location: (115,11)-(115,14)) + │ │ │ @ ConstantReadNode (location: (113,11)-(113,14)) │ │ │ └── name: :Bar │ │ ├── body: - │ │ │ @ StatementsNode (location: (115,15)-(115,25)) + │ │ │ @ StatementsNode (location: (113,15)-(113,25)) │ │ │ └── body: (length: 1) - │ │ │ └── @ CallNode (location: (115,15)-(115,25)) + │ │ │ └── @ CallNode (location: (113,15)-(113,25)) │ │ │ ├── flags: ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :baz - │ │ │ ├── message_loc: (115,15)-(115,18) = "baz" + │ │ │ ├── message_loc: (113,15)-(113,18) = "baz" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: - │ │ │ @ BlockNode (location: (115,19)-(115,25)) + │ │ │ @ BlockNode (location: (113,19)-(113,25)) │ │ │ ├── locals: [] │ │ │ ├── locals_body_index: 0 │ │ │ ├── parameters: ∅ │ │ │ ├── body: ∅ - │ │ │ ├── opening_loc: (115,19)-(115,21) = "do" - │ │ │ └── closing_loc: (115,22)-(115,25) = "end" - │ │ ├── end_keyword_loc: (115,26)-(115,29) = "end" + │ │ │ ├── opening_loc: (113,19)-(113,21) = "do" + │ │ │ └── closing_loc: (113,22)-(113,25) = "end" + │ │ ├── end_keyword_loc: (113,26)-(113,29) = "end" │ │ └── name: :Bar │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (117,0)-(117,16)) + ├── @ CallNode (location: (115,0)-(115,16)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (117,0)-(117,3) = "foo" + │ ├── message_loc: (115,0)-(115,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (117,4)-(117,16)) + │ │ @ ArgumentsNode (location: (115,4)-(115,16)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ ArrayNode (location: (117,4)-(117,16)) + │ │ └── @ ArrayNode (location: (115,4)-(115,16)) │ │ ├── flags: ∅ │ │ ├── elements: (length: 1) - │ │ │ └── @ CallNode (location: (117,5)-(117,15)) + │ │ │ └── @ CallNode (location: (115,5)-(115,15)) │ │ │ ├── flags: ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :baz - │ │ │ ├── message_loc: (117,5)-(117,8) = "baz" + │ │ │ ├── message_loc: (115,5)-(115,8) = "baz" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: - │ │ │ @ BlockNode (location: (117,9)-(117,15)) + │ │ │ @ BlockNode (location: (115,9)-(115,15)) │ │ │ ├── locals: [] │ │ │ ├── locals_body_index: 0 │ │ │ ├── parameters: ∅ │ │ │ ├── body: ∅ - │ │ │ ├── opening_loc: (117,9)-(117,11) = "do" - │ │ │ └── closing_loc: (117,12)-(117,15) = "end" - │ │ ├── opening_loc: (117,4)-(117,5) = "[" - │ │ └── closing_loc: (117,15)-(117,16) = "]" + │ │ │ ├── opening_loc: (115,9)-(115,11) = "do" + │ │ │ └── closing_loc: (115,12)-(115,15) = "end" + │ │ ├── opening_loc: (115,4)-(115,5) = "[" + │ │ └── closing_loc: (115,15)-(115,16) = "]" │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (119,0)-(119,28)) + ├── @ CallNode (location: (117,0)-(117,28)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :p - │ ├── message_loc: (119,0)-(119,1) = "p" + │ ├── message_loc: (117,0)-(117,1) = "p" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (119,2)-(119,28)) + │ │ @ ArgumentsNode (location: (117,2)-(117,28)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ BeginNode (location: (119,2)-(119,28)) - │ │ ├── begin_keyword_loc: (119,2)-(119,7) = "begin" + │ │ └── @ BeginNode (location: (117,2)-(117,28)) + │ │ ├── begin_keyword_loc: (117,2)-(117,7) = "begin" │ │ ├── statements: - │ │ │ @ StatementsNode (location: (119,8)-(119,24)) + │ │ │ @ StatementsNode (location: (117,8)-(117,24)) │ │ │ └── body: (length: 1) - │ │ │ └── @ CallNode (location: (119,8)-(119,24)) + │ │ │ └── @ CallNode (location: (117,8)-(117,24)) │ │ │ ├── flags: ∅ │ │ │ ├── receiver: - │ │ │ │ @ IntegerNode (location: (119,8)-(119,9)) + │ │ │ │ @ IntegerNode (location: (117,8)-(117,9)) │ │ │ │ └── flags: decimal - │ │ │ ├── call_operator_loc: (119,9)-(119,10) = "." + │ │ │ ├── call_operator_loc: (117,9)-(117,10) = "." │ │ │ ├── name: :times - │ │ │ ├── message_loc: (119,10)-(119,15) = "times" + │ │ │ ├── message_loc: (117,10)-(117,15) = "times" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: - │ │ │ @ BlockNode (location: (119,16)-(119,24)) + │ │ │ @ BlockNode (location: (117,16)-(117,24)) │ │ │ ├── locals: [] │ │ │ ├── locals_body_index: 0 │ │ │ ├── parameters: ∅ │ │ │ ├── body: - │ │ │ │ @ StatementsNode (location: (119,19)-(119,20)) + │ │ │ │ @ StatementsNode (location: (117,19)-(117,20)) │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ IntegerNode (location: (119,19)-(119,20)) + │ │ │ │ └── @ IntegerNode (location: (117,19)-(117,20)) │ │ │ │ └── flags: decimal - │ │ │ ├── opening_loc: (119,16)-(119,18) = "do" - │ │ │ └── closing_loc: (119,21)-(119,24) = "end" + │ │ │ ├── opening_loc: (117,16)-(117,18) = "do" + │ │ │ └── closing_loc: (117,21)-(117,24) = "end" │ │ ├── rescue_clause: ∅ │ │ ├── else_clause: ∅ │ │ ├── ensure_clause: ∅ - │ │ └── end_keyword_loc: (119,25)-(119,28) = "end" + │ │ └── end_keyword_loc: (117,25)-(117,28) = "end" │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (121,0)-(126,5)) + ├── @ CallNode (location: (119,0)-(124,5)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (121,0)-(121,3) = "foo" + │ ├── message_loc: (119,0)-(119,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (121,4)-(126,5)) + │ │ @ ArgumentsNode (location: (119,4)-(124,5)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ SymbolNode (location: (121,4)-(121,6)) + │ │ ├── @ SymbolNode (location: (119,4)-(119,6)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (121,4)-(121,5) = ":" - │ │ │ ├── value_loc: (121,5)-(121,6) = "a" + │ │ │ ├── opening_loc: (119,4)-(119,5) = ":" + │ │ │ ├── value_loc: (119,5)-(119,6) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" - │ │ └── @ IfNode (location: (122,2)-(126,5)) - │ │ ├── if_keyword_loc: (122,2)-(122,4) = "if" + │ │ └── @ IfNode (location: (120,2)-(124,5)) + │ │ ├── if_keyword_loc: (120,2)-(120,4) = "if" │ │ ├── predicate: - │ │ │ @ CallNode (location: (122,5)-(122,6)) + │ │ │ @ CallNode (location: (120,5)-(120,6)) │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :x - │ │ │ ├── message_loc: (122,5)-(122,6) = "x" + │ │ │ ├── message_loc: (120,5)-(120,6) = "x" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ ├── then_keyword_loc: ∅ │ │ ├── statements: - │ │ │ @ StatementsNode (location: (123,4)-(125,7)) + │ │ │ @ StatementsNode (location: (121,4)-(123,7)) │ │ │ └── body: (length: 1) - │ │ │ └── @ CallNode (location: (123,4)-(125,7)) + │ │ │ └── @ CallNode (location: (121,4)-(123,7)) │ │ │ ├── flags: ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :bar - │ │ │ ├── message_loc: (123,4)-(123,7) = "bar" + │ │ │ ├── message_loc: (121,4)-(121,7) = "bar" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: - │ │ │ @ BlockNode (location: (123,8)-(125,7)) + │ │ │ @ BlockNode (location: (121,8)-(123,7)) │ │ │ ├── locals: [:a] │ │ │ ├── locals_body_index: 1 │ │ │ ├── parameters: - │ │ │ │ @ BlockParametersNode (location: (123,11)-(123,14)) + │ │ │ │ @ BlockParametersNode (location: (121,11)-(121,14)) │ │ │ │ ├── parameters: - │ │ │ │ │ @ ParametersNode (location: (123,12)-(123,13)) + │ │ │ │ │ @ ParametersNode (location: (121,12)-(121,13)) │ │ │ │ │ ├── requireds: (length: 1) - │ │ │ │ │ │ └── @ RequiredParameterNode (location: (123,12)-(123,13)) + │ │ │ │ │ │ └── @ RequiredParameterNode (location: (121,12)-(121,13)) │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── name: :a │ │ │ │ │ ├── optionals: (length: 0) @@ -1968,74 +1943,74 @@ │ │ │ │ │ ├── keyword_rest: ∅ │ │ │ │ │ └── block: ∅ │ │ │ │ ├── locals: (length: 0) - │ │ │ │ ├── opening_loc: (123,11)-(123,12) = "|" - │ │ │ │ └── closing_loc: (123,13)-(123,14) = "|" + │ │ │ │ ├── opening_loc: (121,11)-(121,12) = "|" + │ │ │ │ └── closing_loc: (121,13)-(121,14) = "|" │ │ │ ├── body: - │ │ │ │ @ StatementsNode (location: (124,6)-(124,7)) + │ │ │ │ @ StatementsNode (location: (122,6)-(122,7)) │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ LocalVariableReadNode (location: (124,6)-(124,7)) + │ │ │ │ └── @ LocalVariableReadNode (location: (122,6)-(122,7)) │ │ │ │ ├── name: :a │ │ │ │ └── depth: 0 - │ │ │ ├── opening_loc: (123,8)-(123,10) = "do" - │ │ │ └── closing_loc: (125,4)-(125,7) = "end" + │ │ │ ├── opening_loc: (121,8)-(121,10) = "do" + │ │ │ └── closing_loc: (123,4)-(123,7) = "end" │ │ ├── consequent: ∅ - │ │ └── end_keyword_loc: (126,2)-(126,5) = "end" + │ │ └── end_keyword_loc: (124,2)-(124,5) = "end" │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (128,0)-(137,5)) + ├── @ CallNode (location: (126,0)-(135,5)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (128,0)-(128,3) = "foo" + │ ├── message_loc: (126,0)-(126,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (128,4)-(137,5)) + │ │ @ ArgumentsNode (location: (126,4)-(135,5)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 3) - │ │ ├── @ SymbolNode (location: (128,4)-(128,6)) + │ │ ├── @ SymbolNode (location: (126,4)-(126,6)) │ │ │ ├── flags: ∅ - │ │ │ ├── opening_loc: (128,4)-(128,5) = ":" - │ │ │ ├── value_loc: (128,5)-(128,6) = "a" + │ │ │ ├── opening_loc: (126,4)-(126,5) = ":" + │ │ │ ├── value_loc: (126,5)-(126,6) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" - │ │ ├── @ WhileNode (location: (129,2)-(133,5)) + │ │ ├── @ WhileNode (location: (127,2)-(131,5)) │ │ │ ├── flags: ∅ - │ │ │ ├── keyword_loc: (129,2)-(129,7) = "while" - │ │ │ ├── closing_loc: (133,2)-(133,5) = "end" + │ │ │ ├── keyword_loc: (127,2)-(127,7) = "while" + │ │ │ ├── closing_loc: (131,2)-(131,5) = "end" │ │ │ ├── predicate: - │ │ │ │ @ CallNode (location: (129,8)-(129,9)) + │ │ │ │ @ CallNode (location: (127,8)-(127,9)) │ │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :x - │ │ │ │ ├── message_loc: (129,8)-(129,9) = "x" + │ │ │ │ ├── message_loc: (127,8)-(127,9) = "x" │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── arguments: ∅ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ │ │ │ └── statements: - │ │ │ @ StatementsNode (location: (130,4)-(132,7)) + │ │ │ @ StatementsNode (location: (128,4)-(130,7)) │ │ │ └── body: (length: 1) - │ │ │ └── @ CallNode (location: (130,4)-(132,7)) + │ │ │ └── @ CallNode (location: (128,4)-(130,7)) │ │ │ ├── flags: ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :bar - │ │ │ ├── message_loc: (130,4)-(130,7) = "bar" + │ │ │ ├── message_loc: (128,4)-(128,7) = "bar" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: - │ │ │ @ BlockNode (location: (130,8)-(132,7)) + │ │ │ @ BlockNode (location: (128,8)-(130,7)) │ │ │ ├── locals: [:a] │ │ │ ├── locals_body_index: 1 │ │ │ ├── parameters: - │ │ │ │ @ BlockParametersNode (location: (130,11)-(130,14)) + │ │ │ │ @ BlockParametersNode (location: (128,11)-(128,14)) │ │ │ │ ├── parameters: - │ │ │ │ │ @ ParametersNode (location: (130,12)-(130,13)) + │ │ │ │ │ @ ParametersNode (location: (128,12)-(128,13)) │ │ │ │ │ ├── requireds: (length: 1) - │ │ │ │ │ │ └── @ RequiredParameterNode (location: (130,12)-(130,13)) + │ │ │ │ │ │ └── @ RequiredParameterNode (location: (128,12)-(128,13)) │ │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ │ └── name: :a │ │ │ │ │ ├── optionals: (length: 0) @@ -2045,121 +2020,121 @@ │ │ │ │ │ ├── keyword_rest: ∅ │ │ │ │ │ └── block: ∅ │ │ │ │ ├── locals: (length: 0) - │ │ │ │ ├── opening_loc: (130,11)-(130,12) = "|" - │ │ │ │ └── closing_loc: (130,13)-(130,14) = "|" + │ │ │ │ ├── opening_loc: (128,11)-(128,12) = "|" + │ │ │ │ └── closing_loc: (128,13)-(128,14) = "|" │ │ │ ├── body: - │ │ │ │ @ StatementsNode (location: (131,6)-(131,7)) + │ │ │ │ @ StatementsNode (location: (129,6)-(129,7)) │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ LocalVariableReadNode (location: (131,6)-(131,7)) + │ │ │ │ └── @ LocalVariableReadNode (location: (129,6)-(129,7)) │ │ │ │ ├── name: :a │ │ │ │ └── depth: 0 - │ │ │ ├── opening_loc: (130,8)-(130,10) = "do" - │ │ │ └── closing_loc: (132,4)-(132,7) = "end" - │ │ └── @ UntilNode (location: (134,2)-(137,5)) + │ │ │ ├── opening_loc: (128,8)-(128,10) = "do" + │ │ │ └── closing_loc: (130,4)-(130,7) = "end" + │ │ └── @ UntilNode (location: (132,2)-(135,5)) │ │ ├── flags: ∅ - │ │ ├── keyword_loc: (134,2)-(134,7) = "until" - │ │ ├── closing_loc: (137,2)-(137,5) = "end" + │ │ ├── keyword_loc: (132,2)-(132,7) = "until" + │ │ ├── closing_loc: (135,2)-(135,5) = "end" │ │ ├── predicate: - │ │ │ @ CallNode (location: (134,8)-(134,9)) + │ │ │ @ CallNode (location: (132,8)-(132,9)) │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :x - │ │ │ ├── message_loc: (134,8)-(134,9) = "x" + │ │ │ ├── message_loc: (132,8)-(132,9) = "x" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ └── statements: - │ │ @ StatementsNode (location: (135,4)-(136,7)) + │ │ @ StatementsNode (location: (133,4)-(134,7)) │ │ └── body: (length: 1) - │ │ └── @ CallNode (location: (135,4)-(136,7)) + │ │ └── @ CallNode (location: (133,4)-(134,7)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :baz - │ │ ├── message_loc: (135,4)-(135,7) = "baz" + │ │ ├── message_loc: (133,4)-(133,7) = "baz" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: - │ │ @ BlockNode (location: (135,8)-(136,7)) + │ │ @ BlockNode (location: (133,8)-(134,7)) │ │ ├── locals: [] │ │ ├── locals_body_index: 0 │ │ ├── parameters: ∅ │ │ ├── body: ∅ - │ │ ├── opening_loc: (135,8)-(135,10) = "do" - │ │ └── closing_loc: (136,4)-(136,7) = "end" + │ │ ├── opening_loc: (133,8)-(133,10) = "do" + │ │ └── closing_loc: (134,4)-(134,7) = "end" │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (139,0)-(139,9)) + ├── @ CallNode (location: (137,0)-(137,9)) │ ├── flags: ∅ │ ├── receiver: - │ │ @ HashNode (location: (139,0)-(139,2)) - │ │ ├── opening_loc: (139,0)-(139,1) = "{" + │ │ @ HashNode (location: (137,0)-(137,2)) + │ │ ├── opening_loc: (137,0)-(137,1) = "{" │ │ ├── elements: (length: 0) - │ │ └── closing_loc: (139,1)-(139,2) = "}" + │ │ └── closing_loc: (137,1)-(137,2) = "}" │ ├── call_operator_loc: ∅ │ ├── name: :+ - │ ├── message_loc: (139,3)-(139,4) = "+" + │ ├── message_loc: (137,3)-(137,4) = "+" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (139,5)-(139,9)) + │ │ @ ArgumentsNode (location: (137,5)-(137,9)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ CallNode (location: (139,5)-(139,9)) + │ │ └── @ CallNode (location: (137,5)-(137,9)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :A - │ │ ├── message_loc: (139,5)-(139,6) = "A" + │ │ ├── message_loc: (137,5)-(137,6) = "A" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: - │ │ @ BlockNode (location: (139,7)-(139,9)) + │ │ @ BlockNode (location: (137,7)-(137,9)) │ │ ├── locals: [] │ │ ├── locals_body_index: 0 │ │ ├── parameters: ∅ │ │ ├── body: ∅ - │ │ ├── opening_loc: (139,7)-(139,8) = "{" - │ │ └── closing_loc: (139,8)-(139,9) = "}" + │ │ ├── opening_loc: (137,7)-(137,8) = "{" + │ │ └── closing_loc: (137,8)-(137,9) = "}" │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (141,0)-(141,16)) + ├── @ CallNode (location: (139,0)-(139,16)) │ ├── flags: ∅ │ ├── receiver: - │ │ @ HashNode (location: (141,0)-(141,2)) - │ │ ├── opening_loc: (141,0)-(141,1) = "{" + │ │ @ HashNode (location: (139,0)-(139,2)) + │ │ ├── opening_loc: (139,0)-(139,1) = "{" │ │ ├── elements: (length: 0) - │ │ └── closing_loc: (141,1)-(141,2) = "}" + │ │ └── closing_loc: (139,1)-(139,2) = "}" │ ├── call_operator_loc: ∅ │ ├── name: :+ - │ ├── message_loc: (141,3)-(141,4) = "+" + │ ├── message_loc: (139,3)-(139,4) = "+" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (141,5)-(141,16)) + │ │ @ ArgumentsNode (location: (139,5)-(139,16)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ CallNode (location: (141,5)-(141,16)) + │ │ └── @ CallNode (location: (139,5)-(139,16)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :A - │ │ ├── message_loc: (141,5)-(141,6) = "A" + │ │ ├── message_loc: (139,5)-(139,6) = "A" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: - │ │ @ BlockNode (location: (141,7)-(141,16)) + │ │ @ BlockNode (location: (139,7)-(139,16)) │ │ ├── locals: [:a] │ │ ├── locals_body_index: 1 │ │ ├── parameters: - │ │ │ @ BlockParametersNode (location: (141,9)-(141,12)) + │ │ │ @ BlockParametersNode (location: (139,9)-(139,12)) │ │ │ ├── parameters: - │ │ │ │ @ ParametersNode (location: (141,10)-(141,11)) + │ │ │ │ @ ParametersNode (location: (139,10)-(139,11)) │ │ │ │ ├── requireds: (length: 1) - │ │ │ │ │ └── @ RequiredParameterNode (location: (141,10)-(141,11)) + │ │ │ │ │ └── @ RequiredParameterNode (location: (139,10)-(139,11)) │ │ │ │ │ ├── flags: ∅ │ │ │ │ │ └── name: :a │ │ │ │ ├── optionals: (length: 0) @@ -2169,269 +2144,269 @@ │ │ │ │ ├── keyword_rest: ∅ │ │ │ │ └── block: ∅ │ │ │ ├── locals: (length: 0) - │ │ │ ├── opening_loc: (141,9)-(141,10) = "|" - │ │ │ └── closing_loc: (141,11)-(141,12) = "|" + │ │ │ ├── opening_loc: (139,9)-(139,10) = "|" + │ │ │ └── closing_loc: (139,11)-(139,12) = "|" │ │ ├── body: - │ │ │ @ StatementsNode (location: (141,13)-(141,14)) + │ │ │ @ StatementsNode (location: (139,13)-(139,14)) │ │ │ └── body: (length: 1) - │ │ │ └── @ LocalVariableReadNode (location: (141,13)-(141,14)) + │ │ │ └── @ LocalVariableReadNode (location: (139,13)-(139,14)) │ │ │ ├── name: :a │ │ │ └── depth: 0 - │ │ ├── opening_loc: (141,7)-(141,8) = "{" - │ │ └── closing_loc: (141,15)-(141,16) = "}" + │ │ ├── opening_loc: (139,7)-(139,8) = "{" + │ │ └── closing_loc: (139,15)-(139,16) = "}" │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (143,0)-(143,11)) + ├── @ CallNode (location: (141,0)-(141,11)) │ ├── flags: ∅ │ ├── receiver: - │ │ @ CallNode (location: (143,0)-(143,4)) + │ │ @ CallNode (location: (141,0)-(141,4)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :A - │ │ ├── message_loc: (143,0)-(143,1) = "A" + │ │ ├── message_loc: (141,0)-(141,1) = "A" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: - │ │ @ BlockNode (location: (143,2)-(143,4)) + │ │ @ BlockNode (location: (141,2)-(141,4)) │ │ ├── locals: [] │ │ ├── locals_body_index: 0 │ │ ├── parameters: ∅ │ │ ├── body: ∅ - │ │ ├── opening_loc: (143,2)-(143,3) = "{" - │ │ └── closing_loc: (143,3)-(143,4) = "}" + │ │ ├── opening_loc: (141,2)-(141,3) = "{" + │ │ └── closing_loc: (141,3)-(141,4) = "}" │ ├── call_operator_loc: ∅ │ ├── name: :+ - │ ├── message_loc: (143,5)-(143,6) = "+" + │ ├── message_loc: (141,5)-(141,6) = "+" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (143,7)-(143,11)) + │ │ @ ArgumentsNode (location: (141,7)-(141,11)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ CallNode (location: (143,7)-(143,11)) + │ │ └── @ CallNode (location: (141,7)-(141,11)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :A - │ │ ├── message_loc: (143,7)-(143,8) = "A" + │ │ ├── message_loc: (141,7)-(141,8) = "A" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: - │ │ @ BlockNode (location: (143,9)-(143,11)) + │ │ @ BlockNode (location: (141,9)-(141,11)) │ │ ├── locals: [] │ │ ├── locals_body_index: 0 │ │ ├── parameters: ∅ │ │ ├── body: ∅ - │ │ ├── opening_loc: (143,9)-(143,10) = "{" - │ │ └── closing_loc: (143,10)-(143,11) = "}" + │ │ ├── opening_loc: (141,9)-(141,10) = "{" + │ │ └── closing_loc: (141,10)-(141,11) = "}" │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ CallNode (location: (145,0)-(145,11)) + ├── @ CallNode (location: (143,0)-(143,11)) │ ├── flags: ∅ │ ├── receiver: - │ │ @ CallNode (location: (145,0)-(145,3)) + │ │ @ CallNode (location: (143,0)-(143,3)) │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :lst - │ │ ├── message_loc: (145,0)-(145,3) = "lst" + │ │ ├── message_loc: (143,0)-(143,3) = "lst" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :<< - │ ├── message_loc: (145,4)-(145,6) = "<<" + │ ├── message_loc: (143,4)-(143,6) = "<<" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (145,7)-(145,11)) + │ │ @ ArgumentsNode (location: (143,7)-(143,11)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) - │ │ └── @ CallNode (location: (145,7)-(145,11)) + │ │ └── @ CallNode (location: (143,7)-(143,11)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :A - │ │ ├── message_loc: (145,7)-(145,8) = "A" + │ │ ├── message_loc: (143,7)-(143,8) = "A" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: - │ │ @ BlockNode (location: (145,9)-(145,11)) + │ │ @ BlockNode (location: (143,9)-(143,11)) │ │ ├── locals: [] │ │ ├── locals_body_index: 0 │ │ ├── parameters: ∅ │ │ ├── body: ∅ - │ │ ├── opening_loc: (145,9)-(145,10) = "{" - │ │ └── closing_loc: (145,10)-(145,11) = "}" + │ │ ├── opening_loc: (143,9)-(143,10) = "{" + │ │ └── closing_loc: (143,10)-(143,11) = "}" │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ InterpolatedStringNode (location: (147,0)-(147,17)) - │ ├── opening_loc: (147,0)-(147,1) = "\"" + ├── @ InterpolatedStringNode (location: (145,0)-(145,17)) + │ ├── opening_loc: (145,0)-(145,1) = "\"" │ ├── parts: (length: 1) - │ │ └── @ EmbeddedStatementsNode (location: (147,1)-(147,16)) - │ │ ├── opening_loc: (147,1)-(147,3) = "\#{" + │ │ └── @ EmbeddedStatementsNode (location: (145,1)-(145,16)) + │ │ ├── opening_loc: (145,1)-(145,3) = "\#{" │ │ ├── statements: - │ │ │ @ StatementsNode (location: (147,4)-(147,14)) + │ │ │ @ StatementsNode (location: (145,4)-(145,14)) │ │ │ └── body: (length: 1) - │ │ │ └── @ CallNode (location: (147,4)-(147,14)) + │ │ │ └── @ CallNode (location: (145,4)-(145,14)) │ │ │ ├── flags: ignore_visibility │ │ │ ├── receiver: ∅ │ │ │ ├── call_operator_loc: ∅ │ │ │ ├── name: :join - │ │ │ ├── message_loc: (147,4)-(147,8) = "join" + │ │ │ ├── message_loc: (145,4)-(145,8) = "join" │ │ │ ├── opening_loc: ∅ │ │ │ ├── arguments: - │ │ │ │ @ ArgumentsNode (location: (147,9)-(147,14)) + │ │ │ │ @ ArgumentsNode (location: (145,9)-(145,14)) │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) - │ │ │ │ └── @ ParenthesesNode (location: (147,9)-(147,14)) + │ │ │ │ └── @ ParenthesesNode (location: (145,9)-(145,14)) │ │ │ │ ├── body: - │ │ │ │ │ @ StatementsNode (location: (147,10)-(147,13)) + │ │ │ │ │ @ StatementsNode (location: (145,10)-(145,13)) │ │ │ │ │ └── body: (length: 1) - │ │ │ │ │ └── @ StringNode (location: (147,10)-(147,13)) + │ │ │ │ │ └── @ StringNode (location: (145,10)-(145,13)) │ │ │ │ │ ├── flags: ∅ - │ │ │ │ │ ├── opening_loc: (147,10)-(147,11) = "\"" - │ │ │ │ │ ├── content_loc: (147,11)-(147,12) = " " - │ │ │ │ │ ├── closing_loc: (147,12)-(147,13) = "\"" + │ │ │ │ │ ├── opening_loc: (145,10)-(145,11) = "\"" + │ │ │ │ │ ├── content_loc: (145,11)-(145,12) = " " + │ │ │ │ │ ├── closing_loc: (145,12)-(145,13) = "\"" │ │ │ │ │ └── unescaped: " " - │ │ │ │ ├── opening_loc: (147,9)-(147,10) = "(" - │ │ │ │ └── closing_loc: (147,13)-(147,14) = ")" + │ │ │ │ ├── opening_loc: (145,9)-(145,10) = "(" + │ │ │ │ └── closing_loc: (145,13)-(145,14) = ")" │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── closing_loc: (147,15)-(147,16) = "}" - │ └── closing_loc: (147,16)-(147,17) = "\"" - ├── @ InterpolatedStringNode (location: (149,0)-(149,8)) - │ ├── opening_loc: (149,0)-(149,1) = "\"" + │ │ └── closing_loc: (145,15)-(145,16) = "}" + │ └── closing_loc: (145,16)-(145,17) = "\"" + ├── @ InterpolatedStringNode (location: (147,0)-(147,8)) + │ ├── opening_loc: (147,0)-(147,1) = "\"" │ ├── parts: (length: 1) - │ │ └── @ EmbeddedStatementsNode (location: (149,1)-(149,7)) - │ │ ├── opening_loc: (149,1)-(149,3) = "\#{" + │ │ └── @ EmbeddedStatementsNode (location: (147,1)-(147,7)) + │ │ ├── opening_loc: (147,1)-(147,3) = "\#{" │ │ ├── statements: - │ │ │ @ StatementsNode (location: (149,3)-(149,6)) + │ │ │ @ StatementsNode (location: (147,3)-(147,6)) │ │ │ └── body: (length: 1) - │ │ │ └── @ ParenthesesNode (location: (149,3)-(149,6)) + │ │ │ └── @ ParenthesesNode (location: (147,3)-(147,6)) │ │ │ ├── body: - │ │ │ │ @ StatementsNode (location: (149,4)-(149,5)) + │ │ │ │ @ StatementsNode (location: (147,4)-(147,5)) │ │ │ │ └── body: (length: 1) - │ │ │ │ └── @ CallNode (location: (149,4)-(149,5)) + │ │ │ │ └── @ CallNode (location: (147,4)-(147,5)) │ │ │ │ ├── flags: variable_call, ignore_visibility │ │ │ │ ├── receiver: ∅ │ │ │ │ ├── call_operator_loc: ∅ │ │ │ │ ├── name: :v - │ │ │ │ ├── message_loc: (149,4)-(149,5) = "v" + │ │ │ │ ├── message_loc: (147,4)-(147,5) = "v" │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── arguments: ∅ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── block: ∅ - │ │ │ ├── opening_loc: (149,3)-(149,4) = "(" - │ │ │ └── closing_loc: (149,5)-(149,6) = ")" - │ │ └── closing_loc: (149,6)-(149,7) = "}" - │ └── closing_loc: (149,7)-(149,8) = "\"" - ├── @ DefNode (location: (151,0)-(151,18)) + │ │ │ ├── opening_loc: (147,3)-(147,4) = "(" + │ │ │ └── closing_loc: (147,5)-(147,6) = ")" + │ │ └── closing_loc: (147,6)-(147,7) = "}" + │ └── closing_loc: (147,7)-(147,8) = "\"" + ├── @ DefNode (location: (149,0)-(149,18)) │ ├── name: :f - │ ├── name_loc: (151,4)-(151,5) = "f" + │ ├── name_loc: (149,4)-(149,5) = "f" │ ├── receiver: ∅ │ ├── parameters: - │ │ @ ParametersNode (location: (151,6)-(151,7)) + │ │ @ ParametersNode (location: (149,6)-(149,7)) │ │ ├── requireds: (length: 0) │ │ ├── optionals: (length: 0) │ │ ├── rest: - │ │ │ @ RestParameterNode (location: (151,6)-(151,7)) + │ │ │ @ RestParameterNode (location: (149,6)-(149,7)) │ │ │ ├── flags: ∅ │ │ │ ├── name: ∅ │ │ │ ├── name_loc: ∅ - │ │ │ └── operator_loc: (151,6)-(151,7) = "*" + │ │ │ └── operator_loc: (149,6)-(149,7) = "*" │ │ ├── posts: (length: 0) │ │ ├── keywords: (length: 0) │ │ ├── keyword_rest: ∅ │ │ └── block: ∅ │ ├── body: - │ │ @ StatementsNode (location: (151,10)-(151,13)) + │ │ @ StatementsNode (location: (149,10)-(149,13)) │ │ └── body: (length: 1) - │ │ └── @ CallNode (location: (151,10)-(151,13)) + │ │ └── @ CallNode (location: (149,10)-(149,13)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :p - │ │ ├── message_loc: (151,10)-(151,11) = "p" + │ │ ├── message_loc: (149,10)-(149,11) = "p" │ │ ├── opening_loc: ∅ │ │ ├── arguments: - │ │ │ @ ArgumentsNode (location: (151,12)-(151,13)) + │ │ │ @ ArgumentsNode (location: (149,12)-(149,13)) │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) - │ │ │ └── @ SplatNode (location: (151,12)-(151,13)) - │ │ │ ├── operator_loc: (151,12)-(151,13) = "*" + │ │ │ └── @ SplatNode (location: (149,12)-(149,13)) + │ │ │ ├── operator_loc: (149,12)-(149,13) = "*" │ │ │ └── expression: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── locals: [:*] │ ├── locals_body_index: 1 - │ ├── def_keyword_loc: (151,0)-(151,3) = "def" + │ ├── def_keyword_loc: (149,0)-(149,3) = "def" │ ├── operator_loc: ∅ - │ ├── lparen_loc: (151,5)-(151,6) = "(" - │ ├── rparen_loc: (151,7)-(151,8) = ")" + │ ├── lparen_loc: (149,5)-(149,6) = "(" + │ ├── rparen_loc: (149,7)-(149,8) = ")" │ ├── equal_loc: ∅ - │ └── end_keyword_loc: (151,15)-(151,18) = "end" - ├── @ CallNode (location: (153,0)-(153,16)) + │ └── end_keyword_loc: (149,15)-(149,18) = "end" + ├── @ CallNode (location: (151,0)-(151,16)) │ ├── flags: ignore_visibility │ ├── receiver: ∅ │ ├── call_operator_loc: ∅ │ ├── name: :foo - │ ├── message_loc: (153,0)-(153,3) = "foo" + │ ├── message_loc: (151,0)-(151,3) = "foo" │ ├── opening_loc: ∅ │ ├── arguments: - │ │ @ ArgumentsNode (location: (153,4)-(153,16)) + │ │ @ ArgumentsNode (location: (151,4)-(151,16)) │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) - │ │ ├── @ IntegerNode (location: (153,4)-(153,5)) + │ │ ├── @ IntegerNode (location: (151,4)-(151,5)) │ │ │ └── flags: decimal - │ │ └── @ CallNode (location: (153,7)-(153,16)) + │ │ └── @ CallNode (location: (151,7)-(151,16)) │ │ ├── flags: ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ │ │ ├── name: :Bar - │ │ ├── message_loc: (153,7)-(153,10) = "Bar" + │ │ ├── message_loc: (151,7)-(151,10) = "Bar" │ │ ├── opening_loc: ∅ │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: - │ │ @ BlockNode (location: (153,11)-(153,16)) + │ │ @ BlockNode (location: (151,11)-(151,16)) │ │ ├── locals: [] │ │ ├── locals_body_index: 0 │ │ ├── parameters: ∅ │ │ ├── body: - │ │ │ @ StatementsNode (location: (153,13)-(153,14)) + │ │ │ @ StatementsNode (location: (151,13)-(151,14)) │ │ │ └── body: (length: 1) - │ │ │ └── @ IntegerNode (location: (153,13)-(153,14)) + │ │ │ └── @ IntegerNode (location: (151,13)-(151,14)) │ │ │ └── flags: decimal - │ │ ├── opening_loc: (153,11)-(153,12) = "{" - │ │ └── closing_loc: (153,15)-(153,16) = "}" + │ │ ├── opening_loc: (151,11)-(151,12) = "{" + │ │ └── closing_loc: (151,15)-(151,16) = "}" │ ├── closing_loc: ∅ │ └── block: ∅ - ├── @ LocalVariableWriteNode (location: (155,0)-(155,7)) + ├── @ LocalVariableWriteNode (location: (153,0)-(153,7)) │ ├── name: :foo │ ├── depth: 0 - │ ├── name_loc: (155,0)-(155,3) = "foo" + │ ├── name_loc: (153,0)-(153,3) = "foo" │ ├── value: - │ │ @ IntegerNode (location: (155,6)-(155,7)) + │ │ @ IntegerNode (location: (153,6)-(153,7)) │ │ └── flags: decimal - │ └── operator_loc: (155,4)-(155,5) = "=" - └── @ CallNode (location: (156,0)-(156,6)) + │ └── operator_loc: (153,4)-(153,5) = "=" + └── @ CallNode (location: (154,0)-(154,6)) ├── flags: ignore_visibility ├── receiver: ∅ ├── call_operator_loc: ∅ ├── name: :foo - ├── message_loc: (156,0)-(156,3) = "foo" + ├── message_loc: (154,0)-(154,3) = "foo" ├── opening_loc: ∅ ├── arguments: ∅ ├── closing_loc: ∅ └── block: - @ BlockNode (location: (156,4)-(156,6)) + @ BlockNode (location: (154,4)-(154,6)) ├── locals: [] ├── locals_body_index: 0 ├── parameters: ∅ ├── body: ∅ - ├── opening_loc: (156,4)-(156,5) = "{" - └── closing_loc: (156,5)-(156,6) = "}" + ├── opening_loc: (154,4)-(154,5) = "{" + └── closing_loc: (154,5)-(154,6) = "}" From a65b52b57f0b577a0486d5c05a1b5e6c53e6dc77 Mon Sep 17 00:00:00 2001 From: Max Prokopiev Date: Wed, 24 Jan 2024 21:10:54 +0100 Subject: [PATCH 515/640] [ruby/prism] Add missing snapshot for the new file https://github.com/ruby/prism/commit/459a9f544e --- test/prism/snapshots/emoji_method_calls.txt | 30 +++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 test/prism/snapshots/emoji_method_calls.txt diff --git a/test/prism/snapshots/emoji_method_calls.txt b/test/prism/snapshots/emoji_method_calls.txt new file mode 100644 index 00000000000000..a38d1431dad84c --- /dev/null +++ b/test/prism/snapshots/emoji_method_calls.txt @@ -0,0 +1,30 @@ +@ ProgramNode (location: (1,0)-(1,12)) +├── locals: [] +└── statements: + @ StatementsNode (location: (1,0)-(1,12)) + └── body: (length: 1) + └── @ CallNode (location: (1,0)-(1,12)) + ├── flags: attribute_write + ├── receiver: + │ @ CallNode (location: (1,0)-(1,3)) + │ ├── flags: variable_call, ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :foo + │ ├── message_loc: (1,0)-(1,3) = "foo" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ └── block: ∅ + ├── call_operator_loc: (1,3)-(1,4) = "." + ├── name: :🌊= + ├── message_loc: (1,4)-(1,8) = "🌊" + ├── opening_loc: ∅ + ├── arguments: + │ @ ArgumentsNode (location: (1,11)-(1,12)) + │ ├── flags: ∅ + │ └── arguments: (length: 1) + │ └── @ IntegerNode (location: (1,11)-(1,12)) + │ └── flags: decimal + ├── closing_loc: ∅ + └── block: ∅ From f769d68a69f0a8c84e46e43179bda6332923fb11 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Wed, 24 Jan 2024 17:01:16 -0500 Subject: [PATCH 516/640] [PRISM] Fix getblockparamproxy for forwarding arguments --- prism_compile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 2df3e27e24258c..a71209e0fd4124 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -1188,8 +1188,8 @@ pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinf ADD_INSN1(ret, &dummy_line_node, splatarray, RBOOL(arguments_node_list.size > 1)); - pm_local_index_t dot3_index = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_DOT3, 0); - ADD_INSN2(ret, &dummy_line_node, getblockparamproxy, INT2FIX(dot3_index.index), INT2FIX(dot3_index.level)); + pm_local_index_t and_index = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_AND, 0); + ADD_INSN2(ret, &dummy_line_node, getblockparamproxy, INT2FIX(and_index.index + VM_ENV_DATA_SIZE - 1), INT2FIX(and_index.level)); break; } From 2cc7a56ec7830fd5efaf2bc449637fd831743714 Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Wed, 24 Jan 2024 18:06:58 -0500 Subject: [PATCH 517/640] YJIT: Avoid leaks by skipping objects with a singleton class For receiver with a singleton class, there are multiple vectors YJIT can end up retaining the object. There is a path in jit_guard_known_klass() that bakes the receiver into the code, and the object could also be kept alive indirectly through a path starting at the CME object baked into the code. To avoid these leaks, avoid compiling calls on objects with a singleton class. See: https://github.com/Shopify/ruby/issues/552 [Bug #20209] --- yjit/bindgen/src/main.rs | 1 + yjit/src/codegen.rs | 17 +++++++++++++++++ yjit/src/cruby_bindings.inc.rs | 1 + yjit/src/stats.rs | 2 ++ 4 files changed, 21 insertions(+) diff --git a/yjit/bindgen/src/main.rs b/yjit/bindgen/src/main.rs index 742885de3b53ff..45874f28a1308c 100644 --- a/yjit/bindgen/src/main.rs +++ b/yjit/bindgen/src/main.rs @@ -447,6 +447,7 @@ fn main() { .allowlist_function("rb_obj_is_proc") .allowlist_function("rb_vm_base_ptr") .allowlist_function("rb_ec_stack_check") + .allowlist_function("rb_vm_top_self") // We define VALUE manually, don't import it .blocklist_type("VALUE") diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 576a9888797853..33298eed5cdb71 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -7258,6 +7258,17 @@ fn gen_send_general( assert_eq!(RUBY_T_CLASS, comptime_recv_klass.builtin_type(), "objects visible to ruby code should have a T_CLASS in their klass field"); + // Don't compile calls through singleton classes to avoid retaining the receiver. + // Make an exception for class methods since classes tend to be retained anyways. + // Also compile calls on top_self to help tests. + if VALUE(0) != unsafe { FL_TEST(comptime_recv_klass, VALUE(RUBY_FL_SINGLETON as usize)) } + && comptime_recv != unsafe { rb_vm_top_self() } + && !unsafe { RB_TYPE_P(comptime_recv, RUBY_T_CLASS) } + && !unsafe { RB_TYPE_P(comptime_recv, RUBY_T_MODULE) } { + gen_counter_incr(asm, Counter::send_singleton_class); + return None; + } + // Points to the receiver operand on the stack let recv = asm.stack_opnd(recv_idx); let recv_opnd: YARVOpnd = recv.into(); @@ -8038,6 +8049,12 @@ fn gen_invokesuper_specialized( return None; } + // Don't compile `super` on objects with singleton class to avoid retaining the receiver. + if VALUE(0) != unsafe { FL_TEST(comptime_recv.class_of(), VALUE(RUBY_FL_SINGLETON as usize)) } { + gen_counter_incr(asm, Counter::invokesuper_singleton_class); + return None; + } + // Do method lookup let cme = unsafe { rb_callable_method_entry(comptime_superclass, mid) }; if cme.is_null() { diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs index 7b0f5678977897..944fbcd55e2e22 100644 --- a/yjit/src/cruby_bindings.inc.rs +++ b/yjit/src/cruby_bindings.inc.rs @@ -975,6 +975,7 @@ extern "C" { n: ::std::os::raw::c_long, elts: *const VALUE, ) -> VALUE; + pub fn rb_vm_top_self() -> VALUE; pub static mut rb_vm_insns_count: u64; pub fn rb_method_entry_at(obj: VALUE, id: ID) -> *const rb_method_entry_t; pub fn rb_callable_method_entry(klass: VALUE, id: ID) -> *const rb_callable_method_entry_t; diff --git a/yjit/src/stats.rs b/yjit/src/stats.rs index 98e33f23757c94..b6add639c1510b 100644 --- a/yjit/src/stats.rs +++ b/yjit/src/stats.rs @@ -319,6 +319,7 @@ make_counters! { // Method calls that fallback to dynamic dispatch send_keywords, send_kw_splat, + send_singleton_class, send_args_splat_super, send_iseq_zsuper, send_block_arg, @@ -405,6 +406,7 @@ make_counters! { invokesuper_no_me, invokesuper_not_iseq_or_cfunc, invokesuper_refinement, + invokesuper_singleton_class, invokeblock_megamorphic, invokeblock_none, From 34c688b163aa44ff319575c3b3d7d6a5c0dc5260 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Wed, 24 Jan 2024 16:03:05 -0800 Subject: [PATCH 518/640] Omit TestCompilePrism on s390x for now (#9694) --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 741c0a32efcb59..bc61e507b049aa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -72,6 +72,7 @@ env: # on s390x CPU architecture. # https://github.com/madler/zlib/pull/410 - DFLTCC=0 + - TESTS="--exclude=ruby/test_compile_prism.rb --exclude=ruby/test_iseq.rb" - &arm32-linux name: arm32-linux arch: arm64 @@ -134,7 +135,7 @@ before_script: script: - $SETARCH make -s test - - ../tool/travis_wait.sh $SETARCH make -s test-all RUBYOPT="-w" + - ../tool/travis_wait.sh $SETARCH make -s test-all RUBYOPT="-w" TESTS="$TESTS" - $SETARCH make -s test-spec # We want to be notified when something happens. From 52085b66d6352c013c483fa9aac5d0b5c3e121e6 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 24 Jan 2024 16:07:26 +0900 Subject: [PATCH 519/640] Use echo command in mswin platform --- test/ruby/test_compile_prism.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index c5b8bd46474d35..b8ca217142af55 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -724,7 +724,11 @@ def test_InterpolatedSymbolNode def test_InterpolatedXStringNode assert_prism_eval('`echo #{1}`') - assert_prism_eval('`printf #{"100"}`') + if /mswin|ucrt/ =~ RUBY_PLATFORM + assert_prism_eval('`echo #{"100"}`') + else + assert_prism_eval('`printf #{"100"}`') + end end def test_MatchLastLineNode From 2e18228dff4332ec08a0a53ff658ad0bf7133cc0 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 25 Jan 2024 09:59:27 +0900 Subject: [PATCH 520/640] Use echo with all platforms --- test/ruby/test_compile_prism.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index b8ca217142af55..888e3d0a2a2b5c 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -724,11 +724,7 @@ def test_InterpolatedSymbolNode def test_InterpolatedXStringNode assert_prism_eval('`echo #{1}`') - if /mswin|ucrt/ =~ RUBY_PLATFORM - assert_prism_eval('`echo #{"100"}`') - else - assert_prism_eval('`printf #{"100"}`') - end + assert_prism_eval('`echo #{"100"}`') end def test_MatchLastLineNode From ef276858d9295208add48e27208c69184dc50472 Mon Sep 17 00:00:00 2001 From: KJ Tsanaktsidis Date: Mon, 22 Jan 2024 16:22:14 +1100 Subject: [PATCH 521/640] Trigger postponed jobs on running_ec if that is available Currently, any postponed job triggered from a non-ruby thread gets sent to the main thread, but if the main thread is sleeping it won't be checking ints. Instead, we should try and interrupt running_ec if that's possible, and only fall back to the main thread if it's not. [Bug #20197] --- ractor.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/ractor.c b/ractor.c index 4d47e75a6c7ee5..f7b251a8dc678a 100644 --- a/ractor.c +++ b/ractor.c @@ -2481,6 +2481,22 @@ rb_ractor_terminate_all(void) rb_execution_context_t * rb_vm_main_ractor_ec(rb_vm_t *vm) { + /* This code needs to carefully work around two bugs: + * - Bug #20016: When M:N threading is enabled, running_ec is NULL if no thread is + * actually currently running (as opposed to without M:N threading, when + * running_ec will still point to the _last_ thread which ran) + * - Bug #20197: If the main thread is sleeping, setting its postponed job + * interrupt flag is pointless; it won't look at the flag until it stops sleeping + * for some reason. It would be better to set the flag on the running ec, which + * will presumably look at it soon. + * + * Solution: use running_ec if it's set, otherwise fall back to the main thread ec. + * This is still susceptible to some rare race conditions (what if the last thread + * to run just entered a long-running sleep?), but seems like the best balance of + * robustness and complexity. + */ + rb_execution_context_t *running_ec = vm->ractor.main_ractor->threads.running_ec; + if (running_ec) { return running_ec; } return vm->ractor.main_thread->ec; } From 22e488464a412afa58f201c49e54773aa8011320 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Thu, 23 Nov 2023 10:47:24 -0800 Subject: [PATCH 522/640] Add VM_CALL_ARGS_SPLAT_MUT callinfo flag This flag is set when the caller has already created a new array to handle a splat, such as for `f(*a, b)` and `f(*a, *b)`. Previously, if `f` was defined as `def f(*a)`, these calls would create an extra array on the callee side, instead of using the new array created by the caller. This modifies `setup_args_core` to set the flag whenver it would add a `splatarray true` instruction. However, when `splatarray true` is changed to `splatarray false` in the peephole optimizer, to avoid unnecessary allocations on the caller side, the flag must be removed. Add `optimize_args_splat_no_copy` and have the peephole optimizer call that. This significantly simplifies the related peephole optimizer code. On the callee side, in `setup_parameters_complex`, set `args->rest_dupped` to true if the flag is set. This takes a similar approach for optimizing regular splats that was previiously used for keyword splats in d2c41b1bff1f3102544bb0d03d4e82356d034d33 (via VM_CALL_KW_SPLAT_MUT). --- compile.c | 193 +++++++++++++++------------------ iseq.c | 1 + vm_args.c | 2 +- vm_callinfo.h | 2 + yjit/src/cruby_bindings.inc.rs | 3 +- 5 files changed, 95 insertions(+), 106 deletions(-) diff --git a/compile.c b/compile.c index e9c66bd62dad7d..a2efc054389743 100644 --- a/compile.c +++ b/compile.c @@ -3190,6 +3190,30 @@ ci_argc_set(const rb_iseq_t *iseq, const struct rb_callinfo *ci, int argc) return nci; } +static bool +optimize_args_splat_no_copy(rb_iseq_t *iseq, INSN *insn, LINK_ELEMENT *niobj, + unsigned int set_flags, unsigned int unset_flags) +{ + LINK_ELEMENT *iobj = (LINK_ELEMENT *)insn; + if (!IS_NEXT_INSN_ID(niobj, send)) { + return false; + } + niobj = niobj->next; + + const struct rb_callinfo *ci = (const struct rb_callinfo *)OPERAND_AT(niobj, 0); + unsigned int flags = vm_ci_flag(ci); + if ((flags & set_flags) == set_flags && !(flags & unset_flags)) { + RUBY_ASSERT(flags & VM_CALL_ARGS_SPLAT_MUT); + OPERAND_AT(iobj, 0) = Qfalse; + const struct rb_callinfo *nci = vm_ci_new(vm_ci_mid(ci), + flags & ~VM_CALL_ARGS_SPLAT_MUT, vm_ci_argc(ci), vm_ci_kwarg(ci)); + RB_OBJ_WRITTEN(iseq, ci, nci); + OPERAND_AT(niobj, 0) = (VALUE)nci; + return true; + } + return false; +} + static int iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcallopt) { @@ -3879,58 +3903,46 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal * splatarray false * send */ - if (IS_NEXT_INSN_ID(niobj, send)) { - niobj = niobj->next; - unsigned int flag = vm_ci_flag((const struct rb_callinfo *)OPERAND_AT(niobj, 0)); - if ((flag & VM_CALL_ARGS_SPLAT) && !(flag & (VM_CALL_KW_SPLAT|VM_CALL_ARGS_BLOCKARG))) { - OPERAND_AT(iobj, 0) = Qfalse; - } - } - else if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable)) { + if (optimize_args_splat_no_copy(iseq, iobj, niobj, + VM_CALL_ARGS_SPLAT, VM_CALL_KW_SPLAT|VM_CALL_ARGS_BLOCKARG)) goto optimized_splat; + + if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable)) { niobj = niobj->next; - if (IS_NEXT_INSN_ID(niobj, send)) { - niobj = niobj->next; - unsigned int flag = vm_ci_flag((const struct rb_callinfo *)OPERAND_AT(niobj, 0)); + /* + * Eliminate array allocation for f(1, *a, &lvar) and f(1, *a, &@iv) + * + * splatarray true + * getlocal / getinstancevariable + * send ARGS_SPLAT|ARGS_BLOCKARG and not KW_SPLAT + * => + * splatarray false + * getlocal / getinstancevariable + * send + */ + if (optimize_args_splat_no_copy(iseq, iobj, niobj, + VM_CALL_ARGS_SPLAT|VM_CALL_ARGS_BLOCKARG, VM_CALL_KW_SPLAT)) goto optimized_splat; - if ((flag & VM_CALL_ARGS_SPLAT)) { - /* - * Eliminate array allocation for f(1, *a, &lvar) and f(1, *a, &@iv) - * - * splatarray true - * getlocal / getinstancevariable - * send ARGS_SPLAT|ARGS_BLOCKARG and not KW_SPLAT - * => - * splatarray false - * getlocal / getinstancevariable - * send - */ - if ((flag & VM_CALL_ARGS_BLOCKARG) && !(flag & VM_CALL_KW_SPLAT)) { - OPERAND_AT(iobj, 0) = Qfalse; - } + /* + * Eliminate array allocation for f(*a, **lvar) and f(*a, **@iv) + * + * splatarray true + * getlocal / getinstancevariable + * send ARGS_SPLAT|KW_SPLAT and not ARGS_BLOCKARG + * => + * splatarray false + * getlocal / getinstancevariable + * send + */ + if (optimize_args_splat_no_copy(iseq, iobj, niobj, + VM_CALL_ARGS_SPLAT|VM_CALL_KW_SPLAT, VM_CALL_ARGS_BLOCKARG)) goto optimized_splat; - /* - * Eliminate array allocation for f(*a, **lvar) and f(*a, **@iv) - * - * splatarray true - * getlocal / getinstancevariable - * send ARGS_SPLAT|KW_SPLAT and not ARGS_BLOCKARG - * => - * splatarray false - * getlocal / getinstancevariable - * send - */ - else if (!(flag & VM_CALL_ARGS_BLOCKARG) && (flag & VM_CALL_KW_SPLAT)) { - OPERAND_AT(iobj, 0) = Qfalse; - } - } - } - else if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable) || - IS_NEXT_INSN_ID(niobj, getblockparamproxy)) { + if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable) || + IS_NEXT_INSN_ID(niobj, getblockparamproxy)) { niobj = niobj->next; /* - * Eliminate array allocation for f(*a, **lvar, &lvar) and f(*a, **@iv, &@iv) + * Eliminate array allocation for f(*a, **lvar, &{arg,lvar,@iv}) * * splatarray true * getlocal / getinstancevariable @@ -3942,40 +3954,24 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal * getlocal / getinstancevariable / getblockparamproxy * send */ - if (IS_NEXT_INSN_ID(niobj, send)) { - niobj = niobj->next; - unsigned int flag = vm_ci_flag((const struct rb_callinfo *)OPERAND_AT(niobj, 0)); - - if ((flag & VM_CALL_ARGS_SPLAT) && (flag & VM_CALL_KW_SPLAT) && (flag & VM_CALL_ARGS_BLOCKARG)) { - OPERAND_AT(iobj, 0) = Qfalse; - } - } - } - } - else if (IS_NEXT_INSN_ID(niobj, getblockparamproxy)) { - niobj = niobj->next; - - if (IS_NEXT_INSN_ID(niobj, send)) { - niobj = niobj->next; - unsigned int flag = vm_ci_flag((const struct rb_callinfo *)OPERAND_AT(niobj, 0)); - - /* - * Eliminate array allocation for f(1, *a, &arg) - * - * splatarray true - * getblockparamproxy - * send ARGS_SPLAT|ARGS_BLOCKARG and not KW_SPLAT - * => - * splatarray false - * getblockparamproxy - * send - */ - if ((flag & VM_CALL_ARGS_BLOCKARG) & (flag & VM_CALL_ARGS_SPLAT) && !(flag & VM_CALL_KW_SPLAT)) { - OPERAND_AT(iobj, 0) = Qfalse; - } + optimize_args_splat_no_copy(iseq, iobj, niobj, + VM_CALL_ARGS_SPLAT|VM_CALL_KW_SPLAT|VM_CALL_ARGS_BLOCKARG, 0); } - } - else if (IS_NEXT_INSN_ID(niobj, duphash)) { + } else if (IS_NEXT_INSN_ID(niobj, getblockparamproxy)) { + /* + * Eliminate array allocation for f(1, *a, &arg) + * + * splatarray true + * getblockparamproxy + * send ARGS_SPLAT|ARGS_BLOCKARG and not KW_SPLAT + * => + * splatarray false + * getblockparamproxy + * send + */ + optimize_args_splat_no_copy(iseq, iobj, niobj, + VM_CALL_ARGS_SPLAT|VM_CALL_ARGS_BLOCKARG, VM_CALL_KW_SPLAT); + } else if (IS_NEXT_INSN_ID(niobj, duphash)) { niobj = niobj->next; /* @@ -3989,21 +3985,13 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal * duphash * send */ - if (IS_NEXT_INSN_ID(niobj, send)) { - niobj = niobj->next; - unsigned int flag = vm_ci_flag((const struct rb_callinfo *)OPERAND_AT(niobj, 0)); - - if ((flag & VM_CALL_ARGS_SPLAT) && (flag & VM_CALL_KW_SPLAT) && - (flag & VM_CALL_KW_SPLAT_MUT) && !(flag & VM_CALL_ARGS_BLOCKARG)) { - OPERAND_AT(iobj, 0) = Qfalse; - } - } - else if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable) || - IS_NEXT_INSN_ID(niobj, getblockparamproxy)) { - niobj = niobj->next; + if (optimize_args_splat_no_copy(iseq, iobj, niobj->next, + VM_CALL_ARGS_SPLAT|VM_CALL_KW_SPLAT|VM_CALL_KW_SPLAT_MUT, VM_CALL_ARGS_BLOCKARG)) goto optimized_splat; + if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable) || + IS_NEXT_INSN_ID(niobj, getblockparamproxy)) { /* - * Eliminate array allocation for f(*a, kw: 1, &lvar) and f(*a, kw: 1, &@iv) + * Eliminate array allocation for f(*a, kw: 1, &{arg,lvar,@iv}) * * splatarray true * duphash @@ -4015,18 +4003,12 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal * getlocal / getinstancevariable / getblockparamproxy * send */ - if (IS_NEXT_INSN_ID(niobj, send)) { - niobj = niobj->next; - unsigned int flag = vm_ci_flag((const struct rb_callinfo *)OPERAND_AT(niobj, 0)); - - if ((flag & VM_CALL_ARGS_SPLAT) && (flag & VM_CALL_KW_SPLAT) && - (flag & VM_CALL_KW_SPLAT_MUT) && (flag & VM_CALL_ARGS_BLOCKARG)) { - OPERAND_AT(iobj, 0) = Qfalse; - } - } + optimize_args_splat_no_copy(iseq, iobj, niobj->next, + VM_CALL_ARGS_SPLAT|VM_CALL_KW_SPLAT|VM_CALL_KW_SPLAT_MUT|VM_CALL_ARGS_BLOCKARG, 0); } } } + optimized_splat: return COMPILE_OK; } @@ -6190,12 +6172,15 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn, // f(*a) NO_CHECK(COMPILE(args, "args (splat)", RNODE_SPLAT(argn)->nd_head)); ADD_INSN1(args, argn, splatarray, RBOOL(dup_rest)); - if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT; + if (flag_ptr) { + *flag_ptr |= VM_CALL_ARGS_SPLAT; + if (dup_rest) *flag_ptr |= VM_CALL_ARGS_SPLAT_MUT; + } RUBY_ASSERT(flag_ptr == NULL || (*flag_ptr & VM_CALL_KW_SPLAT) == 0); return 1; } case NODE_ARGSCAT: { - if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT; + if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_SPLAT_MUT; int argc = setup_args_core(iseq, args, RNODE_ARGSCAT(argn)->nd_head, 1, NULL, NULL); if (nd_type_p(RNODE_ARGSCAT(argn)->nd_body, NODE_LIST)) { @@ -6229,7 +6214,7 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn, return argc; } case NODE_ARGSPUSH: { - if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT; + if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_SPLAT_MUT; int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, 1, NULL, NULL); if (nd_type_p(RNODE_ARGSPUSH(argn)->nd_body, NODE_LIST)) { @@ -9080,7 +9065,7 @@ compile_op_asgn1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node } ADD_INSN1(ret, node, dupn, INT2FIX(dup_argn)); flag |= asgnflag; - ADD_SEND_R(ret, node, idAREF, argc, NULL, INT2FIX(flag & ~VM_CALL_KW_SPLAT_MUT), keywords); + ADD_SEND_R(ret, node, idAREF, argc, NULL, INT2FIX(flag & ~(VM_CALL_ARGS_SPLAT_MUT|VM_CALL_KW_SPLAT_MUT)), keywords); if (id == idOROP || id == idANDOP) { /* a[x] ||= y or a[x] &&= y diff --git a/iseq.c b/iseq.c index 87cca58468a23e..a5eb049f9729c4 100644 --- a/iseq.c +++ b/iseq.c @@ -2315,6 +2315,7 @@ rb_insn_operand_intern(const rb_iseq_t *iseq, VALUE flags = rb_ary_new(); # define CALL_FLAG(n) if (vm_ci_flag(ci) & VM_CALL_##n) rb_ary_push(flags, rb_str_new2(#n)) CALL_FLAG(ARGS_SPLAT); + CALL_FLAG(ARGS_SPLAT_MUT); CALL_FLAG(ARGS_BLOCKARG); CALL_FLAG(FCALL); CALL_FLAG(VCALL); diff --git a/vm_args.c b/vm_args.c index 37b765a41d1d0f..8171dcb8e0b0ad 100644 --- a/vm_args.c +++ b/vm_args.c @@ -510,7 +510,7 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co args = &args_body; given_argc = args->argc = calling->argc; args->argv = locals; - args->rest_dupped = FALSE; + args->rest_dupped = vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT_MUT; if (kw_flag & VM_CALL_KWARG) { args->kw_arg = vm_ci_kwarg(ci); diff --git a/vm_callinfo.h b/vm_callinfo.h index 8437f2176cdd5c..2165582a2f3bab 100644 --- a/vm_callinfo.h +++ b/vm_callinfo.h @@ -25,6 +25,7 @@ enum vm_call_flag_bits { VM_CALL_ZSUPER_bit, // zsuper VM_CALL_OPT_SEND_bit, // internal flag VM_CALL_KW_SPLAT_MUT_bit, // kw splat hash can be modified (to avoid allocating a new one) + VM_CALL_ARGS_SPLAT_MUT_bit, // args splat can be modified (to avoid allocating a new one) VM_CALL__END }; @@ -40,6 +41,7 @@ enum vm_call_flag_bits { #define VM_CALL_ZSUPER (0x01 << VM_CALL_ZSUPER_bit) #define VM_CALL_OPT_SEND (0x01 << VM_CALL_OPT_SEND_bit) #define VM_CALL_KW_SPLAT_MUT (0x01 << VM_CALL_KW_SPLAT_MUT_bit) +#define VM_CALL_ARGS_SPLAT_MUT (0x01 << VM_CALL_ARGS_SPLAT_MUT_bit) struct rb_callinfo_kwarg { int keyword_len; diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs index 944fbcd55e2e22..9a1f48dc0b2123 100644 --- a/yjit/src/cruby_bindings.inc.rs +++ b/yjit/src/cruby_bindings.inc.rs @@ -632,7 +632,8 @@ pub const VM_CALL_SUPER_bit: vm_call_flag_bits = 8; pub const VM_CALL_ZSUPER_bit: vm_call_flag_bits = 9; pub const VM_CALL_OPT_SEND_bit: vm_call_flag_bits = 10; pub const VM_CALL_KW_SPLAT_MUT_bit: vm_call_flag_bits = 11; -pub const VM_CALL__END: vm_call_flag_bits = 12; +pub const VM_CALL_ARGS_SPLAT_MUT_bit: vm_call_flag_bits = 12; +pub const VM_CALL__END: vm_call_flag_bits = 13; pub type vm_call_flag_bits = u32; #[repr(C)] pub struct rb_callinfo { From 6e06d0d180001a79abadf48e2fe6baf3886f54c0 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Fri, 24 Nov 2023 20:23:58 -0800 Subject: [PATCH 523/640] Add concattoarray VM instruction This instruction is similar to concatarray, but assumes the first object is already an array, and appends to it directly. This is different than concatarray, which will create a new array instead of appending to an existing array. Additionally, for both concatarray and concattoarray, if the second argument cannot be converted to an array, then just push it onto the array, instead of creating a new array to wrap it, and then using concat array. This saves an array allocation in that case. This allows `f(*a, *a, *1)` to allocate only a single array on the caller side (which can be reused on the callee side in the case of `def f(*a)`). Prior to this commit, `f(*a, *a, *1)` would generate 4 arrays: * a dupped by splatarray true * a dupped again by first concatarray * 1 wrapped in array by third splatarray * result of [*a, *a] dupped by second concatarray Instructions Before for `a = []; f(*a, *a, *1)`: ``` 0000 newarray 0 ( 1)[Li] 0002 setlocal_WC_0 a@0 0004 putself 0005 getlocal_WC_0 a@0 0007 splatarray true 0009 getlocal_WC_0 a@0 0011 splatarray false 0013 concatarray 0014 putobject_INT2FIX_1_ 0015 splatarray false 0017 concatarray 0018 opt_send_without_block 0020 leave ``` Instructions After for `a = []; f(*a, *a, *1)`: ``` 0000 newarray 0 ( 1)[Li] 0002 setlocal_WC_0 a@0 0004 putself 0005 getlocal_WC_0 a@0 0007 splatarray true 0009 getlocal_WC_0 a@0 0011 concattoarray 0012 putobject_INT2FIX_1_ 0013 concattoarray 0014 opt_send_without_block 0016 leave ``` --- compile.c | 3 +-- insns.def | 18 +++++++++++++++++- vm_insnhelper.c | 22 ++++++++++++++++++---- 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/compile.c b/compile.c index a2efc054389743..f2701060d87138 100644 --- a/compile.c +++ b/compile.c @@ -6198,8 +6198,7 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn, argc += 1; } else { - ADD_INSN1(args, argn, splatarray, Qfalse); - ADD_INSN(args, argn, concatarray); + ADD_INSN(args, argn, concattoarray); } // f(..., *a, ..., k1:1, ...) #=> f(..., *[*a, ...], **{k1:1, ...}) diff --git a/insns.def b/insns.def index 5f6cb314ffeb25..2b03e3eb47b38d 100644 --- a/insns.def +++ b/insns.def @@ -505,7 +505,9 @@ expandarray vm_expandarray(GET_CFP(), ary, num, (int)flag); } -/* concat two arrays */ +/* concat two arrays, without modifying first array. + * attempts to convert both objects to arrays using to_a. + */ DEFINE_INSN concatarray () @@ -516,6 +518,20 @@ concatarray ary = vm_concat_array(ary1, ary2); } +/* concat second array to first array. + * first argument must already be an array. + * attempts to convert second object to array using to_a. + */ +DEFINE_INSN +concattoarray +() +(VALUE ary1, VALUE ary2) +(VALUE ary) +// attr bool leaf = false; /* has rb_check_array_type() */ +{ + ary = vm_concat_to_array(ary1, ary2); +} + /* call to_a on array ary to splat */ DEFINE_INSN splatarray diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 97776f7a695b86..55e79acdd82e16 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -5204,15 +5204,29 @@ vm_concat_array(VALUE ary1, VALUE ary2st) if (NIL_P(tmp1)) { tmp1 = rb_ary_new3(1, ary1); } + if (tmp1 == ary1) { + tmp1 = rb_ary_dup(ary1); + } if (NIL_P(tmp2)) { - tmp2 = rb_ary_new3(1, ary2); + return rb_ary_push(tmp1, ary2); + } else { + return rb_ary_concat(tmp1, tmp2); } +} - if (tmp1 == ary1) { - tmp1 = rb_ary_dup(ary1); +static VALUE +vm_concat_to_array(VALUE ary1, VALUE ary2st) +{ + /* ary1 must be a newly created array */ + const VALUE ary2 = ary2st; + VALUE tmp2 = rb_check_to_array(ary2); + + if (NIL_P(tmp2)) { + return rb_ary_push(ary1, ary2); + } else { + return rb_ary_concat(ary1, tmp2); } - return rb_ary_concat(tmp1, tmp2); } // YJIT implementation is using the C function From b8516d6d0174a10579817f4bcf5a94c8ef03dd7a Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Tue, 28 Nov 2023 12:14:45 -0800 Subject: [PATCH 524/640] Add pushtoarray VM instruction This instruction is similar to concattoarray, but it takes the number of arguments to push to the array, removes that number of arguments from the stack, and adds them to the array now at the top of the stack. This allows `f(*a, 1)` to allocate only a single array on the caller side (which can be reused on the callee side in the case of `def f(*a)`). Prior to this commit, `f(*a, 1)` would generate 3 arrays: * a dupped by splatarray true * 1 wrapped in array by newarray * a dupped again by concatarray Instructions Before for `a = []; f(*a, 1)`: ``` 0000 newarray 0 ( 1)[Li] 0002 setlocal_WC_0 a@0 0004 putself 0005 getlocal_WC_0 a@0 0007 splatarray true 0009 putobject_INT2FIX_1_ 0010 newarray 1 0012 concatarray 0013 opt_send_without_block 0015 leave ``` Instructions After for `a = []; f(*a, 1)`: ``` 0000 newarray 0 ( 1)[Li] 0002 setlocal_WC_0 a@0 0004 putself 0005 getlocal_WC_0 a@0 0007 splatarray true 0009 putobject_INT2FIX_1_ 0010 pushtoarray 1 0012 opt_send_without_block 0014 leave ``` With these changes, method calls to Ruby methods should implicitly allocate at most one array. Ignore typeprof bundled gem failure due to unrecognized instruction. --- .github/workflows/ubuntu.yml | 2 +- .github/workflows/yjit-ubuntu.yml | 2 +- compile.c | 12 +- insns.def | 12 + yjit/src/cruby_bindings.inc.rs | 350 +++++++++++++++--------------- 5 files changed, 197 insertions(+), 181 deletions(-) diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 93ced0d1d21f34..b78570e22479c0 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -99,7 +99,7 @@ jobs: env: RUBY_TESTOPTS: '-q --tty=no' TESTS: ${{ matrix.test_task == 'check' && matrix.skipped_tests || '' }} - TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' + TEST_BUNDLED_GEMS_ALLOW_FAILURES: 'typeprof' PRECHECK_BUNDLED_GEMS: 'no' - name: make skipped tests diff --git a/.github/workflows/yjit-ubuntu.yml b/.github/workflows/yjit-ubuntu.yml index ec8483b7d1281d..82ca02890ef9fd 100644 --- a/.github/workflows/yjit-ubuntu.yml +++ b/.github/workflows/yjit-ubuntu.yml @@ -169,7 +169,7 @@ jobs: timeout-minutes: 60 env: RUBY_TESTOPTS: '-q --tty=no' - TEST_BUNDLED_GEMS_ALLOW_FAILURES: 'rbs' + TEST_BUNDLED_GEMS_ALLOW_FAILURES: 'rbs,typeprof' PRECHECK_BUNDLED_GEMS: 'no' SYNTAX_SUGGEST_TIMEOUT: '5' YJIT_BINDGEN_DIFF_OPTS: '--exit-code' diff --git a/compile.c b/compile.c index f2701060d87138..67b22db5dc6cbc 100644 --- a/compile.c +++ b/compile.c @@ -6182,11 +6182,13 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn, case NODE_ARGSCAT: { if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_SPLAT_MUT; int argc = setup_args_core(iseq, args, RNODE_ARGSCAT(argn)->nd_head, 1, NULL, NULL); + bool args_pushed = false; if (nd_type_p(RNODE_ARGSCAT(argn)->nd_body, NODE_LIST)) { int rest_len = compile_args(iseq, args, RNODE_ARGSCAT(argn)->nd_body, &kwnode); if (kwnode) rest_len--; - ADD_INSN1(args, argn, newarray, INT2FIX(rest_len)); + ADD_INSN1(args, argn, pushtoarray, INT2FIX(rest_len)); + args_pushed = true; } else { RUBY_ASSERT(!check_keyword(RNODE_ARGSCAT(argn)->nd_body)); @@ -6197,7 +6199,7 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn, ADD_INSN1(args, argn, splatarray, Qtrue); argc += 1; } - else { + else if (!args_pushed) { ADD_INSN(args, argn, concattoarray); } @@ -6220,8 +6222,7 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn, int rest_len = compile_args(iseq, args, RNODE_ARGSPUSH(argn)->nd_body, &kwnode); if (kwnode) rest_len--; ADD_INSN1(args, argn, newarray, INT2FIX(rest_len)); - ADD_INSN1(args, argn, newarray, INT2FIX(1)); - ADD_INSN(args, argn, concatarray); + ADD_INSN1(args, argn, pushtoarray, INT2FIX(1)); } else { if (keyword_node_p(RNODE_ARGSPUSH(argn)->nd_body)) { @@ -6229,8 +6230,7 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn, } else { NO_CHECK(COMPILE(args, "args (cat: splat)", RNODE_ARGSPUSH(argn)->nd_body)); - ADD_INSN1(args, argn, newarray, INT2FIX(1)); - ADD_INSN(args, argn, concatarray); + ADD_INSN1(args, argn, pushtoarray, INT2FIX(1)); } } diff --git a/insns.def b/insns.def index 2b03e3eb47b38d..e449419708e65b 100644 --- a/insns.def +++ b/insns.def @@ -532,6 +532,18 @@ concattoarray ary = vm_concat_to_array(ary1, ary2); } +/* push given number of objects to array directly before. */ +DEFINE_INSN +pushtoarray +(rb_num_t num) +(...) +(VALUE val) +// attr rb_snum_t sp_inc = -(rb_snum_t)num; +{ + const VALUE *objp = STACK_ADDR_FROM_TOP(num); + val = rb_ary_cat(*(objp-1), objp, num); +} + /* call to_a on array ary to splat */ DEFINE_INSN splatarray diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs index 9a1f48dc0b2123..01f0cca2804376 100644 --- a/yjit/src/cruby_bindings.inc.rs +++ b/yjit/src/cruby_bindings.inc.rs @@ -699,179 +699,183 @@ pub const YARVINSN_duparray: ruby_vminsn_type = 28; pub const YARVINSN_duphash: ruby_vminsn_type = 29; pub const YARVINSN_expandarray: ruby_vminsn_type = 30; pub const YARVINSN_concatarray: ruby_vminsn_type = 31; -pub const YARVINSN_splatarray: ruby_vminsn_type = 32; -pub const YARVINSN_splatkw: ruby_vminsn_type = 33; -pub const YARVINSN_newhash: ruby_vminsn_type = 34; -pub const YARVINSN_newrange: ruby_vminsn_type = 35; -pub const YARVINSN_pop: ruby_vminsn_type = 36; -pub const YARVINSN_dup: ruby_vminsn_type = 37; -pub const YARVINSN_dupn: ruby_vminsn_type = 38; -pub const YARVINSN_swap: ruby_vminsn_type = 39; -pub const YARVINSN_opt_reverse: ruby_vminsn_type = 40; -pub const YARVINSN_topn: ruby_vminsn_type = 41; -pub const YARVINSN_setn: ruby_vminsn_type = 42; -pub const YARVINSN_adjuststack: ruby_vminsn_type = 43; -pub const YARVINSN_defined: ruby_vminsn_type = 44; -pub const YARVINSN_definedivar: ruby_vminsn_type = 45; -pub const YARVINSN_checkmatch: ruby_vminsn_type = 46; -pub const YARVINSN_checkkeyword: ruby_vminsn_type = 47; -pub const YARVINSN_checktype: ruby_vminsn_type = 48; -pub const YARVINSN_defineclass: ruby_vminsn_type = 49; -pub const YARVINSN_definemethod: ruby_vminsn_type = 50; -pub const YARVINSN_definesmethod: ruby_vminsn_type = 51; -pub const YARVINSN_send: ruby_vminsn_type = 52; -pub const YARVINSN_opt_send_without_block: ruby_vminsn_type = 53; -pub const YARVINSN_objtostring: ruby_vminsn_type = 54; -pub const YARVINSN_opt_str_freeze: ruby_vminsn_type = 55; -pub const YARVINSN_opt_nil_p: ruby_vminsn_type = 56; -pub const YARVINSN_opt_str_uminus: ruby_vminsn_type = 57; -pub const YARVINSN_opt_newarray_send: ruby_vminsn_type = 58; -pub const YARVINSN_invokesuper: ruby_vminsn_type = 59; -pub const YARVINSN_invokeblock: ruby_vminsn_type = 60; -pub const YARVINSN_leave: ruby_vminsn_type = 61; -pub const YARVINSN_throw: ruby_vminsn_type = 62; -pub const YARVINSN_jump: ruby_vminsn_type = 63; -pub const YARVINSN_branchif: ruby_vminsn_type = 64; -pub const YARVINSN_branchunless: ruby_vminsn_type = 65; -pub const YARVINSN_branchnil: ruby_vminsn_type = 66; -pub const YARVINSN_once: ruby_vminsn_type = 67; -pub const YARVINSN_opt_case_dispatch: ruby_vminsn_type = 68; -pub const YARVINSN_opt_plus: ruby_vminsn_type = 69; -pub const YARVINSN_opt_minus: ruby_vminsn_type = 70; -pub const YARVINSN_opt_mult: ruby_vminsn_type = 71; -pub const YARVINSN_opt_div: ruby_vminsn_type = 72; -pub const YARVINSN_opt_mod: ruby_vminsn_type = 73; -pub const YARVINSN_opt_eq: ruby_vminsn_type = 74; -pub const YARVINSN_opt_neq: ruby_vminsn_type = 75; -pub const YARVINSN_opt_lt: ruby_vminsn_type = 76; -pub const YARVINSN_opt_le: ruby_vminsn_type = 77; -pub const YARVINSN_opt_gt: ruby_vminsn_type = 78; -pub const YARVINSN_opt_ge: ruby_vminsn_type = 79; -pub const YARVINSN_opt_ltlt: ruby_vminsn_type = 80; -pub const YARVINSN_opt_and: ruby_vminsn_type = 81; -pub const YARVINSN_opt_or: ruby_vminsn_type = 82; -pub const YARVINSN_opt_aref: ruby_vminsn_type = 83; -pub const YARVINSN_opt_aset: ruby_vminsn_type = 84; -pub const YARVINSN_opt_aset_with: ruby_vminsn_type = 85; -pub const YARVINSN_opt_aref_with: ruby_vminsn_type = 86; -pub const YARVINSN_opt_length: ruby_vminsn_type = 87; -pub const YARVINSN_opt_size: ruby_vminsn_type = 88; -pub const YARVINSN_opt_empty_p: ruby_vminsn_type = 89; -pub const YARVINSN_opt_succ: ruby_vminsn_type = 90; -pub const YARVINSN_opt_not: ruby_vminsn_type = 91; -pub const YARVINSN_opt_regexpmatch2: ruby_vminsn_type = 92; -pub const YARVINSN_invokebuiltin: ruby_vminsn_type = 93; -pub const YARVINSN_opt_invokebuiltin_delegate: ruby_vminsn_type = 94; -pub const YARVINSN_opt_invokebuiltin_delegate_leave: ruby_vminsn_type = 95; -pub const YARVINSN_getlocal_WC_0: ruby_vminsn_type = 96; -pub const YARVINSN_getlocal_WC_1: ruby_vminsn_type = 97; -pub const YARVINSN_setlocal_WC_0: ruby_vminsn_type = 98; -pub const YARVINSN_setlocal_WC_1: ruby_vminsn_type = 99; -pub const YARVINSN_putobject_INT2FIX_0_: ruby_vminsn_type = 100; -pub const YARVINSN_putobject_INT2FIX_1_: ruby_vminsn_type = 101; -pub const YARVINSN_trace_nop: ruby_vminsn_type = 102; -pub const YARVINSN_trace_getlocal: ruby_vminsn_type = 103; -pub const YARVINSN_trace_setlocal: ruby_vminsn_type = 104; -pub const YARVINSN_trace_getblockparam: ruby_vminsn_type = 105; -pub const YARVINSN_trace_setblockparam: ruby_vminsn_type = 106; -pub const YARVINSN_trace_getblockparamproxy: ruby_vminsn_type = 107; -pub const YARVINSN_trace_getspecial: ruby_vminsn_type = 108; -pub const YARVINSN_trace_setspecial: ruby_vminsn_type = 109; -pub const YARVINSN_trace_getinstancevariable: ruby_vminsn_type = 110; -pub const YARVINSN_trace_setinstancevariable: ruby_vminsn_type = 111; -pub const YARVINSN_trace_getclassvariable: ruby_vminsn_type = 112; -pub const YARVINSN_trace_setclassvariable: ruby_vminsn_type = 113; -pub const YARVINSN_trace_opt_getconstant_path: ruby_vminsn_type = 114; -pub const YARVINSN_trace_getconstant: ruby_vminsn_type = 115; -pub const YARVINSN_trace_setconstant: ruby_vminsn_type = 116; -pub const YARVINSN_trace_getglobal: ruby_vminsn_type = 117; -pub const YARVINSN_trace_setglobal: ruby_vminsn_type = 118; -pub const YARVINSN_trace_putnil: ruby_vminsn_type = 119; -pub const YARVINSN_trace_putself: ruby_vminsn_type = 120; -pub const YARVINSN_trace_putobject: ruby_vminsn_type = 121; -pub const YARVINSN_trace_putspecialobject: ruby_vminsn_type = 122; -pub const YARVINSN_trace_putstring: ruby_vminsn_type = 123; -pub const YARVINSN_trace_concatstrings: ruby_vminsn_type = 124; -pub const YARVINSN_trace_anytostring: ruby_vminsn_type = 125; -pub const YARVINSN_trace_toregexp: ruby_vminsn_type = 126; -pub const YARVINSN_trace_intern: ruby_vminsn_type = 127; -pub const YARVINSN_trace_newarray: ruby_vminsn_type = 128; -pub const YARVINSN_trace_newarraykwsplat: ruby_vminsn_type = 129; -pub const YARVINSN_trace_duparray: ruby_vminsn_type = 130; -pub const YARVINSN_trace_duphash: ruby_vminsn_type = 131; -pub const YARVINSN_trace_expandarray: ruby_vminsn_type = 132; -pub const YARVINSN_trace_concatarray: ruby_vminsn_type = 133; -pub const YARVINSN_trace_splatarray: ruby_vminsn_type = 134; -pub const YARVINSN_trace_splatkw: ruby_vminsn_type = 135; -pub const YARVINSN_trace_newhash: ruby_vminsn_type = 136; -pub const YARVINSN_trace_newrange: ruby_vminsn_type = 137; -pub const YARVINSN_trace_pop: ruby_vminsn_type = 138; -pub const YARVINSN_trace_dup: ruby_vminsn_type = 139; -pub const YARVINSN_trace_dupn: ruby_vminsn_type = 140; -pub const YARVINSN_trace_swap: ruby_vminsn_type = 141; -pub const YARVINSN_trace_opt_reverse: ruby_vminsn_type = 142; -pub const YARVINSN_trace_topn: ruby_vminsn_type = 143; -pub const YARVINSN_trace_setn: ruby_vminsn_type = 144; -pub const YARVINSN_trace_adjuststack: ruby_vminsn_type = 145; -pub const YARVINSN_trace_defined: ruby_vminsn_type = 146; -pub const YARVINSN_trace_definedivar: ruby_vminsn_type = 147; -pub const YARVINSN_trace_checkmatch: ruby_vminsn_type = 148; -pub const YARVINSN_trace_checkkeyword: ruby_vminsn_type = 149; -pub const YARVINSN_trace_checktype: ruby_vminsn_type = 150; -pub const YARVINSN_trace_defineclass: ruby_vminsn_type = 151; -pub const YARVINSN_trace_definemethod: ruby_vminsn_type = 152; -pub const YARVINSN_trace_definesmethod: ruby_vminsn_type = 153; -pub const YARVINSN_trace_send: ruby_vminsn_type = 154; -pub const YARVINSN_trace_opt_send_without_block: ruby_vminsn_type = 155; -pub const YARVINSN_trace_objtostring: ruby_vminsn_type = 156; -pub const YARVINSN_trace_opt_str_freeze: ruby_vminsn_type = 157; -pub const YARVINSN_trace_opt_nil_p: ruby_vminsn_type = 158; -pub const YARVINSN_trace_opt_str_uminus: ruby_vminsn_type = 159; -pub const YARVINSN_trace_opt_newarray_send: ruby_vminsn_type = 160; -pub const YARVINSN_trace_invokesuper: ruby_vminsn_type = 161; -pub const YARVINSN_trace_invokeblock: ruby_vminsn_type = 162; -pub const YARVINSN_trace_leave: ruby_vminsn_type = 163; -pub const YARVINSN_trace_throw: ruby_vminsn_type = 164; -pub const YARVINSN_trace_jump: ruby_vminsn_type = 165; -pub const YARVINSN_trace_branchif: ruby_vminsn_type = 166; -pub const YARVINSN_trace_branchunless: ruby_vminsn_type = 167; -pub const YARVINSN_trace_branchnil: ruby_vminsn_type = 168; -pub const YARVINSN_trace_once: ruby_vminsn_type = 169; -pub const YARVINSN_trace_opt_case_dispatch: ruby_vminsn_type = 170; -pub const YARVINSN_trace_opt_plus: ruby_vminsn_type = 171; -pub const YARVINSN_trace_opt_minus: ruby_vminsn_type = 172; -pub const YARVINSN_trace_opt_mult: ruby_vminsn_type = 173; -pub const YARVINSN_trace_opt_div: ruby_vminsn_type = 174; -pub const YARVINSN_trace_opt_mod: ruby_vminsn_type = 175; -pub const YARVINSN_trace_opt_eq: ruby_vminsn_type = 176; -pub const YARVINSN_trace_opt_neq: ruby_vminsn_type = 177; -pub const YARVINSN_trace_opt_lt: ruby_vminsn_type = 178; -pub const YARVINSN_trace_opt_le: ruby_vminsn_type = 179; -pub const YARVINSN_trace_opt_gt: ruby_vminsn_type = 180; -pub const YARVINSN_trace_opt_ge: ruby_vminsn_type = 181; -pub const YARVINSN_trace_opt_ltlt: ruby_vminsn_type = 182; -pub const YARVINSN_trace_opt_and: ruby_vminsn_type = 183; -pub const YARVINSN_trace_opt_or: ruby_vminsn_type = 184; -pub const YARVINSN_trace_opt_aref: ruby_vminsn_type = 185; -pub const YARVINSN_trace_opt_aset: ruby_vminsn_type = 186; -pub const YARVINSN_trace_opt_aset_with: ruby_vminsn_type = 187; -pub const YARVINSN_trace_opt_aref_with: ruby_vminsn_type = 188; -pub const YARVINSN_trace_opt_length: ruby_vminsn_type = 189; -pub const YARVINSN_trace_opt_size: ruby_vminsn_type = 190; -pub const YARVINSN_trace_opt_empty_p: ruby_vminsn_type = 191; -pub const YARVINSN_trace_opt_succ: ruby_vminsn_type = 192; -pub const YARVINSN_trace_opt_not: ruby_vminsn_type = 193; -pub const YARVINSN_trace_opt_regexpmatch2: ruby_vminsn_type = 194; -pub const YARVINSN_trace_invokebuiltin: ruby_vminsn_type = 195; -pub const YARVINSN_trace_opt_invokebuiltin_delegate: ruby_vminsn_type = 196; -pub const YARVINSN_trace_opt_invokebuiltin_delegate_leave: ruby_vminsn_type = 197; -pub const YARVINSN_trace_getlocal_WC_0: ruby_vminsn_type = 198; -pub const YARVINSN_trace_getlocal_WC_1: ruby_vminsn_type = 199; -pub const YARVINSN_trace_setlocal_WC_0: ruby_vminsn_type = 200; -pub const YARVINSN_trace_setlocal_WC_1: ruby_vminsn_type = 201; -pub const YARVINSN_trace_putobject_INT2FIX_0_: ruby_vminsn_type = 202; -pub const YARVINSN_trace_putobject_INT2FIX_1_: ruby_vminsn_type = 203; -pub const VM_INSTRUCTION_SIZE: ruby_vminsn_type = 204; +pub const YARVINSN_concattoarray: ruby_vminsn_type = 32; +pub const YARVINSN_pushtoarray: ruby_vminsn_type = 33; +pub const YARVINSN_splatarray: ruby_vminsn_type = 34; +pub const YARVINSN_splatkw: ruby_vminsn_type = 35; +pub const YARVINSN_newhash: ruby_vminsn_type = 36; +pub const YARVINSN_newrange: ruby_vminsn_type = 37; +pub const YARVINSN_pop: ruby_vminsn_type = 38; +pub const YARVINSN_dup: ruby_vminsn_type = 39; +pub const YARVINSN_dupn: ruby_vminsn_type = 40; +pub const YARVINSN_swap: ruby_vminsn_type = 41; +pub const YARVINSN_opt_reverse: ruby_vminsn_type = 42; +pub const YARVINSN_topn: ruby_vminsn_type = 43; +pub const YARVINSN_setn: ruby_vminsn_type = 44; +pub const YARVINSN_adjuststack: ruby_vminsn_type = 45; +pub const YARVINSN_defined: ruby_vminsn_type = 46; +pub const YARVINSN_definedivar: ruby_vminsn_type = 47; +pub const YARVINSN_checkmatch: ruby_vminsn_type = 48; +pub const YARVINSN_checkkeyword: ruby_vminsn_type = 49; +pub const YARVINSN_checktype: ruby_vminsn_type = 50; +pub const YARVINSN_defineclass: ruby_vminsn_type = 51; +pub const YARVINSN_definemethod: ruby_vminsn_type = 52; +pub const YARVINSN_definesmethod: ruby_vminsn_type = 53; +pub const YARVINSN_send: ruby_vminsn_type = 54; +pub const YARVINSN_opt_send_without_block: ruby_vminsn_type = 55; +pub const YARVINSN_objtostring: ruby_vminsn_type = 56; +pub const YARVINSN_opt_str_freeze: ruby_vminsn_type = 57; +pub const YARVINSN_opt_nil_p: ruby_vminsn_type = 58; +pub const YARVINSN_opt_str_uminus: ruby_vminsn_type = 59; +pub const YARVINSN_opt_newarray_send: ruby_vminsn_type = 60; +pub const YARVINSN_invokesuper: ruby_vminsn_type = 61; +pub const YARVINSN_invokeblock: ruby_vminsn_type = 62; +pub const YARVINSN_leave: ruby_vminsn_type = 63; +pub const YARVINSN_throw: ruby_vminsn_type = 64; +pub const YARVINSN_jump: ruby_vminsn_type = 65; +pub const YARVINSN_branchif: ruby_vminsn_type = 66; +pub const YARVINSN_branchunless: ruby_vminsn_type = 67; +pub const YARVINSN_branchnil: ruby_vminsn_type = 68; +pub const YARVINSN_once: ruby_vminsn_type = 69; +pub const YARVINSN_opt_case_dispatch: ruby_vminsn_type = 70; +pub const YARVINSN_opt_plus: ruby_vminsn_type = 71; +pub const YARVINSN_opt_minus: ruby_vminsn_type = 72; +pub const YARVINSN_opt_mult: ruby_vminsn_type = 73; +pub const YARVINSN_opt_div: ruby_vminsn_type = 74; +pub const YARVINSN_opt_mod: ruby_vminsn_type = 75; +pub const YARVINSN_opt_eq: ruby_vminsn_type = 76; +pub const YARVINSN_opt_neq: ruby_vminsn_type = 77; +pub const YARVINSN_opt_lt: ruby_vminsn_type = 78; +pub const YARVINSN_opt_le: ruby_vminsn_type = 79; +pub const YARVINSN_opt_gt: ruby_vminsn_type = 80; +pub const YARVINSN_opt_ge: ruby_vminsn_type = 81; +pub const YARVINSN_opt_ltlt: ruby_vminsn_type = 82; +pub const YARVINSN_opt_and: ruby_vminsn_type = 83; +pub const YARVINSN_opt_or: ruby_vminsn_type = 84; +pub const YARVINSN_opt_aref: ruby_vminsn_type = 85; +pub const YARVINSN_opt_aset: ruby_vminsn_type = 86; +pub const YARVINSN_opt_aset_with: ruby_vminsn_type = 87; +pub const YARVINSN_opt_aref_with: ruby_vminsn_type = 88; +pub const YARVINSN_opt_length: ruby_vminsn_type = 89; +pub const YARVINSN_opt_size: ruby_vminsn_type = 90; +pub const YARVINSN_opt_empty_p: ruby_vminsn_type = 91; +pub const YARVINSN_opt_succ: ruby_vminsn_type = 92; +pub const YARVINSN_opt_not: ruby_vminsn_type = 93; +pub const YARVINSN_opt_regexpmatch2: ruby_vminsn_type = 94; +pub const YARVINSN_invokebuiltin: ruby_vminsn_type = 95; +pub const YARVINSN_opt_invokebuiltin_delegate: ruby_vminsn_type = 96; +pub const YARVINSN_opt_invokebuiltin_delegate_leave: ruby_vminsn_type = 97; +pub const YARVINSN_getlocal_WC_0: ruby_vminsn_type = 98; +pub const YARVINSN_getlocal_WC_1: ruby_vminsn_type = 99; +pub const YARVINSN_setlocal_WC_0: ruby_vminsn_type = 100; +pub const YARVINSN_setlocal_WC_1: ruby_vminsn_type = 101; +pub const YARVINSN_putobject_INT2FIX_0_: ruby_vminsn_type = 102; +pub const YARVINSN_putobject_INT2FIX_1_: ruby_vminsn_type = 103; +pub const YARVINSN_trace_nop: ruby_vminsn_type = 104; +pub const YARVINSN_trace_getlocal: ruby_vminsn_type = 105; +pub const YARVINSN_trace_setlocal: ruby_vminsn_type = 106; +pub const YARVINSN_trace_getblockparam: ruby_vminsn_type = 107; +pub const YARVINSN_trace_setblockparam: ruby_vminsn_type = 108; +pub const YARVINSN_trace_getblockparamproxy: ruby_vminsn_type = 109; +pub const YARVINSN_trace_getspecial: ruby_vminsn_type = 110; +pub const YARVINSN_trace_setspecial: ruby_vminsn_type = 111; +pub const YARVINSN_trace_getinstancevariable: ruby_vminsn_type = 112; +pub const YARVINSN_trace_setinstancevariable: ruby_vminsn_type = 113; +pub const YARVINSN_trace_getclassvariable: ruby_vminsn_type = 114; +pub const YARVINSN_trace_setclassvariable: ruby_vminsn_type = 115; +pub const YARVINSN_trace_opt_getconstant_path: ruby_vminsn_type = 116; +pub const YARVINSN_trace_getconstant: ruby_vminsn_type = 117; +pub const YARVINSN_trace_setconstant: ruby_vminsn_type = 118; +pub const YARVINSN_trace_getglobal: ruby_vminsn_type = 119; +pub const YARVINSN_trace_setglobal: ruby_vminsn_type = 120; +pub const YARVINSN_trace_putnil: ruby_vminsn_type = 121; +pub const YARVINSN_trace_putself: ruby_vminsn_type = 122; +pub const YARVINSN_trace_putobject: ruby_vminsn_type = 123; +pub const YARVINSN_trace_putspecialobject: ruby_vminsn_type = 124; +pub const YARVINSN_trace_putstring: ruby_vminsn_type = 125; +pub const YARVINSN_trace_concatstrings: ruby_vminsn_type = 126; +pub const YARVINSN_trace_anytostring: ruby_vminsn_type = 127; +pub const YARVINSN_trace_toregexp: ruby_vminsn_type = 128; +pub const YARVINSN_trace_intern: ruby_vminsn_type = 129; +pub const YARVINSN_trace_newarray: ruby_vminsn_type = 130; +pub const YARVINSN_trace_newarraykwsplat: ruby_vminsn_type = 131; +pub const YARVINSN_trace_duparray: ruby_vminsn_type = 132; +pub const YARVINSN_trace_duphash: ruby_vminsn_type = 133; +pub const YARVINSN_trace_expandarray: ruby_vminsn_type = 134; +pub const YARVINSN_trace_concatarray: ruby_vminsn_type = 135; +pub const YARVINSN_trace_concattoarray: ruby_vminsn_type = 136; +pub const YARVINSN_trace_pushtoarray: ruby_vminsn_type = 137; +pub const YARVINSN_trace_splatarray: ruby_vminsn_type = 138; +pub const YARVINSN_trace_splatkw: ruby_vminsn_type = 139; +pub const YARVINSN_trace_newhash: ruby_vminsn_type = 140; +pub const YARVINSN_trace_newrange: ruby_vminsn_type = 141; +pub const YARVINSN_trace_pop: ruby_vminsn_type = 142; +pub const YARVINSN_trace_dup: ruby_vminsn_type = 143; +pub const YARVINSN_trace_dupn: ruby_vminsn_type = 144; +pub const YARVINSN_trace_swap: ruby_vminsn_type = 145; +pub const YARVINSN_trace_opt_reverse: ruby_vminsn_type = 146; +pub const YARVINSN_trace_topn: ruby_vminsn_type = 147; +pub const YARVINSN_trace_setn: ruby_vminsn_type = 148; +pub const YARVINSN_trace_adjuststack: ruby_vminsn_type = 149; +pub const YARVINSN_trace_defined: ruby_vminsn_type = 150; +pub const YARVINSN_trace_definedivar: ruby_vminsn_type = 151; +pub const YARVINSN_trace_checkmatch: ruby_vminsn_type = 152; +pub const YARVINSN_trace_checkkeyword: ruby_vminsn_type = 153; +pub const YARVINSN_trace_checktype: ruby_vminsn_type = 154; +pub const YARVINSN_trace_defineclass: ruby_vminsn_type = 155; +pub const YARVINSN_trace_definemethod: ruby_vminsn_type = 156; +pub const YARVINSN_trace_definesmethod: ruby_vminsn_type = 157; +pub const YARVINSN_trace_send: ruby_vminsn_type = 158; +pub const YARVINSN_trace_opt_send_without_block: ruby_vminsn_type = 159; +pub const YARVINSN_trace_objtostring: ruby_vminsn_type = 160; +pub const YARVINSN_trace_opt_str_freeze: ruby_vminsn_type = 161; +pub const YARVINSN_trace_opt_nil_p: ruby_vminsn_type = 162; +pub const YARVINSN_trace_opt_str_uminus: ruby_vminsn_type = 163; +pub const YARVINSN_trace_opt_newarray_send: ruby_vminsn_type = 164; +pub const YARVINSN_trace_invokesuper: ruby_vminsn_type = 165; +pub const YARVINSN_trace_invokeblock: ruby_vminsn_type = 166; +pub const YARVINSN_trace_leave: ruby_vminsn_type = 167; +pub const YARVINSN_trace_throw: ruby_vminsn_type = 168; +pub const YARVINSN_trace_jump: ruby_vminsn_type = 169; +pub const YARVINSN_trace_branchif: ruby_vminsn_type = 170; +pub const YARVINSN_trace_branchunless: ruby_vminsn_type = 171; +pub const YARVINSN_trace_branchnil: ruby_vminsn_type = 172; +pub const YARVINSN_trace_once: ruby_vminsn_type = 173; +pub const YARVINSN_trace_opt_case_dispatch: ruby_vminsn_type = 174; +pub const YARVINSN_trace_opt_plus: ruby_vminsn_type = 175; +pub const YARVINSN_trace_opt_minus: ruby_vminsn_type = 176; +pub const YARVINSN_trace_opt_mult: ruby_vminsn_type = 177; +pub const YARVINSN_trace_opt_div: ruby_vminsn_type = 178; +pub const YARVINSN_trace_opt_mod: ruby_vminsn_type = 179; +pub const YARVINSN_trace_opt_eq: ruby_vminsn_type = 180; +pub const YARVINSN_trace_opt_neq: ruby_vminsn_type = 181; +pub const YARVINSN_trace_opt_lt: ruby_vminsn_type = 182; +pub const YARVINSN_trace_opt_le: ruby_vminsn_type = 183; +pub const YARVINSN_trace_opt_gt: ruby_vminsn_type = 184; +pub const YARVINSN_trace_opt_ge: ruby_vminsn_type = 185; +pub const YARVINSN_trace_opt_ltlt: ruby_vminsn_type = 186; +pub const YARVINSN_trace_opt_and: ruby_vminsn_type = 187; +pub const YARVINSN_trace_opt_or: ruby_vminsn_type = 188; +pub const YARVINSN_trace_opt_aref: ruby_vminsn_type = 189; +pub const YARVINSN_trace_opt_aset: ruby_vminsn_type = 190; +pub const YARVINSN_trace_opt_aset_with: ruby_vminsn_type = 191; +pub const YARVINSN_trace_opt_aref_with: ruby_vminsn_type = 192; +pub const YARVINSN_trace_opt_length: ruby_vminsn_type = 193; +pub const YARVINSN_trace_opt_size: ruby_vminsn_type = 194; +pub const YARVINSN_trace_opt_empty_p: ruby_vminsn_type = 195; +pub const YARVINSN_trace_opt_succ: ruby_vminsn_type = 196; +pub const YARVINSN_trace_opt_not: ruby_vminsn_type = 197; +pub const YARVINSN_trace_opt_regexpmatch2: ruby_vminsn_type = 198; +pub const YARVINSN_trace_invokebuiltin: ruby_vminsn_type = 199; +pub const YARVINSN_trace_opt_invokebuiltin_delegate: ruby_vminsn_type = 200; +pub const YARVINSN_trace_opt_invokebuiltin_delegate_leave: ruby_vminsn_type = 201; +pub const YARVINSN_trace_getlocal_WC_0: ruby_vminsn_type = 202; +pub const YARVINSN_trace_getlocal_WC_1: ruby_vminsn_type = 203; +pub const YARVINSN_trace_setlocal_WC_0: ruby_vminsn_type = 204; +pub const YARVINSN_trace_setlocal_WC_1: ruby_vminsn_type = 205; +pub const YARVINSN_trace_putobject_INT2FIX_0_: ruby_vminsn_type = 206; +pub const YARVINSN_trace_putobject_INT2FIX_1_: ruby_vminsn_type = 207; +pub const VM_INSTRUCTION_SIZE: ruby_vminsn_type = 208; pub type ruby_vminsn_type = u32; pub type rb_iseq_callback = ::std::option::Option< unsafe extern "C" fn(arg1: *const rb_iseq_t, arg2: *mut ::std::os::raw::c_void), From 0f90a24a816bec438edb272fb83f334484dfc285 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Thu, 30 Nov 2023 14:58:42 -0800 Subject: [PATCH 525/640] Introduce Allocationless Anonymous Splat Forwarding Ruby makes it easy to delegate all arguments from one method to another: ```ruby def f(*args, **kw) g(*args, **kw) end ``` Unfortunately, this indirection decreases performance. One reason it decreases performance is that this allocates an array and a hash per call to `f`, even if `args` and `kw` are not modified. Due to Ruby's ability to modify almost anything at runtime, it's difficult to avoid the array allocation in the general case. For example, it's not safe to avoid the allocation in a case like this: ```ruby def f(*args, **kw) foo(bar) g(*args, **kw) end ``` Because `foo` may be `eval` and `bar` may be a string referencing `args` or `kw`. To fix this correctly, you need to perform something similar to escape analysis on the variables. However, there is a case where you can avoid the allocation without doing escape analysis, and that is when the splat variables are anonymous: ```ruby def f(*, **) g(*, **) end ``` When splat variables are anonymous, it is not possible to reference them directly, it is only possible to use them as splats to other methods. Since that is the case, if `f` is called with a regular splat and a keyword splat, it can pass the arguments directly to `g` without copying them, avoiding allocation. For example: ```ruby def g(a, b:) a + b end def f(*, **) g(*, **) end a = [1] kw = {b: 2} f(*a, **kw) ``` I call this technique: Allocationless Anonymous Splat Forwarding. This is implemented using a couple additional iseq param flags, anon_rest and anon_kwrest. If anon_rest is set, and an array splat is passed when calling the method when the array splat can be used without modification, `setup_parameters_complex` does not duplicate it. Similarly, if anon_kwest is set, and a keyword splat is passed when calling the method, `setup_parameters_complex` does not duplicate it. --- compile.c | 8 ++++++++ rjit_c.rb | 2 ++ vm_args.c | 28 ++++++++++++++++++++++++---- vm_core.h | 2 ++ 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/compile.c b/compile.c index 67b22db5dc6cbc..dfc1980bcc629e 100644 --- a/compile.c +++ b/compile.c @@ -2072,6 +2072,7 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *cons if (rest_id) { body->param.rest_start = arg_size++; body->param.flags.has_rest = TRUE; + if (rest_id == '*') body->param.flags.anon_rest = TRUE; assert(body->param.rest_start != -1); } @@ -2090,10 +2091,15 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *cons arg_size = iseq_set_arguments_keywords(iseq, optargs, args, arg_size); } else if (args->kw_rest_arg) { + ID kw_id = iseq->body->local_table[arg_size]; 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; + + static ID anon_kwrest = 0; + if (!anon_kwrest) anon_kwrest = rb_intern("**"); + if (kw_id == anon_kwrest) body->param.flags.anon_kwrest = TRUE; } else if (args->no_kwarg) { body->param.flags.accepts_no_kwarg = TRUE; @@ -12848,6 +12854,8 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset) load_body->param.flags.ambiguous_param0 = (param_flags >> 7) & 1; load_body->param.flags.accepts_no_kwarg = (param_flags >> 8) & 1; load_body->param.flags.ruby2_keywords = (param_flags >> 9) & 1; + load_body->param.flags.anon_rest = (param_flags >> 10) & 1; + load_body->param.flags.anon_kwrest = (param_flags >> 11) & 1; load_body->param.size = param_size; load_body->param.lead_num = param_lead_num; load_body->param.opt_num = param_opt_num; diff --git a/rjit_c.rb b/rjit_c.rb index 92674643c6ea6a..dd037a9547cd1e 100644 --- a/rjit_c.rb +++ b/rjit_c.rb @@ -1131,6 +1131,8 @@ def C.rb_iseq_constant_body ambiguous_param0: [CType::BitField.new(1, 7), 7], accepts_no_kwarg: [CType::BitField.new(1, 0), 8], ruby2_keywords: [CType::BitField.new(1, 1), 9], + anon_rest: [CType::BitField.new(1, 2), 10], + anon_kwrest: [CType::BitField.new(1, 3), 11], ), Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->param, flags)")], size: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->param, size)")], lead_num: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->param, lead_num)")], diff --git a/vm_args.c b/vm_args.c index 8171dcb8e0b0ad..e7043ac8970938 100644 --- a/vm_args.c +++ b/vm_args.c @@ -475,7 +475,8 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co const int min_argc = ISEQ_BODY(iseq)->param.lead_num + ISEQ_BODY(iseq)->param.post_num; const int max_argc = (ISEQ_BODY(iseq)->param.flags.has_rest == FALSE) ? min_argc + ISEQ_BODY(iseq)->param.opt_num : UNLIMITED_ARGUMENTS; int given_argc; - unsigned int kw_flag = vm_ci_flag(ci) & (VM_CALL_KWARG | VM_CALL_KW_SPLAT | VM_CALL_KW_SPLAT_MUT); + unsigned int ci_flag = vm_ci_flag(ci); + unsigned int kw_flag = ci_flag & (VM_CALL_KWARG | VM_CALL_KW_SPLAT | VM_CALL_KW_SPLAT_MUT); int opt_pc = 0, allow_autosplat = !kw_flag; struct args_info args_body, *args; VALUE keyword_hash = Qnil; @@ -510,7 +511,26 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co args = &args_body; given_argc = args->argc = calling->argc; args->argv = locals; - args->rest_dupped = vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT_MUT; + args->rest_dupped = ci_flag & VM_CALL_ARGS_SPLAT_MUT; + + if (UNLIKELY(ISEQ_BODY(iseq)->param.flags.anon_rest)) { + if ((ci_flag & VM_CALL_ARGS_SPLAT) && + given_argc == ISEQ_BODY(iseq)->param.lead_num + (kw_flag ? 2 : 1) && + !ISEQ_BODY(iseq)->param.flags.has_opt && + !ISEQ_BODY(iseq)->param.flags.has_post && + (!kw_flag || + !ISEQ_BODY(iseq)->param.flags.has_kw || + !ISEQ_BODY(iseq)->param.flags.has_kwrest || + !ISEQ_BODY(iseq)->param.flags.accepts_no_kwarg)) { + args->rest_dupped = true; + } + } + + if (UNLIKELY(ISEQ_BODY(iseq)->param.flags.anon_kwrest)) { + if (kw_flag & VM_CALL_KW_SPLAT) { + kw_flag |= VM_CALL_KW_SPLAT_MUT; + } + } if (kw_flag & VM_CALL_KWARG) { args->kw_arg = vm_ci_kwarg(ci); @@ -534,7 +554,7 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co args->kw_argv = NULL; } - if ((vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT) && (vm_ci_flag(ci) & VM_CALL_KW_SPLAT)) { + if ((ci_flag & VM_CALL_ARGS_SPLAT) && (ci_flag & VM_CALL_KW_SPLAT)) { // f(*a, **kw) args->rest_index = 0; keyword_hash = locals[--args->argc]; @@ -563,7 +583,7 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co int len = RARRAY_LENINT(args->rest); given_argc += len - 2; } - else if (vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT) { + else if (ci_flag & VM_CALL_ARGS_SPLAT) { // f(*a) args->rest_index = 0; args->rest = locals[--args->argc]; diff --git a/vm_core.h b/vm_core.h index 6532c6b038c3c8..c1508736bde048 100644 --- a/vm_core.h +++ b/vm_core.h @@ -416,6 +416,8 @@ struct rb_iseq_constant_body { unsigned int ambiguous_param0 : 1; /* {|a|} */ unsigned int accepts_no_kwarg : 1; unsigned int ruby2_keywords: 1; + unsigned int anon_rest: 1; + unsigned int anon_kwrest: 1; } flags; unsigned int size; From 4f77d8d3289ece0e3537d9273a5c745120bff59a Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Fri, 8 Dec 2023 14:30:39 -0800 Subject: [PATCH 526/640] Do not use ruby2_keywords for ... argument forwarding This allows ... argument forwarding to benefit from Allocationless Anonymous Splat Forwarding, allowing the `f` call below to not allocate an array or a hash. ```ruby a = [1] kw = {b: 2} def c(a, b:) end def f(...) c(...) end f(*a, **kw) ``` This temporarily skips prism locals tests until prism is changed to use * and ** for ..., instead of using ruby2_keywords. Ignore failures in rbs bundled gems tests, since they fail due to this change. --- .github/workflows/ubuntu.yml | 2 +- parse.y | 1 - test/prism/locals_test.rb | 2 +- test/prism/newline_test.rb | 1 + test/ruby/test_ast.rb | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index b78570e22479c0..3a8c563cf48f67 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -99,7 +99,7 @@ jobs: env: RUBY_TESTOPTS: '-q --tty=no' TESTS: ${{ matrix.test_task == 'check' && matrix.skipped_tests || '' }} - TEST_BUNDLED_GEMS_ALLOW_FAILURES: 'typeprof' + TEST_BUNDLED_GEMS_ALLOW_FAILURES: 'rbs,typeprof' PRECHECK_BUNDLED_GEMS: 'no' - name: make skipped tests diff --git a/parse.y b/parse.y index 71b7507d272d92..db7154446d11e0 100644 --- a/parse.y +++ b/parse.y @@ -1627,7 +1627,6 @@ static void numparam_pop(struct parser_params *p, NODE *prev_inner); #else #define arg_FWD_BLOCK idFWD_BLOCK #endif -#define FORWARD_ARGS_WITH_RUBY2_KEYWORDS #define RE_OPTION_ONCE (1<<16) #define RE_OPTION_ENCODING_SHIFT 8 diff --git a/test/prism/locals_test.rb b/test/prism/locals_test.rb index df391ca048c5bc..3dbe58f64da336 100644 --- a/test/prism/locals_test.rb +++ b/test/prism/locals_test.rb @@ -83,7 +83,7 @@ class LocalsTest < TestCase filepath = File.join(base, relative) define_method("test_#{relative}") { assert_locals(filepath) } - end + end if false # skip until ... uses * and ** and not ruby2_keywords def setup @previous_default_external = Encoding.default_external diff --git a/test/prism/newline_test.rb b/test/prism/newline_test.rb index d99850286999d2..a3fff7a1d1a2b9 100644 --- a/test/prism/newline_test.rb +++ b/test/prism/newline_test.rb @@ -11,6 +11,7 @@ class NewlineTest < TestCase filepaths.each do |relative| define_method("test_newline_flags_#{relative}") do + next if relative == 'locals_test.rb' assert_newlines(base, relative) end end diff --git a/test/ruby/test_ast.rb b/test/ruby/test_ast.rb index efd27548bddb43..d19bda118f1097 100644 --- a/test/ruby/test_ast.rb +++ b/test/ruby/test_ast.rb @@ -661,7 +661,7 @@ def test_argument_forwarding node ? [node.children[-4], node.children[-2]&.children, node.children[-1]] : [] end - assert_equal([:*, nil, :&], forwarding.call('...')) + assert_equal([:*, [:**], :&], forwarding.call('...')) end def test_ranges_numbered_parameter From 42d891be2c202eae4ddfa15a4338712fd6d63668 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Thu, 14 Dec 2023 16:48:09 -0800 Subject: [PATCH 527/640] Add benchmark for implicit array/hash allocation reduction changes Benchmark results: ``` named_multi_arg_splat after: 5344097.6 i/s before: 3088134.0 i/s - 1.73x slower named_post_splat after: 5401882.3 i/s before: 2629321.8 i/s - 2.05x slower anon_arg_splat after: 12242780.9 i/s before: 6845413.2 i/s - 1.79x slower anon_arg_kw_splat after: 11277398.7 i/s before: 4329509.4 i/s - 2.60x slower anon_multi_arg_splat after: 5132699.5 i/s before: 3018103.7 i/s - 1.70x slower anon_post_splat after: 5602915.1 i/s before: 2645185.5 i/s - 2.12x slower anon_kw_splat after: 15403727.3 i/s before: 6249504.6 i/s - 2.46x slower anon_fw_to_named_splat after: 2985715.3 i/s before: 2049159.9 i/s - 1.46x slower anon_fw_to_named_no_splat after: 2941030.4 i/s before: 2100380.0 i/s - 1.40x slower fw_to_named_splat after: 2801008.7 i/s before: 2012416.4 i/s - 1.39x slower fw_to_named_no_splat after: 2742670.4 i/s before: 1957707.2 i/s - 1.40x slower fw_to_anon_to_named_splat after: 2309246.6 i/s before: 1375924.6 i/s - 1.68x slower fw_to_anon_to_named_no_splat after: 2193227.6 i/s before: 1351184.1 i/s - 1.62x slower ``` --- benchmark/vm_method_splat_calls2.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 benchmark/vm_method_splat_calls2.yml diff --git a/benchmark/vm_method_splat_calls2.yml b/benchmark/vm_method_splat_calls2.yml new file mode 100644 index 00000000000000..0b09fce88f542b --- /dev/null +++ b/benchmark/vm_method_splat_calls2.yml @@ -0,0 +1,25 @@ +prelude: | + def named_arg_splat(*a) end + def named_arg_kw_splat(*a, **kw) end + def anon_arg_splat(*) end + def anon_kw_splat(**) end + def anon_arg_kw_splat(*, **) end + def anon_fw_to_named(*, **) named_arg_kw_splat(*, **) end + def fw_to_named(...) named_arg_kw_splat(...) end + def fw_to_anon_to_named(...) anon_fw_to_named(...) end + a = [1] + kw = {y: 1} +benchmark: + named_multi_arg_splat: "named_arg_splat(*a, *a)" + named_post_splat: "named_arg_splat(*a, a)" + anon_arg_splat: "anon_arg_splat(*a)" + anon_arg_kw_splat: "anon_arg_kw_splat(*a, **kw)" + anon_multi_arg_splat: "anon_arg_splat(*a, *a)" + anon_post_splat: "anon_arg_splat(*a, a)" + anon_kw_splat: "anon_kw_splat(**kw)" + anon_fw_to_named_splat: "anon_fw_to_named(*a, **kw)" + anon_fw_to_named_no_splat: "anon_fw_to_named(1, y: 1)" + fw_to_named_splat: "fw_to_named(*a, **kw)" + fw_to_named_no_splat: "fw_to_named(1, y: 1)" + fw_to_anon_to_named_splat: "fw_to_anon_to_named(*a, **kw)" + fw_to_anon_to_named_no_splat: "fw_to_anon_to_named(1, y: 1)" From fb596499f7b1538c5039861852e55aff4dd182bb Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Wed, 24 Jan 2024 18:39:54 -0800 Subject: [PATCH 528/640] Temporarily ignore bundled gems failures for rbs and typeprof on macos, similar to ubuntu This should be reverted after rbs and typeprof are updated to handle the changes for the optimizations. --- .github/workflows/macos.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index f665085f1d0feb..82aac2fdf56727 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -85,7 +85,7 @@ jobs: env: RUBY_TESTOPTS: '-q --tty=no' TESTS: ${{ matrix.test_task == 'check' && matrix.skipped_tests || '' }} - TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' + TEST_BUNDLED_GEMS_ALLOW_FAILURES: 'rbs,typeprof' PRECHECK_BUNDLED_GEMS: 'no' - name: make skipped tests From 2b9719ea30fe4227c082e3cc7e03803ff018e67f Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Wed, 24 Jan 2024 19:13:30 -0800 Subject: [PATCH 529/640] Ignore --parser=prism failures until prism compiler fixed for recent optimizations --- .github/workflows/prism.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/prism.yml b/.github/workflows/prism.yml index 5c0148e8b55268..d8fbb8ee830eb0 100644 --- a/.github/workflows/prism.yml +++ b/.github/workflows/prism.yml @@ -91,6 +91,7 @@ jobs: GNUMAKEFLAGS: '' RUBY_TESTOPTS: '-v --tty=no' RUN_OPTS: ${{ matrix.run_opts }} + continue-on-error: true # - name: make test # run: | From ff55d6b8e1e4c22a80f6bbf882c5ae4a07a9eb45 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 25 Jan 2024 14:33:53 +0900 Subject: [PATCH 530/640] Use `token_seen` and simplify `comment_at_top` Instead of scanning before the current comment. --- parse.y | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/parse.y b/parse.y index db7154446d11e0..878869b35923b8 100644 --- a/parse.y +++ b/parse.y @@ -9630,16 +9630,11 @@ parser_set_encode(struct parser_params *p, const char *name) #endif } -static int +static bool comment_at_top(struct parser_params *p) { - const char *ptr = p->lex.pbeg, *ptr_end = p->lex.pcur - 1; - if (p->line_count != (p->has_shebang ? 2 : 1)) return 0; - while (ptr < ptr_end) { - if (!ISSPACE(*ptr)) return 0; - ptr++; - } - return 1; + if (p->token_seen) return false; + return (p->line_count == (p->has_shebang ? 2 : 1)); } typedef long (*rb_magic_comment_length_t)(struct parser_params *p, const char *name, long len); From 1d972498eb62a0d718501a956cc391ee59a1d9d1 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 25 Jan 2024 11:42:26 +0900 Subject: [PATCH 531/640] Use Encoding::CESU_8 for test case Encoding::Windows_31J is already loaded in mswin platform --- test/-ext-/string/test_fstring.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/-ext-/string/test_fstring.rb b/test/-ext-/string/test_fstring.rb index b7416ccbf37d95..f737c9a2694984 100644 --- a/test/-ext-/string/test_fstring.rb +++ b/test/-ext-/string/test_fstring.rb @@ -15,16 +15,16 @@ def assert_fstring(str) def test_rb_enc_interned_str_autoloaded_encoding assert_separately([], <<~RUBY) require '-test-/string' - assert_include(Encoding::Windows_31J.inspect, 'autoload') - Bug::String.rb_enc_interned_str(Encoding::Windows_31J) + assert_include(Encoding::CESU_8.inspect, 'autoload') + Bug::String.rb_enc_interned_str(Encoding::CESU_8) RUBY end def test_rb_enc_str_new_autoloaded_encoding assert_separately([], <<~RUBY) require '-test-/string' - assert_include(Encoding::Windows_31J.inspect, 'autoload') - Bug::String.rb_enc_str_new(Encoding::Windows_31J) + assert_include(Encoding::CESU_8.inspect, 'autoload') + Bug::String.rb_enc_str_new(Encoding::CESU_8) RUBY end From d13a57cd65153409e826b52ad653147ea24069a4 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 25 Jan 2024 14:23:12 +0900 Subject: [PATCH 532/640] Use Encoding.local_charmap instead of locale In my windows environment uses cp932 for terminal encoding. --- test/ruby/test_process.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb index 8fb3a9df0caad9..8de4b80d64e579 100644 --- a/test/ruby/test_process.rb +++ b/test/ruby/test_process.rb @@ -2170,7 +2170,7 @@ def test_exec_nonascii "c\u{1EE7}a", ].each do |arg| begin - arg = arg.encode(Encoding.find("locale")) + arg = arg.encode(Encoding.local_charmap) rescue else assert_in_out_err([], "#{<<-"begin;"}\n#{<<-"end;"}", [arg], [], bug12841) From 0f5407b33772743154c50b01e1ea2ade494bd520 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 25 Jan 2024 14:34:35 +0900 Subject: [PATCH 533/640] Simplified test case for encoding option Co-authored-by: Nobuyoshi Nakada --- test/ruby/test_rubyoptions.rb | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/test/ruby/test_rubyoptions.rb b/test/ruby/test_rubyoptions.rb index e98bd9fb17e63d..97d78ba1667bbe 100644 --- a/test/ruby/test_rubyoptions.rb +++ b/test/ruby/test_rubyoptions.rb @@ -366,18 +366,10 @@ def test_encoding assert_in_out_err(%w(--encoding test_ruby_test_rubyoptions_foobarbazqux), "", [], /unknown encoding name - test_ruby_test_rubyoptions_foobarbazqux \(RuntimeError\)/) - if /mswin|mingw|aix|android/ =~ RUBY_PLATFORM && - (str = "\u3042".force_encoding(Encoding.find("external"))).valid_encoding? - # This result depends on locale because LANG=C doesn't affect locale - # on Windows. - # On AIX, the source encoding of stdin with LANG=C is ISO-8859-1, - # which allows \u3042. - out, err = [str], [] - else - out, err = [], /invalid multibyte char/ - end - assert_in_out_err(%w(-Eutf-8), "puts '\u3042'", out, err) - assert_in_out_err(%w(--encoding utf-8), "puts '\u3042'", out, err) + assert_in_out_err(%w(-Eutf-8), 'puts Encoding::default_external', ["UTF-8"]) + assert_in_out_err(%w(-Ecesu-8), 'puts Encoding::default_external', ["CESU-8"]) + assert_in_out_err(%w(--encoding utf-8), 'puts Encoding::default_external', ["UTF-8"]) + assert_in_out_err(%w(--encoding cesu-8), 'puts Encoding::default_external', ["CESU-8"]) end def test_syntax_check From 4d4d418457a1b6dc2ce63b166cff51fd0827c0a3 Mon Sep 17 00:00:00 2001 From: ydah <13041216+ydah@users.noreply.github.com> Date: Thu, 25 Jan 2024 11:25:56 +0900 Subject: [PATCH 534/640] [ruby/irb] overrided ==> overridden https://github.com/ruby/irb/commit/b77b23aade --- test/irb/test_input_method.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/irb/test_input_method.rb b/test/irb/test_input_method.rb index 6974fe2df8101b..0b52d4cbc31209 100644 --- a/test/irb/test_input_method.rb +++ b/test/irb/test_input_method.rb @@ -15,7 +15,7 @@ def setup def teardown IRB.conf.replace(@conf_backup) restore_encodings - # Reset Reline configuration overrided by RelineInputMethod. + # Reset Reline configuration overridden by RelineInputMethod. Reline.instance_variable_set(:@core, nil) end end From 6580a95f8d5a74bec20d41eb9660a93f13be8922 Mon Sep 17 00:00:00 2001 From: ydah <13041216+ydah@users.noreply.github.com> Date: Thu, 25 Jan 2024 11:26:13 +0900 Subject: [PATCH 535/640] [ruby/irb] inifinity ==> infinity https://github.com/ruby/irb/commit/78dea58000 --- lib/irb/history.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/irb/history.rb b/lib/irb/history.rb index 06088adb0d7d92..50fe1ce22995f1 100644 --- a/lib/irb/history.rb +++ b/lib/irb/history.rb @@ -65,7 +65,7 @@ def save_history begin hist = hist.last(num) if hist.size > num and num > 0 rescue RangeError # bignum too big to convert into `long' - # Do nothing because the bignum should be treated as inifinity + # Do nothing because the bignum should be treated as infinity end end f.puts(hist) From fd9b968569fc8b7a4cdc3dcad815cd3aab8d7088 Mon Sep 17 00:00:00 2001 From: ydah <13041216+ydah@users.noreply.github.com> Date: Thu, 25 Jan 2024 11:26:33 +0900 Subject: [PATCH 536/640] [ruby/irb] recever ==> receiver https://github.com/ruby/irb/commit/dbd0e368c4 --- lib/irb/nesting_parser.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/irb/nesting_parser.rb b/lib/irb/nesting_parser.rb index 3d4db8244451dd..23eeeaf6cfc714 100644 --- a/lib/irb/nesting_parser.rb +++ b/lib/irb/nesting_parser.rb @@ -61,17 +61,17 @@ def self.scan_opens(tokens) if args.include?(:arg) case t.event when :on_nl, :on_semicolon - # def recever.f; + # def receiver.f; body = :normal when :on_lparen - # def recever.f() + # def receiver.f() next_args << :eq else if t.event == :on_op && t.tok == '=' # def receiver.f = body = :oneliner else - # def recever.f arg + # def receiver.f arg next_args << :arg_without_paren end end From 9b1cc68b770145b8ccd1ca10e7604e5f5af32d10 Mon Sep 17 00:00:00 2001 From: ydah <13041216+ydah@users.noreply.github.com> Date: Thu, 25 Jan 2024 11:27:00 +0900 Subject: [PATCH 537/640] [ruby/irb] configuation ==> configuration https://github.com/ruby/irb/commit/a27a511777 --- lib/irb.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/irb.rb b/lib/irb.rb index 5ced3d98a9cf12..48879a57d23ba6 100644 --- a/lib/irb.rb +++ b/lib/irb.rb @@ -413,7 +413,7 @@ # # By default, \IRB prefixes a newline to a multiline response. # -# You can change the initial default value by adding to the configuation file: +# You can change the initial default value by adding to the configuration file: # # IRB.conf[:NEWLINE_BEFORE_MULTILINE_OUTPUT] = false # From 5f9f46a24cd8c166baa4cdd3ef014b695eed6a0e Mon Sep 17 00:00:00 2001 From: ydah <13041216+ydah@users.noreply.github.com> Date: Thu, 25 Jan 2024 11:27:16 +0900 Subject: [PATCH 538/640] [ruby/irb] reseting ==> resetting https://github.com/ruby/irb/commit/6209f06c72 --- lib/irb.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/irb.rb b/lib/irb.rb index 48879a57d23ba6..b3b9e0929b2cf5 100644 --- a/lib/irb.rb +++ b/lib/irb.rb @@ -945,7 +945,7 @@ def debug_readline(binding) # Irb#eval_input will simply return the input, and we need to pass it to the debugger. input = if IRB.conf[:SAVE_HISTORY] && context.io.support_history_saving? # Previous IRB session's history has been saved when `Irb#run` is exited - # We need to make sure the saved history is not saved again by reseting the counter + # We need to make sure the saved history is not saved again by resetting the counter context.io.reset_history_counter begin From 819ae2c2c181b3e27e4ba57b66a7e89f1745ff09 Mon Sep 17 00:00:00 2001 From: ydah <13041216+ydah@users.noreply.github.com> Date: Thu, 25 Jan 2024 11:34:10 +0900 Subject: [PATCH 539/640] [ruby/irb] assigment ==> assignment https://github.com/ruby/irb/commit/24c7694467 --- lib/irb.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/irb.rb b/lib/irb.rb index b3b9e0929b2cf5..0ff87d5702d534 100644 --- a/lib/irb.rb +++ b/lib/irb.rb @@ -392,7 +392,7 @@ # (The default value for this entry is +niL+, which means the same as +:truncate+.) # - Giving command-line option --noecho-on-assignment # or --echo-on-assignment. -# (The default is --truncate-echo-on-assigment.) +# (The default is --truncate-echo-on-assignment.) # # During the session, you can change the current setting # with configuration method conf.echo_on_assignment= From 033411562802d1ec2d8a57dfef480f8e7d346214 Mon Sep 17 00:00:00 2001 From: ydah <13041216+ydah@users.noreply.github.com> Date: Thu, 25 Jan 2024 11:36:41 +0900 Subject: [PATCH 540/640] [ruby/irb] Synatx ==> Syntax https://github.com/ruby/irb/commit/2ffacaa031 --- lib/irb/context.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/irb/context.rb b/lib/irb/context.rb index 10dab861797d00..ac61b765c0f3a9 100644 --- a/lib/irb/context.rb +++ b/lib/irb/context.rb @@ -178,7 +178,7 @@ def initialize(irb, workspace = nil, input_method = nil) private def build_type_completor if RUBY_ENGINE == 'truffleruby' - # Avoid SynatxError. truffleruby does not support endless method definition yet. + # Avoid SyntaxError. truffleruby does not support endless method definition yet. warn 'TypeCompletor is not supported on TruffleRuby yet' return end From 4bd58e1ade11f9bc82b12427f59871dd73db7c50 Mon Sep 17 00:00:00 2001 From: ydah <13041216+ydah@users.noreply.github.com> Date: Thu, 25 Jan 2024 11:40:12 +0900 Subject: [PATCH 541/640] [ruby/irb] diabled ==> disabled https://github.com/ruby/irb/commit/295797ff37 --- test/irb/test_eval_history.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/irb/test_eval_history.rb b/test/irb/test_eval_history.rb index 0f9ec4811cf4d4..a6ab36fb8b4af8 100644 --- a/test/irb/test_eval_history.rb +++ b/test/irb/test_eval_history.rb @@ -30,7 +30,7 @@ def execute_lines(*lines, conf: {}, main: self, irb_path: nil) end end - def test_eval_history_is_diabled_by_default + def test_eval_history_is_disabled_by_default out, err = execute_lines( "a = 1", "__" From fdb8f086396e0f9b64e069852cb0dd40147877d1 Mon Sep 17 00:00:00 2001 From: Eddie Lebow <7873686+elebow@users.noreply.github.com> Date: Thu, 25 Jan 2024 05:20:44 -0500 Subject: [PATCH 542/640] [ruby/irb] Reword history file documentation and fix typo (https://github.com/ruby/irb/pull/842) https://github.com/ruby/irb/commit/bbabf818c7 --- lib/irb.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/irb.rb b/lib/irb.rb index 0ff87d5702d534..6e3448d6957367 100644 --- a/lib/irb.rb +++ b/lib/irb.rb @@ -203,11 +203,10 @@ # # === Input Command History # -# By default, \IRB stores a history of up to 1000 input commands -# in file ~/.irb_history -# (or, if a {configuration file}[rdoc-ref:IRB@Configuration+File] -# is found, in file +.irb_history+ -# inin the same directory as that file). +# By default, \IRB stores a history of up to 1000 input commands in a +# file named .irb_history. The history file will be in the same directory +# as the {configuration file}[rdoc-ref:IRB@Configuration+File] if one is found, or +# in ~/ otherwise. # # A new \IRB session creates the history file if it does not exist, # and appends to the file if it does exist. From ebf803aa196e2df4c129b1ec11107363ebbe1382 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 25 Jan 2024 08:43:41 -0500 Subject: [PATCH 543/640] [ruby/prism] Fix Ruby head build https://github.com/ruby/prism/commit/149e2ff7f6 --- lib/prism/debug.rb | 18 ++---------------- prism/prism.c | 5 ++--- test/prism/locals_test.rb | 20 +------------------- 3 files changed, 5 insertions(+), 38 deletions(-) diff --git a/lib/prism/debug.rb b/lib/prism/debug.rb index 24a27d07ef4fb0..f4c0bcf91a7a0e 100644 --- a/lib/prism/debug.rb +++ b/lib/prism/debug.rb @@ -59,21 +59,7 @@ def self.cruby_locals(source) stack = [ISeq.new(RubyVM::InstructionSequence.compile(source).to_a)] while (iseq = stack.pop) - names = [*iseq.local_table] - names.map!.with_index do |name, index| - # When an anonymous local variable is present in the iseq's local - # table, it is represented as the stack offset from the top. - # However, when these are dumped to binary and read back in, they - # are replaced with the symbol :#arg_rest. To consistently handle - # this, we replace them here with their index. - if name == :"#arg_rest" - names.length - index + 1 - else - name - end - end - - locals << names + locals << iseq.local_table iseq.each_child { |child| stack << child } end @@ -141,7 +127,7 @@ def self.prism_locals(source) sorted << AnonymousLocal if params.keywords.any? if params.keyword_rest.is_a?(ForwardingParameterNode) - sorted.push(:*, :&, :"...") + sorted.push(:*, :**, :&, :"...") elsif params.keyword_rest.is_a?(KeywordRestParameterNode) sorted << params.keyword_rest.name if params.keyword_rest.name end diff --git a/prism/prism.c b/prism/prism.c index 1c1b53f78713db..4d2602cdb93cc9 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -3999,9 +3999,8 @@ pm_keyword_hash_node_create(pm_parser_t *parser) { */ static void pm_keyword_hash_node_elements_append(pm_keyword_hash_node_t *hash, pm_node_t *element) { - // If the element being added is not an AssocNode or does not have a symbol key, then - // we want to turn the STATIC_KEYS flag off. - // TODO: Rename the flag to SYMBOL_KEYS instead. + // If the element being added is not an AssocNode or does not have a symbol + // key, then we want to turn the SYMBOL_KEYS flag off. if (!PM_NODE_TYPE_P(element, PM_ASSOC_NODE) || !PM_NODE_TYPE_P(((pm_assoc_node_t *) element)->key, PM_SYMBOL_NODE)) { pm_node_flag_unset((pm_node_t *)hash, PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS); } diff --git a/test/prism/locals_test.rb b/test/prism/locals_test.rb index 3dbe58f64da336..e7322b0314bb44 100644 --- a/test/prism/locals_test.rb +++ b/test/prism/locals_test.rb @@ -7,7 +7,7 @@ # # There have also been changes made in other versions of Ruby, so we only want # to test on the most recent versions. -return if !defined?(RubyVM::InstructionSequence) || RUBY_VERSION < "3.2" +return if !defined?(RubyVM::InstructionSequence) || RUBY_VERSION < "3.4.0" # Omit tests if running on a 32-bit machine because there is a bug with how # Ruby is handling large ISeqs on 32-bit machines @@ -57,24 +57,6 @@ class LocalsTest < TestCase # Dead code eliminated invalid << "whitequark/ruby_bug_10653.txt" - # case :a - # in Symbol(*lhs, x, *rhs) - # end - todos << "seattlerb/case_in.txt" - - # <<~HERE - # #{<<~THERE} - # THERE - # HERE - todos << "seattlerb/heredoc_nested.txt" - - # Ruby < 3.3.0 fails to parse: - # - # <<-' HERE' - # foo - # HERE - invalid << "heredocs_leading_whitespace.txt" if RUBY_VERSION < "3.3.0" - base = File.join(__dir__, "fixtures") skips = invalid | todos From 1301422dfe44ed6aca97b20f672098c276dd9bd4 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 25 Jan 2024 10:33:48 -0500 Subject: [PATCH 544/640] [PRISM] Fix VM_CALL_ARGS_SPLAT_MUT failures --- prism_compile.c | 1 + test/prism/locals_test.rb | 2 +- test/prism/newline_test.rb | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index a71209e0fd4124..f1b5d0f35ce2c1 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -1153,6 +1153,7 @@ pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinf // ^^ if (index + 1 < arguments_node_list.size) { ADD_INSN1(ret, &dummy_line_node, splatarray, Qtrue); + *flags |= VM_CALL_ARGS_SPLAT_MUT; } // If this is the first spalt array seen and it's the last // parameter, we don't want splatarray to dup it. diff --git a/test/prism/locals_test.rb b/test/prism/locals_test.rb index e7322b0314bb44..1453e7aecddedd 100644 --- a/test/prism/locals_test.rb +++ b/test/prism/locals_test.rb @@ -65,7 +65,7 @@ class LocalsTest < TestCase filepath = File.join(base, relative) define_method("test_#{relative}") { assert_locals(filepath) } - end if false # skip until ... uses * and ** and not ruby2_keywords + end def setup @previous_default_external = Encoding.default_external diff --git a/test/prism/newline_test.rb b/test/prism/newline_test.rb index a3fff7a1d1a2b9..d99850286999d2 100644 --- a/test/prism/newline_test.rb +++ b/test/prism/newline_test.rb @@ -11,7 +11,6 @@ class NewlineTest < TestCase filepaths.each do |relative| define_method("test_newline_flags_#{relative}") do - next if relative == 'locals_test.rb' assert_newlines(base, relative) end end From d4cc77e7b6107b136e977e9b107b2d50aaa42314 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Thu, 25 Jan 2024 08:23:26 -0800 Subject: [PATCH 545/640] YJIT: Add a counter for invokebuiltin exits (#9696) --- yjit.rb | 1 + yjit/src/codegen.rs | 2 ++ yjit/src/stats.rs | 2 ++ 3 files changed, 5 insertions(+) diff --git a/yjit.rb b/yjit.rb index c25ea8997d7710..06cb75adb147a3 100644 --- a/yjit.rb +++ b/yjit.rb @@ -271,6 +271,7 @@ def _print_stats_reasons(stats, out) # :nodoc: branchunless definedivar expandarray + invokebuiltin jump leave objtostring diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 33298eed5cdb71..06adbe8553f168 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -8786,6 +8786,7 @@ fn gen_invokebuiltin( // ec, self, and arguments if bf_argc + 2 > C_ARG_OPNDS.len() { + incr_counter!(invokebuiltin_too_many_args); return None; } @@ -8825,6 +8826,7 @@ fn gen_opt_invokebuiltin_delegate( // ec, self, and arguments if bf_argc + 2 > (C_ARG_OPNDS.len() as i32) { + incr_counter!(invokebuiltin_too_many_args); return None; } diff --git a/yjit/src/stats.rs b/yjit/src/stats.rs index b6add639c1510b..7e83fa504fb923 100644 --- a/yjit/src/stats.rs +++ b/yjit/src/stats.rs @@ -468,6 +468,8 @@ make_counters! { setlocal_wb_required, + invokebuiltin_too_many_args, + opt_plus_overflow, opt_minus_overflow, opt_mult_overflow, From e7262966c91c63511122153ea555c4cd420cd353 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Thu, 25 Jan 2024 11:32:31 -0500 Subject: [PATCH 546/640] [PRISM] Fix indentation of test_ScopeNode --- test/ruby/test_compile_prism.rb | 40 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 888e3d0a2a2b5c..6b8549df7f6186 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -2444,30 +2444,30 @@ def test_PinnedVariableNode ############################################################################ def test_ScopeNode - assert_separately(%w[], "#{<<-'begin;'}\n#{<<-'end;'}") - begin; - def compare_eval(source) - ruby_eval = RubyVM::InstructionSequence.compile("module A; " + source + "; end").eval - prism_eval = RubyVM::InstructionSequence.compile_prism("module B; " + source + "; end").eval + assert_separately(%w[], <<~'RUBY') + def compare_eval(source) + ruby_eval = RubyVM::InstructionSequence.compile("module A; " + source + "; end").eval + prism_eval = RubyVM::InstructionSequence.compile_prism("module B; " + source + "; end").eval - assert_equal ruby_eval, prism_eval - end + assert_equal ruby_eval, prism_eval + end - def assert_prism_eval(source) - $VERBOSE, verbose_bak = nil, $VERBOSE + def assert_prism_eval(source) + $VERBOSE, verbose_bak = nil, $VERBOSE - begin - compare_eval(source) + begin + compare_eval(source) - # Test "popped" functionality - compare_eval("#{source}; 1") - ensure - $VERBOSE = verbose_bak - end - end - assert_prism_eval("a = 1; 1.times do; { a: }; end") - assert_prism_eval("a = 1; def foo(a); a; end") - end; + # Test "popped" functionality + compare_eval("#{source}; 1") + ensure + $VERBOSE = verbose_bak + end + end + + assert_prism_eval("a = 1; 1.times do; { a: }; end") + assert_prism_eval("a = 1; def foo(a); a; end") + RUBY end ############################################################################ From e452caac10c651a2b7de5fdc076b7b44a66785d5 Mon Sep 17 00:00:00 2001 From: Matt Valentine-House Date: Thu, 25 Jan 2024 12:54:49 +0000 Subject: [PATCH 547/640] [PRISM] Fix next inside rescue --- prism_compile.c | 11 +++++++++++ test/ruby/test_compile_prism.rb | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index f1b5d0f35ce2c1..c0975b4acfe40f 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -6132,7 +6132,18 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // If we have statements to execute, we'll compile them here. Otherwise // we'll push nil onto the stack. if (cast->statements) { + + // We'll temporarily remove the end_label location from the iseq + // when compiling the statements so that next/redo statements + // inside the body will throw to the correct place instead of + // jumping straight to the end of this iseq + LABEL *prev_end = ISEQ_COMPILE_DATA(iseq)->end_label; + ISEQ_COMPILE_DATA(iseq)->end_label = NULL; + PM_COMPILE((pm_node_t *) cast->statements); + + // Now restore the end_label + ISEQ_COMPILE_DATA(iseq)->end_label = prev_end; } else { PM_PUTNIL; } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 6b8549df7f6186..7fb71a666e5312 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1206,6 +1206,15 @@ def test_NextNode next end CODE + + assert_prism_eval(<<~CODE) + [].each do + begin + rescue + next + end + end + CODE end def test_RedoNode From f0224adf2f6ec5c1a9c77001bfbfdae9eb93f5fc Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Thu, 25 Jan 2024 15:29:42 -0500 Subject: [PATCH 548/640] YJIT: Assert lea source operand type --- yjit/src/asm/x86_64/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/yjit/src/asm/x86_64/mod.rs b/yjit/src/asm/x86_64/mod.rs index 20ac13f09cbc8a..fbbfa714d85093 100644 --- a/yjit/src/asm/x86_64/mod.rs +++ b/yjit/src/asm/x86_64/mod.rs @@ -952,6 +952,7 @@ pub fn jmp32(cb: &mut CodeBlock, offset: i32) { pub fn lea(cb: &mut CodeBlock, dst: X86Opnd, src: X86Opnd) { if let X86Opnd::Reg(reg) = dst { assert!(reg.num_bits == 64); + assert!(matches!(src, X86Opnd::Mem(_) | X86Opnd::IPRel(_))); write_rm(cb, false, true, dst, src, None, &[0x8d]); } else { unreachable!(); From 2034e6ad5a22fa1dcde428751ae97a29ba434d7e Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Thu, 25 Jan 2024 13:45:58 -0800 Subject: [PATCH 549/640] YJIT: Support concattoarray and pushtoarray (#9708) --- bootstraptest/test_yjit.rb | 14 ++++++++++ vm_insnhelper.c | 6 ++++ yjit/bindgen/src/main.rs | 1 + yjit/src/codegen.rs | 50 ++++++++++++++++++++++++++++++++++ yjit/src/cruby.rs | 1 + yjit/src/cruby_bindings.inc.rs | 1 + 6 files changed, 73 insertions(+) diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index 6832a0d76c513f..a981ba150b5eed 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -4459,3 +4459,17 @@ def body body } + +# concatarray +assert_equal '[1, 2]', %q{ + def foo(a, b) = [a, b] + arr = [2] + foo(*[1], *arr) +} + +# pushtoarray +assert_equal '[1, 2]', %q{ + def foo(a, b) = [a, b] + arr = [1] + foo(*arr, 2) +} diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 55e79acdd82e16..edce1fbe41930a 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -5237,6 +5237,12 @@ rb_vm_concat_array(VALUE ary1, VALUE ary2st) return vm_concat_array(ary1, ary2st); } +VALUE +rb_vm_concat_to_array(VALUE ary1, VALUE ary2st) +{ + return vm_concat_to_array(ary1, ary2st); +} + static VALUE vm_splat_array(VALUE flag, VALUE ary) { diff --git a/yjit/bindgen/src/main.rs b/yjit/bindgen/src/main.rs index 45874f28a1308c..df9bb4d727fb1d 100644 --- a/yjit/bindgen/src/main.rs +++ b/yjit/bindgen/src/main.rs @@ -133,6 +133,7 @@ fn main() { .allowlist_function("rb_ary_new_capa") .allowlist_function("rb_ary_store") .allowlist_function("rb_ary_resurrect") + .allowlist_function("rb_ary_cat") .allowlist_function("rb_ary_clear") .allowlist_function("rb_ary_dup") .allowlist_function("rb_ary_push") diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 06adbe8553f168..2bec0cf6d4dc92 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -1459,6 +1459,54 @@ fn gen_concatarray( Some(KeepCompiling) } +// concat second array to first array. +// first argument must already be an array. +// attempts to convert second object to array using to_a. +fn gen_concattoarray( + jit: &mut JITState, + asm: &mut Assembler, + _ocb: &mut OutlinedCb, +) -> Option { + // Save the PC and SP because the callee may allocate + jit_prepare_routine_call(jit, asm); + + // Get the operands from the stack + let ary2_opnd = asm.stack_opnd(0); + let ary1_opnd = asm.stack_opnd(1); + + let ary = asm.ccall(rb_vm_concat_to_array as *const u8, vec![ary1_opnd, ary2_opnd]); + asm.stack_pop(2); // Keep them on stack during ccall for GC + + let stack_ret = asm.stack_push(Type::TArray); + asm.mov(stack_ret, ary); + + Some(KeepCompiling) +} + +// push given number of objects to array directly before. +fn gen_pushtoarray( + jit: &mut JITState, + asm: &mut Assembler, + _ocb: &mut OutlinedCb, +) -> Option { + let num = jit.get_arg(0).as_u64(); + + // Save the PC and SP because the callee may allocate + jit_prepare_routine_call(jit, asm); + + // Get the operands from the stack + let ary_opnd = asm.stack_opnd(num as i32); + let objp_opnd = asm.lea(asm.ctx.sp_opnd(-(num as isize) * SIZEOF_VALUE as isize)); + + let ary = asm.ccall(rb_ary_cat as *const u8, vec![ary_opnd, objp_opnd, num.into()]); + asm.stack_pop(num as usize + 1); // Keep it on stack during ccall for GC + + let stack_ret = asm.stack_push(Type::TArray); + asm.mov(stack_ret, ary); + + Some(KeepCompiling) +} + // new range initialized from top 2 values fn gen_newrange( jit: &mut JITState, @@ -8904,6 +8952,8 @@ fn get_gen_fn(opcode: VALUE) -> Option { YARVINSN_opt_newarray_send => Some(gen_opt_newarray_send), YARVINSN_splatarray => Some(gen_splatarray), YARVINSN_concatarray => Some(gen_concatarray), + YARVINSN_concattoarray => Some(gen_concattoarray), + YARVINSN_pushtoarray => Some(gen_pushtoarray), YARVINSN_newrange => Some(gen_newrange), YARVINSN_putstring => Some(gen_putstring), YARVINSN_expandarray => Some(gen_expandarray), diff --git a/yjit/src/cruby.rs b/yjit/src/cruby.rs index 9f289e93dda4ae..dda9f6ecd0edaf 100644 --- a/yjit/src/cruby.rs +++ b/yjit/src/cruby.rs @@ -114,6 +114,7 @@ pub use autogened::*; extern "C" { pub fn rb_vm_splat_array(flag: VALUE, ary: VALUE) -> VALUE; pub fn rb_vm_concat_array(ary1: VALUE, ary2st: VALUE) -> VALUE; + pub fn rb_vm_concat_to_array(ary1: VALUE, ary2st: VALUE) -> VALUE; pub fn rb_vm_defined( ec: EcPtr, reg_cfp: CfpPtr, diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs index 01f0cca2804376..2f965059d82187 100644 --- a/yjit/src/cruby_bindings.inc.rs +++ b/yjit/src/cruby_bindings.inc.rs @@ -936,6 +936,7 @@ extern "C" { pub fn rb_ary_store(ary: VALUE, key: ::std::os::raw::c_long, val: VALUE); pub fn rb_ary_dup(ary: VALUE) -> VALUE; pub fn rb_ary_resurrect(ary: VALUE) -> VALUE; + pub fn rb_ary_cat(ary: VALUE, train: *const VALUE, len: ::std::os::raw::c_long) -> VALUE; pub fn rb_ary_push(ary: VALUE, elem: VALUE) -> VALUE; pub fn rb_ary_clear(ary: VALUE) -> VALUE; pub fn rb_hash_new() -> VALUE; From 5bd6949151512a6667a58bcadcb019157b65cd7c Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Thu, 25 Jan 2024 16:59:42 -0500 Subject: [PATCH 550/640] [PRISM] Add raw option to assert_prism_eval --- test/ruby/test_compile_prism.rb | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 7fb71a666e5312..4ccea6d319ad73 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -59,10 +59,7 @@ def test_SourceFileNode end def test_SourceLineNode - ruby_eval = RubyVM::InstructionSequence.compile("__LINE__").eval - prism_eval = RubyVM::InstructionSequence.compile_prism("__LINE__").eval - - assert_equal ruby_eval, prism_eval + assert_prism_eval("__LINE__", raw: true) end def test_TrueNode @@ -776,10 +773,7 @@ def test_StringNode "hello".equal?("hello") RUBY ].each do |src| - ruby_eval = RubyVM::InstructionSequence.compile(src).eval - prism_eval = RubyVM::InstructionSequence.compile_prism(src).eval - - assert_equal ruby_eval, prism_eval, src + assert_prism_eval(src, raw: true) end end @@ -1710,15 +1704,8 @@ def test_ParenthesesNode end def test_PreExecutionNode - # BEGIN {} must be defined at the top level, so we need to manually - # call the evals here instead of calling `assert_prism_eval` - ruby_eval = RubyVM::InstructionSequence.compile("BEGIN { a = 1 }; 2").eval - prism_eval = RubyVM::InstructionSequence.compile_prism("BEGIN { a = 1 }; 2").eval - assert_equal ruby_eval, prism_eval - - ruby_eval = RubyVM::InstructionSequence.compile("b = 2; BEGIN { a = 1 }; a + b").eval - prism_eval = RubyVM::InstructionSequence.compile_prism("b = 2; BEGIN { a = 1 }; a + b").eval - assert_equal ruby_eval, prism_eval + assert_prism_eval("BEGIN { a = 1 }; 2", raw: true) + assert_prism_eval("b = 2; BEGIN { a = 1 }; a + b", raw: true) end def test_PostExecutionNode @@ -2498,8 +2485,8 @@ def test_encoding private - def compare_eval(source) - source = "class Prism::TestCompilePrism\n#{source}\nend" + def compare_eval(source, raw:) + source = raw ? source : "class Prism::TestCompilePrism\n#{source}\nend" ruby_eval = RubyVM::InstructionSequence.compile(source).eval prism_eval = RubyVM::InstructionSequence.compile_prism(source).eval @@ -2511,14 +2498,14 @@ def compare_eval(source) end end - def assert_prism_eval(source) + def assert_prism_eval(source, raw: false) $VERBOSE, verbose_bak = nil, $VERBOSE begin - compare_eval(source) + compare_eval(source, raw:) # Test "popped" functionality - compare_eval("#{source}; 1") + compare_eval("#{source}; 1", raw:) ensure $VERBOSE = verbose_bak end From b822f9f6fc5a00ec08dbc698b9845887d1c4dbc2 Mon Sep 17 00:00:00 2001 From: Soutaro Matsumoto Date: Fri, 26 Jan 2024 08:47:29 +0900 Subject: [PATCH 551/640] Bundle rbs-3.4.3 (#9702) * Bundle rbs-3.4.3 * Remove rbs from `TEST_BUNDLED_GEMS_ALLOW_FAILURES` list * Add the failing tests to `rbs_skip_tests` --- .github/workflows/macos.yml | 2 +- .github/workflows/ubuntu.yml | 2 +- .github/workflows/yjit-ubuntu.yml | 2 +- gems/bundled_gems | 2 +- tool/rbs_skip_tests | 3 +++ 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 82aac2fdf56727..1f93580c4eaeda 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -85,7 +85,7 @@ jobs: env: RUBY_TESTOPTS: '-q --tty=no' TESTS: ${{ matrix.test_task == 'check' && matrix.skipped_tests || '' }} - TEST_BUNDLED_GEMS_ALLOW_FAILURES: 'rbs,typeprof' + TEST_BUNDLED_GEMS_ALLOW_FAILURES: 'typeprof' PRECHECK_BUNDLED_GEMS: 'no' - name: make skipped tests diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 3a8c563cf48f67..b78570e22479c0 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -99,7 +99,7 @@ jobs: env: RUBY_TESTOPTS: '-q --tty=no' TESTS: ${{ matrix.test_task == 'check' && matrix.skipped_tests || '' }} - TEST_BUNDLED_GEMS_ALLOW_FAILURES: 'rbs,typeprof' + TEST_BUNDLED_GEMS_ALLOW_FAILURES: 'typeprof' PRECHECK_BUNDLED_GEMS: 'no' - name: make skipped tests diff --git a/.github/workflows/yjit-ubuntu.yml b/.github/workflows/yjit-ubuntu.yml index 82ca02890ef9fd..7998e6b2e944a1 100644 --- a/.github/workflows/yjit-ubuntu.yml +++ b/.github/workflows/yjit-ubuntu.yml @@ -169,7 +169,7 @@ jobs: timeout-minutes: 60 env: RUBY_TESTOPTS: '-q --tty=no' - TEST_BUNDLED_GEMS_ALLOW_FAILURES: 'rbs,typeprof' + TEST_BUNDLED_GEMS_ALLOW_FAILURES: 'typeprof' PRECHECK_BUNDLED_GEMS: 'no' SYNTAX_SUGGEST_TIMEOUT: '5' YJIT_BINDGEN_DIFF_OPTS: '--exit-code' diff --git a/gems/bundled_gems b/gems/bundled_gems index 02d583ebf656a2..fcdc6c20ee3f51 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -17,7 +17,7 @@ net-pop 0.1.2 https://github.com/ruby/net-pop net-smtp 0.4.0.1 https://github.com/ruby/net-smtp matrix 0.4.2 https://github.com/ruby/matrix prime 0.1.2 https://github.com/ruby/prime -rbs 3.4.2 https://github.com/ruby/rbs +rbs 3.4.3 https://github.com/ruby/rbs typeprof 0.21.9 https://github.com/ruby/typeprof debug 1.9.1 https://github.com/ruby/debug 91fe870eeceb9ffbbc7f1bb4673f9e2f6a2c1f60 racc 1.7.3 https://github.com/ruby/racc diff --git a/tool/rbs_skip_tests b/tool/rbs_skip_tests index c860ac3b454dcf..56a864d19313b7 100644 --- a/tool/rbs_skip_tests +++ b/tool/rbs_skip_tests @@ -22,6 +22,8 @@ test_collection_install_frozen(RBS::CliTest) running tests without Bundler test_collection_install_gemspec(RBS::CliTest) running tests without Bundler test_collection_update(RBS::CliTest) running tests without Bundler +test_loading_from_rbs_collection__gem_version_mismatch(RBS::EnvironmentLoaderTest) running test without rbs-amber testing gem + test_defs(RBS::RbPrototypeTest) Numeric Nodes are added test_defs_return_type(RBS::RbPrototypeTest) Numeric Nodes are added test_defs_return_type_with_block(RBS::RbPrototypeTest) Numeric Nodes are added @@ -46,6 +48,7 @@ test_parameter(RBS::RbiPrototypeTest) Symbol Node is added test_parameter_type_member_variance(RBS::RbiPrototypeTest) Symbol Node is added test_tuple(RBS::RbiPrototypeTest) Symbol Node is added test_untyped_block(RBS::RbiPrototypeTest) Symbol Node is added +test_argument_forwarding(RBS::RbPrototypeTest) `...` args handling is changed test_TOPDIR(RbConfigSingletonTest) `TOPDIR` is `nil` during CI while RBS type is declared as `String` From 30b4070ffac3a66904a6fd74f4cb4860dd20ac37 Mon Sep 17 00:00:00 2001 From: git Date: Thu, 25 Jan 2024 23:48:01 +0000 Subject: [PATCH 552/640] Update bundled gems list at b822f9f6fc5a00ec08dbc698b98458 [ci skip] --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index accab09e1c6c6f..9c9e7340b1d40b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -39,7 +39,7 @@ The following bundled gems are updated. * net-ftp 0.3.4 * net-imap 0.4.9.1 * net-smtp 0.4.0.1 -* rbs 3.4.2 +* rbs 3.4.3 * typeprof 0.21.9 * debug 1.9.1 From 7567e4e1e1e8029b19cda81b612f2d1a0c27cb9f Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Thu, 25 Jan 2024 16:22:27 -0800 Subject: [PATCH 553/640] YJIT: Fix exits on splatkw instruction (#9711) --- bootstraptest/test_yjit.rb | 12 ++++++++++++ yjit/bindgen/src/main.rs | 1 + yjit/src/codegen.rs | 28 ++++++++++++++++++++++++++++ yjit/src/cruby_bindings.inc.rs | 1 + 4 files changed, 42 insertions(+) diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index a981ba150b5eed..a13a8d62950532 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -2521,6 +2521,18 @@ def splatarray splatarray } +# splatkw +assert_equal '[1, 2]', %q{ + def foo(a:) = [a, yield] + + def entry(&block) + a = { a: 1 } + foo(**a, &block) + end + + entry { 2 } +} + assert_equal '[1, 1, 2, 1, 2, 3]', %q{ def expandarray arr = [1, 2, 3] diff --git a/yjit/bindgen/src/main.rs b/yjit/bindgen/src/main.rs index df9bb4d727fb1d..2c264287bcbe09 100644 --- a/yjit/bindgen/src/main.rs +++ b/yjit/bindgen/src/main.rs @@ -119,6 +119,7 @@ fn main() { .allowlist_function("rb_hash_new_with_size") .allowlist_function("rb_hash_resurrect") .allowlist_function("rb_hash_stlike_foreach") + .allowlist_function("rb_to_hash_type") // From include/ruby/st.h .allowlist_type("st_retval") diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 2bec0cf6d4dc92..a8c77b8d01b46d 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -1435,6 +1435,33 @@ fn gen_splatarray( Some(KeepCompiling) } +// call to_hash on hash to keyword splat before converting block +// e.g. foo(**object, &block) +fn gen_splatkw( + jit: &mut JITState, + asm: &mut Assembler, + _ocb: &mut OutlinedCb, +) -> Option { + // Save the PC and SP because the callee may allocate + jit_prepare_routine_call(jit, asm); + + // Get the operands from the stack + let block_opnd = asm.stack_opnd(0); + let block_type = asm.ctx.get_opnd_type(block_opnd.into()); + let hash_opnd = asm.stack_opnd(1); + + let hash = asm.ccall(rb_to_hash_type as *const u8, vec![hash_opnd]); + asm.stack_pop(2); // Keep it on stack during ccall for GC + + let stack_ret = asm.stack_push(Type::Hash); + asm.mov(stack_ret, hash); + asm.stack_push(block_type); + // Leave block_opnd spilled by ccall as is + asm.ctx.dealloc_temp_reg(asm.ctx.get_stack_size() - 1); + + Some(KeepCompiling) +} + // concat two arrays fn gen_concatarray( jit: &mut JITState, @@ -8951,6 +8978,7 @@ fn get_gen_fn(opcode: VALUE) -> Option { YARVINSN_opt_str_uminus => Some(gen_opt_str_uminus), YARVINSN_opt_newarray_send => Some(gen_opt_newarray_send), YARVINSN_splatarray => Some(gen_splatarray), + YARVINSN_splatkw => Some(gen_splatkw), YARVINSN_concatarray => Some(gen_concatarray), YARVINSN_concattoarray => Some(gen_concattoarray), YARVINSN_pushtoarray => Some(gen_pushtoarray), diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs index 2f965059d82187..db71c1b0db0545 100644 --- a/yjit/src/cruby_bindings.inc.rs +++ b/yjit/src/cruby_bindings.inc.rs @@ -1015,6 +1015,7 @@ extern "C" { pub fn rb_obj_as_string_result(str_: VALUE, obj: VALUE) -> VALUE; pub fn rb_str_concat_literals(num: usize, strary: *const VALUE) -> VALUE; pub fn rb_ec_str_resurrect(ec: *mut rb_execution_context_struct, str_: VALUE) -> VALUE; + pub fn rb_to_hash_type(obj: VALUE) -> VALUE; pub fn rb_hash_stlike_foreach( hash: VALUE, func: st_foreach_callback_func, From f9bf7d531bcea3fde3bb055d5d517f93945515dd Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 26 Jan 2024 12:38:01 +0900 Subject: [PATCH 554/640] Added vcpkg manifest for windows build environment. "builtin-baseline": "53bef8994c541b6561884a8395ea35715ece75db" is 2024.01.12 released version of vcpkg. https://github.com/microsoft/vcpkg/releases/tag/2024.01.12 --- .gitignore | 1 + doc/windows.md | 7 ++++--- vcpkg.json | 11 +++++++++++ 3 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 vcpkg.json diff --git a/.gitignore b/.gitignore index f402bf21555446..89b817b4f666ff 100644 --- a/.gitignore +++ b/.gitignore @@ -138,6 +138,7 @@ lcov*.info /test.rb /test-coverage.dat /tmp +/vcpkg_installed /transdb.h /uncommon.mk /verconf.h diff --git a/doc/windows.md b/doc/windows.md index a8bc4f6a42bdb0..2020eec9cfb86e 100644 --- a/doc/windows.md +++ b/doc/windows.md @@ -88,10 +88,11 @@ make scoop install git ruby sed patch ``` -5. You need to install required libraries using [vcpkg](https://vcpkg.io/) like: +5. You need to install required libraries using [vcpkg](https://vcpkg.io/) on + directory of ruby repository like: ``` - vcpkg --triplet x64-windows install openssl libffi libyaml zlib + vcpkg --triplet x64-windows install ``` 6. Enable Command Extension of your command line. It's the default behavior @@ -117,7 +118,7 @@ make executable without console window if also you want. 3. You need specify vcpkg directory to use `--with-opt-dir` - option like `configure --with-opt-dir=C:\vcpkg\installed\x64-windows` + option like `win32\configure.bat --with-opt-dir=vcpkg_installed\x64-windows` 4. Run `nmake up` if you are building from GIT source. diff --git a/vcpkg.json b/vcpkg.json new file mode 100644 index 00000000000000..1296010e1fdfc1 --- /dev/null +++ b/vcpkg.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", + "dependencies": [ + "gmp", + "libffi", + "libyaml", + "openssl", + "zlib" + ], + "builtin-baseline": "53bef8994c541b6561884a8395ea35715ece75db" +} From 395a240b7c1daa058f590893ca8d8f6d28866abf Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 26 Jan 2024 13:40:05 +0900 Subject: [PATCH 555/640] Try to use irb instead of rubygems for completion test I'm not sure why OpenBSD suggest `rubygems_plugin` file for this. https://rubyci.s3.amazonaws.com/openbsd-current/ruby-master/log/20240126T013005Z.fail.html.gz It seems environmental issue, not irb. --- test/irb/test_completion.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/irb/test_completion.rb b/test/irb/test_completion.rb index 4500fedb0b6c4b..8194463931ef70 100644 --- a/test/irb/test_completion.rb +++ b/test/irb/test_completion.rb @@ -125,8 +125,8 @@ def object.to_s; raise; end def test_complete_require_library_name_first # Test that library name is completed first with subdirectories - candidates = IRB::RegexpCompletor.new.completion_candidates("require ", "'rubygems", "", bind: binding) - assert_equal "'rubygems", candidates.first + candidates = IRB::RegexpCompletor.new.completion_candidates("require ", "'irb", "", bind: binding) + assert_equal "'irb", candidates.first end def test_complete_require_relative From 771a2f039b9a059a73e8f111d1d46590fa697f63 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Thu, 25 Jan 2024 12:44:13 -0800 Subject: [PATCH 556/640] Fix incorrect use of VM_CALL_KW_SPLAT_MUT in zsuper with keyword splat For zsuper calls with a keyword splat but no actual keywords, the keyword splat is passed directly, so it cannot be mutable, because if the callee accepts a keyword splat, changes to the keyword splat by the callee would be reflected in the caller. While here, simplify the logic when the method supports literal keywords. I don't think it is possible for a method with has_kw param flags to not have keywords, so add an assertion for that, and set VM_CALL_KW_SPLAT_MUT in a single place. --- compile.c | 11 ++++------- test/ruby/test_super.rb | 12 ++++++++++++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/compile.c b/compile.c index dfc1980bcc629e..4ae1174caae7ff 100644 --- a/compile.c +++ b/compile.c @@ -9534,14 +9534,11 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i 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; - } + assert(local_kwd->num > 0); + ADD_SEND (args, node, rb_intern("dup"), 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]; @@ -9550,13 +9547,13 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i ADD_GETLOCAL(args, node, idx, lvar_level); } ADD_SEND(args, node, id_core_hash_merge_ptr, INT2FIX(i * 2 + 1)); - flag |= VM_CALL_KW_SPLAT; + flag |= VM_CALL_KW_SPLAT| VM_CALL_KW_SPLAT_MUT; } else if (local_body->param.flags.has_kwrest) { int idx = local_body->local_table_size - local_kwd->rest_start; ADD_GETLOCAL(args, node, idx, lvar_level); argc++; - flag |= VM_CALL_KW_SPLAT | VM_CALL_KW_SPLAT_MUT; + flag |= VM_CALL_KW_SPLAT; } } diff --git a/test/ruby/test_super.rb b/test/ruby/test_super.rb index 6a575b88c5174d..ce78e66c52196a 100644 --- a/test/ruby/test_super.rb +++ b/test/ruby/test_super.rb @@ -558,6 +558,18 @@ def danger!; end end end + def test_zsuper_kw_splat_not_mutable + extend(Module.new{def a(**k) k[:a] = 1 end}) + extend(Module.new do + def a(**k) + before = k.dup + super + [before, k] + end + end) + assert_equal(*a) + end + def test_from_eval bug10263 = '[ruby-core:65122] [Bug #10263a]' a = Class.new do From 1949a04f81311660e2d0ec002c48115c63742d0b Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 26 Jan 2024 17:46:39 +0900 Subject: [PATCH 557/640] `vcpkg x-update-baseline` for updating baseline commit hash uses 2-spaces indent --- vcpkg.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/vcpkg.json b/vcpkg.json index 1296010e1fdfc1..6d2ee3a6bc0457 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,11 +1,11 @@ { - "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", - "dependencies": [ - "gmp", - "libffi", - "libyaml", - "openssl", - "zlib" - ], - "builtin-baseline": "53bef8994c541b6561884a8395ea35715ece75db" + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", + "dependencies": [ + "gmp", + "libffi", + "libyaml", + "openssl", + "zlib" + ], + "builtin-baseline": "53bef8994c541b6561884a8395ea35715ece75db" } From 8e5bc8f7c24f4ff161bdac3d6b876a4a158642fb Mon Sep 17 00:00:00 2001 From: Max Prokopiev Date: Fri, 26 Jan 2024 18:27:08 +0100 Subject: [PATCH 558/640] [ruby/prism] Change binding power for modifiers in case-in nodes https://github.com/ruby/prism/commit/c31eeba54c --- prism/prism.c | 4 +- test/prism/fixtures/case.txt | 5 ++ test/prism/snapshots/case.txt | 113 +++++++++++++++++++++++++++------- 3 files changed, 98 insertions(+), 24 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 4d2602cdb93cc9..30b33d28a684e8 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -14856,11 +14856,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // for guard clauses in the form of `if` or `unless` statements. if (accept1(parser, PM_TOKEN_KEYWORD_IF_MODIFIER)) { pm_token_t keyword = parser->previous; - pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, true, PM_ERR_CONDITIONAL_IF_PREDICATE); + pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_CONDITIONAL_IF_PREDICATE); pattern = (pm_node_t *) pm_if_node_modifier_create(parser, pattern, &keyword, predicate); } else if (accept1(parser, PM_TOKEN_KEYWORD_UNLESS_MODIFIER)) { pm_token_t keyword = parser->previous; - pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, true, PM_ERR_CONDITIONAL_UNLESS_PREDICATE); + pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_CONDITIONAL_UNLESS_PREDICATE); pattern = (pm_node_t *) pm_unless_node_modifier_create(parser, pattern, &keyword, predicate); } diff --git a/test/prism/fixtures/case.txt b/test/prism/fixtures/case.txt index dea6424db309d8..733e1e54d2423e 100644 --- a/test/prism/fixtures/case.txt +++ b/test/prism/fixtures/case.txt @@ -43,6 +43,11 @@ end case 1 in 2; in 3; end +case a +in b if c and d + e +end + 1.then do case 1 in ^_1 diff --git a/test/prism/snapshots/case.txt b/test/prism/snapshots/case.txt index 44f438092dc260..bcd5ef67900ff4 100644 --- a/test/prism/snapshots/case.txt +++ b/test/prism/snapshots/case.txt @@ -1,8 +1,8 @@ -@ ProgramNode (location: (1,0)-(50,3)) -├── locals: [] +@ ProgramNode (location: (1,0)-(55,3)) +├── locals: [:b] └── statements: - @ StatementsNode (location: (1,0)-(50,3)) - └── body: (length: 14) + @ StatementsNode (location: (1,0)-(55,3)) + └── body: (length: 15) ├── @ CaseNode (location: (1,0)-(3,3)) │ ├── predicate: │ │ @ SymbolNode (location: (1,5)-(1,8)) @@ -356,45 +356,114 @@ │ ├── consequent: ∅ │ ├── case_keyword_loc: (44,0)-(44,4) = "case" │ └── end_keyword_loc: (44,19)-(44,22) = "end" - └── @ CallNode (location: (46,0)-(50,3)) + ├── @ CaseMatchNode (location: (46,0)-(49,3)) + │ ├── predicate: + │ │ @ CallNode (location: (46,5)-(46,6)) + │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :a + │ │ ├── message_loc: (46,5)-(46,6) = "a" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ └── block: ∅ + │ ├── conditions: (length: 1) + │ │ └── @ InNode (location: (47,0)-(48,3)) + │ │ ├── pattern: + │ │ │ @ IfNode (location: (47,3)-(47,15)) + │ │ │ ├── if_keyword_loc: (47,5)-(47,7) = "if" + │ │ │ ├── predicate: + │ │ │ │ @ AndNode (location: (47,8)-(47,15)) + │ │ │ │ ├── left: + │ │ │ │ │ @ CallNode (location: (47,8)-(47,9)) + │ │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ │ ├── receiver: ∅ + │ │ │ │ │ ├── call_operator_loc: ∅ + │ │ │ │ │ ├── name: :c + │ │ │ │ │ ├── message_loc: (47,8)-(47,9) = "c" + │ │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ │ ├── arguments: ∅ + │ │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ │ └── block: ∅ + │ │ │ │ ├── right: + │ │ │ │ │ @ CallNode (location: (47,14)-(47,15)) + │ │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ │ ├── receiver: ∅ + │ │ │ │ │ ├── call_operator_loc: ∅ + │ │ │ │ │ ├── name: :d + │ │ │ │ │ ├── message_loc: (47,14)-(47,15) = "d" + │ │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ │ ├── arguments: ∅ + │ │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ │ └── block: ∅ + │ │ │ │ └── operator_loc: (47,10)-(47,13) = "and" + │ │ │ ├── then_keyword_loc: ∅ + │ │ │ ├── statements: + │ │ │ │ @ StatementsNode (location: (47,3)-(47,4)) + │ │ │ │ └── body: (length: 1) + │ │ │ │ └── @ LocalVariableTargetNode (location: (47,3)-(47,4)) + │ │ │ │ ├── name: :b + │ │ │ │ └── depth: 0 + │ │ │ ├── consequent: ∅ + │ │ │ └── end_keyword_loc: ∅ + │ │ ├── statements: + │ │ │ @ StatementsNode (location: (48,2)-(48,3)) + │ │ │ └── body: (length: 1) + │ │ │ └── @ CallNode (location: (48,2)-(48,3)) + │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :e + │ │ │ ├── message_loc: (48,2)-(48,3) = "e" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ └── block: ∅ + │ │ ├── in_loc: (47,0)-(47,2) = "in" + │ │ └── then_loc: ∅ + │ ├── consequent: ∅ + │ ├── case_keyword_loc: (46,0)-(46,4) = "case" + │ └── end_keyword_loc: (49,0)-(49,3) = "end" + └── @ CallNode (location: (51,0)-(55,3)) ├── flags: ∅ ├── receiver: - │ @ IntegerNode (location: (46,0)-(46,1)) + │ @ IntegerNode (location: (51,0)-(51,1)) │ └── flags: decimal - ├── call_operator_loc: (46,1)-(46,2) = "." + ├── call_operator_loc: (51,1)-(51,2) = "." ├── name: :then - ├── message_loc: (46,2)-(46,6) = "then" + ├── message_loc: (51,2)-(51,6) = "then" ├── opening_loc: ∅ ├── arguments: ∅ ├── closing_loc: ∅ └── block: - @ BlockNode (location: (46,7)-(50,3)) + @ BlockNode (location: (51,7)-(55,3)) ├── locals: [:_1] ├── locals_body_index: 1 ├── parameters: - │ @ NumberedParametersNode (location: (46,7)-(50,3)) + │ @ NumberedParametersNode (location: (51,7)-(55,3)) │ └── maximum: 1 ├── body: - │ @ StatementsNode (location: (47,2)-(49,5)) + │ @ StatementsNode (location: (52,2)-(54,5)) │ └── body: (length: 1) - │ └── @ CaseMatchNode (location: (47,2)-(49,5)) + │ └── @ CaseMatchNode (location: (52,2)-(54,5)) │ ├── predicate: - │ │ @ IntegerNode (location: (47,7)-(47,8)) + │ │ @ IntegerNode (location: (52,7)-(52,8)) │ │ └── flags: decimal │ ├── conditions: (length: 1) - │ │ └── @ InNode (location: (48,2)-(48,8)) + │ │ └── @ InNode (location: (53,2)-(53,8)) │ │ ├── pattern: - │ │ │ @ PinnedVariableNode (location: (48,5)-(48,8)) + │ │ │ @ PinnedVariableNode (location: (53,5)-(53,8)) │ │ │ ├── variable: - │ │ │ │ @ LocalVariableReadNode (location: (48,6)-(48,8)) + │ │ │ │ @ LocalVariableReadNode (location: (53,6)-(53,8)) │ │ │ │ ├── name: :_1 │ │ │ │ └── depth: 0 - │ │ │ └── operator_loc: (48,5)-(48,6) = "^" + │ │ │ └── operator_loc: (53,5)-(53,6) = "^" │ │ ├── statements: ∅ - │ │ ├── in_loc: (48,2)-(48,4) = "in" + │ │ ├── in_loc: (53,2)-(53,4) = "in" │ │ └── then_loc: ∅ │ ├── consequent: ∅ - │ ├── case_keyword_loc: (47,2)-(47,6) = "case" - │ └── end_keyword_loc: (49,2)-(49,5) = "end" - ├── opening_loc: (46,7)-(46,9) = "do" - └── closing_loc: (50,0)-(50,3) = "end" + │ ├── case_keyword_loc: (52,2)-(52,6) = "case" + │ └── end_keyword_loc: (54,2)-(54,5) = "end" + ├── opening_loc: (51,7)-(51,9) = "do" + └── closing_loc: (55,0)-(55,3) = "end" From b0e10345d3b1f4c1f1b82d2598a31c066a0b2c28 Mon Sep 17 00:00:00 2001 From: Haldun Bayhantopcu Date: Wed, 24 Jan 2024 00:31:57 +0100 Subject: [PATCH 559/640] [ruby/prism] Fix parsing calls with labels https://github.com/ruby/prism/commit/3db7849a31 --- prism/prism.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/prism/prism.c b/prism/prism.c index 30b33d28a684e8..f0091d7e23d447 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -423,6 +423,11 @@ lex_state_beg_p(pm_parser_t *parser) { return lex_state_p(parser, PM_LEX_STATE_BEG_ANY) || ((parser->lex_state & (PM_LEX_STATE_ARG | PM_LEX_STATE_LABELED)) == (PM_LEX_STATE_ARG | PM_LEX_STATE_LABELED)); } +static inline bool +lex_state_arg_labeled_p(pm_parser_t *parser) { + return (parser->lex_state & (PM_LEX_STATE_ARG | PM_LEX_STATE_LABELED)) == (PM_LEX_STATE_ARG | PM_LEX_STATE_LABELED); +} + static inline bool lex_state_arg_p(pm_parser_t *parser) { return lex_state_p(parser, PM_LEX_STATE_ARG_ANY); @@ -13924,7 +13929,7 @@ parse_strings(pm_parser_t *parser, pm_node_t *current) { assert(parser->current.type == PM_TOKEN_STRING_BEGIN); bool concating = false; - bool state_is_arg_labeled = lex_state_p(parser, PM_LEX_STATE_ARG | PM_LEX_STATE_LABELED); + bool state_is_arg_labeled = lex_state_arg_labeled_p(parser); while (match1(parser, PM_TOKEN_STRING_BEGIN)) { pm_node_t *node = NULL; From 9a7637da2d0fd6a43e980bb210957011c6f146be Mon Sep 17 00:00:00 2001 From: Haldun Bayhantopcu Date: Wed, 24 Jan 2024 00:35:32 +0100 Subject: [PATCH 560/640] [ruby/prism] Add tests https://github.com/ruby/prism/commit/b9ebf987bd --- test/prism/fixtures/method_calls.txt | 2 + test/prism/snapshots/method_calls.txt | 86 +++++++++++++++++++++------ 2 files changed, 70 insertions(+), 18 deletions(-) diff --git a/test/prism/fixtures/method_calls.txt b/test/prism/fixtures/method_calls.txt index d30780771f7376..987fb3f90ff5a2 100644 --- a/test/prism/fixtures/method_calls.txt +++ b/test/prism/fixtures/method_calls.txt @@ -152,3 +152,5 @@ foo 1, Bar { 1 } foo = 1 foo {} + +@a.b "c#{name}": 42 diff --git a/test/prism/snapshots/method_calls.txt b/test/prism/snapshots/method_calls.txt index ff6e0dd7df1381..ec694ef5331014 100644 --- a/test/prism/snapshots/method_calls.txt +++ b/test/prism/snapshots/method_calls.txt @@ -1,8 +1,8 @@ -@ ProgramNode (location: (1,0)-(154,6)) +@ ProgramNode (location: (1,0)-(156,19)) ├── locals: [:foo] └── statements: - @ StatementsNode (location: (1,0)-(154,6)) - └── body: (length: 66) + @ StatementsNode (location: (1,0)-(156,19)) + └── body: (length: 67) ├── @ CallNode (location: (1,0)-(1,14)) │ ├── flags: ∅ │ ├── receiver: @@ -2393,20 +2393,70 @@ │ │ @ IntegerNode (location: (153,6)-(153,7)) │ │ └── flags: decimal │ └── operator_loc: (153,4)-(153,5) = "=" - └── @ CallNode (location: (154,0)-(154,6)) - ├── flags: ignore_visibility - ├── receiver: ∅ - ├── call_operator_loc: ∅ - ├── name: :foo - ├── message_loc: (154,0)-(154,3) = "foo" + ├── @ CallNode (location: (154,0)-(154,6)) + │ ├── flags: ignore_visibility + │ ├── receiver: ∅ + │ ├── call_operator_loc: ∅ + │ ├── name: :foo + │ ├── message_loc: (154,0)-(154,3) = "foo" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ └── block: + │ @ BlockNode (location: (154,4)-(154,6)) + │ ├── locals: [] + │ ├── locals_body_index: 0 + │ ├── parameters: ∅ + │ ├── body: ∅ + │ ├── opening_loc: (154,4)-(154,5) = "{" + │ └── closing_loc: (154,5)-(154,6) = "}" + └── @ CallNode (location: (156,0)-(156,19)) + ├── flags: ∅ + ├── receiver: + │ @ InstanceVariableReadNode (location: (156,0)-(156,2)) + │ └── name: :@a + ├── call_operator_loc: (156,2)-(156,3) = "." + ├── name: :b + ├── message_loc: (156,3)-(156,4) = "b" ├── opening_loc: ∅ - ├── arguments: ∅ + ├── arguments: + │ @ ArgumentsNode (location: (156,5)-(156,19)) + │ ├── flags: ∅ + │ └── arguments: (length: 1) + │ └── @ KeywordHashNode (location: (156,5)-(156,19)) + │ ├── flags: ∅ + │ └── elements: (length: 1) + │ └── @ AssocNode (location: (156,5)-(156,19)) + │ ├── key: + │ │ @ InterpolatedSymbolNode (location: (156,5)-(156,16)) + │ │ ├── opening_loc: (156,5)-(156,6) = "\"" + │ │ ├── parts: (length: 2) + │ │ │ ├── @ StringNode (location: (156,6)-(156,7)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── content_loc: (156,6)-(156,7) = "c" + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── unescaped: "c" + │ │ │ └── @ EmbeddedStatementsNode (location: (156,7)-(156,14)) + │ │ │ ├── opening_loc: (156,7)-(156,9) = "\#{" + │ │ │ ├── statements: + │ │ │ │ @ StatementsNode (location: (156,9)-(156,13)) + │ │ │ │ └── body: (length: 1) + │ │ │ │ └── @ CallNode (location: (156,9)-(156,13)) + │ │ │ │ ├── flags: variable_call, ignore_visibility + │ │ │ │ ├── receiver: ∅ + │ │ │ │ ├── call_operator_loc: ∅ + │ │ │ │ ├── name: :name + │ │ │ │ ├── message_loc: (156,9)-(156,13) = "name" + │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ ├── arguments: ∅ + │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ └── block: ∅ + │ │ │ └── closing_loc: (156,13)-(156,14) = "}" + │ │ └── closing_loc: (156,14)-(156,16) = "\":" + │ ├── value: + │ │ @ IntegerNode (location: (156,17)-(156,19)) + │ │ └── flags: decimal + │ └── operator_loc: ∅ ├── closing_loc: ∅ - └── block: - @ BlockNode (location: (154,4)-(154,6)) - ├── locals: [] - ├── locals_body_index: 0 - ├── parameters: ∅ - ├── body: ∅ - ├── opening_loc: (154,4)-(154,5) = "{" - └── closing_loc: (154,5)-(154,6) = "}" + └── block: ∅ From 7d356b8f0e5be81075a30e779c872eeed9049150 Mon Sep 17 00:00:00 2001 From: Haldun Bayhantopcu Date: Wed, 24 Jan 2024 00:57:41 +0100 Subject: [PATCH 561/640] [ruby/prism] Fix multiple assigns with newlines https://github.com/ruby/prism/commit/b4ba41bdcd --- prism/prism.c | 2 + test/prism/fixtures/patterns.txt | 5 ++ test/prism/snapshots/patterns.txt | 100 ++++++++++++++++++------------ 3 files changed, 69 insertions(+), 38 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index f0091d7e23d447..6d7beaf88f5c8d 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -11144,6 +11144,8 @@ static pm_node_t * parse_targets_validate(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t binding_power) { pm_node_t *result = parse_targets(parser, first_target, binding_power); + while (accept1(parser, PM_TOKEN_NEWLINE)); + // Ensure that we have either an = or a ) after the targets. if (!match2(parser, PM_TOKEN_EQUAL, PM_TOKEN_PARENTHESIS_RIGHT)) { pm_parser_err_node(parser, result, PM_ERR_WRITE_TARGET_UNEXPECTED); diff --git a/test/prism/fixtures/patterns.txt b/test/prism/fixtures/patterns.txt index 41e8aad29e9590..54a5a6e00af00c 100644 --- a/test/prism/fixtures/patterns.txt +++ b/test/prism/fixtures/patterns.txt @@ -202,3 +202,8 @@ end foo => Object[{x:}] 1.then { 1 in ^_1 } + +( + a, + b +) = c diff --git a/test/prism/snapshots/patterns.txt b/test/prism/snapshots/patterns.txt index eed0a8e2b7b58c..843a1fc6a71412 100644 --- a/test/prism/snapshots/patterns.txt +++ b/test/prism/snapshots/patterns.txt @@ -1,8 +1,8 @@ -@ ProgramNode (location: (1,0)-(204,19)) +@ ProgramNode (location: (1,0)-(209,5)) ├── locals: [:bar, :baz, :qux, :b, :a, :foo, :x] └── statements: - @ StatementsNode (location: (1,0)-(204,19)) - └── body: (length: 177) + @ StatementsNode (location: (1,0)-(209,5)) + └── body: (length: 178) ├── @ MatchRequiredNode (location: (1,0)-(1,10)) │ ├── value: │ │ @ CallNode (location: (1,0)-(1,3)) @@ -4772,38 +4772,62 @@ │ │ ├── opening_loc: (202,13)-(202,14) = "[" │ │ └── closing_loc: (202,18)-(202,19) = "]" │ └── operator_loc: (202,4)-(202,6) = "=>" - └── @ CallNode (location: (204,0)-(204,19)) - ├── flags: ∅ - ├── receiver: - │ @ IntegerNode (location: (204,0)-(204,1)) - │ └── flags: decimal - ├── call_operator_loc: (204,1)-(204,2) = "." - ├── name: :then - ├── message_loc: (204,2)-(204,6) = "then" - ├── opening_loc: ∅ - ├── arguments: ∅ - ├── closing_loc: ∅ - └── block: - @ BlockNode (location: (204,7)-(204,19)) - ├── locals: [:_1] - ├── locals_body_index: 1 - ├── parameters: - │ @ NumberedParametersNode (location: (204,7)-(204,19)) - │ └── maximum: 1 - ├── body: - │ @ StatementsNode (location: (204,9)-(204,17)) - │ └── body: (length: 1) - │ └── @ MatchPredicateNode (location: (204,9)-(204,17)) - │ ├── value: - │ │ @ IntegerNode (location: (204,9)-(204,10)) - │ │ └── flags: decimal - │ ├── pattern: - │ │ @ PinnedVariableNode (location: (204,14)-(204,17)) - │ │ ├── variable: - │ │ │ @ LocalVariableReadNode (location: (204,15)-(204,17)) - │ │ │ ├── name: :_1 - │ │ │ └── depth: 0 - │ │ └── operator_loc: (204,14)-(204,15) = "^" - │ └── operator_loc: (204,11)-(204,13) = "in" - ├── opening_loc: (204,7)-(204,8) = "{" - └── closing_loc: (204,18)-(204,19) = "}" + ├── @ CallNode (location: (204,0)-(204,19)) + │ ├── flags: ∅ + │ ├── receiver: + │ │ @ IntegerNode (location: (204,0)-(204,1)) + │ │ └── flags: decimal + │ ├── call_operator_loc: (204,1)-(204,2) = "." + │ ├── name: :then + │ ├── message_loc: (204,2)-(204,6) = "then" + │ ├── opening_loc: ∅ + │ ├── arguments: ∅ + │ ├── closing_loc: ∅ + │ └── block: + │ @ BlockNode (location: (204,7)-(204,19)) + │ ├── locals: [:_1] + │ ├── locals_body_index: 1 + │ ├── parameters: + │ │ @ NumberedParametersNode (location: (204,7)-(204,19)) + │ │ └── maximum: 1 + │ ├── body: + │ │ @ StatementsNode (location: (204,9)-(204,17)) + │ │ └── body: (length: 1) + │ │ └── @ MatchPredicateNode (location: (204,9)-(204,17)) + │ │ ├── value: + │ │ │ @ IntegerNode (location: (204,9)-(204,10)) + │ │ │ └── flags: decimal + │ │ ├── pattern: + │ │ │ @ PinnedVariableNode (location: (204,14)-(204,17)) + │ │ │ ├── variable: + │ │ │ │ @ LocalVariableReadNode (location: (204,15)-(204,17)) + │ │ │ │ ├── name: :_1 + │ │ │ │ └── depth: 0 + │ │ │ └── operator_loc: (204,14)-(204,15) = "^" + │ │ └── operator_loc: (204,11)-(204,13) = "in" + │ ├── opening_loc: (204,7)-(204,8) = "{" + │ └── closing_loc: (204,18)-(204,19) = "}" + └── @ MultiWriteNode (location: (206,0)-(209,5)) + ├── lefts: (length: 2) + │ ├── @ LocalVariableTargetNode (location: (207,2)-(207,3)) + │ │ ├── name: :a + │ │ └── depth: 0 + │ └── @ LocalVariableTargetNode (location: (208,2)-(208,3)) + │ ├── name: :b + │ └── depth: 0 + ├── rest: ∅ + ├── rights: (length: 0) + ├── lparen_loc: (206,0)-(206,1) = "(" + ├── rparen_loc: (209,0)-(209,1) = ")" + ├── operator_loc: (209,2)-(209,3) = "=" + └── value: + @ CallNode (location: (209,4)-(209,5)) + ├── flags: variable_call, ignore_visibility + ├── receiver: ∅ + ├── call_operator_loc: ∅ + ├── name: :c + ├── message_loc: (209,4)-(209,5) = "c" + ├── opening_loc: ∅ + ├── arguments: ∅ + ├── closing_loc: ∅ + └── block: ∅ From 99d91838e0daab390d17cbbf90479c9569602488 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 26 Jan 2024 13:33:45 -0500 Subject: [PATCH 562/640] [ruby/prism] Update src/prism.c https://github.com/ruby/prism/commit/91b5550726 --- prism/prism.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 6d7beaf88f5c8d..107b284e1dd87d 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -11143,8 +11143,7 @@ parse_targets(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t b static pm_node_t * parse_targets_validate(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t binding_power) { pm_node_t *result = parse_targets(parser, first_target, binding_power); - - while (accept1(parser, PM_TOKEN_NEWLINE)); + accept1(parser, PM_TOKEN_NEWLINE); // Ensure that we have either an = or a ) after the targets. if (!match2(parser, PM_TOKEN_EQUAL, PM_TOKEN_PARENTHESIS_RIGHT)) { From 3d996e827f2ff74a1bb7e978d754cea7d957b9eb Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Fri, 26 Jan 2024 09:44:09 -0500 Subject: [PATCH 563/640] [PRISM] Keyword arguments incorrectly passed as mutable Fixes ruby/prism#2279. --- prism_compile.c | 1 - test/ruby/test_compile_prism.rb | 10 ++++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/prism_compile.c b/prism_compile.c index c0975b4acfe40f..bda506e3ffb73d 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -1085,7 +1085,6 @@ pm_setup_args(pm_arguments_node_t *arguments_node, int *flags, struct rb_callinf if (has_keyword_splat || has_splat) { *flags |= VM_CALL_KW_SPLAT; - *flags |= VM_CALL_KW_SPLAT_MUT; has_keyword_splat = true; diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 4ccea6d319ad73..05e95e8b06141b 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -2134,6 +2134,16 @@ def test_FowardingParameterNode def test_KeywordRestParameterNode assert_prism_eval("def prism_test_keyword_rest_parameter_node(a, **b); end") assert_prism_eval("Object.tap { |**| }") + + # Test that KeywordRestParameterNode creates a copy + assert_prism_eval(<<~RUBY) + hash = {} + o = Object.new + def o.foo(**a) = a[:foo] = 1 + + o.foo(**hash) + hash + RUBY end def test_NoKeywordsParameterNode From 2a509787cb8869301b614139218432aef9b68f9b Mon Sep 17 00:00:00 2001 From: Kevin Menard Date: Wed, 24 Jan 2024 16:39:06 -0500 Subject: [PATCH 564/640] [ruby/prism] Track whether a Symbol should have its encoding changed from the source encoding. Ruby sets a Symbol literal's encoding to US-ASCII if the symbols consists only of US ASCII code points. Character escapes can also lead a Symbol to have a different encoding than its source's encoding. https://github.com/ruby/prism/commit/f315660b31 --- prism/prism.c | 69 +++++++++++- test/prism/encoding_test.rb | 98 +++++++++++++++++ test/prism/errors_test.rb | 26 ++--- test/prism/snapshots/alias.txt | 38 +++---- test/prism/snapshots/arrays.txt | 40 +++---- test/prism/snapshots/begin_ensure.txt | 2 +- test/prism/snapshots/case.txt | 16 +-- test/prism/snapshots/dos_endings.txt | 2 +- test/prism/snapshots/global_variables.txt | 46 ++++---- test/prism/snapshots/hashes.txt | 22 ++-- test/prism/snapshots/if.txt | 2 +- test/prism/snapshots/method_calls.txt | 102 +++++++++--------- test/prism/snapshots/methods.txt | 4 +- test/prism/snapshots/patterns.txt | 66 ++++++------ test/prism/snapshots/ranges.txt | 4 +- test/prism/snapshots/rescue.txt | 2 +- .../seattlerb/TestRubyParserShared.txt | 20 ++-- .../snapshots/seattlerb/alias_resword.txt | 4 +- .../prism/snapshots/seattlerb/assoc__bare.txt | 2 +- .../prism/snapshots/seattlerb/assoc_label.txt | 2 +- .../block_command_operation_colon.txt | 4 +- .../seattlerb/block_command_operation_dot.txt | 4 +- .../snapshots/seattlerb/block_kwarg_lvar.txt | 2 +- .../seattlerb/block_kwarg_lvar_multiple.txt | 4 +- .../snapshots/seattlerb/block_optarg.txt | 2 +- .../snapshots/seattlerb/block_reg_optarg.txt | 2 +- test/prism/snapshots/seattlerb/bug_215.txt | 2 +- test/prism/snapshots/seattlerb/bug_249.txt | 2 +- .../seattlerb/bug_case_when_regexp.txt | 2 +- .../snapshots/seattlerb/bug_hash_args.txt | 4 +- .../bug_hash_args_trailing_comma.txt | 4 +- .../seattlerb/call_arg_assoc_kwsplat.txt | 2 +- .../seattlerb/call_args_assoc_quoted.txt | 4 +- .../snapshots/seattlerb/call_array_arg.txt | 4 +- .../seattlerb/call_array_lit_inline_hash.txt | 4 +- .../snapshots/seattlerb/call_assoc_new.txt | 2 +- .../seattlerb/call_assoc_new_if_multiline.txt | 4 +- test/prism/snapshots/seattlerb/case_in.txt | 84 +++++++-------- test/prism/snapshots/seattlerb/case_in_31.txt | 6 +- test/prism/snapshots/seattlerb/case_in_37.txt | 6 +- test/prism/snapshots/seattlerb/case_in_42.txt | 4 +- .../snapshots/seattlerb/case_in_42_2.txt | 2 +- test/prism/snapshots/seattlerb/case_in_47.txt | 8 +- test/prism/snapshots/seattlerb/case_in_67.txt | 2 +- test/prism/snapshots/seattlerb/case_in_86.txt | 4 +- .../snapshots/seattlerb/case_in_86_2.txt | 4 +- .../seattlerb/case_in_array_pat_const.txt | 4 +- .../seattlerb/case_in_array_pat_const2.txt | 4 +- .../case_in_array_pat_paren_assign.txt | 4 +- .../snapshots/seattlerb/case_in_const.txt | 2 +- .../snapshots/seattlerb/case_in_else.txt | 4 +- .../snapshots/seattlerb/case_in_find.txt | 4 +- .../seattlerb/case_in_find_array.txt | 4 +- .../snapshots/seattlerb/case_in_hash_pat.txt | 8 +- .../seattlerb/case_in_hash_pat_assign.txt | 10 +- .../case_in_hash_pat_paren_assign.txt | 6 +- .../seattlerb/case_in_hash_pat_paren_true.txt | 6 +- .../seattlerb/case_in_hash_pat_rest.txt | 6 +- .../seattlerb/case_in_hash_pat_rest_solo.txt | 4 +- .../seattlerb/case_in_if_unless_post_mod.txt | 6 +- .../snapshots/seattlerb/case_in_multiple.txt | 6 +- test/prism/snapshots/seattlerb/case_in_or.txt | 4 +- .../seattlerb/defn_args_forward_args.txt | 2 +- .../snapshots/seattlerb/defn_kwarg_lvar.txt | 2 +- .../snapshots/seattlerb/defn_reg_opt_reg.txt | 2 +- .../prism/snapshots/seattlerb/difficult2_.txt | 2 +- .../prism/snapshots/seattlerb/difficult7_.txt | 4 +- .../snapshots/seattlerb/dstr_lex_state.txt | 2 +- .../snapshots/seattlerb/dsym_esc_to_sym.txt | 2 +- .../prism/snapshots/seattlerb/dsym_to_sym.txt | 8 +- test/prism/snapshots/seattlerb/if_symbol.txt | 2 +- .../interpolated_symbol_array_line_breaks.txt | 4 +- .../seattlerb/multiline_hash_declaration.txt | 6 +- ..._interpolated_symbol_array_line_breaks.txt | 4 +- .../seattlerb/op_asgn_index_command_call.txt | 2 +- .../seattlerb/parse_line_hash_lit.txt | 2 +- .../snapshots/seattlerb/parse_pattern_058.txt | 4 +- .../seattlerb/parse_pattern_058_2.txt | 4 +- .../snapshots/seattlerb/parse_pattern_069.txt | 4 +- .../snapshots/seattlerb/parse_pattern_076.txt | 4 +- test/prism/snapshots/seattlerb/qsymbols.txt | 6 +- .../snapshots/seattlerb/qsymbols_interp.txt | 4 +- .../seattlerb/quoted_symbol_hash_arg.txt | 2 +- .../seattlerb/quoted_symbol_keys.txt | 4 +- .../seattlerb/rescue_do_end_ensure_result.txt | 4 +- .../seattlerb/rescue_do_end_no_raise.txt | 8 +- .../seattlerb/rescue_do_end_raised.txt | 2 +- .../seattlerb/rescue_do_end_rescued.txt | 6 +- .../seattlerb/return_call_assocs.txt | 12 +-- .../snapshots/seattlerb/symbol_empty.txt | 2 +- test/prism/snapshots/seattlerb/symbols.txt | 6 +- .../snapshots/seattlerb/symbols_interp.txt | 6 +- .../seattlerb/unary_plus_on_literal.txt | 2 +- .../snapshots/seattlerb/yield_call_assocs.txt | 12 +-- test/prism/snapshots/spanning_heredoc.txt | 6 +- .../snapshots/spanning_heredoc_newlines.txt | 2 +- test/prism/snapshots/strings.txt | 2 +- test/prism/snapshots/super.txt | 6 +- test/prism/snapshots/symbols.txt | 94 ++++++++-------- test/prism/snapshots/undef.txt | 12 +-- test/prism/snapshots/unless.txt | 4 +- .../unparser/corpus/literal/alias.txt | 4 +- .../unparser/corpus/literal/case.txt | 6 +- .../unparser/corpus/literal/class.txt | 2 +- .../snapshots/unparser/corpus/literal/if.txt | 2 +- .../unparser/corpus/literal/kwbegin.txt | 2 +- .../unparser/corpus/literal/literal.txt | 32 +++--- .../unparser/corpus/literal/module.txt | 2 +- .../unparser/corpus/literal/pattern.txt | 8 +- .../unparser/corpus/literal/send.txt | 20 ++-- .../unparser/corpus/literal/undef.txt | 6 +- .../unparser/corpus/literal/while.txt | 4 +- test/prism/snapshots/until.txt | 4 +- test/prism/snapshots/while.txt | 4 +- test/prism/snapshots/whitequark/alias.txt | 4 +- test/prism/snapshots/whitequark/arg_label.txt | 6 +- .../snapshots/whitequark/args_args_assocs.txt | 4 +- .../whitequark/args_args_assocs_comma.txt | 2 +- .../snapshots/whitequark/args_assocs.txt | 12 +-- .../whitequark/args_assocs_comma.txt | 2 +- .../whitequark/args_assocs_legacy.txt | 12 +-- .../snapshots/whitequark/array_symbols.txt | 4 +- .../whitequark/array_symbols_interp.txt | 2 +- .../prism/snapshots/whitequark/bug_cmdarg.txt | 4 +- .../whitequark/bug_do_block_in_hash_brace.txt | 26 ++--- .../whitequark/class_super_label.txt | 2 +- ...warded_kwrestarg_with_additional_kwarg.txt | 2 +- .../snapshots/whitequark/hash_hashrocket.txt | 2 +- .../snapshots/whitequark/hash_kwsplat.txt | 2 +- .../prism/snapshots/whitequark/hash_label.txt | 2 +- .../snapshots/whitequark/hash_label_end.txt | 6 +- .../whitequark/hash_pair_value_omission.txt | 8 +- .../snapshots/whitequark/interp_digit_var.txt | 20 ++-- .../whitequark/keyword_argument_omission.txt | 4 +- .../lbrace_arg_after_command_args.txt | 2 +- .../whitequark/multiple_pattern_matches.txt | 16 +-- .../whitequark/newline_in_hash_argument.txt | 8 +- .../snapshots/whitequark/parser_bug_525.txt | 2 +- ...ser_slash_slash_n_escaping_in_literals.txt | 10 +- ...e_line_allowed_omission_of_parentheses.txt | 20 ++-- .../snapshots/whitequark/ruby_bug_10279.txt | 2 +- .../snapshots/whitequark/ruby_bug_11380.txt | 4 +- .../snapshots/whitequark/ruby_bug_11873_a.txt | 8 +- .../snapshots/whitequark/ruby_bug_12073.txt | 2 +- .../snapshots/whitequark/ruby_bug_12669.txt | 8 +- .../snapshots/whitequark/ruby_bug_9669.txt | 2 +- .../snapshots/whitequark/symbol_plain.txt | 4 +- test/prism/snapshots/whitequark/undef.txt | 2 +- 148 files changed, 777 insertions(+), 618 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 107b284e1dd87d..a68577b4dce6b1 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -5471,6 +5471,53 @@ pm_super_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_argument return node; } +/** + * Read through the contents of a string and check if it consists solely of US ASCII code points. + */ +static bool +ascii_only_p( const pm_string_t *contents) { + const size_t length = contents->length; + + for (size_t i = 0; i < length; i++) { + if (contents->source[i] & 0x80) { + return false; + } + } + + return true; +} + +/** + * Ruby "downgrades" the encoding of Symbols to US-ASCII if the associated encoding is ASCII-compatible and + * the Symbol consists only of US-ASCII code points. Otherwise, the encoding may be explicitly set with an + * escape sequence. + */ +static inline pm_node_flags_t +parse_symbol_encoding(const pm_parser_t *parser, const pm_string_t *contents) { + // Don't set any flags on the Symbol if it hasn't been populated yet. + if (contents->source == NULL) { + return 0; + } + + // Ruby stipulates that all source files must use an ASCII-compatible encoding. Thus, all symbols appearing in + // source are eligible for "downgrading" to US-ASCII. + if (ascii_only_p(contents)) { + return PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING; + } else { + // A Symbol may optionally have its encoding explicitly set. + // + // NB: an explicitly set encoding is ignored by Ruby if the Symbol consists of only US ASCII code points. + if (parser->explicit_encoding != NULL) { + if (parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY) { + return PM_SYMBOL_FLAGS_FORCED_UTF8_ENCODING; + } else if (parser->encoding == PM_ENCODING_US_ASCII_ENTRY) { + return PM_SYMBOL_FLAGS_FORCED_BINARY_ENCODING; + } + } + } + return 0; +} + /** * Allocate and initialize a new SymbolNode node with the given unescaped * string. @@ -5494,6 +5541,8 @@ pm_symbol_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, .unescaped = *unescaped }; + pm_node_flag_set((pm_node_t *)node, parse_symbol_encoding(parser, unescaped)); + return node; } @@ -5532,6 +5581,7 @@ pm_symbol_node_label_create(pm_parser_t *parser, const pm_token_t *token) { assert((label.end - label.start) >= 0); pm_string_shared_init(&node->unescaped, label.start, label.end); + pm_node_flag_set((pm_node_t *)node, parse_symbol_encoding(parser, &node->unescaped)); break; } case PM_TOKEN_MISSING: { @@ -5594,6 +5644,8 @@ pm_string_node_to_symbol_node(pm_parser_t *parser, pm_string_node_t *node, const .unescaped = node->unescaped }; + pm_node_flag_set((pm_node_t *)new_node, parse_symbol_encoding(parser, &node->unescaped)); + // We are explicitly _not_ using pm_node_destroy here because we don't want // to trash the unescaped string. We could instead copy the string if we // know that it is owned, but we're taking the fast path for now. @@ -8115,7 +8167,6 @@ pm_token_buffer_push(pm_token_buffer_t *token_buffer, uint8_t byte) { /** * When we're about to return from lexing the current token and we know for sure * that we have found an escape sequence, this function is called to copy the - * * contents of the token buffer into the current string on the parser so that it * can be attached to the correct node. */ @@ -8130,7 +8181,6 @@ pm_token_buffer_copy(pm_parser_t *parser, pm_token_buffer_t *token_buffer) { * string. If we haven't pushed anything into the buffer, this means that we * never found an escape sequence, so we can directly reference the bounds of * the current string. Either way, at the return of this function it is expected - * * that parser->current_string is established in such a way that it can be * attached to a node. */ @@ -8149,7 +8199,6 @@ pm_token_buffer_flush(pm_parser_t *parser, pm_token_buffer_t *token_buffer) { * point into the buffer because we're about to provide a string that has * different content than a direct slice of the source. * - * * It is expected that the parser's current token end will be pointing at one * byte past the backslash that starts the escape sequence. */ @@ -12595,8 +12644,11 @@ PM_STATIC_ASSERT(__LINE__, ((int) PM_STRING_FLAGS_FORCED_UTF8_ENCODING) == ((int static inline pm_node_flags_t parse_unescaped_encoding(const pm_parser_t *parser) { if (parser->explicit_encoding != NULL) { + // If the there's an explicit encoding and it's using a UTF-8 escape sequence, then mark the string as UTF-8. if (parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY) { return PM_STRING_FLAGS_FORCED_UTF8_ENCODING; + // If there's a non-UTF-8 escape sequence being used, then the string uses the source encoding, unless the source + // is marked as US-ASCII. In that case the string is forced as ASCII-8BIT in order to keep the string valid. } else if (parser->encoding == PM_ENCODING_US_ASCII_ENTRY) { return PM_STRING_FLAGS_FORCED_BINARY_ENCODING; } @@ -12749,6 +12801,7 @@ parse_operator_symbol(pm_parser_t *parser, const pm_token_t *opening, pm_lex_sta parser_lex(parser); pm_string_shared_init(&symbol->unescaped, parser->previous.start, end); + pm_node_flag_set((pm_node_t *)symbol, parse_symbol_encoding(parser, &symbol->unescaped)); return (pm_node_t *) symbol; } @@ -12787,6 +12840,8 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s pm_symbol_node_t *symbol = pm_symbol_node_create(parser, &opening, &parser->previous, &closing); pm_string_shared_init(&symbol->unescaped, parser->previous.start, parser->previous.end); + pm_node_flag_set((pm_node_t *)symbol, parse_symbol_encoding(parser, &symbol->unescaped)); + return (pm_node_t *) symbol; } @@ -12872,6 +12927,7 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s } else { content = (pm_token_t) { .type = PM_TOKEN_STRING_CONTENT, .start = parser->previous.end, .end = parser->previous.end }; pm_string_shared_init(&unescaped, content.start, content.end); + } if (next_state != PM_LEX_STATE_NONE) { @@ -12883,7 +12939,11 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s } else { expect1(parser, PM_TOKEN_STRING_END, PM_ERR_SYMBOL_TERM_DYNAMIC); } - return (pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped); + + pm_symbol_node_t *symbol_node = pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped); + pm_node_flag_set((pm_node_t *)symbol_node, parse_symbol_encoding(parser, &symbol_node->unescaped)); + + return (pm_node_t *) symbol_node; } /** @@ -12947,6 +13007,7 @@ parse_alias_argument(pm_parser_t *parser, bool first) { pm_symbol_node_t *symbol = pm_symbol_node_create(parser, &opening, &parser->previous, &closing); pm_string_shared_init(&symbol->unescaped, parser->previous.start, parser->previous.end); + pm_node_flag_set((pm_node_t *)symbol, parse_symbol_encoding(parser, &symbol->unescaped)); return (pm_node_t *) symbol; } case PM_TOKEN_SYMBOL_BEGIN: { diff --git a/test/prism/encoding_test.rb b/test/prism/encoding_test.rb index e755cdaba2d63c..f6caeeb769f20b 100644 --- a/test/prism/encoding_test.rb +++ b/test/prism/encoding_test.rb @@ -148,6 +148,7 @@ class EncodingTest < TestCase # encoding that prism supports. escapes = ["\\x00", "\\x7F", "\\x80", "\\xFF", "\\u{00}", "\\u{7F}", "\\u{80}", "\\M-\\C-?"] escapes = escapes.concat(escapes.product(escapes).map(&:join)) + symbols = [:a, :ą, :+] encodings.each_key do |encoding| define_method(:"test_encoding_flags_#{encoding.name}") do @@ -155,6 +156,18 @@ class EncodingTest < TestCase end end + encodings.each_key do |encoding| + define_method(:"test_symbol_encoding_flags_#{encoding.name}") do + assert_symbol_encoding_flags(encoding, symbols) + end + end + + encodings.each_key do |encoding| + define_method(:"test_symbol_character_escape_encoding_flags_#{encoding.name}") do + assert_symbol_character_escape_encoding_flags(encoding, escapes) + end + end + def test_coding result = Prism.parse("# coding: utf-8\n'string'") actual = result.value.statements.body.first.unescaped.encoding @@ -343,5 +356,90 @@ def assert_encoding_flags(encoding, escapes) assert_equal expected, actual end end + + # Test Symbol literals without any interpolation or escape sequences. + def assert_symbol_encoding_flags(encoding, symbols) + symbols.each do |symbol| + source = "# encoding: #{encoding.name}\n#{symbol.inspect}" + + expected = + begin + eval(source).encoding + rescue SyntaxError => error + unless error.message.include?("invalid multibyte char") + raise + end + end + + actual = + Prism.parse(source).then do |result| + if result.success? + symbol = result.value.statements.body.first + + if symbol.forced_utf8_encoding? + Encoding::UTF_8 + elsif symbol.forced_binary_encoding? + Encoding::ASCII_8BIT + elsif symbol.forced_us_ascii_encoding? + Encoding::US_ASCII + else + encoding + end + else + error = result.errors.last + + unless error.message.include?("invalid symbol") + raise error.message + end + end + end + + assert_equal expected, actual + end + end + + def assert_symbol_character_escape_encoding_flags(encoding, escapes) + escapes.each do |escaped| + source = "# encoding: #{encoding.name}\n:\"#{escaped}\"" + + expected = + begin + eval(source).encoding + rescue SyntaxError => error + if error.message.include?("UTF-8 mixed within") + error.message[/: (.+?)\n/, 1] + else + raise + end + end + + actual = + Prism.parse(source).then do |result| + if result.success? + symbol = result.value.statements.body.first + + if symbol.forced_utf8_encoding? + Encoding::UTF_8 + elsif symbol.forced_binary_encoding? + Encoding::ASCII_8BIT + elsif symbol.forced_us_ascii_encoding? + Encoding::US_ASCII + else + encoding + end + else + error = result.errors.first + + if error.message.include?("mixed") + error.message + else + raise error.message + end + end + end + + assert_equal expected, actual + end + end end end diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index 60322585f05133..304d55274e98fc 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -416,7 +416,7 @@ def test_splat_argument_after_keyword_argument ArgumentsNode(0, [ KeywordHashNode(1, [ AssocNode( - SymbolNode(0, nil, Location(), Location(), "foo"), + SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, nil, Location(), Location(), "foo"), expression("bar"), nil ) @@ -594,16 +594,16 @@ def test_cannot_assign_to_a_reserved_numbered_parameter expected = BeginNode( Location(), StatementsNode([ - LocalVariableWriteNode(:_1, 0, Location(), SymbolNode(0, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_2, 0, Location(), SymbolNode(0, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_3, 0, Location(), SymbolNode(0, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_4, 0, Location(), SymbolNode(0, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_5, 0, Location(), SymbolNode(0, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_6, 0, Location(), SymbolNode(0, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_7, 0, Location(), SymbolNode(0, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_8, 0, Location(), SymbolNode(0, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_9, 0, Location(), SymbolNode(0, Location(), Location(), nil, "a"), Location()), - LocalVariableWriteNode(:_10, 0, Location(), SymbolNode(0, Location(), Location(), nil, "a"), Location()) + LocalVariableWriteNode(:_1, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), + LocalVariableWriteNode(:_2, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), + LocalVariableWriteNode(:_3, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), + LocalVariableWriteNode(:_4, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), + LocalVariableWriteNode(:_5, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), + LocalVariableWriteNode(:_6, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), + LocalVariableWriteNode(:_7, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), + LocalVariableWriteNode(:_8, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), + LocalVariableWriteNode(:_9, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()), + LocalVariableWriteNode(:_10, 0, Location(), SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), Location()) ]), nil, nil, @@ -1004,7 +1004,7 @@ def test_returning_to_optional_parameters_multiple_times def test_case_without_when_clauses_errors_on_else_clause expected = CaseMatchNode( - SymbolNode(0, Location(), Location(), nil, "a"), + SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), [], ElseNode(Location(), nil, Location()), Location(), @@ -1018,7 +1018,7 @@ def test_case_without_when_clauses_errors_on_else_clause def test_case_without_clauses expected = CaseNode( - SymbolNode(0, Location(), Location(), nil, "a"), + SymbolNode(SymbolFlags::FORCED_US_ASCII_ENCODING, Location(), Location(), nil, "a"), [], nil, Location(), diff --git a/test/prism/snapshots/alias.txt b/test/prism/snapshots/alias.txt index b473ab7a9b5468..c2ddc9d2da8ea4 100644 --- a/test/prism/snapshots/alias.txt +++ b/test/prism/snapshots/alias.txt @@ -6,14 +6,14 @@ ├── @ AliasMethodNode (location: (1,0)-(1,15)) │ ├── new_name: │ │ @ SymbolNode (location: (1,6)-(1,10)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,6)-(1,7) = ":" │ │ ├── value_loc: (1,7)-(1,10) = "foo" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "foo" │ ├── old_name: │ │ @ SymbolNode (location: (1,11)-(1,15)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,11)-(1,12) = ":" │ │ ├── value_loc: (1,12)-(1,15) = "bar" │ │ ├── closing_loc: ∅ @@ -22,14 +22,14 @@ ├── @ AliasMethodNode (location: (3,0)-(3,21)) │ ├── new_name: │ │ @ SymbolNode (location: (3,6)-(3,13)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (3,6)-(3,9) = "%s[" │ │ ├── value_loc: (3,9)-(3,12) = "abc" │ │ ├── closing_loc: (3,12)-(3,13) = "]" │ │ └── unescaped: "abc" │ ├── old_name: │ │ @ SymbolNode (location: (3,14)-(3,21)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (3,14)-(3,17) = "%s[" │ │ ├── value_loc: (3,17)-(3,20) = "def" │ │ ├── closing_loc: (3,20)-(3,21) = "]" @@ -38,14 +38,14 @@ ├── @ AliasMethodNode (location: (5,0)-(5,19)) │ ├── new_name: │ │ @ SymbolNode (location: (5,6)-(5,12)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (5,6)-(5,8) = ":'" │ │ ├── value_loc: (5,8)-(5,11) = "abc" │ │ ├── closing_loc: (5,11)-(5,12) = "'" │ │ └── unescaped: "abc" │ ├── old_name: │ │ @ SymbolNode (location: (5,13)-(5,19)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (5,13)-(5,15) = ":'" │ │ ├── value_loc: (5,15)-(5,18) = "def" │ │ ├── closing_loc: (5,18)-(5,19) = "'" @@ -73,7 +73,7 @@ │ │ └── closing_loc: (7,15)-(7,16) = "\"" │ ├── old_name: │ │ @ SymbolNode (location: (7,17)-(7,23)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (7,17)-(7,19) = ":'" │ │ ├── value_loc: (7,19)-(7,22) = "def" │ │ ├── closing_loc: (7,22)-(7,23) = "'" @@ -90,14 +90,14 @@ ├── @ AliasMethodNode (location: (11,0)-(11,13)) │ ├── new_name: │ │ @ SymbolNode (location: (11,6)-(11,9)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (11,6)-(11,9) = "foo" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "foo" │ ├── old_name: │ │ @ SymbolNode (location: (11,10)-(11,13)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (11,10)-(11,13) = "bar" │ │ ├── closing_loc: ∅ @@ -114,14 +114,14 @@ ├── @ AliasMethodNode (location: (15,0)-(15,12)) │ ├── new_name: │ │ @ SymbolNode (location: (15,6)-(15,9)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (15,6)-(15,9) = "foo" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "foo" │ ├── old_name: │ │ @ SymbolNode (location: (15,10)-(15,12)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (15,10)-(15,12) = "if" │ │ ├── closing_loc: ∅ @@ -130,14 +130,14 @@ ├── @ AliasMethodNode (location: (17,0)-(17,13)) │ ├── new_name: │ │ @ SymbolNode (location: (17,6)-(17,9)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (17,6)-(17,9) = "foo" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "foo" │ ├── old_name: │ │ @ SymbolNode (location: (17,10)-(17,13)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (17,10)-(17,13) = "<=>" │ │ ├── closing_loc: ∅ @@ -146,14 +146,14 @@ ├── @ AliasMethodNode (location: (19,0)-(19,15)) │ ├── new_name: │ │ @ SymbolNode (location: (19,6)-(19,9)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (19,6)-(19,7) = ":" │ │ ├── value_loc: (19,7)-(19,9) = "==" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "==" │ ├── old_name: │ │ @ SymbolNode (location: (19,10)-(19,15)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (19,10)-(19,11) = ":" │ │ ├── value_loc: (19,11)-(19,15) = "eql?" │ │ ├── closing_loc: ∅ @@ -162,14 +162,14 @@ ├── @ AliasMethodNode (location: (21,0)-(21,9)) │ ├── new_name: │ │ @ SymbolNode (location: (21,6)-(21,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (21,6)-(21,7) = "A" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "A" │ ├── old_name: │ │ @ SymbolNode (location: (21,8)-(21,9)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (21,8)-(21,9) = "B" │ │ ├── closing_loc: ∅ @@ -178,14 +178,14 @@ └── @ AliasMethodNode (location: (23,0)-(23,11)) ├── new_name: │ @ SymbolNode (location: (23,6)-(23,8)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (23,6)-(23,7) = ":" │ ├── value_loc: (23,7)-(23,8) = "A" │ ├── closing_loc: ∅ │ └── unescaped: "A" ├── old_name: │ @ SymbolNode (location: (23,9)-(23,11)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (23,9)-(23,10) = ":" │ ├── value_loc: (23,10)-(23,11) = "B" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/arrays.txt b/test/prism/snapshots/arrays.txt index c1b29134619bbc..bea52be855fbcf 100644 --- a/test/prism/snapshots/arrays.txt +++ b/test/prism/snapshots/arrays.txt @@ -84,7 +84,7 @@ │ │ └── @ AssocNode (location: (5,1)-(5,12)) │ │ ├── key: │ │ │ @ SymbolNode (location: (5,1)-(5,3)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (5,1)-(5,2) = "a" │ │ │ ├── closing_loc: (5,2)-(5,3) = ":" @@ -94,13 +94,13 @@ │ │ │ ├── flags: ∅ │ │ │ ├── elements: (length: 2) │ │ │ │ ├── @ SymbolNode (location: (5,5)-(5,7)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (5,5)-(5,6) = ":" │ │ │ │ │ ├── value_loc: (5,6)-(5,7) = "b" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "b" │ │ │ │ └── @ SymbolNode (location: (5,9)-(5,11)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (5,9)-(5,10) = ":" │ │ │ │ ├── value_loc: (5,10)-(5,11) = "c" │ │ │ │ ├── closing_loc: ∅ @@ -114,19 +114,19 @@ │ ├── flags: ∅ │ ├── elements: (length: 5) │ │ ├── @ SymbolNode (location: (9,1)-(9,3)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (9,1)-(9,2) = ":" │ │ │ ├── value_loc: (9,2)-(9,3) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ ├── @ SymbolNode (location: (9,5)-(9,7)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (9,5)-(9,6) = ":" │ │ │ ├── value_loc: (9,6)-(9,7) = "b" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "b" │ │ ├── @ SymbolNode (location: (10,0)-(10,2)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (10,0)-(10,1) = ":" │ │ │ ├── value_loc: (10,1)-(10,2) = "c" │ │ │ ├── closing_loc: ∅ @@ -134,7 +134,7 @@ │ │ ├── @ IntegerNode (location: (10,3)-(10,4)) │ │ │ └── flags: decimal │ │ └── @ SymbolNode (location: (14,0)-(14,2)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (14,0)-(14,1) = ":" │ │ ├── value_loc: (14,1)-(14,2) = "d" │ │ ├── closing_loc: ∅ @@ -145,19 +145,19 @@ │ ├── flags: ∅ │ ├── elements: (length: 5) │ │ ├── @ SymbolNode (location: (18,1)-(18,3)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (18,1)-(18,2) = ":" │ │ │ ├── value_loc: (18,2)-(18,3) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ ├── @ SymbolNode (location: (18,5)-(18,7)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (18,5)-(18,6) = ":" │ │ │ ├── value_loc: (18,6)-(18,7) = "b" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "b" │ │ ├── @ SymbolNode (location: (19,0)-(19,2)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (19,0)-(19,1) = ":" │ │ │ ├── value_loc: (19,1)-(19,2) = "c" │ │ │ ├── closing_loc: ∅ @@ -165,7 +165,7 @@ │ │ ├── @ IntegerNode (location: (19,3)-(19,4)) │ │ │ └── flags: decimal │ │ └── @ SymbolNode (location: (23,0)-(23,2)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (23,0)-(23,1) = ":" │ │ ├── value_loc: (23,1)-(23,2) = "d" │ │ ├── closing_loc: ∅ @@ -768,19 +768,19 @@ │ ├── flags: ∅ │ ├── elements: (length: 3) │ │ ├── @ SymbolNode (location: (62,3)-(62,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (62,3)-(62,6) = "one" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "one" │ │ ├── @ SymbolNode (location: (62,7)-(62,10)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (62,7)-(62,10) = "two" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "two" │ │ └── @ SymbolNode (location: (62,11)-(62,16)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (62,11)-(62,16) = "three" │ │ ├── closing_loc: ∅ @@ -820,19 +820,19 @@ │ ├── flags: ∅ │ ├── elements: (length: 3) │ │ ├── @ SymbolNode (location: (69,3)-(69,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (69,3)-(69,6) = "one" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "one" │ │ ├── @ SymbolNode (location: (69,7)-(69,10)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (69,7)-(69,10) = "two" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "two" │ │ └── @ SymbolNode (location: (69,11)-(69,16)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (69,11)-(69,16) = "three" │ │ ├── closing_loc: ∅ @@ -872,19 +872,19 @@ │ ├── flags: ∅ │ ├── elements: (length: 3) │ │ ├── @ SymbolNode (location: (76,3)-(76,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (76,3)-(76,6) = "one" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "one" │ │ ├── @ SymbolNode (location: (76,7)-(76,10)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (76,7)-(76,10) = "two" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "two" │ │ └── @ SymbolNode (location: (76,11)-(76,16)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (76,11)-(76,16) = "three" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/begin_ensure.txt b/test/prism/snapshots/begin_ensure.txt index e6325141996fcb..b86feefc1db38d 100644 --- a/test/prism/snapshots/begin_ensure.txt +++ b/test/prism/snapshots/begin_ensure.txt @@ -157,7 +157,7 @@ │ │ ├── flags: ∅ │ │ ├── receiver: │ │ │ @ SymbolNode (location: (15,11)-(15,13)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (15,11)-(15,12) = ":" │ │ │ ├── value_loc: (15,12)-(15,13) = "s" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/case.txt b/test/prism/snapshots/case.txt index bcd5ef67900ff4..b8cafca6a01989 100644 --- a/test/prism/snapshots/case.txt +++ b/test/prism/snapshots/case.txt @@ -6,7 +6,7 @@ ├── @ CaseNode (location: (1,0)-(3,3)) │ ├── predicate: │ │ @ SymbolNode (location: (1,5)-(1,8)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,5)-(1,6) = ":" │ │ ├── value_loc: (1,6)-(1,8) = "hi" │ │ ├── closing_loc: ∅ @@ -16,7 +16,7 @@ │ │ ├── keyword_loc: (2,0)-(2,4) = "when" │ │ ├── conditions: (length: 1) │ │ │ └── @ SymbolNode (location: (2,5)-(2,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (2,5)-(2,6) = ":" │ │ │ ├── value_loc: (2,6)-(2,8) = "hi" │ │ │ ├── closing_loc: ∅ @@ -48,7 +48,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ SymbolNode (location: (5,27)-(5,30)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (5,27)-(5,28) = ":" │ │ │ │ ├── value_loc: (5,28)-(5,30) = "hi" │ │ │ │ ├── closing_loc: ∅ @@ -74,7 +74,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ SymbolNode (location: (5,49)-(5,53)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (5,49)-(5,50) = ":" │ │ │ ├── value_loc: (5,50)-(5,53) = "bye" │ │ │ ├── closing_loc: ∅ @@ -110,7 +110,7 @@ ├── @ CaseNode (location: (9,0)-(13,3)) │ ├── predicate: │ │ @ SymbolNode (location: (9,5)-(9,8)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (9,5)-(9,6) = ":" │ │ ├── value_loc: (9,6)-(9,8) = "hi" │ │ ├── closing_loc: ∅ @@ -120,7 +120,7 @@ │ │ ├── keyword_loc: (10,0)-(10,4) = "when" │ │ ├── conditions: (length: 1) │ │ │ └── @ SymbolNode (location: (10,5)-(10,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (10,5)-(10,6) = ":" │ │ │ ├── value_loc: (10,6)-(10,8) = "hi" │ │ │ ├── closing_loc: ∅ @@ -133,7 +133,7 @@ │ │ │ @ StatementsNode (location: (12,0)-(12,2)) │ │ │ └── body: (length: 1) │ │ │ └── @ SymbolNode (location: (12,0)-(12,2)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (12,0)-(12,1) = ":" │ │ │ ├── value_loc: (12,1)-(12,2) = "b" │ │ │ ├── closing_loc: ∅ @@ -249,7 +249,7 @@ │ │ ├── keyword_loc: (28,3)-(28,7) = "when" │ │ ├── conditions: (length: 1) │ │ │ └── @ SymbolNode (location: (28,8)-(28,10)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (28,8)-(28,9) = ":" │ │ │ ├── value_loc: (28,9)-(28,10) = "b" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/dos_endings.txt b/test/prism/snapshots/dos_endings.txt index 963375201c3139..ed75b8a52fdaa7 100644 --- a/test/prism/snapshots/dos_endings.txt +++ b/test/prism/snapshots/dos_endings.txt @@ -36,7 +36,7 @@ │ ├── flags: ∅ │ ├── elements: (length: 1) │ │ └── @ SymbolNode (location: (4,3)-(5,1)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (4,3)-(5,1) = "a\\\r\nb" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/global_variables.txt b/test/prism/snapshots/global_variables.txt index 725de21126da7a..9f775ed80d399a 100644 --- a/test/prism/snapshots/global_variables.txt +++ b/test/prism/snapshots/global_variables.txt @@ -52,139 +52,139 @@ ├── @ GlobalVariableReadNode (location: (47,0)-(47,3)) │ └── name: :$-K ├── @ SymbolNode (location: (49,0)-(49,17)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (49,0)-(49,1) = ":" │ ├── value_loc: (49,1)-(49,17) = "$global_variable" │ ├── closing_loc: ∅ │ └── unescaped: "$global_variable" ├── @ SymbolNode (location: (51,0)-(51,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (51,0)-(51,1) = ":" │ ├── value_loc: (51,1)-(51,3) = "$_" │ ├── closing_loc: ∅ │ └── unescaped: "$_" ├── @ SymbolNode (location: (53,0)-(53,4)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (53,0)-(53,1) = ":" │ ├── value_loc: (53,1)-(53,4) = "$-w" │ ├── closing_loc: ∅ │ └── unescaped: "$-w" ├── @ SymbolNode (location: (55,0)-(55,11)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (55,0)-(55,1) = ":" │ ├── value_loc: (55,1)-(55,11) = "$LOAD_PATH" │ ├── closing_loc: ∅ │ └── unescaped: "$LOAD_PATH" ├── @ SymbolNode (location: (57,0)-(57,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (57,0)-(57,1) = ":" │ ├── value_loc: (57,1)-(57,7) = "$stdin" │ ├── closing_loc: ∅ │ └── unescaped: "$stdin" ├── @ SymbolNode (location: (59,0)-(59,8)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (59,0)-(59,1) = ":" │ ├── value_loc: (59,1)-(59,8) = "$stdout" │ ├── closing_loc: ∅ │ └── unescaped: "$stdout" ├── @ SymbolNode (location: (61,0)-(61,8)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (61,0)-(61,1) = ":" │ ├── value_loc: (61,1)-(61,8) = "$stderr" │ ├── closing_loc: ∅ │ └── unescaped: "$stderr" ├── @ SymbolNode (location: (63,0)-(63,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (63,0)-(63,1) = ":" │ ├── value_loc: (63,1)-(63,3) = "$!" │ ├── closing_loc: ∅ │ └── unescaped: "$!" ├── @ SymbolNode (location: (65,0)-(65,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (65,0)-(65,1) = ":" │ ├── value_loc: (65,1)-(65,3) = "$?" │ ├── closing_loc: ∅ │ └── unescaped: "$?" ├── @ SymbolNode (location: (67,0)-(67,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (67,0)-(67,1) = ":" │ ├── value_loc: (67,1)-(67,3) = "$~" │ ├── closing_loc: ∅ │ └── unescaped: "$~" ├── @ SymbolNode (location: (69,0)-(69,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (69,0)-(69,1) = ":" │ ├── value_loc: (69,1)-(69,3) = "$&" │ ├── closing_loc: ∅ │ └── unescaped: "$&" ├── @ SymbolNode (location: (71,0)-(71,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (71,0)-(71,1) = ":" │ ├── value_loc: (71,1)-(71,3) = "$`" │ ├── closing_loc: ∅ │ └── unescaped: "$`" ├── @ SymbolNode (location: (73,0)-(73,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (73,0)-(73,1) = ":" │ ├── value_loc: (73,1)-(73,3) = "$'" │ ├── closing_loc: ∅ │ └── unescaped: "$'" ├── @ SymbolNode (location: (75,0)-(75,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (75,0)-(75,1) = ":" │ ├── value_loc: (75,1)-(75,3) = "$+" │ ├── closing_loc: ∅ │ └── unescaped: "$+" ├── @ SymbolNode (location: (77,0)-(77,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (77,0)-(77,1) = ":" │ ├── value_loc: (77,1)-(77,3) = "$:" │ ├── closing_loc: ∅ │ └── unescaped: "$:" ├── @ SymbolNode (location: (79,0)-(79,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (79,0)-(79,1) = ":" │ ├── value_loc: (79,1)-(79,3) = "$;" │ ├── closing_loc: ∅ │ └── unescaped: "$;" ├── @ SymbolNode (location: (81,0)-(81,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (81,0)-(81,1) = ":" │ ├── value_loc: (81,1)-(81,7) = "$DEBUG" │ ├── closing_loc: ∅ │ └── unescaped: "$DEBUG" ├── @ SymbolNode (location: (83,0)-(83,10)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (83,0)-(83,1) = ":" │ ├── value_loc: (83,1)-(83,10) = "$FILENAME" │ ├── closing_loc: ∅ │ └── unescaped: "$FILENAME" ├── @ SymbolNode (location: (85,0)-(85,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (85,0)-(85,1) = ":" │ ├── value_loc: (85,1)-(85,3) = "$0" │ ├── closing_loc: ∅ │ └── unescaped: "$0" ├── @ SymbolNode (location: (87,0)-(87,4)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (87,0)-(87,1) = ":" │ ├── value_loc: (87,1)-(87,4) = "$-0" │ ├── closing_loc: ∅ │ └── unescaped: "$-0" ├── @ SymbolNode (location: (89,0)-(89,17)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (89,0)-(89,1) = ":" │ ├── value_loc: (89,1)-(89,17) = "$LOADED_FEATURES" │ ├── closing_loc: ∅ │ └── unescaped: "$LOADED_FEATURES" ├── @ SymbolNode (location: (91,0)-(91,9)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (91,0)-(91,1) = ":" │ ├── value_loc: (91,1)-(91,9) = "$VERBOSE" │ ├── closing_loc: ∅ │ └── unescaped: "$VERBOSE" └── @ SymbolNode (location: (93,0)-(93,4)) - ├── flags: ∅ + ├── flags: forced_us_ascii_encoding ├── opening_loc: (93,0)-(93,1) = ":" ├── value_loc: (93,1)-(93,4) = "$-K" ├── closing_loc: ∅ diff --git a/test/prism/snapshots/hashes.txt b/test/prism/snapshots/hashes.txt index 741fb8939b88b9..824326e863ade4 100644 --- a/test/prism/snapshots/hashes.txt +++ b/test/prism/snapshots/hashes.txt @@ -110,7 +110,7 @@ │ │ ├── @ AssocNode (location: (11,6)-(11,10)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (11,6)-(11,8)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (11,6)-(11,7) = "a" │ │ │ │ ├── closing_loc: (11,7)-(11,8) = ":" @@ -130,7 +130,7 @@ │ │ └── @ AssocNode (location: (12,6)-(12,10)) │ │ ├── key: │ │ │ @ SymbolNode (location: (12,6)-(12,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (12,6)-(12,7) = "c" │ │ │ ├── closing_loc: (12,7)-(12,8) = ":" @@ -154,7 +154,7 @@ │ │ ├── @ AssocNode (location: (18,2)-(18,6)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (18,2)-(18,4)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (18,2)-(18,3) = "a" │ │ │ │ ├── closing_loc: (18,3)-(18,4) = ":" @@ -174,7 +174,7 @@ │ │ ├── @ AssocNode (location: (18,8)-(18,12)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (18,8)-(18,10)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (18,8)-(18,9) = "c" │ │ │ │ ├── closing_loc: (18,9)-(18,10) = ":" @@ -207,7 +207,7 @@ │ │ └── @ AssocNode (location: (18,19)-(18,23)) │ │ ├── key: │ │ │ @ SymbolNode (location: (18,19)-(18,21)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (18,19)-(18,20) = "f" │ │ │ ├── closing_loc: (18,20)-(18,21) = ":" @@ -231,7 +231,7 @@ │ │ └── @ AssocNode (location: (20,2)-(20,10)) │ │ ├── key: │ │ │ @ SymbolNode (location: (20,2)-(20,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (20,2)-(20,3) = "\"" │ │ │ ├── value_loc: (20,3)-(20,4) = "a" │ │ │ ├── closing_loc: (20,4)-(20,6) = "\":" @@ -298,7 +298,7 @@ │ │ │ ├── @ AssocNode (location: (25,4)-(25,6)) │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (25,4)-(25,6)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (25,4)-(25,5) = "a" │ │ │ │ │ ├── closing_loc: (25,5)-(25,6) = ":" @@ -313,7 +313,7 @@ │ │ │ ├── @ AssocNode (location: (25,8)-(25,10)) │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (25,8)-(25,10)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (25,8)-(25,9) = "b" │ │ │ │ │ ├── closing_loc: (25,9)-(25,10) = ":" @@ -328,7 +328,7 @@ │ │ │ ├── @ AssocNode (location: (25,12)-(25,14)) │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (25,12)-(25,14)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (25,12)-(25,13) = "c" │ │ │ │ │ ├── closing_loc: (25,13)-(25,14) = ":" @@ -350,7 +350,7 @@ │ │ │ └── @ AssocNode (location: (25,16)-(25,18)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (25,16)-(25,18)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (25,16)-(25,17) = "D" │ │ │ │ ├── closing_loc: (25,17)-(25,18) = ":" @@ -370,7 +370,7 @@ │ └── @ AssocNode (location: (28,2)-(28,7)) │ ├── key: │ │ @ SymbolNode (location: (28,2)-(28,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (28,2)-(28,3) = "a" │ │ ├── closing_loc: (28,3)-(28,4) = ":" diff --git a/test/prism/snapshots/if.txt b/test/prism/snapshots/if.txt index ae3df9719b7040..76e102d42dfa15 100644 --- a/test/prism/snapshots/if.txt +++ b/test/prism/snapshots/if.txt @@ -255,7 +255,7 @@ │ │ │ └── @ AssocNode (location: (25,4)-(25,6)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (25,4)-(25,6)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (25,4)-(25,5) = "b" │ │ │ │ ├── closing_loc: (25,5)-(25,6) = ":" diff --git a/test/prism/snapshots/method_calls.txt b/test/prism/snapshots/method_calls.txt index ec694ef5331014..adf02ef1871612 100644 --- a/test/prism/snapshots/method_calls.txt +++ b/test/prism/snapshots/method_calls.txt @@ -698,13 +698,13 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 2) │ │ │ ├── @ SymbolNode (location: (51,4)-(51,6)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (51,4)-(51,5) = ":" │ │ │ │ ├── value_loc: (51,5)-(51,6) = "a" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "a" │ │ │ └── @ SymbolNode (location: (51,8)-(51,10)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (51,8)-(51,9) = ":" │ │ │ ├── value_loc: (51,9)-(51,10) = "b" │ │ │ ├── closing_loc: ∅ @@ -725,13 +725,13 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ SymbolNode (location: (53,4)-(53,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (53,4)-(53,5) = ":" │ │ │ ├── value_loc: (53,5)-(53,6) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ └── @ SymbolNode (location: (55,2)-(55,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (55,2)-(55,3) = ":" │ │ ├── value_loc: (55,3)-(55,4) = "b" │ │ ├── closing_loc: ∅ @@ -776,7 +776,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ SymbolNode (location: (60,4)-(60,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (60,4)-(60,5) = ":" │ │ │ ├── value_loc: (60,5)-(60,6) = "a" │ │ │ ├── closing_loc: ∅ @@ -787,7 +787,7 @@ │ │ ├── @ AssocNode (location: (60,8)-(60,22)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (60,8)-(60,10)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (60,8)-(60,9) = ":" │ │ │ │ ├── value_loc: (60,9)-(60,10) = "h" │ │ │ │ ├── closing_loc: ∅ @@ -797,13 +797,13 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ ├── elements: (length: 2) │ │ │ │ │ ├── @ SymbolNode (location: (60,15)-(60,17)) - │ │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ │ ├── opening_loc: (60,15)-(60,16) = ":" │ │ │ │ │ │ ├── value_loc: (60,16)-(60,17) = "x" │ │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ │ └── unescaped: "x" │ │ │ │ │ └── @ SymbolNode (location: (60,19)-(60,21)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (60,19)-(60,20) = ":" │ │ │ │ │ ├── value_loc: (60,20)-(60,21) = "y" │ │ │ │ │ ├── closing_loc: ∅ @@ -814,14 +814,14 @@ │ │ └── @ AssocNode (location: (60,24)-(60,32)) │ │ ├── key: │ │ │ @ SymbolNode (location: (60,24)-(60,26)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (60,24)-(60,25) = ":" │ │ │ ├── value_loc: (60,25)-(60,26) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ ├── value: │ │ │ @ SymbolNode (location: (60,30)-(60,32)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (60,30)-(60,31) = ":" │ │ │ ├── value_loc: (60,31)-(60,32) = "b" │ │ │ ├── closing_loc: ∅ @@ -832,7 +832,7 @@ │ @ BlockArgumentNode (location: (60,34)-(60,39)) │ ├── expression: │ │ @ SymbolNode (location: (60,35)-(60,39)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (60,35)-(60,36) = ":" │ │ ├── value_loc: (60,36)-(60,39) = "bar" │ │ ├── closing_loc: ∅ @@ -857,14 +857,14 @@ │ │ │ ├── @ AssocNode (location: (62,10)-(62,27)) │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (62,10)-(62,16)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (62,10)-(62,11) = ":" │ │ │ │ │ ├── value_loc: (62,11)-(62,16) = "there" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "there" │ │ │ │ ├── value: │ │ │ │ │ @ SymbolNode (location: (62,20)-(62,27)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (62,20)-(62,21) = ":" │ │ │ │ │ ├── value_loc: (62,21)-(62,27) = "friend" │ │ │ │ │ ├── closing_loc: ∅ @@ -880,14 +880,14 @@ │ │ │ └── @ AssocNode (location: (62,35)-(62,47)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (62,35)-(62,42)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (62,35)-(62,41) = "whatup" │ │ │ │ ├── closing_loc: (62,41)-(62,42) = ":" │ │ │ │ └── unescaped: "whatup" │ │ │ ├── value: │ │ │ │ @ SymbolNode (location: (62,43)-(62,47)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (62,43)-(62,44) = ":" │ │ │ │ ├── value_loc: (62,44)-(62,47) = "dog" │ │ │ │ ├── closing_loc: ∅ @@ -908,7 +908,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ SymbolNode (location: (64,4)-(64,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (64,4)-(64,5) = ":" │ │ │ ├── value_loc: (64,5)-(64,6) = "a" │ │ │ ├── closing_loc: ∅ @@ -919,7 +919,7 @@ │ │ └── @ AssocNode (location: (64,8)-(64,15)) │ │ ├── key: │ │ │ @ SymbolNode (location: (64,8)-(64,10)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (64,8)-(64,9) = "b" │ │ │ ├── closing_loc: (64,9)-(64,10) = ":" @@ -990,14 +990,14 @@ │ │ └── @ AssocNode (location: (66,3)-(66,17)) │ │ ├── key: │ │ │ @ SymbolNode (location: (66,3)-(66,9)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (66,3)-(66,8) = "there" │ │ │ ├── closing_loc: (66,8)-(66,9) = ":" │ │ │ └── unescaped: "there" │ │ ├── value: │ │ │ @ SymbolNode (location: (66,10)-(66,17)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (66,10)-(66,11) = ":" │ │ │ ├── value_loc: (66,11)-(66,17) = "friend" │ │ │ ├── closing_loc: ∅ @@ -1022,14 +1022,14 @@ │ │ ├── @ AssocNode (location: (68,3)-(68,20)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (68,3)-(68,9)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (68,3)-(68,4) = ":" │ │ │ │ ├── value_loc: (68,4)-(68,9) = "there" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "there" │ │ │ ├── value: │ │ │ │ @ SymbolNode (location: (68,13)-(68,20)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (68,13)-(68,14) = ":" │ │ │ │ ├── value_loc: (68,14)-(68,20) = "friend" │ │ │ │ ├── closing_loc: ∅ @@ -1045,14 +1045,14 @@ │ │ └── @ AssocNode (location: (68,28)-(68,40)) │ │ ├── key: │ │ │ @ SymbolNode (location: (68,28)-(68,35)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (68,28)-(68,34) = "whatup" │ │ │ ├── closing_loc: (68,34)-(68,35) = ":" │ │ │ └── unescaped: "whatup" │ │ ├── value: │ │ │ @ SymbolNode (location: (68,36)-(68,40)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (68,36)-(68,37) = ":" │ │ │ ├── value_loc: (68,37)-(68,40) = "dog" │ │ │ ├── closing_loc: ∅ @@ -1077,14 +1077,14 @@ │ │ ├── @ AssocNode (location: (70,3)-(70,20)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (70,3)-(70,9)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (70,3)-(70,4) = ":" │ │ │ │ ├── value_loc: (70,4)-(70,9) = "there" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "there" │ │ │ ├── value: │ │ │ │ @ SymbolNode (location: (70,13)-(70,20)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (70,13)-(70,14) = ":" │ │ │ │ ├── value_loc: (70,14)-(70,20) = "friend" │ │ │ │ ├── closing_loc: ∅ @@ -1100,14 +1100,14 @@ │ │ └── @ AssocNode (location: (70,28)-(70,40)) │ │ ├── key: │ │ │ @ SymbolNode (location: (70,28)-(70,35)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (70,28)-(70,34) = "whatup" │ │ │ ├── closing_loc: (70,34)-(70,35) = ":" │ │ │ └── unescaped: "whatup" │ │ ├── value: │ │ │ @ SymbolNode (location: (70,36)-(70,40)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (70,36)-(70,37) = ":" │ │ │ ├── value_loc: (70,37)-(70,40) = "dog" │ │ │ ├── closing_loc: ∅ @@ -1132,7 +1132,7 @@ │ │ │ ├── @ AssocNode (location: (72,6)-(72,13)) │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (72,6)-(72,8)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (72,6)-(72,7) = "a" │ │ │ │ │ ├── closing_loc: (72,7)-(72,8) = ":" @@ -1143,7 +1143,7 @@ │ │ │ └── @ AssocNode (location: (72,15)-(72,23)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (72,15)-(72,17)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (72,15)-(72,16) = "b" │ │ │ │ ├── closing_loc: (72,16)-(72,17) = ":" @@ -1157,7 +1157,7 @@ │ @ BlockArgumentNode (location: (72,28)-(72,35)) │ ├── expression: │ │ @ SymbolNode (location: (72,29)-(72,35)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (72,29)-(72,30) = ":" │ │ ├── value_loc: (72,30)-(72,35) = "block" │ │ ├── closing_loc: ∅ @@ -1180,14 +1180,14 @@ │ │ └── @ AssocNode (location: (74,3)-(74,20)) │ │ ├── key: │ │ │ @ SymbolNode (location: (74,3)-(74,9)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (74,3)-(74,4) = ":" │ │ │ ├── value_loc: (74,4)-(74,9) = "there" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "there" │ │ ├── value: │ │ │ @ SymbolNode (location: (74,13)-(74,20)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (74,13)-(74,14) = ":" │ │ │ ├── value_loc: (74,14)-(74,20) = "friend" │ │ │ ├── closing_loc: ∅ @@ -1207,13 +1207,13 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ SymbolNode (location: (76,4)-(76,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (76,4)-(76,5) = ":" │ │ │ ├── value_loc: (76,5)-(76,6) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ └── @ SymbolNode (location: (77,0)-(77,2)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (77,0)-(77,1) = ":" │ │ ├── value_loc: (77,1)-(77,2) = "b" │ │ ├── closing_loc: ∅ @@ -1232,7 +1232,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ SymbolNode (location: (81,0)-(81,2)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (81,0)-(81,1) = ":" │ │ │ ├── value_loc: (81,1)-(81,2) = "a" │ │ │ ├── closing_loc: ∅ @@ -1243,14 +1243,14 @@ │ │ └── @ AssocNode (location: (82,0)-(82,5)) │ │ ├── key: │ │ │ @ SymbolNode (location: (82,0)-(82,2)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (82,0)-(82,1) = "b" │ │ │ ├── closing_loc: (82,1)-(82,2) = ":" │ │ │ └── unescaped: "b" │ │ ├── value: │ │ │ @ SymbolNode (location: (82,3)-(82,5)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (82,3)-(82,4) = ":" │ │ │ ├── value_loc: (82,4)-(82,5) = "c" │ │ │ ├── closing_loc: ∅ @@ -1271,7 +1271,7 @@ │ @ BlockArgumentNode (location: (85,4)-(85,11)) │ ├── expression: │ │ @ SymbolNode (location: (85,5)-(85,11)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (85,5)-(85,6) = ":" │ │ ├── value_loc: (85,6)-(85,11) = "block" │ │ ├── closing_loc: ∅ @@ -1294,7 +1294,7 @@ │ │ ├── @ AssocNode (location: (87,4)-(87,11)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (87,4)-(87,6)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (87,4)-(87,5) = "a" │ │ │ │ ├── closing_loc: (87,5)-(87,6) = ":" @@ -1305,7 +1305,7 @@ │ │ └── @ AssocNode (location: (87,13)-(87,21)) │ │ ├── key: │ │ │ @ SymbolNode (location: (87,13)-(87,15)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (87,13)-(87,14) = "b" │ │ │ ├── closing_loc: (87,14)-(87,15) = ":" @@ -1318,7 +1318,7 @@ │ @ BlockArgumentNode (location: (87,23)-(87,30)) │ ├── expression: │ │ @ SymbolNode (location: (87,24)-(87,30)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (87,24)-(87,25) = ":" │ │ ├── value_loc: (87,25)-(87,30) = "block" │ │ ├── closing_loc: ∅ @@ -1343,7 +1343,7 @@ │ │ └── @ AssocNode (location: (89,13)-(89,21)) │ │ ├── key: │ │ │ @ SymbolNode (location: (89,13)-(89,19)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (89,13)-(89,18) = "kwarg" │ │ │ ├── closing_loc: (89,18)-(89,19) = ":" @@ -1449,7 +1449,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ SymbolNode (location: (97,8)-(97,12)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (97,8)-(97,9) = ":" │ │ ├── value_loc: (97,9)-(97,12) = "foo" │ │ ├── closing_loc: ∅ @@ -1476,7 +1476,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ SymbolNode (location: (99,8)-(99,12)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (99,8)-(99,9) = ":" │ │ ├── value_loc: (99,9)-(99,12) = "foo" │ │ ├── closing_loc: ∅ @@ -1503,7 +1503,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ SymbolNode (location: (101,8)-(101,12)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (101,8)-(101,9) = ":" │ │ ├── value_loc: (101,9)-(101,12) = "foo" │ │ ├── closing_loc: ∅ @@ -1534,7 +1534,7 @@ │ │ └── @ AssocNode (location: (103,4)-(103,11)) │ │ ├── key: │ │ │ @ SymbolNode (location: (103,4)-(103,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (103,4)-(103,5) = "\"" │ │ │ ├── value_loc: (103,5)-(103,6) = "a" │ │ │ ├── closing_loc: (103,6)-(103,8) = "\":" @@ -1562,7 +1562,7 @@ │ │ └── @ AssocNode (location: (105,4)-(105,28)) │ │ ├── key: │ │ │ @ SymbolNode (location: (105,4)-(105,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (105,4)-(105,7) = "bar" │ │ │ ├── closing_loc: (105,7)-(105,8) = ":" @@ -1574,7 +1574,7 @@ │ │ │ │ └── @ AssocNode (location: (105,11)-(105,26)) │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (105,11)-(105,15)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (105,11)-(105,14) = "baz" │ │ │ │ │ ├── closing_loc: (105,14)-(105,15) = ":" @@ -1619,7 +1619,7 @@ │ │ └── @ AssocNode (location: (107,4)-(107,24)) │ │ ├── key: │ │ │ @ SymbolNode (location: (107,4)-(107,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (107,4)-(107,7) = "bar" │ │ │ ├── closing_loc: (107,7)-(107,8) = ":" @@ -1893,7 +1893,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ SymbolNode (location: (119,4)-(119,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (119,4)-(119,5) = ":" │ │ │ ├── value_loc: (119,5)-(119,6) = "a" │ │ │ ├── closing_loc: ∅ @@ -1969,7 +1969,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 3) │ │ ├── @ SymbolNode (location: (126,4)-(126,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (126,4)-(126,5) = ":" │ │ │ ├── value_loc: (126,5)-(126,6) = "a" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/methods.txt b/test/prism/snapshots/methods.txt index 9e0e0548e8137d..c4f4b70f505014 100644 --- a/test/prism/snapshots/methods.txt +++ b/test/prism/snapshots/methods.txt @@ -842,7 +842,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ SymbolNode (location: (99,7)-(99,10)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (99,7)-(99,8) = ":" │ │ │ │ ├── value_loc: (99,8)-(99,10) = "hi" │ │ │ │ ├── closing_loc: ∅ @@ -850,7 +850,7 @@ │ │ │ ├── consequent: ∅ │ │ │ └── end_keyword_loc: ∅ │ │ └── @ SymbolNode (location: (100,0)-(100,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (100,0)-(100,1) = ":" │ │ ├── value_loc: (100,1)-(100,4) = "bye" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/patterns.txt b/test/prism/snapshots/patterns.txt index 843a1fc6a71412..93333ce78554ba 100644 --- a/test/prism/snapshots/patterns.txt +++ b/test/prism/snapshots/patterns.txt @@ -101,7 +101,7 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ SymbolNode (location: (6,7)-(6,11)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (6,7)-(6,8) = ":" │ │ ├── value_loc: (6,8)-(6,11) = "foo" │ │ ├── closing_loc: ∅ @@ -121,7 +121,7 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ SymbolNode (location: (7,7)-(7,14)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (7,7)-(7,10) = "%s[" │ │ ├── value_loc: (7,10)-(7,13) = "foo" │ │ ├── closing_loc: (7,13)-(7,14) = "]" @@ -141,7 +141,7 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ SymbolNode (location: (8,7)-(8,13)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (8,7)-(8,9) = ":\"" │ │ ├── value_loc: (8,9)-(8,12) = "foo" │ │ ├── closing_loc: (8,12)-(8,13) = "\"" @@ -224,7 +224,7 @@ │ │ ├── flags: ∅ │ │ ├── elements: (length: 1) │ │ │ └── @ SymbolNode (location: (12,10)-(12,13)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (12,10)-(12,13) = "foo" │ │ │ ├── closing_loc: ∅ @@ -249,7 +249,7 @@ │ │ ├── flags: ∅ │ │ ├── elements: (length: 1) │ │ │ └── @ SymbolNode (location: (13,10)-(13,13)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (13,10)-(13,13) = "foo" │ │ │ ├── closing_loc: ∅ @@ -615,14 +615,14 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ SymbolNode (location: (32,7)-(32,11)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (32,7)-(32,8) = ":" │ │ │ ├── value_loc: (32,8)-(32,11) = "foo" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "foo" │ │ ├── right: │ │ │ @ SymbolNode (location: (32,15)-(32,19)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (32,15)-(32,16) = ":" │ │ │ ├── value_loc: (32,16)-(32,19) = "foo" │ │ │ ├── closing_loc: ∅ @@ -646,14 +646,14 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ SymbolNode (location: (33,7)-(33,14)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (33,7)-(33,10) = "%s[" │ │ │ ├── value_loc: (33,10)-(33,13) = "foo" │ │ │ ├── closing_loc: (33,13)-(33,14) = "]" │ │ │ └── unescaped: "foo" │ │ ├── right: │ │ │ @ SymbolNode (location: (33,18)-(33,25)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (33,18)-(33,21) = "%s[" │ │ │ ├── value_loc: (33,21)-(33,24) = "foo" │ │ │ ├── closing_loc: (33,24)-(33,25) = "]" @@ -677,14 +677,14 @@ │ │ ├── flags: ∅ │ │ ├── left: │ │ │ @ SymbolNode (location: (34,7)-(34,13)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (34,7)-(34,9) = ":\"" │ │ │ ├── value_loc: (34,9)-(34,12) = "foo" │ │ │ ├── closing_loc: (34,12)-(34,13) = "\"" │ │ │ └── unescaped: "foo" │ │ ├── right: │ │ │ @ SymbolNode (location: (34,17)-(34,23)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (34,17)-(34,19) = ":\"" │ │ │ ├── value_loc: (34,19)-(34,22) = "foo" │ │ │ ├── closing_loc: (34,22)-(34,23) = "\"" @@ -804,7 +804,7 @@ │ │ │ ├── flags: ∅ │ │ │ ├── elements: (length: 1) │ │ │ │ └── @ SymbolNode (location: (38,10)-(38,13)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (38,10)-(38,13) = "foo" │ │ │ │ ├── closing_loc: ∅ @@ -816,7 +816,7 @@ │ │ │ ├── flags: ∅ │ │ │ ├── elements: (length: 1) │ │ │ │ └── @ SymbolNode (location: (38,21)-(38,24)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (38,21)-(38,24) = "foo" │ │ │ │ ├── closing_loc: ∅ @@ -845,7 +845,7 @@ │ │ │ ├── flags: ∅ │ │ │ ├── elements: (length: 1) │ │ │ │ └── @ SymbolNode (location: (39,10)-(39,13)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (39,10)-(39,13) = "foo" │ │ │ │ ├── closing_loc: ∅ @@ -857,7 +857,7 @@ │ │ │ ├── flags: ∅ │ │ │ ├── elements: (length: 1) │ │ │ │ └── @ SymbolNode (location: (39,21)-(39,24)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (39,21)-(39,24) = "foo" │ │ │ │ ├── closing_loc: ∅ @@ -2435,7 +2435,7 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ SymbolNode (location: (105,7)-(105,11)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (105,7)-(105,8) = ":" │ │ ├── value_loc: (105,8)-(105,11) = "foo" │ │ ├── closing_loc: ∅ @@ -2455,7 +2455,7 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ SymbolNode (location: (106,7)-(106,14)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (106,7)-(106,10) = "%s[" │ │ ├── value_loc: (106,10)-(106,13) = "foo" │ │ ├── closing_loc: (106,13)-(106,14) = "]" @@ -2475,7 +2475,7 @@ │ │ └── block: ∅ │ ├── pattern: │ │ @ SymbolNode (location: (107,7)-(107,13)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (107,7)-(107,9) = ":\"" │ │ ├── value_loc: (107,9)-(107,12) = "foo" │ │ ├── closing_loc: (107,12)-(107,13) = "\"" @@ -2558,7 +2558,7 @@ │ │ ├── flags: ∅ │ │ ├── elements: (length: 1) │ │ │ └── @ SymbolNode (location: (111,10)-(111,13)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (111,10)-(111,13) = "foo" │ │ │ ├── closing_loc: ∅ @@ -2583,7 +2583,7 @@ │ │ ├── flags: ∅ │ │ ├── elements: (length: 1) │ │ │ └── @ SymbolNode (location: (112,10)-(112,13)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (112,10)-(112,13) = "foo" │ │ │ ├── closing_loc: ∅ @@ -2969,7 +2969,7 @@ │ │ └── @ InNode (location: (132,10)-(132,22)) │ │ ├── pattern: │ │ │ @ SymbolNode (location: (132,13)-(132,17)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (132,13)-(132,14) = ":" │ │ │ ├── value_loc: (132,14)-(132,17) = "foo" │ │ │ ├── closing_loc: ∅ @@ -2996,7 +2996,7 @@ │ │ └── @ InNode (location: (133,10)-(133,25)) │ │ ├── pattern: │ │ │ @ SymbolNode (location: (133,13)-(133,20)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (133,13)-(133,16) = "%s[" │ │ │ ├── value_loc: (133,16)-(133,19) = "foo" │ │ │ ├── closing_loc: (133,19)-(133,20) = "]" @@ -3023,7 +3023,7 @@ │ │ └── @ InNode (location: (134,10)-(134,24)) │ │ ├── pattern: │ │ │ @ SymbolNode (location: (134,13)-(134,19)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (134,13)-(134,15) = ":\"" │ │ │ ├── value_loc: (134,15)-(134,18) = "foo" │ │ │ ├── closing_loc: (134,18)-(134,19) = "\"" @@ -3134,7 +3134,7 @@ │ │ │ ├── flags: ∅ │ │ │ ├── elements: (length: 1) │ │ │ │ └── @ SymbolNode (location: (138,16)-(138,19)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (138,16)-(138,19) = "foo" │ │ │ │ ├── closing_loc: ∅ @@ -3166,7 +3166,7 @@ │ │ │ ├── flags: ∅ │ │ │ ├── elements: (length: 1) │ │ │ │ └── @ SymbolNode (location: (139,16)-(139,19)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (139,16)-(139,19) = "foo" │ │ │ │ ├── closing_loc: ∅ @@ -3718,7 +3718,7 @@ │ │ │ │ @ StatementsNode (location: (159,13)-(159,17)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ SymbolNode (location: (159,13)-(159,17)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (159,13)-(159,14) = ":" │ │ │ │ ├── value_loc: (159,14)-(159,17) = "foo" │ │ │ │ ├── closing_loc: ∅ @@ -3757,7 +3757,7 @@ │ │ │ │ @ StatementsNode (location: (160,13)-(160,20)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ SymbolNode (location: (160,13)-(160,20)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (160,13)-(160,16) = "%s[" │ │ │ │ ├── value_loc: (160,16)-(160,19) = "foo" │ │ │ │ ├── closing_loc: (160,19)-(160,20) = "]" @@ -3796,7 +3796,7 @@ │ │ │ │ @ StatementsNode (location: (161,13)-(161,19)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ SymbolNode (location: (161,13)-(161,19)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (161,13)-(161,15) = ":\"" │ │ │ │ ├── value_loc: (161,15)-(161,18) = "foo" │ │ │ │ ├── closing_loc: (161,18)-(161,19) = "\"" @@ -3955,7 +3955,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ ├── elements: (length: 1) │ │ │ │ │ └── @ SymbolNode (location: (165,16)-(165,19)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (165,16)-(165,19) = "foo" │ │ │ │ │ ├── closing_loc: ∅ @@ -3999,7 +3999,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ ├── elements: (length: 1) │ │ │ │ │ └── @ SymbolNode (location: (166,16)-(166,19)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (166,16)-(166,19) = "foo" │ │ │ │ │ ├── closing_loc: ∅ @@ -4577,7 +4577,7 @@ │ │ │ └── @ AssocNode (location: (189,2)-(191,3)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (189,2)-(189,6)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (189,2)-(189,5) = "bar" │ │ │ │ ├── closing_loc: (189,5)-(189,6) = ":" @@ -4591,7 +4591,7 @@ │ │ │ │ │ └── @ AssocNode (location: (190,4)-(190,12)) │ │ │ │ │ ├── key: │ │ │ │ │ │ @ SymbolNode (location: (190,4)-(190,10)) - │ │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ │ ├── value_loc: (190,4)-(190,9) = "value" │ │ │ │ │ │ ├── closing_loc: (190,9)-(190,10) = ":" @@ -4752,7 +4752,7 @@ │ │ │ │ └── @ AssocNode (location: (202,15)-(202,17)) │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (202,15)-(202,17)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (202,15)-(202,16) = "x" │ │ │ │ │ ├── closing_loc: (202,16)-(202,17) = ":" diff --git a/test/prism/snapshots/ranges.txt b/test/prism/snapshots/ranges.txt index 317f4164b35f43..906bf2de6bbe1d 100644 --- a/test/prism/snapshots/ranges.txt +++ b/test/prism/snapshots/ranges.txt @@ -74,7 +74,7 @@ │ │ └── @ AssocNode (location: (9,2)-(9,13)) │ │ ├── key: │ │ │ @ SymbolNode (location: (9,2)-(9,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (9,2)-(9,5) = "foo" │ │ │ ├── closing_loc: (9,5)-(9,6) = ":" @@ -125,7 +125,7 @@ │ │ └── @ AssocNode (location: (15,2)-(15,12)) │ │ ├── key: │ │ │ @ SymbolNode (location: (15,2)-(15,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (15,2)-(15,5) = "foo" │ │ │ ├── closing_loc: (15,5)-(15,6) = ":" diff --git a/test/prism/snapshots/rescue.txt b/test/prism/snapshots/rescue.txt index f7675ce927d70d..9627d4d9ce944c 100644 --- a/test/prism/snapshots/rescue.txt +++ b/test/prism/snapshots/rescue.txt @@ -349,7 +349,7 @@ │ │ │ └── @ AssocNode (location: (29,4)-(29,6)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (29,4)-(29,6)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (29,4)-(29,5) = "b" │ │ │ │ ├── closing_loc: (29,5)-(29,6) = ":" diff --git a/test/prism/snapshots/seattlerb/TestRubyParserShared.txt b/test/prism/snapshots/seattlerb/TestRubyParserShared.txt index 64030f3aeb023f..123241054322c2 100644 --- a/test/prism/snapshots/seattlerb/TestRubyParserShared.txt +++ b/test/prism/snapshots/seattlerb/TestRubyParserShared.txt @@ -12,13 +12,13 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ SymbolNode (location: (7,0)-(7,5)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (7,0)-(7,5) = "line2" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "line2" │ │ └── @ SymbolNode (location: (8,0)-(8,5)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (8,0)-(8,5) = "line3" │ │ ├── closing_loc: ∅ @@ -56,13 +56,13 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ SymbolNode (location: (27,0)-(27,5)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (27,0)-(27,5) = "line2" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "line2" │ │ └── @ SymbolNode (location: (28,0)-(28,5)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (28,0)-(28,5) = "line3" │ │ ├── closing_loc: ∅ @@ -101,13 +101,13 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ SymbolNode (location: (47,0)-(47,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (47,0)-(47,1) = ":" │ │ │ ├── value_loc: (47,1)-(47,6) = "line2" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "line2" │ │ └── @ SymbolNode (location: (48,0)-(48,6)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (48,0)-(48,1) = ":" │ │ ├── value_loc: (48,1)-(48,6) = "line3" │ │ ├── closing_loc: ∅ @@ -289,13 +289,13 @@ │ │ │ ├── flags: ∅ │ │ │ ├── elements: (length: 2) │ │ │ │ ├── @ SymbolNode (location: (76,4)-(76,10)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (76,4)-(76,5) = ":" │ │ │ │ │ ├── value_loc: (76,5)-(76,10) = "line3" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "line3" │ │ │ │ └── @ SymbolNode (location: (77,4)-(77,10)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (77,4)-(77,5) = ":" │ │ │ │ ├── value_loc: (77,5)-(77,10) = "line4" │ │ │ │ ├── closing_loc: ∅ @@ -346,13 +346,13 @@ │ ├── flags: ∅ │ └── arguments: (length: 2) │ ├── @ SymbolNode (location: (90,0)-(90,6)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (90,0)-(90,1) = ":" │ │ ├── value_loc: (90,1)-(90,6) = "line2" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "line2" │ └── @ SymbolNode (location: (91,0)-(91,6)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (91,0)-(91,1) = ":" │ ├── value_loc: (91,1)-(91,6) = "line3" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/alias_resword.txt b/test/prism/snapshots/seattlerb/alias_resword.txt index bf475a5c71dda3..99ed696c6873b9 100644 --- a/test/prism/snapshots/seattlerb/alias_resword.txt +++ b/test/prism/snapshots/seattlerb/alias_resword.txt @@ -6,14 +6,14 @@ └── @ AliasMethodNode (location: (1,0)-(1,12)) ├── new_name: │ @ SymbolNode (location: (1,6)-(1,8)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: ∅ │ ├── value_loc: (1,6)-(1,8) = "in" │ ├── closing_loc: ∅ │ └── unescaped: "in" ├── old_name: │ @ SymbolNode (location: (1,9)-(1,12)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: ∅ │ ├── value_loc: (1,9)-(1,12) = "out" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/assoc__bare.txt b/test/prism/snapshots/seattlerb/assoc__bare.txt index 8f6fe48b473804..28e4f713c51462 100644 --- a/test/prism/snapshots/seattlerb/assoc__bare.txt +++ b/test/prism/snapshots/seattlerb/assoc__bare.txt @@ -9,7 +9,7 @@ │ └── @ AssocNode (location: (1,2)-(1,4)) │ ├── key: │ │ @ SymbolNode (location: (1,2)-(1,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,2)-(1,3) = "y" │ │ ├── closing_loc: (1,3)-(1,4) = ":" diff --git a/test/prism/snapshots/seattlerb/assoc_label.txt b/test/prism/snapshots/seattlerb/assoc_label.txt index c6d43270266c70..725a74f9114852 100644 --- a/test/prism/snapshots/seattlerb/assoc_label.txt +++ b/test/prism/snapshots/seattlerb/assoc_label.txt @@ -20,7 +20,7 @@ │ └── @ AssocNode (location: (1,2)-(1,5)) │ ├── key: │ │ @ SymbolNode (location: (1,2)-(1,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,2)-(1,3) = "b" │ │ ├── closing_loc: (1,3)-(1,4) = ":" diff --git a/test/prism/snapshots/seattlerb/block_command_operation_colon.txt b/test/prism/snapshots/seattlerb/block_command_operation_colon.txt index 5496fb7b47f043..d08fe7ece10b4e 100644 --- a/test/prism/snapshots/seattlerb/block_command_operation_colon.txt +++ b/test/prism/snapshots/seattlerb/block_command_operation_colon.txt @@ -18,7 +18,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ SymbolNode (location: (1,2)-(1,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,2)-(1,3) = ":" │ │ ├── value_loc: (1,3)-(1,4) = "b" │ │ ├── closing_loc: ∅ @@ -41,7 +41,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ SymbolNode (location: (1,15)-(1,17)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,15)-(1,16) = ":" │ ├── value_loc: (1,16)-(1,17) = "d" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/block_command_operation_dot.txt b/test/prism/snapshots/seattlerb/block_command_operation_dot.txt index f6a52af23d071f..a603c6aefcfebe 100644 --- a/test/prism/snapshots/seattlerb/block_command_operation_dot.txt +++ b/test/prism/snapshots/seattlerb/block_command_operation_dot.txt @@ -18,7 +18,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ SymbolNode (location: (1,2)-(1,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,2)-(1,3) = ":" │ │ ├── value_loc: (1,3)-(1,4) = "b" │ │ ├── closing_loc: ∅ @@ -41,7 +41,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ SymbolNode (location: (1,14)-(1,16)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,14)-(1,15) = ":" │ ├── value_loc: (1,15)-(1,16) = "d" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/block_kwarg_lvar.txt b/test/prism/snapshots/seattlerb/block_kwarg_lvar.txt index 05c6c9c323b4c5..360a3e51af47f2 100644 --- a/test/prism/snapshots/seattlerb/block_kwarg_lvar.txt +++ b/test/prism/snapshots/seattlerb/block_kwarg_lvar.txt @@ -31,7 +31,7 @@ │ │ │ ├── name_loc: (1,6)-(1,9) = "kw:" │ │ │ └── value: │ │ │ @ SymbolNode (location: (1,10)-(1,14)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,10)-(1,11) = ":" │ │ │ ├── value_loc: (1,11)-(1,14) = "val" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/block_kwarg_lvar_multiple.txt b/test/prism/snapshots/seattlerb/block_kwarg_lvar_multiple.txt index a05ca0c380032e..f651eef4adaf33 100644 --- a/test/prism/snapshots/seattlerb/block_kwarg_lvar_multiple.txt +++ b/test/prism/snapshots/seattlerb/block_kwarg_lvar_multiple.txt @@ -31,7 +31,7 @@ │ │ │ │ ├── name_loc: (1,6)-(1,9) = "kw:" │ │ │ │ └── value: │ │ │ │ @ SymbolNode (location: (1,10)-(1,14)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (1,10)-(1,11) = ":" │ │ │ │ ├── value_loc: (1,11)-(1,14) = "val" │ │ │ │ ├── closing_loc: ∅ @@ -42,7 +42,7 @@ │ │ │ ├── name_loc: (1,16)-(1,20) = "kw2:" │ │ │ └── value: │ │ │ @ SymbolNode (location: (1,21)-(1,26)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,21)-(1,22) = ":" │ │ │ ├── value_loc: (1,22)-(1,26) = "val2" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/block_optarg.txt b/test/prism/snapshots/seattlerb/block_optarg.txt index 3328ee30e3ed78..40e334d1dad31a 100644 --- a/test/prism/snapshots/seattlerb/block_optarg.txt +++ b/test/prism/snapshots/seattlerb/block_optarg.txt @@ -29,7 +29,7 @@ │ │ │ ├── operator_loc: (1,7)-(1,8) = "=" │ │ │ └── value: │ │ │ @ SymbolNode (location: (1,9)-(1,11)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,9)-(1,10) = ":" │ │ │ ├── value_loc: (1,10)-(1,11) = "c" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/block_reg_optarg.txt b/test/prism/snapshots/seattlerb/block_reg_optarg.txt index 47d19852002ed8..764374957679e4 100644 --- a/test/prism/snapshots/seattlerb/block_reg_optarg.txt +++ b/test/prism/snapshots/seattlerb/block_reg_optarg.txt @@ -32,7 +32,7 @@ │ │ │ ├── operator_loc: (1,10)-(1,11) = "=" │ │ │ └── value: │ │ │ @ SymbolNode (location: (1,12)-(1,14)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,12)-(1,13) = ":" │ │ │ ├── value_loc: (1,13)-(1,14) = "d" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/bug_215.txt b/test/prism/snapshots/seattlerb/bug_215.txt index 443b9b7358e93b..de7716335e9ffd 100644 --- a/test/prism/snapshots/seattlerb/bug_215.txt +++ b/test/prism/snapshots/seattlerb/bug_215.txt @@ -6,7 +6,7 @@ └── @ UndefNode (location: (1,0)-(1,13)) ├── names: (length: 1) │ └── @ SymbolNode (location: (1,6)-(1,13)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,6)-(1,9) = "%s(" │ ├── value_loc: (1,9)-(1,12) = "foo" │ ├── closing_loc: (1,12)-(1,13) = ")" diff --git a/test/prism/snapshots/seattlerb/bug_249.txt b/test/prism/snapshots/seattlerb/bug_249.txt index 9b0e0d248224c5..bc57cfb2ab0fd5 100644 --- a/test/prism/snapshots/seattlerb/bug_249.txt +++ b/test/prism/snapshots/seattlerb/bug_249.txt @@ -71,7 +71,7 @@ │ └── @ AssocNode (location: (4,11)-(4,28)) │ ├── key: │ │ @ SymbolNode (location: (4,11)-(4,14)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (4,11)-(4,12) = ":" │ │ ├── value_loc: (4,12)-(4,14) = "at" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/bug_case_when_regexp.txt b/test/prism/snapshots/seattlerb/bug_case_when_regexp.txt index 6479334c8e22b0..d7b071100dde08 100644 --- a/test/prism/snapshots/seattlerb/bug_case_when_regexp.txt +++ b/test/prism/snapshots/seattlerb/bug_case_when_regexp.txt @@ -6,7 +6,7 @@ └── @ CaseNode (location: (1,0)-(1,26)) ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "x" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/bug_hash_args.txt b/test/prism/snapshots/seattlerb/bug_hash_args.txt index 08ae7df3197c25..6f17e88714a682 100644 --- a/test/prism/snapshots/seattlerb/bug_hash_args.txt +++ b/test/prism/snapshots/seattlerb/bug_hash_args.txt @@ -15,7 +15,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 2) │ ├── @ SymbolNode (location: (1,4)-(1,8)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,4)-(1,5) = ":" │ │ ├── value_loc: (1,5)-(1,8) = "bar" │ │ ├── closing_loc: ∅ @@ -26,7 +26,7 @@ │ └── @ AssocNode (location: (1,10)-(1,18)) │ ├── key: │ │ @ SymbolNode (location: (1,10)-(1,14)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,10)-(1,13) = "baz" │ │ ├── closing_loc: (1,13)-(1,14) = ":" diff --git a/test/prism/snapshots/seattlerb/bug_hash_args_trailing_comma.txt b/test/prism/snapshots/seattlerb/bug_hash_args_trailing_comma.txt index 9c984f81a1ab06..e7256b337b95ea 100644 --- a/test/prism/snapshots/seattlerb/bug_hash_args_trailing_comma.txt +++ b/test/prism/snapshots/seattlerb/bug_hash_args_trailing_comma.txt @@ -15,7 +15,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 2) │ ├── @ SymbolNode (location: (1,4)-(1,8)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,4)-(1,5) = ":" │ │ ├── value_loc: (1,5)-(1,8) = "bar" │ │ ├── closing_loc: ∅ @@ -26,7 +26,7 @@ │ └── @ AssocNode (location: (1,10)-(1,18)) │ ├── key: │ │ @ SymbolNode (location: (1,10)-(1,14)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,10)-(1,13) = "baz" │ │ ├── closing_loc: (1,13)-(1,14) = ":" diff --git a/test/prism/snapshots/seattlerb/call_arg_assoc_kwsplat.txt b/test/prism/snapshots/seattlerb/call_arg_assoc_kwsplat.txt index a9399ca184b56f..a16c652ae4245a 100644 --- a/test/prism/snapshots/seattlerb/call_arg_assoc_kwsplat.txt +++ b/test/prism/snapshots/seattlerb/call_arg_assoc_kwsplat.txt @@ -22,7 +22,7 @@ │ ├── @ AssocNode (location: (1,5)-(1,10)) │ │ ├── key: │ │ │ @ SymbolNode (location: (1,5)-(1,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (1,5)-(1,7) = "kw" │ │ │ ├── closing_loc: (1,7)-(1,8) = ":" diff --git a/test/prism/snapshots/seattlerb/call_args_assoc_quoted.txt b/test/prism/snapshots/seattlerb/call_args_assoc_quoted.txt index 41ec2209e1aafa..cb048dba8f70a0 100644 --- a/test/prism/snapshots/seattlerb/call_args_assoc_quoted.txt +++ b/test/prism/snapshots/seattlerb/call_args_assoc_quoted.txt @@ -62,7 +62,7 @@ │ │ └── @ AssocNode (location: (3,2)-(3,8)) │ │ ├── key: │ │ │ @ SymbolNode (location: (3,2)-(3,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (3,2)-(3,3) = "\"" │ │ │ ├── value_loc: (3,3)-(3,4) = "k" │ │ │ ├── closing_loc: (3,4)-(3,6) = "\":" @@ -90,7 +90,7 @@ │ └── @ AssocNode (location: (5,2)-(5,8)) │ ├── key: │ │ @ SymbolNode (location: (5,2)-(5,6)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (5,2)-(5,3) = "'" │ │ ├── value_loc: (5,3)-(5,4) = "k" │ │ ├── closing_loc: (5,4)-(5,6) = "':" diff --git a/test/prism/snapshots/seattlerb/call_array_arg.txt b/test/prism/snapshots/seattlerb/call_array_arg.txt index 1bca15afca6a81..3558ad0f0b98f1 100644 --- a/test/prism/snapshots/seattlerb/call_array_arg.txt +++ b/test/prism/snapshots/seattlerb/call_array_arg.txt @@ -20,13 +20,13 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ SymbolNode (location: (1,6)-(1,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,6)-(1,7) = ":" │ │ │ ├── value_loc: (1,7)-(1,8) = "b" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "b" │ │ └── @ SymbolNode (location: (1,10)-(1,12)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,10)-(1,11) = ":" │ │ ├── value_loc: (1,11)-(1,12) = "c" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/call_array_lit_inline_hash.txt b/test/prism/snapshots/seattlerb/call_array_lit_inline_hash.txt index e13af7c62f2931..e1bd056fd4c8e3 100644 --- a/test/prism/snapshots/seattlerb/call_array_lit_inline_hash.txt +++ b/test/prism/snapshots/seattlerb/call_array_lit_inline_hash.txt @@ -18,7 +18,7 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ SymbolNode (location: (1,3)-(1,5)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,3)-(1,4) = ":" │ │ │ ├── value_loc: (1,4)-(1,5) = "b" │ │ │ ├── closing_loc: ∅ @@ -29,7 +29,7 @@ │ │ └── @ AssocNode (location: (1,7)-(1,14)) │ │ ├── key: │ │ │ @ SymbolNode (location: (1,7)-(1,9)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,7)-(1,8) = ":" │ │ │ ├── value_loc: (1,8)-(1,9) = "c" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/call_assoc_new.txt b/test/prism/snapshots/seattlerb/call_assoc_new.txt index 26f7c6fc43e021..bd31becacabd58 100644 --- a/test/prism/snapshots/seattlerb/call_assoc_new.txt +++ b/test/prism/snapshots/seattlerb/call_assoc_new.txt @@ -20,7 +20,7 @@ │ └── @ AssocNode (location: (1,2)-(1,5)) │ ├── key: │ │ @ SymbolNode (location: (1,2)-(1,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,2)-(1,3) = "a" │ │ ├── closing_loc: (1,3)-(1,4) = ":" diff --git a/test/prism/snapshots/seattlerb/call_assoc_new_if_multiline.txt b/test/prism/snapshots/seattlerb/call_assoc_new_if_multiline.txt index 65d725f3207135..6f2b1fa876bc34 100644 --- a/test/prism/snapshots/seattlerb/call_assoc_new_if_multiline.txt +++ b/test/prism/snapshots/seattlerb/call_assoc_new_if_multiline.txt @@ -20,7 +20,7 @@ │ └── @ AssocNode (location: (1,2)-(5,3)) │ ├── key: │ │ @ SymbolNode (location: (1,2)-(1,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,2)-(1,3) = "b" │ │ ├── closing_loc: (1,3)-(1,4) = ":" @@ -30,7 +30,7 @@ │ │ ├── if_keyword_loc: (1,5)-(1,7) = "if" │ │ ├── predicate: │ │ │ @ SymbolNode (location: (1,8)-(1,10)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,8)-(1,9) = ":" │ │ │ ├── value_loc: (1,9)-(1,10) = "c" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in.txt b/test/prism/snapshots/seattlerb/case_in.txt index 96a76174d2ef59..069dec19387dd5 100644 --- a/test/prism/snapshots/seattlerb/case_in.txt +++ b/test/prism/snapshots/seattlerb/case_in.txt @@ -6,7 +6,7 @@ ├── @ CaseMatchNode (location: (1,0)-(3,3)) │ ├── predicate: │ │ @ SymbolNode (location: (1,5)-(1,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,5)-(1,6) = ":" │ │ ├── value_loc: (1,6)-(1,7) = "a" │ │ ├── closing_loc: ∅ @@ -20,7 +20,7 @@ │ │ │ │ └── @ AssocNode (location: (2,4)-(2,8)) │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (2,4)-(2,8)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (2,4)-(2,5) = "\"" │ │ │ │ │ ├── value_loc: (2,5)-(2,6) = "b" │ │ │ │ │ ├── closing_loc: (2,6)-(2,8) = "\":" @@ -44,7 +44,7 @@ ├── @ CaseMatchNode (location: (5,0)-(7,3)) │ ├── predicate: │ │ @ SymbolNode (location: (5,5)-(5,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (5,5)-(5,6) = ":" │ │ ├── value_loc: (5,6)-(5,7) = "a" │ │ ├── closing_loc: ∅ @@ -56,13 +56,13 @@ │ │ │ ├── flags: ∅ │ │ │ ├── elements: (length: 2) │ │ │ │ ├── @ SymbolNode (location: (6,6)-(6,7)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (6,6)-(6,7) = "a" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "a" │ │ │ │ └── @ SymbolNode (location: (6,8)-(6,9)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (6,8)-(6,9) = "b" │ │ │ │ ├── closing_loc: ∅ @@ -78,7 +78,7 @@ ├── @ CaseMatchNode (location: (9,0)-(11,3)) │ ├── predicate: │ │ @ SymbolNode (location: (9,5)-(9,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (9,5)-(9,6) = ":" │ │ ├── value_loc: (9,6)-(9,7) = "a" │ │ ├── closing_loc: ∅ @@ -112,7 +112,7 @@ ├── @ CaseMatchNode (location: (13,0)-(15,3)) │ ├── predicate: │ │ @ SymbolNode (location: (13,5)-(13,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (13,5)-(13,6) = ":" │ │ ├── value_loc: (13,6)-(13,7) = "a" │ │ ├── closing_loc: ∅ @@ -124,13 +124,13 @@ │ │ │ ├── flags: ∅ │ │ │ ├── elements: (length: 2) │ │ │ │ ├── @ SymbolNode (location: (14,6)-(14,7)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (14,6)-(14,7) = "a" │ │ │ │ │ ├── closing_loc: ∅ │ │ │ │ │ └── unescaped: "a" │ │ │ │ └── @ SymbolNode (location: (14,8)-(14,9)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (14,8)-(14,9) = "b" │ │ │ │ ├── closing_loc: ∅ @@ -146,7 +146,7 @@ ├── @ CaseMatchNode (location: (17,0)-(19,3)) │ ├── predicate: │ │ @ SymbolNode (location: (17,5)-(17,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (17,5)-(17,6) = ":" │ │ ├── value_loc: (17,6)-(17,7) = "a" │ │ ├── closing_loc: ∅ @@ -180,7 +180,7 @@ ├── @ CaseMatchNode (location: (21,0)-(23,3)) │ ├── predicate: │ │ @ SymbolNode (location: (21,5)-(21,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (21,5)-(21,6) = ":" │ │ ├── value_loc: (21,6)-(21,7) = "a" │ │ ├── closing_loc: ∅ @@ -204,7 +204,7 @@ ├── @ CaseMatchNode (location: (25,0)-(27,3)) │ ├── predicate: │ │ @ SymbolNode (location: (25,5)-(25,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (25,5)-(25,6) = ":" │ │ ├── value_loc: (25,6)-(25,7) = "a" │ │ ├── closing_loc: ∅ @@ -228,7 +228,7 @@ ├── @ CaseMatchNode (location: (29,0)-(31,3)) │ ├── predicate: │ │ @ SymbolNode (location: (29,5)-(29,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (29,5)-(29,6) = ":" │ │ ├── value_loc: (29,6)-(29,7) = "a" │ │ ├── closing_loc: ∅ @@ -252,7 +252,7 @@ ├── @ CaseMatchNode (location: (33,0)-(35,3)) │ ├── predicate: │ │ @ SymbolNode (location: (33,5)-(33,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (33,5)-(33,6) = ":" │ │ ├── value_loc: (33,6)-(33,7) = "a" │ │ ├── closing_loc: ∅ @@ -278,7 +278,7 @@ ├── @ CaseMatchNode (location: (37,0)-(39,3)) │ ├── predicate: │ │ @ SymbolNode (location: (37,5)-(37,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (37,5)-(37,6) = ":" │ │ ├── value_loc: (37,6)-(37,7) = "a" │ │ ├── closing_loc: ∅ @@ -297,7 +297,7 @@ ├── @ CaseMatchNode (location: (41,0)-(43,3)) │ ├── predicate: │ │ @ SymbolNode (location: (41,5)-(41,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (41,5)-(41,6) = ":" │ │ ├── value_loc: (41,6)-(41,7) = "a" │ │ ├── closing_loc: ∅ @@ -323,7 +323,7 @@ ├── @ CaseMatchNode (location: (45,0)-(47,3)) │ ├── predicate: │ │ @ SymbolNode (location: (45,5)-(45,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (45,5)-(45,6) = ":" │ │ ├── value_loc: (45,6)-(45,7) = "a" │ │ ├── closing_loc: ∅ @@ -346,7 +346,7 @@ ├── @ CaseMatchNode (location: (49,0)-(51,3)) │ ├── predicate: │ │ @ SymbolNode (location: (49,5)-(49,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (49,5)-(49,6) = ":" │ │ ├── value_loc: (49,6)-(49,7) = "a" │ │ ├── closing_loc: ∅ @@ -358,7 +358,7 @@ │ │ │ ├── constant: ∅ │ │ │ ├── requireds: (length: 1) │ │ │ │ └── @ SymbolNode (location: (50,3)-(50,5)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (50,3)-(50,4) = ":" │ │ │ │ ├── value_loc: (50,4)-(50,5) = "b" │ │ │ │ ├── closing_loc: ∅ @@ -372,7 +372,7 @@ │ │ │ │ └── depth: 0 │ │ │ ├── posts: (length: 1) │ │ │ │ └── @ SymbolNode (location: (50,11)-(50,13)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (50,11)-(50,12) = ":" │ │ │ │ ├── value_loc: (50,12)-(50,13) = "c" │ │ │ │ ├── closing_loc: ∅ @@ -388,7 +388,7 @@ ├── @ CaseMatchNode (location: (53,0)-(55,3)) │ ├── predicate: │ │ @ SymbolNode (location: (53,5)-(53,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (53,5)-(53,6) = ":" │ │ ├── value_loc: (53,6)-(53,7) = "a" │ │ ├── closing_loc: ∅ @@ -400,7 +400,7 @@ │ │ │ ├── constant: ∅ │ │ │ ├── requireds: (length: 2) │ │ │ │ ├── @ SymbolNode (location: (54,3)-(54,5)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (54,3)-(54,4) = ":" │ │ │ │ │ ├── value_loc: (54,4)-(54,5) = "b" │ │ │ │ │ ├── closing_loc: ∅ @@ -409,7 +409,7 @@ │ │ │ │ ├── constant: ∅ │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ └── @ SymbolNode (location: (54,8)-(54,10)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (54,8)-(54,9) = ":" │ │ │ │ │ ├── value_loc: (54,9)-(54,10) = "c" │ │ │ │ │ ├── closing_loc: ∅ @@ -431,7 +431,7 @@ ├── @ CaseMatchNode (location: (57,0)-(59,3)) │ ├── predicate: │ │ @ SymbolNode (location: (57,5)-(57,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (57,5)-(57,6) = ":" │ │ ├── value_loc: (57,6)-(57,7) = "a" │ │ ├── closing_loc: ∅ @@ -457,7 +457,7 @@ ├── @ CaseMatchNode (location: (61,0)-(63,3)) │ ├── predicate: │ │ @ SymbolNode (location: (61,5)-(61,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (61,5)-(61,6) = ":" │ │ ├── value_loc: (61,6)-(61,7) = "a" │ │ ├── closing_loc: ∅ @@ -498,7 +498,7 @@ ├── @ CaseMatchNode (location: (65,0)-(67,3)) │ ├── predicate: │ │ @ SymbolNode (location: (65,5)-(65,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (65,5)-(65,6) = ":" │ │ ├── value_loc: (65,6)-(65,7) = "a" │ │ ├── closing_loc: ∅ @@ -539,7 +539,7 @@ ├── @ CaseMatchNode (location: (69,0)-(71,3)) │ ├── predicate: │ │ @ SymbolNode (location: (69,5)-(69,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (69,5)-(69,6) = ":" │ │ ├── value_loc: (69,6)-(69,7) = "a" │ │ ├── closing_loc: ∅ @@ -593,7 +593,7 @@ ├── @ CaseMatchNode (location: (73,0)-(75,3)) │ ├── predicate: │ │ @ SymbolNode (location: (73,5)-(73,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (73,5)-(73,6) = ":" │ │ ├── value_loc: (73,6)-(73,7) = "a" │ │ ├── closing_loc: ∅ @@ -605,7 +605,7 @@ │ │ │ ├── constant: ∅ │ │ │ ├── requireds: (length: 4) │ │ │ │ ├── @ SymbolNode (location: (74,4)-(74,6)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (74,4)-(74,5) = ":" │ │ │ │ │ ├── value_loc: (74,5)-(74,6) = "a" │ │ │ │ │ ├── closing_loc: ∅ @@ -620,7 +620,7 @@ │ │ │ │ ├── constant: ∅ │ │ │ │ ├── requireds: (length: 1) │ │ │ │ │ └── @ SymbolNode (location: (74,15)-(74,17)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (74,15)-(74,16) = ":" │ │ │ │ │ ├── value_loc: (74,16)-(74,17) = "d" │ │ │ │ │ ├── closing_loc: ∅ @@ -649,7 +649,7 @@ ├── @ CaseMatchNode (location: (77,0)-(79,3)) │ ├── predicate: │ │ @ SymbolNode (location: (77,5)-(77,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (77,5)-(77,6) = ":" │ │ ├── value_loc: (77,6)-(77,7) = "a" │ │ ├── closing_loc: ∅ @@ -680,7 +680,7 @@ ├── @ CaseMatchNode (location: (81,0)-(83,3)) │ ├── predicate: │ │ @ SymbolNode (location: (81,5)-(81,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (81,5)-(81,6) = ":" │ │ ├── value_loc: (81,6)-(81,7) = "a" │ │ ├── closing_loc: ∅ @@ -695,7 +695,7 @@ │ │ │ │ │ ├── constant: ∅ │ │ │ │ │ ├── requireds: (length: 2) │ │ │ │ │ │ ├── @ SymbolNode (location: (82,5)-(82,7)) - │ │ │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ │ │ ├── opening_loc: (82,5)-(82,6) = ":" │ │ │ │ │ │ │ ├── value_loc: (82,6)-(82,7) = "b" │ │ │ │ │ │ │ ├── closing_loc: ∅ @@ -711,7 +711,7 @@ │ │ │ │ ├── constant: ∅ │ │ │ │ ├── requireds: (length: 2) │ │ │ │ │ ├── @ SymbolNode (location: (82,14)-(82,16)) - │ │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ │ ├── opening_loc: (82,14)-(82,15) = ":" │ │ │ │ │ │ ├── value_loc: (82,15)-(82,16) = "d" │ │ │ │ │ │ ├── closing_loc: ∅ @@ -739,7 +739,7 @@ ├── @ CaseMatchNode (location: (85,0)-(87,3)) │ ├── predicate: │ │ @ SymbolNode (location: (85,5)-(85,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (85,5)-(85,6) = ":" │ │ ├── value_loc: (85,6)-(85,7) = "a" │ │ ├── closing_loc: ∅ @@ -763,7 +763,7 @@ ├── @ CaseMatchNode (location: (89,0)-(91,3)) │ ├── predicate: │ │ @ SymbolNode (location: (89,5)-(89,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (89,5)-(89,6) = ":" │ │ ├── value_loc: (89,6)-(89,7) = "a" │ │ ├── closing_loc: ∅ @@ -802,7 +802,7 @@ ├── @ CaseMatchNode (location: (93,0)-(95,3)) │ ├── predicate: │ │ @ SymbolNode (location: (93,5)-(93,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (93,5)-(93,6) = ":" │ │ ├── value_loc: (93,6)-(93,7) = "a" │ │ ├── closing_loc: ∅ @@ -841,7 +841,7 @@ ├── @ CaseMatchNode (location: (97,0)-(99,3)) │ ├── predicate: │ │ @ SymbolNode (location: (97,5)-(97,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (97,5)-(97,6) = ":" │ │ ├── value_loc: (97,6)-(97,7) = "a" │ │ ├── closing_loc: ∅ @@ -864,7 +864,7 @@ ├── @ CaseMatchNode (location: (101,0)-(103,3)) │ ├── predicate: │ │ @ SymbolNode (location: (101,5)-(101,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (101,5)-(101,6) = ":" │ │ ├── value_loc: (101,6)-(101,7) = "a" │ │ ├── closing_loc: ∅ @@ -891,7 +891,7 @@ ├── @ CaseMatchNode (location: (105,0)-(107,3)) │ ├── predicate: │ │ @ SymbolNode (location: (105,5)-(105,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (105,5)-(105,6) = ":" │ │ ├── value_loc: (105,6)-(105,7) = "a" │ │ ├── closing_loc: ∅ @@ -905,7 +905,7 @@ │ │ │ │ └── @ AssocNode (location: (106,5)-(106,9)) │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (106,5)-(106,9)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (106,5)-(106,6) = "\"" │ │ │ │ │ ├── value_loc: (106,6)-(106,7) = "b" │ │ │ │ │ ├── closing_loc: (106,7)-(106,9) = "\":" @@ -929,7 +929,7 @@ └── @ CaseMatchNode (location: (109,0)-(111,3)) ├── predicate: │ @ SymbolNode (location: (109,5)-(109,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (109,5)-(109,6) = ":" │ ├── value_loc: (109,6)-(109,7) = "a" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_31.txt b/test/prism/snapshots/seattlerb/case_in_31.txt index b33d5943fc67ef..fdf5ce2a29e6ee 100644 --- a/test/prism/snapshots/seattlerb/case_in_31.txt +++ b/test/prism/snapshots/seattlerb/case_in_31.txt @@ -6,7 +6,7 @@ └── @ CaseMatchNode (location: (1,0)-(4,3)) ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ @@ -18,7 +18,7 @@ │ │ ├── constant: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ SymbolNode (location: (2,4)-(2,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (2,4)-(2,5) = ":" │ │ │ ├── value_loc: (2,5)-(2,6) = "b" │ │ │ ├── closing_loc: ∅ @@ -37,7 +37,7 @@ │ │ @ StatementsNode (location: (3,2)-(3,4)) │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "d" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_37.txt b/test/prism/snapshots/seattlerb/case_in_37.txt index 117b27503ae4b6..1a1d887b4fdf20 100644 --- a/test/prism/snapshots/seattlerb/case_in_37.txt +++ b/test/prism/snapshots/seattlerb/case_in_37.txt @@ -6,7 +6,7 @@ └── @ CaseMatchNode (location: (1,0)-(4,3)) ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ @@ -20,7 +20,7 @@ │ │ │ └── @ AssocNode (location: (2,5)-(2,17)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (2,5)-(2,7)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (2,5)-(2,6) = "b" │ │ │ │ ├── closing_loc: (2,6)-(2,7) = ":" @@ -46,7 +46,7 @@ │ │ @ StatementsNode (location: (3,2)-(3,4)) │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "c" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_42.txt b/test/prism/snapshots/seattlerb/case_in_42.txt index 41f3094cd1670d..f985d6bc8db09b 100644 --- a/test/prism/snapshots/seattlerb/case_in_42.txt +++ b/test/prism/snapshots/seattlerb/case_in_42.txt @@ -6,7 +6,7 @@ └── @ CaseMatchNode (location: (1,0)-(3,3)) ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ @@ -18,7 +18,7 @@ │ │ ├── constant: ∅ │ │ ├── requireds: (length: 1) │ │ │ └── @ SymbolNode (location: (2,3)-(2,5)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (2,3)-(2,4) = ":" │ │ │ ├── value_loc: (2,4)-(2,5) = "b" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_42_2.txt b/test/prism/snapshots/seattlerb/case_in_42_2.txt index e144f1d13a69fc..c399ba1bfa4adc 100644 --- a/test/prism/snapshots/seattlerb/case_in_42_2.txt +++ b/test/prism/snapshots/seattlerb/case_in_42_2.txt @@ -6,7 +6,7 @@ └── @ CaseMatchNode (location: (1,0)-(3,3)) ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_47.txt b/test/prism/snapshots/seattlerb/case_in_47.txt index b104d0022424e8..99baebce05a9b3 100644 --- a/test/prism/snapshots/seattlerb/case_in_47.txt +++ b/test/prism/snapshots/seattlerb/case_in_47.txt @@ -6,7 +6,7 @@ └── @ CaseMatchNode (location: (1,0)-(4,3)) ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ @@ -23,13 +23,13 @@ │ │ │ └── expression: ∅ │ │ ├── posts: (length: 2) │ │ │ ├── @ SymbolNode (location: (2,7)-(2,9)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (2,7)-(2,8) = ":" │ │ │ │ ├── value_loc: (2,8)-(2,9) = "b" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "b" │ │ │ └── @ SymbolNode (location: (2,11)-(2,13)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (2,11)-(2,12) = ":" │ │ │ ├── value_loc: (2,12)-(2,13) = "c" │ │ │ ├── closing_loc: ∅ @@ -40,7 +40,7 @@ │ │ @ StatementsNode (location: (3,2)-(3,4)) │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "d" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_67.txt b/test/prism/snapshots/seattlerb/case_in_67.txt index 4b6c2a2b172e6a..72c7f567635ace 100644 --- a/test/prism/snapshots/seattlerb/case_in_67.txt +++ b/test/prism/snapshots/seattlerb/case_in_67.txt @@ -6,7 +6,7 @@ └── @ CaseMatchNode (location: (1,0)-(3,3)) ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_86.txt b/test/prism/snapshots/seattlerb/case_in_86.txt index cd11904371982c..588913784483d9 100644 --- a/test/prism/snapshots/seattlerb/case_in_86.txt +++ b/test/prism/snapshots/seattlerb/case_in_86.txt @@ -9,13 +9,13 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ SymbolNode (location: (1,6)-(1,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,6)-(1,7) = ":" │ │ │ ├── value_loc: (1,7)-(1,8) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ └── @ SymbolNode (location: (1,10)-(1,12)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,10)-(1,11) = ":" │ │ ├── value_loc: (1,11)-(1,12) = "b" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_86_2.txt b/test/prism/snapshots/seattlerb/case_in_86_2.txt index f750ffa90c45ba..18ce70ae93fee7 100644 --- a/test/prism/snapshots/seattlerb/case_in_86_2.txt +++ b/test/prism/snapshots/seattlerb/case_in_86_2.txt @@ -9,13 +9,13 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ SymbolNode (location: (1,6)-(1,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,6)-(1,7) = ":" │ │ │ ├── value_loc: (1,7)-(1,8) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ └── @ SymbolNode (location: (1,10)-(1,12)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,10)-(1,11) = ":" │ │ ├── value_loc: (1,11)-(1,12) = "b" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_array_pat_const.txt b/test/prism/snapshots/seattlerb/case_in_array_pat_const.txt index 9490477ab09899..f361e8d4589940 100644 --- a/test/prism/snapshots/seattlerb/case_in_array_pat_const.txt +++ b/test/prism/snapshots/seattlerb/case_in_array_pat_const.txt @@ -6,7 +6,7 @@ └── @ CaseMatchNode (location: (1,0)-(4,3)) ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ @@ -30,7 +30,7 @@ │ │ @ StatementsNode (location: (3,2)-(3,4)) │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "d" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_array_pat_const2.txt b/test/prism/snapshots/seattlerb/case_in_array_pat_const2.txt index 5d18d5fca777a1..c783af9ce568cd 100644 --- a/test/prism/snapshots/seattlerb/case_in_array_pat_const2.txt +++ b/test/prism/snapshots/seattlerb/case_in_array_pat_const2.txt @@ -6,7 +6,7 @@ └── @ CaseMatchNode (location: (1,0)-(4,3)) ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ @@ -36,7 +36,7 @@ │ │ @ StatementsNode (location: (3,2)-(3,4)) │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "e" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_array_pat_paren_assign.txt b/test/prism/snapshots/seattlerb/case_in_array_pat_paren_assign.txt index e09f87f98ed1ef..8d185b250a7048 100644 --- a/test/prism/snapshots/seattlerb/case_in_array_pat_paren_assign.txt +++ b/test/prism/snapshots/seattlerb/case_in_array_pat_paren_assign.txt @@ -6,7 +6,7 @@ └── @ CaseMatchNode (location: (1,0)-(4,3)) ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ @@ -36,7 +36,7 @@ │ │ @ StatementsNode (location: (3,2)-(3,4)) │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "d" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_const.txt b/test/prism/snapshots/seattlerb/case_in_const.txt index c31a44d95273f4..c4b838aa1d5e47 100644 --- a/test/prism/snapshots/seattlerb/case_in_const.txt +++ b/test/prism/snapshots/seattlerb/case_in_const.txt @@ -16,7 +16,7 @@ │ │ @ StatementsNode (location: (3,2)-(3,4)) │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "b" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_else.txt b/test/prism/snapshots/seattlerb/case_in_else.txt index 8e4cefe48dacd9..5eae7fc1ea25bf 100644 --- a/test/prism/snapshots/seattlerb/case_in_else.txt +++ b/test/prism/snapshots/seattlerb/case_in_else.txt @@ -16,7 +16,7 @@ │ │ @ StatementsNode (location: (3,2)-(3,4)) │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "b" │ │ ├── closing_loc: ∅ @@ -30,7 +30,7 @@ │ │ @ StatementsNode (location: (5,2)-(5,4)) │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (5,2)-(5,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (5,2)-(5,3) = ":" │ │ ├── value_loc: (5,3)-(5,4) = "c" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_find.txt b/test/prism/snapshots/seattlerb/case_in_find.txt index 37a264e2734ed0..f84c4c30d0d381 100644 --- a/test/prism/snapshots/seattlerb/case_in_find.txt +++ b/test/prism/snapshots/seattlerb/case_in_find.txt @@ -6,7 +6,7 @@ └── @ CaseMatchNode (location: (1,0)-(3,3)) ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ @@ -25,7 +25,7 @@ │ │ │ └── depth: 0 │ │ ├── requireds: (length: 1) │ │ │ └── @ SymbolNode (location: (2,9)-(2,11)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (2,9)-(2,10) = ":" │ │ │ ├── value_loc: (2,10)-(2,11) = "+" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_find_array.txt b/test/prism/snapshots/seattlerb/case_in_find_array.txt index 757256d3fda9b7..a757f803460d03 100644 --- a/test/prism/snapshots/seattlerb/case_in_find_array.txt +++ b/test/prism/snapshots/seattlerb/case_in_find_array.txt @@ -6,7 +6,7 @@ └── @ CaseMatchNode (location: (1,0)-(3,3)) ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ @@ -22,7 +22,7 @@ │ │ │ └── expression: ∅ │ │ ├── requireds: (length: 2) │ │ │ ├── @ SymbolNode (location: (2,7)-(2,9)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (2,7)-(2,8) = ":" │ │ │ │ ├── value_loc: (2,8)-(2,9) = "b" │ │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_hash_pat.txt b/test/prism/snapshots/seattlerb/case_in_hash_pat.txt index 50d7867c7238cb..e813efa9ee52f2 100644 --- a/test/prism/snapshots/seattlerb/case_in_hash_pat.txt +++ b/test/prism/snapshots/seattlerb/case_in_hash_pat.txt @@ -6,7 +6,7 @@ └── @ CaseMatchNode (location: (1,0)-(4,3)) ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ @@ -20,7 +20,7 @@ │ │ │ ├── @ AssocNode (location: (2,5)-(2,11)) │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (2,5)-(2,7)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (2,5)-(2,6) = "b" │ │ │ │ │ ├── closing_loc: (2,6)-(2,7) = ":" @@ -36,7 +36,7 @@ │ │ │ └── @ AssocNode (location: (2,13)-(2,19)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (2,13)-(2,15)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (2,13)-(2,14) = "d" │ │ │ │ ├── closing_loc: (2,14)-(2,15) = ":" @@ -56,7 +56,7 @@ │ │ @ StatementsNode (location: (3,2)-(3,4)) │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "f" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_hash_pat_assign.txt b/test/prism/snapshots/seattlerb/case_in_hash_pat_assign.txt index 9863dfbc3f3a6c..790d9d63ffb2b3 100644 --- a/test/prism/snapshots/seattlerb/case_in_hash_pat_assign.txt +++ b/test/prism/snapshots/seattlerb/case_in_hash_pat_assign.txt @@ -6,7 +6,7 @@ └── @ CaseMatchNode (location: (1,0)-(4,3)) ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ @@ -20,7 +20,7 @@ │ │ │ ├── @ AssocNode (location: (2,5)-(2,20)) │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (2,5)-(2,7)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (2,5)-(2,6) = "b" │ │ │ │ │ ├── closing_loc: (2,6)-(2,7) = ":" @@ -39,7 +39,7 @@ │ │ │ ├── @ AssocNode (location: (2,22)-(2,28)) │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (2,22)-(2,24)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (2,22)-(2,23) = "d" │ │ │ │ │ ├── closing_loc: (2,23)-(2,24) = ":" @@ -55,7 +55,7 @@ │ │ │ └── @ AssocNode (location: (2,30)-(2,32)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (2,30)-(2,32)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (2,30)-(2,31) = "f" │ │ │ │ ├── closing_loc: (2,31)-(2,32) = ":" @@ -74,7 +74,7 @@ │ │ @ StatementsNode (location: (3,2)-(3,4)) │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "g" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_hash_pat_paren_assign.txt b/test/prism/snapshots/seattlerb/case_in_hash_pat_paren_assign.txt index 8c25711bfdcd19..052468bcc43823 100644 --- a/test/prism/snapshots/seattlerb/case_in_hash_pat_paren_assign.txt +++ b/test/prism/snapshots/seattlerb/case_in_hash_pat_paren_assign.txt @@ -6,7 +6,7 @@ └── @ CaseMatchNode (location: (1,0)-(4,3)) ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ @@ -22,7 +22,7 @@ │ │ │ └── @ AssocNode (location: (2,5)-(2,10)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (2,5)-(2,7)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (2,5)-(2,6) = "a" │ │ │ │ ├── closing_loc: (2,6)-(2,7) = ":" @@ -38,7 +38,7 @@ │ │ @ StatementsNode (location: (3,2)-(3,4)) │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "d" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_hash_pat_paren_true.txt b/test/prism/snapshots/seattlerb/case_in_hash_pat_paren_true.txt index f062b23cbca227..8ff95a161f37da 100644 --- a/test/prism/snapshots/seattlerb/case_in_hash_pat_paren_true.txt +++ b/test/prism/snapshots/seattlerb/case_in_hash_pat_paren_true.txt @@ -6,7 +6,7 @@ └── @ CaseMatchNode (location: (1,0)-(4,3)) ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ @@ -20,7 +20,7 @@ │ │ │ └── @ AssocNode (location: (2,3)-(2,10)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (2,3)-(2,5)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (2,3)-(2,4) = "b" │ │ │ │ ├── closing_loc: (2,4)-(2,5) = ":" @@ -35,7 +35,7 @@ │ │ @ StatementsNode (location: (3,2)-(3,4)) │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "c" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_hash_pat_rest.txt b/test/prism/snapshots/seattlerb/case_in_hash_pat_rest.txt index bfdfa905059419..b93b889ec5fd91 100644 --- a/test/prism/snapshots/seattlerb/case_in_hash_pat_rest.txt +++ b/test/prism/snapshots/seattlerb/case_in_hash_pat_rest.txt @@ -6,7 +6,7 @@ └── @ CaseMatchNode (location: (1,0)-(3,3)) ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ @@ -20,7 +20,7 @@ │ │ │ └── @ AssocNode (location: (2,3)-(2,7)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (2,3)-(2,5)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (2,3)-(2,4) = "b" │ │ │ │ ├── closing_loc: (2,4)-(2,5) = ":" @@ -43,7 +43,7 @@ │ │ @ StatementsNode (location: (2,21)-(2,23)) │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (2,21)-(2,23)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (2,21)-(2,22) = ":" │ │ ├── value_loc: (2,22)-(2,23) = "d" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_hash_pat_rest_solo.txt b/test/prism/snapshots/seattlerb/case_in_hash_pat_rest_solo.txt index 78f784054429cd..956e93faa02b46 100644 --- a/test/prism/snapshots/seattlerb/case_in_hash_pat_rest_solo.txt +++ b/test/prism/snapshots/seattlerb/case_in_hash_pat_rest_solo.txt @@ -6,7 +6,7 @@ └── @ CaseMatchNode (location: (1,0)-(3,3)) ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ @@ -30,7 +30,7 @@ │ │ @ StatementsNode (location: (2,15)-(2,17)) │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (2,15)-(2,17)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (2,15)-(2,16) = ":" │ │ ├── value_loc: (2,16)-(2,17) = "d" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_if_unless_post_mod.txt b/test/prism/snapshots/seattlerb/case_in_if_unless_post_mod.txt index 4292c1effa3b8c..a21d3e15dd4d4e 100644 --- a/test/prism/snapshots/seattlerb/case_in_if_unless_post_mod.txt +++ b/test/prism/snapshots/seattlerb/case_in_if_unless_post_mod.txt @@ -6,7 +6,7 @@ └── @ CaseMatchNode (location: (1,0)-(6,3)) ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ @@ -30,7 +30,7 @@ │ │ │ @ StatementsNode (location: (3,2)-(3,4)) │ │ │ └── body: (length: 1) │ │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ │ ├── value_loc: (3,3)-(3,4) = "C" │ │ │ ├── closing_loc: ∅ @@ -55,7 +55,7 @@ │ │ @ StatementsNode (location: (5,2)-(5,4)) │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (5,2)-(5,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (5,2)-(5,3) = ":" │ │ ├── value_loc: (5,3)-(5,4) = "E" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_multiple.txt b/test/prism/snapshots/seattlerb/case_in_multiple.txt index 60d48f0be4f825..d8597c4bfab216 100644 --- a/test/prism/snapshots/seattlerb/case_in_multiple.txt +++ b/test/prism/snapshots/seattlerb/case_in_multiple.txt @@ -6,7 +6,7 @@ └── @ CaseMatchNode (location: (1,0)-(6,3)) ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ @@ -26,7 +26,7 @@ │ │ │ @ StatementsNode (location: (3,2)-(3,4)) │ │ │ └── body: (length: 1) │ │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ │ ├── value_loc: (3,3)-(3,4) = "C" │ │ │ ├── closing_loc: ∅ @@ -47,7 +47,7 @@ │ │ @ StatementsNode (location: (5,2)-(5,4)) │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (5,2)-(5,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (5,2)-(5,3) = ":" │ │ ├── value_loc: (5,3)-(5,4) = "F" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/case_in_or.txt b/test/prism/snapshots/seattlerb/case_in_or.txt index 26c26974dafd58..7ac66176082b45 100644 --- a/test/prism/snapshots/seattlerb/case_in_or.txt +++ b/test/prism/snapshots/seattlerb/case_in_or.txt @@ -6,7 +6,7 @@ └── @ CaseMatchNode (location: (1,0)-(4,3)) ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ @@ -26,7 +26,7 @@ │ │ @ StatementsNode (location: (3,2)-(3,4)) │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (3,2)-(3,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ ├── value_loc: (3,3)-(3,4) = "d" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_args_forward_args.txt b/test/prism/snapshots/seattlerb/defn_args_forward_args.txt index 76d0fbe71c6c2a..e6b72907b09d2d 100644 --- a/test/prism/snapshots/seattlerb/defn_args_forward_args.txt +++ b/test/prism/snapshots/seattlerb/defn_args_forward_args.txt @@ -41,7 +41,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 3) │ │ ├── @ SymbolNode (location: (1,23)-(1,27)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,23)-(1,24) = ":" │ │ │ ├── value_loc: (1,24)-(1,27) = "get" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_kwarg_lvar.txt b/test/prism/snapshots/seattlerb/defn_kwarg_lvar.txt index 93bdb4205438f5..2e920f9a2e1498 100644 --- a/test/prism/snapshots/seattlerb/defn_kwarg_lvar.txt +++ b/test/prism/snapshots/seattlerb/defn_kwarg_lvar.txt @@ -20,7 +20,7 @@ │ │ ├── name_loc: (1,8)-(1,11) = "kw:" │ │ └── value: │ │ @ SymbolNode (location: (1,12)-(1,16)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,12)-(1,13) = ":" │ │ ├── value_loc: (1,13)-(1,16) = "val" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/defn_reg_opt_reg.txt b/test/prism/snapshots/seattlerb/defn_reg_opt_reg.txt index 2a5e151bc24836..fd68d67329aca0 100644 --- a/test/prism/snapshots/seattlerb/defn_reg_opt_reg.txt +++ b/test/prism/snapshots/seattlerb/defn_reg_opt_reg.txt @@ -21,7 +21,7 @@ │ │ ├── operator_loc: (1,11)-(1,12) = "=" │ │ └── value: │ │ @ SymbolNode (location: (1,13)-(1,15)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,13)-(1,14) = ":" │ │ ├── value_loc: (1,14)-(1,15) = "c" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/difficult2_.txt b/test/prism/snapshots/seattlerb/difficult2_.txt index 6a34e024be14ec..6680a28d6c6763 100644 --- a/test/prism/snapshots/seattlerb/difficult2_.txt +++ b/test/prism/snapshots/seattlerb/difficult2_.txt @@ -58,7 +58,7 @@ │ └── @ AssocNode (location: (2,2)-(2,6)) │ ├── key: │ │ @ SymbolNode (location: (2,2)-(2,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (2,2)-(2,3) = "d" │ │ ├── closing_loc: (2,3)-(2,4) = ":" diff --git a/test/prism/snapshots/seattlerb/difficult7_.txt b/test/prism/snapshots/seattlerb/difficult7_.txt index c94842928ec51f..0c71a1ad2498e3 100644 --- a/test/prism/snapshots/seattlerb/difficult7_.txt +++ b/test/prism/snapshots/seattlerb/difficult7_.txt @@ -9,7 +9,7 @@ │ ├── @ AssocNode (location: (2,8)-(2,33)) │ │ ├── key: │ │ │ @ SymbolNode (location: (2,8)-(2,10)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (2,8)-(2,9) = "a" │ │ │ ├── closing_loc: (2,9)-(2,10) = ":" @@ -83,7 +83,7 @@ │ └── @ AssocNode (location: (3,8)-(3,14)) │ ├── key: │ │ @ SymbolNode (location: (3,8)-(3,10)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (3,8)-(3,9) = "e" │ │ ├── closing_loc: (3,9)-(3,10) = ":" diff --git a/test/prism/snapshots/seattlerb/dstr_lex_state.txt b/test/prism/snapshots/seattlerb/dstr_lex_state.txt index 7fac367c919861..0e7f8ff83d99e3 100644 --- a/test/prism/snapshots/seattlerb/dstr_lex_state.txt +++ b/test/prism/snapshots/seattlerb/dstr_lex_state.txt @@ -23,7 +23,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ SymbolNode (location: (1,4)-(1,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,4)-(1,5) = ":" │ │ │ ├── value_loc: (1,5)-(1,6) = "a" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/dsym_esc_to_sym.txt b/test/prism/snapshots/seattlerb/dsym_esc_to_sym.txt index e3da9c4a9affb0..7b1b68131e0b29 100644 --- a/test/prism/snapshots/seattlerb/dsym_esc_to_sym.txt +++ b/test/prism/snapshots/seattlerb/dsym_esc_to_sym.txt @@ -4,7 +4,7 @@ @ StatementsNode (location: (1,0)-(1,17)) └── body: (length: 1) └── @ SymbolNode (location: (1,0)-(1,17)) - ├── flags: ∅ + ├── flags: forced_utf8_encoding ├── opening_loc: (1,0)-(1,2) = ":\"" ├── value_loc: (1,2)-(1,16) = "Variet\\303\\240" ├── closing_loc: (1,16)-(1,17) = "\"" diff --git a/test/prism/snapshots/seattlerb/dsym_to_sym.txt b/test/prism/snapshots/seattlerb/dsym_to_sym.txt index 92ca0392077ea2..eb7e435c630fcd 100644 --- a/test/prism/snapshots/seattlerb/dsym_to_sym.txt +++ b/test/prism/snapshots/seattlerb/dsym_to_sym.txt @@ -6,14 +6,14 @@ ├── @ AliasMethodNode (location: (1,0)-(1,17)) │ ├── new_name: │ │ @ SymbolNode (location: (1,6)-(1,11)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,6)-(1,8) = ":\"" │ │ ├── value_loc: (1,8)-(1,10) = "<<" │ │ ├── closing_loc: (1,10)-(1,11) = "\"" │ │ └── unescaped: "<<" │ ├── old_name: │ │ @ SymbolNode (location: (1,12)-(1,17)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,12)-(1,14) = ":\"" │ │ ├── value_loc: (1,14)-(1,16) = ">>" │ │ ├── closing_loc: (1,16)-(1,17) = "\"" @@ -22,14 +22,14 @@ └── @ AliasMethodNode (location: (3,0)-(3,13)) ├── new_name: │ @ SymbolNode (location: (3,6)-(3,9)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (3,6)-(3,7) = ":" │ ├── value_loc: (3,7)-(3,9) = "<<" │ ├── closing_loc: ∅ │ └── unescaped: "<<" ├── old_name: │ @ SymbolNode (location: (3,10)-(3,13)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (3,10)-(3,11) = ":" │ ├── value_loc: (3,11)-(3,13) = ">>" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/if_symbol.txt b/test/prism/snapshots/seattlerb/if_symbol.txt index 8d1a78d563fa34..85ec52b4c82837 100644 --- a/test/prism/snapshots/seattlerb/if_symbol.txt +++ b/test/prism/snapshots/seattlerb/if_symbol.txt @@ -18,7 +18,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ SymbolNode (location: (1,5)-(1,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,5)-(1,6) = ":" │ │ ├── value_loc: (1,6)-(1,7) = "x" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/interpolated_symbol_array_line_breaks.txt b/test/prism/snapshots/seattlerb/interpolated_symbol_array_line_breaks.txt index f1965557709898..955cd210330395 100644 --- a/test/prism/snapshots/seattlerb/interpolated_symbol_array_line_breaks.txt +++ b/test/prism/snapshots/seattlerb/interpolated_symbol_array_line_breaks.txt @@ -7,13 +7,13 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ SymbolNode (location: (2,0)-(2,1)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (2,0)-(2,1) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ └── @ SymbolNode (location: (3,0)-(3,1)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (3,0)-(3,1) = "b" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/multiline_hash_declaration.txt b/test/prism/snapshots/seattlerb/multiline_hash_declaration.txt index ac28532a9aa4d8..79b0ef5d236388 100644 --- a/test/prism/snapshots/seattlerb/multiline_hash_declaration.txt +++ b/test/prism/snapshots/seattlerb/multiline_hash_declaration.txt @@ -20,7 +20,7 @@ │ │ └── @ AssocNode (location: (1,2)-(3,1)) │ │ ├── key: │ │ │ @ SymbolNode (location: (1,2)-(1,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (1,2)-(1,7) = "state" │ │ │ ├── closing_loc: (1,7)-(1,8) = ":" @@ -50,7 +50,7 @@ │ │ └── @ AssocNode (location: (5,2)-(6,1)) │ │ ├── key: │ │ │ @ SymbolNode (location: (5,2)-(5,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (5,2)-(5,7) = "state" │ │ │ ├── closing_loc: (5,7)-(5,8) = ":" @@ -80,7 +80,7 @@ │ └── @ AssocNode (location: (8,2)-(8,11)) │ ├── key: │ │ @ SymbolNode (location: (8,2)-(8,8)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (8,2)-(8,7) = "state" │ │ ├── closing_loc: (8,7)-(8,8) = ":" diff --git a/test/prism/snapshots/seattlerb/non_interpolated_symbol_array_line_breaks.txt b/test/prism/snapshots/seattlerb/non_interpolated_symbol_array_line_breaks.txt index 08dce249affc7b..a39a6c12559095 100644 --- a/test/prism/snapshots/seattlerb/non_interpolated_symbol_array_line_breaks.txt +++ b/test/prism/snapshots/seattlerb/non_interpolated_symbol_array_line_breaks.txt @@ -7,13 +7,13 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ SymbolNode (location: (2,0)-(2,1)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (2,0)-(2,1) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ └── @ SymbolNode (location: (3,0)-(3,1)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (3,0)-(3,1) = "b" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/op_asgn_index_command_call.txt b/test/prism/snapshots/seattlerb/op_asgn_index_command_call.txt index 8c371f7b40cd74..9221c717c7a1e1 100644 --- a/test/prism/snapshots/seattlerb/op_asgn_index_command_call.txt +++ b/test/prism/snapshots/seattlerb/op_asgn_index_command_call.txt @@ -23,7 +23,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 1) │ └── @ SymbolNode (location: (1,2)-(1,4)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,2)-(1,3) = ":" │ ├── value_loc: (1,3)-(1,4) = "b" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/parse_line_hash_lit.txt b/test/prism/snapshots/seattlerb/parse_line_hash_lit.txt index 17aa26bda769bf..410a54b7e370be 100644 --- a/test/prism/snapshots/seattlerb/parse_line_hash_lit.txt +++ b/test/prism/snapshots/seattlerb/parse_line_hash_lit.txt @@ -9,7 +9,7 @@ │ └── @ AssocNode (location: (2,0)-(2,8)) │ ├── key: │ │ @ SymbolNode (location: (2,0)-(2,3)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (2,0)-(2,1) = ":" │ │ ├── value_loc: (2,1)-(2,3) = "s1" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/parse_pattern_058.txt b/test/prism/snapshots/seattlerb/parse_pattern_058.txt index 66db776bcb6d8e..f3ff72c35f295c 100644 --- a/test/prism/snapshots/seattlerb/parse_pattern_058.txt +++ b/test/prism/snapshots/seattlerb/parse_pattern_058.txt @@ -11,7 +11,7 @@ │ │ └── @ AssocNode (location: (1,6)-(1,10)) │ │ ├── key: │ │ │ @ SymbolNode (location: (1,6)-(1,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (1,6)-(1,7) = "a" │ │ │ ├── closing_loc: (1,7)-(1,8) = ":" @@ -30,7 +30,7 @@ │ │ │ └── @ AssocNode (location: (2,4)-(2,6)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (2,4)-(2,6)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (2,4)-(2,5) = "a" │ │ │ │ ├── closing_loc: (2,5)-(2,6) = ":" diff --git a/test/prism/snapshots/seattlerb/parse_pattern_058_2.txt b/test/prism/snapshots/seattlerb/parse_pattern_058_2.txt index 075084ed962efe..383b4d5f2f116e 100644 --- a/test/prism/snapshots/seattlerb/parse_pattern_058_2.txt +++ b/test/prism/snapshots/seattlerb/parse_pattern_058_2.txt @@ -11,7 +11,7 @@ │ │ └── @ AssocNode (location: (1,6)-(1,10)) │ │ ├── key: │ │ │ @ SymbolNode (location: (1,6)-(1,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (1,6)-(1,7) = "a" │ │ │ ├── closing_loc: (1,7)-(1,8) = ":" @@ -30,7 +30,7 @@ │ │ │ └── @ AssocNode (location: (2,4)-(2,6)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (2,4)-(2,6)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (2,4)-(2,5) = "a" │ │ │ │ ├── closing_loc: (2,5)-(2,6) = ":" diff --git a/test/prism/snapshots/seattlerb/parse_pattern_069.txt b/test/prism/snapshots/seattlerb/parse_pattern_069.txt index b5cd94cd770307..e76c6d3f147451 100644 --- a/test/prism/snapshots/seattlerb/parse_pattern_069.txt +++ b/test/prism/snapshots/seattlerb/parse_pattern_069.txt @@ -6,7 +6,7 @@ └── @ CaseMatchNode (location: (1,0)-(4,3)) ├── predicate: │ @ SymbolNode (location: (1,5)-(1,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,5)-(1,6) = ":" │ ├── value_loc: (1,6)-(1,7) = "a" │ ├── closing_loc: ∅ @@ -22,7 +22,7 @@ │ │ │ └── @ AssocNode (location: (2,10)-(2,14)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (2,10)-(2,12)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (2,10)-(2,11) = "b" │ │ │ │ ├── closing_loc: (2,11)-(2,12) = ":" diff --git a/test/prism/snapshots/seattlerb/parse_pattern_076.txt b/test/prism/snapshots/seattlerb/parse_pattern_076.txt index 8f4ef571c7c7bf..8ae4b68547bcad 100644 --- a/test/prism/snapshots/seattlerb/parse_pattern_076.txt +++ b/test/prism/snapshots/seattlerb/parse_pattern_076.txt @@ -11,7 +11,7 @@ │ │ └── @ AssocNode (location: (1,6)-(1,10)) │ │ ├── key: │ │ │ @ SymbolNode (location: (1,6)-(1,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (1,6)-(1,7) = "a" │ │ │ ├── closing_loc: (1,7)-(1,8) = ":" @@ -30,7 +30,7 @@ │ │ │ └── @ AssocNode (location: (2,4)-(2,8)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (2,4)-(2,6)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (2,4)-(2,5) = "a" │ │ │ │ ├── closing_loc: (2,5)-(2,6) = ":" diff --git a/test/prism/snapshots/seattlerb/qsymbols.txt b/test/prism/snapshots/seattlerb/qsymbols.txt index ff04f9a6500a12..8ba68638c5bb02 100644 --- a/test/prism/snapshots/seattlerb/qsymbols.txt +++ b/test/prism/snapshots/seattlerb/qsymbols.txt @@ -7,19 +7,19 @@ ├── flags: ∅ ├── elements: (length: 3) │ ├── @ SymbolNode (location: (1,3)-(1,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,3)-(1,4) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── @ SymbolNode (location: (1,5)-(1,6)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,5)-(1,6) = "b" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "b" │ └── @ SymbolNode (location: (1,7)-(1,8)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: ∅ │ ├── value_loc: (1,7)-(1,8) = "c" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/qsymbols_interp.txt b/test/prism/snapshots/seattlerb/qsymbols_interp.txt index 16b9f7c845cb59..ca300721cc6a70 100644 --- a/test/prism/snapshots/seattlerb/qsymbols_interp.txt +++ b/test/prism/snapshots/seattlerb/qsymbols_interp.txt @@ -7,7 +7,7 @@ ├── flags: ∅ ├── elements: (length: 3) │ ├── @ SymbolNode (location: (1,3)-(1,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,3)-(1,4) = "a" │ │ ├── closing_loc: ∅ @@ -46,7 +46,7 @@ │ │ │ └── closing_loc: (1,11)-(1,12) = "}" │ │ └── closing_loc: ∅ │ └── @ SymbolNode (location: (1,13)-(1,14)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: ∅ │ ├── value_loc: (1,13)-(1,14) = "c" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/quoted_symbol_hash_arg.txt b/test/prism/snapshots/seattlerb/quoted_symbol_hash_arg.txt index 4f89f48ccc606d..64caf51bcbd7dd 100644 --- a/test/prism/snapshots/seattlerb/quoted_symbol_hash_arg.txt +++ b/test/prism/snapshots/seattlerb/quoted_symbol_hash_arg.txt @@ -20,7 +20,7 @@ │ └── @ AssocNode (location: (1,5)-(1,12)) │ ├── key: │ │ @ SymbolNode (location: (1,5)-(1,9)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,5)-(1,6) = "'" │ │ ├── value_loc: (1,6)-(1,7) = "a" │ │ ├── closing_loc: (1,7)-(1,9) = "':" diff --git a/test/prism/snapshots/seattlerb/quoted_symbol_keys.txt b/test/prism/snapshots/seattlerb/quoted_symbol_keys.txt index 1e28bb61cba518..96e6af51a423de 100644 --- a/test/prism/snapshots/seattlerb/quoted_symbol_keys.txt +++ b/test/prism/snapshots/seattlerb/quoted_symbol_keys.txt @@ -9,14 +9,14 @@ │ └── @ AssocNode (location: (1,2)-(1,9)) │ ├── key: │ │ @ SymbolNode (location: (1,2)-(1,6)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,2)-(1,3) = "'" │ │ ├── value_loc: (1,3)-(1,4) = "a" │ │ ├── closing_loc: (1,4)-(1,6) = "':" │ │ └── unescaped: "a" │ ├── value: │ │ @ SymbolNode (location: (1,7)-(1,9)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,7)-(1,8) = ":" │ │ ├── value_loc: (1,8)-(1,9) = "b" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/rescue_do_end_ensure_result.txt b/test/prism/snapshots/seattlerb/rescue_do_end_ensure_result.txt index c480feb5034511..761565352b16b6 100644 --- a/test/prism/snapshots/seattlerb/rescue_do_end_ensure_result.txt +++ b/test/prism/snapshots/seattlerb/rescue_do_end_ensure_result.txt @@ -27,7 +27,7 @@ │ │ │ @ StatementsNode (location: (2,2)-(2,8)) │ │ │ └── body: (length: 1) │ │ │ └── @ SymbolNode (location: (2,2)-(2,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (2,2)-(2,3) = ":" │ │ │ ├── value_loc: (2,3)-(2,8) = "begin" │ │ │ ├── closing_loc: ∅ @@ -41,7 +41,7 @@ │ │ │ │ @ StatementsNode (location: (4,2)-(4,9)) │ │ │ │ └── body: (length: 1) │ │ │ │ └── @ SymbolNode (location: (4,2)-(4,9)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (4,2)-(4,3) = ":" │ │ │ │ ├── value_loc: (4,3)-(4,9) = "ensure" │ │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/rescue_do_end_no_raise.txt b/test/prism/snapshots/seattlerb/rescue_do_end_no_raise.txt index 154e75fe1072fc..4d6d8f6f18efee 100644 --- a/test/prism/snapshots/seattlerb/rescue_do_end_no_raise.txt +++ b/test/prism/snapshots/seattlerb/rescue_do_end_no_raise.txt @@ -24,7 +24,7 @@ │ │ @ StatementsNode (location: (2,2)-(2,8)) │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (2,2)-(2,8)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (2,2)-(2,3) = ":" │ │ ├── value_loc: (2,3)-(2,8) = "begin" │ │ ├── closing_loc: ∅ @@ -39,7 +39,7 @@ │ │ │ @ StatementsNode (location: (4,2)-(4,9)) │ │ │ └── body: (length: 1) │ │ │ └── @ SymbolNode (location: (4,2)-(4,9)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (4,2)-(4,3) = ":" │ │ │ ├── value_loc: (4,3)-(4,9) = "rescue" │ │ │ ├── closing_loc: ∅ @@ -52,7 +52,7 @@ │ │ │ @ StatementsNode (location: (6,2)-(6,7)) │ │ │ └── body: (length: 1) │ │ │ └── @ SymbolNode (location: (6,2)-(6,7)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (6,2)-(6,3) = ":" │ │ │ ├── value_loc: (6,3)-(6,7) = "else" │ │ │ ├── closing_loc: ∅ @@ -65,7 +65,7 @@ │ │ │ @ StatementsNode (location: (8,2)-(8,9)) │ │ │ └── body: (length: 1) │ │ │ └── @ SymbolNode (location: (8,2)-(8,9)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (8,2)-(8,3) = ":" │ │ │ ├── value_loc: (8,3)-(8,9) = "ensure" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/rescue_do_end_raised.txt b/test/prism/snapshots/seattlerb/rescue_do_end_raised.txt index 33fbd0e6e0c4d0..b702acef569d8d 100644 --- a/test/prism/snapshots/seattlerb/rescue_do_end_raised.txt +++ b/test/prism/snapshots/seattlerb/rescue_do_end_raised.txt @@ -42,7 +42,7 @@ │ │ │ @ StatementsNode (location: (4,2)-(4,9)) │ │ │ └── body: (length: 1) │ │ │ └── @ SymbolNode (location: (4,2)-(4,9)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (4,2)-(4,3) = ":" │ │ │ ├── value_loc: (4,3)-(4,9) = "ensure" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/rescue_do_end_rescued.txt b/test/prism/snapshots/seattlerb/rescue_do_end_rescued.txt index b68d05e569ed46..c52a5e6a492de2 100644 --- a/test/prism/snapshots/seattlerb/rescue_do_end_rescued.txt +++ b/test/prism/snapshots/seattlerb/rescue_do_end_rescued.txt @@ -43,7 +43,7 @@ │ │ │ @ StatementsNode (location: (4,2)-(4,9)) │ │ │ └── body: (length: 1) │ │ │ └── @ SymbolNode (location: (4,2)-(4,9)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (4,2)-(4,3) = ":" │ │ │ ├── value_loc: (4,3)-(4,9) = "rescue" │ │ │ ├── closing_loc: ∅ @@ -56,7 +56,7 @@ │ │ │ @ StatementsNode (location: (6,2)-(6,7)) │ │ │ └── body: (length: 1) │ │ │ └── @ SymbolNode (location: (6,2)-(6,7)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (6,2)-(6,3) = ":" │ │ │ ├── value_loc: (6,3)-(6,7) = "else" │ │ │ ├── closing_loc: ∅ @@ -69,7 +69,7 @@ │ │ │ @ StatementsNode (location: (8,2)-(8,9)) │ │ │ └── body: (length: 1) │ │ │ └── @ SymbolNode (location: (8,2)-(8,9)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (8,2)-(8,3) = ":" │ │ │ ├── value_loc: (8,3)-(8,9) = "ensure" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/return_call_assocs.txt b/test/prism/snapshots/seattlerb/return_call_assocs.txt index 128037d2269526..3acf37174456ac 100644 --- a/test/prism/snapshots/seattlerb/return_call_assocs.txt +++ b/test/prism/snapshots/seattlerb/return_call_assocs.txt @@ -17,7 +17,7 @@ │ └── @ AssocNode (location: (1,10)-(1,17)) │ ├── key: │ │ @ SymbolNode (location: (1,10)-(1,12)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,10)-(1,11) = ":" │ │ ├── value_loc: (1,11)-(1,12) = "z" │ │ ├── closing_loc: ∅ @@ -40,7 +40,7 @@ │ ├── @ AssocNode (location: (3,10)-(3,17)) │ │ ├── key: │ │ │ @ SymbolNode (location: (3,10)-(3,12)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (3,10)-(3,11) = ":" │ │ │ ├── value_loc: (3,11)-(3,12) = "z" │ │ │ ├── closing_loc: ∅ @@ -52,7 +52,7 @@ │ └── @ AssocNode (location: (3,19)-(3,26)) │ ├── key: │ │ @ SymbolNode (location: (3,19)-(3,21)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (3,19)-(3,20) = ":" │ │ ├── value_loc: (3,20)-(3,21) = "w" │ │ ├── closing_loc: ∅ @@ -84,7 +84,7 @@ │ │ └── @ AssocNode (location: (5,9)-(5,14)) │ │ ├── key: │ │ │ @ SymbolNode (location: (5,9)-(5,11)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (5,9)-(5,10) = ":" │ │ │ ├── value_loc: (5,10)-(5,11) = "z" │ │ │ ├── closing_loc: ∅ @@ -118,7 +118,7 @@ │ │ └── @ AssocNode (location: (7,9)-(7,12)) │ │ ├── key: │ │ │ @ SymbolNode (location: (7,9)-(7,11)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (7,9)-(7,10) = "z" │ │ │ ├── closing_loc: (7,10)-(7,11) = ":" @@ -152,7 +152,7 @@ │ │ └── @ AssocNode (location: (9,9)-(9,12)) │ │ ├── key: │ │ │ @ SymbolNode (location: (9,9)-(9,11)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (9,9)-(9,10) = "z" │ │ │ ├── closing_loc: (9,10)-(9,11) = ":" diff --git a/test/prism/snapshots/seattlerb/symbol_empty.txt b/test/prism/snapshots/seattlerb/symbol_empty.txt index 0208aa39c5cd25..e95543e925d7f1 100644 --- a/test/prism/snapshots/seattlerb/symbol_empty.txt +++ b/test/prism/snapshots/seattlerb/symbol_empty.txt @@ -4,7 +4,7 @@ @ StatementsNode (location: (1,0)-(1,3)) └── body: (length: 1) └── @ SymbolNode (location: (1,0)-(1,3)) - ├── flags: ∅ + ├── flags: forced_us_ascii_encoding ├── opening_loc: (1,0)-(1,2) = ":'" ├── value_loc: (1,2)-(1,2) = "" ├── closing_loc: (1,2)-(1,3) = "'" diff --git a/test/prism/snapshots/seattlerb/symbols.txt b/test/prism/snapshots/seattlerb/symbols.txt index bd07b09de321fe..30cf57c52879c9 100644 --- a/test/prism/snapshots/seattlerb/symbols.txt +++ b/test/prism/snapshots/seattlerb/symbols.txt @@ -7,19 +7,19 @@ ├── flags: ∅ ├── elements: (length: 3) │ ├── @ SymbolNode (location: (1,3)-(1,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,3)-(1,4) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── @ SymbolNode (location: (1,5)-(1,6)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,5)-(1,6) = "b" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "b" │ └── @ SymbolNode (location: (1,7)-(1,8)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: ∅ │ ├── value_loc: (1,7)-(1,8) = "c" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/symbols_interp.txt b/test/prism/snapshots/seattlerb/symbols_interp.txt index d141c9a5a24e11..2ad3cc502d9734 100644 --- a/test/prism/snapshots/seattlerb/symbols_interp.txt +++ b/test/prism/snapshots/seattlerb/symbols_interp.txt @@ -7,19 +7,19 @@ ├── flags: ∅ ├── elements: (length: 3) │ ├── @ SymbolNode (location: (1,3)-(1,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,3)-(1,4) = "a" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "a" │ ├── @ SymbolNode (location: (1,5)-(1,12)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,5)-(1,12) = "b\#{1+1}" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "b\#{1+1}" │ └── @ SymbolNode (location: (1,13)-(1,14)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: ∅ │ ├── value_loc: (1,13)-(1,14) = "c" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/unary_plus_on_literal.txt b/test/prism/snapshots/seattlerb/unary_plus_on_literal.txt index 1638de8b8d37e2..4deb857536f7f4 100644 --- a/test/prism/snapshots/seattlerb/unary_plus_on_literal.txt +++ b/test/prism/snapshots/seattlerb/unary_plus_on_literal.txt @@ -7,7 +7,7 @@ ├── flags: ∅ ├── receiver: │ @ SymbolNode (location: (1,1)-(1,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,1)-(1,2) = ":" │ ├── value_loc: (1,2)-(1,3) = "a" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/yield_call_assocs.txt b/test/prism/snapshots/seattlerb/yield_call_assocs.txt index 8a842b5166d1cd..28ac198b701a64 100644 --- a/test/prism/snapshots/seattlerb/yield_call_assocs.txt +++ b/test/prism/snapshots/seattlerb/yield_call_assocs.txt @@ -18,7 +18,7 @@ │ │ └── @ AssocNode (location: (1,9)-(1,16)) │ │ ├── key: │ │ │ @ SymbolNode (location: (1,9)-(1,11)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,9)-(1,10) = ":" │ │ │ ├── value_loc: (1,10)-(1,11) = "z" │ │ │ ├── closing_loc: ∅ @@ -43,7 +43,7 @@ │ │ ├── @ AssocNode (location: (3,9)-(3,16)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (3,9)-(3,11)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (3,9)-(3,10) = ":" │ │ │ │ ├── value_loc: (3,10)-(3,11) = "z" │ │ │ │ ├── closing_loc: ∅ @@ -55,7 +55,7 @@ │ │ └── @ AssocNode (location: (3,18)-(3,25)) │ │ ├── key: │ │ │ @ SymbolNode (location: (3,18)-(3,20)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (3,18)-(3,19) = ":" │ │ │ ├── value_loc: (3,19)-(3,20) = "w" │ │ │ ├── closing_loc: ∅ @@ -89,7 +89,7 @@ │ │ │ └── @ AssocNode (location: (5,8)-(5,13)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (5,8)-(5,10)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (5,8)-(5,9) = ":" │ │ │ │ ├── value_loc: (5,9)-(5,10) = "z" │ │ │ │ ├── closing_loc: ∅ @@ -125,7 +125,7 @@ │ │ │ └── @ AssocNode (location: (7,8)-(7,11)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (7,8)-(7,10)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (7,8)-(7,9) = "z" │ │ │ │ ├── closing_loc: (7,9)-(7,10) = ":" @@ -161,7 +161,7 @@ │ │ │ └── @ AssocNode (location: (9,8)-(9,11)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (9,8)-(9,10)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (9,8)-(9,9) = "z" │ │ │ │ ├── closing_loc: (9,9)-(9,10) = ":" diff --git a/test/prism/snapshots/spanning_heredoc.txt b/test/prism/snapshots/spanning_heredoc.txt index 6f499ffcea1d41..da930499d6ede8 100644 --- a/test/prism/snapshots/spanning_heredoc.txt +++ b/test/prism/snapshots/spanning_heredoc.txt @@ -260,13 +260,13 @@ │ │ ├── flags: ∅ │ │ ├── elements: (length: 2) │ │ │ ├── @ SymbolNode (location: (41,12)-(41,14)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (41,12)-(41,14) = "n\\" │ │ │ │ ├── closing_loc: ∅ │ │ │ │ └── unescaped: "n\n" │ │ │ └── @ SymbolNode (location: (44,0)-(44,1)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (44,0)-(44,1) = "n" │ │ │ ├── closing_loc: ∅ @@ -299,7 +299,7 @@ │ │ │ ├── opening_loc: ∅ │ │ │ ├── parts: (length: 2) │ │ │ │ ├── @ SymbolNode (location: (48,12)-(48,14)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (48,12)-(48,14) = "p\\" │ │ │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/spanning_heredoc_newlines.txt b/test/prism/snapshots/spanning_heredoc_newlines.txt index 07530890824745..171b0ff974c938 100644 --- a/test/prism/snapshots/spanning_heredoc_newlines.txt +++ b/test/prism/snapshots/spanning_heredoc_newlines.txt @@ -121,7 +121,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ SymbolNode (location: (17,4)-(20,0)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (17,4)-(18,0) = "%s\n" │ │ ├── value_loc: (18,0)-(18,0) = "" │ │ ├── closing_loc: (19,0)-(20,0) = "\n" diff --git a/test/prism/snapshots/strings.txt b/test/prism/snapshots/strings.txt index 47f26f439deae5..40a05ce09d5bbf 100644 --- a/test/prism/snapshots/strings.txt +++ b/test/prism/snapshots/strings.txt @@ -177,7 +177,7 @@ │ ├── closing_loc: (43,6)-(43,7) = "}" │ └── unescaped: "abc" ├── @ SymbolNode (location: (45,0)-(45,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (45,0)-(45,3) = "%s[" │ ├── value_loc: (45,3)-(45,6) = "abc" │ ├── closing_loc: (45,6)-(45,7) = "]" diff --git a/test/prism/snapshots/super.txt b/test/prism/snapshots/super.txt index 72ed5625bd5f26..a3e9069b4ac3af 100644 --- a/test/prism/snapshots/super.txt +++ b/test/prism/snapshots/super.txt @@ -46,7 +46,7 @@ │ @ BlockArgumentNode (location: (9,6)-(9,11)) │ ├── expression: │ │ @ SymbolNode (location: (9,7)-(9,11)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (9,7)-(9,8) = ":" │ │ ├── value_loc: (9,8)-(9,11) = "foo" │ │ ├── closing_loc: ∅ @@ -61,7 +61,7 @@ │ @ BlockArgumentNode (location: (11,6)-(11,11)) │ ├── expression: │ │ @ SymbolNode (location: (11,7)-(11,11)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (11,7)-(11,8) = ":" │ │ ├── value_loc: (11,8)-(11,11) = "foo" │ │ ├── closing_loc: ∅ @@ -116,7 +116,7 @@ @ BlockArgumentNode (location: (17,15)-(17,20)) ├── expression: │ @ SymbolNode (location: (17,16)-(17,20)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (17,16)-(17,17) = ":" │ ├── value_loc: (17,17)-(17,20) = "foo" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/symbols.txt b/test/prism/snapshots/symbols.txt index 6ca49b72a4cfec..54a385e34678ce 100644 --- a/test/prism/snapshots/symbols.txt +++ b/test/prism/snapshots/symbols.txt @@ -4,7 +4,7 @@ @ StatementsNode (location: (1,0)-(93,13)) └── body: (length: 47) ├── @ SymbolNode (location: (1,0)-(1,6)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,0)-(1,2) = ":'" │ ├── value_loc: (1,2)-(1,5) = "abc" │ ├── closing_loc: (1,5)-(1,6) = "'" @@ -77,61 +77,61 @@ │ ├── opening_loc: (7,0)-(7,1) = "[" │ └── closing_loc: (7,19)-(7,20) = "]" ├── @ SymbolNode (location: (9,0)-(9,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (9,0)-(9,1) = ":" │ ├── value_loc: (9,1)-(9,3) = "-@" │ ├── closing_loc: ∅ │ └── unescaped: "-@" ├── @ SymbolNode (location: (11,0)-(11,2)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (11,0)-(11,1) = ":" │ ├── value_loc: (11,1)-(11,2) = "-" │ ├── closing_loc: ∅ │ └── unescaped: "-" ├── @ SymbolNode (location: (13,0)-(13,2)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (13,0)-(13,1) = ":" │ ├── value_loc: (13,1)-(13,2) = "%" │ ├── closing_loc: ∅ │ └── unescaped: "%" ├── @ SymbolNode (location: (15,0)-(15,2)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (15,0)-(15,1) = ":" │ ├── value_loc: (15,1)-(15,2) = "|" │ ├── closing_loc: ∅ │ └── unescaped: "|" ├── @ SymbolNode (location: (17,0)-(17,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (17,0)-(17,1) = ":" │ ├── value_loc: (17,1)-(17,3) = "+@" │ ├── closing_loc: ∅ │ └── unescaped: "+@" ├── @ SymbolNode (location: (19,0)-(19,2)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (19,0)-(19,1) = ":" │ ├── value_loc: (19,1)-(19,2) = "+" │ ├── closing_loc: ∅ │ └── unescaped: "+" ├── @ SymbolNode (location: (21,0)-(21,2)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (21,0)-(21,1) = ":" │ ├── value_loc: (21,1)-(21,2) = "/" │ ├── closing_loc: ∅ │ └── unescaped: "/" ├── @ SymbolNode (location: (23,0)-(23,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (23,0)-(23,1) = ":" │ ├── value_loc: (23,1)-(23,3) = "**" │ ├── closing_loc: ∅ │ └── unescaped: "**" ├── @ SymbolNode (location: (25,0)-(25,2)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (25,0)-(25,1) = ":" │ ├── value_loc: (25,1)-(25,2) = "*" │ ├── closing_loc: ∅ │ └── unescaped: "*" ├── @ SymbolNode (location: (27,0)-(27,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (27,0)-(27,1) = ":" │ ├── value_loc: (27,1)-(27,3) = "~@" │ ├── closing_loc: ∅ @@ -153,13 +153,13 @@ │ ├── opening_loc: (29,0)-(29,1) = "[" │ └── closing_loc: (29,15)-(29,16) = "]" ├── @ SymbolNode (location: (31,0)-(31,2)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (31,0)-(31,1) = ":" │ ├── value_loc: (31,1)-(31,2) = "~" │ ├── closing_loc: ∅ │ └── unescaped: "~" ├── @ SymbolNode (location: (33,0)-(33,2)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (33,0)-(33,1) = ":" │ ├── value_loc: (33,1)-(33,2) = "a" │ ├── closing_loc: ∅ @@ -168,19 +168,19 @@ │ ├── flags: ∅ │ ├── elements: (length: 3) │ │ ├── @ SymbolNode (location: (35,3)-(35,4)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (35,3)-(35,4) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ ├── @ SymbolNode (location: (35,5)-(35,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (35,5)-(35,6) = "b" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "b" │ │ └── @ SymbolNode (location: (35,7)-(35,8)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (35,7)-(35,8) = "c" │ │ ├── closing_loc: ∅ @@ -191,25 +191,25 @@ │ ├── flags: ∅ │ ├── elements: (length: 4) │ │ ├── @ SymbolNode (location: (37,3)-(37,4)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (37,3)-(37,4) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ ├── @ SymbolNode (location: (37,5)-(37,10)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (37,5)-(37,10) = "b\#{1}" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "b\#{1}" │ │ ├── @ SymbolNode (location: (37,11)-(37,16)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (37,11)-(37,16) = "\#{2}c" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "\#{2}c" │ │ └── @ SymbolNode (location: (37,17)-(37,23)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (37,17)-(37,23) = "d\#{3}f" │ │ ├── closing_loc: ∅ @@ -220,7 +220,7 @@ │ ├── flags: ∅ │ ├── elements: (length: 4) │ │ ├── @ SymbolNode (location: (39,3)-(39,4)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (39,3)-(39,4) = "a" │ │ │ ├── closing_loc: ∅ @@ -288,7 +288,7 @@ │ ├── opening_loc: (39,0)-(39,3) = "%I[" │ └── closing_loc: (39,23)-(39,24) = "]" ├── @ SymbolNode (location: (41,0)-(41,4)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (41,0)-(41,1) = ":" │ ├── value_loc: (41,1)-(41,4) = "@@a" │ ├── closing_loc: ∅ @@ -303,7 +303,7 @@ │ ├── flags: ∅ │ ├── elements: (length: 1) │ │ └── @ SymbolNode (location: (45,3)-(45,6)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (45,3)-(45,6) = "a\\b" │ │ ├── closing_loc: ∅ @@ -311,145 +311,145 @@ │ ├── opening_loc: (45,0)-(45,3) = "%i[" │ └── closing_loc: (45,6)-(45,7) = "]" ├── @ SymbolNode (location: (47,0)-(47,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (47,0)-(47,1) = ":" │ ├── value_loc: (47,1)-(47,3) = "$a" │ ├── closing_loc: ∅ │ └── unescaped: "$a" ├── @ SymbolNode (location: (49,0)-(49,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (49,0)-(49,1) = ":" │ ├── value_loc: (49,1)-(49,3) = "@a" │ ├── closing_loc: ∅ │ └── unescaped: "@a" ├── @ SymbolNode (location: (51,0)-(51,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (51,0)-(51,1) = ":" │ ├── value_loc: (51,1)-(51,3) = "do" │ ├── closing_loc: ∅ │ └── unescaped: "do" ├── @ SymbolNode (location: (53,0)-(53,2)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (53,0)-(53,1) = ":" │ ├── value_loc: (53,1)-(53,2) = "&" │ ├── closing_loc: ∅ │ └── unescaped: "&" ├── @ SymbolNode (location: (55,0)-(55,2)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (55,0)-(55,1) = ":" │ ├── value_loc: (55,1)-(55,2) = "`" │ ├── closing_loc: ∅ │ └── unescaped: "`" ├── @ SymbolNode (location: (57,0)-(57,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (57,0)-(57,1) = ":" │ ├── value_loc: (57,1)-(57,3) = "!@" │ ├── closing_loc: ∅ │ └── unescaped: "!" ├── @ SymbolNode (location: (59,0)-(59,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (59,0)-(59,1) = ":" │ ├── value_loc: (59,1)-(59,3) = "!~" │ ├── closing_loc: ∅ │ └── unescaped: "!~" ├── @ SymbolNode (location: (61,0)-(61,2)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (61,0)-(61,1) = ":" │ ├── value_loc: (61,1)-(61,2) = "!" │ ├── closing_loc: ∅ │ └── unescaped: "!" ├── @ SymbolNode (location: (63,0)-(63,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (63,0)-(63,1) = ":" │ ├── value_loc: (63,1)-(63,3) = "[]" │ ├── closing_loc: ∅ │ └── unescaped: "[]" ├── @ SymbolNode (location: (65,0)-(65,4)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (65,0)-(65,1) = ":" │ ├── value_loc: (65,1)-(65,4) = "[]=" │ ├── closing_loc: ∅ │ └── unescaped: "[]=" ├── @ SymbolNode (location: (67,0)-(67,2)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (67,0)-(67,1) = ":" │ ├── value_loc: (67,1)-(67,2) = "^" │ ├── closing_loc: ∅ │ └── unescaped: "^" ├── @ SymbolNode (location: (69,0)-(69,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (69,0)-(69,1) = ":" │ ├── value_loc: (69,1)-(69,3) = "==" │ ├── closing_loc: ∅ │ └── unescaped: "==" ├── @ SymbolNode (location: (71,0)-(71,4)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (71,0)-(71,1) = ":" │ ├── value_loc: (71,1)-(71,4) = "===" │ ├── closing_loc: ∅ │ └── unescaped: "===" ├── @ SymbolNode (location: (73,0)-(73,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (73,0)-(73,1) = ":" │ ├── value_loc: (73,1)-(73,3) = "=~" │ ├── closing_loc: ∅ │ └── unescaped: "=~" ├── @ SymbolNode (location: (75,0)-(75,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (75,0)-(75,1) = ":" │ ├── value_loc: (75,1)-(75,3) = ">=" │ ├── closing_loc: ∅ │ └── unescaped: ">=" ├── @ SymbolNode (location: (77,0)-(77,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (77,0)-(77,1) = ":" │ ├── value_loc: (77,1)-(77,3) = ">>" │ ├── closing_loc: ∅ │ └── unescaped: ">>" ├── @ SymbolNode (location: (79,0)-(79,2)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (79,0)-(79,1) = ":" │ ├── value_loc: (79,1)-(79,2) = ">" │ ├── closing_loc: ∅ │ └── unescaped: ">" ├── @ SymbolNode (location: (81,0)-(81,4)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (81,0)-(81,1) = ":" │ ├── value_loc: (81,1)-(81,4) = "<=>" │ ├── closing_loc: ∅ │ └── unescaped: "<=>" ├── @ SymbolNode (location: (83,0)-(83,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (83,0)-(83,1) = ":" │ ├── value_loc: (83,1)-(83,3) = "<=" │ ├── closing_loc: ∅ │ └── unescaped: "<=" ├── @ SymbolNode (location: (85,0)-(85,3)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (85,0)-(85,1) = ":" │ ├── value_loc: (85,1)-(85,3) = "<<" │ ├── closing_loc: ∅ │ └── unescaped: "<<" ├── @ SymbolNode (location: (87,0)-(87,2)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (87,0)-(87,1) = ":" │ ├── value_loc: (87,1)-(87,2) = "<" │ ├── closing_loc: ∅ │ └── unescaped: "<" ├── @ SymbolNode (location: (89,0)-(89,9)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (89,0)-(89,1) = ":" │ ├── value_loc: (89,1)-(89,9) = "__LINE__" │ ├── closing_loc: ∅ │ └── unescaped: "__LINE__" ├── @ SymbolNode (location: (91,0)-(91,9)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (91,0)-(91,1) = ":" │ ├── value_loc: (91,1)-(91,9) = "__FILE__" │ ├── closing_loc: ∅ │ └── unescaped: "__FILE__" └── @ SymbolNode (location: (93,0)-(93,13)) - ├── flags: ∅ + ├── flags: forced_us_ascii_encoding ├── opening_loc: (93,0)-(93,1) = ":" ├── value_loc: (93,1)-(93,13) = "__ENCODING__" ├── closing_loc: ∅ diff --git a/test/prism/snapshots/undef.txt b/test/prism/snapshots/undef.txt index 2bb369d7d828f2..fb62b9acb52ec5 100644 --- a/test/prism/snapshots/undef.txt +++ b/test/prism/snapshots/undef.txt @@ -39,7 +39,7 @@ ├── @ UndefNode (location: (7,0)-(7,9)) │ ├── names: (length: 1) │ │ └── @ SymbolNode (location: (7,6)-(7,9)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (7,6)-(7,9) = "<=>" │ │ ├── closing_loc: ∅ @@ -48,7 +48,7 @@ ├── @ UndefNode (location: (9,0)-(9,8)) │ ├── names: (length: 1) │ │ └── @ SymbolNode (location: (9,6)-(9,8)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (9,6)-(9,7) = ":" │ │ ├── value_loc: (9,7)-(9,8) = "a" │ │ ├── closing_loc: ∅ @@ -57,19 +57,19 @@ ├── @ UndefNode (location: (11,0)-(11,16)) │ ├── names: (length: 3) │ │ ├── @ SymbolNode (location: (11,6)-(11,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (11,6)-(11,7) = ":" │ │ │ ├── value_loc: (11,7)-(11,8) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ ├── @ SymbolNode (location: (11,10)-(11,12)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (11,10)-(11,11) = ":" │ │ │ ├── value_loc: (11,11)-(11,12) = "b" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "b" │ │ └── @ SymbolNode (location: (11,14)-(11,16)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (11,14)-(11,15) = ":" │ │ ├── value_loc: (11,15)-(11,16) = "c" │ │ ├── closing_loc: ∅ @@ -78,7 +78,7 @@ ├── @ UndefNode (location: (13,0)-(13,12)) │ ├── names: (length: 1) │ │ └── @ SymbolNode (location: (13,6)-(13,12)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (13,6)-(13,8) = ":'" │ │ ├── value_loc: (13,8)-(13,11) = "abc" │ │ ├── closing_loc: (13,11)-(13,12) = "'" diff --git a/test/prism/snapshots/unless.txt b/test/prism/snapshots/unless.txt index 7deb8f79594e27..0439e12d379b4b 100644 --- a/test/prism/snapshots/unless.txt +++ b/test/prism/snapshots/unless.txt @@ -115,13 +115,13 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ SymbolNode (location: (14,4)-(14,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (14,4)-(14,5) = ":" │ │ │ ├── value_loc: (14,5)-(14,6) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ └── @ SymbolNode (location: (14,8)-(14,10)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (14,8)-(14,9) = ":" │ │ ├── value_loc: (14,9)-(14,10) = "b" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/alias.txt b/test/prism/snapshots/unparser/corpus/literal/alias.txt index 68ee27f7f95b8c..18ddc86d4f4817 100644 --- a/test/prism/snapshots/unparser/corpus/literal/alias.txt +++ b/test/prism/snapshots/unparser/corpus/literal/alias.txt @@ -14,14 +14,14 @@ └── @ AliasMethodNode (location: (2,0)-(2,15)) ├── new_name: │ @ SymbolNode (location: (2,6)-(2,10)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (2,6)-(2,7) = ":" │ ├── value_loc: (2,7)-(2,10) = "foo" │ ├── closing_loc: ∅ │ └── unescaped: "foo" ├── old_name: │ @ SymbolNode (location: (2,11)-(2,15)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (2,11)-(2,12) = ":" │ ├── value_loc: (2,12)-(2,15) = "bar" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/case.txt b/test/prism/snapshots/unparser/corpus/literal/case.txt index ee5866a15866d8..d9990e59234198 100644 --- a/test/prism/snapshots/unparser/corpus/literal/case.txt +++ b/test/prism/snapshots/unparser/corpus/literal/case.txt @@ -225,7 +225,7 @@ │ │ @ StatementsNode (location: (20,2)-(20,8)) │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (20,2)-(20,8)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (20,2)-(20,3) = ":" │ │ ├── value_loc: (20,3)-(20,8) = "other" │ │ ├── closing_loc: ∅ @@ -266,7 +266,7 @@ │ │ @ StatementsNode (location: (24,2)-(24,8)) │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (24,2)-(24,8)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (24,2)-(24,3) = ":" │ │ ├── value_loc: (24,3)-(24,8) = "value" │ │ ├── closing_loc: ∅ @@ -320,7 +320,7 @@ │ │ │ @ StatementsNode (location: (30,2)-(30,6)) │ │ │ └── body: (length: 1) │ │ │ └── @ SymbolNode (location: (30,2)-(30,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (30,2)-(30,3) = ":" │ │ │ ├── value_loc: (30,3)-(30,6) = "foo" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/class.txt b/test/prism/snapshots/unparser/corpus/literal/class.txt index ce22483410fdaa..bb967ca69af5f8 100644 --- a/test/prism/snapshots/unparser/corpus/literal/class.txt +++ b/test/prism/snapshots/unparser/corpus/literal/class.txt @@ -202,7 +202,7 @@ │ │ │ @ StatementsNode (location: (30,4)-(30,8)) │ │ │ └── body: (length: 1) │ │ │ └── @ SymbolNode (location: (30,4)-(30,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (30,4)-(30,5) = ":" │ │ │ ├── value_loc: (30,5)-(30,8) = "bar" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/if.txt b/test/prism/snapshots/unparser/corpus/literal/if.txt index 08682ab155d8cb..e4f60f7d2800fb 100644 --- a/test/prism/snapshots/unparser/corpus/literal/if.txt +++ b/test/prism/snapshots/unparser/corpus/literal/if.txt @@ -268,7 +268,7 @@ │ │ ├── name_loc: (34,2)-(34,6) = "pair" │ │ ├── value: │ │ │ @ SymbolNode (location: (34,9)-(34,13)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (34,9)-(34,10) = ":" │ │ │ ├── value_loc: (34,10)-(34,13) = "foo" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/kwbegin.txt b/test/prism/snapshots/unparser/corpus/literal/kwbegin.txt index 130dc4e08ad8e3..48e53af00e4e0f 100644 --- a/test/prism/snapshots/unparser/corpus/literal/kwbegin.txt +++ b/test/prism/snapshots/unparser/corpus/literal/kwbegin.txt @@ -479,7 +479,7 @@ │ │ @ UndefNode (location: (79,2)-(79,12)) │ │ ├── names: (length: 1) │ │ │ └── @ SymbolNode (location: (79,8)-(79,12)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (79,8)-(79,9) = ":" │ │ │ ├── value_loc: (79,9)-(79,12) = "bar" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/literal.txt b/test/prism/snapshots/unparser/corpus/literal/literal.txt index c9bb0b0153b471..17df1565c50741 100644 --- a/test/prism/snapshots/unparser/corpus/literal/literal.txt +++ b/test/prism/snapshots/unparser/corpus/literal/literal.txt @@ -46,7 +46,7 @@ │ │ │ └── unescaped: "bar" │ │ ├── value: │ │ │ @ SymbolNode (location: (1,32)-(1,36)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,32)-(1,33) = ":" │ │ │ ├── value_loc: (1,33)-(1,36) = "baz" │ │ │ ├── closing_loc: ∅ @@ -82,7 +82,7 @@ │ │ │ └── unescaped: "bar" │ │ ├── value: │ │ │ @ SymbolNode (location: (4,25)-(4,29)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (4,25)-(4,26) = ":" │ │ │ ├── value_loc: (4,26)-(4,29) = "baz" │ │ │ ├── closing_loc: ∅ @@ -516,31 +516,31 @@ │ ├── closing_loc: (42,2)-(42,3) = "`" │ └── unescaped: "\"" ├── @ SymbolNode (location: (43,0)-(43,4)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (43,0)-(43,1) = ":" │ ├── value_loc: (43,1)-(43,4) = "foo" │ ├── closing_loc: ∅ │ └── unescaped: "foo" ├── @ SymbolNode (location: (44,0)-(44,6)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (44,0)-(44,2) = ":\"" │ ├── value_loc: (44,2)-(44,5) = "A B" │ ├── closing_loc: (44,5)-(44,6) = "\"" │ └── unescaped: "A B" ├── @ SymbolNode (location: (45,0)-(45,4)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (45,0)-(45,1) = ":" │ ├── value_loc: (45,1)-(45,4) = "foo" │ ├── closing_loc: ∅ │ └── unescaped: "foo" ├── @ SymbolNode (location: (46,0)-(46,6)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (46,0)-(46,2) = ":\"" │ ├── value_loc: (46,2)-(46,5) = "A B" │ ├── closing_loc: (46,5)-(46,6) = "\"" │ └── unescaped: "A B" ├── @ SymbolNode (location: (47,0)-(47,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (47,0)-(47,2) = ":\"" │ ├── value_loc: (47,2)-(47,6) = "A\\\"B" │ ├── closing_loc: (47,6)-(47,7) = "\"" @@ -915,7 +915,7 @@ │ │ ├── @ AssocNode (location: (76,2)-(76,19)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (76,2)-(76,4)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (76,2)-(76,3) = "a" │ │ │ │ ├── closing_loc: (76,3)-(76,4) = ":" @@ -947,7 +947,7 @@ │ │ └── @ AssocNode (location: (76,21)-(76,25)) │ │ ├── key: │ │ │ @ SymbolNode (location: (76,21)-(76,23)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (76,21)-(76,22) = "b" │ │ │ ├── closing_loc: (76,22)-(76,23) = ":" @@ -963,7 +963,7 @@ │ │ ├── @ AssocNode (location: (77,2)-(77,6)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (77,2)-(77,4)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (77,2)-(77,3) = "a" │ │ │ │ ├── closing_loc: (77,3)-(77,4) = ":" @@ -975,7 +975,7 @@ │ │ └── @ AssocNode (location: (77,8)-(77,12)) │ │ ├── key: │ │ │ @ SymbolNode (location: (77,8)-(77,10)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (77,8)-(77,9) = "b" │ │ │ ├── closing_loc: (77,9)-(77,10) = ":" @@ -991,14 +991,14 @@ │ │ └── @ AssocNode (location: (78,2)-(78,7)) │ │ ├── key: │ │ │ @ SymbolNode (location: (78,2)-(78,4)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (78,2)-(78,3) = "a" │ │ │ ├── closing_loc: (78,3)-(78,4) = ":" │ │ │ └── unescaped: "a" │ │ ├── value: │ │ │ @ SymbolNode (location: (78,5)-(78,7)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (78,5)-(78,6) = ":" │ │ │ ├── value_loc: (78,6)-(78,7) = "a" │ │ │ ├── closing_loc: ∅ @@ -1011,7 +1011,7 @@ │ │ └── @ AssocNode (location: (79,2)-(79,13)) │ │ ├── key: │ │ │ @ SymbolNode (location: (79,2)-(79,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (79,2)-(79,4) = ":\"" │ │ │ ├── value_loc: (79,4)-(79,7) = "a b" │ │ │ ├── closing_loc: (79,7)-(79,8) = "\"" @@ -1027,7 +1027,7 @@ │ │ └── @ AssocNode (location: (80,2)-(80,10)) │ │ ├── key: │ │ │ @ SymbolNode (location: (80,2)-(80,5)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (80,2)-(80,3) = ":" │ │ │ ├── value_loc: (80,3)-(80,5) = "-@" │ │ │ ├── closing_loc: ∅ @@ -1105,7 +1105,7 @@ │ ├── opening_loc: (83,4)-(83,5) = "{" │ └── closing_loc: (86,0)-(86,1) = "}" ├── @ SymbolNode (location: (87,0)-(88,2)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (87,0)-(87,2) = ":\"" │ ├── value_loc: (87,2)-(88,1) = "a\\\\\nb" │ ├── closing_loc: (88,1)-(88,2) = "\"" diff --git a/test/prism/snapshots/unparser/corpus/literal/module.txt b/test/prism/snapshots/unparser/corpus/literal/module.txt index 83766b1def1ef2..178d27ce974242 100644 --- a/test/prism/snapshots/unparser/corpus/literal/module.txt +++ b/test/prism/snapshots/unparser/corpus/literal/module.txt @@ -91,7 +91,7 @@ │ │ @ StatementsNode (location: (14,4)-(14,8)) │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (14,4)-(14,8)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (14,4)-(14,5) = ":" │ │ ├── value_loc: (14,5)-(14,8) = "bar" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/pattern.txt b/test/prism/snapshots/unparser/corpus/literal/pattern.txt index b55309472aeb64..d89ef39c90b06c 100644 --- a/test/prism/snapshots/unparser/corpus/literal/pattern.txt +++ b/test/prism/snapshots/unparser/corpus/literal/pattern.txt @@ -84,7 +84,7 @@ │ │ │ │ │ └── @ AssocNode (location: (6,5)-(6,7)) │ │ │ │ │ ├── key: │ │ │ │ │ │ @ SymbolNode (location: (6,5)-(6,7)) - │ │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ │ ├── value_loc: (6,5)-(6,6) = "x" │ │ │ │ │ │ ├── closing_loc: (6,6)-(6,7) = ":" @@ -181,7 +181,7 @@ │ │ │ │ │ ├── @ AssocNode (location: (14,4)-(14,8)) │ │ │ │ │ │ ├── key: │ │ │ │ │ │ │ @ SymbolNode (location: (14,4)-(14,6)) - │ │ │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ │ │ ├── value_loc: (14,4)-(14,5) = "a" │ │ │ │ │ │ │ ├── closing_loc: (14,5)-(14,6) = ":" @@ -193,7 +193,7 @@ │ │ │ │ │ └── @ AssocNode (location: (14,10)-(14,15)) │ │ │ │ │ ├── key: │ │ │ │ │ │ @ SymbolNode (location: (14,10)-(14,13)) - │ │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ │ ├── value_loc: (14,10)-(14,12) = "aa" │ │ │ │ │ │ ├── closing_loc: (14,12)-(14,13) = ":" @@ -250,7 +250,7 @@ │ │ │ │ │ └── @ AssocNode (location: (20,4)-(20,10)) │ │ │ │ │ ├── key: │ │ │ │ │ │ @ SymbolNode (location: (20,4)-(20,8)) - │ │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ │ ├── opening_loc: (20,4)-(20,5) = "\"" │ │ │ │ │ │ ├── value_loc: (20,5)-(20,6) = "a" │ │ │ │ │ │ ├── closing_loc: (20,6)-(20,8) = "\":" diff --git a/test/prism/snapshots/unparser/corpus/literal/send.txt b/test/prism/snapshots/unparser/corpus/literal/send.txt index cdb95cd491ca90..d2a744c6875034 100644 --- a/test/prism/snapshots/unparser/corpus/literal/send.txt +++ b/test/prism/snapshots/unparser/corpus/literal/send.txt @@ -170,7 +170,7 @@ │ │ │ │ │ ├── equal_loc: ∅ │ │ │ │ │ └── end_keyword_loc: (17,0)-(17,3) = "end" │ │ │ │ └── @ SymbolNode (location: (17,5)-(17,9)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (17,5)-(17,6) = ":" │ │ │ │ ├── value_loc: (17,6)-(17,9) = "bar" │ │ │ │ ├── closing_loc: ∅ @@ -440,7 +440,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ SymbolNode (location: (37,10)-(37,14)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (37,10)-(37,11) = ":" │ │ │ │ ├── value_loc: (37,11)-(37,14) = "foo" │ │ │ │ ├── closing_loc: ∅ @@ -544,7 +544,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ SymbolNode (location: (40,9)-(40,13)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (40,9)-(40,10) = ":" │ │ ├── value_loc: (40,10)-(40,13) = "foo" │ │ ├── closing_loc: ∅ @@ -1207,7 +1207,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ SymbolNode (location: (62,8)-(62,12)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (62,8)-(62,9) = ":" │ │ ├── value_loc: (62,9)-(62,12) = "baz" │ │ ├── closing_loc: ∅ @@ -1254,7 +1254,7 @@ │ │ └── @ AssocNode (location: (63,8)-(63,16)) │ │ ├── key: │ │ │ @ SymbolNode (location: (63,8)-(63,12)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (63,8)-(63,11) = "baz" │ │ │ ├── closing_loc: (63,11)-(63,12) = ":" @@ -1498,7 +1498,7 @@ │ │ │ │ └── @ AssocNode (location: (68,10)-(68,18)) │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (68,10)-(68,14)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (68,10)-(68,13) = "foo" │ │ │ │ │ ├── closing_loc: (68,13)-(68,14) = ":" @@ -1550,7 +1550,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ SymbolNode (location: (69,8)-(69,12)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (69,8)-(69,9) = ":" │ │ ├── value_loc: (69,9)-(69,12) = "baz" │ │ ├── closing_loc: ∅ @@ -1574,7 +1574,7 @@ │ │ └── @ AssocNode (location: (70,4)-(70,8)) │ │ ├── key: │ │ │ @ SymbolNode (location: (70,4)-(70,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (70,4)-(70,5) = "a" │ │ │ ├── closing_loc: (70,5)-(70,6) = ":" @@ -1620,7 +1620,7 @@ │ │ └── @ AssocNode (location: (71,6)-(71,10)) │ │ ├── key: │ │ │ @ SymbolNode (location: (71,6)-(71,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (71,6)-(71,7) = "a" │ │ │ ├── closing_loc: (71,7)-(71,8) = ":" @@ -1785,7 +1785,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ SymbolNode (location: (77,9)-(77,13)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (77,9)-(77,10) = ":" │ │ ├── value_loc: (77,10)-(77,13) = "bar" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/undef.txt b/test/prism/snapshots/unparser/corpus/literal/undef.txt index 4133ea0a345c62..282cbe8f8725a7 100644 --- a/test/prism/snapshots/unparser/corpus/literal/undef.txt +++ b/test/prism/snapshots/unparser/corpus/literal/undef.txt @@ -6,7 +6,7 @@ ├── @ UndefNode (location: (1,0)-(1,10)) │ ├── names: (length: 1) │ │ └── @ SymbolNode (location: (1,6)-(1,10)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,6)-(1,7) = ":" │ │ ├── value_loc: (1,7)-(1,10) = "foo" │ │ ├── closing_loc: ∅ @@ -15,13 +15,13 @@ └── @ UndefNode (location: (2,0)-(2,16)) ├── names: (length: 2) │ ├── @ SymbolNode (location: (2,6)-(2,10)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (2,6)-(2,7) = ":" │ │ ├── value_loc: (2,7)-(2,10) = "foo" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "foo" │ └── @ SymbolNode (location: (2,12)-(2,16)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (2,12)-(2,13) = ":" │ ├── value_loc: (2,13)-(2,16) = "bar" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/unparser/corpus/literal/while.txt b/test/prism/snapshots/unparser/corpus/literal/while.txt index ac015b1cc6a533..b2138fe9f3959c 100644 --- a/test/prism/snapshots/unparser/corpus/literal/while.txt +++ b/test/prism/snapshots/unparser/corpus/literal/while.txt @@ -646,7 +646,7 @@ │ @ StatementsNode (location: (63,2)-(63,7)) │ └── body: (length: 1) │ └── @ SymbolNode (location: (63,2)-(63,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (63,2)-(63,3) = ":" │ ├── value_loc: (63,3)-(63,7) = "body" │ ├── closing_loc: ∅ @@ -701,7 +701,7 @@ @ StatementsNode (location: (72,2)-(72,7)) └── body: (length: 1) └── @ SymbolNode (location: (72,2)-(72,7)) - ├── flags: ∅ + ├── flags: forced_us_ascii_encoding ├── opening_loc: (72,2)-(72,3) = ":" ├── value_loc: (72,3)-(72,7) = "body" ├── closing_loc: ∅ diff --git a/test/prism/snapshots/until.txt b/test/prism/snapshots/until.txt index 178502751a281c..bb3987a0455548 100644 --- a/test/prism/snapshots/until.txt +++ b/test/prism/snapshots/until.txt @@ -91,13 +91,13 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ SymbolNode (location: (11,4)-(11,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (11,4)-(11,5) = ":" │ │ │ ├── value_loc: (11,5)-(11,6) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ └── @ SymbolNode (location: (11,8)-(11,10)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (11,8)-(11,9) = ":" │ │ ├── value_loc: (11,9)-(11,10) = "b" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/while.txt b/test/prism/snapshots/while.txt index a2919154f2a3a5..e403efe869a710 100644 --- a/test/prism/snapshots/while.txt +++ b/test/prism/snapshots/while.txt @@ -91,13 +91,13 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ SymbolNode (location: (11,4)-(11,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (11,4)-(11,5) = ":" │ │ │ ├── value_loc: (11,5)-(11,6) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ └── @ SymbolNode (location: (11,8)-(11,10)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (11,8)-(11,9) = ":" │ │ ├── value_loc: (11,9)-(11,10) = "b" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/alias.txt b/test/prism/snapshots/whitequark/alias.txt index 6c529a358940c5..509ea2b6334fd9 100644 --- a/test/prism/snapshots/whitequark/alias.txt +++ b/test/prism/snapshots/whitequark/alias.txt @@ -6,14 +6,14 @@ └── @ AliasMethodNode (location: (1,0)-(1,14)) ├── new_name: │ @ SymbolNode (location: (1,6)-(1,10)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,6)-(1,7) = ":" │ ├── value_loc: (1,7)-(1,10) = "foo" │ ├── closing_loc: ∅ │ └── unescaped: "foo" ├── old_name: │ @ SymbolNode (location: (1,11)-(1,14)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: ∅ │ ├── value_loc: (1,11)-(1,14) = "bar" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/arg_label.txt b/test/prism/snapshots/whitequark/arg_label.txt index 4b650190476c02..16366c6e3c7928 100644 --- a/test/prism/snapshots/whitequark/arg_label.txt +++ b/test/prism/snapshots/whitequark/arg_label.txt @@ -23,7 +23,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ SymbolNode (location: (2,2)-(2,4)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (2,2)-(2,3) = ":" │ │ │ ├── value_loc: (2,3)-(2,4) = "b" │ │ │ ├── closing_loc: ∅ @@ -58,7 +58,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ SymbolNode (location: (4,11)-(4,13)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (4,11)-(4,12) = ":" │ │ │ ├── value_loc: (4,12)-(4,13) = "b" │ │ │ ├── closing_loc: ∅ @@ -107,7 +107,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ SymbolNode (location: (6,8)-(6,10)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (6,8)-(6,9) = ":" │ │ ├── value_loc: (6,9)-(6,10) = "b" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/args_args_assocs.txt b/test/prism/snapshots/whitequark/args_args_assocs.txt index 951d1a0a4aae8e..3520b0e67275ac 100644 --- a/test/prism/snapshots/whitequark/args_args_assocs.txt +++ b/test/prism/snapshots/whitequark/args_args_assocs.txt @@ -30,7 +30,7 @@ │ │ └── @ AssocNode (location: (1,9)-(1,18)) │ │ ├── key: │ │ │ @ SymbolNode (location: (1,9)-(1,13)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,9)-(1,10) = ":" │ │ │ ├── value_loc: (1,10)-(1,13) = "foo" │ │ │ ├── closing_loc: ∅ @@ -68,7 +68,7 @@ │ └── @ AssocNode (location: (3,9)-(3,18)) │ ├── key: │ │ @ SymbolNode (location: (3,9)-(3,13)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (3,9)-(3,10) = ":" │ │ ├── value_loc: (3,10)-(3,13) = "foo" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/args_args_assocs_comma.txt b/test/prism/snapshots/whitequark/args_args_assocs_comma.txt index 2e16454a083484..3e9f0a8f9fc39c 100644 --- a/test/prism/snapshots/whitequark/args_args_assocs_comma.txt +++ b/test/prism/snapshots/whitequark/args_args_assocs_comma.txt @@ -40,7 +40,7 @@ │ └── @ AssocNode (location: (1,9)-(1,18)) │ ├── key: │ │ @ SymbolNode (location: (1,9)-(1,13)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,9)-(1,10) = ":" │ │ ├── value_loc: (1,10)-(1,13) = "baz" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/args_assocs.txt b/test/prism/snapshots/whitequark/args_assocs.txt index 68ef7bb1d78ee1..6d8bd6b1bddbce 100644 --- a/test/prism/snapshots/whitequark/args_assocs.txt +++ b/test/prism/snapshots/whitequark/args_assocs.txt @@ -20,7 +20,7 @@ │ │ └── @ AssocNode (location: (1,4)-(1,13)) │ │ ├── key: │ │ │ @ SymbolNode (location: (1,4)-(1,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,4)-(1,5) = ":" │ │ │ ├── value_loc: (1,5)-(1,8) = "foo" │ │ │ ├── closing_loc: ∅ @@ -48,7 +48,7 @@ │ │ └── @ AssocNode (location: (3,4)-(3,13)) │ │ ├── key: │ │ │ @ SymbolNode (location: (3,4)-(3,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (3,4)-(3,5) = ":" │ │ │ ├── value_loc: (3,5)-(3,8) = "foo" │ │ │ ├── closing_loc: ∅ @@ -100,7 +100,7 @@ │ │ └── @ AssocNode (location: (5,14)-(5,21)) │ │ ├── key: │ │ │ @ SymbolNode (location: (5,14)-(5,16)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (5,14)-(5,15) = ":" │ │ │ ├── value_loc: (5,15)-(5,16) = "a" │ │ │ ├── closing_loc: ∅ @@ -129,7 +129,7 @@ │ │ └── @ AssocNode (location: (7,5)-(7,14)) │ │ ├── key: │ │ │ @ SymbolNode (location: (7,5)-(7,9)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (7,5)-(7,6) = ":" │ │ │ ├── value_loc: (7,6)-(7,9) = "bar" │ │ │ ├── closing_loc: ∅ @@ -153,7 +153,7 @@ │ │ └── @ AssocNode (location: (9,6)-(9,16)) │ │ ├── key: │ │ │ @ SymbolNode (location: (9,6)-(9,10)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (9,6)-(9,7) = ":" │ │ │ ├── value_loc: (9,7)-(9,10) = "foo" │ │ │ ├── closing_loc: ∅ @@ -177,7 +177,7 @@ │ └── @ AssocNode (location: (11,6)-(11,16)) │ ├── key: │ │ @ SymbolNode (location: (11,6)-(11,10)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (11,6)-(11,7) = ":" │ │ ├── value_loc: (11,7)-(11,10) = "foo" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/args_assocs_comma.txt b/test/prism/snapshots/whitequark/args_assocs_comma.txt index a94dde32457237..bea6e8b3006d47 100644 --- a/test/prism/snapshots/whitequark/args_assocs_comma.txt +++ b/test/prism/snapshots/whitequark/args_assocs_comma.txt @@ -30,7 +30,7 @@ │ └── @ AssocNode (location: (1,4)-(1,13)) │ ├── key: │ │ @ SymbolNode (location: (1,4)-(1,8)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,4)-(1,5) = ":" │ │ ├── value_loc: (1,5)-(1,8) = "baz" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/args_assocs_legacy.txt b/test/prism/snapshots/whitequark/args_assocs_legacy.txt index 68ef7bb1d78ee1..6d8bd6b1bddbce 100644 --- a/test/prism/snapshots/whitequark/args_assocs_legacy.txt +++ b/test/prism/snapshots/whitequark/args_assocs_legacy.txt @@ -20,7 +20,7 @@ │ │ └── @ AssocNode (location: (1,4)-(1,13)) │ │ ├── key: │ │ │ @ SymbolNode (location: (1,4)-(1,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,4)-(1,5) = ":" │ │ │ ├── value_loc: (1,5)-(1,8) = "foo" │ │ │ ├── closing_loc: ∅ @@ -48,7 +48,7 @@ │ │ └── @ AssocNode (location: (3,4)-(3,13)) │ │ ├── key: │ │ │ @ SymbolNode (location: (3,4)-(3,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (3,4)-(3,5) = ":" │ │ │ ├── value_loc: (3,5)-(3,8) = "foo" │ │ │ ├── closing_loc: ∅ @@ -100,7 +100,7 @@ │ │ └── @ AssocNode (location: (5,14)-(5,21)) │ │ ├── key: │ │ │ @ SymbolNode (location: (5,14)-(5,16)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (5,14)-(5,15) = ":" │ │ │ ├── value_loc: (5,15)-(5,16) = "a" │ │ │ ├── closing_loc: ∅ @@ -129,7 +129,7 @@ │ │ └── @ AssocNode (location: (7,5)-(7,14)) │ │ ├── key: │ │ │ @ SymbolNode (location: (7,5)-(7,9)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (7,5)-(7,6) = ":" │ │ │ ├── value_loc: (7,6)-(7,9) = "bar" │ │ │ ├── closing_loc: ∅ @@ -153,7 +153,7 @@ │ │ └── @ AssocNode (location: (9,6)-(9,16)) │ │ ├── key: │ │ │ @ SymbolNode (location: (9,6)-(9,10)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (9,6)-(9,7) = ":" │ │ │ ├── value_loc: (9,7)-(9,10) = "foo" │ │ │ ├── closing_loc: ∅ @@ -177,7 +177,7 @@ │ └── @ AssocNode (location: (11,6)-(11,16)) │ ├── key: │ │ @ SymbolNode (location: (11,6)-(11,10)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (11,6)-(11,7) = ":" │ │ ├── value_loc: (11,7)-(11,10) = "foo" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/array_symbols.txt b/test/prism/snapshots/whitequark/array_symbols.txt index 9eeaa3e69a1c18..0662f01af1dc6d 100644 --- a/test/prism/snapshots/whitequark/array_symbols.txt +++ b/test/prism/snapshots/whitequark/array_symbols.txt @@ -7,13 +7,13 @@ ├── flags: ∅ ├── elements: (length: 2) │ ├── @ SymbolNode (location: (1,3)-(1,6)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,3)-(1,6) = "foo" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "foo" │ └── @ SymbolNode (location: (1,7)-(1,10)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: ∅ │ ├── value_loc: (1,7)-(1,10) = "bar" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/array_symbols_interp.txt b/test/prism/snapshots/whitequark/array_symbols_interp.txt index 6e872446c4cb17..7583ad8833e17d 100644 --- a/test/prism/snapshots/whitequark/array_symbols_interp.txt +++ b/test/prism/snapshots/whitequark/array_symbols_interp.txt @@ -7,7 +7,7 @@ │ ├── flags: ∅ │ ├── elements: (length: 2) │ │ ├── @ SymbolNode (location: (1,3)-(1,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (1,3)-(1,6) = "foo" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/bug_cmdarg.txt b/test/prism/snapshots/whitequark/bug_cmdarg.txt index addff0390834cd..c3fa59949a7aa7 100644 --- a/test/prism/snapshots/whitequark/bug_cmdarg.txt +++ b/test/prism/snapshots/whitequark/bug_cmdarg.txt @@ -20,7 +20,7 @@ │ │ └── @ AssocNode (location: (1,7)-(1,15)) │ │ ├── key: │ │ │ @ SymbolNode (location: (1,7)-(1,10)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (1,7)-(1,9) = "do" │ │ │ ├── closing_loc: (1,9)-(1,10) = ":" @@ -70,7 +70,7 @@ │ └── @ AssocNode (location: (5,2)-(5,26)) │ ├── key: │ │ @ SymbolNode (location: (5,2)-(5,4)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (5,2)-(5,3) = "x" │ │ ├── closing_loc: (5,3)-(5,4) = ":" diff --git a/test/prism/snapshots/whitequark/bug_do_block_in_hash_brace.txt b/test/prism/snapshots/whitequark/bug_do_block_in_hash_brace.txt index 2244d6f8aa5195..1b26346abf4cb0 100644 --- a/test/prism/snapshots/whitequark/bug_do_block_in_hash_brace.txt +++ b/test/prism/snapshots/whitequark/bug_do_block_in_hash_brace.txt @@ -15,7 +15,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ SymbolNode (location: (1,2)-(1,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (1,2)-(1,3) = ":" │ │ │ ├── value_loc: (1,3)-(1,6) = "foo" │ │ │ ├── closing_loc: ∅ @@ -26,7 +26,7 @@ │ │ │ ├── @ AssocNode (location: (1,9)-(1,25)) │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (1,9)-(1,13)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (1,9)-(1,10) = "\"" │ │ │ │ │ ├── value_loc: (1,10)-(1,11) = "a" │ │ │ │ │ ├── closing_loc: (1,11)-(1,13) = "\":" @@ -53,7 +53,7 @@ │ │ │ └── @ AssocNode (location: (1,27)-(1,41)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (1,27)-(1,29)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (1,27)-(1,28) = "b" │ │ │ │ ├── closing_loc: (1,28)-(1,29) = ":" @@ -92,7 +92,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ SymbolNode (location: (3,2)-(3,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (3,2)-(3,3) = ":" │ │ │ ├── value_loc: (3,3)-(3,6) = "foo" │ │ │ ├── closing_loc: ∅ @@ -123,7 +123,7 @@ │ │ │ └── @ AssocNode (location: (3,25)-(3,39)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (3,25)-(3,27)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (3,25)-(3,26) = "b" │ │ │ │ ├── closing_loc: (3,26)-(3,27) = ":" @@ -162,7 +162,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ SymbolNode (location: (5,2)-(5,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (5,2)-(5,3) = ":" │ │ │ ├── value_loc: (5,3)-(5,6) = "foo" │ │ │ ├── closing_loc: ∅ @@ -173,7 +173,7 @@ │ │ │ ├── @ AssocNode (location: (5,9)-(5,26)) │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (5,9)-(5,11)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (5,9)-(5,10) = ":" │ │ │ │ │ ├── value_loc: (5,10)-(5,11) = "a" │ │ │ │ │ ├── closing_loc: ∅ @@ -200,7 +200,7 @@ │ │ │ └── @ AssocNode (location: (5,28)-(5,42)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (5,28)-(5,30)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (5,28)-(5,29) = "b" │ │ │ │ ├── closing_loc: (5,29)-(5,30) = ":" @@ -239,7 +239,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 2) │ │ ├── @ SymbolNode (location: (7,2)-(7,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (7,2)-(7,3) = ":" │ │ │ ├── value_loc: (7,3)-(7,6) = "foo" │ │ │ ├── closing_loc: ∅ @@ -250,7 +250,7 @@ │ │ │ ├── @ AssocNode (location: (7,9)-(7,23)) │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (7,9)-(7,11)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ ├── value_loc: (7,9)-(7,10) = "a" │ │ │ │ │ ├── closing_loc: (7,10)-(7,11) = ":" @@ -277,7 +277,7 @@ │ │ │ └── @ AssocNode (location: (7,25)-(7,39)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (7,25)-(7,27)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (7,25)-(7,26) = "b" │ │ │ │ ├── closing_loc: (7,26)-(7,27) = ":" @@ -316,7 +316,7 @@ │ ├── flags: ∅ │ └── arguments: (length: 2) │ ├── @ SymbolNode (location: (9,2)-(9,6)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (9,2)-(9,3) = ":" │ │ ├── value_loc: (9,3)-(9,6) = "foo" │ │ ├── closing_loc: ∅ @@ -365,7 +365,7 @@ │ │ └── @ AssocNode (location: (9,37)-(9,51)) │ │ ├── key: │ │ │ @ SymbolNode (location: (9,37)-(9,39)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (9,37)-(9,38) = "b" │ │ │ ├── closing_loc: (9,38)-(9,39) = ":" diff --git a/test/prism/snapshots/whitequark/class_super_label.txt b/test/prism/snapshots/whitequark/class_super_label.txt index abfdaf32a9615e..c873ea0c125f29 100644 --- a/test/prism/snapshots/whitequark/class_super_label.txt +++ b/test/prism/snapshots/whitequark/class_super_label.txt @@ -23,7 +23,7 @@ │ │ ├── flags: ∅ │ │ └── arguments: (length: 1) │ │ └── @ SymbolNode (location: (1,13)-(1,15)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,13)-(1,14) = ":" │ │ ├── value_loc: (1,14)-(1,15) = "b" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt b/test/prism/snapshots/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt index 0af593e9e900ab..4299036bf8f396 100644 --- a/test/prism/snapshots/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt +++ b/test/prism/snapshots/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt @@ -44,7 +44,7 @@ │ │ └── @ AssocNode (location: (1,21)-(1,35)) │ │ ├── key: │ │ │ @ SymbolNode (location: (1,21)-(1,30)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (1,21)-(1,29) = "from_foo" │ │ │ ├── closing_loc: (1,29)-(1,30) = ":" diff --git a/test/prism/snapshots/whitequark/hash_hashrocket.txt b/test/prism/snapshots/whitequark/hash_hashrocket.txt index 59117a744559f7..124de2f3a3718c 100644 --- a/test/prism/snapshots/whitequark/hash_hashrocket.txt +++ b/test/prism/snapshots/whitequark/hash_hashrocket.txt @@ -29,7 +29,7 @@ │ └── @ AssocNode (location: (3,10)-(3,23)) │ ├── key: │ │ @ SymbolNode (location: (3,10)-(3,14)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (3,10)-(3,11) = ":" │ │ ├── value_loc: (3,11)-(3,14) = "foo" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/hash_kwsplat.txt b/test/prism/snapshots/whitequark/hash_kwsplat.txt index 729a9c6b88b745..b0d75a64b47124 100644 --- a/test/prism/snapshots/whitequark/hash_kwsplat.txt +++ b/test/prism/snapshots/whitequark/hash_kwsplat.txt @@ -9,7 +9,7 @@ │ ├── @ AssocNode (location: (1,2)-(1,8)) │ │ ├── key: │ │ │ @ SymbolNode (location: (1,2)-(1,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (1,2)-(1,5) = "foo" │ │ │ ├── closing_loc: (1,5)-(1,6) = ":" diff --git a/test/prism/snapshots/whitequark/hash_label.txt b/test/prism/snapshots/whitequark/hash_label.txt index 4e385b7df4acdc..bbc49bbbd7a59a 100644 --- a/test/prism/snapshots/whitequark/hash_label.txt +++ b/test/prism/snapshots/whitequark/hash_label.txt @@ -9,7 +9,7 @@ │ └── @ AssocNode (location: (1,2)-(1,8)) │ ├── key: │ │ @ SymbolNode (location: (1,2)-(1,6)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,2)-(1,5) = "foo" │ │ ├── closing_loc: (1,5)-(1,6) = ":" diff --git a/test/prism/snapshots/whitequark/hash_label_end.txt b/test/prism/snapshots/whitequark/hash_label_end.txt index 4999fc842ad179..71fd7b00501e41 100644 --- a/test/prism/snapshots/whitequark/hash_label_end.txt +++ b/test/prism/snapshots/whitequark/hash_label_end.txt @@ -55,7 +55,7 @@ │ │ └── @ AssocNode (location: (3,2)-(3,10)) │ │ ├── key: │ │ │ @ SymbolNode (location: (3,2)-(3,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (3,2)-(3,3) = "'" │ │ │ ├── value_loc: (3,3)-(3,6) = "foo" │ │ │ ├── closing_loc: (3,6)-(3,8) = "':" @@ -71,7 +71,7 @@ │ ├── @ AssocNode (location: (5,2)-(5,10)) │ │ ├── key: │ │ │ @ SymbolNode (location: (5,2)-(5,8)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (5,2)-(5,3) = "'" │ │ │ ├── value_loc: (5,3)-(5,6) = "foo" │ │ │ ├── closing_loc: (5,6)-(5,8) = "':" @@ -83,7 +83,7 @@ │ └── @ AssocNode (location: (5,12)-(5,21)) │ ├── key: │ │ @ SymbolNode (location: (5,12)-(5,18)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (5,12)-(5,13) = "'" │ │ ├── value_loc: (5,13)-(5,16) = "bar" │ │ ├── closing_loc: (5,16)-(5,18) = "':" diff --git a/test/prism/snapshots/whitequark/hash_pair_value_omission.txt b/test/prism/snapshots/whitequark/hash_pair_value_omission.txt index 28af78036026ad..455ba48407a898 100644 --- a/test/prism/snapshots/whitequark/hash_pair_value_omission.txt +++ b/test/prism/snapshots/whitequark/hash_pair_value_omission.txt @@ -9,7 +9,7 @@ │ │ └── @ AssocNode (location: (1,1)-(1,5)) │ │ ├── key: │ │ │ @ SymbolNode (location: (1,1)-(1,5)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (1,1)-(1,4) = "BAR" │ │ │ ├── closing_loc: (1,4)-(1,5) = ":" @@ -27,7 +27,7 @@ │ │ ├── @ AssocNode (location: (3,1)-(3,3)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (3,1)-(3,3)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (3,1)-(3,2) = "a" │ │ │ │ ├── closing_loc: (3,2)-(3,3) = ":" @@ -49,7 +49,7 @@ │ │ └── @ AssocNode (location: (3,5)-(3,7)) │ │ ├── key: │ │ │ @ SymbolNode (location: (3,5)-(3,7)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (3,5)-(3,6) = "b" │ │ │ ├── closing_loc: (3,6)-(3,7) = ":" @@ -75,7 +75,7 @@ │ └── @ AssocNode (location: (5,1)-(5,6)) │ ├── key: │ │ @ SymbolNode (location: (5,1)-(5,6)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (5,1)-(5,5) = "puts" │ │ ├── closing_loc: (5,5)-(5,6) = ":" diff --git a/test/prism/snapshots/whitequark/interp_digit_var.txt b/test/prism/snapshots/whitequark/interp_digit_var.txt index e867b6bdde187e..6c34760bc35320 100644 --- a/test/prism/snapshots/whitequark/interp_digit_var.txt +++ b/test/prism/snapshots/whitequark/interp_digit_var.txt @@ -19,7 +19,7 @@ │ ├── flags: ∅ │ ├── elements: (length: 1) │ │ └── @ SymbolNode (location: (5,4)-(5,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (5,4)-(5,7) = "\#@1" │ │ ├── closing_loc: ∅ @@ -30,7 +30,7 @@ │ ├── flags: ∅ │ ├── elements: (length: 1) │ │ └── @ SymbolNode (location: (7,4)-(7,8)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (7,4)-(7,8) = "\#@@1" │ │ ├── closing_loc: ∅ @@ -75,7 +75,7 @@ │ ├── flags: ∅ │ ├── elements: (length: 1) │ │ └── @ SymbolNode (location: (17,5)-(17,8)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (17,5)-(17,8) = "\#@1" │ │ ├── closing_loc: ∅ @@ -86,7 +86,7 @@ │ ├── flags: ∅ │ ├── elements: (length: 1) │ │ └── @ SymbolNode (location: (19,5)-(19,9)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (19,5)-(19,9) = "\#@@1" │ │ ├── closing_loc: ∅ @@ -118,13 +118,13 @@ │ ├── closing_loc: (27,8)-(27,9) = "}" │ └── unescaped: "\#@@1" ├── @ SymbolNode (location: (29,1)-(29,8)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (29,1)-(29,4) = "%s{" │ ├── value_loc: (29,4)-(29,7) = "\#@1" │ ├── closing_loc: (29,7)-(29,8) = "}" │ └── unescaped: "\#@1" ├── @ SymbolNode (location: (31,1)-(31,9)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (31,1)-(31,4) = "%s{" │ ├── value_loc: (31,4)-(31,8) = "\#@@1" │ ├── closing_loc: (31,8)-(31,9) = "}" @@ -200,25 +200,25 @@ │ ├── closing_loc: (51,6)-(51,7) = "/" │ └── unescaped: "\#@@1" ├── @ SymbolNode (location: (53,1)-(53,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (53,1)-(53,3) = ":\"" │ ├── value_loc: (53,3)-(53,6) = "\#@1" │ ├── closing_loc: (53,6)-(53,7) = "\"" │ └── unescaped: "\#@1" ├── @ SymbolNode (location: (55,1)-(55,8)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (55,1)-(55,3) = ":\"" │ ├── value_loc: (55,3)-(55,7) = "\#@@1" │ ├── closing_loc: (55,7)-(55,8) = "\"" │ └── unescaped: "\#@@1" ├── @ SymbolNode (location: (57,1)-(57,7)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (57,1)-(57,3) = ":'" │ ├── value_loc: (57,3)-(57,6) = "\#@1" │ ├── closing_loc: (57,6)-(57,7) = "'" │ └── unescaped: "\#@1" ├── @ SymbolNode (location: (59,1)-(59,8)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (59,1)-(59,3) = ":'" │ ├── value_loc: (59,3)-(59,7) = "\#@@1" │ ├── closing_loc: (59,7)-(59,8) = "'" diff --git a/test/prism/snapshots/whitequark/keyword_argument_omission.txt b/test/prism/snapshots/whitequark/keyword_argument_omission.txt index 74e337843298b9..62e8fecf4e9192 100644 --- a/test/prism/snapshots/whitequark/keyword_argument_omission.txt +++ b/test/prism/snapshots/whitequark/keyword_argument_omission.txt @@ -20,7 +20,7 @@ │ ├── @ AssocNode (location: (1,4)-(1,6)) │ │ ├── key: │ │ │ @ SymbolNode (location: (1,4)-(1,6)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (1,4)-(1,5) = "a" │ │ │ ├── closing_loc: (1,5)-(1,6) = ":" @@ -42,7 +42,7 @@ │ └── @ AssocNode (location: (1,8)-(1,10)) │ ├── key: │ │ @ SymbolNode (location: (1,8)-(1,10)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,8)-(1,9) = "b" │ │ ├── closing_loc: (1,9)-(1,10) = ":" diff --git a/test/prism/snapshots/whitequark/lbrace_arg_after_command_args.txt b/test/prism/snapshots/whitequark/lbrace_arg_after_command_args.txt index 4265c8a87c4f26..61154fb1e36177 100644 --- a/test/prism/snapshots/whitequark/lbrace_arg_after_command_args.txt +++ b/test/prism/snapshots/whitequark/lbrace_arg_after_command_args.txt @@ -19,7 +19,7 @@ │ │ @ StatementsNode (location: (1,5)-(1,7)) │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (1,5)-(1,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,5)-(1,6) = ":" │ │ ├── value_loc: (1,6)-(1,7) = "a" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/multiple_pattern_matches.txt b/test/prism/snapshots/whitequark/multiple_pattern_matches.txt index 3150bfb8e22a67..c3479d139a7524 100644 --- a/test/prism/snapshots/whitequark/multiple_pattern_matches.txt +++ b/test/prism/snapshots/whitequark/multiple_pattern_matches.txt @@ -11,7 +11,7 @@ │ │ │ └── @ AssocNode (location: (1,1)-(1,5)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (1,1)-(1,3)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (1,1)-(1,2) = "a" │ │ │ │ ├── closing_loc: (1,2)-(1,3) = ":" @@ -28,7 +28,7 @@ │ │ │ └── @ AssocNode (location: (1,10)-(1,12)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (1,10)-(1,12)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (1,10)-(1,11) = "a" │ │ │ │ ├── closing_loc: (1,11)-(1,12) = ":" @@ -52,7 +52,7 @@ │ │ │ └── @ AssocNode (location: (2,1)-(2,5)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (2,1)-(2,3)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (2,1)-(2,2) = "a" │ │ │ │ ├── closing_loc: (2,2)-(2,3) = ":" @@ -69,7 +69,7 @@ │ │ │ └── @ AssocNode (location: (2,10)-(2,12)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (2,10)-(2,12)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (2,10)-(2,11) = "a" │ │ │ │ ├── closing_loc: (2,11)-(2,12) = ":" @@ -93,7 +93,7 @@ │ │ │ └── @ AssocNode (location: (4,1)-(4,5)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (4,1)-(4,3)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (4,1)-(4,2) = "a" │ │ │ │ ├── closing_loc: (4,2)-(4,3) = ":" @@ -110,7 +110,7 @@ │ │ │ └── @ AssocNode (location: (4,10)-(4,12)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (4,10)-(4,12)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (4,10)-(4,11) = "a" │ │ │ │ ├── closing_loc: (4,11)-(4,12) = ":" @@ -134,7 +134,7 @@ │ │ └── @ AssocNode (location: (5,1)-(5,5)) │ │ ├── key: │ │ │ @ SymbolNode (location: (5,1)-(5,3)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (5,1)-(5,2) = "a" │ │ │ ├── closing_loc: (5,2)-(5,3) = ":" @@ -151,7 +151,7 @@ │ │ └── @ AssocNode (location: (5,10)-(5,12)) │ │ ├── key: │ │ │ @ SymbolNode (location: (5,10)-(5,12)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (5,10)-(5,11) = "a" │ │ │ ├── closing_loc: (5,11)-(5,12) = ":" diff --git a/test/prism/snapshots/whitequark/newline_in_hash_argument.txt b/test/prism/snapshots/whitequark/newline_in_hash_argument.txt index 554d3108cd7176..a57e9f5b285ca1 100644 --- a/test/prism/snapshots/whitequark/newline_in_hash_argument.txt +++ b/test/prism/snapshots/whitequark/newline_in_hash_argument.txt @@ -24,7 +24,7 @@ │ │ │ │ │ └── @ AssocNode (location: (2,3)-(2,5)) │ │ │ │ │ ├── key: │ │ │ │ │ │ @ SymbolNode (location: (2,3)-(2,5)) - │ │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ │ ├── opening_loc: ∅ │ │ │ │ │ │ ├── value_loc: (2,3)-(2,4) = "a" │ │ │ │ │ │ ├── closing_loc: (2,4)-(2,5) = ":" @@ -55,7 +55,7 @@ │ │ │ │ └── @ AssocNode (location: (5,3)-(5,7)) │ │ │ │ ├── key: │ │ │ │ │ @ SymbolNode (location: (5,3)-(5,7)) - │ │ │ │ │ ├── flags: ∅ + │ │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ │ ├── opening_loc: (5,3)-(5,4) = "\"" │ │ │ │ │ ├── value_loc: (5,4)-(5,5) = "b" │ │ │ │ │ ├── closing_loc: (5,5)-(5,7) = "\":" @@ -108,7 +108,7 @@ │ │ └── @ AssocNode (location: (10,8)-(11,1)) │ │ ├── key: │ │ │ @ SymbolNode (location: (10,8)-(10,14)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (10,8)-(10,9) = "\"" │ │ │ ├── value_loc: (10,9)-(10,12) = "foo" │ │ │ ├── closing_loc: (10,12)-(10,14) = "\":" @@ -146,7 +146,7 @@ │ └── @ AssocNode (location: (13,8)-(14,1)) │ ├── key: │ │ @ SymbolNode (location: (13,8)-(13,12)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (13,8)-(13,11) = "foo" │ │ ├── closing_loc: (13,11)-(13,12) = ":" diff --git a/test/prism/snapshots/whitequark/parser_bug_525.txt b/test/prism/snapshots/whitequark/parser_bug_525.txt index 1d61921effc6fa..9fddff99814926 100644 --- a/test/prism/snapshots/whitequark/parser_bug_525.txt +++ b/test/prism/snapshots/whitequark/parser_bug_525.txt @@ -20,7 +20,7 @@ │ └── @ AssocNode (location: (1,3)-(1,11)) │ ├── key: │ │ @ SymbolNode (location: (1,3)-(1,5)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,3)-(1,4) = ":" │ │ ├── value_loc: (1,4)-(1,5) = "k" │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/parser_slash_slash_n_escaping_in_literals.txt b/test/prism/snapshots/whitequark/parser_slash_slash_n_escaping_in_literals.txt index aac6b051b31738..96cc5671a61482 100644 --- a/test/prism/snapshots/whitequark/parser_slash_slash_n_escaping_in_literals.txt +++ b/test/prism/snapshots/whitequark/parser_slash_slash_n_escaping_in_literals.txt @@ -13,7 +13,7 @@ │ ├── flags: ∅ │ ├── elements: (length: 1) │ │ └── @ SymbolNode (location: (4,3)-(5,1)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (4,3)-(5,1) = "a\\\nb" │ │ ├── closing_loc: ∅ @@ -41,7 +41,7 @@ │ ├── flags: ∅ │ ├── elements: (length: 1) │ │ └── @ SymbolNode (location: (13,3)-(14,1)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (13,3)-(14,1) = "a\\\nb" │ │ ├── closing_loc: ∅ @@ -61,7 +61,7 @@ │ ├── closing_loc: (20,1)-(20,2) = "}" │ └── unescaped: "ab" ├── @ SymbolNode (location: (22,0)-(23,2)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (22,0)-(22,3) = "%s{" │ ├── value_loc: (22,3)-(23,1) = "a\\\nb" │ ├── closing_loc: (23,1)-(23,2) = "}" @@ -102,13 +102,13 @@ │ ├── closing_loc: (38,1)-(38,2) = "/" │ └── unescaped: "ab" ├── @ SymbolNode (location: (40,0)-(41,2)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (40,0)-(40,2) = ":\"" │ ├── value_loc: (40,2)-(41,1) = "a\\\nb" │ ├── closing_loc: (41,1)-(41,2) = "\"" │ └── unescaped: "ab" ├── @ SymbolNode (location: (43,0)-(44,2)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (43,0)-(43,2) = ":'" │ ├── value_loc: (43,2)-(44,1) = "a\\\nb" │ ├── closing_loc: (44,1)-(44,2) = "'" diff --git a/test/prism/snapshots/whitequark/pattern_matching_single_line_allowed_omission_of_parentheses.txt b/test/prism/snapshots/whitequark/pattern_matching_single_line_allowed_omission_of_parentheses.txt index 99d1cdc25b8c14..4cfb5718ec3dc3 100644 --- a/test/prism/snapshots/whitequark/pattern_matching_single_line_allowed_omission_of_parentheses.txt +++ b/test/prism/snapshots/whitequark/pattern_matching_single_line_allowed_omission_of_parentheses.txt @@ -69,7 +69,7 @@ │ │ │ └── @ AssocNode (location: (5,1)-(5,5)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (5,1)-(5,3)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (5,1)-(5,2) = "a" │ │ │ │ ├── closing_loc: (5,2)-(5,3) = ":" @@ -86,7 +86,7 @@ │ │ │ └── @ AssocNode (location: (5,10)-(5,12)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (5,10)-(5,12)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (5,10)-(5,11) = "a" │ │ │ │ ├── closing_loc: (5,11)-(5,12) = ":" @@ -113,7 +113,7 @@ │ │ │ └── @ AssocNode (location: (7,1)-(7,5)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (7,1)-(7,3)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (7,1)-(7,2) = "a" │ │ │ │ ├── closing_loc: (7,2)-(7,3) = ":" @@ -130,7 +130,7 @@ │ │ │ └── @ AssocNode (location: (7,10)-(7,12)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (7,10)-(7,12)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (7,10)-(7,11) = "a" │ │ │ │ ├── closing_loc: (7,11)-(7,12) = ":" @@ -157,14 +157,14 @@ │ │ │ └── @ AssocNode (location: (9,1)-(9,12)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (9,1)-(9,5)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (9,1)-(9,4) = "key" │ │ │ │ ├── closing_loc: (9,4)-(9,5) = ":" │ │ │ │ └── unescaped: "key" │ │ │ ├── value: │ │ │ │ @ SymbolNode (location: (9,6)-(9,12)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (9,6)-(9,7) = ":" │ │ │ │ ├── value_loc: (9,7)-(9,12) = "value" │ │ │ │ ├── closing_loc: ∅ @@ -178,7 +178,7 @@ │ │ │ └── @ AssocNode (location: (9,17)-(9,27)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (9,17)-(9,21)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (9,17)-(9,20) = "key" │ │ │ │ ├── closing_loc: (9,20)-(9,21) = ":" @@ -203,14 +203,14 @@ │ │ │ └── @ AssocNode (location: (11,1)-(11,12)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (11,1)-(11,5)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (11,1)-(11,4) = "key" │ │ │ │ ├── closing_loc: (11,4)-(11,5) = ":" │ │ │ │ └── unescaped: "key" │ │ │ ├── value: │ │ │ │ @ SymbolNode (location: (11,6)-(11,12)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (11,6)-(11,7) = ":" │ │ │ │ ├── value_loc: (11,7)-(11,12) = "value" │ │ │ │ ├── closing_loc: ∅ @@ -224,7 +224,7 @@ │ │ │ └── @ AssocNode (location: (11,17)-(11,27)) │ │ │ ├── key: │ │ │ │ @ SymbolNode (location: (11,17)-(11,21)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: ∅ │ │ │ │ ├── value_loc: (11,17)-(11,20) = "key" │ │ │ │ ├── closing_loc: (11,20)-(11,21) = ":" diff --git a/test/prism/snapshots/whitequark/ruby_bug_10279.txt b/test/prism/snapshots/whitequark/ruby_bug_10279.txt index cd681d8d3cd0a9..d1eaa26a11a966 100644 --- a/test/prism/snapshots/whitequark/ruby_bug_10279.txt +++ b/test/prism/snapshots/whitequark/ruby_bug_10279.txt @@ -9,7 +9,7 @@ │ └── @ AssocNode (location: (1,1)-(1,23)) │ ├── key: │ │ @ SymbolNode (location: (1,1)-(1,3)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,1)-(1,2) = "a" │ │ ├── closing_loc: (1,2)-(1,3) = ":" diff --git a/test/prism/snapshots/whitequark/ruby_bug_11380.txt b/test/prism/snapshots/whitequark/ruby_bug_11380.txt index fd86387e07a893..ffc4e496cb6c32 100644 --- a/test/prism/snapshots/whitequark/ruby_bug_11380.txt +++ b/test/prism/snapshots/whitequark/ruby_bug_11380.txt @@ -25,7 +25,7 @@ │ │ @ StatementsNode (location: (1,7)-(1,13)) │ │ └── body: (length: 1) │ │ └── @ SymbolNode (location: (1,7)-(1,13)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,7)-(1,8) = ":" │ │ ├── value_loc: (1,8)-(1,13) = "hello" │ │ ├── closing_loc: ∅ @@ -36,7 +36,7 @@ │ └── @ AssocNode (location: (1,17)-(1,21)) │ ├── key: │ │ @ SymbolNode (location: (1,17)-(1,19)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,17)-(1,18) = "a" │ │ ├── closing_loc: (1,18)-(1,19) = ":" diff --git a/test/prism/snapshots/whitequark/ruby_bug_11873_a.txt b/test/prism/snapshots/whitequark/ruby_bug_11873_a.txt index d5519d035265a2..451fbb7540b6a6 100644 --- a/test/prism/snapshots/whitequark/ruby_bug_11873_a.txt +++ b/test/prism/snapshots/whitequark/ruby_bug_11873_a.txt @@ -284,7 +284,7 @@ │ │ │ ├── closing_loc: (9,7)-(9,8) = ")" │ │ │ └── block: ∅ │ │ └── @ SymbolNode (location: (9,10)-(9,12)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (9,10)-(9,11) = ":" │ │ ├── value_loc: (9,11)-(9,12) = "e" │ │ ├── closing_loc: ∅ @@ -579,7 +579,7 @@ │ │ │ ├── closing_loc: (19,8)-(19,9) = ")" │ │ │ └── block: ∅ │ │ └── @ SymbolNode (location: (19,11)-(19,13)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (19,11)-(19,12) = ":" │ │ ├── value_loc: (19,12)-(19,13) = "e" │ │ ├── closing_loc: ∅ @@ -904,7 +904,7 @@ │ │ │ ├── opening_loc: (29,3)-(29,4) = "{" │ │ │ └── closing_loc: (29,7)-(29,8) = "}" │ │ └── @ SymbolNode (location: (29,10)-(29,12)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (29,10)-(29,11) = ":" │ │ ├── value_loc: (29,11)-(29,12) = "e" │ │ ├── closing_loc: ∅ @@ -1229,7 +1229,7 @@ │ │ ├── opening_loc: (39,3)-(39,4) = "{" │ │ └── closing_loc: (39,8)-(39,9) = "}" │ └── @ SymbolNode (location: (39,11)-(39,13)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (39,11)-(39,12) = ":" │ ├── value_loc: (39,12)-(39,13) = "e" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/ruby_bug_12073.txt b/test/prism/snapshots/whitequark/ruby_bug_12073.txt index 3ac68ad707ae60..a9ee4d8fe50663 100644 --- a/test/prism/snapshots/whitequark/ruby_bug_12073.txt +++ b/test/prism/snapshots/whitequark/ruby_bug_12073.txt @@ -28,7 +28,7 @@ │ │ └── @ AssocNode (location: (1,9)-(1,13)) │ │ ├── key: │ │ │ @ SymbolNode (location: (1,9)-(1,11)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (1,9)-(1,10) = "b" │ │ │ ├── closing_loc: (1,10)-(1,11) = ":" diff --git a/test/prism/snapshots/whitequark/ruby_bug_12669.txt b/test/prism/snapshots/whitequark/ruby_bug_12669.txt index cb8a1b370e18d3..86b021351b8329 100644 --- a/test/prism/snapshots/whitequark/ruby_bug_12669.txt +++ b/test/prism/snapshots/whitequark/ruby_bug_12669.txt @@ -23,7 +23,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ SymbolNode (location: (1,16)-(1,18)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (1,16)-(1,17) = ":" │ │ │ │ ├── value_loc: (1,17)-(1,18) = "x" │ │ │ │ ├── closing_loc: ∅ @@ -57,7 +57,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ SymbolNode (location: (3,15)-(3,17)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (3,15)-(3,16) = ":" │ │ │ │ ├── value_loc: (3,16)-(3,17) = "x" │ │ │ │ ├── closing_loc: ∅ @@ -89,7 +89,7 @@ │ │ │ │ ├── flags: ∅ │ │ │ │ └── arguments: (length: 1) │ │ │ │ └── @ SymbolNode (location: (5,15)-(5,17)) - │ │ │ │ ├── flags: ∅ + │ │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ │ ├── opening_loc: (5,15)-(5,16) = ":" │ │ │ │ ├── value_loc: (5,16)-(5,17) = "x" │ │ │ │ ├── closing_loc: ∅ @@ -122,7 +122,7 @@ │ │ │ ├── flags: ∅ │ │ │ └── arguments: (length: 1) │ │ │ └── @ SymbolNode (location: (7,14)-(7,16)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: (7,14)-(7,15) = ":" │ │ │ ├── value_loc: (7,15)-(7,16) = "x" │ │ │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/ruby_bug_9669.txt b/test/prism/snapshots/whitequark/ruby_bug_9669.txt index 55e61cb46bebac..74dbe31f4fc205 100644 --- a/test/prism/snapshots/whitequark/ruby_bug_9669.txt +++ b/test/prism/snapshots/whitequark/ruby_bug_9669.txt @@ -45,7 +45,7 @@ │ │ └── @ AssocNode (location: (6,0)-(7,1)) │ │ ├── key: │ │ │ @ SymbolNode (location: (6,0)-(6,2)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (6,0)-(6,1) = "a" │ │ │ ├── closing_loc: (6,1)-(6,2) = ":" diff --git a/test/prism/snapshots/whitequark/symbol_plain.txt b/test/prism/snapshots/whitequark/symbol_plain.txt index 54c7ce1b5ccd3b..a2466600f57426 100644 --- a/test/prism/snapshots/whitequark/symbol_plain.txt +++ b/test/prism/snapshots/whitequark/symbol_plain.txt @@ -4,13 +4,13 @@ @ StatementsNode (location: (1,0)-(3,4)) └── body: (length: 2) ├── @ SymbolNode (location: (1,0)-(1,6)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: (1,0)-(1,2) = ":'" │ ├── value_loc: (1,2)-(1,5) = "foo" │ ├── closing_loc: (1,5)-(1,6) = "'" │ └── unescaped: "foo" └── @ SymbolNode (location: (3,0)-(3,4)) - ├── flags: ∅ + ├── flags: forced_us_ascii_encoding ├── opening_loc: (3,0)-(3,1) = ":" ├── value_loc: (3,1)-(3,4) = "foo" ├── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/undef.txt b/test/prism/snapshots/whitequark/undef.txt index 6d0bffb289c4d6..0f735cc76316e0 100644 --- a/test/prism/snapshots/whitequark/undef.txt +++ b/test/prism/snapshots/whitequark/undef.txt @@ -12,7 +12,7 @@ │ │ ├── closing_loc: ∅ │ │ └── unescaped: "foo" │ ├── @ SymbolNode (location: (1,11)-(1,15)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: (1,11)-(1,12) = ":" │ │ ├── value_loc: (1,12)-(1,15) = "bar" │ │ ├── closing_loc: ∅ From 59bb78ebd023d42c9ac604c89d0885cef1622c21 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Fri, 26 Jan 2024 14:51:25 -0500 Subject: [PATCH 565/640] [PRISM] Fix for s390x On s390x, a long is 8 bytes. st_data_t is an unsigned long but pm_constant_id_t is a 4 byte integer. We need to cast it to st_data_t when passing it to ST functions. --- .travis.yml | 3 +-- prism_compile.c | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index bc61e507b049aa..741c0a32efcb59 100644 --- a/.travis.yml +++ b/.travis.yml @@ -72,7 +72,6 @@ env: # on s390x CPU architecture. # https://github.com/madler/zlib/pull/410 - DFLTCC=0 - - TESTS="--exclude=ruby/test_compile_prism.rb --exclude=ruby/test_iseq.rb" - &arm32-linux name: arm32-linux arch: arm64 @@ -135,7 +134,7 @@ before_script: script: - $SETARCH make -s test - - ../tool/travis_wait.sh $SETARCH make -s test-all RUBYOPT="-w" TESTS="$TESTS" + - ../tool/travis_wait.sh $SETARCH make -s test-all RUBYOPT="-w" - $SETARCH make -s test-spec # We want to be notified when something happens. diff --git a/prism_compile.c b/prism_compile.c index bda506e3ffb73d..c9e397163850dc 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2816,7 +2816,7 @@ static int pm_local_table_insert_func(st_data_t *key, st_data_t *value, st_data_t arg, int existing) { if (!existing) { - pm_constant_id_t constant_id = *(pm_constant_id_t *)key; + pm_constant_id_t constant_id = (pm_constant_id_t)*key; struct pm_local_table_insert_ctx * ctx = (struct pm_local_table_insert_ctx *)arg; pm_scope_node_t *scope_node = ctx->scope_node; @@ -2826,7 +2826,7 @@ pm_local_table_insert_func(st_data_t *key, st_data_t *value, st_data_t arg, int ID local = pm_constant_id_lookup(scope_node, constant_id); local_table_for_iseq->ids[local_index] = local; - *value = local_index; + *value = (st_data_t)local_index; ctx->local_index++; } @@ -2841,7 +2841,7 @@ pm_insert_local_index(pm_constant_id_t constant_id, int local_index, st_table *i ID local = pm_constant_id_lookup(scope_node, constant_id); local_table_for_iseq->ids[local_index] = local; - st_insert(index_lookup_table, constant_id, local_index); + st_insert(index_lookup_table, (st_data_t)constant_id, local_index); } /** @@ -6543,7 +6543,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // def foo(a, (b, *c, d), e = 1, *, g, (h, *i, j), k:, l: 1, **m, &n) // ^ local_table_for_iseq->ids[local_index] = PM_CONSTANT_MULT; - st_insert(index_lookup_table, PM_CONSTANT_MULT, local_index); + st_insert(index_lookup_table, (st_data_t)PM_CONSTANT_MULT, local_index); } local_index++; } @@ -6726,7 +6726,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } else { local_table_for_iseq->ids[local_index] = PM_CONSTANT_POW; - st_insert(index_lookup_table, PM_CONSTANT_POW, local_index); + st_insert(index_lookup_table, (st_data_t)PM_CONSTANT_POW, local_index); } local_index++; break; @@ -6737,17 +6737,17 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, body->param.rest_start = local_index; body->param.flags.has_rest = true; local_table_for_iseq->ids[local_index] = PM_CONSTANT_MULT; - st_insert(index_lookup_table, PM_CONSTANT_MULT, local_index); + st_insert(index_lookup_table, (st_data_t)PM_CONSTANT_MULT, local_index); local_index++; body->param.block_start = local_index; body->param.flags.has_block = true; local_table_for_iseq->ids[local_index] = PM_CONSTANT_AND; - st_insert(index_lookup_table, PM_CONSTANT_AND, local_index); + st_insert(index_lookup_table, (st_data_t)PM_CONSTANT_AND, local_index); local_index++; local_table_for_iseq->ids[local_index] = PM_CONSTANT_DOT3; - st_insert(index_lookup_table, PM_CONSTANT_DOT3, local_index); + st_insert(index_lookup_table, (st_data_t)PM_CONSTANT_DOT3, local_index); local_index++; break; } @@ -6767,7 +6767,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, if (name == 0) { local_table_for_iseq->ids[local_index] = PM_CONSTANT_AND; - st_insert(index_lookup_table, PM_CONSTANT_AND, local_index); + st_insert(index_lookup_table, (st_data_t)PM_CONSTANT_AND, local_index); } else { if (PM_NODE_FLAG_P(parameters_node->block, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { @@ -6866,7 +6866,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, ctx.local_table_for_iseq = local_table_for_iseq; ctx.local_index = local_index; - st_update(index_lookup_table, constant_id, pm_local_table_insert_func, (st_data_t)&ctx); + st_update(index_lookup_table, (st_data_t)constant_id, pm_local_table_insert_func, (st_data_t)&ctx); local_index = ctx.local_index; } From a12052902088caff04eca2f61a4b62c0c309ba08 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Fri, 26 Jan 2024 12:17:04 -0500 Subject: [PATCH 566/640] [PRISM] Fix loop in rescue blocks Fixes ruby/prism#2250. Co-Authored-By: Kevin Newton --- prism_compile.c | 14 ++++++++------ test/ruby/test_compile_prism.rb | 28 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index c9e397163850dc..31220996fdf328 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2761,7 +2761,10 @@ pm_compile_call(rb_iseq_t *iseq, const pm_call_node_t *call_node, LINK_ANCHOR *c ADD_INSNL(ret, &dummy_line_node, jump, end_label); ADD_LABEL(ret, else_label); } - ADD_LABEL(ret, end_label); + + if ((block_iseq && ISEQ_BODY(block_iseq)->catch_table) || (call_node->base.flags & PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) { + ADD_LABEL(ret, end_label); + } PM_POP_IF_POPPED; } @@ -6073,7 +6076,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // this compilation block. LABEL *exception_match_label = NEW_LABEL(lineno); LABEL *rescue_end_label = NEW_LABEL(lineno); - ISEQ_COMPILE_DATA(iseq)->end_label = rescue_end_label; // Next, compile each of the exceptions that we're going to be // handling. For each one, we'll add instructions to check if the @@ -6098,12 +6100,12 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0); ADD_INSN1(ret, &dummy_line_node, putobject, rb_eStandardError); ADD_INSN1(ret, &dummy_line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE)); - ADD_INSN1(ret, &dummy_line_node, branchif, exception_match_label); + ADD_INSNL(ret, &dummy_line_node, branchif, exception_match_label); } // If none of the exceptions that we are matching against matched, then // we'll jump straight to the rescue_end_label label. - ADD_INSN1(ret, &dummy_line_node, jump, rescue_end_label); + ADD_INSNL(ret, &dummy_line_node, jump, rescue_end_label); // Here we have the exception_match_label, which is where the // control-flow goes in the case that one of the exceptions matched. @@ -7081,8 +7083,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0); ADD_INSN1(ret, &dummy_line_node, putobject, rb_eStandardError); ADD_INSN1(ret, &dummy_line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE)); - ADD_INSN1(ret, &dummy_line_node, branchif, lab); - ADD_INSN1(ret, &dummy_line_node, jump, rescue_end); + ADD_INSNL(ret, &dummy_line_node, branchif, lab); + ADD_INSNL(ret, &dummy_line_node, jump, rescue_end); ADD_LABEL(ret, lab); PM_COMPILE((pm_node_t *)scope_node->body); ADD_INSN(ret, &dummy_line_node, leave); diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 05e95e8b06141b..ff0a252b71db60 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -987,10 +987,38 @@ def test_UnlessNode def test_UntilNode assert_prism_eval("a = 0; until a == 1; a = a + 1; end") + + # Test UntilNode in rescue + assert_prism_eval(<<~RUBY) + o = Object.new + o.instance_variable_set(:@ret, []) + def o.foo = @ret << @ret.length + def o.bar = @ret.length > 3 + begin + raise + rescue + o.foo until o.bar + end + o.instance_variable_get(:@ret) + RUBY end def test_WhileNode assert_prism_eval("a = 0; while a != 1; a = a + 1; end") + + # Test WhileNode in rescue + assert_prism_eval(<<~RUBY) + o = Object.new + o.instance_variable_set(:@ret, []) + def o.foo = @ret << @ret.length + def o.bar = @ret.length < 3 + begin + raise + rescue + o.foo while o.bar + end + o.instance_variable_get(:@ret) + RUBY end def test_ForNode From bcafd28a3e2ec6c35d80c55a5d11c2f8aab6fc8b Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 26 Jan 2024 15:29:37 -0500 Subject: [PATCH 567/640] [ruby/prism] Symbol encoding follow-up Ensure we don't accidentally parse the symbol encoding twice, and ensure we parse it in every circumstance we need to by requiring it as a parameter. https://github.com/ruby/prism/commit/9cea31c785 --- prism/prism.c | 92 +++++++++---------- test/prism/snapshots/undef.txt | 10 +- .../unparser/corpus/semantic/undef.txt | 6 +- test/prism/snapshots/whitequark/undef.txt | 2 +- 4 files changed, 53 insertions(+), 57 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index a68577b4dce6b1..69f896cbb6b716 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -5475,46 +5475,40 @@ pm_super_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_argument * Read through the contents of a string and check if it consists solely of US ASCII code points. */ static bool -ascii_only_p( const pm_string_t *contents) { - const size_t length = contents->length; +pm_ascii_only_p(const pm_string_t *contents) { + const size_t length = pm_string_length(contents); + const uint8_t *source = pm_string_source(contents); - for (size_t i = 0; i < length; i++) { - if (contents->source[i] & 0x80) { - return false; - } + for (size_t index = 0; index < length; index++) { + if (source[index] & 0x80) return false; } return true; } /** - * Ruby "downgrades" the encoding of Symbols to US-ASCII if the associated encoding is ASCII-compatible and - * the Symbol consists only of US-ASCII code points. Otherwise, the encoding may be explicitly set with an - * escape sequence. + * Ruby "downgrades" the encoding of Symbols to US-ASCII if the associated + * encoding is ASCII-compatible and the Symbol consists only of US-ASCII code + * points. Otherwise, the encoding may be explicitly set with an escape + * sequence. */ static inline pm_node_flags_t parse_symbol_encoding(const pm_parser_t *parser, const pm_string_t *contents) { - // Don't set any flags on the Symbol if it hasn't been populated yet. - if (contents->source == NULL) { - return 0; - } - - // Ruby stipulates that all source files must use an ASCII-compatible encoding. Thus, all symbols appearing in - // source are eligible for "downgrading" to US-ASCII. - if (ascii_only_p(contents)) { - return PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING; - } else { - // A Symbol may optionally have its encoding explicitly set. - // - // NB: an explicitly set encoding is ignored by Ruby if the Symbol consists of only US ASCII code points. - if (parser->explicit_encoding != NULL) { - if (parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY) { - return PM_SYMBOL_FLAGS_FORCED_UTF8_ENCODING; - } else if (parser->encoding == PM_ENCODING_US_ASCII_ENTRY) { - return PM_SYMBOL_FLAGS_FORCED_BINARY_ENCODING; - } + if (parser->explicit_encoding != NULL) { + // A Symbol may optionally have its encoding explicitly set. This will + // happen if an escape sequence results in a non-ASCII code point. + if (parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY) { + return PM_SYMBOL_FLAGS_FORCED_UTF8_ENCODING; + } else if (parser->encoding == PM_ENCODING_US_ASCII_ENTRY) { + return PM_SYMBOL_FLAGS_FORCED_BINARY_ENCODING; } + } else if (pm_ascii_only_p(contents)) { + // Ruby stipulates that all source files must use an ASCII-compatible + // encoding. Thus, all symbols appearing in source are eligible for + // "downgrading" to US-ASCII. + return PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING; } + return 0; } @@ -5523,13 +5517,13 @@ parse_symbol_encoding(const pm_parser_t *parser, const pm_string_t *contents) { * string. */ static pm_symbol_node_t * -pm_symbol_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *value, const pm_token_t *closing, const pm_string_t *unescaped) { +pm_symbol_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *value, const pm_token_t *closing, const pm_string_t *unescaped, pm_node_flags_t flags) { pm_symbol_node_t *node = PM_ALLOC_NODE(parser, pm_symbol_node_t); *node = (pm_symbol_node_t) { { .type = PM_SYMBOL_NODE, - .flags = PM_NODE_FLAG_STATIC_LITERAL, + .flags = PM_NODE_FLAG_STATIC_LITERAL | flags, .location = { .start = (opening->type == PM_TOKEN_NOT_PROVIDED ? value->start : opening->start), .end = (closing->type == PM_TOKEN_NOT_PROVIDED ? value->end : closing->end) @@ -5541,8 +5535,6 @@ pm_symbol_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, .unescaped = *unescaped }; - pm_node_flag_set((pm_node_t *)node, parse_symbol_encoding(parser, unescaped)); - return node; } @@ -5551,7 +5543,7 @@ pm_symbol_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, */ static inline pm_symbol_node_t * pm_symbol_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *value, const pm_token_t *closing) { - return pm_symbol_node_create_unescaped(parser, opening, value, closing, &PM_STRING_EMPTY); + return pm_symbol_node_create_unescaped(parser, opening, value, closing, &PM_STRING_EMPTY, 0); } /** @@ -5559,7 +5551,7 @@ pm_symbol_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_t */ static pm_symbol_node_t * pm_symbol_node_create_current_string(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *value, const pm_token_t *closing) { - pm_symbol_node_t *node = pm_symbol_node_create_unescaped(parser, opening, value, closing, &parser->current_string); + pm_symbol_node_t *node = pm_symbol_node_create_unescaped(parser, opening, value, closing, &parser->current_string, parse_symbol_encoding(parser, &parser->current_string)); parser->current_string = PM_STRING_EMPTY; return node; } @@ -5581,7 +5573,8 @@ pm_symbol_node_label_create(pm_parser_t *parser, const pm_token_t *token) { assert((label.end - label.start) >= 0); pm_string_shared_init(&node->unescaped, label.start, label.end); - pm_node_flag_set((pm_node_t *)node, parse_symbol_encoding(parser, &node->unescaped)); + pm_node_flag_set((pm_node_t *) node, parse_symbol_encoding(parser, &node->unescaped)); + break; } case PM_TOKEN_MISSING: { @@ -12644,12 +12637,15 @@ PM_STATIC_ASSERT(__LINE__, ((int) PM_STRING_FLAGS_FORCED_UTF8_ENCODING) == ((int static inline pm_node_flags_t parse_unescaped_encoding(const pm_parser_t *parser) { if (parser->explicit_encoding != NULL) { - // If the there's an explicit encoding and it's using a UTF-8 escape sequence, then mark the string as UTF-8. if (parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY) { + // If the there's an explicit encoding and it's using a UTF-8 escape + // sequence, then mark the string as UTF-8. return PM_STRING_FLAGS_FORCED_UTF8_ENCODING; - // If there's a non-UTF-8 escape sequence being used, then the string uses the source encoding, unless the source - // is marked as US-ASCII. In that case the string is forced as ASCII-8BIT in order to keep the string valid. } else if (parser->encoding == PM_ENCODING_US_ASCII_ENTRY) { + // If there's a non-UTF-8 escape sequence being used, then the + // string uses the source encoding, unless the source is marked as + // US-ASCII. In that case the string is forced as ASCII-8BIT in + // order to keep the string valid. return PM_STRING_FLAGS_FORCED_BINARY_ENCODING; } } @@ -12801,7 +12797,8 @@ parse_operator_symbol(pm_parser_t *parser, const pm_token_t *opening, pm_lex_sta parser_lex(parser); pm_string_shared_init(&symbol->unescaped, parser->previous.start, end); - pm_node_flag_set((pm_node_t *)symbol, parse_symbol_encoding(parser, &symbol->unescaped)); + pm_node_flag_set((pm_node_t *) symbol, PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING); + return (pm_node_t *) symbol; } @@ -12840,7 +12837,7 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s pm_symbol_node_t *symbol = pm_symbol_node_create(parser, &opening, &parser->previous, &closing); pm_string_shared_init(&symbol->unescaped, parser->previous.start, parser->previous.end); - pm_node_flag_set((pm_node_t *)symbol, parse_symbol_encoding(parser, &symbol->unescaped)); + pm_node_flag_set((pm_node_t *) symbol, parse_symbol_encoding(parser, &symbol->unescaped)); return (pm_node_t *) symbol; } @@ -12927,7 +12924,6 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s } else { content = (pm_token_t) { .type = PM_TOKEN_STRING_CONTENT, .start = parser->previous.end, .end = parser->previous.end }; pm_string_shared_init(&unescaped, content.start, content.end); - } if (next_state != PM_LEX_STATE_NONE) { @@ -12940,10 +12936,7 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s expect1(parser, PM_TOKEN_STRING_END, PM_ERR_SYMBOL_TERM_DYNAMIC); } - pm_symbol_node_t *symbol_node = pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped); - pm_node_flag_set((pm_node_t *)symbol_node, parse_symbol_encoding(parser, &symbol_node->unescaped)); - - return (pm_node_t *) symbol_node; + return (pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped, parse_symbol_encoding(parser, &unescaped)); } /** @@ -12968,6 +12961,8 @@ parse_undef_argument(pm_parser_t *parser) { pm_symbol_node_t *symbol = pm_symbol_node_create(parser, &opening, &parser->previous, &closing); pm_string_shared_init(&symbol->unescaped, parser->previous.start, parser->previous.end); + pm_node_flag_set((pm_node_t *) symbol, parse_symbol_encoding(parser, &symbol->unescaped)); + return (pm_node_t *) symbol; } case PM_TOKEN_SYMBOL_BEGIN: { @@ -13007,7 +13002,8 @@ parse_alias_argument(pm_parser_t *parser, bool first) { pm_symbol_node_t *symbol = pm_symbol_node_create(parser, &opening, &parser->previous, &closing); pm_string_shared_init(&symbol->unescaped, parser->previous.start, parser->previous.end); - pm_node_flag_set((pm_node_t *)symbol, parse_symbol_encoding(parser, &symbol->unescaped)); + pm_node_flag_set((pm_node_t *) symbol, parse_symbol_encoding(parser, &symbol->unescaped)); + return (pm_node_t *) symbol; } case PM_TOKEN_SYMBOL_BEGIN: { @@ -14066,7 +14062,7 @@ parse_strings(pm_parser_t *parser, pm_node_t *current) { expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_TERM); node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous); } else if (accept1(parser, PM_TOKEN_LABEL_END) && !state_is_arg_labeled) { - node = (pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped); + node = (pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped, parse_symbol_encoding(parser, &unescaped)); } else if (match1(parser, PM_TOKEN_EOF)) { pm_parser_err_token(parser, &opening, PM_ERR_STRING_LITERAL_TERM); node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->current, &unescaped); @@ -14088,7 +14084,7 @@ parse_strings(pm_parser_t *parser, pm_node_t *current) { pm_node_flag_set(node, parse_unescaped_encoding(parser)); expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_TERM); } else if (accept1(parser, PM_TOKEN_LABEL_END)) { - node = (pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped); + node = (pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped, parse_symbol_encoding(parser, &unescaped)); } else { // If we get here, then we have interpolation so we'll need // to create a string or symbol node with interpolation. diff --git a/test/prism/snapshots/undef.txt b/test/prism/snapshots/undef.txt index fb62b9acb52ec5..3430ef50599d7d 100644 --- a/test/prism/snapshots/undef.txt +++ b/test/prism/snapshots/undef.txt @@ -6,7 +6,7 @@ ├── @ UndefNode (location: (1,0)-(1,7)) │ ├── names: (length: 1) │ │ └── @ SymbolNode (location: (1,6)-(1,7)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,6)-(1,7) = "a" │ │ ├── closing_loc: ∅ @@ -15,13 +15,13 @@ ├── @ UndefNode (location: (3,0)-(3,10)) │ ├── names: (length: 2) │ │ ├── @ SymbolNode (location: (3,6)-(3,7)) - │ │ │ ├── flags: ∅ + │ │ │ ├── flags: forced_us_ascii_encoding │ │ │ ├── opening_loc: ∅ │ │ │ ├── value_loc: (3,6)-(3,7) = "a" │ │ │ ├── closing_loc: ∅ │ │ │ └── unescaped: "a" │ │ └── @ SymbolNode (location: (3,9)-(3,10)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (3,9)-(3,10) = "b" │ │ ├── closing_loc: ∅ @@ -30,7 +30,7 @@ ├── @ UndefNode (location: (5,0)-(5,8)) │ ├── names: (length: 1) │ │ └── @ SymbolNode (location: (5,6)-(5,8)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (5,6)-(5,8) = "if" │ │ ├── closing_loc: ∅ @@ -108,7 +108,7 @@ └── @ UndefNode (location: (17,0)-(17,14)) ├── names: (length: 1) │ └── @ SymbolNode (location: (17,6)-(17,14)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: ∅ │ ├── value_loc: (17,6)-(17,14) = "Constant" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/unparser/corpus/semantic/undef.txt b/test/prism/snapshots/unparser/corpus/semantic/undef.txt index 1578260a64fded..ecb073148d73d8 100644 --- a/test/prism/snapshots/unparser/corpus/semantic/undef.txt +++ b/test/prism/snapshots/unparser/corpus/semantic/undef.txt @@ -6,7 +6,7 @@ ├── @ UndefNode (location: (1,0)-(1,9)) │ ├── names: (length: 1) │ │ └── @ SymbolNode (location: (1,6)-(1,9)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,6)-(1,9) = "foo" │ │ ├── closing_loc: ∅ @@ -15,13 +15,13 @@ └── @ UndefNode (location: (2,0)-(2,14)) ├── names: (length: 2) │ ├── @ SymbolNode (location: (2,6)-(2,9)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (2,6)-(2,9) = "foo" │ │ ├── closing_loc: ∅ │ │ └── unescaped: "foo" │ └── @ SymbolNode (location: (2,11)-(2,14)) - │ ├── flags: ∅ + │ ├── flags: forced_us_ascii_encoding │ ├── opening_loc: ∅ │ ├── value_loc: (2,11)-(2,14) = "bar" │ ├── closing_loc: ∅ diff --git a/test/prism/snapshots/whitequark/undef.txt b/test/prism/snapshots/whitequark/undef.txt index 0f735cc76316e0..9889a5a5257f65 100644 --- a/test/prism/snapshots/whitequark/undef.txt +++ b/test/prism/snapshots/whitequark/undef.txt @@ -6,7 +6,7 @@ └── @ UndefNode (location: (1,0)-(1,27)) ├── names: (length: 3) │ ├── @ SymbolNode (location: (1,6)-(1,9)) - │ │ ├── flags: ∅ + │ │ ├── flags: forced_us_ascii_encoding │ │ ├── opening_loc: ∅ │ │ ├── value_loc: (1,6)-(1,9) = "foo" │ │ ├── closing_loc: ∅ From de135bc247408712a0f630010778af0b405bae1f Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Wed, 24 Jan 2024 21:12:31 +0100 Subject: [PATCH 568/640] [ruby/prism] Add level to warnings and errors to categorize them * Fixes https://github.com/ruby/prism/issues/2082 https://github.com/ruby/prism/commit/7a74576357 --- lib/prism/parse_result.rb | 18 +- prism/diagnostic.c | 471 +++++++++++---------- prism/diagnostic.h | 15 + prism/extension.c | 23 +- prism/templates/lib/prism/serialize.rb.erb | 18 +- prism/templates/src/serialize.c.erb | 2 + test/prism/errors_test.rb | 10 + 7 files changed, 324 insertions(+), 233 deletions(-) diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index 556c66401967e7..27e03fe23b4c01 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -312,10 +312,14 @@ class ParseError # A Location object representing the location of this error in the source. attr_reader :location + # The level of this error + attr_reader :level + # Create a new error object with the given message and location. - def initialize(message, location) + def initialize(message, location, level) @message = message @location = location + @level = level end # Implement the hash pattern matching interface for ParseError. @@ -325,7 +329,7 @@ def deconstruct_keys(keys) # Returns a string representation of this error. def inspect - "#" + "#" end end @@ -337,20 +341,24 @@ class ParseWarning # A Location object representing the location of this warning in the source. attr_reader :location + # The level of this warning + attr_reader :level + # Create a new warning object with the given message and location. - def initialize(message, location) + def initialize(message, location, level) @message = message @location = location + @level = level end # Implement the hash pattern matching interface for ParseWarning. def deconstruct_keys(keys) - { message: message, location: location } + { message: message, location: location, verbose_only: verbose_only } end # Returns a string representation of this warning. def inspect - "#" + "#" end end diff --git a/prism/diagnostic.c b/prism/diagnostic.c index ed47a1cdade06d..112ee4ddee6111 100644 --- a/prism/diagnostic.c +++ b/prism/diagnostic.c @@ -1,5 +1,14 @@ #include "prism/diagnostic.h" +/** This struct holds the data for each diagnostic. */ +struct diagnostic_data { + /** The message associated with the diagnostic. */ + const char* message; + + /** The level associated with the diagnostic. */ + pm_diagnostic_level_t level; +}; + /** * ## Message composition * @@ -49,238 +58,254 @@ * - e.g., "INVALID_NUMBER_DECIMAL" is better than "DECIMAL_INVALID_NUMBER". * - When in doubt, look for similar patterns and name them so that they are grouped when lexically * sorted. See PM_ERR_ARGUMENT_NO_FORWARDING_* for an example. + * + * ## Level + * + * See pm_diagnostic_level_t for the available levels. + * For warning, they are either: + * PM_WARNING_VERBOSE_NOT_NIL if they appear for `ruby -c -e 'code'`, + * or PM_WARNING_VERBOSE_TRUE if they appear only with -w: `ruby -w -c -e 'code'`. */ -static const char* const diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = { - [PM_ERR_ALIAS_ARGUMENT] = "invalid argument being passed to `alias`; expected a bare word, symbol, constant, or global variable", - [PM_ERR_AMPAMPEQ_MULTI_ASSIGN] = "unexpected `&&=` in a multiple assignment", - [PM_ERR_ARGUMENT_AFTER_BLOCK] = "unexpected argument after a block argument", - [PM_ERR_ARGUMENT_AFTER_FORWARDING_ELLIPSES] = "unexpected argument after `...`", - [PM_ERR_ARGUMENT_BARE_HASH] = "unexpected bare hash argument", - [PM_ERR_ARGUMENT_BLOCK_FORWARDING] = "both a block argument and a forwarding argument; only one block is allowed", - [PM_ERR_ARGUMENT_BLOCK_MULTI] = "multiple block arguments; only one block is allowed", - [PM_ERR_ARGUMENT_FORMAL_CLASS] = "invalid formal argument; formal argument cannot be a class variable", - [PM_ERR_ARGUMENT_FORMAL_CONSTANT] = "invalid formal argument; formal argument cannot be a constant", - [PM_ERR_ARGUMENT_FORMAL_GLOBAL] = "invalid formal argument; formal argument cannot be a global variable", - [PM_ERR_ARGUMENT_FORMAL_IVAR] = "invalid formal argument; formal argument cannot be an instance variable", - [PM_ERR_ARGUMENT_FORWARDING_UNBOUND] = "unexpected `...` in an non-parenthesized call", - [PM_ERR_ARGUMENT_IN] = "unexpected `in` keyword in arguments", - [PM_ERR_ARGUMENT_NO_FORWARDING_AMP] = "unexpected `&` when the parent method is not forwarding", - [PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES] = "unexpected `...` when the parent method is not forwarding", - [PM_ERR_ARGUMENT_NO_FORWARDING_STAR] = "unexpected `*` when the parent method is not forwarding", - [PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT] = "unexpected `*` splat argument after a `**` keyword splat argument", - [PM_ERR_ARGUMENT_SPLAT_AFTER_SPLAT] = "unexpected `*` splat argument after a `*` splat argument", - [PM_ERR_ARGUMENT_TERM_PAREN] = "expected a `)` to close the arguments", - [PM_ERR_ARGUMENT_UNEXPECTED_BLOCK] = "unexpected `{` after a method call without parenthesis", - [PM_ERR_ARRAY_ELEMENT] = "expected an element for the array", - [PM_ERR_ARRAY_EXPRESSION] = "expected an expression for the array element", - [PM_ERR_ARRAY_EXPRESSION_AFTER_STAR] = "expected an expression after `*` in the array", - [PM_ERR_ARRAY_SEPARATOR] = "expected a `,` separator for the array elements", - [PM_ERR_ARRAY_TERM] = "expected a `]` to close the array", - [PM_ERR_BEGIN_LONELY_ELSE] = "unexpected `else` in `begin` block; a `rescue` clause must precede `else`", - [PM_ERR_BEGIN_TERM] = "expected an `end` to close the `begin` statement", - [PM_ERR_BEGIN_UPCASE_BRACE] = "expected a `{` after `BEGIN`", - [PM_ERR_BEGIN_UPCASE_TERM] = "expected a `}` to close the `BEGIN` statement", - [PM_ERR_BEGIN_UPCASE_TOPLEVEL] = "BEGIN is permitted only at toplevel", - [PM_ERR_BLOCK_PARAM_LOCAL_VARIABLE] = "expected a local variable name in the block parameters", - [PM_ERR_BLOCK_PARAM_PIPE_TERM] = "expected the block parameters to end with `|`", - [PM_ERR_BLOCK_TERM_BRACE] = "expected a block beginning with `{` to end with `}`", - [PM_ERR_BLOCK_TERM_END] = "expected a block beginning with `do` to end with `end`", - [PM_ERR_CANNOT_PARSE_EXPRESSION] = "cannot parse the expression", - [PM_ERR_CANNOT_PARSE_STRING_PART] = "cannot parse the string part", - [PM_ERR_CASE_EXPRESSION_AFTER_CASE] = "expected an expression after `case`", - [PM_ERR_CASE_EXPRESSION_AFTER_WHEN] = "expected an expression after `when`", - [PM_ERR_CASE_MATCH_MISSING_PREDICATE] = "expected a predicate for a case matching statement", - [PM_ERR_CASE_MISSING_CONDITIONS] = "expected a `when` or `in` clause after `case`", - [PM_ERR_CASE_TERM] = "expected an `end` to close the `case` statement", - [PM_ERR_CLASS_IN_METHOD] = "unexpected class definition in a method definition", - [PM_ERR_CLASS_NAME] = "expected a constant name after `class`", - [PM_ERR_CLASS_SUPERCLASS] = "expected a superclass after `<`", - [PM_ERR_CLASS_TERM] = "expected an `end` to close the `class` statement", - [PM_ERR_CLASS_UNEXPECTED_END] = "unexpected `end`, expecting ';' or '\\n'", - [PM_ERR_CONDITIONAL_ELSIF_PREDICATE] = "expected a predicate expression for the `elsif` statement", - [PM_ERR_CONDITIONAL_IF_PREDICATE] = "expected a predicate expression for the `if` statement", - [PM_ERR_CONDITIONAL_PREDICATE_TERM] = "expected `then` or `;` or '\\n'", - [PM_ERR_CONDITIONAL_TERM] = "expected an `end` to close the conditional clause", - [PM_ERR_CONDITIONAL_TERM_ELSE] = "expected an `end` to close the `else` clause", - [PM_ERR_CONDITIONAL_UNLESS_PREDICATE] = "expected a predicate expression for the `unless` statement", - [PM_ERR_CONDITIONAL_UNTIL_PREDICATE] = "expected a predicate expression for the `until` statement", - [PM_ERR_CONDITIONAL_WHILE_PREDICATE] = "expected a predicate expression for the `while` statement", - [PM_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT] = "expected a constant after the `::` operator", - [PM_ERR_DEF_ENDLESS] = "could not parse the endless method body", - [PM_ERR_DEF_ENDLESS_SETTER] = "invalid method name; a setter method cannot be defined in an endless method definition", - [PM_ERR_DEF_NAME] = "expected a method name", - [PM_ERR_DEF_NAME_AFTER_RECEIVER] = "expected a method name after the receiver", - [PM_ERR_DEF_PARAMS_TERM] = "expected a delimiter to close the parameters", - [PM_ERR_DEF_PARAMS_TERM_PAREN] = "expected a `)` to close the parameters", - [PM_ERR_DEF_RECEIVER] = "expected a receiver for the method definition", - [PM_ERR_DEF_RECEIVER_TERM] = "expected a `.` or `::` after the receiver in a method definition", - [PM_ERR_DEF_TERM] = "expected an `end` to close the `def` statement", - [PM_ERR_DEFINED_EXPRESSION] = "expected an expression after `defined?`", - [PM_ERR_EMBDOC_TERM] = "could not find a terminator for the embedded document", - [PM_ERR_EMBEXPR_END] = "expected a `}` to close the embedded expression", - [PM_ERR_EMBVAR_INVALID] = "invalid embedded variable", - [PM_ERR_END_UPCASE_BRACE] = "expected a `{` after `END`", - [PM_ERR_END_UPCASE_TERM] = "expected a `}` to close the `END` statement", - [PM_ERR_ESCAPE_INVALID_CONTROL] = "invalid control escape sequence", - [PM_ERR_ESCAPE_INVALID_CONTROL_REPEAT] = "invalid control escape sequence; control cannot be repeated", - [PM_ERR_ESCAPE_INVALID_HEXADECIMAL] = "invalid hexadecimal escape sequence", - [PM_ERR_ESCAPE_INVALID_META] = "invalid meta escape sequence", - [PM_ERR_ESCAPE_INVALID_META_REPEAT] = "invalid meta escape sequence; meta cannot be repeated", - [PM_ERR_ESCAPE_INVALID_UNICODE] = "invalid Unicode escape sequence", - [PM_ERR_ESCAPE_INVALID_UNICODE_CM_FLAGS] = "invalid Unicode escape sequence; Unicode cannot be combined with control or meta flags", - [PM_ERR_ESCAPE_INVALID_UNICODE_LITERAL] = "invalid Unicode escape sequence; multiple codepoints are not allowed in a character literal", - [PM_ERR_ESCAPE_INVALID_UNICODE_LONG] = "invalid Unicode escape sequence; maximum length is 6 digits", - [PM_ERR_ESCAPE_INVALID_UNICODE_TERM] = "invalid Unicode escape sequence; needs closing `}`", - [PM_ERR_EXPECT_ARGUMENT] = "expected an argument", - [PM_ERR_EXPECT_EOL_AFTER_STATEMENT] = "expected a newline or semicolon after the statement", - [PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ] = "expected an expression after `&&=`", - [PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ] = "expected an expression after `||=`", - [PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA] = "expected an expression after `,`", - [PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL] = "expected an expression after `=`", - [PM_ERR_EXPECT_EXPRESSION_AFTER_LESS_LESS] = "expected an expression after `<<`", - [PM_ERR_EXPECT_EXPRESSION_AFTER_LPAREN] = "expected an expression after `(`", - [PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR] = "expected an expression after the operator", - [PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT] = "expected an expression after `*` splat in an argument", - [PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH] = "expected an expression after `**` in a hash", - [PM_ERR_EXPECT_EXPRESSION_AFTER_STAR] = "expected an expression after `*`", - [PM_ERR_EXPECT_IDENT_REQ_PARAMETER] = "expected an identifier for the required parameter", - [PM_ERR_EXPECT_LPAREN_REQ_PARAMETER] = "expected a `(` to start a required parameter", - [PM_ERR_EXPECT_RBRACKET] = "expected a matching `]`", - [PM_ERR_EXPECT_RPAREN] = "expected a matching `)`", - [PM_ERR_EXPECT_RPAREN_AFTER_MULTI] = "expected a `)` after multiple assignment", - [PM_ERR_EXPECT_RPAREN_REQ_PARAMETER] = "expected a `)` to end a required parameter", - [PM_ERR_EXPECT_STRING_CONTENT] = "expected string content after opening string delimiter", - [PM_ERR_EXPECT_WHEN_DELIMITER] = "expected a delimiter after the predicates of a `when` clause", - [PM_ERR_EXPRESSION_BARE_HASH] = "unexpected bare hash in expression", - [PM_ERR_FOR_COLLECTION] = "expected a collection after the `in` in a `for` statement", - [PM_ERR_FOR_INDEX] = "expected an index after `for`", - [PM_ERR_FOR_IN] = "expected an `in` after the index in a `for` statement", - [PM_ERR_FOR_TERM] = "expected an `end` to close the `for` loop", - [PM_ERR_HASH_EXPRESSION_AFTER_LABEL] = "expected an expression after the label in a hash", - [PM_ERR_HASH_KEY] = "expected a key in the hash literal", - [PM_ERR_HASH_ROCKET] = "expected a `=>` between the hash key and value", - [PM_ERR_HASH_TERM] = "expected a `}` to close the hash literal", - [PM_ERR_HASH_VALUE] = "expected a value in the hash literal", - [PM_ERR_HEREDOC_TERM] = "could not find a terminator for the heredoc", - [PM_ERR_INCOMPLETE_QUESTION_MARK] = "incomplete expression at `?`", - [PM_ERR_INCOMPLETE_VARIABLE_CLASS] = "incomplete class variable", - [PM_ERR_INCOMPLETE_VARIABLE_INSTANCE] = "incomplete instance variable", - [PM_ERR_INVALID_ENCODING_MAGIC_COMMENT] = "unknown or invalid encoding in the magic comment", - [PM_ERR_INVALID_FLOAT_EXPONENT] = "invalid exponent", - [PM_ERR_INVALID_NUMBER_BINARY] = "invalid binary number", - [PM_ERR_INVALID_NUMBER_DECIMAL] = "invalid decimal number", - [PM_ERR_INVALID_NUMBER_HEXADECIMAL] = "invalid hexadecimal number", - [PM_ERR_INVALID_NUMBER_OCTAL] = "invalid octal number", - [PM_ERR_INVALID_NUMBER_UNDERSCORE] = "invalid underscore placement in number", - [PM_ERR_INVALID_PERCENT] = "invalid `%` token", // TODO WHAT? - [PM_ERR_INVALID_TOKEN] = "invalid token", // TODO WHAT? - [PM_ERR_INVALID_VARIABLE_GLOBAL] = "invalid global variable", - [PM_ERR_IT_NOT_ALLOWED] = "`it` is not allowed when an ordinary parameter is defined", - [PM_ERR_LAMBDA_OPEN] = "expected a `do` keyword or a `{` to open the lambda block", - [PM_ERR_LAMBDA_TERM_BRACE] = "expected a lambda block beginning with `{` to end with `}`", - [PM_ERR_LAMBDA_TERM_END] = "expected a lambda block beginning with `do` to end with `end`", - [PM_ERR_LIST_I_LOWER_ELEMENT] = "expected a symbol in a `%i` list", - [PM_ERR_LIST_I_LOWER_TERM] = "expected a closing delimiter for the `%i` list", - [PM_ERR_LIST_I_UPPER_ELEMENT] = "expected a symbol in a `%I` list", - [PM_ERR_LIST_I_UPPER_TERM] = "expected a closing delimiter for the `%I` list", - [PM_ERR_LIST_W_LOWER_ELEMENT] = "expected a string in a `%w` list", - [PM_ERR_LIST_W_LOWER_TERM] = "expected a closing delimiter for the `%w` list", - [PM_ERR_LIST_W_UPPER_ELEMENT] = "expected a string in a `%W` list", - [PM_ERR_LIST_W_UPPER_TERM] = "expected a closing delimiter for the `%W` list", - [PM_ERR_MALLOC_FAILED] = "failed to allocate memory", - [PM_ERR_MIXED_ENCODING] = "UTF-8 mixed within %s source", - [PM_ERR_MODULE_IN_METHOD] = "unexpected module definition in a method definition", - [PM_ERR_MODULE_NAME] = "expected a constant name after `module`", - [PM_ERR_MODULE_TERM] = "expected an `end` to close the `module` statement", - [PM_ERR_MULTI_ASSIGN_MULTI_SPLATS] = "multiple splats in multiple assignment", - [PM_ERR_NOT_EXPRESSION] = "expected an expression after `not`", - [PM_ERR_NO_LOCAL_VARIABLE] = "%.*s: no such local variable", - [PM_ERR_NUMBER_LITERAL_UNDERSCORE] = "number literal ending with a `_`", - [PM_ERR_NUMBERED_PARAMETER_NOT_ALLOWED] = "numbered parameters are not allowed when an ordinary parameter is defined", - [PM_ERR_NUMBERED_PARAMETER_OUTER_SCOPE] = "numbered parameter is already used in outer scope", - [PM_ERR_OPERATOR_MULTI_ASSIGN] = "unexpected operator for a multiple assignment", - [PM_ERR_OPERATOR_WRITE_ARGUMENTS] = "unexpected operator after a call with arguments", - [PM_ERR_OPERATOR_WRITE_BLOCK] = "unexpected operator after a call with a block", - [PM_ERR_PARAMETER_ASSOC_SPLAT_MULTI] = "unexpected multiple `**` splat parameters", - [PM_ERR_PARAMETER_BLOCK_MULTI] = "multiple block parameters; only one block is allowed", - [PM_ERR_PARAMETER_CIRCULAR] = "parameter default value references itself", - [PM_ERR_PARAMETER_METHOD_NAME] = "unexpected name for a parameter", - [PM_ERR_PARAMETER_NAME_REPEAT] = "repeated parameter name", - [PM_ERR_PARAMETER_NO_DEFAULT] = "expected a default value for the parameter", - [PM_ERR_PARAMETER_NO_DEFAULT_KW] = "expected a default value for the keyword parameter", - [PM_ERR_PARAMETER_NUMBERED_RESERVED] = "%.2s is reserved for numbered parameters", - [PM_ERR_PARAMETER_ORDER] = "unexpected parameter order", - [PM_ERR_PARAMETER_SPLAT_MULTI] = "unexpected multiple `*` splat parameters", - [PM_ERR_PARAMETER_STAR] = "unexpected parameter `*`", - [PM_ERR_PARAMETER_UNEXPECTED_FWD] = "unexpected `...` in parameters", - [PM_ERR_PARAMETER_WILD_LOOSE_COMMA] = "unexpected `,` in parameters", - [PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET] = "expected a pattern expression after the `[` operator", - [PM_ERR_PATTERN_EXPRESSION_AFTER_COMMA] = "expected a pattern expression after `,`", - [PM_ERR_PATTERN_EXPRESSION_AFTER_HROCKET] = "expected a pattern expression after `=>`", - [PM_ERR_PATTERN_EXPRESSION_AFTER_IN] = "expected a pattern expression after the `in` keyword", - [PM_ERR_PATTERN_EXPRESSION_AFTER_KEY] = "expected a pattern expression after the key", - [PM_ERR_PATTERN_EXPRESSION_AFTER_PAREN] = "expected a pattern expression after the `(` operator", - [PM_ERR_PATTERN_EXPRESSION_AFTER_PIN] = "expected a pattern expression after the `^` pin operator", - [PM_ERR_PATTERN_EXPRESSION_AFTER_PIPE] = "expected a pattern expression after the `|` operator", - [PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE] = "expected a pattern expression after the range operator", - [PM_ERR_PATTERN_EXPRESSION_AFTER_REST] = "unexpected pattern expression after the `**` expression", - [PM_ERR_PATTERN_HASH_KEY] = "expected a key in the hash pattern", - [PM_ERR_PATTERN_HASH_KEY_LABEL] = "expected a label as the key in the hash pattern", // TODO // THIS // AND // ABOVE // IS WEIRD - [PM_ERR_PATTERN_IDENT_AFTER_HROCKET] = "expected an identifier after the `=>` operator", - [PM_ERR_PATTERN_LABEL_AFTER_COMMA] = "expected a label after the `,` in the hash pattern", - [PM_ERR_PATTERN_REST] = "unexpected rest pattern", - [PM_ERR_PATTERN_TERM_BRACE] = "expected a `}` to close the pattern expression", - [PM_ERR_PATTERN_TERM_BRACKET] = "expected a `]` to close the pattern expression", - [PM_ERR_PATTERN_TERM_PAREN] = "expected a `)` to close the pattern expression", - [PM_ERR_PIPEPIPEEQ_MULTI_ASSIGN] = "unexpected `||=` in a multiple assignment", - [PM_ERR_REGEXP_TERM] = "expected a closing delimiter for the regular expression", - [PM_ERR_RESCUE_EXPRESSION] = "expected a rescued expression", - [PM_ERR_RESCUE_MODIFIER_VALUE] = "expected a value after the `rescue` modifier", - [PM_ERR_RESCUE_TERM] = "expected a closing delimiter for the `rescue` clause", - [PM_ERR_RESCUE_VARIABLE] = "expected an exception variable after `=>` in a rescue statement", - [PM_ERR_RETURN_INVALID] = "invalid `return` in a class or module body", - [PM_ERR_STATEMENT_ALIAS] = "unexpected an `alias` at a non-statement position", - [PM_ERR_STATEMENT_POSTEXE_END] = "unexpected an `END` at a non-statement position", - [PM_ERR_STATEMENT_PREEXE_BEGIN] = "unexpected a `BEGIN` at a non-statement position", - [PM_ERR_STATEMENT_UNDEF] = "unexpected an `undef` at a non-statement position", - [PM_ERR_STRING_CONCATENATION] = "expected a string for concatenation", - [PM_ERR_STRING_INTERPOLATED_TERM] = "expected a closing delimiter for the interpolated string", - [PM_ERR_STRING_LITERAL_TERM] = "expected a closing delimiter for the string literal", - [PM_ERR_SYMBOL_INVALID] = "invalid symbol", // TODO expected symbol? prism.c ~9719 - [PM_ERR_SYMBOL_TERM_DYNAMIC] = "expected a closing delimiter for the dynamic symbol", - [PM_ERR_SYMBOL_TERM_INTERPOLATED] = "expected a closing delimiter for the interpolated symbol", - [PM_ERR_TERNARY_COLON] = "expected a `:` after the true expression of a ternary operator", - [PM_ERR_TERNARY_EXPRESSION_FALSE] = "expected an expression after `:` in the ternary operator", - [PM_ERR_TERNARY_EXPRESSION_TRUE] = "expected an expression after `?` in the ternary operator", - [PM_ERR_UNDEF_ARGUMENT] = "invalid argument being passed to `undef`; expected a bare word, constant, or symbol argument", - [PM_ERR_UNARY_RECEIVER_BANG] = "expected a receiver for unary `!`", - [PM_ERR_UNARY_RECEIVER_MINUS] = "expected a receiver for unary `-`", - [PM_ERR_UNARY_RECEIVER_PLUS] = "expected a receiver for unary `+`", - [PM_ERR_UNARY_RECEIVER_TILDE] = "expected a receiver for unary `~`", - [PM_ERR_UNTIL_TERM] = "expected an `end` to close the `until` statement", - [PM_ERR_VOID_EXPRESSION] = "unexpected void value expression", - [PM_ERR_WHILE_TERM] = "expected an `end` to close the `while` statement", - [PM_ERR_WRITE_TARGET_IN_METHOD] = "dynamic constant assignment", - [PM_ERR_WRITE_TARGET_READONLY] = "immutable variable as a write target", - [PM_ERR_WRITE_TARGET_UNEXPECTED] = "unexpected write target", - [PM_ERR_XSTRING_TERM] = "expected a closing delimiter for the `%x` or backtick string", - [PM_WARN_AMBIGUOUS_FIRST_ARGUMENT_MINUS] = "ambiguous first argument; put parentheses or a space even after `-` operator", - [PM_WARN_AMBIGUOUS_FIRST_ARGUMENT_PLUS] = "ambiguous first argument; put parentheses or a space even after `+` operator", - [PM_WARN_AMBIGUOUS_PREFIX_STAR] = "ambiguous `*` has been interpreted as an argument prefix", - [PM_WARN_AMBIGUOUS_SLASH] = "ambiguous `/`; wrap regexp in parentheses or add a space after `/` operator", - [PM_WARN_END_IN_METHOD] = "END in method; use at_exit", +static struct diagnostic_data const diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = { + // Errors + [PM_ERR_ALIAS_ARGUMENT] = { "invalid argument being passed to `alias`; expected a bare word, symbol, constant, or global variable", PM_ERROR_DEFAULT }, + [PM_ERR_AMPAMPEQ_MULTI_ASSIGN] = { "unexpected `&&=` in a multiple assignment", PM_ERROR_DEFAULT }, + [PM_ERR_ARGUMENT_AFTER_BLOCK] = { "unexpected argument after a block argument", PM_ERROR_DEFAULT }, + [PM_ERR_ARGUMENT_AFTER_FORWARDING_ELLIPSES] = { "unexpected argument after `...`", PM_ERROR_DEFAULT }, + [PM_ERR_ARGUMENT_BARE_HASH] = { "unexpected bare hash argument", PM_ERROR_DEFAULT }, + [PM_ERR_ARGUMENT_BLOCK_FORWARDING] = { "both a block argument and a forwarding argument; only one block is allowed", PM_ERROR_DEFAULT }, + [PM_ERR_ARGUMENT_BLOCK_MULTI] = { "multiple block arguments; only one block is allowed", PM_ERROR_DEFAULT }, + [PM_ERR_ARGUMENT_FORMAL_CLASS] = { "invalid formal argument; formal argument cannot be a class variable", PM_ERROR_DEFAULT }, + [PM_ERR_ARGUMENT_FORMAL_CONSTANT] = { "invalid formal argument; formal argument cannot be a constant", PM_ERROR_DEFAULT }, + [PM_ERR_ARGUMENT_FORMAL_GLOBAL] = { "invalid formal argument; formal argument cannot be a global variable", PM_ERROR_DEFAULT }, + [PM_ERR_ARGUMENT_FORMAL_IVAR] = { "invalid formal argument; formal argument cannot be an instance variable", PM_ERROR_DEFAULT }, + [PM_ERR_ARGUMENT_FORWARDING_UNBOUND] = { "unexpected `...` in an non-parenthesized call", PM_ERROR_DEFAULT }, + [PM_ERR_ARGUMENT_IN] = { "unexpected `in` keyword in arguments", PM_ERROR_DEFAULT }, + [PM_ERR_ARGUMENT_NO_FORWARDING_AMP] = { "unexpected `&` when the parent method is not forwarding", PM_ERROR_DEFAULT }, + [PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES] = { "unexpected `...` when the parent method is not forwarding", PM_ERROR_DEFAULT }, + [PM_ERR_ARGUMENT_NO_FORWARDING_STAR] = { "unexpected `*` when the parent method is not forwarding", PM_ERROR_DEFAULT }, + [PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT] = { "unexpected `*` splat argument after a `**` keyword splat argument", PM_ERROR_DEFAULT }, + [PM_ERR_ARGUMENT_SPLAT_AFTER_SPLAT] = { "unexpected `*` splat argument after a `*` splat argument", PM_ERROR_DEFAULT }, + [PM_ERR_ARGUMENT_TERM_PAREN] = { "expected a `)` to close the arguments", PM_ERROR_DEFAULT }, + [PM_ERR_ARGUMENT_UNEXPECTED_BLOCK] = { "unexpected `{` after a method call without parenthesis", PM_ERROR_DEFAULT }, + [PM_ERR_ARRAY_ELEMENT] = { "expected an element for the array", PM_ERROR_DEFAULT }, + [PM_ERR_ARRAY_EXPRESSION] = { "expected an expression for the array element", PM_ERROR_DEFAULT }, + [PM_ERR_ARRAY_EXPRESSION_AFTER_STAR] = { "expected an expression after `*` in the array", PM_ERROR_DEFAULT }, + [PM_ERR_ARRAY_SEPARATOR] = { "expected a `,` separator for the array elements", PM_ERROR_DEFAULT }, + [PM_ERR_ARRAY_TERM] = { "expected a `]` to close the array", PM_ERROR_DEFAULT }, + [PM_ERR_BEGIN_LONELY_ELSE] = { "unexpected `else` in `begin` block; a `rescue` clause must precede `else`", PM_ERROR_DEFAULT }, + [PM_ERR_BEGIN_TERM] = { "expected an `end` to close the `begin` statement", PM_ERROR_DEFAULT }, + [PM_ERR_BEGIN_UPCASE_BRACE] = { "expected a `{` after `BEGIN`", PM_ERROR_DEFAULT }, + [PM_ERR_BEGIN_UPCASE_TERM] = { "expected a `}` to close the `BEGIN` statement", PM_ERROR_DEFAULT }, + [PM_ERR_BEGIN_UPCASE_TOPLEVEL] = { "BEGIN is permitted only at toplevel", PM_ERROR_DEFAULT }, + [PM_ERR_BLOCK_PARAM_LOCAL_VARIABLE] = { "expected a local variable name in the block parameters", PM_ERROR_DEFAULT }, + [PM_ERR_BLOCK_PARAM_PIPE_TERM] = { "expected the block parameters to end with `|`", PM_ERROR_DEFAULT }, + [PM_ERR_BLOCK_TERM_BRACE] = { "expected a block beginning with `{` to end with `}`", PM_ERROR_DEFAULT }, + [PM_ERR_BLOCK_TERM_END] = { "expected a block beginning with `do` to end with `end`", PM_ERROR_DEFAULT }, + [PM_ERR_CANNOT_PARSE_EXPRESSION] = { "cannot parse the expression", PM_ERROR_DEFAULT }, + [PM_ERR_CANNOT_PARSE_STRING_PART] = { "cannot parse the string part", PM_ERROR_DEFAULT }, + [PM_ERR_CASE_EXPRESSION_AFTER_CASE] = { "expected an expression after `case`", PM_ERROR_DEFAULT }, + [PM_ERR_CASE_EXPRESSION_AFTER_WHEN] = { "expected an expression after `when`", PM_ERROR_DEFAULT }, + [PM_ERR_CASE_MATCH_MISSING_PREDICATE] = { "expected a predicate for a case matching statement", PM_ERROR_DEFAULT }, + [PM_ERR_CASE_MISSING_CONDITIONS] = { "expected a `when` or `in` clause after `case`", PM_ERROR_DEFAULT }, + [PM_ERR_CASE_TERM] = { "expected an `end` to close the `case` statement", PM_ERROR_DEFAULT }, + [PM_ERR_CLASS_IN_METHOD] = { "unexpected class definition in a method definition", PM_ERROR_DEFAULT }, + [PM_ERR_CLASS_NAME] = { "expected a constant name after `class`", PM_ERROR_DEFAULT }, + [PM_ERR_CLASS_SUPERCLASS] = { "expected a superclass after `<`", PM_ERROR_DEFAULT }, + [PM_ERR_CLASS_TERM] = { "expected an `end` to close the `class` statement", PM_ERROR_DEFAULT }, + [PM_ERR_CLASS_UNEXPECTED_END] = { "unexpected `end`, expecting ';' or '\\n'", PM_ERROR_DEFAULT }, + [PM_ERR_CONDITIONAL_ELSIF_PREDICATE] = { "expected a predicate expression for the `elsif` statement", PM_ERROR_DEFAULT }, + [PM_ERR_CONDITIONAL_IF_PREDICATE] = { "expected a predicate expression for the `if` statement", PM_ERROR_DEFAULT }, + [PM_ERR_CONDITIONAL_PREDICATE_TERM] = { "expected `then` or `;` or '\\n'", PM_ERROR_DEFAULT }, + [PM_ERR_CONDITIONAL_TERM] = { "expected an `end` to close the conditional clause", PM_ERROR_DEFAULT }, + [PM_ERR_CONDITIONAL_TERM_ELSE] = { "expected an `end` to close the `else` clause", PM_ERROR_DEFAULT }, + [PM_ERR_CONDITIONAL_UNLESS_PREDICATE] = { "expected a predicate expression for the `unless` statement", PM_ERROR_DEFAULT }, + [PM_ERR_CONDITIONAL_UNTIL_PREDICATE] = { "expected a predicate expression for the `until` statement", PM_ERROR_DEFAULT }, + [PM_ERR_CONDITIONAL_WHILE_PREDICATE] = { "expected a predicate expression for the `while` statement", PM_ERROR_DEFAULT }, + [PM_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT] = { "expected a constant after the `::` operator", PM_ERROR_DEFAULT }, + [PM_ERR_DEF_ENDLESS] = { "could not parse the endless method body", PM_ERROR_DEFAULT }, + [PM_ERR_DEF_ENDLESS_SETTER] = { "invalid method name; a setter method cannot be defined in an endless method definition", PM_ERROR_DEFAULT }, + [PM_ERR_DEF_NAME] = { "expected a method name", PM_ERROR_DEFAULT }, + [PM_ERR_DEF_NAME_AFTER_RECEIVER] = { "expected a method name after the receiver", PM_ERROR_DEFAULT }, + [PM_ERR_DEF_PARAMS_TERM] = { "expected a delimiter to close the parameters", PM_ERROR_DEFAULT }, + [PM_ERR_DEF_PARAMS_TERM_PAREN] = { "expected a `)` to close the parameters", PM_ERROR_DEFAULT }, + [PM_ERR_DEF_RECEIVER] = { "expected a receiver for the method definition", PM_ERROR_DEFAULT }, + [PM_ERR_DEF_RECEIVER_TERM] = { "expected a `.` or `::` after the receiver in a method definition", PM_ERROR_DEFAULT }, + [PM_ERR_DEF_TERM] = { "expected an `end` to close the `def` statement", PM_ERROR_DEFAULT }, + [PM_ERR_DEFINED_EXPRESSION] = { "expected an expression after `defined?`", PM_ERROR_DEFAULT }, + [PM_ERR_EMBDOC_TERM] = { "could not find a terminator for the embedded document", PM_ERROR_DEFAULT }, + [PM_ERR_EMBEXPR_END] = { "expected a `}` to close the embedded expression", PM_ERROR_DEFAULT }, + [PM_ERR_EMBVAR_INVALID] = { "invalid embedded variable", PM_ERROR_DEFAULT }, + [PM_ERR_END_UPCASE_BRACE] = { "expected a `{` after `END`", PM_ERROR_DEFAULT }, + [PM_ERR_END_UPCASE_TERM] = { "expected a `}` to close the `END` statement", PM_ERROR_DEFAULT }, + [PM_ERR_ESCAPE_INVALID_CONTROL] = { "invalid control escape sequence", PM_ERROR_DEFAULT }, + [PM_ERR_ESCAPE_INVALID_CONTROL_REPEAT] = { "invalid control escape sequence; control cannot be repeated", PM_ERROR_DEFAULT }, + [PM_ERR_ESCAPE_INVALID_HEXADECIMAL] = { "invalid hexadecimal escape sequence", PM_ERROR_DEFAULT }, + [PM_ERR_ESCAPE_INVALID_META] = { "invalid meta escape sequence", PM_ERROR_DEFAULT }, + [PM_ERR_ESCAPE_INVALID_META_REPEAT] = { "invalid meta escape sequence; meta cannot be repeated", PM_ERROR_DEFAULT }, + [PM_ERR_ESCAPE_INVALID_UNICODE] = { "invalid Unicode escape sequence", PM_ERROR_DEFAULT }, + [PM_ERR_ESCAPE_INVALID_UNICODE_CM_FLAGS] = { "invalid Unicode escape sequence; Unicode cannot be combined with control or meta flags", PM_ERROR_DEFAULT }, + [PM_ERR_ESCAPE_INVALID_UNICODE_LITERAL] = { "invalid Unicode escape sequence; multiple codepoints are not allowed in a character literal", PM_ERROR_DEFAULT }, + [PM_ERR_ESCAPE_INVALID_UNICODE_LONG] = { "invalid Unicode escape sequence; maximum length is 6 digits", PM_ERROR_DEFAULT }, + [PM_ERR_ESCAPE_INVALID_UNICODE_TERM] = { "invalid Unicode escape sequence; needs closing `}`", PM_ERROR_DEFAULT }, + [PM_ERR_EXPECT_ARGUMENT] = { "expected an argument", PM_ERROR_DEFAULT }, + [PM_ERR_EXPECT_EOL_AFTER_STATEMENT] = { "expected a newline or semicolon after the statement", PM_ERROR_DEFAULT }, + [PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ] = { "expected an expression after `&&=`", PM_ERROR_DEFAULT }, + [PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ] = { "expected an expression after `||=`", PM_ERROR_DEFAULT }, + [PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA] = { "expected an expression after `,`", PM_ERROR_DEFAULT }, + [PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL] = { "expected an expression after `=`", PM_ERROR_DEFAULT }, + [PM_ERR_EXPECT_EXPRESSION_AFTER_LESS_LESS] = { "expected an expression after `<<`", PM_ERROR_DEFAULT }, + [PM_ERR_EXPECT_EXPRESSION_AFTER_LPAREN] = { "expected an expression after `(`", PM_ERROR_DEFAULT }, + [PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR] = { "expected an expression after the operator", PM_ERROR_DEFAULT }, + [PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT] = { "expected an expression after `*` splat in an argument", PM_ERROR_DEFAULT }, + [PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH] = { "expected an expression after `**` in a hash", PM_ERROR_DEFAULT }, + [PM_ERR_EXPECT_EXPRESSION_AFTER_STAR] = { "expected an expression after `*`", PM_ERROR_DEFAULT }, + [PM_ERR_EXPECT_IDENT_REQ_PARAMETER] = { "expected an identifier for the required parameter", PM_ERROR_DEFAULT }, + [PM_ERR_EXPECT_LPAREN_REQ_PARAMETER] = { "expected a `(` to start a required parameter", PM_ERROR_DEFAULT }, + [PM_ERR_EXPECT_RBRACKET] = { "expected a matching `]`", PM_ERROR_DEFAULT }, + [PM_ERR_EXPECT_RPAREN] = { "expected a matching `)`", PM_ERROR_DEFAULT }, + [PM_ERR_EXPECT_RPAREN_AFTER_MULTI] = { "expected a `)` after multiple assignment", PM_ERROR_DEFAULT }, + [PM_ERR_EXPECT_RPAREN_REQ_PARAMETER] = { "expected a `)` to end a required parameter", PM_ERROR_DEFAULT }, + [PM_ERR_EXPECT_STRING_CONTENT] = { "expected string content after opening string delimiter", PM_ERROR_DEFAULT }, + [PM_ERR_EXPECT_WHEN_DELIMITER] = { "expected a delimiter after the predicates of a `when` clause", PM_ERROR_DEFAULT }, + [PM_ERR_EXPRESSION_BARE_HASH] = { "unexpected bare hash in expression", PM_ERROR_DEFAULT }, + [PM_ERR_FOR_COLLECTION] = { "expected a collection after the `in` in a `for` statement", PM_ERROR_DEFAULT }, + [PM_ERR_FOR_INDEX] = { "expected an index after `for`", PM_ERROR_DEFAULT }, + [PM_ERR_FOR_IN] = { "expected an `in` after the index in a `for` statement", PM_ERROR_DEFAULT }, + [PM_ERR_FOR_TERM] = { "expected an `end` to close the `for` loop", PM_ERROR_DEFAULT }, + [PM_ERR_HASH_EXPRESSION_AFTER_LABEL] = { "expected an expression after the label in a hash", PM_ERROR_DEFAULT }, + [PM_ERR_HASH_KEY] = { "expected a key in the hash literal", PM_ERROR_DEFAULT }, + [PM_ERR_HASH_ROCKET] = { "expected a `=>` between the hash key and value", PM_ERROR_DEFAULT }, + [PM_ERR_HASH_TERM] = { "expected a `}` to close the hash literal", PM_ERROR_DEFAULT }, + [PM_ERR_HASH_VALUE] = { "expected a value in the hash literal", PM_ERROR_DEFAULT }, + [PM_ERR_HEREDOC_TERM] = { "could not find a terminator for the heredoc", PM_ERROR_DEFAULT }, + [PM_ERR_INCOMPLETE_QUESTION_MARK] = { "incomplete expression at `?`", PM_ERROR_DEFAULT }, + [PM_ERR_INCOMPLETE_VARIABLE_CLASS] = { "incomplete class variable", PM_ERROR_DEFAULT }, + [PM_ERR_INCOMPLETE_VARIABLE_INSTANCE] = { "incomplete instance variable", PM_ERROR_DEFAULT }, + [PM_ERR_INVALID_ENCODING_MAGIC_COMMENT] = { "unknown or invalid encoding in the magic comment", PM_ERROR_DEFAULT }, + [PM_ERR_INVALID_FLOAT_EXPONENT] = { "invalid exponent", PM_ERROR_DEFAULT }, + [PM_ERR_INVALID_NUMBER_BINARY] = { "invalid binary number", PM_ERROR_DEFAULT }, + [PM_ERR_INVALID_NUMBER_DECIMAL] = { "invalid decimal number", PM_ERROR_DEFAULT }, + [PM_ERR_INVALID_NUMBER_HEXADECIMAL] = { "invalid hexadecimal number", PM_ERROR_DEFAULT }, + [PM_ERR_INVALID_NUMBER_OCTAL] = { "invalid octal number", PM_ERROR_DEFAULT }, + [PM_ERR_INVALID_NUMBER_UNDERSCORE] = { "invalid underscore placement in number", PM_ERROR_DEFAULT }, + [PM_ERR_INVALID_PERCENT] = { "invalid `%` token", PM_ERROR_DEFAULT }, // TODO WHAT? + [PM_ERR_INVALID_TOKEN] = { "invalid token", PM_ERROR_DEFAULT }, // TODO WHAT? + [PM_ERR_INVALID_VARIABLE_GLOBAL] = { "invalid global variable", PM_ERROR_DEFAULT }, + [PM_ERR_IT_NOT_ALLOWED] = { "`it` is not allowed when an ordinary parameter is defined", PM_ERROR_DEFAULT }, + [PM_ERR_LAMBDA_OPEN] = { "expected a `do` keyword or a `{` to open the lambda block", PM_ERROR_DEFAULT }, + [PM_ERR_LAMBDA_TERM_BRACE] = { "expected a lambda block beginning with `{` to end with `}`", PM_ERROR_DEFAULT }, + [PM_ERR_LAMBDA_TERM_END] = { "expected a lambda block beginning with `do` to end with `end`", PM_ERROR_DEFAULT }, + [PM_ERR_LIST_I_LOWER_ELEMENT] = { "expected a symbol in a `%i` list", PM_ERROR_DEFAULT }, + [PM_ERR_LIST_I_LOWER_TERM] = { "expected a closing delimiter for the `%i` list", PM_ERROR_DEFAULT }, + [PM_ERR_LIST_I_UPPER_ELEMENT] = { "expected a symbol in a `%I` list", PM_ERROR_DEFAULT }, + [PM_ERR_LIST_I_UPPER_TERM] = { "expected a closing delimiter for the `%I` list", PM_ERROR_DEFAULT }, + [PM_ERR_LIST_W_LOWER_ELEMENT] = { "expected a string in a `%w` list", PM_ERROR_DEFAULT }, + [PM_ERR_LIST_W_LOWER_TERM] = { "expected a closing delimiter for the `%w` list", PM_ERROR_DEFAULT }, + [PM_ERR_LIST_W_UPPER_ELEMENT] = { "expected a string in a `%W` list", PM_ERROR_DEFAULT }, + [PM_ERR_LIST_W_UPPER_TERM] = { "expected a closing delimiter for the `%W` list", PM_ERROR_DEFAULT }, + [PM_ERR_MALLOC_FAILED] = { "failed to allocate memory", PM_ERROR_DEFAULT }, + [PM_ERR_MIXED_ENCODING] = { "UTF-8 mixed within %s source", PM_ERROR_DEFAULT }, + [PM_ERR_MODULE_IN_METHOD] = { "unexpected module definition in a method definition", PM_ERROR_DEFAULT }, + [PM_ERR_MODULE_NAME] = { "expected a constant name after `module`", PM_ERROR_DEFAULT }, + [PM_ERR_MODULE_TERM] = { "expected an `end` to close the `module` statement", PM_ERROR_DEFAULT }, + [PM_ERR_MULTI_ASSIGN_MULTI_SPLATS] = { "multiple splats in multiple assignment", PM_ERROR_DEFAULT }, + [PM_ERR_NOT_EXPRESSION] = { "expected an expression after `not`", PM_ERROR_DEFAULT }, + [PM_ERR_NO_LOCAL_VARIABLE] = { "%.*s: no such local variable", PM_ERROR_DEFAULT }, + [PM_ERR_NUMBER_LITERAL_UNDERSCORE] = { "number literal ending with a `_`", PM_ERROR_DEFAULT }, + [PM_ERR_NUMBERED_PARAMETER_NOT_ALLOWED] = { "numbered parameters are not allowed when an ordinary parameter is defined", PM_ERROR_DEFAULT }, + [PM_ERR_NUMBERED_PARAMETER_OUTER_SCOPE] = { "numbered parameter is already used in outer scope", PM_ERROR_DEFAULT }, + [PM_ERR_OPERATOR_MULTI_ASSIGN] = { "unexpected operator for a multiple assignment", PM_ERROR_DEFAULT }, + [PM_ERR_OPERATOR_WRITE_ARGUMENTS] = { "unexpected operator after a call with arguments", PM_ERROR_DEFAULT }, + [PM_ERR_OPERATOR_WRITE_BLOCK] = { "unexpected operator after a call with a block", PM_ERROR_DEFAULT }, + [PM_ERR_PARAMETER_ASSOC_SPLAT_MULTI] = { "unexpected multiple `**` splat parameters", PM_ERROR_DEFAULT }, + [PM_ERR_PARAMETER_BLOCK_MULTI] = { "multiple block parameters; only one block is allowed", PM_ERROR_DEFAULT }, + [PM_ERR_PARAMETER_CIRCULAR] = { "parameter default value references itself", PM_ERROR_DEFAULT }, + [PM_ERR_PARAMETER_METHOD_NAME] = { "unexpected name for a parameter", PM_ERROR_DEFAULT }, + [PM_ERR_PARAMETER_NAME_REPEAT] = { "repeated parameter name", PM_ERROR_DEFAULT }, + [PM_ERR_PARAMETER_NO_DEFAULT] = { "expected a default value for the parameter", PM_ERROR_DEFAULT }, + [PM_ERR_PARAMETER_NO_DEFAULT_KW] = { "expected a default value for the keyword parameter", PM_ERROR_DEFAULT }, + [PM_ERR_PARAMETER_NUMBERED_RESERVED] = { "%.2s is reserved for numbered parameters", PM_ERROR_DEFAULT }, + [PM_ERR_PARAMETER_ORDER] = { "unexpected parameter order", PM_ERROR_DEFAULT }, + [PM_ERR_PARAMETER_SPLAT_MULTI] = { "unexpected multiple `*` splat parameters", PM_ERROR_DEFAULT }, + [PM_ERR_PARAMETER_STAR] = { "unexpected parameter `*`", PM_ERROR_DEFAULT }, + [PM_ERR_PARAMETER_UNEXPECTED_FWD] = { "unexpected `...` in parameters", PM_ERROR_DEFAULT }, + [PM_ERR_PARAMETER_WILD_LOOSE_COMMA] = { "unexpected `,` in parameters", PM_ERROR_DEFAULT }, + [PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET] = { "expected a pattern expression after the `[` operator", PM_ERROR_DEFAULT }, + [PM_ERR_PATTERN_EXPRESSION_AFTER_COMMA] = { "expected a pattern expression after `,`", PM_ERROR_DEFAULT }, + [PM_ERR_PATTERN_EXPRESSION_AFTER_HROCKET] = { "expected a pattern expression after `=>`", PM_ERROR_DEFAULT }, + [PM_ERR_PATTERN_EXPRESSION_AFTER_IN] = { "expected a pattern expression after the `in` keyword", PM_ERROR_DEFAULT }, + [PM_ERR_PATTERN_EXPRESSION_AFTER_KEY] = { "expected a pattern expression after the key", PM_ERROR_DEFAULT }, + [PM_ERR_PATTERN_EXPRESSION_AFTER_PAREN] = { "expected a pattern expression after the `(` operator", PM_ERROR_DEFAULT }, + [PM_ERR_PATTERN_EXPRESSION_AFTER_PIN] = { "expected a pattern expression after the `^` pin operator", PM_ERROR_DEFAULT }, + [PM_ERR_PATTERN_EXPRESSION_AFTER_PIPE] = { "expected a pattern expression after the `|` operator", PM_ERROR_DEFAULT }, + [PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE] = { "expected a pattern expression after the range operator", PM_ERROR_DEFAULT }, + [PM_ERR_PATTERN_EXPRESSION_AFTER_REST] = { "unexpected pattern expression after the `**` expression", PM_ERROR_DEFAULT }, + [PM_ERR_PATTERN_HASH_KEY] = { "expected a key in the hash pattern", PM_ERROR_DEFAULT }, + [PM_ERR_PATTERN_HASH_KEY_LABEL] = { "expected a label as the key in the hash pattern", PM_ERROR_DEFAULT }, // TODO // THIS // AND // ABOVE // IS WEIRD + [PM_ERR_PATTERN_IDENT_AFTER_HROCKET] = { "expected an identifier after the `=>` operator", PM_ERROR_DEFAULT }, + [PM_ERR_PATTERN_LABEL_AFTER_COMMA] = { "expected a label after the `,` in the hash pattern", PM_ERROR_DEFAULT }, + [PM_ERR_PATTERN_REST] = { "unexpected rest pattern", PM_ERROR_DEFAULT }, + [PM_ERR_PATTERN_TERM_BRACE] = { "expected a `}` to close the pattern expression", PM_ERROR_DEFAULT }, + [PM_ERR_PATTERN_TERM_BRACKET] = { "expected a `]` to close the pattern expression", PM_ERROR_DEFAULT }, + [PM_ERR_PATTERN_TERM_PAREN] = { "expected a `)` to close the pattern expression", PM_ERROR_DEFAULT }, + [PM_ERR_PIPEPIPEEQ_MULTI_ASSIGN] = { "unexpected `||=` in a multiple assignment", PM_ERROR_DEFAULT }, + [PM_ERR_REGEXP_TERM] = { "expected a closing delimiter for the regular expression", PM_ERROR_DEFAULT }, + [PM_ERR_RESCUE_EXPRESSION] = { "expected a rescued expression", PM_ERROR_DEFAULT }, + [PM_ERR_RESCUE_MODIFIER_VALUE] = { "expected a value after the `rescue` modifier", PM_ERROR_DEFAULT }, + [PM_ERR_RESCUE_TERM] = { "expected a closing delimiter for the `rescue` clause", PM_ERROR_DEFAULT }, + [PM_ERR_RESCUE_VARIABLE] = { "expected an exception variable after `=>` in a rescue statement", PM_ERROR_DEFAULT }, + [PM_ERR_RETURN_INVALID] = { "invalid `return` in a class or module body", PM_ERROR_DEFAULT }, + [PM_ERR_STATEMENT_ALIAS] = { "unexpected an `alias` at a non-statement position", PM_ERROR_DEFAULT }, + [PM_ERR_STATEMENT_POSTEXE_END] = { "unexpected an `END` at a non-statement position", PM_ERROR_DEFAULT }, + [PM_ERR_STATEMENT_PREEXE_BEGIN] = { "unexpected a `BEGIN` at a non-statement position", PM_ERROR_DEFAULT }, + [PM_ERR_STATEMENT_UNDEF] = { "unexpected an `undef` at a non-statement position", PM_ERROR_DEFAULT }, + [PM_ERR_STRING_CONCATENATION] = { "expected a string for concatenation", PM_ERROR_DEFAULT }, + [PM_ERR_STRING_INTERPOLATED_TERM] = { "expected a closing delimiter for the interpolated string", PM_ERROR_DEFAULT }, + [PM_ERR_STRING_LITERAL_TERM] = { "expected a closing delimiter for the string literal", PM_ERROR_DEFAULT }, + [PM_ERR_SYMBOL_INVALID] = { "invalid symbol", PM_ERROR_DEFAULT }, // TODO expected symbol? prism.c ~9719 + [PM_ERR_SYMBOL_TERM_DYNAMIC] = { "expected a closing delimiter for the dynamic symbol", PM_ERROR_DEFAULT }, + [PM_ERR_SYMBOL_TERM_INTERPOLATED] = { "expected a closing delimiter for the interpolated symbol", PM_ERROR_DEFAULT }, + [PM_ERR_TERNARY_COLON] = { "expected a `:` after the true expression of a ternary operator", PM_ERROR_DEFAULT }, + [PM_ERR_TERNARY_EXPRESSION_FALSE] = { "expected an expression after `:` in the ternary operator", PM_ERROR_DEFAULT }, + [PM_ERR_TERNARY_EXPRESSION_TRUE] = { "expected an expression after `?` in the ternary operator", PM_ERROR_DEFAULT }, + [PM_ERR_UNDEF_ARGUMENT] = { "invalid argument being passed to `undef`; expected a bare word, constant, or symbol argument", PM_ERROR_DEFAULT }, + [PM_ERR_UNARY_RECEIVER_BANG] = { "expected a receiver for unary `!`", PM_ERROR_DEFAULT }, + [PM_ERR_UNARY_RECEIVER_MINUS] = { "expected a receiver for unary `-`", PM_ERROR_DEFAULT }, + [PM_ERR_UNARY_RECEIVER_PLUS] = { "expected a receiver for unary `+`", PM_ERROR_DEFAULT }, + [PM_ERR_UNARY_RECEIVER_TILDE] = { "expected a receiver for unary `~`", PM_ERROR_DEFAULT }, + [PM_ERR_UNTIL_TERM] = { "expected an `end` to close the `until` statement", PM_ERROR_DEFAULT }, + [PM_ERR_VOID_EXPRESSION] = { "unexpected void value expression", PM_ERROR_DEFAULT }, + [PM_ERR_WHILE_TERM] = { "expected an `end` to close the `while` statement", PM_ERROR_DEFAULT }, + [PM_ERR_WRITE_TARGET_IN_METHOD] = { "dynamic constant assignment", PM_ERROR_DEFAULT }, + [PM_ERR_WRITE_TARGET_READONLY] = { "immutable variable as a write target", PM_ERROR_DEFAULT }, + [PM_ERR_WRITE_TARGET_UNEXPECTED] = { "unexpected write target", PM_ERROR_DEFAULT }, + [PM_ERR_XSTRING_TERM] = { "expected a closing delimiter for the `%x` or backtick string", PM_ERROR_DEFAULT }, + // Warnings + [PM_WARN_AMBIGUOUS_FIRST_ARGUMENT_MINUS] = { "ambiguous first argument; put parentheses or a space even after `-` operator", PM_WARNING_VERBOSE_TRUE }, + [PM_WARN_AMBIGUOUS_FIRST_ARGUMENT_PLUS] = { "ambiguous first argument; put parentheses or a space even after `+` operator", PM_WARNING_VERBOSE_TRUE }, + [PM_WARN_AMBIGUOUS_PREFIX_STAR] = { "ambiguous `*` has been interpreted as an argument prefix", PM_WARNING_VERBOSE_TRUE }, + [PM_WARN_AMBIGUOUS_SLASH] = { "ambiguous `/`; wrap regexp in parentheses or add a space after `/` operator", PM_WARNING_VERBOSE_TRUE }, + [PM_WARN_END_IN_METHOD] = { "END in method; use at_exit", PM_WARNING_VERBOSE_NOT_NIL }, }; static const char* pm_diagnostic_message(pm_diagnostic_id_t diag_id) { assert(diag_id < PM_DIAGNOSTIC_ID_LEN); - const char *message = diagnostic_messages[diag_id]; + const char *message = diagnostic_messages[diag_id].message; assert(message); return message; } +static uint8_t +pm_diagnostic_level(pm_diagnostic_id_t diag_id) { + assert(diag_id < PM_DIAGNOSTIC_ID_LEN); + + return (uint8_t) diagnostic_messages[diag_id].level; +} + /** * Append an error to the given list of diagnostic. */ @@ -292,7 +317,8 @@ pm_diagnostic_list_append(pm_list_t *list, const uint8_t *start, const uint8_t * *diagnostic = (pm_diagnostic_t) { .location = { start, end }, .message = pm_diagnostic_message(diag_id), - .owned = false + .owned = false, + .level = pm_diagnostic_level(diag_id) }; pm_list_append(list, (pm_list_node_t *) diagnostic); @@ -335,7 +361,8 @@ pm_diagnostic_list_append_format(pm_list_t *list, const uint8_t *start, const ui *diagnostic = (pm_diagnostic_t) { .location = { start, end }, .message = message, - .owned = true + .owned = true, + .level = pm_diagnostic_level(diag_id) }; pm_list_append(list, (pm_list_node_t *) diagnostic); diff --git a/prism/diagnostic.h b/prism/diagnostic.h index fb4110236151d2..19395176ac4f00 100644 --- a/prism/diagnostic.h +++ b/prism/diagnostic.h @@ -14,6 +14,18 @@ #include #include +/** + * This enum represents the level of diagnostics generated during parsing. + */ +typedef enum { + /** The default level for errors. */ + PM_ERROR_DEFAULT = 0, + /** For warnings which should be emitted if $VERBOSE != nil. */ + PM_WARNING_VERBOSE_NOT_NIL = 1, + /** For warnings which should be emitted if $VERBOSE == true. */ + PM_WARNING_VERBOSE_TRUE = 2 +} pm_diagnostic_level_t; + /** * This struct represents a diagnostic generated during parsing. * @@ -35,6 +47,9 @@ typedef struct { * diagnostic is freed. */ bool owned; + + /** The level of the diagnostic, see pm_diagnostic_level_t for possible values. */ + uint8_t level; } pm_diagnostic_t; /** diff --git a/prism/extension.c b/prism/extension.c index 416e682f762a03..72be59bc6d83d4 100644 --- a/prism/extension.c +++ b/prism/extension.c @@ -368,6 +368,19 @@ parser_magic_comments(pm_parser_t *parser, VALUE source) { return magic_comments; } +static VALUE get_diagnostic_level_symbol(uint8_t level) { + switch (level) { + case 0: + return ID2SYM(rb_intern("error_default")); + case 1: + return ID2SYM(rb_intern("warning_verbose_not_nil")); + case 2: + return ID2SYM(rb_intern("warning_verbose_true")); + default: + rb_raise(rb_eRuntimeError, "Unknown level: %" PRIu8, level); + } +} + /** * Extract out the data location from the parser into a Location instance if one * exists. @@ -404,10 +417,11 @@ parser_errors(pm_parser_t *parser, rb_encoding *encoding, VALUE source) { VALUE error_argv[] = { rb_enc_str_new_cstr(error->message, encoding), - rb_class_new_instance(3, location_argv, rb_cPrismLocation) + rb_class_new_instance(3, location_argv, rb_cPrismLocation), + get_diagnostic_level_symbol(error->level) }; - rb_ary_push(errors, rb_class_new_instance(2, error_argv, rb_cPrismParseError)); + rb_ary_push(errors, rb_class_new_instance(3, error_argv, rb_cPrismParseError)); } return errors; @@ -430,10 +444,11 @@ parser_warnings(pm_parser_t *parser, rb_encoding *encoding, VALUE source) { VALUE warning_argv[] = { rb_enc_str_new_cstr(warning->message, encoding), - rb_class_new_instance(3, location_argv, rb_cPrismLocation) + rb_class_new_instance(3, location_argv, rb_cPrismLocation), + get_diagnostic_level_symbol(warning->level) }; - rb_ary_push(warnings, rb_class_new_instance(2, warning_argv, rb_cPrismParseWarning)); + rb_ary_push(warnings, rb_class_new_instance(3, warning_argv, rb_cPrismParseWarning)); } return warnings; diff --git a/prism/templates/lib/prism/serialize.rb.erb b/prism/templates/lib/prism/serialize.rb.erb index 0b5300c4c55df1..35b5b4ddb0b5a6 100644 --- a/prism/templates/lib/prism/serialize.rb.erb +++ b/prism/templates/lib/prism/serialize.rb.erb @@ -96,8 +96,8 @@ module Prism comments = load_comments magic_comments = load_varuint.times.map { MagicComment.new(load_location, load_location) } data_loc = load_optional_location - errors = load_varuint.times.map { ParseError.new(load_embedded_string, load_location) } - warnings = load_varuint.times.map { ParseWarning.new(load_embedded_string, load_location) } + errors = load_varuint.times.map { ParseError.new(load_embedded_string, load_location, load_diagnostic_level) } + warnings = load_varuint.times.map { ParseWarning.new(load_embedded_string, load_location, load_diagnostic_level) } [comments, magic_comments, data_loc, errors, warnings] end @@ -231,6 +231,20 @@ module Prism load_constant(index - 1) if index != 0 end + def load_diagnostic_level + level = io.getbyte + case level + when 0 + :error_default + when 1 + :warning_verbose_not_nil + when 2 + :warning_verbose_true + else + raise "Unknown level: #{level}" + end + end + if RUBY_ENGINE == 'ruby' def load_node type = io.getbyte diff --git a/prism/templates/src/serialize.c.erb b/prism/templates/src/serialize.c.erb index e9cdd1e82c2cbf..deda01f29caa61 100644 --- a/prism/templates/src/serialize.c.erb +++ b/prism/templates/src/serialize.c.erb @@ -190,6 +190,8 @@ pm_serialize_diagnostic(pm_parser_t *parser, pm_diagnostic_t *diagnostic, pm_buf // serialize location pm_serialize_location(parser, &diagnostic->location, buffer); + + pm_buffer_append_byte(buffer, diagnostic->level); } static void diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index 304d55274e98fc..b7215c755dfde1 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -1871,6 +1871,16 @@ def test_upcase_end_in_def ] end + def test_warnings_verbosity + warning = Prism.parse("def foo; END { }; end").warnings[0] + assert_equal "END in method; use at_exit", warning.message + assert_equal :warning_verbose_not_nil, warning.level + + warning = Prism.parse("foo /regexp/").warnings[0] + assert_equal "ambiguous `/`; wrap regexp in parentheses or add a space after `/` operator", warning.message + assert_equal :warning_verbose_true, warning.level + end + def test_statement_operators source = <<~RUBY alias x y + 1 From cb9a47f2acd6e373ef868b890a9d07da6f565dd4 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 26 Jan 2024 16:19:21 -0500 Subject: [PATCH 569/640] [PRISM] Fix branchif ADD_INSN1 --- prism_compile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prism_compile.c b/prism_compile.c index 31220996fdf328..ecbe8810ba8fd0 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -6094,7 +6094,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, checkmatch_flags |= VM_CHECKMATCH_ARRAY; } ADD_INSN1(ret, &dummy_line_node, checkmatch, INT2FIX(checkmatch_flags)); - ADD_INSN1(ret, &dummy_line_node, branchif, exception_match_label); + ADD_INSNL(ret, &dummy_line_node, branchif, exception_match_label); } } else { ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0); From 70cb0a4dec2e445730357eea2aa347747df302af Mon Sep 17 00:00:00 2001 From: yui-knk Date: Sat, 27 Jan 2024 09:40:51 +0900 Subject: [PATCH 570/640] Lrama v0.6.2 --- tool/lrama/NEWS.md | 9 + tool/lrama/lib/lrama/command.rb | 12 +- tool/lrama/lib/lrama/context.rb | 4 +- .../lib/lrama/counterexamples/example.rb | 4 +- tool/lrama/lib/lrama/grammar.rb | 13 +- tool/lrama/lib/lrama/grammar/code.rb | 2 +- .../grammar/parameterizing_rule/resolver.rb | 26 +- .../grammar/parameterizing_rules/builder.rb | 60 -- .../parameterizing_rules/builder/base.rb | 36 - .../parameterizing_rules/builder/list.rb | 28 - .../builder/nonempty_list.rb | 28 - .../parameterizing_rules/builder/option.rb | 28 - .../builder/separated_list.rb | 39 - .../builder/separated_nonempty_list.rb | 34 - tool/lrama/lib/lrama/grammar/rule.rb | 4 +- tool/lrama/lib/lrama/grammar/rule_builder.rb | 67 +- tool/lrama/lib/lrama/grammar/stdlib.y | 80 ++ tool/lrama/lib/lrama/lexer.rb | 1 + tool/lrama/lib/lrama/parser.rb | 925 +++++++++--------- tool/lrama/lib/lrama/states/item.rb | 30 +- tool/lrama/lib/lrama/states_reporter.rb | 18 +- tool/lrama/lib/lrama/version.rb | 2 +- 22 files changed, 666 insertions(+), 784 deletions(-) delete mode 100644 tool/lrama/lib/lrama/grammar/parameterizing_rules/builder.rb delete mode 100644 tool/lrama/lib/lrama/grammar/parameterizing_rules/builder/base.rb delete mode 100644 tool/lrama/lib/lrama/grammar/parameterizing_rules/builder/list.rb delete mode 100644 tool/lrama/lib/lrama/grammar/parameterizing_rules/builder/nonempty_list.rb delete mode 100644 tool/lrama/lib/lrama/grammar/parameterizing_rules/builder/option.rb delete mode 100644 tool/lrama/lib/lrama/grammar/parameterizing_rules/builder/separated_list.rb delete mode 100644 tool/lrama/lib/lrama/grammar/parameterizing_rules/builder/separated_nonempty_list.rb create mode 100644 tool/lrama/lib/lrama/grammar/stdlib.y diff --git a/tool/lrama/NEWS.md b/tool/lrama/NEWS.md index c4a0f28f5b4eea..122443261f4857 100644 --- a/tool/lrama/NEWS.md +++ b/tool/lrama/NEWS.md @@ -1,5 +1,14 @@ # NEWS for Lrama +## Lrama 0.6.2 (2024-01-27) + +### %no-stdlib directive + +If `%no-stdlib` directive is set, Lrama doesn't load Lrama standard library for +parameterizing rules, stdlib.y. + +https://github.com/ruby/lrama/pull/344 + ## Lrama 0.6.1 (2024-01-13) ### Nested parameterizing rules diff --git a/tool/lrama/lib/lrama/command.rb b/tool/lrama/lib/lrama/command.rb index a39eed139baea0..94e86c6c945ab1 100644 --- a/tool/lrama/lib/lrama/command.rb +++ b/tool/lrama/lib/lrama/command.rb @@ -1,5 +1,8 @@ module Lrama class Command + LRAMA_LIB = File.realpath(File.join(File.dirname(__FILE__))) + STDLIB_FILE_PATH = File.join(LRAMA_LIB, 'grammar', 'stdlib.y') + def run(argv) begin options = OptionParser.new.parse(argv) @@ -14,9 +17,14 @@ def run(argv) warning = Lrama::Warning.new text = options.y.read options.y.close if options.y != STDIN - parser = Lrama::Parser.new(text, options.grammar_file, options.debug) begin - grammar = parser.parse + grammar = Lrama::Parser.new(text, options.grammar_file, options.debug).parse + unless grammar.no_stdlib + stdlib_grammar = Lrama::Parser.new(File.read(STDLIB_FILE_PATH), STDLIB_FILE_PATH, options.debug).parse + grammar.insert_before_parameterizing_rules(stdlib_grammar.parameterizing_rules) + end + grammar.prepare + grammar.validate! rescue => e raise e if options.debug message = e.message diff --git a/tool/lrama/lib/lrama/context.rb b/tool/lrama/lib/lrama/context.rb index 245c91a199d544..d796de12579249 100644 --- a/tool/lrama/lib/lrama/context.rb +++ b/tool/lrama/lib/lrama/context.rb @@ -41,7 +41,7 @@ def yysymbol_kind_t def yyfinal @states.states.find do |state| state.items.find do |item| - item.rule.lhs.accept_symbol? && item.end_of_rule? + item.lhs.accept_symbol? && item.end_of_rule? end end.id end @@ -221,7 +221,7 @@ def compute_yydefact if state.reduces.map(&:selected_look_ahead).any? {|la| !la.empty? } # Iterate reduces with reverse order so that first rule is used. - state.reduces.reverse.each do |reduce| + state.reduces.reverse_each do |reduce| reduce.look_ahead.each do |term| actions[term.number] = rule_id_to_action_number(reduce.rule.id) end diff --git a/tool/lrama/lib/lrama/counterexamples/example.rb b/tool/lrama/lib/lrama/counterexamples/example.rb index 8f02d71fa45e0c..62244a77e0fa01 100644 --- a/tool/lrama/lib/lrama/counterexamples/example.rb +++ b/tool/lrama/lib/lrama/counterexamples/example.rb @@ -40,7 +40,7 @@ def _derivations(paths) current = :production lookahead_sym = paths.last.to.item.end_of_rule? ? @conflict_symbol : nil - paths.reverse.each do |path| + paths.reverse_each do |path| item = path.to.item case current @@ -97,7 +97,7 @@ def find_derivation_for_symbol(state_item, sym) if next_sym == sym derivation = nil - sis.reverse.each do |si| + sis.reverse_each do |si| derivation = Derivation.new(si.item, derivation) end diff --git a/tool/lrama/lib/lrama/grammar.rb b/tool/lrama/lib/lrama/grammar.rb index 9c500b381d47d7..9ce6b87836d9b1 100644 --- a/tool/lrama/lib/lrama/grammar.rb +++ b/tool/lrama/lib/lrama/grammar.rb @@ -24,7 +24,7 @@ class Grammar :lex_param, :parse_param, :initial_action, :symbols, :types, :rules, :rule_builders, - :sym_to_rules + :sym_to_rules, :no_stdlib def initialize(rule_counter) @rule_counter = rule_counter @@ -45,6 +45,7 @@ def initialize(rule_counter) @undef_symbol = nil @accept_symbol = nil @aux = Auxiliary.new + @no_stdlib = false append_special_symbols end @@ -136,6 +137,14 @@ def add_parameterizing_rule(rule) @parameterizing_rule_resolver.add_parameterizing_rule(rule) end + def parameterizing_rules + @parameterizing_rule_resolver.rules + end + + def insert_before_parameterizing_rules(rules) + @parameterizing_rule_resolver.rules = rules + @parameterizing_rule_resolver.rules + end + def prologue_first_lineno=(prologue_first_lineno) @aux.prologue_first_lineno = prologue_first_lineno end @@ -234,7 +243,7 @@ def nterms def compute_nullable @rules.each do |rule| case - when rule.rhs.empty? + when rule.empty_rule? rule.nullable = true when rule.rhs.any?(&:term) rule.nullable = false diff --git a/tool/lrama/lib/lrama/grammar/code.rb b/tool/lrama/lib/lrama/grammar/code.rb index d0bef75ef12ee0..e108d91c7f2af4 100644 --- a/tool/lrama/lib/lrama/grammar/code.rb +++ b/tool/lrama/lib/lrama/grammar/code.rb @@ -28,7 +28,7 @@ def ==(other) def translated_code t_code = s_value.dup - references.reverse.each do |ref| + references.reverse_each do |ref| first_column = ref.first_column last_column = ref.last_column diff --git a/tool/lrama/lib/lrama/grammar/parameterizing_rule/resolver.rb b/tool/lrama/lib/lrama/grammar/parameterizing_rule/resolver.rb index f5de9d0bf39825..1923e7819cdec7 100644 --- a/tool/lrama/lib/lrama/grammar/parameterizing_rule/resolver.rb +++ b/tool/lrama/lib/lrama/grammar/parameterizing_rule/resolver.rb @@ -2,7 +2,7 @@ module Lrama class Grammar class ParameterizingRule class Resolver - attr_accessor :created_lhs_list + attr_accessor :rules, :created_lhs_list def initialize @rules = [] @@ -13,24 +13,32 @@ def add_parameterizing_rule(rule) @rules << rule end - def defined?(token) - !select_rules(token).empty? - end - def find(token) select_rules(token).last end def created_lhs(lhs_s_value) - @created_lhs_list.select { |created_lhs| created_lhs.s_value == lhs_s_value }.last + @created_lhs_list.reverse.find { |created_lhs| created_lhs.s_value == lhs_s_value } end private def select_rules(token) - @rules.select do |rule| - rule.name == token.rule_name && - rule.required_parameters_count == token.args_count + rules = select_rules_by_name(token.rule_name) + rules = rules.select { |rule| rule.required_parameters_count == token.args_count } + if rules.empty? + raise "Invalid number of arguments. `#{token.rule_name}`" + else + rules + end + end + + def select_rules_by_name(rule_name) + rules = @rules.select { |rule| rule.name == rule_name } + if rules.empty? + raise "Parameterizing rule does not exist. `#{rule_name}`" + else + rules end end end diff --git a/tool/lrama/lib/lrama/grammar/parameterizing_rules/builder.rb b/tool/lrama/lib/lrama/grammar/parameterizing_rules/builder.rb deleted file mode 100644 index 20950b9b368e0b..00000000000000 --- a/tool/lrama/lib/lrama/grammar/parameterizing_rules/builder.rb +++ /dev/null @@ -1,60 +0,0 @@ -require 'lrama/grammar/parameterizing_rules/builder/base' -require 'lrama/grammar/parameterizing_rules/builder/list' -require 'lrama/grammar/parameterizing_rules/builder/nonempty_list' -require 'lrama/grammar/parameterizing_rules/builder/option' -require 'lrama/grammar/parameterizing_rules/builder/separated_nonempty_list' -require 'lrama/grammar/parameterizing_rules/builder/separated_list' - -module Lrama - class Grammar - class ParameterizingRules - # Builder for parameterizing rules - class Builder - RULES = { - option: Lrama::Grammar::ParameterizingRules::Builder::Option, - "?": Lrama::Grammar::ParameterizingRules::Builder::Option, - nonempty_list: Lrama::Grammar::ParameterizingRules::Builder::NonemptyList, - "+": Lrama::Grammar::ParameterizingRules::Builder::NonemptyList, - list: Lrama::Grammar::ParameterizingRules::Builder::List, - "*": Lrama::Grammar::ParameterizingRules::Builder::List, - separated_nonempty_list: Lrama::Grammar::ParameterizingRules::Builder::SeparatedNonemptyList, - separated_list: Lrama::Grammar::ParameterizingRules::Builder::SeparatedList, - } - - def initialize(token, rule_counter, lhs_tag, user_code, precedence_sym, line) - @token = token - @key = token.s_value.to_sym - @rule_counter = rule_counter - @lhs_tag = lhs_tag - @user_code = user_code - @precedence_sym = precedence_sym - @line = line - @builder = nil - end - - def build - create_builder - @builder.build - end - - def build_token - create_builder - @builder.build_token - end - - private - - def create_builder - unless @builder - validate_key! - @builder = RULES[@key].new(@token, @rule_counter, @lhs_tag, @user_code, @precedence_sym, @line) - end - end - - def validate_key! - raise "Parameterizing rule does not exist. `#{@key}`" unless RULES.key?(@key) - end - end - end - end -end diff --git a/tool/lrama/lib/lrama/grammar/parameterizing_rules/builder/base.rb b/tool/lrama/lib/lrama/grammar/parameterizing_rules/builder/base.rb deleted file mode 100644 index 5787714f0c8627..00000000000000 --- a/tool/lrama/lib/lrama/grammar/parameterizing_rules/builder/base.rb +++ /dev/null @@ -1,36 +0,0 @@ -module Lrama - class Grammar - class ParameterizingRules - class Builder - # Base class for parameterizing rules builder - class Base - attr_reader :build_token - - def initialize(token, rule_counter, lhs_tag, user_code, precedence_sym, line) - @args = token.args - @token = @args.first - @rule_counter = rule_counter - @lhs_tag = lhs_tag - @user_code = user_code - @precedence_sym = precedence_sym - @line = line - @expected_argument_num = 1 - @build_token = nil - end - - def build - raise NotImplementedError - end - - private - - def validate_argument_number! - unless @args.count == @expected_argument_num - raise "Invalid number of arguments. expect: #{@expected_argument_num} actual: #{@args.count}" - end - end - end - end - end - end -end diff --git a/tool/lrama/lib/lrama/grammar/parameterizing_rules/builder/list.rb b/tool/lrama/lib/lrama/grammar/parameterizing_rules/builder/list.rb deleted file mode 100644 index 248e1e7ad441ea..00000000000000 --- a/tool/lrama/lib/lrama/grammar/parameterizing_rules/builder/list.rb +++ /dev/null @@ -1,28 +0,0 @@ -module Lrama - class Grammar - class ParameterizingRules - class Builder - # Builder for list of general parameterizing rules - class List < Base - - # program: list(number) - # - # => - # - # program: list_number - # list_number: ε - # list_number: list_number number - def build - validate_argument_number! - - rules = [] - @build_token = Lrama::Lexer::Token::Ident.new(s_value: "list_#{@token.s_value}") - rules << Rule.new(id: @rule_counter.increment, _lhs: @build_token, _rhs: [], lhs_tag: @lhs_tag, token_code: @user_code, precedence_sym: @precedence_sym, lineno: @line) - rules << Rule.new(id: @rule_counter.increment, _lhs: @build_token, _rhs: [@build_token, @token], lhs_tag: @lhs_tag, token_code: @user_code, precedence_sym: @precedence_sym, lineno: @line) - rules - end - end - end - end - end -end diff --git a/tool/lrama/lib/lrama/grammar/parameterizing_rules/builder/nonempty_list.rb b/tool/lrama/lib/lrama/grammar/parameterizing_rules/builder/nonempty_list.rb deleted file mode 100644 index bcec1d823a2b4c..00000000000000 --- a/tool/lrama/lib/lrama/grammar/parameterizing_rules/builder/nonempty_list.rb +++ /dev/null @@ -1,28 +0,0 @@ -module Lrama - class Grammar - class ParameterizingRules - class Builder - # Builder for nonempty list of general parameterizing rules - class NonemptyList < Base - - # program: nonempty_list(number) - # - # => - # - # program: nonempty_list_number - # nonempty_list_number: number - # nonempty_list_number: nonempty_list_number number - def build - validate_argument_number! - - rules = [] - @build_token = Lrama::Lexer::Token::Ident.new(s_value: "nonempty_list_#{@token.s_value}") - rules << Rule.new(id: @rule_counter.increment, _lhs: @build_token, _rhs: [@token], lhs_tag: @lhs_tag, token_code: @user_code, precedence_sym: @precedence_sym, lineno: @line) - rules << Rule.new(id: @rule_counter.increment, _lhs: @build_token, _rhs: [@build_token, @token], lhs_tag: @lhs_tag, token_code: @user_code, precedence_sym: @precedence_sym, lineno: @line) - rules - end - end - end - end - end -end diff --git a/tool/lrama/lib/lrama/grammar/parameterizing_rules/builder/option.rb b/tool/lrama/lib/lrama/grammar/parameterizing_rules/builder/option.rb deleted file mode 100644 index 8be045ec30a355..00000000000000 --- a/tool/lrama/lib/lrama/grammar/parameterizing_rules/builder/option.rb +++ /dev/null @@ -1,28 +0,0 @@ -module Lrama - class Grammar - class ParameterizingRules - class Builder - # Builder for option of general parameterizing rules - class Option < Base - - # program: option(number) - # - # => - # - # program: option_number - # option_number: ε - # option_number: number - def build - validate_argument_number! - - rules = [] - @build_token = Lrama::Lexer::Token::Ident.new(s_value: "option_#{@token.s_value}") - rules << Rule.new(id: @rule_counter.increment, _lhs: @build_token, _rhs: [], lhs_tag: @lhs_tag, token_code: @user_code, precedence_sym: @precedence_sym, lineno: @line) - rules << Rule.new(id: @rule_counter.increment, _lhs: @build_token, _rhs: [@token], lhs_tag: @lhs_tag, token_code: @user_code, precedence_sym: @precedence_sym, lineno: @line) - rules - end - end - end - end - end -end diff --git a/tool/lrama/lib/lrama/grammar/parameterizing_rules/builder/separated_list.rb b/tool/lrama/lib/lrama/grammar/parameterizing_rules/builder/separated_list.rb deleted file mode 100644 index f9677cadbc50b7..00000000000000 --- a/tool/lrama/lib/lrama/grammar/parameterizing_rules/builder/separated_list.rb +++ /dev/null @@ -1,39 +0,0 @@ -module Lrama - class Grammar - class ParameterizingRules - class Builder - # Builder for separated list of general parameterizing rules - class SeparatedList < Base - def initialize(token, rule_counter, lhs_tag, user_code, precedence_sym, line) - super - @separator = @args[0] - @token = @args[1] - @expected_argument_num = 2 - end - - # program: separated_list(',', number) - # - # => - # - # program: separated_list_number - # separated_list_number: ε - # separated_list_number: separated_nonempty_list_number - # separated_nonempty_list_number: number - # separated_nonempty_list_number: separated_nonempty_list_number ',' number - def build - validate_argument_number! - - rules = [] - @build_token = Lrama::Lexer::Token::Ident.new(s_value: "separated_list_#{@token.s_value}") - separated_nonempty_list_token = Lrama::Lexer::Token::Ident.new(s_value: "separated_nonempty_list_#{@token.s_value}") - rules << Rule.new(id: @rule_counter.increment, _lhs: @build_token, _rhs: [], lhs_tag: @lhs_tag, token_code: @user_code, precedence_sym: @precedence_sym, lineno: @line) - rules << Rule.new(id: @rule_counter.increment, _lhs: @build_token, _rhs: [separated_nonempty_list_token], lhs_tag: @lhs_tag, token_code: @user_code, precedence_sym: @precedence_sym, lineno: @line) - rules << Rule.new(id: @rule_counter.increment, _lhs: separated_nonempty_list_token, _rhs: [@token], lhs_tag: @lhs_tag, token_code: @user_code, precedence_sym: @precedence_sym, lineno: @line) - rules << Rule.new(id: @rule_counter.increment, _lhs: separated_nonempty_list_token, _rhs: [separated_nonempty_list_token, @separator, @token], lhs_tag: @lhs_tag, token_code: @user_code, precedence_sym: @precedence_sym, lineno: @line) - rules - end - end - end - end - end -end diff --git a/tool/lrama/lib/lrama/grammar/parameterizing_rules/builder/separated_nonempty_list.rb b/tool/lrama/lib/lrama/grammar/parameterizing_rules/builder/separated_nonempty_list.rb deleted file mode 100644 index ba6ecf24cc150c..00000000000000 --- a/tool/lrama/lib/lrama/grammar/parameterizing_rules/builder/separated_nonempty_list.rb +++ /dev/null @@ -1,34 +0,0 @@ -module Lrama - class Grammar - class ParameterizingRules - class Builder - # Builder for separated nonempty list of general parameterizing rules - class SeparatedNonemptyList < Base - def initialize(token, rule_counter, lhs_tag, user_code, precedence_sym, line) - super - @separator = @args[0] - @token = @args[1] - @expected_argument_num = 2 - end - - # program: separated_nonempty_list(',', number) - # - # => - # - # program: separated_nonempty_list_number - # separated_nonempty_list_number: number - # separated_nonempty_list_number: separated_nonempty_list_number ',' number - def build - validate_argument_number! - - rules = [] - @build_token = Lrama::Lexer::Token::Ident.new(s_value: "separated_nonempty_list_#{@token.s_value}") - rules << Rule.new(id: @rule_counter.increment, _lhs: @build_token, _rhs: [@token], lhs_tag: @lhs_tag, token_code: @user_code, precedence_sym: @precedence_sym, lineno: @line) - rules << Rule.new(id: @rule_counter.increment, _lhs: @build_token, _rhs: [@build_token, @separator, @token], lhs_tag: @lhs_tag, token_code: @user_code, precedence_sym: @precedence_sym, lineno: @line) - rules - end - end - end - end - end -end diff --git a/tool/lrama/lib/lrama/grammar/rule.rb b/tool/lrama/lib/lrama/grammar/rule.rb index 2876472030dfd8..9281e0574f9d17 100644 --- a/tool/lrama/lib/lrama/grammar/rule.rb +++ b/tool/lrama/lib/lrama/grammar/rule.rb @@ -19,7 +19,7 @@ def ==(other) # TODO: Change this to display_name def to_s l = lhs.id.s_value - r = rhs.empty? ? "ε" : rhs.map {|r| r.id.s_value }.join(", ") + r = empty_rule? ? "ε" : rhs.map {|r| r.id.s_value }.join(", ") "#{l} -> #{r}" end @@ -27,7 +27,7 @@ def to_s # Used by #user_actions def as_comment l = lhs.id.s_value - r = rhs.empty? ? "%empty" : rhs.map(&:display_name).join(" ") + r = empty_rule? ? "%empty" : rhs.map(&:display_name).join(" ") "#{l}: #{r}" end diff --git a/tool/lrama/lib/lrama/grammar/rule_builder.rb b/tool/lrama/lib/lrama/grammar/rule_builder.rb index 757554f46d041c..954bb0d5b5c793 100644 --- a/tool/lrama/lib/lrama/grammar/rule_builder.rb +++ b/tool/lrama/lib/lrama/grammar/rule_builder.rb @@ -1,5 +1,3 @@ -require 'lrama/grammar/parameterizing_rules/builder' - module Lrama class Grammar class RuleBuilder @@ -59,7 +57,7 @@ def setup_rules(parameterizing_rule_resolver) end def rules - @parameterizing_rules + @old_parameterizing_rules + @midrule_action_rules + @rules + @parameterizing_rules + @midrule_action_rules + @rules end private @@ -97,7 +95,6 @@ def process_rhs(parameterizing_rule_resolver) return if @replaced_rhs @replaced_rhs = [] - @old_parameterizing_rules = [] rhs.each_with_index do |token, i| case token @@ -106,35 +103,28 @@ def process_rhs(parameterizing_rule_resolver) when Lrama::Lexer::Token::Ident @replaced_rhs << token when Lrama::Lexer::Token::InstantiateRule - if parameterizing_rule_resolver.defined?(token) - parameterizing_rule = parameterizing_rule_resolver.find(token) - raise "Unexpected token. #{token}" unless parameterizing_rule - - bindings = Binding.new(parameterizing_rule, token.args) - lhs_s_value = lhs_s_value(token, bindings) - if (created_lhs = parameterizing_rule_resolver.created_lhs(lhs_s_value)) - @replaced_rhs << created_lhs - else - lhs_token = Lrama::Lexer::Token::Ident.new(s_value: lhs_s_value, location: token.location) - @replaced_rhs << lhs_token - parameterizing_rule_resolver.created_lhs_list << lhs_token - parameterizing_rule.rhs_list.each do |r| - rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, i, lhs_tag: token.lhs_tag, skip_preprocess_references: true) - rule_builder.lhs = lhs_token - r.symbols.each { |sym| rule_builder.add_rhs(bindings.resolve_symbol(sym)) } - rule_builder.line = line - rule_builder.user_code = r.user_code - rule_builder.precedence_sym = r.precedence_sym - rule_builder.complete_input - rule_builder.setup_rules(parameterizing_rule_resolver) - @rule_builders_for_parameterizing_rules << rule_builder - end - end + parameterizing_rule = parameterizing_rule_resolver.find(token) + raise "Unexpected token. #{token}" unless parameterizing_rule + + bindings = Binding.new(parameterizing_rule, token.args) + lhs_s_value = lhs_s_value(token, bindings) + if (created_lhs = parameterizing_rule_resolver.created_lhs(lhs_s_value)) + @replaced_rhs << created_lhs else - # TODO: Delete when the standard library will defined as a grammar file. - parameterizing_rule = ParameterizingRules::Builder.new(token, @rule_counter, token.lhs_tag, user_code, precedence_sym, line) - @old_parameterizing_rules = @old_parameterizing_rules + parameterizing_rule.build - @replaced_rhs << parameterizing_rule.build_token + lhs_token = Lrama::Lexer::Token::Ident.new(s_value: lhs_s_value, location: token.location) + @replaced_rhs << lhs_token + parameterizing_rule_resolver.created_lhs_list << lhs_token + parameterizing_rule.rhs_list.each do |r| + rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, i, lhs_tag: token.lhs_tag, skip_preprocess_references: true) + rule_builder.lhs = lhs_token + r.symbols.each { |sym| rule_builder.add_rhs(bindings.resolve_symbol(sym)) } + rule_builder.line = line + rule_builder.user_code = r.user_code + rule_builder.precedence_sym = r.precedence_sym + rule_builder.complete_input + rule_builder.setup_rules(parameterizing_rule_resolver) + @rule_builders_for_parameterizing_rules << rule_builder + end end when Lrama::Lexer::Token::UserCode prefix = token.referred ? "@" : "$@" @@ -173,11 +163,12 @@ def numberize_references token.references.each do |ref| ref_name = ref.name - if ref_name && ref_name != '$' - if lhs.referred_by?(ref_name) + + if ref_name + if ref_name == '$' ref.name = '$' else - candidates = rhs.each_with_index.select {|token, i| token.referred_by?(ref_name) } + candidates = ([lhs] + rhs).each_with_index.select {|token, _i| token.referred_by?(ref_name) } if candidates.size >= 2 token.invalid_ref(ref, "Referring symbol `#{ref_name}` is duplicated.") @@ -187,7 +178,11 @@ def numberize_references token.invalid_ref(ref, "Referring symbol `#{ref_name}` is not found.") end - ref.index = referring_symbol[1] + 1 + if referring_symbol[1] == 0 # Refers to LHS + ref.name = '$' + else + ref.index = referring_symbol[1] + end end end diff --git a/tool/lrama/lib/lrama/grammar/stdlib.y b/tool/lrama/lib/lrama/grammar/stdlib.y new file mode 100644 index 00000000000000..f2dfba07336daf --- /dev/null +++ b/tool/lrama/lib/lrama/grammar/stdlib.y @@ -0,0 +1,80 @@ +/********************************************************************** + + stdlib.y + + This is lrama's standard library. It provides a number of + parameterizing rule definitions, such as options and lists, + that should be useful in a number of situations. + +**********************************************************************/ + +/* + * program: option(number) + * + * => + * + * program: option_number + * option_number: %empty + * option_number: number + */ +%rule option(X): /* empty */ + | X + ; + +/* + * program: list(number) + * + * => + * + * program: list_number + * list_number: %empty + * list_number: list_number number + */ +%rule list(X): /* empty */ + | list(X) X + ; + +/* + * program: nonempty_list(number) + * + * => + * + * program: nonempty_list_number + * nonempty_list_number: number + * nonempty_list_number: nonempty_list_number number + */ +%rule nonempty_list(X): X + | nonempty_list(X) X + ; + +/* + * program: separated_nonempty_list(comma, number) + * + * => + * + * program: separated_nonempty_list_comma_number + * separated_nonempty_list_comma_number: number + * separated_nonempty_list_comma_number: separated_nonempty_list_comma_number comma number + */ +%rule separated_nonempty_list(separator, X): X + | separated_nonempty_list(separator, X) separator X + ; + +/* + * program: separated_list(comma, number) + * + * => + * + * program: separated_list_comma_number + * separated_list_comma_number: option_separated_nonempty_list_comma_number + * option_separated_nonempty_list_comma_number: %empty + * option_separated_nonempty_list_comma_number: separated_nonempty_list_comma_number + * separated_nonempty_list_comma_number: number + * separated_nonempty_list_comma_number: comma separated_nonempty_list_comma_number number + */ +%rule separated_list(separator, X): option(separated_nonempty_list(separator, X)) + ; + +%% + +%union{}; diff --git a/tool/lrama/lib/lrama/lexer.rb b/tool/lrama/lib/lrama/lexer.rb index 746d50cee5c221..35997f2f22bf4d 100644 --- a/tool/lrama/lib/lrama/lexer.rb +++ b/tool/lrama/lib/lrama/lexer.rb @@ -29,6 +29,7 @@ class Lexer %empty %code %rule + %no-stdlib ) def initialize(grammar_file) diff --git a/tool/lrama/lib/lrama/parser.rb b/tool/lrama/lib/lrama/parser.rb index 9434b18cc5519b..e5f2384e796b9a 100644 --- a/tool/lrama/lib/lrama/parser.rb +++ b/tool/lrama/lib/lrama/parser.rb @@ -658,7 +658,7 @@ def token_to_str(t) module Lrama class Parser < Racc::Parser -module_eval(<<'...end parser.y/module_eval...', 'parser.y', 500) +module_eval(<<'...end parser.y/module_eval...', 'parser.y', 501) include Lrama::Report::Duration @@ -676,8 +676,6 @@ def parse @precedence_number = 0 reset_precs do_parse - @grammar.prepare - @grammar.validate! @grammar end end @@ -734,138 +732,138 @@ def raise_parse_error(error_message, location) ##### State transition tables begin ### racc_action_table = [ - 85, 44, 86, 145, 144, 67, 44, 44, 145, 188, - 67, 67, 44, 6, 188, 7, 67, 147, 199, 44, - 143, 43, 147, 189, 58, 163, 164, 165, 189, 3, - 44, 40, 43, 8, 67, 63, 34, 44, 148, 43, - 41, 87, 40, 148, 190, 47, 44, 80, 43, 190, - 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 47, 21, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 9, 44, 47, 43, 13, 14, 15, 16, 17, - 18, 50, 51, 19, 20, 21, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 44, 44, 43, 43, - 52, 70, 70, 44, 44, 43, 43, 53, 70, 70, - 44, 44, 43, 43, 67, 173, 44, 44, 43, 43, - 67, 173, 44, 44, 43, 43, 67, 173, 44, 44, - 43, 43, 67, 173, 44, 44, 43, 43, 67, 173, - 44, 44, 43, 43, 67, 173, 44, 44, 43, 43, - 67, 67, 44, 44, 43, 43, 67, 67, 44, 44, - 43, 43, 67, 67, 44, 44, 179, 43, 67, 67, - 44, 44, 179, 43, 67, 67, 44, 44, 179, 43, - 67, 163, 164, 165, 83, 44, 141, 43, 142, 192, - 54, 193, 163, 164, 165, 208, 210, 193, 193, 55, - 76, 77, 81, 83, 88, 88, 88, 90, 96, 100, - 101, 104, 104, 104, 104, 107, 110, 111, 113, 115, - 116, 117, 118, 119, 122, 126, 127, 128, 131, 132, - 133, 135, 150, 152, 153, 154, 155, 156, 157, 158, - 131, 160, 168, 169, 178, 183, 184, 186, 191, 178, - 83, 183, 205, 207, 83, 212, 83 ] + 86, 45, 87, 146, 145, 68, 45, 45, 146, 189, + 68, 68, 45, 6, 189, 7, 68, 148, 200, 45, + 144, 44, 148, 190, 59, 164, 165, 166, 190, 3, + 45, 41, 44, 8, 68, 64, 35, 42, 45, 149, + 44, 41, 88, 71, 149, 191, 81, 45, 48, 44, + 191, 22, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 22, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 9, 45, 48, 44, 13, 14, 15, 16, 17, + 18, 48, 51, 19, 20, 21, 22, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 45, 45, 44, + 44, 52, 71, 71, 45, 45, 44, 44, 45, 71, + 44, 53, 68, 174, 45, 45, 44, 44, 68, 174, + 45, 45, 44, 44, 68, 174, 45, 45, 44, 44, + 68, 174, 45, 45, 44, 44, 68, 174, 45, 45, + 44, 44, 68, 174, 45, 45, 44, 44, 68, 68, + 45, 45, 44, 44, 68, 68, 45, 45, 44, 44, + 68, 68, 45, 45, 180, 44, 68, 68, 45, 45, + 180, 44, 68, 68, 45, 45, 180, 44, 68, 164, + 165, 166, 84, 45, 45, 44, 44, 142, 193, 143, + 194, 164, 165, 166, 209, 211, 194, 194, 54, 55, + 56, 77, 78, 82, 84, 89, 89, 89, 91, 97, + 101, 102, 105, 105, 105, 105, 108, 111, 112, 114, + 116, 117, 118, 119, 120, 123, 127, 128, 129, 132, + 133, 134, 136, 151, 153, 154, 155, 156, 157, 158, + 159, 132, 161, 169, 170, 179, 184, 185, 187, 192, + 179, 84, 184, 206, 208, 84, 213, 84 ] racc_action_check = [ - 42, 130, 42, 130, 129, 130, 159, 177, 159, 177, - 159, 177, 196, 2, 196, 2, 196, 130, 188, 26, - 129, 26, 159, 177, 26, 188, 188, 188, 196, 1, - 27, 9, 27, 3, 27, 27, 7, 14, 130, 14, - 13, 42, 35, 159, 177, 15, 57, 35, 57, 196, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 16, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 4, 58, 17, 58, 4, 4, 4, 4, 4, - 4, 18, 19, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 28, 29, 28, 29, - 21, 28, 29, 30, 31, 30, 31, 23, 30, 31, - 154, 69, 154, 69, 154, 154, 155, 70, 155, 70, - 155, 155, 156, 96, 156, 96, 156, 156, 170, 98, - 170, 98, 170, 170, 174, 104, 174, 104, 174, 174, - 175, 106, 175, 106, 175, 175, 62, 63, 62, 63, - 62, 63, 101, 103, 101, 103, 101, 103, 123, 148, - 123, 148, 123, 148, 160, 190, 160, 190, 160, 190, - 191, 193, 191, 193, 191, 193, 199, 120, 199, 120, - 199, 146, 146, 146, 146, 124, 125, 124, 125, 180, - 24, 180, 181, 181, 181, 202, 206, 202, 206, 25, - 32, 33, 38, 39, 46, 48, 49, 50, 56, 60, - 61, 68, 73, 74, 75, 76, 82, 83, 89, 91, - 92, 93, 94, 95, 99, 107, 108, 109, 110, 111, - 112, 114, 134, 136, 137, 138, 139, 140, 141, 142, - 143, 145, 149, 151, 157, 162, 166, 176, 179, 186, - 187, 192, 195, 200, 205, 211, 212 ] + 43, 131, 43, 131, 130, 131, 160, 178, 160, 178, + 160, 178, 197, 2, 197, 2, 197, 131, 189, 27, + 130, 27, 160, 178, 27, 189, 189, 189, 197, 1, + 28, 9, 28, 3, 28, 28, 7, 13, 29, 131, + 29, 36, 43, 29, 160, 178, 36, 14, 15, 14, + 197, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 4, 58, 16, 58, 4, 4, 4, 4, 4, + 4, 17, 18, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 30, 31, 30, + 31, 19, 30, 31, 32, 59, 32, 59, 155, 32, + 155, 22, 155, 155, 156, 70, 156, 70, 156, 156, + 157, 71, 157, 71, 157, 157, 171, 97, 171, 97, + 171, 171, 175, 99, 175, 99, 175, 175, 176, 105, + 176, 105, 176, 176, 63, 64, 63, 64, 63, 64, + 102, 104, 102, 104, 102, 104, 124, 149, 124, 149, + 124, 149, 161, 191, 161, 191, 161, 191, 192, 194, + 192, 194, 192, 194, 200, 107, 200, 107, 200, 147, + 147, 147, 147, 121, 125, 121, 125, 126, 181, 126, + 181, 182, 182, 182, 203, 207, 203, 207, 24, 25, + 26, 33, 34, 39, 40, 47, 49, 50, 51, 57, + 61, 62, 69, 74, 75, 76, 77, 83, 84, 90, + 92, 93, 94, 95, 96, 100, 108, 109, 110, 111, + 112, 113, 115, 135, 137, 138, 139, 140, 141, 142, + 143, 144, 146, 150, 152, 158, 163, 167, 177, 180, + 187, 188, 193, 196, 201, 206, 212, 213 ] racc_action_pointer = [ nil, 29, 3, 33, 62, nil, nil, 29, nil, 27, - nil, nil, nil, 34, 34, 26, 41, 54, 76, 63, - nil, 81, nil, 88, 171, 180, 16, 27, 93, 94, - 100, 101, 195, 199, nil, 38, nil, nil, 180, 159, - nil, nil, -5, nil, nil, nil, 185, nil, 186, 187, - 188, nil, nil, nil, nil, nil, 200, 43, 69, nil, - 203, 202, 143, 144, nil, nil, nil, nil, 203, 108, - 114, nil, nil, 204, 205, 206, 181, nil, nil, nil, - nil, nil, 180, 212, nil, nil, nil, nil, nil, 216, - nil, 217, 218, 219, 220, 221, 120, nil, 126, 217, - nil, 149, nil, 150, 132, nil, 138, 220, 215, 225, - 189, 184, 228, nil, 229, nil, nil, nil, nil, nil, - 174, nil, nil, 155, 182, 151, nil, nil, nil, -18, - -2, nil, nil, nil, 212, nil, 213, 214, 215, 216, - 217, 202, 234, 201, nil, 207, 140, nil, 156, 222, - nil, 223, nil, nil, 107, 113, 119, 205, nil, 3, - 161, nil, 237, nil, nil, nil, 244, nil, nil, nil, - 125, nil, nil, nil, 131, 137, 209, 4, nil, 214, - 154, 151, nil, nil, nil, nil, 210, 206, -16, nil, - 162, 167, 243, 168, nil, 232, 9, nil, nil, 173, - 251, nil, 160, nil, nil, 210, 161, nil, nil, nil, - nil, 235, 212, nil ] + nil, nil, nil, 31, 44, 29, 54, 62, 77, 82, + nil, nil, 92, nil, 179, 180, 181, 16, 27, 35, + 94, 95, 101, 196, 200, nil, 37, nil, nil, 180, + 159, nil, nil, -5, nil, nil, nil, 186, nil, 187, + 188, 189, nil, nil, nil, nil, nil, 201, 69, 102, + nil, 204, 203, 141, 142, nil, nil, nil, nil, 204, + 112, 118, nil, nil, 205, 206, 207, 181, nil, nil, + nil, nil, nil, 180, 213, nil, nil, nil, nil, nil, + 217, nil, 218, 219, 220, 221, 222, 124, nil, 130, + 218, nil, 147, nil, 148, 136, nil, 172, 221, 216, + 226, 189, 184, 229, nil, 230, nil, nil, nil, nil, + nil, 180, nil, nil, 153, 181, 151, nil, nil, nil, + -19, -2, nil, nil, nil, 213, nil, 214, 215, 216, + 217, 218, 202, 235, 201, nil, 207, 137, nil, 154, + 223, nil, 224, nil, nil, 105, 111, 117, 205, nil, + 3, 159, nil, 238, nil, nil, nil, 245, nil, nil, + nil, 123, nil, nil, nil, 129, 135, 209, 4, nil, + 214, 152, 149, nil, nil, nil, nil, 210, 206, -17, + nil, 160, 165, 244, 166, nil, 233, 9, nil, nil, + 171, 252, nil, 158, nil, nil, 210, 159, nil, nil, + nil, nil, 236, 212, nil ] racc_action_default = [ - -2, -130, -8, -130, -130, -3, -4, -130, 214, -130, - -9, -10, -11, -130, -130, -130, -130, -130, -130, -130, - -23, -130, -27, -130, -130, -130, -130, -130, -130, -130, - -130, -130, -130, -130, -7, -115, -88, -90, -130, -112, - -114, -12, -119, -86, -87, -118, -14, -77, -15, -16, - -130, -20, -24, -28, -31, -34, -37, -43, -130, -46, - -63, -38, -67, -130, -70, -72, -73, -127, -39, -80, - -130, -83, -85, -40, -41, -42, -130, -5, -1, -89, - -116, -91, -130, -130, -13, -120, -121, -122, -74, -130, - -17, -130, -130, -130, -130, -130, -130, -47, -44, -65, - -64, -130, -71, -68, -130, -84, -81, -130, -130, -130, - -96, -130, -130, -78, -130, -21, -25, -29, -32, -35, - -45, -48, -66, -69, -82, -130, -50, -6, -117, -92, - -93, -97, -113, -75, -130, -18, -130, -130, -130, -130, - -130, -130, -130, -96, -95, -86, -112, -101, -130, -130, - -79, -130, -22, -26, -130, -130, -130, -54, -51, -94, - -130, -98, -128, -105, -106, -107, -130, -104, -76, -19, - -30, -123, -125, -126, -33, -36, -49, -52, -55, -86, - -130, -108, -99, -129, -102, -124, -54, -112, -86, -59, - -130, -130, -128, -130, -110, -130, -53, -56, -57, -130, - -130, -62, -130, -100, -109, -112, -130, -60, -111, -103, - -58, -130, -112, -61 ] + -2, -131, -8, -131, -131, -3, -4, -131, 215, -131, + -9, -10, -11, -131, -131, -131, -131, -131, -131, -131, + -23, -24, -131, -28, -131, -131, -131, -131, -131, -131, + -131, -131, -131, -131, -131, -7, -116, -89, -91, -131, + -113, -115, -12, -120, -87, -88, -119, -14, -78, -15, + -16, -131, -20, -25, -29, -32, -35, -38, -44, -131, + -47, -64, -39, -68, -131, -71, -73, -74, -128, -40, + -81, -131, -84, -86, -41, -42, -43, -131, -5, -1, + -90, -117, -92, -131, -131, -13, -121, -122, -123, -75, + -131, -17, -131, -131, -131, -131, -131, -131, -48, -45, + -66, -65, -131, -72, -69, -131, -85, -82, -131, -131, + -131, -97, -131, -131, -79, -131, -21, -26, -30, -33, + -36, -46, -49, -67, -70, -83, -131, -51, -6, -118, + -93, -94, -98, -114, -76, -131, -18, -131, -131, -131, + -131, -131, -131, -131, -97, -96, -87, -113, -102, -131, + -131, -80, -131, -22, -27, -131, -131, -131, -55, -52, + -95, -131, -99, -129, -106, -107, -108, -131, -105, -77, + -19, -31, -124, -126, -127, -34, -37, -50, -53, -56, + -87, -131, -109, -100, -130, -103, -125, -55, -113, -87, + -60, -131, -131, -129, -131, -111, -131, -54, -57, -58, + -131, -131, -63, -131, -101, -110, -113, -131, -61, -112, + -104, -59, -131, -113, -62 ] racc_goto_table = [ - 82, 62, 57, 45, 97, 64, 105, 162, 182, 36, - 177, 1, 2, 180, 106, 60, 4, 72, 72, 72, - 72, 130, 185, 46, 48, 49, 185, 185, 68, 73, - 74, 75, 35, 78, 98, 79, 5, 103, 203, 196, - 102, 64, 194, 105, 202, 97, 60, 60, 124, 198, - 33, 108, 206, 10, 159, 170, 174, 175, 72, 72, - 11, 105, 12, 42, 84, 114, 151, 97, 91, 136, - 92, 137, 120, 93, 138, 123, 94, 139, 95, 64, - 140, 102, 56, 61, 99, 60, 121, 60, 125, 176, - 200, 211, 112, 72, 149, 72, 89, 134, 129, 166, - 195, 102, 109, nil, nil, nil, nil, 161, 146, 60, - nil, nil, nil, 72, nil, nil, nil, nil, nil, nil, - nil, nil, nil, nil, nil, nil, 167, nil, nil, nil, - nil, nil, nil, nil, nil, nil, nil, 146, 181, nil, - nil, nil, nil, nil, nil, nil, nil, nil, 197, nil, - nil, nil, nil, nil, nil, 187, nil, nil, nil, nil, - nil, nil, nil, nil, nil, nil, 209, nil, 201, 181, - nil, 204, nil, 213, 187, nil, nil, 181 ] + 83, 63, 46, 58, 98, 65, 106, 163, 183, 37, + 178, 1, 2, 181, 107, 61, 4, 73, 73, 73, + 73, 131, 186, 47, 49, 50, 186, 186, 69, 74, + 75, 76, 171, 175, 176, 99, 80, 104, 204, 197, + 103, 65, 195, 106, 203, 98, 61, 61, 125, 199, + 36, 79, 207, 5, 160, 34, 109, 10, 73, 73, + 11, 106, 12, 43, 85, 115, 152, 98, 92, 137, + 93, 138, 94, 121, 139, 124, 95, 140, 96, 65, + 141, 103, 57, 62, 100, 61, 122, 61, 126, 177, + 201, 212, 113, 73, 150, 73, 90, 135, 130, 167, + 196, 103, 110, nil, nil, nil, nil, 162, 147, 61, + nil, nil, nil, 73, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, 168, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, 147, 182, nil, + nil, nil, nil, nil, nil, nil, nil, nil, 198, nil, + nil, nil, nil, nil, nil, 188, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, 210, nil, 202, 182, + nil, 205, nil, 214, 188, nil, nil, 182 ] racc_goto_check = [ - 41, 46, 32, 34, 33, 40, 53, 42, 59, 54, + 41, 46, 34, 32, 33, 40, 53, 42, 59, 54, 39, 1, 2, 43, 52, 34, 3, 34, 34, 34, 34, 58, 63, 14, 14, 14, 63, 63, 31, 31, - 31, 31, 4, 5, 32, 54, 6, 46, 59, 39, + 31, 31, 20, 20, 20, 32, 54, 46, 59, 39, 40, 40, 42, 53, 43, 33, 34, 34, 52, 42, - 7, 8, 43, 9, 58, 20, 20, 20, 34, 34, + 4, 5, 43, 6, 58, 7, 8, 9, 34, 34, 10, 53, 11, 12, 13, 15, 16, 33, 17, 18, - 21, 22, 32, 23, 24, 46, 25, 26, 27, 40, + 21, 22, 23, 32, 24, 46, 25, 26, 27, 40, 28, 40, 29, 30, 35, 34, 36, 34, 37, 38, 44, 45, 48, 34, 49, 34, 50, 51, 57, 60, 61, 40, 62, nil, nil, nil, nil, 41, 40, 34, @@ -878,158 +876,159 @@ def raise_parse_error(error_message, location) nil, 40, nil, 41, 40, nil, nil, 40 ] racc_goto_pointer = [ - nil, 11, 12, 14, 23, -2, 34, 44, -26, 49, - 56, 58, 49, 22, 8, -25, -69, 17, -46, nil, - -99, 18, -45, 20, -43, 22, -41, 23, -39, 56, - 56, 0, -24, -53, -11, 24, -13, -19, -68, -147, - -22, -39, -139, -147, -99, -116, -26, nil, 4, -39, - 49, -16, -56, -63, 0, nil, nil, -12, -89, -154, - -48, -84, 22, -148 ] + nil, 11, 12, 14, 41, 15, 51, 49, -22, 53, + 56, 58, 49, 21, 8, -26, -70, 16, -47, nil, + -123, 17, -46, 18, -44, 21, -42, 22, -40, 55, + 55, -1, -24, -54, -12, 23, -14, -20, -69, -148, + -23, -40, -140, -148, -100, -117, -27, nil, 3, -40, + 48, -17, -57, -64, 0, nil, nil, -13, -90, -155, + -49, -85, 21, -149 ] racc_goto_default = [ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - 38, nil, nil, nil, nil, nil, nil, nil, nil, 22, + 39, nil, nil, nil, nil, nil, nil, nil, nil, 23, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, - nil, nil, nil, 59, 65, nil, nil, nil, nil, nil, - 172, nil, nil, nil, nil, nil, nil, 66, nil, nil, - nil, nil, 69, 71, nil, 37, 39, nil, nil, nil, - nil, nil, nil, 171 ] + nil, nil, nil, 60, 66, nil, nil, nil, nil, nil, + 173, nil, nil, nil, nil, nil, nil, 67, nil, nil, + nil, nil, 70, 72, nil, 38, 40, nil, nil, nil, + nil, nil, nil, 172 ] racc_reduce_table = [ 0, 0, :racc_error, - 5, 48, :_reduce_none, - 0, 49, :_reduce_none, - 2, 49, :_reduce_none, - 0, 54, :_reduce_4, - 0, 55, :_reduce_5, - 5, 53, :_reduce_6, - 2, 53, :_reduce_none, - 0, 50, :_reduce_8, + 5, 49, :_reduce_none, + 0, 50, :_reduce_none, 2, 50, :_reduce_none, - 1, 56, :_reduce_none, - 1, 56, :_reduce_none, - 2, 56, :_reduce_12, - 3, 56, :_reduce_none, - 2, 56, :_reduce_none, - 2, 56, :_reduce_15, - 2, 56, :_reduce_16, - 0, 62, :_reduce_17, - 0, 63, :_reduce_18, - 7, 56, :_reduce_19, - 0, 64, :_reduce_20, - 0, 65, :_reduce_21, - 6, 56, :_reduce_22, - 1, 56, :_reduce_none, - 0, 68, :_reduce_24, - 0, 69, :_reduce_25, - 6, 57, :_reduce_26, + 0, 55, :_reduce_4, + 0, 56, :_reduce_5, + 5, 54, :_reduce_6, + 2, 54, :_reduce_none, + 0, 51, :_reduce_8, + 2, 51, :_reduce_none, + 1, 57, :_reduce_none, 1, 57, :_reduce_none, - 0, 70, :_reduce_28, + 2, 57, :_reduce_12, + 3, 57, :_reduce_none, + 2, 57, :_reduce_none, + 2, 57, :_reduce_15, + 2, 57, :_reduce_16, + 0, 63, :_reduce_17, + 0, 64, :_reduce_18, + 7, 57, :_reduce_19, + 0, 65, :_reduce_20, + 0, 66, :_reduce_21, + 6, 57, :_reduce_22, + 1, 57, :_reduce_23, + 1, 57, :_reduce_none, + 0, 69, :_reduce_25, + 0, 70, :_reduce_26, + 6, 58, :_reduce_27, + 1, 58, :_reduce_none, 0, 71, :_reduce_29, - 7, 57, :_reduce_none, - 0, 72, :_reduce_31, + 0, 72, :_reduce_30, + 7, 58, :_reduce_none, 0, 73, :_reduce_32, - 7, 57, :_reduce_33, - 0, 74, :_reduce_34, + 0, 74, :_reduce_33, + 7, 58, :_reduce_34, 0, 75, :_reduce_35, - 7, 57, :_reduce_36, - 2, 66, :_reduce_none, - 2, 66, :_reduce_38, - 2, 66, :_reduce_39, - 2, 66, :_reduce_40, - 2, 66, :_reduce_41, - 2, 66, :_reduce_42, - 1, 76, :_reduce_43, - 2, 76, :_reduce_44, - 3, 76, :_reduce_45, - 1, 79, :_reduce_46, - 2, 79, :_reduce_47, - 3, 80, :_reduce_48, - 7, 58, :_reduce_49, - 1, 84, :_reduce_50, - 3, 84, :_reduce_51, - 1, 85, :_reduce_52, - 3, 85, :_reduce_53, - 0, 86, :_reduce_54, - 1, 86, :_reduce_55, - 3, 86, :_reduce_56, - 3, 86, :_reduce_57, - 5, 86, :_reduce_58, - 0, 91, :_reduce_59, + 0, 76, :_reduce_36, + 7, 58, :_reduce_37, + 2, 67, :_reduce_none, + 2, 67, :_reduce_39, + 2, 67, :_reduce_40, + 2, 67, :_reduce_41, + 2, 67, :_reduce_42, + 2, 67, :_reduce_43, + 1, 77, :_reduce_44, + 2, 77, :_reduce_45, + 3, 77, :_reduce_46, + 1, 80, :_reduce_47, + 2, 80, :_reduce_48, + 3, 81, :_reduce_49, + 7, 59, :_reduce_50, + 1, 85, :_reduce_51, + 3, 85, :_reduce_52, + 1, 86, :_reduce_53, + 3, 86, :_reduce_54, + 0, 87, :_reduce_55, + 1, 87, :_reduce_56, + 3, 87, :_reduce_57, + 3, 87, :_reduce_58, + 5, 87, :_reduce_59, 0, 92, :_reduce_60, - 7, 86, :_reduce_61, - 3, 86, :_reduce_62, - 0, 82, :_reduce_none, - 1, 82, :_reduce_none, + 0, 93, :_reduce_61, + 7, 87, :_reduce_62, + 3, 87, :_reduce_63, 0, 83, :_reduce_none, 1, 83, :_reduce_none, - 1, 77, :_reduce_67, - 2, 77, :_reduce_68, - 3, 77, :_reduce_69, - 1, 93, :_reduce_70, - 2, 93, :_reduce_71, - 1, 87, :_reduce_none, - 1, 87, :_reduce_none, - 0, 95, :_reduce_74, + 0, 84, :_reduce_none, + 1, 84, :_reduce_none, + 1, 78, :_reduce_68, + 2, 78, :_reduce_69, + 3, 78, :_reduce_70, + 1, 94, :_reduce_71, + 2, 94, :_reduce_72, + 1, 88, :_reduce_none, + 1, 88, :_reduce_none, 0, 96, :_reduce_75, - 6, 61, :_reduce_76, - 0, 97, :_reduce_77, + 0, 97, :_reduce_76, + 6, 62, :_reduce_77, 0, 98, :_reduce_78, - 5, 61, :_reduce_79, - 1, 78, :_reduce_80, - 2, 78, :_reduce_81, - 3, 78, :_reduce_82, - 1, 99, :_reduce_83, - 2, 99, :_reduce_84, - 1, 100, :_reduce_none, - 1, 81, :_reduce_86, - 1, 81, :_reduce_87, - 1, 51, :_reduce_none, - 2, 51, :_reduce_none, + 0, 99, :_reduce_79, + 5, 62, :_reduce_80, + 1, 79, :_reduce_81, + 2, 79, :_reduce_82, + 3, 79, :_reduce_83, + 1, 100, :_reduce_84, + 2, 100, :_reduce_85, 1, 101, :_reduce_none, - 2, 101, :_reduce_none, - 4, 102, :_reduce_92, - 1, 104, :_reduce_93, - 3, 104, :_reduce_94, - 2, 104, :_reduce_none, - 0, 105, :_reduce_96, - 1, 105, :_reduce_97, - 3, 105, :_reduce_98, - 4, 105, :_reduce_99, - 6, 105, :_reduce_100, - 0, 107, :_reduce_101, + 1, 82, :_reduce_87, + 1, 82, :_reduce_88, + 1, 52, :_reduce_none, + 2, 52, :_reduce_none, + 1, 102, :_reduce_none, + 2, 102, :_reduce_none, + 4, 103, :_reduce_93, + 1, 105, :_reduce_94, + 3, 105, :_reduce_95, + 2, 105, :_reduce_none, + 0, 106, :_reduce_97, + 1, 106, :_reduce_98, + 3, 106, :_reduce_99, + 4, 106, :_reduce_100, + 6, 106, :_reduce_101, 0, 108, :_reduce_102, - 7, 105, :_reduce_103, - 3, 105, :_reduce_104, - 1, 89, :_reduce_none, - 1, 89, :_reduce_none, - 1, 89, :_reduce_none, + 0, 109, :_reduce_103, + 7, 106, :_reduce_104, + 3, 106, :_reduce_105, + 1, 90, :_reduce_106, + 1, 90, :_reduce_107, 1, 90, :_reduce_108, - 3, 90, :_reduce_109, - 2, 90, :_reduce_110, - 4, 90, :_reduce_111, - 0, 88, :_reduce_none, - 3, 88, :_reduce_113, - 1, 103, :_reduce_none, - 0, 52, :_reduce_none, - 0, 109, :_reduce_116, - 3, 52, :_reduce_117, - 1, 59, :_reduce_none, - 0, 60, :_reduce_none, + 1, 91, :_reduce_109, + 3, 91, :_reduce_110, + 2, 91, :_reduce_111, + 4, 91, :_reduce_112, + 0, 89, :_reduce_none, + 3, 89, :_reduce_114, + 1, 104, :_reduce_none, + 0, 53, :_reduce_none, + 0, 110, :_reduce_117, + 3, 53, :_reduce_118, 1, 60, :_reduce_none, - 1, 60, :_reduce_none, - 1, 60, :_reduce_none, - 1, 67, :_reduce_123, - 2, 67, :_reduce_124, - 1, 110, :_reduce_none, - 1, 110, :_reduce_none, - 1, 94, :_reduce_127, - 0, 106, :_reduce_none, - 1, 106, :_reduce_none ] - -racc_reduce_n = 130 - -racc_shift_n = 214 + 0, 61, :_reduce_none, + 1, 61, :_reduce_none, + 1, 61, :_reduce_none, + 1, 61, :_reduce_none, + 1, 68, :_reduce_124, + 2, 68, :_reduce_125, + 1, 111, :_reduce_none, + 1, 111, :_reduce_none, + 1, 95, :_reduce_128, + 0, 107, :_reduce_none, + 1, 107, :_reduce_none ] + +racc_reduce_n = 131 + +racc_shift_n = 215 racc_token_table = { false => 0, @@ -1054,33 +1053,34 @@ def raise_parse_error(error_message, location) "{" => 19, "}" => 20, "%initial-action" => 21, - ";" => 22, - "%union" => 23, - "%destructor" => 24, - "%printer" => 25, - "%error-token" => 26, - "%token" => 27, - "%type" => 28, - "%left" => 29, - "%right" => 30, - "%precedence" => 31, - "%nonassoc" => 32, - "%rule" => 33, - "(" => 34, - ")" => 35, - ":" => 36, - "," => 37, - "|" => 38, - "%empty" => 39, - "%prec" => 40, - "?" => 41, - "+" => 42, - "*" => 43, - "[" => 44, - "]" => 45, - "{...}" => 46 } - -racc_nt_base = 47 + "%no-stdlib" => 22, + ";" => 23, + "%union" => 24, + "%destructor" => 25, + "%printer" => 26, + "%error-token" => 27, + "%token" => 28, + "%type" => 29, + "%left" => 30, + "%right" => 31, + "%precedence" => 32, + "%nonassoc" => 33, + "%rule" => 34, + "(" => 35, + ")" => 36, + ":" => 37, + "," => 38, + "|" => 39, + "%empty" => 40, + "%prec" => 41, + "?" => 42, + "+" => 43, + "*" => 44, + "[" => 45, + "]" => 46, + "{...}" => 47 } + +racc_nt_base = 48 racc_use_result_var = true @@ -1124,6 +1124,7 @@ def raise_parse_error(error_message, location) "\"{\"", "\"}\"", "\"%initial-action\"", + "\"%no-stdlib\"", "\";\"", "\"%union\"", "\"%destructor\"", @@ -1346,26 +1347,33 @@ def _reduce_22(val, _values, result) end .,., -# reduce 23 omitted +module_eval(<<'.,.,', 'parser.y', 71) + def _reduce_23(val, _values, result) + @grammar.no_stdlib = true + result + end +.,., + +# reduce 24 omitted -module_eval(<<'.,.,', 'parser.y', 75) - def _reduce_24(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 76) + def _reduce_25(val, _values, result) begin_c_declaration("}") result end .,., -module_eval(<<'.,.,', 'parser.y', 79) - def _reduce_25(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 80) + def _reduce_26(val, _values, result) end_c_declaration result end .,., -module_eval(<<'.,.,', 'parser.y', 83) - def _reduce_26(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 84) + def _reduce_27(val, _values, result) @grammar.set_union( Grammar::Code::NoReferenceCode.new(type: :union, token_code: val[3]), val[3].line @@ -1375,44 +1383,44 @@ def _reduce_26(val, _values, result) end .,., -# reduce 27 omitted +# reduce 28 omitted -module_eval(<<'.,.,', 'parser.y', 91) - def _reduce_28(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 92) + def _reduce_29(val, _values, result) begin_c_declaration("}") result end .,., -module_eval(<<'.,.,', 'parser.y', 95) - def _reduce_29(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 96) + def _reduce_30(val, _values, result) end_c_declaration result end .,., -# reduce 30 omitted +# reduce 31 omitted -module_eval(<<'.,.,', 'parser.y', 100) - def _reduce_31(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 101) + def _reduce_32(val, _values, result) begin_c_declaration("}") result end .,., -module_eval(<<'.,.,', 'parser.y', 104) - def _reduce_32(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 105) + def _reduce_33(val, _values, result) end_c_declaration result end .,., -module_eval(<<'.,.,', 'parser.y', 108) - def _reduce_33(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 109) + def _reduce_34(val, _values, result) @grammar.add_printer( ident_or_tags: val[6], token_code: val[3], @@ -1423,24 +1431,24 @@ def _reduce_33(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 116) - def _reduce_34(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 117) + def _reduce_35(val, _values, result) begin_c_declaration("}") result end .,., -module_eval(<<'.,.,', 'parser.y', 120) - def _reduce_35(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 121) + def _reduce_36(val, _values, result) end_c_declaration result end .,., -module_eval(<<'.,.,', 'parser.y', 124) - def _reduce_36(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 125) + def _reduce_37(val, _values, result) @grammar.add_error_token( ident_or_tags: val[6], token_code: val[3], @@ -1451,10 +1459,10 @@ def _reduce_36(val, _values, result) end .,., -# reduce 37 omitted +# reduce 38 omitted -module_eval(<<'.,.,', 'parser.y', 134) - def _reduce_38(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 135) + def _reduce_39(val, _values, result) val[1].each {|hash| hash[:tokens].each {|id| @grammar.add_type(id: id, tag: hash[:tag]) @@ -1465,8 +1473,8 @@ def _reduce_38(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 142) - def _reduce_39(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 143) + def _reduce_40(val, _values, result) val[1].each {|hash| hash[:tokens].each {|id| sym = @grammar.add_term(id: id) @@ -1479,8 +1487,8 @@ def _reduce_39(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 152) - def _reduce_40(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 153) + def _reduce_41(val, _values, result) val[1].each {|hash| hash[:tokens].each {|id| sym = @grammar.add_term(id: id) @@ -1493,8 +1501,8 @@ def _reduce_40(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 162) - def _reduce_41(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 163) + def _reduce_42(val, _values, result) val[1].each {|hash| hash[:tokens].each {|id| sym = @grammar.add_term(id: id) @@ -1507,8 +1515,8 @@ def _reduce_41(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 172) - def _reduce_42(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 173) + def _reduce_43(val, _values, result) val[1].each {|hash| hash[:tokens].each {|id| sym = @grammar.add_term(id: id) @@ -1521,8 +1529,8 @@ def _reduce_42(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 183) - def _reduce_43(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 184) + def _reduce_44(val, _values, result) val[0].each {|token_declaration| @grammar.add_term(id: token_declaration[0], alias_name: token_declaration[2], token_id: token_declaration[1], tag: nil, replace: true) } @@ -1531,8 +1539,8 @@ def _reduce_43(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 189) - def _reduce_44(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 190) + def _reduce_45(val, _values, result) val[1].each {|token_declaration| @grammar.add_term(id: token_declaration[0], alias_name: token_declaration[2], token_id: token_declaration[1], tag: val[0], replace: true) } @@ -1541,8 +1549,8 @@ def _reduce_44(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 195) - def _reduce_45(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 196) + def _reduce_46(val, _values, result) val[2].each {|token_declaration| @grammar.add_term(id: token_declaration[0], alias_name: token_declaration[2], token_id: token_declaration[1], tag: val[1], replace: true) } @@ -1551,29 +1559,29 @@ def _reduce_45(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 200) - def _reduce_46(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 201) + def _reduce_47(val, _values, result) result = [val[0]] result end .,., -module_eval(<<'.,.,', 'parser.y', 201) - def _reduce_47(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 202) + def _reduce_48(val, _values, result) result = val[0].append(val[1]) result end .,., -module_eval(<<'.,.,', 'parser.y', 203) - def _reduce_48(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 204) + def _reduce_49(val, _values, result) result = val result end .,., -module_eval(<<'.,.,', 'parser.y', 207) - def _reduce_49(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 208) + def _reduce_50(val, _values, result) rule = Grammar::ParameterizingRule::Rule.new(val[1].s_value, val[3], val[6]) @grammar.add_parameterizing_rule(rule) @@ -1581,22 +1589,22 @@ def _reduce_49(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 211) - def _reduce_50(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 212) + def _reduce_51(val, _values, result) result = [val[0]] result end .,., -module_eval(<<'.,.,', 'parser.y', 212) - def _reduce_51(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 213) + def _reduce_52(val, _values, result) result = val[0].append(val[2]) result end .,., -module_eval(<<'.,.,', 'parser.y', 216) - def _reduce_52(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 217) + def _reduce_53(val, _values, result) builder = val[0] result = [builder] @@ -1604,8 +1612,8 @@ def _reduce_52(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 221) - def _reduce_53(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 222) + def _reduce_54(val, _values, result) builder = val[2] result = val[0].append(builder) @@ -1613,8 +1621,8 @@ def _reduce_53(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 227) - def _reduce_54(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 228) + def _reduce_55(val, _values, result) reset_precs result = Grammar::ParameterizingRule::Rhs.new @@ -1622,8 +1630,8 @@ def _reduce_54(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 232) - def _reduce_55(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 233) + def _reduce_56(val, _values, result) reset_precs result = Grammar::ParameterizingRule::Rhs.new @@ -1631,8 +1639,8 @@ def _reduce_55(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 237) - def _reduce_56(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 238) + def _reduce_57(val, _values, result) token = val[1] token.alias_name = val[2] builder = val[0] @@ -1643,8 +1651,8 @@ def _reduce_56(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 245) - def _reduce_57(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 246) + def _reduce_58(val, _values, result) builder = val[0] builder.symbols << Lrama::Lexer::Token::InstantiateRule.new(s_value: val[2], location: @lexer.location, args: [val[1]]) result = builder @@ -1653,8 +1661,8 @@ def _reduce_57(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 251) - def _reduce_58(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 252) + def _reduce_59(val, _values, result) builder = val[0] builder.symbols << Lrama::Lexer::Token::InstantiateRule.new(s_value: val[1].s_value, location: @lexer.location, args: val[3]) result = builder @@ -1663,8 +1671,8 @@ def _reduce_58(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 257) - def _reduce_59(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 258) + def _reduce_60(val, _values, result) if @prec_seen on_action_error("multiple User_code after %prec", val[0]) if @code_after_prec @code_after_prec = true @@ -1675,16 +1683,16 @@ def _reduce_59(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 265) - def _reduce_60(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 266) + def _reduce_61(val, _values, result) end_c_declaration result end .,., -module_eval(<<'.,.,', 'parser.y', 269) - def _reduce_61(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 270) + def _reduce_62(val, _values, result) user_code = val[3] user_code.alias_name = val[6] builder = val[0] @@ -1695,8 +1703,8 @@ def _reduce_61(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 277) - def _reduce_62(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 278) + def _reduce_63(val, _values, result) sym = @grammar.find_symbol_by_id!(val[2]) @prec_seen = true builder = val[0] @@ -1707,168 +1715,168 @@ def _reduce_62(val, _values, result) end .,., -# reduce 63 omitted - # reduce 64 omitted # reduce 65 omitted # reduce 66 omitted -module_eval(<<'.,.,', 'parser.y', 292) - def _reduce_67(val, _values, result) +# reduce 67 omitted + +module_eval(<<'.,.,', 'parser.y', 293) + def _reduce_68(val, _values, result) result = [{tag: nil, tokens: val[0]}] result end .,., -module_eval(<<'.,.,', 'parser.y', 296) - def _reduce_68(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 297) + def _reduce_69(val, _values, result) result = [{tag: val[0], tokens: val[1]}] result end .,., -module_eval(<<'.,.,', 'parser.y', 300) - def _reduce_69(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 301) + def _reduce_70(val, _values, result) result = val[0].append({tag: val[1], tokens: val[2]}) result end .,., -module_eval(<<'.,.,', 'parser.y', 303) - def _reduce_70(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 304) + def _reduce_71(val, _values, result) result = [val[0]] result end .,., -module_eval(<<'.,.,', 'parser.y', 304) - def _reduce_71(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 305) + def _reduce_72(val, _values, result) result = val[0].append(val[1]) result end .,., -# reduce 72 omitted - # reduce 73 omitted -module_eval(<<'.,.,', 'parser.y', 311) - def _reduce_74(val, _values, result) +# reduce 74 omitted + +module_eval(<<'.,.,', 'parser.y', 312) + def _reduce_75(val, _values, result) begin_c_declaration("}") result end .,., -module_eval(<<'.,.,', 'parser.y', 315) - def _reduce_75(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 316) + def _reduce_76(val, _values, result) end_c_declaration result end .,., -module_eval(<<'.,.,', 'parser.y', 319) - def _reduce_76(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 320) + def _reduce_77(val, _values, result) result = val[0].append(val[3]) result end .,., -module_eval(<<'.,.,', 'parser.y', 323) - def _reduce_77(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 324) + def _reduce_78(val, _values, result) begin_c_declaration("}") result end .,., -module_eval(<<'.,.,', 'parser.y', 327) - def _reduce_78(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 328) + def _reduce_79(val, _values, result) end_c_declaration result end .,., -module_eval(<<'.,.,', 'parser.y', 331) - def _reduce_79(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 332) + def _reduce_80(val, _values, result) result = [val[2]] result end .,., -module_eval(<<'.,.,', 'parser.y', 336) - def _reduce_80(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 337) + def _reduce_81(val, _values, result) result = [{tag: nil, tokens: val[0]}] result end .,., -module_eval(<<'.,.,', 'parser.y', 340) - def _reduce_81(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 341) + def _reduce_82(val, _values, result) result = [{tag: val[0], tokens: val[1]}] result end .,., -module_eval(<<'.,.,', 'parser.y', 344) - def _reduce_82(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 345) + def _reduce_83(val, _values, result) result = val[0].append({tag: val[1], tokens: val[2]}) result end .,., -module_eval(<<'.,.,', 'parser.y', 347) - def _reduce_83(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 348) + def _reduce_84(val, _values, result) result = [val[0]] result end .,., -module_eval(<<'.,.,', 'parser.y', 348) - def _reduce_84(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 349) + def _reduce_85(val, _values, result) result = val[0].append(val[1]) result end .,., -# reduce 85 omitted +# reduce 86 omitted -module_eval(<<'.,.,', 'parser.y', 352) - def _reduce_86(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 353) + def _reduce_87(val, _values, result) on_action_error("ident after %prec", val[0]) if @prec_seen result end .,., -module_eval(<<'.,.,', 'parser.y', 353) - def _reduce_87(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 354) + def _reduce_88(val, _values, result) on_action_error("char after %prec", val[0]) if @prec_seen result end .,., -# reduce 88 omitted - # reduce 89 omitted # reduce 90 omitted # reduce 91 omitted -module_eval(<<'.,.,', 'parser.y', 363) - def _reduce_92(val, _values, result) +# reduce 92 omitted + +module_eval(<<'.,.,', 'parser.y', 364) + def _reduce_93(val, _values, result) lhs = val[0] lhs.alias_name = val[1] val[3].each do |builder| @@ -1881,8 +1889,8 @@ def _reduce_92(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 374) - def _reduce_93(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 375) + def _reduce_94(val, _values, result) builder = val[0] if !builder.line builder.line = @lexer.line - 1 @@ -1893,8 +1901,8 @@ def _reduce_93(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 382) - def _reduce_94(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 383) + def _reduce_95(val, _values, result) builder = val[2] if !builder.line builder.line = @lexer.line - 1 @@ -1905,10 +1913,10 @@ def _reduce_94(val, _values, result) end .,., -# reduce 95 omitted +# reduce 96 omitted -module_eval(<<'.,.,', 'parser.y', 392) - def _reduce_96(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 393) + def _reduce_97(val, _values, result) reset_precs result = Grammar::RuleBuilder.new(@rule_counter, @midrule_action_counter) @@ -1916,8 +1924,8 @@ def _reduce_96(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 397) - def _reduce_97(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 398) + def _reduce_98(val, _values, result) reset_precs result = Grammar::RuleBuilder.new(@rule_counter, @midrule_action_counter) @@ -1925,8 +1933,8 @@ def _reduce_97(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 402) - def _reduce_98(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 403) + def _reduce_99(val, _values, result) token = val[1] token.alias_name = val[2] builder = val[0] @@ -1937,8 +1945,8 @@ def _reduce_98(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 410) - def _reduce_99(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 411) + def _reduce_100(val, _values, result) token = Lrama::Lexer::Token::InstantiateRule.new(s_value: val[2], location: @lexer.location, args: [val[1]], lhs_tag: val[3]) builder = val[0] builder.add_rhs(token) @@ -1949,8 +1957,8 @@ def _reduce_99(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 418) - def _reduce_100(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 419) + def _reduce_101(val, _values, result) token = Lrama::Lexer::Token::InstantiateRule.new(s_value: val[1].s_value, location: @lexer.location, args: val[3], lhs_tag: val[5]) builder = val[0] builder.add_rhs(token) @@ -1961,8 +1969,8 @@ def _reduce_100(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 426) - def _reduce_101(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 427) + def _reduce_102(val, _values, result) if @prec_seen on_action_error("multiple User_code after %prec", val[0]) if @code_after_prec @code_after_prec = true @@ -1973,16 +1981,16 @@ def _reduce_101(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 434) - def _reduce_102(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 435) + def _reduce_103(val, _values, result) end_c_declaration result end .,., -module_eval(<<'.,.,', 'parser.y', 438) - def _reduce_103(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 439) + def _reduce_104(val, _values, result) user_code = val[3] user_code.alias_name = val[6] builder = val[0] @@ -1993,8 +2001,8 @@ def _reduce_103(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 446) - def _reduce_104(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 447) + def _reduce_105(val, _values, result) sym = @grammar.find_symbol_by_id!(val[2]) @prec_seen = true builder = val[0] @@ -2005,55 +2013,70 @@ def _reduce_104(val, _values, result) end .,., -# reduce 105 omitted - -# reduce 106 omitted +module_eval(<<'.,.,', 'parser.y', 454) + def _reduce_106(val, _values, result) + result = "option" + result + end +.,., -# reduce 107 omitted +module_eval(<<'.,.,', 'parser.y', 455) + def _reduce_107(val, _values, result) + result = "nonempty_list" + result + end +.,., -module_eval(<<'.,.,', 'parser.y', 457) +module_eval(<<'.,.,', 'parser.y', 456) def _reduce_108(val, _values, result) - result = [val[0]] + result = "list" result end .,., module_eval(<<'.,.,', 'parser.y', 458) def _reduce_109(val, _values, result) - result = val[0].append(val[2]) + result = [val[0]] result end .,., module_eval(<<'.,.,', 'parser.y', 459) def _reduce_110(val, _values, result) - result = [Lrama::Lexer::Token::InstantiateRule.new(s_value: val[1].s_value, location: @lexer.location, args: val[0])] + result = val[0].append(val[2]) result end .,., module_eval(<<'.,.,', 'parser.y', 460) def _reduce_111(val, _values, result) + result = [Lrama::Lexer::Token::InstantiateRule.new(s_value: val[1].s_value, location: @lexer.location, args: val[0])] + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 461) + def _reduce_112(val, _values, result) result = [Lrama::Lexer::Token::InstantiateRule.new(s_value: val[0].s_value, location: @lexer.location, args: val[2])] result end .,., -# reduce 112 omitted +# reduce 113 omitted -module_eval(<<'.,.,', 'parser.y', 463) - def _reduce_113(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 464) + def _reduce_114(val, _values, result) result = val[1].s_value result end .,., -# reduce 114 omitted - # reduce 115 omitted -module_eval(<<'.,.,', 'parser.y', 470) - def _reduce_116(val, _values, result) +# reduce 116 omitted + +module_eval(<<'.,.,', 'parser.y', 471) + def _reduce_117(val, _values, result) begin_c_declaration('\Z') @grammar.epilogue_first_lineno = @lexer.line + 1 @@ -2061,8 +2084,8 @@ def _reduce_116(val, _values, result) end .,., -module_eval(<<'.,.,', 'parser.y', 475) - def _reduce_117(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 476) + def _reduce_118(val, _values, result) end_c_declaration @grammar.epilogue = val[2].s_value @@ -2070,8 +2093,6 @@ def _reduce_117(val, _values, result) end .,., -# reduce 118 omitted - # reduce 119 omitted # reduce 120 omitted @@ -2080,35 +2101,37 @@ def _reduce_117(val, _values, result) # reduce 122 omitted -module_eval(<<'.,.,', 'parser.y', 486) - def _reduce_123(val, _values, result) +# reduce 123 omitted + +module_eval(<<'.,.,', 'parser.y', 487) + def _reduce_124(val, _values, result) result = [val[0]] result end .,., -module_eval(<<'.,.,', 'parser.y', 487) - def _reduce_124(val, _values, result) +module_eval(<<'.,.,', 'parser.y', 488) + def _reduce_125(val, _values, result) result = val[0].append(val[1]) result end .,., -# reduce 125 omitted - # reduce 126 omitted -module_eval(<<'.,.,', 'parser.y', 492) - def _reduce_127(val, _values, result) +# reduce 127 omitted + +module_eval(<<'.,.,', 'parser.y', 493) + def _reduce_128(val, _values, result) result = Lrama::Lexer::Token::Ident.new(s_value: val[0]) result end .,., -# reduce 128 omitted - # reduce 129 omitted +# reduce 130 omitted + def _reduce_none(val, _values, result) val[0] end diff --git a/tool/lrama/lib/lrama/states/item.rb b/tool/lrama/lib/lrama/states/item.rb index 823ccc72e1b4cf..083527729b8c47 100644 --- a/tool/lrama/lib/lrama/states/item.rb +++ b/tool/lrama/lib/lrama/states/item.rb @@ -5,7 +5,7 @@ class States class Item < Struct.new(:rule, :position, keyword_init: true) # Optimization for States#setup_state def hash - [rule.id, position].hash + [rule_id, position].hash end def rule_id @@ -17,27 +17,31 @@ def empty_rule? end def number_of_rest_symbols - rule.rhs.count - position + rhs.count - position end def lhs rule.lhs end + def rhs + rule.rhs + end + def next_sym - rule.rhs[position] + rhs[position] end def next_next_sym - rule.rhs[position + 1] + rhs[position + 1] end def previous_sym - rule.rhs[position - 1] + rhs[position - 1] end def end_of_rule? - rule.rhs.count == position + rhs.count == position end def beginning_of_rule? @@ -45,7 +49,7 @@ def beginning_of_rule? end def start_item? - rule.id == 0 && position == 0 + rule.initial_rule? && beginning_of_rule? end def new_by_next_position @@ -53,11 +57,11 @@ def new_by_next_position end def symbols_before_dot - rule.rhs[0...position] + rhs[0...position] end def symbols_after_dot - rule.rhs[position..-1] + rhs[position..-1] end def to_s @@ -65,14 +69,14 @@ def to_s end def display_name - r = rule.rhs.map(&:display_name).insert(position, "•").join(" ") - "#{r} (rule #{rule.id})" + r = rhs.map(&:display_name).insert(position, "•").join(" ") + "#{r} (rule #{rule_id})" end # Right after position def display_rest - r = rule.rhs[position..-1].map(&:display_name).join(" ") - ". #{r} (rule #{rule.id})" + r = rhs[position..-1].map(&:display_name).join(" ") + ". #{r} (rule #{rule_id})" end end end diff --git a/tool/lrama/lib/lrama/states_reporter.rb b/tool/lrama/lib/lrama/states_reporter.rb index 19830a63bbf29c..6a0b75d98cc810 100644 --- a/tool/lrama/lib/lrama/states_reporter.rb +++ b/tool/lrama/lib/lrama/states_reporter.rb @@ -53,7 +53,7 @@ def report_grammar(io) last_lhs = nil @states.rules.each do |rule| - if rule.rhs.empty? + if rule.empty_rule? r = "ε" else r = rule.rhs.map(&:display_name).join(" ") @@ -84,17 +84,15 @@ def report_states(io, itemsets, lookaheads, solved, counterexamples, verbose) last_lhs = nil list = itemsets ? state.items : state.kernels list.sort_by {|i| [i.rule_id, i.position] }.each do |item| - rule = item.rule - position = item.position - if rule.rhs.empty? + if item.empty_rule? r = "ε •" else - r = rule.rhs.map(&:display_name).insert(position, "•").join(" ") + r = item.rhs.map(&:display_name).insert(item.position, "•").join(" ") end - if rule.lhs == last_lhs - l = " " * rule.lhs.id.s_value.length + "|" + if item.lhs == last_lhs + l = " " * item.lhs.id.s_value.length + "|" else - l = rule.lhs.id.s_value + ":" + l = item.lhs.id.s_value + ":" end la = "" if lookaheads && item.end_of_rule? @@ -104,9 +102,9 @@ def report_states(io, itemsets, lookaheads, solved, counterexamples, verbose) la = " [#{look_ahead.map(&:display_name).join(", ")}]" end end - last_lhs = rule.lhs + last_lhs = item.lhs - io << sprintf("%5i %s %s%s\n", rule.id, l, r, la) + io << sprintf("%5i %s %s%s\n", item.rule_id, l, r, la) end io << "\n" diff --git a/tool/lrama/lib/lrama/version.rb b/tool/lrama/lib/lrama/version.rb index 406939918ce543..b54814595ceaa3 100644 --- a/tool/lrama/lib/lrama/version.rb +++ b/tool/lrama/lib/lrama/version.rb @@ -1,3 +1,3 @@ module Lrama - VERSION = "0.6.1".freeze + VERSION = "0.6.2".freeze end From 68b9a32a624edf0cb497d344a2a8650658500517 Mon Sep 17 00:00:00 2001 From: yui-knk Date: Sat, 27 Jan 2024 14:41:07 +0900 Subject: [PATCH 571/640] bvar is not NODE but ID Before this commit `ruby -y -e 'tap {|;x, y|}'` failed with SEGV. This change fixes it. --- parse.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parse.y b/parse.y index 878869b35923b8..8a47a618250a7a 100644 --- a/parse.y +++ b/parse.y @@ -2415,7 +2415,7 @@ rb_str_to_parser_string(rb_parser_t *p, VALUE str) %type block_param opt_block_param block_param_def %type f_opt %type f_kwarg f_kw f_block_kwarg f_block_kw -%type bv_decls opt_bv_decl bvar +%type bv_decls opt_bv_decl bvar %type lambda lambda_body brace_body do_body %type f_larglist %type brace_block cmd_brace_block do_block lhs none fitem From 9b40f42c22232aaae1b2b17bd6118eacc4c0bee3 Mon Sep 17 00:00:00 2001 From: "S.H" Date: Sat, 27 Jan 2024 17:11:10 +0900 Subject: [PATCH 572/640] Introduce `NODE_ENCODING` `__ENCODING__ `was managed by `NODE_LIT` with Encoding object. Introduce `NODE_ENCODING` for 1. `__ENCODING__` is detectable from AST Node. 2. Reduce dependency Ruby object for parse.y --- ast.c | 2 ++ compile.c | 15 +++++++++++++++ internal/ruby_parser.h | 1 + node_dump.c | 7 +++++++ parse.y | 28 +++++++++++++++++++++++++--- ruby_parser.c | 6 ++++++ rubyparser.h | 7 +++++++ 7 files changed, 63 insertions(+), 3 deletions(-) diff --git a/ast.c b/ast.c index b61dfbf4cb222c..579110e20a78fd 100644 --- a/ast.c +++ b/ast.c @@ -706,6 +706,8 @@ node_children(rb_ast_t *ast, const NODE *node) return rb_ary_new_from_args(1, rb_node_line_lineno_val(node)); case NODE_FILE: return rb_ary_new_from_args(1, rb_node_file_path_val(node)); + case NODE_ENCODING: + return rb_ary_new_from_args(1, rb_node_encoding_val(node)); case NODE_ERROR: return rb_ary_new_from_node_args(ast, 0); case NODE_ARGS_AUX: diff --git a/compile.c b/compile.c index 4ae1174caae7ff..eea92b36381577 100644 --- a/compile.c +++ b/compile.c @@ -1960,6 +1960,9 @@ iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, case NODE_IMAGINARY: dv = rb_node_imaginary_literal_val(val_node); break; + case NODE_ENCODING: + dv = rb_node_encoding_val(val_node); + break; case NODE_NIL: dv = Qnil; break; @@ -4512,6 +4515,7 @@ compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *ret, const NODE *cond, case NODE_SYM: case NODE_LINE: case NODE_FILE: + case NODE_ENCODING: case NODE_INTEGER: /* NODE_INTEGER is always true */ case NODE_FLOAT: /* NODE_FLOAT is always true */ case NODE_RATIONAL: /* NODE_RATIONAL is always true */ @@ -4722,6 +4726,7 @@ static_literal_node_p(const NODE *node, const rb_iseq_t *iseq, bool hash_key) case NODE_LIT: case NODE_SYM: case NODE_LINE: + case NODE_ENCODING: case NODE_INTEGER: case NODE_FLOAT: case NODE_RATIONAL: @@ -4760,6 +4765,8 @@ static_literal_value(const NODE *node, rb_iseq_t *iseq) return rb_node_sym_string_val(node); case NODE_LINE: return rb_node_line_lineno_val(node); + case NODE_ENCODING: + return rb_node_encoding_val(node); case NODE_FILE: case NODE_STR: if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) { @@ -5790,6 +5797,7 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, case NODE_SYM: case NODE_LINE: case NODE_FILE: + case NODE_ENCODING: case NODE_INTEGER: case NODE_FLOAT: case NODE_RATIONAL: @@ -7221,6 +7229,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c case NODE_RATIONAL: case NODE_IMAGINARY: case NODE_FILE: + case NODE_ENCODING: case NODE_STR: case NODE_XSTR: case NODE_DSTR: @@ -10273,6 +10282,12 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no } break; } + case NODE_ENCODING:{ + if (!popped) { + ADD_INSN1(ret, node, putobject, rb_node_encoding_val(node)); + } + break; + } case NODE_INTEGER:{ VALUE lit = rb_node_integer_literal_val(node); debugp_param("integer", lit); diff --git a/internal/ruby_parser.h b/internal/ruby_parser.h index 018a1865ded68d..71e8fdd849ad0c 100644 --- a/internal/ruby_parser.h +++ b/internal/ruby_parser.h @@ -79,6 +79,7 @@ RUBY_SYMBOL_EXPORT_END VALUE rb_node_sym_string_val(const NODE *); VALUE rb_node_line_lineno_val(const NODE *); VALUE rb_node_file_path_val(const NODE *); +VALUE rb_node_encoding_val(const NODE *); VALUE rb_node_integer_literal_val(const NODE *); VALUE rb_node_float_literal_val(const NODE *); diff --git a/node_dump.c b/node_dump.c index 61c1b6a14f2cc2..a6f9bff4e3595d 100644 --- a/node_dump.c +++ b/node_dump.c @@ -1149,6 +1149,13 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node) F_VALUE(path, rb_node_file_path_val(node), "path"); return; + case NODE_ENCODING: + ANN("encoding"); + ANN("format: [enc]"); + ANN("example: __ENCODING__"); + F_VALUE(enc, rb_node_encoding_val(node), "enc"); + break; + case NODE_ERROR: ANN("Broken input recovered by Error Tolerant mode"); return; diff --git a/parse.y b/parse.y index 8a47a618250a7a..180c298a88337b 100644 --- a/parse.y +++ b/parse.y @@ -232,6 +232,8 @@ node_cdhash_hash(VALUE a) case NODE_FILE: /* Same with String in rb_iseq_cdhash_hash */ return rb_str_hash(rb_node_file_path_val(node)); + case NODE_ENCODING: + return rb_node_encoding_val(node); default: rb_bug("unexpected node: %s", ruby_node_name(type)); } @@ -1272,6 +1274,7 @@ static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE #define NEW_FNDPTN(pre,a,post,loc) (NODE *)rb_node_fndptn_new(p,pre,a,post,loc) #define NEW_LINE(loc) (NODE *)rb_node_line_new(p,loc) #define NEW_FILE(str,loc) (NODE *)rb_node_file_new(p,str,loc) +#define NEW_ENCODING(loc) (NODE *)rb_node_encoding_new(p,loc) #define NEW_ERROR(loc) (NODE *)rb_node_error_new(p,loc) #endif @@ -6942,6 +6945,7 @@ singleton : var_ref case NODE_SYM: case NODE_LINE: case NODE_FILE: + case NODE_ENCODING: case NODE_INTEGER: case NODE_FLOAT: case NODE_RATIONAL: @@ -12589,6 +12593,15 @@ rb_node_file_new(struct parser_params *p, VALUE str, const YYLTYPE *loc) return n; } +static rb_node_encoding_t * +rb_node_encoding_new(struct parser_params *p, const YYLTYPE *loc) +{ + rb_node_encoding_t *n = NODE_NEWNODE(NODE_ENCODING, rb_node_encoding_t, loc); + n->enc = p->enc; + + return n; +} + static rb_node_cdecl_t * rb_node_cdecl_new(struct parser_params *p, ID nd_vid, NODE *nd_value, NODE *nd_else, const YYLTYPE *loc) { @@ -13195,9 +13208,7 @@ gettable(struct parser_params *p, ID id, const YYLTYPE *loc) case keyword__LINE__: return NEW_LINE(loc); case keyword__ENCODING__: - node = NEW_LIT(rb_enc_from_encoding(p->enc), loc); - RB_OBJ_WRITTEN(p->ast, Qnil, RNODE_LIT(node)->nd_lit); - return node; + return NEW_ENCODING(loc); } switch (id_type(id)) { @@ -14059,6 +14070,8 @@ shareable_literal_value(struct parser_params *p, NODE *node) return rb_node_rational_literal_val(node); case NODE_IMAGINARY: return rb_node_imaginary_literal_val(node); + case NODE_ENCODING: + return rb_node_encoding_val(node); case NODE_LIT: return RNODE_LIT(node)->nd_lit; default: @@ -14091,6 +14104,7 @@ shareable_literal_constant(struct parser_params *p, enum shareability shareable, case NODE_FLOAT: case NODE_RATIONAL: case NODE_IMAGINARY: + case NODE_ENCODING: return value; case NODE_DSTR: @@ -14407,6 +14421,7 @@ void_expr(struct parser_params *p, NODE *node) case NODE_SYM: case NODE_LINE: case NODE_FILE: + case NODE_ENCODING: case NODE_INTEGER: case NODE_FLOAT: case NODE_RATIONAL: @@ -14551,6 +14566,7 @@ is_static_content(NODE *node) case NODE_SYM: case NODE_LINE: case NODE_FILE: + case NODE_ENCODING: case NODE_INTEGER: case NODE_FLOAT: case NODE_RATIONAL: @@ -14700,6 +14716,10 @@ cond0(struct parser_params *p, NODE *node, enum cond_type type, const YYLTYPE *l SWITCH_BY_COND_TYPE(type, warning, ""); break; + case NODE_ENCODING: + SWITCH_BY_COND_TYPE(type, warning, ""); + break; + case NODE_INTEGER: case NODE_FLOAT: case NODE_RATIONAL: @@ -15096,6 +15116,8 @@ nd_st_key(struct parser_params *p, NODE *node) return rb_node_sym_string_val(node); case NODE_LINE: return rb_node_line_lineno_val(node); + case NODE_ENCODING: + return rb_node_encoding_val(node); case NODE_FILE: return rb_node_file_path_val(node); default: diff --git a/ruby_parser.c b/ruby_parser.c index 965fe2cc1ae552..3a6f9ed0826f63 100644 --- a/ruby_parser.c +++ b/ruby_parser.c @@ -1008,3 +1008,9 @@ rb_node_file_path_val(const NODE *node) { return rb_str_new_parser_string(RNODE_FILE(node)->path); } + +VALUE +rb_node_encoding_val(const NODE *node) +{ + return rb_enc_from_encoding(RNODE_ENCODING(node)->enc); +} diff --git a/rubyparser.h b/rubyparser.h index 2bd93bf0b2a6a6..e4f06a9052a5a4 100644 --- a/rubyparser.h +++ b/rubyparser.h @@ -160,6 +160,7 @@ enum node_type { NODE_ERROR, NODE_LINE, NODE_FILE, + NODE_ENCODING, NODE_RIPPER, NODE_RIPPER_VALUES, NODE_LAST @@ -1005,6 +1006,11 @@ typedef struct RNode_FILE { struct rb_parser_string *path; } rb_node_file_t; +typedef struct RNode_ENCODING { + NODE node; + rb_encoding *enc; +} rb_node_encoding_t; + typedef struct RNode_ERROR { NODE node; } rb_node_error_t; @@ -1121,6 +1127,7 @@ typedef struct RNode_ERROR { #define RNODE_FNDPTN(node) ((struct RNode_FNDPTN *)(node)) #define RNODE_LINE(node) ((struct RNode_LINE *)(node)) #define RNODE_FILE(node) ((struct RNode_FILE *)(node)) +#define RNODE_ENCODING(node) ((struct RNode_ENCODING *)(node)) #ifdef RIPPER typedef struct RNode_RIPPER { From 5d9d07a49184c9a5c5eb0dc2ba579a46c80b3eb6 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Sat, 27 Jan 2024 09:13:28 -0500 Subject: [PATCH 573/640] [ruby/prism] Bring back #arg_rest local https://github.com/ruby/prism/commit/9b6907b727 --- lib/prism/debug.rb | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/prism/debug.rb b/lib/prism/debug.rb index f4c0bcf91a7a0e..4e8d3f216cb654 100644 --- a/lib/prism/debug.rb +++ b/lib/prism/debug.rb @@ -59,7 +59,21 @@ def self.cruby_locals(source) stack = [ISeq.new(RubyVM::InstructionSequence.compile(source).to_a)] while (iseq = stack.pop) - locals << iseq.local_table + names = [*iseq.local_table] + names.map!.with_index do |name, index| + # When an anonymous local variable is present in the iseq's local + # table, it is represented as the stack offset from the top. + # However, when these are dumped to binary and read back in, they + # are replaced with the symbol :#arg_rest. To consistently handle + # this, we replace them here with their index. + if name == :"#arg_rest" + names.length - index + 1 + else + name + end + end + + locals << names iseq.each_child { |child| stack << child } end From 0bac390e079b269ca55e36dd574da1a879d5595f Mon Sep 17 00:00:00 2001 From: Masato Ohba Date: Sat, 27 Jan 2024 22:19:40 +0900 Subject: [PATCH 574/640] [rubygems/rubygems] Bump Ruby version to be used in `bundle gem` template since 2.6 and 2.7 are EOL and bundler dropped their support by https://github.com/rubygems/rubygems/pull/7116. https://github.com/rubygems/rubygems/commit/b562d9a822 --- lib/bundler/cli/gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bundler/cli/gem.rb b/lib/bundler/cli/gem.rb index 98192d952e605e..f0bb3aab188906 100644 --- a/lib/bundler/cli/gem.rb +++ b/lib/bundler/cli/gem.rb @@ -437,7 +437,7 @@ def rust_builder_required_rubygems_version end def required_ruby_version - "2.6.0" + "3.0.0" end def rubocop_version From 2217e08340cbeba427fc58c7f955fc2382ab0372 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Sat, 27 Jan 2024 10:16:52 -0800 Subject: [PATCH 575/640] Optimize compilation of large literal arrays To avoid stack overflow, Ruby splits compilation of large arrays into smaller arrays, and concatenates the small arrays together. It previously used newarray/concatarray for this, which is inefficient. This switches the compilation to use pushtoarray, which is much faster. This makes almost all literal arrays only allocate a single array. For cases where there is a large amount of static values in the array, Ruby will statically compile subarrays, and previously added them using concatarray. This switches to concattoarray, avoiding an array allocation for the append. Keyword splats are also supported in arrays, and ignored if the keyword splat is empty. Previously, this used newarraykwsplat and concatarray. This still uses newarraykwsplat, but switches to concattoarray to save an allocation. So large arrays with keyword splats can allocate 2 arrays instead of 1. Previously, for the following array sizes (assuming local variable access for each element), Ruby allocated the following number of arrays: 1000 elements: 7 arrays 10000 elements: 79 arrays 100000 elements: 781 arrays With these changes, only a single array is allocated (or 2 for a large array with a keyword splat. Results using the included benchmark: ``` array_1000 miniruby: 34770.0 i/s ./miniruby-before: 10511.7 i/s - 3.31x slower array_10000 miniruby: 4938.8 i/s ./miniruby-before: 483.8 i/s - 10.21x slower array_100000 miniruby: 727.2 i/s ./miniruby-before: 4.1 i/s - 176.98x slower ``` Co-authored-by: Nobuyoshi Nakada --- benchmark/array_large_literal.yml | 19 +++++++++++++++++++ compile.c | 27 ++++++++++++++------------- 2 files changed, 33 insertions(+), 13 deletions(-) create mode 100644 benchmark/array_large_literal.yml diff --git a/benchmark/array_large_literal.yml b/benchmark/array_large_literal.yml new file mode 100644 index 00000000000000..423d68391fcfcf --- /dev/null +++ b/benchmark/array_large_literal.yml @@ -0,0 +1,19 @@ +prelude: | + def def_array(size) + Object.class_eval(<<-END) + def array_#{size} + x = 1 + [#{(['x'] * size).join(',')}] + end + END + end + def_array(100) + def_array(1000) + def_array(10000) + def_array(100000) +benchmark: + array_100: array_100 + array_1000: array_1000 + array_10000: array_10000 + array_100000: array_100000 + diff --git a/compile.c b/compile.c index eea92b36381577..71b657d9f2fcfb 100644 --- a/compile.c +++ b/compile.c @@ -4822,8 +4822,8 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop * * [x1,x2,...,x10000] => * push x1 ; push x2 ; ...; push x256; newarray 256; - * push x257; push x258; ...; push x512; newarray 256; concatarray; - * push x513; push x514; ...; push x768; newarray 256; concatarray; + * push x257; push x258; ...; push x512; pushtoarray 256; + * push x513; push x514; ...; push x768; pushtoarray 256; * ... * * - Long subarray can be optimized by pre-allocating a hidden array. @@ -4833,8 +4833,8 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop * * [x, 1,2,3,...,100, z] => * push x; newarray 1; - * putobject [1,2,3,...,100] (<- hidden array); concatarray; - * push z; newarray 1; concatarray + * putobject [1,2,3,...,100] (<- hidden array); concattoarray; + * push z; pushtoarray 1; * * - If the last element is a keyword, newarraykwsplat should be emitted * to check and remove empty keyword arguments hash from array. @@ -4849,11 +4849,11 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop int stack_len = 0; int first_chunk = 1; - /* Convert pushed elements to an array, and concatarray if needed */ -#define FLUSH_CHUNK(newarrayinsn) \ + /* Either create a new array, or push to the existing array */ +#define FLUSH_CHUNK \ if (stack_len) { \ - ADD_INSN1(ret, line_node, newarrayinsn, INT2FIX(stack_len)); \ - if (!first_chunk) ADD_INSN(ret, line_node, concatarray); \ + if (first_chunk) ADD_INSN1(ret, line_node, newarray, INT2FIX(stack_len)); \ + else ADD_INSN1(ret, line_node, pushtoarray, INT2FIX(stack_len)); \ first_chunk = stack_len = 0; \ } @@ -4877,14 +4877,14 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop OBJ_FREEZE(ary); /* Emit optimized code */ - FLUSH_CHUNK(newarray); + FLUSH_CHUNK; if (first_chunk) { ADD_INSN1(ret, line_node, duparray, ary); first_chunk = 0; } else { ADD_INSN1(ret, line_node, putobject, ary); - ADD_INSN(ret, line_node, concatarray); + ADD_INSN(ret, line_node, concattoarray); } RB_OBJ_WRITTEN(iseq, Qundef, ary); } @@ -4901,16 +4901,17 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop if (!RNODE_LIST(node)->nd_next && keyword_node_p(RNODE_LIST(node)->nd_head)) { /* Reached the end, and the last element is a keyword */ - FLUSH_CHUNK(newarraykwsplat); + ADD_INSN1(ret, line_node, newarraykwsplat, INT2FIX(stack_len)); + if (!first_chunk) ADD_INSN(ret, line_node, concattoarray); return 1; } /* If there are many pushed elements, flush them to avoid stack overflow */ - if (stack_len >= max_stack_len) FLUSH_CHUNK(newarray); + if (stack_len >= max_stack_len) FLUSH_CHUNK; } } - FLUSH_CHUNK(newarray); + FLUSH_CHUNK; #undef FLUSH_CHUNK return 1; } From c2e2d2398b86e7bcc89ab534e3a3af54cf8374b5 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Sat, 27 Jan 2024 11:05:30 +0100 Subject: [PATCH 576/640] [ruby/prism] Call #inspect on diagnostic levels * So it's clear it is a Symbol. Before: ... @level=warning_verbose_true> After: ... @level=:warning_verbose_true> https://github.com/ruby/prism/commit/84503643b9 --- lib/prism/parse_result.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index 27e03fe23b4c01..5bb7ac7e9e5e5f 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -329,7 +329,7 @@ def deconstruct_keys(keys) # Returns a string representation of this error. def inspect - "#" + "#" end end @@ -358,7 +358,7 @@ def deconstruct_keys(keys) # Returns a string representation of this warning. def inspect - "#" + "#" end end From e337c9478a1c5d60b6cfa4ddbee71523a7f8bd84 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 26 Jan 2024 16:51:26 -0500 Subject: [PATCH 577/640] [ruby/prism] Error follow-up Split up the diagnostic levels so that error and warning levels aren't mixed. Also fix up deconstruct_keys implementation. https://github.com/ruby/prism/commit/bd3eeb308d Co-authored-by: Benoit Daloze --- lib/prism/parse_result.rb | 8 +- prism/diagnostic.c | 461 +++++++++++---------- prism/diagnostic.h | 23 +- prism/extension.c | 38 +- prism/templates/lib/prism/serialize.rb.erb | 24 +- test/prism/errors_test.rb | 4 +- 6 files changed, 295 insertions(+), 263 deletions(-) diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index 5bb7ac7e9e5e5f..b67fe0617de2dd 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -312,7 +312,7 @@ class ParseError # A Location object representing the location of this error in the source. attr_reader :location - # The level of this error + # The level of this error. attr_reader :level # Create a new error object with the given message and location. @@ -324,7 +324,7 @@ def initialize(message, location, level) # Implement the hash pattern matching interface for ParseError. def deconstruct_keys(keys) - { message: message, location: location } + { message: message, location: location, level: level } end # Returns a string representation of this error. @@ -341,7 +341,7 @@ class ParseWarning # A Location object representing the location of this warning in the source. attr_reader :location - # The level of this warning + # The level of this warning. attr_reader :level # Create a new warning object with the given message and location. @@ -353,7 +353,7 @@ def initialize(message, location, level) # Implement the hash pattern matching interface for ParseWarning. def deconstruct_keys(keys) - { message: message, location: location, verbose_only: verbose_only } + { message: message, location: location, level: level } end # Returns a string representation of this warning. diff --git a/prism/diagnostic.c b/prism/diagnostic.c index 112ee4ddee6111..3ff4a933c64508 100644 --- a/prism/diagnostic.c +++ b/prism/diagnostic.c @@ -1,13 +1,13 @@ #include "prism/diagnostic.h" /** This struct holds the data for each diagnostic. */ -struct diagnostic_data { +typedef struct { /** The message associated with the diagnostic. */ const char* message; /** The level associated with the diagnostic. */ - pm_diagnostic_level_t level; -}; + uint8_t level; +} pm_diagnostic_data_t; /** * ## Message composition @@ -61,235 +61,240 @@ struct diagnostic_data { * * ## Level * - * See pm_diagnostic_level_t for the available levels. - * For warning, they are either: - * PM_WARNING_VERBOSE_NOT_NIL if they appear for `ruby -c -e 'code'`, - * or PM_WARNING_VERBOSE_TRUE if they appear only with -w: `ruby -w -c -e 'code'`. + * For errors, they are: + * + * * `PM_ERROR_LEVEL_FATAL` - The level for all errors. + * + * For warnings, they are: + * + * * `PM_WARNING_LEVEL_DEFAULT` - Warnings that appear for `ruby -c -e 'code'`. + * * `PM_WARNING_LEVEL_VERBOSE` - Warnings that appear with `-w`, as in `ruby -w -c -e 'code'`. */ -static struct diagnostic_data const diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = { +static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = { // Errors - [PM_ERR_ALIAS_ARGUMENT] = { "invalid argument being passed to `alias`; expected a bare word, symbol, constant, or global variable", PM_ERROR_DEFAULT }, - [PM_ERR_AMPAMPEQ_MULTI_ASSIGN] = { "unexpected `&&=` in a multiple assignment", PM_ERROR_DEFAULT }, - [PM_ERR_ARGUMENT_AFTER_BLOCK] = { "unexpected argument after a block argument", PM_ERROR_DEFAULT }, - [PM_ERR_ARGUMENT_AFTER_FORWARDING_ELLIPSES] = { "unexpected argument after `...`", PM_ERROR_DEFAULT }, - [PM_ERR_ARGUMENT_BARE_HASH] = { "unexpected bare hash argument", PM_ERROR_DEFAULT }, - [PM_ERR_ARGUMENT_BLOCK_FORWARDING] = { "both a block argument and a forwarding argument; only one block is allowed", PM_ERROR_DEFAULT }, - [PM_ERR_ARGUMENT_BLOCK_MULTI] = { "multiple block arguments; only one block is allowed", PM_ERROR_DEFAULT }, - [PM_ERR_ARGUMENT_FORMAL_CLASS] = { "invalid formal argument; formal argument cannot be a class variable", PM_ERROR_DEFAULT }, - [PM_ERR_ARGUMENT_FORMAL_CONSTANT] = { "invalid formal argument; formal argument cannot be a constant", PM_ERROR_DEFAULT }, - [PM_ERR_ARGUMENT_FORMAL_GLOBAL] = { "invalid formal argument; formal argument cannot be a global variable", PM_ERROR_DEFAULT }, - [PM_ERR_ARGUMENT_FORMAL_IVAR] = { "invalid formal argument; formal argument cannot be an instance variable", PM_ERROR_DEFAULT }, - [PM_ERR_ARGUMENT_FORWARDING_UNBOUND] = { "unexpected `...` in an non-parenthesized call", PM_ERROR_DEFAULT }, - [PM_ERR_ARGUMENT_IN] = { "unexpected `in` keyword in arguments", PM_ERROR_DEFAULT }, - [PM_ERR_ARGUMENT_NO_FORWARDING_AMP] = { "unexpected `&` when the parent method is not forwarding", PM_ERROR_DEFAULT }, - [PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES] = { "unexpected `...` when the parent method is not forwarding", PM_ERROR_DEFAULT }, - [PM_ERR_ARGUMENT_NO_FORWARDING_STAR] = { "unexpected `*` when the parent method is not forwarding", PM_ERROR_DEFAULT }, - [PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT] = { "unexpected `*` splat argument after a `**` keyword splat argument", PM_ERROR_DEFAULT }, - [PM_ERR_ARGUMENT_SPLAT_AFTER_SPLAT] = { "unexpected `*` splat argument after a `*` splat argument", PM_ERROR_DEFAULT }, - [PM_ERR_ARGUMENT_TERM_PAREN] = { "expected a `)` to close the arguments", PM_ERROR_DEFAULT }, - [PM_ERR_ARGUMENT_UNEXPECTED_BLOCK] = { "unexpected `{` after a method call without parenthesis", PM_ERROR_DEFAULT }, - [PM_ERR_ARRAY_ELEMENT] = { "expected an element for the array", PM_ERROR_DEFAULT }, - [PM_ERR_ARRAY_EXPRESSION] = { "expected an expression for the array element", PM_ERROR_DEFAULT }, - [PM_ERR_ARRAY_EXPRESSION_AFTER_STAR] = { "expected an expression after `*` in the array", PM_ERROR_DEFAULT }, - [PM_ERR_ARRAY_SEPARATOR] = { "expected a `,` separator for the array elements", PM_ERROR_DEFAULT }, - [PM_ERR_ARRAY_TERM] = { "expected a `]` to close the array", PM_ERROR_DEFAULT }, - [PM_ERR_BEGIN_LONELY_ELSE] = { "unexpected `else` in `begin` block; a `rescue` clause must precede `else`", PM_ERROR_DEFAULT }, - [PM_ERR_BEGIN_TERM] = { "expected an `end` to close the `begin` statement", PM_ERROR_DEFAULT }, - [PM_ERR_BEGIN_UPCASE_BRACE] = { "expected a `{` after `BEGIN`", PM_ERROR_DEFAULT }, - [PM_ERR_BEGIN_UPCASE_TERM] = { "expected a `}` to close the `BEGIN` statement", PM_ERROR_DEFAULT }, - [PM_ERR_BEGIN_UPCASE_TOPLEVEL] = { "BEGIN is permitted only at toplevel", PM_ERROR_DEFAULT }, - [PM_ERR_BLOCK_PARAM_LOCAL_VARIABLE] = { "expected a local variable name in the block parameters", PM_ERROR_DEFAULT }, - [PM_ERR_BLOCK_PARAM_PIPE_TERM] = { "expected the block parameters to end with `|`", PM_ERROR_DEFAULT }, - [PM_ERR_BLOCK_TERM_BRACE] = { "expected a block beginning with `{` to end with `}`", PM_ERROR_DEFAULT }, - [PM_ERR_BLOCK_TERM_END] = { "expected a block beginning with `do` to end with `end`", PM_ERROR_DEFAULT }, - [PM_ERR_CANNOT_PARSE_EXPRESSION] = { "cannot parse the expression", PM_ERROR_DEFAULT }, - [PM_ERR_CANNOT_PARSE_STRING_PART] = { "cannot parse the string part", PM_ERROR_DEFAULT }, - [PM_ERR_CASE_EXPRESSION_AFTER_CASE] = { "expected an expression after `case`", PM_ERROR_DEFAULT }, - [PM_ERR_CASE_EXPRESSION_AFTER_WHEN] = { "expected an expression after `when`", PM_ERROR_DEFAULT }, - [PM_ERR_CASE_MATCH_MISSING_PREDICATE] = { "expected a predicate for a case matching statement", PM_ERROR_DEFAULT }, - [PM_ERR_CASE_MISSING_CONDITIONS] = { "expected a `when` or `in` clause after `case`", PM_ERROR_DEFAULT }, - [PM_ERR_CASE_TERM] = { "expected an `end` to close the `case` statement", PM_ERROR_DEFAULT }, - [PM_ERR_CLASS_IN_METHOD] = { "unexpected class definition in a method definition", PM_ERROR_DEFAULT }, - [PM_ERR_CLASS_NAME] = { "expected a constant name after `class`", PM_ERROR_DEFAULT }, - [PM_ERR_CLASS_SUPERCLASS] = { "expected a superclass after `<`", PM_ERROR_DEFAULT }, - [PM_ERR_CLASS_TERM] = { "expected an `end` to close the `class` statement", PM_ERROR_DEFAULT }, - [PM_ERR_CLASS_UNEXPECTED_END] = { "unexpected `end`, expecting ';' or '\\n'", PM_ERROR_DEFAULT }, - [PM_ERR_CONDITIONAL_ELSIF_PREDICATE] = { "expected a predicate expression for the `elsif` statement", PM_ERROR_DEFAULT }, - [PM_ERR_CONDITIONAL_IF_PREDICATE] = { "expected a predicate expression for the `if` statement", PM_ERROR_DEFAULT }, - [PM_ERR_CONDITIONAL_PREDICATE_TERM] = { "expected `then` or `;` or '\\n'", PM_ERROR_DEFAULT }, - [PM_ERR_CONDITIONAL_TERM] = { "expected an `end` to close the conditional clause", PM_ERROR_DEFAULT }, - [PM_ERR_CONDITIONAL_TERM_ELSE] = { "expected an `end` to close the `else` clause", PM_ERROR_DEFAULT }, - [PM_ERR_CONDITIONAL_UNLESS_PREDICATE] = { "expected a predicate expression for the `unless` statement", PM_ERROR_DEFAULT }, - [PM_ERR_CONDITIONAL_UNTIL_PREDICATE] = { "expected a predicate expression for the `until` statement", PM_ERROR_DEFAULT }, - [PM_ERR_CONDITIONAL_WHILE_PREDICATE] = { "expected a predicate expression for the `while` statement", PM_ERROR_DEFAULT }, - [PM_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT] = { "expected a constant after the `::` operator", PM_ERROR_DEFAULT }, - [PM_ERR_DEF_ENDLESS] = { "could not parse the endless method body", PM_ERROR_DEFAULT }, - [PM_ERR_DEF_ENDLESS_SETTER] = { "invalid method name; a setter method cannot be defined in an endless method definition", PM_ERROR_DEFAULT }, - [PM_ERR_DEF_NAME] = { "expected a method name", PM_ERROR_DEFAULT }, - [PM_ERR_DEF_NAME_AFTER_RECEIVER] = { "expected a method name after the receiver", PM_ERROR_DEFAULT }, - [PM_ERR_DEF_PARAMS_TERM] = { "expected a delimiter to close the parameters", PM_ERROR_DEFAULT }, - [PM_ERR_DEF_PARAMS_TERM_PAREN] = { "expected a `)` to close the parameters", PM_ERROR_DEFAULT }, - [PM_ERR_DEF_RECEIVER] = { "expected a receiver for the method definition", PM_ERROR_DEFAULT }, - [PM_ERR_DEF_RECEIVER_TERM] = { "expected a `.` or `::` after the receiver in a method definition", PM_ERROR_DEFAULT }, - [PM_ERR_DEF_TERM] = { "expected an `end` to close the `def` statement", PM_ERROR_DEFAULT }, - [PM_ERR_DEFINED_EXPRESSION] = { "expected an expression after `defined?`", PM_ERROR_DEFAULT }, - [PM_ERR_EMBDOC_TERM] = { "could not find a terminator for the embedded document", PM_ERROR_DEFAULT }, - [PM_ERR_EMBEXPR_END] = { "expected a `}` to close the embedded expression", PM_ERROR_DEFAULT }, - [PM_ERR_EMBVAR_INVALID] = { "invalid embedded variable", PM_ERROR_DEFAULT }, - [PM_ERR_END_UPCASE_BRACE] = { "expected a `{` after `END`", PM_ERROR_DEFAULT }, - [PM_ERR_END_UPCASE_TERM] = { "expected a `}` to close the `END` statement", PM_ERROR_DEFAULT }, - [PM_ERR_ESCAPE_INVALID_CONTROL] = { "invalid control escape sequence", PM_ERROR_DEFAULT }, - [PM_ERR_ESCAPE_INVALID_CONTROL_REPEAT] = { "invalid control escape sequence; control cannot be repeated", PM_ERROR_DEFAULT }, - [PM_ERR_ESCAPE_INVALID_HEXADECIMAL] = { "invalid hexadecimal escape sequence", PM_ERROR_DEFAULT }, - [PM_ERR_ESCAPE_INVALID_META] = { "invalid meta escape sequence", PM_ERROR_DEFAULT }, - [PM_ERR_ESCAPE_INVALID_META_REPEAT] = { "invalid meta escape sequence; meta cannot be repeated", PM_ERROR_DEFAULT }, - [PM_ERR_ESCAPE_INVALID_UNICODE] = { "invalid Unicode escape sequence", PM_ERROR_DEFAULT }, - [PM_ERR_ESCAPE_INVALID_UNICODE_CM_FLAGS] = { "invalid Unicode escape sequence; Unicode cannot be combined with control or meta flags", PM_ERROR_DEFAULT }, - [PM_ERR_ESCAPE_INVALID_UNICODE_LITERAL] = { "invalid Unicode escape sequence; multiple codepoints are not allowed in a character literal", PM_ERROR_DEFAULT }, - [PM_ERR_ESCAPE_INVALID_UNICODE_LONG] = { "invalid Unicode escape sequence; maximum length is 6 digits", PM_ERROR_DEFAULT }, - [PM_ERR_ESCAPE_INVALID_UNICODE_TERM] = { "invalid Unicode escape sequence; needs closing `}`", PM_ERROR_DEFAULT }, - [PM_ERR_EXPECT_ARGUMENT] = { "expected an argument", PM_ERROR_DEFAULT }, - [PM_ERR_EXPECT_EOL_AFTER_STATEMENT] = { "expected a newline or semicolon after the statement", PM_ERROR_DEFAULT }, - [PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ] = { "expected an expression after `&&=`", PM_ERROR_DEFAULT }, - [PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ] = { "expected an expression after `||=`", PM_ERROR_DEFAULT }, - [PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA] = { "expected an expression after `,`", PM_ERROR_DEFAULT }, - [PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL] = { "expected an expression after `=`", PM_ERROR_DEFAULT }, - [PM_ERR_EXPECT_EXPRESSION_AFTER_LESS_LESS] = { "expected an expression after `<<`", PM_ERROR_DEFAULT }, - [PM_ERR_EXPECT_EXPRESSION_AFTER_LPAREN] = { "expected an expression after `(`", PM_ERROR_DEFAULT }, - [PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR] = { "expected an expression after the operator", PM_ERROR_DEFAULT }, - [PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT] = { "expected an expression after `*` splat in an argument", PM_ERROR_DEFAULT }, - [PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH] = { "expected an expression after `**` in a hash", PM_ERROR_DEFAULT }, - [PM_ERR_EXPECT_EXPRESSION_AFTER_STAR] = { "expected an expression after `*`", PM_ERROR_DEFAULT }, - [PM_ERR_EXPECT_IDENT_REQ_PARAMETER] = { "expected an identifier for the required parameter", PM_ERROR_DEFAULT }, - [PM_ERR_EXPECT_LPAREN_REQ_PARAMETER] = { "expected a `(` to start a required parameter", PM_ERROR_DEFAULT }, - [PM_ERR_EXPECT_RBRACKET] = { "expected a matching `]`", PM_ERROR_DEFAULT }, - [PM_ERR_EXPECT_RPAREN] = { "expected a matching `)`", PM_ERROR_DEFAULT }, - [PM_ERR_EXPECT_RPAREN_AFTER_MULTI] = { "expected a `)` after multiple assignment", PM_ERROR_DEFAULT }, - [PM_ERR_EXPECT_RPAREN_REQ_PARAMETER] = { "expected a `)` to end a required parameter", PM_ERROR_DEFAULT }, - [PM_ERR_EXPECT_STRING_CONTENT] = { "expected string content after opening string delimiter", PM_ERROR_DEFAULT }, - [PM_ERR_EXPECT_WHEN_DELIMITER] = { "expected a delimiter after the predicates of a `when` clause", PM_ERROR_DEFAULT }, - [PM_ERR_EXPRESSION_BARE_HASH] = { "unexpected bare hash in expression", PM_ERROR_DEFAULT }, - [PM_ERR_FOR_COLLECTION] = { "expected a collection after the `in` in a `for` statement", PM_ERROR_DEFAULT }, - [PM_ERR_FOR_INDEX] = { "expected an index after `for`", PM_ERROR_DEFAULT }, - [PM_ERR_FOR_IN] = { "expected an `in` after the index in a `for` statement", PM_ERROR_DEFAULT }, - [PM_ERR_FOR_TERM] = { "expected an `end` to close the `for` loop", PM_ERROR_DEFAULT }, - [PM_ERR_HASH_EXPRESSION_AFTER_LABEL] = { "expected an expression after the label in a hash", PM_ERROR_DEFAULT }, - [PM_ERR_HASH_KEY] = { "expected a key in the hash literal", PM_ERROR_DEFAULT }, - [PM_ERR_HASH_ROCKET] = { "expected a `=>` between the hash key and value", PM_ERROR_DEFAULT }, - [PM_ERR_HASH_TERM] = { "expected a `}` to close the hash literal", PM_ERROR_DEFAULT }, - [PM_ERR_HASH_VALUE] = { "expected a value in the hash literal", PM_ERROR_DEFAULT }, - [PM_ERR_HEREDOC_TERM] = { "could not find a terminator for the heredoc", PM_ERROR_DEFAULT }, - [PM_ERR_INCOMPLETE_QUESTION_MARK] = { "incomplete expression at `?`", PM_ERROR_DEFAULT }, - [PM_ERR_INCOMPLETE_VARIABLE_CLASS] = { "incomplete class variable", PM_ERROR_DEFAULT }, - [PM_ERR_INCOMPLETE_VARIABLE_INSTANCE] = { "incomplete instance variable", PM_ERROR_DEFAULT }, - [PM_ERR_INVALID_ENCODING_MAGIC_COMMENT] = { "unknown or invalid encoding in the magic comment", PM_ERROR_DEFAULT }, - [PM_ERR_INVALID_FLOAT_EXPONENT] = { "invalid exponent", PM_ERROR_DEFAULT }, - [PM_ERR_INVALID_NUMBER_BINARY] = { "invalid binary number", PM_ERROR_DEFAULT }, - [PM_ERR_INVALID_NUMBER_DECIMAL] = { "invalid decimal number", PM_ERROR_DEFAULT }, - [PM_ERR_INVALID_NUMBER_HEXADECIMAL] = { "invalid hexadecimal number", PM_ERROR_DEFAULT }, - [PM_ERR_INVALID_NUMBER_OCTAL] = { "invalid octal number", PM_ERROR_DEFAULT }, - [PM_ERR_INVALID_NUMBER_UNDERSCORE] = { "invalid underscore placement in number", PM_ERROR_DEFAULT }, - [PM_ERR_INVALID_PERCENT] = { "invalid `%` token", PM_ERROR_DEFAULT }, // TODO WHAT? - [PM_ERR_INVALID_TOKEN] = { "invalid token", PM_ERROR_DEFAULT }, // TODO WHAT? - [PM_ERR_INVALID_VARIABLE_GLOBAL] = { "invalid global variable", PM_ERROR_DEFAULT }, - [PM_ERR_IT_NOT_ALLOWED] = { "`it` is not allowed when an ordinary parameter is defined", PM_ERROR_DEFAULT }, - [PM_ERR_LAMBDA_OPEN] = { "expected a `do` keyword or a `{` to open the lambda block", PM_ERROR_DEFAULT }, - [PM_ERR_LAMBDA_TERM_BRACE] = { "expected a lambda block beginning with `{` to end with `}`", PM_ERROR_DEFAULT }, - [PM_ERR_LAMBDA_TERM_END] = { "expected a lambda block beginning with `do` to end with `end`", PM_ERROR_DEFAULT }, - [PM_ERR_LIST_I_LOWER_ELEMENT] = { "expected a symbol in a `%i` list", PM_ERROR_DEFAULT }, - [PM_ERR_LIST_I_LOWER_TERM] = { "expected a closing delimiter for the `%i` list", PM_ERROR_DEFAULT }, - [PM_ERR_LIST_I_UPPER_ELEMENT] = { "expected a symbol in a `%I` list", PM_ERROR_DEFAULT }, - [PM_ERR_LIST_I_UPPER_TERM] = { "expected a closing delimiter for the `%I` list", PM_ERROR_DEFAULT }, - [PM_ERR_LIST_W_LOWER_ELEMENT] = { "expected a string in a `%w` list", PM_ERROR_DEFAULT }, - [PM_ERR_LIST_W_LOWER_TERM] = { "expected a closing delimiter for the `%w` list", PM_ERROR_DEFAULT }, - [PM_ERR_LIST_W_UPPER_ELEMENT] = { "expected a string in a `%W` list", PM_ERROR_DEFAULT }, - [PM_ERR_LIST_W_UPPER_TERM] = { "expected a closing delimiter for the `%W` list", PM_ERROR_DEFAULT }, - [PM_ERR_MALLOC_FAILED] = { "failed to allocate memory", PM_ERROR_DEFAULT }, - [PM_ERR_MIXED_ENCODING] = { "UTF-8 mixed within %s source", PM_ERROR_DEFAULT }, - [PM_ERR_MODULE_IN_METHOD] = { "unexpected module definition in a method definition", PM_ERROR_DEFAULT }, - [PM_ERR_MODULE_NAME] = { "expected a constant name after `module`", PM_ERROR_DEFAULT }, - [PM_ERR_MODULE_TERM] = { "expected an `end` to close the `module` statement", PM_ERROR_DEFAULT }, - [PM_ERR_MULTI_ASSIGN_MULTI_SPLATS] = { "multiple splats in multiple assignment", PM_ERROR_DEFAULT }, - [PM_ERR_NOT_EXPRESSION] = { "expected an expression after `not`", PM_ERROR_DEFAULT }, - [PM_ERR_NO_LOCAL_VARIABLE] = { "%.*s: no such local variable", PM_ERROR_DEFAULT }, - [PM_ERR_NUMBER_LITERAL_UNDERSCORE] = { "number literal ending with a `_`", PM_ERROR_DEFAULT }, - [PM_ERR_NUMBERED_PARAMETER_NOT_ALLOWED] = { "numbered parameters are not allowed when an ordinary parameter is defined", PM_ERROR_DEFAULT }, - [PM_ERR_NUMBERED_PARAMETER_OUTER_SCOPE] = { "numbered parameter is already used in outer scope", PM_ERROR_DEFAULT }, - [PM_ERR_OPERATOR_MULTI_ASSIGN] = { "unexpected operator for a multiple assignment", PM_ERROR_DEFAULT }, - [PM_ERR_OPERATOR_WRITE_ARGUMENTS] = { "unexpected operator after a call with arguments", PM_ERROR_DEFAULT }, - [PM_ERR_OPERATOR_WRITE_BLOCK] = { "unexpected operator after a call with a block", PM_ERROR_DEFAULT }, - [PM_ERR_PARAMETER_ASSOC_SPLAT_MULTI] = { "unexpected multiple `**` splat parameters", PM_ERROR_DEFAULT }, - [PM_ERR_PARAMETER_BLOCK_MULTI] = { "multiple block parameters; only one block is allowed", PM_ERROR_DEFAULT }, - [PM_ERR_PARAMETER_CIRCULAR] = { "parameter default value references itself", PM_ERROR_DEFAULT }, - [PM_ERR_PARAMETER_METHOD_NAME] = { "unexpected name for a parameter", PM_ERROR_DEFAULT }, - [PM_ERR_PARAMETER_NAME_REPEAT] = { "repeated parameter name", PM_ERROR_DEFAULT }, - [PM_ERR_PARAMETER_NO_DEFAULT] = { "expected a default value for the parameter", PM_ERROR_DEFAULT }, - [PM_ERR_PARAMETER_NO_DEFAULT_KW] = { "expected a default value for the keyword parameter", PM_ERROR_DEFAULT }, - [PM_ERR_PARAMETER_NUMBERED_RESERVED] = { "%.2s is reserved for numbered parameters", PM_ERROR_DEFAULT }, - [PM_ERR_PARAMETER_ORDER] = { "unexpected parameter order", PM_ERROR_DEFAULT }, - [PM_ERR_PARAMETER_SPLAT_MULTI] = { "unexpected multiple `*` splat parameters", PM_ERROR_DEFAULT }, - [PM_ERR_PARAMETER_STAR] = { "unexpected parameter `*`", PM_ERROR_DEFAULT }, - [PM_ERR_PARAMETER_UNEXPECTED_FWD] = { "unexpected `...` in parameters", PM_ERROR_DEFAULT }, - [PM_ERR_PARAMETER_WILD_LOOSE_COMMA] = { "unexpected `,` in parameters", PM_ERROR_DEFAULT }, - [PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET] = { "expected a pattern expression after the `[` operator", PM_ERROR_DEFAULT }, - [PM_ERR_PATTERN_EXPRESSION_AFTER_COMMA] = { "expected a pattern expression after `,`", PM_ERROR_DEFAULT }, - [PM_ERR_PATTERN_EXPRESSION_AFTER_HROCKET] = { "expected a pattern expression after `=>`", PM_ERROR_DEFAULT }, - [PM_ERR_PATTERN_EXPRESSION_AFTER_IN] = { "expected a pattern expression after the `in` keyword", PM_ERROR_DEFAULT }, - [PM_ERR_PATTERN_EXPRESSION_AFTER_KEY] = { "expected a pattern expression after the key", PM_ERROR_DEFAULT }, - [PM_ERR_PATTERN_EXPRESSION_AFTER_PAREN] = { "expected a pattern expression after the `(` operator", PM_ERROR_DEFAULT }, - [PM_ERR_PATTERN_EXPRESSION_AFTER_PIN] = { "expected a pattern expression after the `^` pin operator", PM_ERROR_DEFAULT }, - [PM_ERR_PATTERN_EXPRESSION_AFTER_PIPE] = { "expected a pattern expression after the `|` operator", PM_ERROR_DEFAULT }, - [PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE] = { "expected a pattern expression after the range operator", PM_ERROR_DEFAULT }, - [PM_ERR_PATTERN_EXPRESSION_AFTER_REST] = { "unexpected pattern expression after the `**` expression", PM_ERROR_DEFAULT }, - [PM_ERR_PATTERN_HASH_KEY] = { "expected a key in the hash pattern", PM_ERROR_DEFAULT }, - [PM_ERR_PATTERN_HASH_KEY_LABEL] = { "expected a label as the key in the hash pattern", PM_ERROR_DEFAULT }, // TODO // THIS // AND // ABOVE // IS WEIRD - [PM_ERR_PATTERN_IDENT_AFTER_HROCKET] = { "expected an identifier after the `=>` operator", PM_ERROR_DEFAULT }, - [PM_ERR_PATTERN_LABEL_AFTER_COMMA] = { "expected a label after the `,` in the hash pattern", PM_ERROR_DEFAULT }, - [PM_ERR_PATTERN_REST] = { "unexpected rest pattern", PM_ERROR_DEFAULT }, - [PM_ERR_PATTERN_TERM_BRACE] = { "expected a `}` to close the pattern expression", PM_ERROR_DEFAULT }, - [PM_ERR_PATTERN_TERM_BRACKET] = { "expected a `]` to close the pattern expression", PM_ERROR_DEFAULT }, - [PM_ERR_PATTERN_TERM_PAREN] = { "expected a `)` to close the pattern expression", PM_ERROR_DEFAULT }, - [PM_ERR_PIPEPIPEEQ_MULTI_ASSIGN] = { "unexpected `||=` in a multiple assignment", PM_ERROR_DEFAULT }, - [PM_ERR_REGEXP_TERM] = { "expected a closing delimiter for the regular expression", PM_ERROR_DEFAULT }, - [PM_ERR_RESCUE_EXPRESSION] = { "expected a rescued expression", PM_ERROR_DEFAULT }, - [PM_ERR_RESCUE_MODIFIER_VALUE] = { "expected a value after the `rescue` modifier", PM_ERROR_DEFAULT }, - [PM_ERR_RESCUE_TERM] = { "expected a closing delimiter for the `rescue` clause", PM_ERROR_DEFAULT }, - [PM_ERR_RESCUE_VARIABLE] = { "expected an exception variable after `=>` in a rescue statement", PM_ERROR_DEFAULT }, - [PM_ERR_RETURN_INVALID] = { "invalid `return` in a class or module body", PM_ERROR_DEFAULT }, - [PM_ERR_STATEMENT_ALIAS] = { "unexpected an `alias` at a non-statement position", PM_ERROR_DEFAULT }, - [PM_ERR_STATEMENT_POSTEXE_END] = { "unexpected an `END` at a non-statement position", PM_ERROR_DEFAULT }, - [PM_ERR_STATEMENT_PREEXE_BEGIN] = { "unexpected a `BEGIN` at a non-statement position", PM_ERROR_DEFAULT }, - [PM_ERR_STATEMENT_UNDEF] = { "unexpected an `undef` at a non-statement position", PM_ERROR_DEFAULT }, - [PM_ERR_STRING_CONCATENATION] = { "expected a string for concatenation", PM_ERROR_DEFAULT }, - [PM_ERR_STRING_INTERPOLATED_TERM] = { "expected a closing delimiter for the interpolated string", PM_ERROR_DEFAULT }, - [PM_ERR_STRING_LITERAL_TERM] = { "expected a closing delimiter for the string literal", PM_ERROR_DEFAULT }, - [PM_ERR_SYMBOL_INVALID] = { "invalid symbol", PM_ERROR_DEFAULT }, // TODO expected symbol? prism.c ~9719 - [PM_ERR_SYMBOL_TERM_DYNAMIC] = { "expected a closing delimiter for the dynamic symbol", PM_ERROR_DEFAULT }, - [PM_ERR_SYMBOL_TERM_INTERPOLATED] = { "expected a closing delimiter for the interpolated symbol", PM_ERROR_DEFAULT }, - [PM_ERR_TERNARY_COLON] = { "expected a `:` after the true expression of a ternary operator", PM_ERROR_DEFAULT }, - [PM_ERR_TERNARY_EXPRESSION_FALSE] = { "expected an expression after `:` in the ternary operator", PM_ERROR_DEFAULT }, - [PM_ERR_TERNARY_EXPRESSION_TRUE] = { "expected an expression after `?` in the ternary operator", PM_ERROR_DEFAULT }, - [PM_ERR_UNDEF_ARGUMENT] = { "invalid argument being passed to `undef`; expected a bare word, constant, or symbol argument", PM_ERROR_DEFAULT }, - [PM_ERR_UNARY_RECEIVER_BANG] = { "expected a receiver for unary `!`", PM_ERROR_DEFAULT }, - [PM_ERR_UNARY_RECEIVER_MINUS] = { "expected a receiver for unary `-`", PM_ERROR_DEFAULT }, - [PM_ERR_UNARY_RECEIVER_PLUS] = { "expected a receiver for unary `+`", PM_ERROR_DEFAULT }, - [PM_ERR_UNARY_RECEIVER_TILDE] = { "expected a receiver for unary `~`", PM_ERROR_DEFAULT }, - [PM_ERR_UNTIL_TERM] = { "expected an `end` to close the `until` statement", PM_ERROR_DEFAULT }, - [PM_ERR_VOID_EXPRESSION] = { "unexpected void value expression", PM_ERROR_DEFAULT }, - [PM_ERR_WHILE_TERM] = { "expected an `end` to close the `while` statement", PM_ERROR_DEFAULT }, - [PM_ERR_WRITE_TARGET_IN_METHOD] = { "dynamic constant assignment", PM_ERROR_DEFAULT }, - [PM_ERR_WRITE_TARGET_READONLY] = { "immutable variable as a write target", PM_ERROR_DEFAULT }, - [PM_ERR_WRITE_TARGET_UNEXPECTED] = { "unexpected write target", PM_ERROR_DEFAULT }, - [PM_ERR_XSTRING_TERM] = { "expected a closing delimiter for the `%x` or backtick string", PM_ERROR_DEFAULT }, + [PM_ERR_ALIAS_ARGUMENT] = { "invalid argument being passed to `alias`; expected a bare word, symbol, constant, or global variable", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_AMPAMPEQ_MULTI_ASSIGN] = { "unexpected `&&=` in a multiple assignment", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ARGUMENT_AFTER_BLOCK] = { "unexpected argument after a block argument", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ARGUMENT_AFTER_FORWARDING_ELLIPSES] = { "unexpected argument after `...`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ARGUMENT_BARE_HASH] = { "unexpected bare hash argument", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ARGUMENT_BLOCK_FORWARDING] = { "both a block argument and a forwarding argument; only one block is allowed", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ARGUMENT_BLOCK_MULTI] = { "multiple block arguments; only one block is allowed", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ARGUMENT_FORMAL_CLASS] = { "invalid formal argument; formal argument cannot be a class variable", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ARGUMENT_FORMAL_CONSTANT] = { "invalid formal argument; formal argument cannot be a constant", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ARGUMENT_FORMAL_GLOBAL] = { "invalid formal argument; formal argument cannot be a global variable", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ARGUMENT_FORMAL_IVAR] = { "invalid formal argument; formal argument cannot be an instance variable", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ARGUMENT_FORWARDING_UNBOUND] = { "unexpected `...` in an non-parenthesized call", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ARGUMENT_IN] = { "unexpected `in` keyword in arguments", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ARGUMENT_NO_FORWARDING_AMP] = { "unexpected `&` when the parent method is not forwarding", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES] = { "unexpected `...` when the parent method is not forwarding", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ARGUMENT_NO_FORWARDING_STAR] = { "unexpected `*` when the parent method is not forwarding", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT] = { "unexpected `*` splat argument after a `**` keyword splat argument", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ARGUMENT_SPLAT_AFTER_SPLAT] = { "unexpected `*` splat argument after a `*` splat argument", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ARGUMENT_TERM_PAREN] = { "expected a `)` to close the arguments", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ARGUMENT_UNEXPECTED_BLOCK] = { "unexpected `{` after a method call without parenthesis", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ARRAY_ELEMENT] = { "expected an element for the array", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ARRAY_EXPRESSION] = { "expected an expression for the array element", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ARRAY_EXPRESSION_AFTER_STAR] = { "expected an expression after `*` in the array", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ARRAY_SEPARATOR] = { "expected a `,` separator for the array elements", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ARRAY_TERM] = { "expected a `]` to close the array", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_BEGIN_LONELY_ELSE] = { "unexpected `else` in `begin` block; a `rescue` clause must precede `else`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_BEGIN_TERM] = { "expected an `end` to close the `begin` statement", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_BEGIN_UPCASE_BRACE] = { "expected a `{` after `BEGIN`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_BEGIN_UPCASE_TERM] = { "expected a `}` to close the `BEGIN` statement", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_BEGIN_UPCASE_TOPLEVEL] = { "BEGIN is permitted only at toplevel", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_BLOCK_PARAM_LOCAL_VARIABLE] = { "expected a local variable name in the block parameters", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_BLOCK_PARAM_PIPE_TERM] = { "expected the block parameters to end with `|`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_BLOCK_TERM_BRACE] = { "expected a block beginning with `{` to end with `}`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_BLOCK_TERM_END] = { "expected a block beginning with `do` to end with `end`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_CANNOT_PARSE_EXPRESSION] = { "cannot parse the expression", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_CANNOT_PARSE_STRING_PART] = { "cannot parse the string part", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_CASE_EXPRESSION_AFTER_CASE] = { "expected an expression after `case`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_CASE_EXPRESSION_AFTER_WHEN] = { "expected an expression after `when`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_CASE_MATCH_MISSING_PREDICATE] = { "expected a predicate for a case matching statement", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_CASE_MISSING_CONDITIONS] = { "expected a `when` or `in` clause after `case`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_CASE_TERM] = { "expected an `end` to close the `case` statement", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_CLASS_IN_METHOD] = { "unexpected class definition in a method definition", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_CLASS_NAME] = { "expected a constant name after `class`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_CLASS_SUPERCLASS] = { "expected a superclass after `<`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_CLASS_TERM] = { "expected an `end` to close the `class` statement", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_CLASS_UNEXPECTED_END] = { "unexpected `end`, expecting ';' or '\\n'", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_CONDITIONAL_ELSIF_PREDICATE] = { "expected a predicate expression for the `elsif` statement", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_CONDITIONAL_IF_PREDICATE] = { "expected a predicate expression for the `if` statement", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_CONDITIONAL_PREDICATE_TERM] = { "expected `then` or `;` or '\\n'", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_CONDITIONAL_TERM] = { "expected an `end` to close the conditional clause", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_CONDITIONAL_TERM_ELSE] = { "expected an `end` to close the `else` clause", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_CONDITIONAL_UNLESS_PREDICATE] = { "expected a predicate expression for the `unless` statement", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_CONDITIONAL_UNTIL_PREDICATE] = { "expected a predicate expression for the `until` statement", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_CONDITIONAL_WHILE_PREDICATE] = { "expected a predicate expression for the `while` statement", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT] = { "expected a constant after the `::` operator", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_DEF_ENDLESS] = { "could not parse the endless method body", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_DEF_ENDLESS_SETTER] = { "invalid method name; a setter method cannot be defined in an endless method definition", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_DEF_NAME] = { "expected a method name", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_DEF_NAME_AFTER_RECEIVER] = { "expected a method name after the receiver", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_DEF_PARAMS_TERM] = { "expected a delimiter to close the parameters", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_DEF_PARAMS_TERM_PAREN] = { "expected a `)` to close the parameters", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_DEF_RECEIVER] = { "expected a receiver for the method definition", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_DEF_RECEIVER_TERM] = { "expected a `.` or `::` after the receiver in a method definition", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_DEF_TERM] = { "expected an `end` to close the `def` statement", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_DEFINED_EXPRESSION] = { "expected an expression after `defined?`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_EMBDOC_TERM] = { "could not find a terminator for the embedded document", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_EMBEXPR_END] = { "expected a `}` to close the embedded expression", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_EMBVAR_INVALID] = { "invalid embedded variable", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_END_UPCASE_BRACE] = { "expected a `{` after `END`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_END_UPCASE_TERM] = { "expected a `}` to close the `END` statement", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ESCAPE_INVALID_CONTROL] = { "invalid control escape sequence", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ESCAPE_INVALID_CONTROL_REPEAT] = { "invalid control escape sequence; control cannot be repeated", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ESCAPE_INVALID_HEXADECIMAL] = { "invalid hexadecimal escape sequence", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ESCAPE_INVALID_META] = { "invalid meta escape sequence", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ESCAPE_INVALID_META_REPEAT] = { "invalid meta escape sequence; meta cannot be repeated", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ESCAPE_INVALID_UNICODE] = { "invalid Unicode escape sequence", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ESCAPE_INVALID_UNICODE_CM_FLAGS] = { "invalid Unicode escape sequence; Unicode cannot be combined with control or meta flags", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ESCAPE_INVALID_UNICODE_LITERAL] = { "invalid Unicode escape sequence; multiple codepoints are not allowed in a character literal", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ESCAPE_INVALID_UNICODE_LONG] = { "invalid Unicode escape sequence; maximum length is 6 digits", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_ESCAPE_INVALID_UNICODE_TERM] = { "invalid Unicode escape sequence; needs closing `}`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_EXPECT_ARGUMENT] = { "expected an argument", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_EXPECT_EOL_AFTER_STATEMENT] = { "expected a newline or semicolon after the statement", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ] = { "expected an expression after `&&=`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ] = { "expected an expression after `||=`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA] = { "expected an expression after `,`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL] = { "expected an expression after `=`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_EXPECT_EXPRESSION_AFTER_LESS_LESS] = { "expected an expression after `<<`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_EXPECT_EXPRESSION_AFTER_LPAREN] = { "expected an expression after `(`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR] = { "expected an expression after the operator", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT] = { "expected an expression after `*` splat in an argument", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH] = { "expected an expression after `**` in a hash", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_EXPECT_EXPRESSION_AFTER_STAR] = { "expected an expression after `*`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_EXPECT_IDENT_REQ_PARAMETER] = { "expected an identifier for the required parameter", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_EXPECT_LPAREN_REQ_PARAMETER] = { "expected a `(` to start a required parameter", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_EXPECT_RBRACKET] = { "expected a matching `]`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_EXPECT_RPAREN] = { "expected a matching `)`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_EXPECT_RPAREN_AFTER_MULTI] = { "expected a `)` after multiple assignment", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_EXPECT_RPAREN_REQ_PARAMETER] = { "expected a `)` to end a required parameter", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_EXPECT_STRING_CONTENT] = { "expected string content after opening string delimiter", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_EXPECT_WHEN_DELIMITER] = { "expected a delimiter after the predicates of a `when` clause", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_EXPRESSION_BARE_HASH] = { "unexpected bare hash in expression", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_FOR_COLLECTION] = { "expected a collection after the `in` in a `for` statement", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_FOR_INDEX] = { "expected an index after `for`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_FOR_IN] = { "expected an `in` after the index in a `for` statement", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_FOR_TERM] = { "expected an `end` to close the `for` loop", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_HASH_EXPRESSION_AFTER_LABEL] = { "expected an expression after the label in a hash", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_HASH_KEY] = { "expected a key in the hash literal", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_HASH_ROCKET] = { "expected a `=>` between the hash key and value", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_HASH_TERM] = { "expected a `}` to close the hash literal", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_HASH_VALUE] = { "expected a value in the hash literal", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_HEREDOC_TERM] = { "could not find a terminator for the heredoc", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_INCOMPLETE_QUESTION_MARK] = { "incomplete expression at `?`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_INCOMPLETE_VARIABLE_CLASS] = { "incomplete class variable", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_INCOMPLETE_VARIABLE_INSTANCE] = { "incomplete instance variable", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_INVALID_ENCODING_MAGIC_COMMENT] = { "unknown or invalid encoding in the magic comment", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_INVALID_FLOAT_EXPONENT] = { "invalid exponent", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_INVALID_NUMBER_BINARY] = { "invalid binary number", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_INVALID_NUMBER_DECIMAL] = { "invalid decimal number", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_INVALID_NUMBER_HEXADECIMAL] = { "invalid hexadecimal number", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_INVALID_NUMBER_OCTAL] = { "invalid octal number", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_INVALID_NUMBER_UNDERSCORE] = { "invalid underscore placement in number", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_INVALID_PERCENT] = { "invalid `%` token", PM_ERROR_LEVEL_FATAL }, // TODO WHAT? + [PM_ERR_INVALID_TOKEN] = { "invalid token", PM_ERROR_LEVEL_FATAL }, // TODO WHAT? + [PM_ERR_INVALID_VARIABLE_GLOBAL] = { "invalid global variable", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_IT_NOT_ALLOWED] = { "`it` is not allowed when an ordinary parameter is defined", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_LAMBDA_OPEN] = { "expected a `do` keyword or a `{` to open the lambda block", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_LAMBDA_TERM_BRACE] = { "expected a lambda block beginning with `{` to end with `}`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_LAMBDA_TERM_END] = { "expected a lambda block beginning with `do` to end with `end`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_LIST_I_LOWER_ELEMENT] = { "expected a symbol in a `%i` list", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_LIST_I_LOWER_TERM] = { "expected a closing delimiter for the `%i` list", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_LIST_I_UPPER_ELEMENT] = { "expected a symbol in a `%I` list", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_LIST_I_UPPER_TERM] = { "expected a closing delimiter for the `%I` list", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_LIST_W_LOWER_ELEMENT] = { "expected a string in a `%w` list", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_LIST_W_LOWER_TERM] = { "expected a closing delimiter for the `%w` list", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_LIST_W_UPPER_ELEMENT] = { "expected a string in a `%W` list", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_LIST_W_UPPER_TERM] = { "expected a closing delimiter for the `%W` list", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_MALLOC_FAILED] = { "failed to allocate memory", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_MIXED_ENCODING] = { "UTF-8 mixed within %s source", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_MODULE_IN_METHOD] = { "unexpected module definition in a method definition", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_MODULE_NAME] = { "expected a constant name after `module`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_MODULE_TERM] = { "expected an `end` to close the `module` statement", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_MULTI_ASSIGN_MULTI_SPLATS] = { "multiple splats in multiple assignment", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_NOT_EXPRESSION] = { "expected an expression after `not`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_NO_LOCAL_VARIABLE] = { "%.*s: no such local variable", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_NUMBER_LITERAL_UNDERSCORE] = { "number literal ending with a `_`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_NUMBERED_PARAMETER_NOT_ALLOWED] = { "numbered parameters are not allowed when an ordinary parameter is defined", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_NUMBERED_PARAMETER_OUTER_SCOPE] = { "numbered parameter is already used in outer scope", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_OPERATOR_MULTI_ASSIGN] = { "unexpected operator for a multiple assignment", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_OPERATOR_WRITE_ARGUMENTS] = { "unexpected operator after a call with arguments", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_OPERATOR_WRITE_BLOCK] = { "unexpected operator after a call with a block", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PARAMETER_ASSOC_SPLAT_MULTI] = { "unexpected multiple `**` splat parameters", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PARAMETER_BLOCK_MULTI] = { "multiple block parameters; only one block is allowed", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PARAMETER_CIRCULAR] = { "parameter default value references itself", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PARAMETER_METHOD_NAME] = { "unexpected name for a parameter", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PARAMETER_NAME_REPEAT] = { "repeated parameter name", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PARAMETER_NO_DEFAULT] = { "expected a default value for the parameter", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PARAMETER_NO_DEFAULT_KW] = { "expected a default value for the keyword parameter", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PARAMETER_NUMBERED_RESERVED] = { "%.2s is reserved for numbered parameters", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PARAMETER_ORDER] = { "unexpected parameter order", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PARAMETER_SPLAT_MULTI] = { "unexpected multiple `*` splat parameters", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PARAMETER_STAR] = { "unexpected parameter `*`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PARAMETER_UNEXPECTED_FWD] = { "unexpected `...` in parameters", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PARAMETER_WILD_LOOSE_COMMA] = { "unexpected `,` in parameters", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET] = { "expected a pattern expression after the `[` operator", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PATTERN_EXPRESSION_AFTER_COMMA] = { "expected a pattern expression after `,`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PATTERN_EXPRESSION_AFTER_HROCKET] = { "expected a pattern expression after `=>`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PATTERN_EXPRESSION_AFTER_IN] = { "expected a pattern expression after the `in` keyword", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PATTERN_EXPRESSION_AFTER_KEY] = { "expected a pattern expression after the key", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PATTERN_EXPRESSION_AFTER_PAREN] = { "expected a pattern expression after the `(` operator", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PATTERN_EXPRESSION_AFTER_PIN] = { "expected a pattern expression after the `^` pin operator", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PATTERN_EXPRESSION_AFTER_PIPE] = { "expected a pattern expression after the `|` operator", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE] = { "expected a pattern expression after the range operator", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PATTERN_EXPRESSION_AFTER_REST] = { "unexpected pattern expression after the `**` expression", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PATTERN_HASH_KEY] = { "expected a key in the hash pattern", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PATTERN_HASH_KEY_LABEL] = { "expected a label as the key in the hash pattern", PM_ERROR_LEVEL_FATAL }, // TODO // THIS // AND // ABOVE // IS WEIRD + [PM_ERR_PATTERN_IDENT_AFTER_HROCKET] = { "expected an identifier after the `=>` operator", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PATTERN_LABEL_AFTER_COMMA] = { "expected a label after the `,` in the hash pattern", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PATTERN_REST] = { "unexpected rest pattern", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PATTERN_TERM_BRACE] = { "expected a `}` to close the pattern expression", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PATTERN_TERM_BRACKET] = { "expected a `]` to close the pattern expression", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PATTERN_TERM_PAREN] = { "expected a `)` to close the pattern expression", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_PIPEPIPEEQ_MULTI_ASSIGN] = { "unexpected `||=` in a multiple assignment", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_REGEXP_TERM] = { "expected a closing delimiter for the regular expression", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_RESCUE_EXPRESSION] = { "expected a rescued expression", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_RESCUE_MODIFIER_VALUE] = { "expected a value after the `rescue` modifier", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_RESCUE_TERM] = { "expected a closing delimiter for the `rescue` clause", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_RESCUE_VARIABLE] = { "expected an exception variable after `=>` in a rescue statement", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_RETURN_INVALID] = { "invalid `return` in a class or module body", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_STATEMENT_ALIAS] = { "unexpected an `alias` at a non-statement position", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_STATEMENT_POSTEXE_END] = { "unexpected an `END` at a non-statement position", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_STATEMENT_PREEXE_BEGIN] = { "unexpected a `BEGIN` at a non-statement position", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_STATEMENT_UNDEF] = { "unexpected an `undef` at a non-statement position", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_STRING_CONCATENATION] = { "expected a string for concatenation", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_STRING_INTERPOLATED_TERM] = { "expected a closing delimiter for the interpolated string", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_STRING_LITERAL_TERM] = { "expected a closing delimiter for the string literal", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_SYMBOL_INVALID] = { "invalid symbol", PM_ERROR_LEVEL_FATAL }, // TODO expected symbol? prism.c ~9719 + [PM_ERR_SYMBOL_TERM_DYNAMIC] = { "expected a closing delimiter for the dynamic symbol", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_SYMBOL_TERM_INTERPOLATED] = { "expected a closing delimiter for the interpolated symbol", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_TERNARY_COLON] = { "expected a `:` after the true expression of a ternary operator", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_TERNARY_EXPRESSION_FALSE] = { "expected an expression after `:` in the ternary operator", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_TERNARY_EXPRESSION_TRUE] = { "expected an expression after `?` in the ternary operator", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_UNDEF_ARGUMENT] = { "invalid argument being passed to `undef`; expected a bare word, constant, or symbol argument", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_UNARY_RECEIVER_BANG] = { "expected a receiver for unary `!`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_UNARY_RECEIVER_MINUS] = { "expected a receiver for unary `-`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_UNARY_RECEIVER_PLUS] = { "expected a receiver for unary `+`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_UNARY_RECEIVER_TILDE] = { "expected a receiver for unary `~`", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_UNTIL_TERM] = { "expected an `end` to close the `until` statement", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_VOID_EXPRESSION] = { "unexpected void value expression", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_WHILE_TERM] = { "expected an `end` to close the `while` statement", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_WRITE_TARGET_IN_METHOD] = { "dynamic constant assignment", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_WRITE_TARGET_READONLY] = { "immutable variable as a write target", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_WRITE_TARGET_UNEXPECTED] = { "unexpected write target", PM_ERROR_LEVEL_FATAL }, + [PM_ERR_XSTRING_TERM] = { "expected a closing delimiter for the `%x` or backtick string", PM_ERROR_LEVEL_FATAL }, + // Warnings - [PM_WARN_AMBIGUOUS_FIRST_ARGUMENT_MINUS] = { "ambiguous first argument; put parentheses or a space even after `-` operator", PM_WARNING_VERBOSE_TRUE }, - [PM_WARN_AMBIGUOUS_FIRST_ARGUMENT_PLUS] = { "ambiguous first argument; put parentheses or a space even after `+` operator", PM_WARNING_VERBOSE_TRUE }, - [PM_WARN_AMBIGUOUS_PREFIX_STAR] = { "ambiguous `*` has been interpreted as an argument prefix", PM_WARNING_VERBOSE_TRUE }, - [PM_WARN_AMBIGUOUS_SLASH] = { "ambiguous `/`; wrap regexp in parentheses or add a space after `/` operator", PM_WARNING_VERBOSE_TRUE }, - [PM_WARN_END_IN_METHOD] = { "END in method; use at_exit", PM_WARNING_VERBOSE_NOT_NIL }, + [PM_WARN_AMBIGUOUS_FIRST_ARGUMENT_MINUS] = { "ambiguous first argument; put parentheses or a space even after `-` operator", PM_WARNING_LEVEL_VERBOSE }, + [PM_WARN_AMBIGUOUS_FIRST_ARGUMENT_PLUS] = { "ambiguous first argument; put parentheses or a space even after `+` operator", PM_WARNING_LEVEL_VERBOSE }, + [PM_WARN_AMBIGUOUS_PREFIX_STAR] = { "ambiguous `*` has been interpreted as an argument prefix", PM_WARNING_LEVEL_VERBOSE }, + [PM_WARN_AMBIGUOUS_SLASH] = { "ambiguous `/`; wrap regexp in parentheses or add a space after `/` operator", PM_WARNING_LEVEL_VERBOSE }, + [PM_WARN_END_IN_METHOD] = { "END in method; use at_exit", PM_WARNING_LEVEL_DEFAULT }, }; -static const char* +static inline const char * pm_diagnostic_message(pm_diagnostic_id_t diag_id) { assert(diag_id < PM_DIAGNOSTIC_ID_LEN); @@ -299,7 +304,7 @@ pm_diagnostic_message(pm_diagnostic_id_t diag_id) { return message; } -static uint8_t +static inline uint8_t pm_diagnostic_level(pm_diagnostic_id_t diag_id) { assert(diag_id < PM_DIAGNOSTIC_ID_LEN); diff --git a/prism/diagnostic.h b/prism/diagnostic.h index 19395176ac4f00..9b600208aeacec 100644 --- a/prism/diagnostic.h +++ b/prism/diagnostic.h @@ -15,16 +15,22 @@ #include /** - * This enum represents the level of diagnostics generated during parsing. + * The levels of errors generated during parsing. + */ +typedef enum { + /** For errors that cannot be recovered from. */ + PM_ERROR_LEVEL_FATAL = 0 +} pm_error_level_t; + +/** + * The levels of warnings generated during parsing. */ typedef enum { - /** The default level for errors. */ - PM_ERROR_DEFAULT = 0, /** For warnings which should be emitted if $VERBOSE != nil. */ - PM_WARNING_VERBOSE_NOT_NIL = 1, + PM_WARNING_LEVEL_DEFAULT = 0, /** For warnings which should be emitted if $VERBOSE == true. */ - PM_WARNING_VERBOSE_TRUE = 2 -} pm_diagnostic_level_t; + PM_WARNING_LEVEL_VERBOSE = 1 +} pm_warning_level_t; /** * This struct represents a diagnostic generated during parsing. @@ -48,7 +54,10 @@ typedef struct { */ bool owned; - /** The level of the diagnostic, see pm_diagnostic_level_t for possible values. */ + /** + * The level of the diagnostic, see `pm_error_level_t` and + * `pm_warning_level_t` for possible values. + */ uint8_t level; } pm_diagnostic_t; diff --git a/prism/extension.c b/prism/extension.c index 72be59bc6d83d4..7467aa5709bb2b 100644 --- a/prism/extension.c +++ b/prism/extension.c @@ -368,19 +368,6 @@ parser_magic_comments(pm_parser_t *parser, VALUE source) { return magic_comments; } -static VALUE get_diagnostic_level_symbol(uint8_t level) { - switch (level) { - case 0: - return ID2SYM(rb_intern("error_default")); - case 1: - return ID2SYM(rb_intern("warning_verbose_not_nil")); - case 2: - return ID2SYM(rb_intern("warning_verbose_true")); - default: - rb_raise(rb_eRuntimeError, "Unknown level: %" PRIu8, level); - } -} - /** * Extract out the data location from the parser into a Location instance if one * exists. @@ -415,10 +402,19 @@ parser_errors(pm_parser_t *parser, rb_encoding *encoding, VALUE source) { LONG2FIX(error->location.end - error->location.start) }; + VALUE level = Qnil; + switch (error->level) { + case PM_ERROR_LEVEL_FATAL: + level = ID2SYM(rb_intern("fatal")); + break; + default: + rb_raise(rb_eRuntimeError, "Unknown level: %" PRIu8, error->level); + } + VALUE error_argv[] = { rb_enc_str_new_cstr(error->message, encoding), rb_class_new_instance(3, location_argv, rb_cPrismLocation), - get_diagnostic_level_symbol(error->level) + level }; rb_ary_push(errors, rb_class_new_instance(3, error_argv, rb_cPrismParseError)); @@ -442,10 +438,22 @@ parser_warnings(pm_parser_t *parser, rb_encoding *encoding, VALUE source) { LONG2FIX(warning->location.end - warning->location.start) }; + VALUE level = Qnil; + switch (warning->level) { + case PM_WARNING_LEVEL_DEFAULT: + level = ID2SYM(rb_intern("default")); + break; + case PM_WARNING_LEVEL_VERBOSE: + level = ID2SYM(rb_intern("verbose")); + break; + default: + rb_raise(rb_eRuntimeError, "Unknown level: %" PRIu8, warning->level); + } + VALUE warning_argv[] = { rb_enc_str_new_cstr(warning->message, encoding), rb_class_new_instance(3, location_argv, rb_cPrismLocation), - get_diagnostic_level_symbol(warning->level) + level }; rb_ary_push(warnings, rb_class_new_instance(3, warning_argv, rb_cPrismParseWarning)); diff --git a/prism/templates/lib/prism/serialize.rb.erb b/prism/templates/lib/prism/serialize.rb.erb index 35b5b4ddb0b5a6..62379fa149f9e5 100644 --- a/prism/templates/lib/prism/serialize.rb.erb +++ b/prism/templates/lib/prism/serialize.rb.erb @@ -96,8 +96,8 @@ module Prism comments = load_comments magic_comments = load_varuint.times.map { MagicComment.new(load_location, load_location) } data_loc = load_optional_location - errors = load_varuint.times.map { ParseError.new(load_embedded_string, load_location, load_diagnostic_level) } - warnings = load_varuint.times.map { ParseWarning.new(load_embedded_string, load_location, load_diagnostic_level) } + errors = load_varuint.times.map { ParseError.new(load_embedded_string, load_location, load_error_level) } + warnings = load_varuint.times.map { ParseWarning.new(load_embedded_string, load_location, load_warning_level) } [comments, magic_comments, data_loc, errors, warnings] end @@ -231,15 +231,25 @@ module Prism load_constant(index - 1) if index != 0 end - def load_diagnostic_level + def load_error_level level = io.getbyte + case level when 0 - :error_default + :fatal + else + raise "Unknown level: #{level}" + end + end + + def load_warning_level + level = io.getbyte + + case level + when 0 + :default when 1 - :warning_verbose_not_nil - when 2 - :warning_verbose_true + :verbose else raise "Unknown level: #{level}" end diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index b7215c755dfde1..2b45167bee7033 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -1874,11 +1874,11 @@ def test_upcase_end_in_def def test_warnings_verbosity warning = Prism.parse("def foo; END { }; end").warnings[0] assert_equal "END in method; use at_exit", warning.message - assert_equal :warning_verbose_not_nil, warning.level + assert_equal :default, warning.level warning = Prism.parse("foo /regexp/").warnings[0] assert_equal "ambiguous `/`; wrap regexp in parentheses or add a space after `/` operator", warning.message - assert_equal :warning_verbose_true, warning.level + assert_equal :verbose, warning.level end def test_statement_operators From 223910b329751fbee36efe66ccd544e66dbe90f8 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Fri, 26 Jan 2024 13:35:37 -0800 Subject: [PATCH 578/640] Reduce array allocations for literal arrays with splats and other args Previously, a literal array with a splat and any other args resulted in more than one array allocation: ```ruby [1, *a] [*a, 1] [*a, *a] [*a, 1, 2] [*a, a] [*a, 1, *a] [*a, 1, a] [*a, a, a] [*a, a, *a] [*a, 1, *a, 1] [*a, 1, *a, *a] [*a, a, *a, a] ``` This is because previously Ruby would use newarray and concatarray to create the array, which both each allocate an array internally. This changes the compilation to use concattoarray and pushtoarray, which do not allocate arrays. It also updates the peephole optimizer to optimize the duparray/concattoarray sequence to putobject/concattoarray, mirroring the existing duparray/concatarray optimization. These changes reduce the array allocations for the above examples to a single array allocation, except for: ``` [*a, 1, a] [*a, a, a] ``` The reason for this is because optimizing this case to only allocate 1 array requires changes to compile_array, which would currently conflict with an unmerged pull request (#9721). After that pull request is merged, it should be possible to refactor things to only allocate a 1 array for all literal arrays (or 2 for arrays with keyword splats). --- compile.c | 37 ++++++++++++------------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/compile.c b/compile.c index 71b657d9f2fcfb..4718ecc9e2b649 100644 --- a/compile.c +++ b/compile.c @@ -3377,15 +3377,15 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal /* * ... * duparray [...] - * concatarray + * concatarray | concattoarray * => * ... * putobject [...] - * concatarray + * concatarray | concattoarray */ if (IS_INSN_ID(iobj, duparray)) { LINK_ELEMENT *next = iobj->link.next; - if (IS_INSN(next) && IS_INSN_ID(next, concatarray)) { + if (IS_INSN(next) && (IS_INSN_ID(next, concatarray) || IS_INSN_ID(next, concattoarray))) { iobj->insn_id = BIN(putobject); } } @@ -4916,25 +4916,6 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop return 1; } -/* Compile an array containing the single element represented by node */ -static int -compile_array_1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node) -{ - if (static_literal_node_p(node, iseq, false)) { - VALUE ary = rb_ary_hidden_new(1); - rb_ary_push(ary, static_literal_value(node, iseq)); - OBJ_FREEZE(ary); - - ADD_INSN1(ret, node, duparray, ary); - } - else { - CHECK(COMPILE_(ret, "array element", node, FALSE)); - ADD_INSN1(ret, node, newarray, INT2FIX(1)); - } - - return 1; -} - static inline int static_literal_node_pair_p(const NODE *node, const rb_iseq_t *iseq) { @@ -10412,7 +10393,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no else { CHECK(COMPILE(ret, "argscat head", RNODE_ARGSCAT(node)->nd_head)); CHECK(COMPILE(ret, "argscat body", RNODE_ARGSCAT(node)->nd_body)); - ADD_INSN(ret, node, concatarray); + ADD_INSN(ret, node, concattoarray); } break; } @@ -10425,8 +10406,14 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no } else { CHECK(COMPILE(ret, "argspush head", RNODE_ARGSPUSH(node)->nd_head)); - CHECK(compile_array_1(iseq, ret, RNODE_ARGSPUSH(node)->nd_body)); - ADD_INSN(ret, node, concatarray); + const NODE *body_node = RNODE_ARGSPUSH(node)->nd_body; + if (static_literal_node_p(body_node, iseq, false)) { + ADD_INSN1(ret, body_node, putobject, static_literal_value(body_node, iseq)); + } + else { + CHECK(COMPILE_(ret, "array element", body_node, FALSE)); + } + ADD_INSN1(ret, node, pushtoarray, INT2FIX(1)); } break; } From f12ebe11888d9fdd121c98ca8a5155dc044f4cf4 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 10 Jan 2024 11:04:39 -0500 Subject: [PATCH 579/640] [ruby/prism] Add parser translation https://github.com/ruby/prism/commit/8cdec8070c --- lib/prism.rb | 1 + lib/prism/node_ext.rb | 2 +- lib/prism/prism.gemspec | 12 +- lib/prism/translation.rb | 11 + lib/prism/translation/parser.rb | 136 ++ lib/prism/translation/parser/compiler.rb | 1797 ++++++++++++++++++++++ lib/prism/translation/parser/lexer.rb | 335 ++++ lib/prism/translation/parser/rubocop.rb | 37 + test/prism/newline_test.rb | 2 +- test/prism/parser_test.rb | 188 +++ 10 files changed, 2516 insertions(+), 5 deletions(-) create mode 100644 lib/prism/translation.rb create mode 100644 lib/prism/translation/parser.rb create mode 100644 lib/prism/translation/parser/compiler.rb create mode 100644 lib/prism/translation/parser/lexer.rb create mode 100644 lib/prism/translation/parser/rubocop.rb create mode 100644 test/prism/parser_test.rb diff --git a/lib/prism.rb b/lib/prism.rb index e44d163d0265ca..5d78b42c4dc041 100644 --- a/lib/prism.rb +++ b/lib/prism.rb @@ -26,6 +26,7 @@ module Prism autoload :Pack, "prism/pack" autoload :Pattern, "prism/pattern" autoload :Serialize, "prism/serialize" + autoload :Translation, "prism/translation" autoload :Visitor, "prism/visitor" # Some of these constants are not meant to be exposed, so marking them as diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb index 1a78759e2ccfa9..f87714e552ba35 100644 --- a/lib/prism/node_ext.rb +++ b/lib/prism/node_ext.rb @@ -81,7 +81,7 @@ def value class RationalNode < Node # Returns the value of the node as a Ruby Rational. def value - Rational(numeric.is_a?(IntegerNode) && !numeric.decimal? ? numeric.value : slice.chomp("r")) + Rational(numeric.is_a?(IntegerNode) ? numeric.value : slice.chomp("r")) end end diff --git a/lib/prism/prism.gemspec b/lib/prism/prism.gemspec index f04aa253b69b6c..80d5abcaef0c85 100644 --- a/lib/prism/prism.gemspec +++ b/lib/prism/prism.gemspec @@ -31,6 +31,7 @@ Gem::Specification.new do |spec| "docs/javascript.md", "docs/local_variable_depth.md", "docs/mapping.md", + "docs/parser_translation.md", "docs/parsing_rules.md", "docs/releasing.md", "docs/ripper.md", @@ -74,16 +75,21 @@ Gem::Specification.new do |spec| "lib/prism/ffi.rb", "lib/prism/lex_compat.rb", "lib/prism/mutation_compiler.rb", - "lib/prism/node.rb", "lib/prism/node_ext.rb", "lib/prism/node_inspector.rb", + "lib/prism/node.rb", "lib/prism/pack.rb", "lib/prism/parse_result.rb", + "lib/prism/parse_result/comments.rb", + "lib/prism/parse_result/newlines.rb", "lib/prism/pattern.rb", "lib/prism/ripper_compat.rb", "lib/prism/serialize.rb", - "lib/prism/parse_result/comments.rb", - "lib/prism/parse_result/newlines.rb", + "lib/prism/translation.rb", + "lib/prism/translation/parser.rb", + "lib/prism/translation/parser/compiler.rb", + "lib/prism/translation/parser/lexer.rb", + "lib/prism/translation/parser/rubocop.rb", "lib/prism/visitor.rb", "src/diagnostic.c", "src/encoding.c", diff --git a/lib/prism/translation.rb b/lib/prism/translation.rb new file mode 100644 index 00000000000000..9a7cedac46a4ea --- /dev/null +++ b/lib/prism/translation.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Prism + # This module is responsible for converting the prism syntax tree into other + # syntax trees. At the moment it only supports converting to the + # whitequark/parser gem's syntax tree, but support is planned for the + # seattlerb/ruby_parser gem's syntax tree as well. + module Translation + autoload :Parser, "prism/translation/parser" + end +end diff --git a/lib/prism/translation/parser.rb b/lib/prism/translation/parser.rb new file mode 100644 index 00000000000000..7cc18ac5de32ed --- /dev/null +++ b/lib/prism/translation/parser.rb @@ -0,0 +1,136 @@ +# frozen_string_literal: true + +require "parser" + +module Prism + module Translation + # This class is the entry-point for converting a prism syntax tree into the + # whitequark/parser gem's syntax tree. It inherits from the base parser for + # the parser gem, and overrides the parse* methods to parse with prism and + # then translate. + class Parser < ::Parser::Base + Racc_debug_parser = false # :nodoc: + + def version # :nodoc: + 33 + end + + # The default encoding for Ruby files is UTF-8. + def default_encoding + Encoding::UTF_8 + end + + def yyerror # :nodoc: + end + + # Parses a source buffer and returns the AST. + def parse(source_buffer) + @source_buffer = source_buffer + source = source_buffer.source + + build_ast( + Prism.parse(source, filepath: source_buffer.name).value, + build_offset_cache(source) + ) + ensure + @source_buffer = nil + end + + # Parses a source buffer and returns the AST and the source code comments. + def parse_with_comments(source_buffer) + @source_buffer = source_buffer + source = source_buffer.source + + offset_cache = build_offset_cache(source) + result = Prism.parse(source, filepath: source_buffer.name) + + [ + build_ast(result.value, offset_cache), + build_comments(result.comments, offset_cache) + ] + ensure + @source_buffer = nil + end + + # Parses a source buffer and returns the AST, the source code comments, + # and the tokens emitted by the lexer. + def tokenize(source_buffer, _recover = false) + @source_buffer = source_buffer + source = source_buffer.source + + offset_cache = build_offset_cache(source) + result = Prism.parse_lex(source, filepath: source_buffer.name) + program, tokens = result.value + + [ + build_ast(program, offset_cache), + build_comments(result.comments, offset_cache), + build_tokens(tokens, offset_cache) + ] + ensure + @source_buffer = nil + end + + # Since prism resolves num params for us, we don't need to support this + # kind of logic here. + def try_declare_numparam(node) + node.children[0].match?(/\A_[1-9]\z/) + end + + private + + # Prism deals with offsets in bytes, while the parser gem deals with + # offsets in characters. We need to handle this conversion in order to + # build the parser gem AST. + # + # If the bytesize of the source is the same as the length, then we can + # just use the offset directly. Otherwise, we build a hash that functions + # as a cache for the conversion. + # + # This is a good opportunity for some optimizations. If the source file + # has any multi-byte characters, this can tank the performance of the + # translator. We could make this significantly faster by using a + # different data structure for the cache. + def build_offset_cache(source) + if source.bytesize == source.length + -> (offset) { offset } + else + Hash.new do |hash, offset| + hash[offset] = source.byteslice(0, offset).length + end + end + end + + # Build the parser gem AST from the prism AST. + def build_ast(program, offset_cache) + program.accept(Compiler.new(self, offset_cache)) + end + + # Build the parser gem comments from the prism comments. + def build_comments(comments, offset_cache) + comments.map do |comment| + location = comment.location + + ::Parser::Source::Comment.new( + ::Parser::Source::Range.new( + source_buffer, + offset_cache[location.start_offset], + offset_cache[location.end_offset] + ) + ) + end + end + + # Build the parser gem tokens from the prism tokens. + def build_tokens(tokens, offset_cache) + Lexer.new(source_buffer, tokens.map(&:first), offset_cache).to_a + end + + require_relative "parser/compiler" + require_relative "parser/lexer" + + private_constant :Compiler + private_constant :Lexer + end + end +end diff --git a/lib/prism/translation/parser/compiler.rb b/lib/prism/translation/parser/compiler.rb new file mode 100644 index 00000000000000..e4b4e8ad3a0e58 --- /dev/null +++ b/lib/prism/translation/parser/compiler.rb @@ -0,0 +1,1797 @@ +# frozen_string_literal: true + +module Prism + module Translation + class Parser + # A visitor that knows how to convert a prism syntax tree into the + # whitequark/parser gem's syntax tree. + class Compiler < ::Prism::Compiler + # Raised when the tree is malformed or there is a bug in the compiler. + class CompilationError < StandardError + end + + # The Parser::Base instance that is being used to build the AST. + attr_reader :parser + + # The Parser::Builders::Default instance that is being used to build the + # AST. + attr_reader :builder + + # The Parser::Source::Buffer instance that is holding a reference to the + # source code. + attr_reader :source_buffer + + # The offset cache that is used to map between byte and character + # offsets in the file. + attr_reader :offset_cache + + # The locals in the current scope. + attr_reader :locals + + # Whether or not the current node is in a destructure. + attr_reader :in_destructure + + # Whether or not the current node is in a pattern. + attr_reader :in_pattern + + # Initialize a new compiler with the given parser, offset cache, and + # options. + def initialize(parser, offset_cache, locals: nil, in_destructure: false, in_pattern: false) + @parser = parser + @builder = parser.builder + @source_buffer = parser.source_buffer + @offset_cache = offset_cache + + @locals = locals + @in_destructure = in_destructure + @in_pattern = in_pattern + end + + # alias foo bar + # ^^^^^^^^^^^^^ + def visit_alias_method_node(node) + builder.alias(token(node.keyword_loc), visit(node.new_name), visit(node.old_name)) + end + + # alias $foo $bar + # ^^^^^^^^^^^^^^^ + def visit_alias_global_variable_node(node) + builder.alias(token(node.keyword_loc), visit(node.new_name), visit(node.old_name)) + end + + # foo => bar | baz + # ^^^^^^^^^ + def visit_alternation_pattern_node(node) + builder.match_alt(visit(node.left), token(node.operator_loc), visit(node.right)) + end + + # a and b + # ^^^^^^^ + def visit_and_node(node) + builder.logical_op(:and, visit(node.left), token(node.operator_loc), visit(node.right)) + end + + # [] + # ^^ + def visit_array_node(node) + builder.array(token(node.opening_loc), visit_all(node.elements), token(node.closing_loc)) + end + + # foo => [bar] + # ^^^^^ + def visit_array_pattern_node(node) + if node.constant + builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.array_pattern(nil, visit_all([*node.requireds, *node.rest, *node.posts]), nil), token(node.closing_loc)) + else + builder.array_pattern(token(node.opening_loc), visit_all([*node.requireds, *node.rest, *node.posts]), token(node.closing_loc)) + end + end + + # foo(bar) + # ^^^ + def visit_arguments_node(node) + visit_all(node.arguments) + end + + # { a: 1 } + # ^^^^ + def visit_assoc_node(node) + if node.value.is_a?(ImplicitNode) + builder.pair_label([node.key.slice.chomp(":"), srange(node.key.location)]) + elsif in_pattern && node.value.nil? + if node.key.is_a?(SymbolNode) + builder.match_hash_var([node.key.unescaped, srange(node.key.location)]) + else + builder.match_hash_var_from_str(token(node.key.opening_loc), visit_all(node.key.parts), token(node.key.closing_loc)) + end + elsif node.operator_loc + builder.pair(visit(node.key), token(node.operator_loc), visit(node.value)) + elsif node.key.is_a?(SymbolNode) && node.key.opening_loc.nil? + builder.pair_keyword([node.key.unescaped, srange(node.key.location)], visit(node.value)) + else + parts = + if node.key.is_a?(SymbolNode) + [builder.string_internal([node.key.unescaped, srange(node.key.value_loc)])] + else + visit_all(node.key.parts) + end + + builder.pair_quoted(token(node.key.opening_loc), parts, token(node.key.closing_loc), visit(node.value)) + end + end + + # def foo(**); bar(**); end + # ^^ + # + # { **foo } + # ^^^^^ + def visit_assoc_splat_node(node) + if node.value.nil? && locals.include?(:**) + builder.forwarded_kwrestarg(token(node.operator_loc)) + else + builder.kwsplat(token(node.operator_loc), visit(node.value)) + end + end + + # $+ + # ^^ + def visit_back_reference_read_node(node) + builder.back_ref(token(node.location)) + end + + # begin end + # ^^^^^^^^^ + def visit_begin_node(node) + rescue_bodies = [] + + if (rescue_clause = node.rescue_clause) + begin + find_start_offset = (rescue_clause.reference&.location || rescue_clause.exceptions.last&.location || rescue_clause.keyword_loc).end_offset + find_end_offset = (rescue_clause.statements&.location&.start_offset || rescue_clause.consequent&.location&.start_offset || (find_start_offset + 1)) + + rescue_bodies << builder.rescue_body( + token(rescue_clause.keyword_loc), + rescue_clause.exceptions.any? ? builder.array(nil, visit_all(rescue_clause.exceptions), nil) : nil, + token(rescue_clause.operator_loc), + visit(rescue_clause.reference), + srange_find(find_start_offset, find_end_offset, [";"]), + visit(rescue_clause.statements) + ) + end until (rescue_clause = rescue_clause.consequent).nil? + end + + begin_body = + builder.begin_body( + visit(node.statements), + rescue_bodies, + token(node.else_clause&.else_keyword_loc), + visit(node.else_clause), + token(node.ensure_clause&.ensure_keyword_loc), + visit(node.ensure_clause&.statements) + ) + + if node.begin_keyword_loc + builder.begin_keyword(token(node.begin_keyword_loc), begin_body, token(node.end_keyword_loc)) + else + begin_body + end + end + + # foo(&bar) + # ^^^^ + def visit_block_argument_node(node) + builder.block_pass(token(node.operator_loc), visit(node.expression)) + end + + # foo { |; bar| } + # ^^^ + def visit_block_local_variable_node(node) + builder.shadowarg(token(node.location)) + end + + # A block on a keyword or method call. + def visit_block_node(node) + raise CompilationError, "Cannot directly compile block nodes" + end + + # def foo(&bar); end + # ^^^^ + def visit_block_parameter_node(node) + builder.blockarg(token(node.operator_loc), token(node.name_loc)) + end + + # A block's parameters. + def visit_block_parameters_node(node) + [*visit(node.parameters)].concat(visit_all(node.locals)) + end + + # break + # ^^^^^ + # + # break foo + # ^^^^^^^^^ + def visit_break_node(node) + builder.keyword_cmd(:break, token(node.keyword_loc), nil, visit(node.arguments) || [], nil) + end + + # foo + # ^^^ + # + # foo.bar + # ^^^^^^^ + # + # foo.bar() {} + # ^^^^^^^^^^^^ + def visit_call_node(node) + name = node.name + arguments = node.arguments&.arguments || [] + block = node.block + + if block.is_a?(BlockArgumentNode) + arguments = [*arguments, block] + block = nil + end + + visit_block( + if name == :! + builder.not_op( + token(node.message_loc), + token(node.opening_loc), + visit(node.receiver), + token(node.closing_loc) + ) + elsif name == :[] + builder.index( + visit(node.receiver), + token(node.opening_loc), + visit_all(arguments), + token(node.closing_loc) + ) + elsif name == :[]= && node.message != "[]=" && node.arguments && block.nil? + builder.assign( + builder.index_asgn( + visit(node.receiver), + token(node.opening_loc), + visit_all(node.arguments.arguments[...-1]), + token(node.closing_loc), + ), + srange_find(node.message_loc.end_offset, node.arguments.arguments.last.location.start_offset, ["="]), + visit(node.arguments.arguments.last) + ) + else + message_loc = node.message_loc + call_operator_loc = node.call_operator_loc + call_operator = [{ "." => :dot, "&." => :anddot, "::" => "::" }.fetch(call_operator_loc.slice), srange(call_operator_loc)] if call_operator_loc + + if name.end_with?("=") && !message_loc.slice.end_with?("=") && node.arguments && block.nil? + builder.assign( + builder.attr_asgn(visit(node.receiver), call_operator, token(message_loc)), + srange_find(message_loc.end_offset, node.arguments.location.start_offset, ["="]), + visit(node.arguments.arguments.last) + ) + else + builder.call_method( + visit(node.receiver), + call_operator, + message_loc ? [node.name, srange(message_loc)] : nil, + token(node.opening_loc), + visit_all(arguments), + token(node.closing_loc) + ) + end + end, + block + ) + end + + # foo.bar += baz + # ^^^^^^^^^^^^^^^ + def visit_call_operator_write_node(node) + call_operator_loc = node.call_operator_loc + + builder.op_assign( + builder.call_method( + visit(node.receiver), + call_operator_loc.nil? ? nil : [{ "." => :dot, "&." => :anddot, "::" => "::" }.fetch(call_operator_loc.slice), srange(call_operator_loc)], + node.message_loc ? [node.read_name, srange(node.message_loc)] : nil, + nil, + [], + nil + ), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end + + # foo.bar &&= baz + # ^^^^^^^^^^^^^^^ + alias visit_call_and_write_node visit_call_operator_write_node + + # foo.bar ||= baz + # ^^^^^^^^^^^^^^^ + alias visit_call_or_write_node visit_call_operator_write_node + + # foo.bar, = 1 + # ^^^^^^^ + def visit_call_target_node(node) + call_operator_loc = node.call_operator_loc + + builder.attr_asgn( + visit(node.receiver), + call_operator_loc.nil? ? nil : [{ "." => :dot, "&." => :anddot, "::" => "::" }.fetch(call_operator_loc.slice), srange(call_operator_loc)], + token(node.message_loc) + ) + end + + # foo => bar => baz + # ^^^^^^^^^^ + def visit_capture_pattern_node(node) + builder.match_as(visit(node.value), token(node.operator_loc), visit(node.target)) + end + + # case foo; when bar; end + # ^^^^^^^^^^^^^^^^^^^^^^^ + def visit_case_node(node) + builder.case( + token(node.case_keyword_loc), + visit(node.predicate), + visit_all(node.conditions), + token(node.consequent&.else_keyword_loc), + visit(node.consequent), + token(node.end_keyword_loc) + ) + end + + # case foo; in bar; end + # ^^^^^^^^^^^^^^^^^^^^^ + def visit_case_match_node(node) + builder.case_match( + token(node.case_keyword_loc), + visit(node.predicate), + visit_all(node.conditions), + token(node.consequent&.else_keyword_loc), + visit(node.consequent), + token(node.end_keyword_loc) + ) + end + + # class Foo; end + # ^^^^^^^^^^^^^^ + def visit_class_node(node) + builder.def_class( + token(node.class_keyword_loc), + visit(node.constant_path), + token(node.inheritance_operator_loc), + visit(node.superclass), + node.body&.accept(copy_compiler(locals: node.locals)), + token(node.end_keyword_loc) + ) + end + + # @@foo + # ^^^^^ + def visit_class_variable_read_node(node) + builder.cvar(token(node.location)) + end + + # @@foo = 1 + # ^^^^^^^^^ + # + # @@foo, @@bar = 1 + # ^^^^^ ^^^^^ + def visit_class_variable_write_node(node) + builder.assign( + builder.assignable(builder.cvar(token(node.name_loc))), + token(node.operator_loc), + visit(node.value) + ) + end + + # @@foo += bar + # ^^^^^^^^^^^^ + def visit_class_variable_operator_write_node(node) + builder.op_assign( + builder.assignable(builder.cvar(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end + + # @@foo &&= bar + # ^^^^^^^^^^^^^ + alias visit_class_variable_and_write_node visit_class_variable_operator_write_node + + # @@foo ||= bar + # ^^^^^^^^^^^^^ + alias visit_class_variable_or_write_node visit_class_variable_operator_write_node + + # @@foo, = bar + # ^^^^^ + def visit_class_variable_target_node(node) + builder.assignable(builder.cvar(token(node.location))) + end + + # Foo + # ^^^ + def visit_constant_read_node(node) + builder.const([node.name, srange(node.location)]) + end + + # Foo = 1 + # ^^^^^^^ + # + # Foo, Bar = 1 + # ^^^ ^^^ + def visit_constant_write_node(node) + builder.assign(builder.assignable(builder.const([node.name, srange(node.name_loc)])), token(node.operator_loc), visit(node.value)) + end + + # Foo += bar + # ^^^^^^^^^^^ + def visit_constant_operator_write_node(node) + builder.op_assign( + builder.assignable(builder.const([node.name, srange(node.name_loc)])), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end + + # Foo &&= bar + # ^^^^^^^^^^^^ + alias visit_constant_and_write_node visit_constant_operator_write_node + + # Foo ||= bar + # ^^^^^^^^^^^^ + alias visit_constant_or_write_node visit_constant_operator_write_node + + # Foo, = bar + # ^^^ + def visit_constant_target_node(node) + builder.assignable(builder.const([node.name, srange(node.location)])) + end + + # Foo::Bar + # ^^^^^^^^ + def visit_constant_path_node(node) + if node.parent.nil? + builder.const_global( + token(node.delimiter_loc), + [node.child.name, srange(node.child.location)] + ) + else + builder.const_fetch( + visit(node.parent), + token(node.delimiter_loc), + [node.child.name, srange(node.child.location)] + ) + end + end + + # Foo::Bar = 1 + # ^^^^^^^^^^^^ + # + # Foo::Foo, Bar::Bar = 1 + # ^^^^^^^^ ^^^^^^^^ + def visit_constant_path_write_node(node) + builder.assign( + builder.assignable(visit(node.target)), + token(node.operator_loc), + visit(node.value) + ) + end + + # Foo::Bar += baz + # ^^^^^^^^^^^^^^^ + def visit_constant_path_operator_write_node(node) + builder.op_assign( + builder.assignable(visit(node.target)), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end + + # Foo::Bar &&= baz + # ^^^^^^^^^^^^^^^^ + alias visit_constant_path_and_write_node visit_constant_path_operator_write_node + + # Foo::Bar ||= baz + # ^^^^^^^^^^^^^^^^ + alias visit_constant_path_or_write_node visit_constant_path_operator_write_node + + # Foo::Bar, = baz + # ^^^^^^^^ + def visit_constant_path_target_node(node) + builder.assignable(visit_constant_path_node(node)) + end + + # def foo; end + # ^^^^^^^^^^^^ + # + # def self.foo; end + # ^^^^^^^^^^^^^^^^^ + def visit_def_node(node) + if node.equal_loc + if node.receiver + builder.def_endless_singleton( + token(node.def_keyword_loc), + visit(node.receiver.is_a?(ParenthesesNode) ? node.receiver.body : node.receiver), + token(node.operator_loc), + token(node.name_loc), + builder.args(token(node.lparen_loc), visit(node.parameters) || [], token(node.rparen_loc), false), + token(node.equal_loc), + node.body&.accept(copy_compiler(locals: node.locals)) + ) + else + builder.def_endless_method( + token(node.def_keyword_loc), + token(node.name_loc), + builder.args(token(node.lparen_loc), visit(node.parameters) || [], token(node.rparen_loc), false), + token(node.equal_loc), + node.body&.accept(copy_compiler(locals: node.locals)) + ) + end + elsif node.receiver + builder.def_singleton( + token(node.def_keyword_loc), + visit(node.receiver.is_a?(ParenthesesNode) ? node.receiver.body : node.receiver), + token(node.operator_loc), + token(node.name_loc), + builder.args(token(node.lparen_loc), visit(node.parameters) || [], token(node.rparen_loc), false), + node.body&.accept(copy_compiler(locals: node.locals)), + token(node.end_keyword_loc) + ) + else + builder.def_method( + token(node.def_keyword_loc), + token(node.name_loc), + builder.args(token(node.lparen_loc), visit(node.parameters) || [], token(node.rparen_loc), false), + node.body&.accept(copy_compiler(locals: node.locals)), + token(node.end_keyword_loc) + ) + end + end + + # defined? a + # ^^^^^^^^^^ + # + # defined?(a) + # ^^^^^^^^^^^ + def visit_defined_node(node) + builder.keyword_cmd( + :defined?, + token(node.keyword_loc), + token(node.lparen_loc), + [visit(node.value)], + token(node.rparen_loc) + ) + end + + # if foo then bar else baz end + # ^^^^^^^^^^^^ + def visit_else_node(node) + visit(node.statements) + end + + # "foo #{bar}" + # ^^^^^^ + def visit_embedded_statements_node(node) + builder.begin( + token(node.opening_loc), + visit(node.statements), + token(node.closing_loc) + ) + end + + # "foo #@bar" + # ^^^^^ + def visit_embedded_variable_node(node) + visit(node.variable) + end + + # begin; foo; ensure; bar; end + # ^^^^^^^^^^^^ + def visit_ensure_node(node) + raise CompilationError, "Cannot directly compile ensure nodes" + end + + # false + # ^^^^^ + def visit_false_node(node) + builder.false(token(node.location)) + end + + # foo => [*, bar, *] + # ^^^^^^^^^^^ + def visit_find_pattern_node(node) + if node.constant + builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.find_pattern(nil, visit_all([node.left, *node.requireds, node.right]), nil), token(node.closing_loc)) + else + builder.find_pattern(token(node.opening_loc), visit_all([node.left, *node.requireds, node.right]), token(node.closing_loc)) + end + end + + # 1.0 + # ^^^ + def visit_float_node(node) + visit_numeric(node, builder.float([node.value, srange(node.location)])) + end + + # for foo in bar do end + # ^^^^^^^^^^^^^^^^^^^^^ + def visit_for_node(node) + builder.for( + token(node.for_keyword_loc), + visit(node.index), + token(node.in_keyword_loc), + visit(node.collection), + if node.do_keyword_loc + token(node.do_keyword_loc) + else + srange_find(node.collection.location.end_offset, (node.statements&.location || node.end_keyword_loc).start_offset, [";"]) + end, + visit(node.statements), + token(node.end_keyword_loc) + ) + end + + # def foo(...); bar(...); end + # ^^^ + def visit_forwarding_arguments_node(node) + builder.forwarded_args(token(node.location)) + end + + # def foo(...); end + # ^^^ + def visit_forwarding_parameter_node(node) + builder.forward_arg(token(node.location)) + end + + # super + # ^^^^^ + # + # super {} + # ^^^^^^^^ + def visit_forwarding_super_node(node) + visit_block( + builder.keyword_cmd( + :zsuper, + ["super", srange_offsets(node.location.start_offset, node.location.start_offset + 5)] + ), + node.block + ) + end + + # $foo + # ^^^^ + def visit_global_variable_read_node(node) + builder.gvar(token(node.location)) + end + + # $foo = 1 + # ^^^^^^^^ + # + # $foo, $bar = 1 + # ^^^^ ^^^^ + def visit_global_variable_write_node(node) + builder.assign( + builder.assignable(builder.gvar(token(node.name_loc))), + token(node.operator_loc), + visit(node.value) + ) + end + + # $foo += bar + # ^^^^^^^^^^^ + def visit_global_variable_operator_write_node(node) + builder.op_assign( + builder.assignable(builder.gvar(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end + + # $foo &&= bar + # ^^^^^^^^^^^^ + alias visit_global_variable_and_write_node visit_global_variable_operator_write_node + + # $foo ||= bar + # ^^^^^^^^^^^^ + alias visit_global_variable_or_write_node visit_global_variable_operator_write_node + + # $foo, = bar + # ^^^^ + def visit_global_variable_target_node(node) + builder.assignable(builder.gvar([node.slice, srange(node.location)])) + end + + # {} + # ^^ + def visit_hash_node(node) + builder.associate( + token(node.opening_loc), + visit_all(node.elements), + token(node.closing_loc) + ) + end + + # foo => {} + # ^^ + def visit_hash_pattern_node(node) + elements = [*node.elements, *node.rest] + + if node.constant + builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.hash_pattern(nil, visit_all(elements), nil), token(node.closing_loc)) + else + builder.hash_pattern(token(node.opening_loc), visit_all(elements), token(node.closing_loc)) + end + end + + # if foo then bar end + # ^^^^^^^^^^^^^^^^^^^ + # + # bar if foo + # ^^^^^^^^^^ + # + # foo ? bar : baz + # ^^^^^^^^^^^^^^^ + def visit_if_node(node) + if !node.if_keyword_loc + builder.ternary( + visit(node.predicate), + token(node.then_keyword_loc), + visit(node.statements), + token(node.consequent.else_keyword_loc), + visit(node.consequent) + ) + elsif node.if_keyword_loc.start_offset == node.location.start_offset + builder.condition( + token(node.if_keyword_loc), + visit(node.predicate), + if node.then_keyword_loc + token(node.then_keyword_loc) + else + srange_find(node.predicate.location.end_offset, (node.statements&.location || node.consequent&.location || node.end_keyword_loc).start_offset, [";"]) + end, + visit(node.statements), + case node.consequent + when IfNode + token(node.consequent.if_keyword_loc) + when ElseNode + token(node.consequent.else_keyword_loc) + end, + visit(node.consequent), + if node.if_keyword != "elsif" + token(node.end_keyword_loc) + end + ) + else + builder.condition_mod( + visit(node.statements), + visit(node.consequent), + token(node.if_keyword_loc), + visit(node.predicate) + ) + end + end + + # 1i + def visit_imaginary_node(node) + visit_numeric(node, builder.complex([node.value, srange(node.location)])) + end + + # { foo: } + # ^^^^ + def visit_implicit_node(node) + raise CompilationError, "Cannot directly compile implicit nodes" + end + + # foo { |bar,| } + # ^ + def visit_implicit_rest_node(node) + raise CompilationError, "Cannot compile implicit rest nodes" + end + + # case foo; in bar; end + # ^^^^^^^^^^^^^^^^^^^^^ + def visit_in_node(node) + pattern = nil + guard = nil + + case node.pattern + when IfNode + pattern = within_pattern { |compiler| node.pattern.statements.accept(compiler) } + guard = builder.if_guard(token(node.pattern.if_keyword_loc), visit(node.pattern.predicate)) + when UnlessNode + pattern = within_pattern { |compiler| node.pattern.statements.accept(compiler) } + guard = builder.unless_guard(token(node.pattern.keyword_loc), visit(node.pattern.predicate)) + else + pattern = within_pattern { |compiler| node.pattern.accept(compiler) } + end + + builder.in_pattern( + token(node.in_loc), + pattern, + guard, + srange_find(node.pattern.location.end_offset, node.statements&.location&.start_offset || node.location.end_offset, [";", "then"]), + visit(node.statements) + ) + end + + # foo[bar] += baz + # ^^^^^^^^^^^^^^^ + def visit_index_operator_write_node(node) + arguments = node.arguments&.arguments || [] + arguments << node.block if node.block + + builder.op_assign( + builder.index( + visit(node.receiver), + token(node.opening_loc), + visit_all(arguments), + token(node.closing_loc) + ), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end + + # foo[bar] &&= baz + # ^^^^^^^^^^^^^^^^ + alias visit_index_and_write_node visit_index_operator_write_node + + # foo[bar] ||= baz + # ^^^^^^^^^^^^^^^^ + alias visit_index_or_write_node visit_index_operator_write_node + + # foo[bar], = 1 + # ^^^^^^^^ + def visit_index_target_node(node) + builder.index_asgn( + visit(node.receiver), + token(node.opening_loc), + visit_all(node.arguments.arguments), + token(node.closing_loc), + ) + end + + # @foo + # ^^^^ + def visit_instance_variable_read_node(node) + builder.ivar(token(node.location)) + end + + # @foo = 1 + # ^^^^^^^^ + # + # @foo, @bar = 1 + # ^^^^ ^^^^ + def visit_instance_variable_write_node(node) + builder.assign( + builder.assignable(builder.ivar(token(node.name_loc))), + token(node.operator_loc), + visit(node.value) + ) + end + + # @foo += bar + # ^^^^^^^^^^^ + def visit_instance_variable_operator_write_node(node) + builder.op_assign( + builder.assignable(builder.ivar(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end + + # @foo &&= bar + # ^^^^^^^^^^^^ + alias visit_instance_variable_and_write_node visit_instance_variable_operator_write_node + + # @foo ||= bar + # ^^^^^^^^^^^^ + alias visit_instance_variable_or_write_node visit_instance_variable_operator_write_node + + # @foo, = bar + # ^^^^ + def visit_instance_variable_target_node(node) + builder.assignable(builder.ivar(token(node.location))) + end + + # 1 + # ^ + def visit_integer_node(node) + visit_numeric(node, builder.integer([node.value, srange(node.location)])) + end + + # /foo #{bar}/ + # ^^^^^^^^^^^^ + def visit_interpolated_regular_expression_node(node) + builder.regexp_compose( + token(node.opening_loc), + visit_all(node.parts), + [node.closing[0], srange_offsets(node.closing_loc.start_offset, node.closing_loc.start_offset + 1)], + builder.regexp_options([node.closing[1..], srange_offsets(node.closing_loc.start_offset + 1, node.closing_loc.end_offset)]) + ) + end + + # if /foo #{bar}/ then end + # ^^^^^^^^^^^^ + alias visit_interpolated_match_last_line_node visit_interpolated_regular_expression_node + + # "foo #{bar}" + # ^^^^^^^^^^^^ + def visit_interpolated_string_node(node) + if node.opening&.start_with?("<<") + children, closing = visit_heredoc(node) + builder.string_compose(token(node.opening_loc), children, closing) + else + builder.string_compose( + token(node.opening_loc), + visit_all(node.parts), + token(node.closing_loc) + ) + end + end + + # :"foo #{bar}" + # ^^^^^^^^^^^^^ + def visit_interpolated_symbol_node(node) + builder.symbol_compose( + token(node.opening_loc), + visit_all(node.parts), + token(node.closing_loc) + ) + end + + # `foo #{bar}` + # ^^^^^^^^^^^^ + def visit_interpolated_x_string_node(node) + if node.opening.start_with?("<<") + children, closing = visit_heredoc(node) + builder.xstring_compose(token(node.opening_loc), children, closing) + else + builder.xstring_compose( + token(node.opening_loc), + visit_all(node.parts), + token(node.closing_loc) + ) + end + end + + # foo(bar: baz) + # ^^^^^^^^ + def visit_keyword_hash_node(node) + builder.associate(nil, visit_all(node.elements), nil) + end + + # def foo(**bar); end + # ^^^^^ + # + # def foo(**); end + # ^^ + def visit_keyword_rest_parameter_node(node) + builder.kwrestarg( + token(node.operator_loc), + node.name ? [node.name, srange(node.name_loc)] : nil + ) + end + + # -> {} + def visit_lambda_node(node) + builder.block( + builder.call_lambda(token(node.operator_loc)), + [node.opening, srange(node.opening_loc)], + if node.parameters + if node.parameters.is_a?(NumberedParametersNode) + visit(node.parameters) + else + builder.args( + token(node.parameters.opening_loc), + visit(node.parameters), + token(node.parameters.closing_loc), + false + ) + end + else + builder.args(nil, [], nil, false) + end, + node.body&.accept(copy_compiler(locals: node.locals)), + [node.closing, srange(node.closing_loc)] + ) + end + + # foo + # ^^^ + def visit_local_variable_read_node(node) + builder.ident([node.name, srange(node.location)]).updated(:lvar) + end + + # foo = 1 + # ^^^^^^^ + # + # foo, bar = 1 + # ^^^ ^^^ + def visit_local_variable_write_node(node) + builder.assign( + builder.assignable(builder.ident(token(node.name_loc))), + token(node.operator_loc), + visit(node.value) + ) + end + + # foo += bar + # ^^^^^^^^^^ + def visit_local_variable_operator_write_node(node) + builder.op_assign( + builder.assignable(builder.ident(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end + + # foo &&= bar + # ^^^^^^^^^^^ + alias visit_local_variable_and_write_node visit_local_variable_operator_write_node + + # foo ||= bar + # ^^^^^^^^^^^ + alias visit_local_variable_or_write_node visit_local_variable_operator_write_node + + # foo, = bar + # ^^^ + def visit_local_variable_target_node(node) + if in_pattern + builder.assignable(builder.match_var([node.name, srange(node.location)])) + else + builder.assignable(builder.ident(token(node.location))) + end + end + + # foo in bar + # ^^^^^^^^^^ + def visit_match_predicate_node(node) + builder.match_pattern_p( + visit(node.value), + token(node.operator_loc), + within_pattern { |compiler| node.pattern.accept(compiler) } + ) + end + + # foo => bar + # ^^^^^^^^^^ + def visit_match_required_node(node) + builder.match_pattern( + visit(node.value), + token(node.operator_loc), + within_pattern { |compiler| node.pattern.accept(compiler) } + ) + end + + # /(?foo)/ =~ bar + # ^^^^^^^^^^^^^^^^^^^^ + def visit_match_write_node(node) + builder.match_op( + visit(node.call.receiver), + token(node.call.message_loc), + visit(node.call.arguments.arguments.first) + ) + end + + # A node that is missing from the syntax tree. This is only used in the + # case of a syntax error. The parser gem doesn't have such a concept, so + # we invent our own here. + def visit_missing_node(node) + raise CompilationError, "Cannot compile missing nodes" + end + + # module Foo; end + # ^^^^^^^^^^^^^^^ + def visit_module_node(node) + builder.def_module( + token(node.module_keyword_loc), + visit(node.constant_path), + node.body&.accept(copy_compiler(locals: node.locals)), + token(node.end_keyword_loc) + ) + end + + # foo, bar = baz + # ^^^^^^^^ + def visit_multi_target_node(node) + node = node.copy(rest: nil) if node.rest.is_a?(ImplicitRestNode) + + builder.multi_lhs( + token(node.lparen_loc), + visit_all([*node.lefts, *node.rest, *node.rights]), + token(node.rparen_loc) + ) + end + + # foo, bar = baz + # ^^^^^^^^^^^^^^ + def visit_multi_write_node(node) + node = node.copy(rest: nil) if node.rest.is_a?(ImplicitRestNode) + + builder.multi_assign( + builder.multi_lhs( + token(node.lparen_loc), + visit_all([*node.lefts, *node.rest, *node.rights]), + token(node.rparen_loc) + ), + token(node.operator_loc), + visit(node.value) + ) + end + + # next + # ^^^^ + # + # next foo + # ^^^^^^^^ + def visit_next_node(node) + builder.keyword_cmd( + :next, + token(node.keyword_loc), + nil, + visit(node.arguments) || [], + nil + ) + end + + # nil + # ^^^ + def visit_nil_node(node) + builder.nil(token(node.location)) + end + + # def foo(**nil); end + # ^^^^^ + def visit_no_keywords_parameter_node(node) + if in_pattern + builder.match_nil_pattern(token(node.operator_loc), token(node.keyword_loc)) + else + builder.kwnilarg(token(node.operator_loc), token(node.keyword_loc)) + end + end + + # -> { _1 + _2 } + # ^^^^^^^^^^^^^^ + def visit_numbered_parameters_node(node) + builder.numargs(node.maximum) + end + + # $1 + # ^^ + def visit_numbered_reference_read_node(node) + builder.nth_ref([node.number, srange(node.location)]) + end + + # def foo(bar: baz); end + # ^^^^^^^^ + def visit_optional_keyword_parameter_node(node) + builder.kwoptarg([node.name, srange(node.name_loc)], visit(node.value)) + end + + # def foo(bar = 1); end + # ^^^^^^^ + def visit_optional_parameter_node(node) + builder.optarg(token(node.name_loc), token(node.operator_loc), visit(node.value)) + end + + # a or b + # ^^^^^^ + def visit_or_node(node) + builder.logical_op(:or, visit(node.left), token(node.operator_loc), visit(node.right)) + end + + # def foo(bar, *baz); end + # ^^^^^^^^^ + def visit_parameters_node(node) + params = [] + + if node.requireds.any? + node.requireds.each do |required| + if required.is_a?(RequiredParameterNode) + params << visit(required) + else + compiler = copy_compiler(in_destructure: true) + params << required.accept(compiler) + end + end + end + + params.concat(visit_all(node.optionals)) if node.optionals.any? + params << visit(node.rest) if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode) + + if node.posts.any? + node.posts.each do |post| + if post.is_a?(RequiredParameterNode) + params << visit(post) + else + compiler = copy_compiler(in_destructure: true) + params << post.accept(compiler) + end + end + end + + params.concat(visit_all(node.keywords)) if node.keywords.any? + params << visit(node.keyword_rest) if !node.keyword_rest.nil? + params << visit(node.block) if !node.block.nil? + params + end + + # () + # ^^ + # + # (1) + # ^^^ + def visit_parentheses_node(node) + builder.begin( + token(node.opening_loc), + visit(node.body), + token(node.closing_loc) + ) + end + + # foo => ^(bar) + # ^^^^^^ + def visit_pinned_expression_node(node) + builder.pin(token(node.operator_loc), visit(node.expression)) + end + + # foo = 1 and bar => ^foo + # ^^^^ + def visit_pinned_variable_node(node) + builder.pin(token(node.operator_loc), visit(node.variable)) + end + + # END {} + def visit_post_execution_node(node) + builder.postexe( + token(node.keyword_loc), + token(node.opening_loc), + visit(node.statements), + token(node.closing_loc) + ) + end + + # BEGIN {} + def visit_pre_execution_node(node) + builder.preexe( + token(node.keyword_loc), + token(node.opening_loc), + visit(node.statements), + token(node.closing_loc) + ) + end + + # The top-level program node. + def visit_program_node(node) + node.statements.accept(copy_compiler(locals: node.locals)) + end + + # 0..5 + # ^^^^ + def visit_range_node(node) + if node.exclude_end? + builder.range_exclusive( + visit(node.left), + token(node.operator_loc), + visit(node.right) + ) + else + builder.range_inclusive( + visit(node.left), + token(node.operator_loc), + visit(node.right) + ) + end + end + + # if foo .. bar; end + # ^^^^^^^^^^ + alias visit_flip_flop_node visit_range_node + + # 1r + # ^^ + def visit_rational_node(node) + visit_numeric(node, builder.rational([node.value, srange(node.location)])) + end + + # redo + # ^^^^ + def visit_redo_node(node) + builder.keyword_cmd(:redo, token(node.location)) + end + + # /foo/ + # ^^^^^ + def visit_regular_expression_node(node) + builder.regexp_compose( + token(node.opening_loc), + [builder.string_internal(token(node.content_loc))], + [node.closing[0], srange_offsets(node.closing_loc.start_offset, node.closing_loc.start_offset + 1)], + builder.regexp_options([node.closing[1..], srange_offsets(node.closing_loc.start_offset + 1, node.closing_loc.end_offset)]) + ) + end + + # if /foo/ then end + # ^^^^^ + alias visit_match_last_line_node visit_regular_expression_node + + # def foo(bar:); end + # ^^^^ + def visit_required_keyword_parameter_node(node) + builder.kwarg([node.name, srange(node.name_loc)]) + end + + # def foo(bar); end + # ^^^ + def visit_required_parameter_node(node) + builder.arg(token(node.location)) + end + + # foo rescue bar + # ^^^^^^^^^^^^^^ + def visit_rescue_modifier_node(node) + builder.begin_body( + visit(node.expression), + [ + builder.rescue_body( + token(node.keyword_loc), + nil, + nil, + nil, + nil, + visit(node.rescue_expression) + ) + ] + ) + end + + # begin; rescue; end + # ^^^^^^^ + def visit_rescue_node(node) + raise CompilationError, "Cannot directly compile rescue nodes" + end + + # def foo(*bar); end + # ^^^^ + # + # def foo(*); end + # ^ + def visit_rest_parameter_node(node) + builder.restarg(token(node.operator_loc), token(node.name_loc)) + end + + # retry + # ^^^^^ + def visit_retry_node(node) + builder.keyword_cmd(:retry, token(node.location)) + end + + # return + # ^^^^^^ + # + # return 1 + # ^^^^^^^^ + def visit_return_node(node) + builder.keyword_cmd( + :return, + token(node.keyword_loc), + nil, + visit(node.arguments) || [], + nil + ) + end + + # self + # ^^^^ + def visit_self_node(node) + builder.self(token(node.location)) + end + + # class << self; end + # ^^^^^^^^^^^^^^^^^^ + def visit_singleton_class_node(node) + builder.def_sclass( + token(node.class_keyword_loc), + token(node.operator_loc), + visit(node.expression), + node.body&.accept(copy_compiler(locals: node.locals)), + token(node.end_keyword_loc) + ) + end + + # __ENCODING__ + # ^^^^^^^^^^^^ + def visit_source_encoding_node(node) + builder.accessible(builder.__ENCODING__(token(node.location))) + end + + # __FILE__ + # ^^^^^^^^ + def visit_source_file_node(node) + builder.accessible(builder.__FILE__(token(node.location))) + end + + # __LINE__ + # ^^^^^^^^ + def visit_source_line_node(node) + builder.accessible(builder.__LINE__(token(node.location))) + end + + # foo(*bar) + # ^^^^ + # + # def foo((bar, *baz)); end + # ^^^^ + # + # def foo(*); bar(*); end + # ^ + def visit_splat_node(node) + if node.expression.nil? && locals.include?(:*) + builder.forwarded_restarg(token(node.operator_loc)) + elsif in_destructure + builder.restarg(token(node.operator_loc), token(node.expression&.location)) + elsif in_pattern + builder.match_rest(token(node.operator_loc), token(node.expression&.location)) + else + builder.splat(token(node.operator_loc), visit(node.expression)) + end + end + + # A list of statements. + def visit_statements_node(node) + builder.compstmt(visit_all(node.body)) + end + + # "foo" + # ^^^^^ + def visit_string_node(node) + if node.opening&.start_with?("<<") + children, closing = visit_heredoc(InterpolatedStringNode.new(node.opening_loc, [node.copy(opening_loc: nil, closing_loc: nil, location: node.content_loc)], node.closing_loc, node.location)) + builder.string_compose(token(node.opening_loc), children, closing) + elsif node.opening == "?" + builder.character([node.unescaped, srange(node.location)]) + else + builder.string_compose( + token(node.opening_loc), + [builder.string_internal([node.unescaped, srange(node.content_loc)])], + token(node.closing_loc) + ) + end + end + + # super(foo) + # ^^^^^^^^^^ + def visit_super_node(node) + arguments = node.arguments&.arguments || [] + block = node.block + + if block.is_a?(BlockArgumentNode) + arguments = [*arguments, block] + block = nil + end + + visit_block( + builder.keyword_cmd( + :super, + token(node.keyword_loc), + token(node.lparen_loc), + visit_all(arguments), + token(node.rparen_loc) + ), + block + ) + end + + # :foo + # ^^^^ + def visit_symbol_node(node) + if node.closing_loc.nil? + if node.opening_loc.nil? + builder.symbol_internal([node.unescaped, srange(node.location)]) + else + builder.symbol([node.unescaped, srange(node.location)]) + end + else + builder.symbol_compose( + token(node.opening_loc), + [builder.string_internal([node.unescaped, srange(node.value_loc)])], + token(node.closing_loc) + ) + end + end + + # true + # ^^^^ + def visit_true_node(node) + builder.true(token(node.location)) + end + + # undef foo + # ^^^^^^^^^ + def visit_undef_node(node) + builder.undef_method(token(node.keyword_loc), visit_all(node.names)) + end + + # unless foo; bar end + # ^^^^^^^^^^^^^^^^^^^ + # + # bar unless foo + # ^^^^^^^^^^^^^^ + def visit_unless_node(node) + if node.keyword_loc.start_offset == node.location.start_offset + builder.condition( + token(node.keyword_loc), + visit(node.predicate), + if node.then_keyword_loc + token(node.then_keyword_loc) + else + srange_find(node.predicate.location.end_offset, (node.statements&.location || node.consequent&.location || node.end_keyword_loc).start_offset, [";"]) + end, + visit(node.consequent), + token(node.consequent&.else_keyword_loc), + visit(node.statements), + token(node.end_keyword_loc) + ) + else + builder.condition_mod( + visit(node.consequent), + visit(node.statements), + token(node.keyword_loc), + visit(node.predicate) + ) + end + end + + # until foo; bar end + # ^^^^^^^^^^^^^^^^^ + # + # bar until foo + # ^^^^^^^^^^^^^ + def visit_until_node(node) + if node.location.start_offset == node.keyword_loc.start_offset + builder.loop( + :until, + token(node.keyword_loc), + visit(node.predicate), + srange_find(node.predicate.location.end_offset, (node.statements&.location || node.closing_loc).start_offset, [";", "do"]), + visit(node.statements), + token(node.closing_loc) + ) + else + builder.loop_mod( + :until, + visit(node.statements), + token(node.keyword_loc), + visit(node.predicate) + ) + end + end + + # case foo; when bar; end + # ^^^^^^^^^^^^^ + def visit_when_node(node) + builder.when( + token(node.keyword_loc), + visit_all(node.conditions), + srange_find(node.conditions.last.location.end_offset, node.statements&.location&.start_offset || (node.conditions.last.location.end_offset + 1), [";", "then"]), + visit(node.statements) + ) + end + + # while foo; bar end + # ^^^^^^^^^^^^^^^^^^ + # + # bar while foo + # ^^^^^^^^^^^^^ + def visit_while_node(node) + if node.location.start_offset == node.keyword_loc.start_offset + builder.loop( + :while, + token(node.keyword_loc), + visit(node.predicate), + srange_find(node.predicate.location.end_offset, (node.statements&.location || node.closing_loc).start_offset, [";", "do"]), + visit(node.statements), + token(node.closing_loc) + ) + else + builder.loop_mod( + :while, + visit(node.statements), + token(node.keyword_loc), + visit(node.predicate) + ) + end + end + + # `foo` + # ^^^^^ + def visit_x_string_node(node) + if node.opening&.start_with?("<<") + children, closing = visit_heredoc(InterpolatedXStringNode.new(node.opening_loc, [StringNode.new(0, nil, node.content_loc, nil, node.unescaped, node.content_loc)], node.closing_loc, node.location)) + builder.xstring_compose(token(node.opening_loc), children, closing) + else + builder.xstring_compose( + token(node.opening_loc), + [builder.string_internal([node.unescaped, srange(node.content_loc)])], + token(node.closing_loc) + ) + end + end + + # yield + # ^^^^^ + # + # yield 1 + # ^^^^^^^ + def visit_yield_node(node) + builder.keyword_cmd( + :yield, + token(node.keyword_loc), + token(node.lparen_loc), + visit(node.arguments) || [], + token(node.rparen_loc) + ) + end + + private + + # Initialize a new compiler with the given option overrides, used to + # visit a subtree with the given options. + def copy_compiler(locals: self.locals, in_destructure: self.in_destructure, in_pattern: self.in_pattern) + Compiler.new(parser, offset_cache, locals: locals, in_destructure: in_destructure, in_pattern: in_pattern) + end + + # Blocks can have a special set of parameters that automatically expand + # when given arrays if they have a single required parameter and no + # other parameters. + def procarg0?(parameters) + parameters && + parameters.requireds.length == 1 && + parameters.optionals.empty? && + parameters.rest.nil? && + parameters.posts.empty? && + parameters.keywords.empty? && + parameters.keyword_rest.nil? && + parameters.block.nil? + end + + # Locations in the parser gem AST are generated using this class. We + # store a reference to its constant to make it slightly faster to look + # up. + Range = ::Parser::Source::Range + + # Constructs a new source range from the given start and end offsets. + def srange(location) + Range.new(source_buffer, offset_cache[location.start_offset], offset_cache[location.end_offset]) if location + end + + # Constructs a new source range from the given start and end offsets. + def srange_offsets(start_offset, end_offset) + Range.new(source_buffer, offset_cache[start_offset], offset_cache[end_offset]) + end + + # Constructs a new source range by finding the given tokens between the + # given start offset and end offset. If the needle is not found, it + # returns nil. + def srange_find(start_offset, end_offset, tokens) + tokens.find do |token| + next unless (index = source_buffer.source.byteslice(start_offset...end_offset).index(token)) + offset = start_offset + index + return [token, Range.new(source_buffer, offset_cache[offset], offset_cache[offset + token.length])] + end + end + + # Transform a location into a token that the parser gem expects. + def token(location) + [location.slice, Range.new(source_buffer, offset_cache[location.start_offset], offset_cache[location.end_offset])] if location + end + + # Visit a block node on a call. + def visit_block(call, block) + if block + builder.block( + call, + token(block.opening_loc), + if (parameters = block.parameters) + if parameters.is_a?(NumberedParametersNode) + visit(parameters) + else + builder.args( + token(parameters.opening_loc), + if procarg0?(parameters.parameters) + parameter = parameters.parameters.requireds.first + [builder.procarg0(visit(parameter))].concat(visit_all(parameters.locals)) + else + visit(parameters) + end, + token(parameters.closing_loc), + false + ) + end + else + builder.args(nil, [], nil, false) + end, + visit(block.body), + token(block.closing_loc) + ) + else + call + end + end + + # Visit a heredoc that can be either a string or an xstring. + def visit_heredoc(node) + children = [] + node.parts.each do |part| + pushing = + if part.is_a?(StringNode) && part.unescaped.count("\n") > 1 + unescaped = part.unescaped.split("\n") + escaped = part.content.split("\n") + + escaped_lengths = + if node.opening.end_with?("'") + escaped.map { |line| line.bytesize + 1 } + else + escaped.chunk_while { |before, after| before.match?(/(? "~", "!@" => "!" }.fetch(value, value) + location = Range.new(source_buffer, offset_cache[next_location.start_offset], offset_cache[next_location.end_offset]) + index += 1 + end + when :tFID + if tokens[-1][0] == :kDEF + type = :tIDENTIFIER + end + end + + tokens << [type, [value, location]] + + if token.type == :REGEXP_END + tokens << [:tREGEXP_OPT, [token.value[1..], Range.new(source_buffer, offset_cache[token.location.start_offset + 1], offset_cache[token.location.end_offset])]] + end + end + + tokens + end + + private + + # Parse a complex from the string representation. + def parse_complex(value) + value.chomp!("i") + + if value.end_with?("r") + Complex(0, parse_rational(value)) + elsif value.start_with?(/0[BbOoDdXx]/) + Complex(0, Integer(value)) + else + Complex(0, value) + end + end + + # Parse a rational from the string representation. + def parse_rational(value) + value.chomp!("r") + + if value.start_with?(/0[BbOoDdXx]/) + Rational(Integer(value)) + else + Rational(value) + end + end + end + end + end +end diff --git a/lib/prism/translation/parser/rubocop.rb b/lib/prism/translation/parser/rubocop.rb new file mode 100644 index 00000000000000..3e34fc7ace66dd --- /dev/null +++ b/lib/prism/translation/parser/rubocop.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require "parser" +require "rubocop" + +require "prism" +require "prism/translation/parser" + +module Prism + module Translation + class Parser + # This is the special version number that should be used in rubocop + # configuration files to trigger using prism. + VERSION_3_3 = 80_82_73_83_77.33 + + # This module gets prepended into RuboCop::AST::ProcessedSource. + module ProcessedSource + # Redefine parser_class so that we can inject the prism parser into the + # list of known parsers. + def parser_class(ruby_version) + if ruby_version == Prism::Translation::Parser::VERSION_3_3 + require "prism/translation/parser" + Prism::Translation::Parser + else + super + end + end + end + end + end +end + +# :stopdoc: +RuboCop::AST::ProcessedSource.prepend(Prism::Translation::Parser::ProcessedSource) +known_rubies = RuboCop::TargetRuby.const_get(:KNOWN_RUBIES) +RuboCop::TargetRuby.send(:remove_const, :KNOWN_RUBIES) +RuboCop::TargetRuby::KNOWN_RUBIES = [*known_rubies, Prism::Translation::Parser::VERSION_3_3].freeze diff --git a/test/prism/newline_test.rb b/test/prism/newline_test.rb index d99850286999d2..3d42ca99cda562 100644 --- a/test/prism/newline_test.rb +++ b/test/prism/newline_test.rb @@ -7,7 +7,7 @@ module Prism class NewlineTest < TestCase base = File.expand_path("../", __FILE__) - filepaths = Dir["*.rb", base: base] - %w[encoding_test.rb unescape_test.rb] + filepaths = Dir["*.rb", base: base] - %w[encoding_test.rb parser_test.rb unescape_test.rb] filepaths.each do |relative| define_method("test_newline_flags_#{relative}") do diff --git a/test/prism/parser_test.rb b/test/prism/parser_test.rb new file mode 100644 index 00000000000000..e13ee39c6d46ce --- /dev/null +++ b/test/prism/parser_test.rb @@ -0,0 +1,188 @@ +# frozen_string_literal: true + +require_relative "test_helper" + +begin + require "parser/current" +rescue LoadError + # In CRuby's CI, we're not going to test against the parser gem because we + # don't want to have to install it. So in this case we'll just skip this test. + return +end + +# First, opt in to every AST feature. +Parser::Builders::Default.modernize + +# Modify the source map == check so that it doesn't check against the node +# itself so we don't get into a recursive loop. +Parser::Source::Map.prepend( + Module.new { + def ==(other) + self.class == other.class && + (instance_variables - %i[@node]).map do |ivar| + instance_variable_get(ivar) == other.instance_variable_get(ivar) + end.reduce(:&) + end + } +) + +# Next, ensure that we're comparing the nodes and also comparing the source +# ranges so that we're getting all of the necessary information. +Parser::AST::Node.prepend( + Module.new { + def ==(other) + super && (location == other.location) + end + } +) + +module Prism + class ParserTest < TestCase + base = File.join(__dir__, "fixtures") + + # These files are either failing to parse or failing to translate, so we'll + # skip them for now. + skip_all = %w[ + arrays.txt + constants.txt + dash_heredocs.txt + dos_endings.txt + embdoc_no_newline_at_end.txt + heredocs_with_ignored_newlines.txt + regex.txt + spanning_heredoc.txt + spanning_heredoc_newlines.txt + tilde_heredocs.txt + unescaping.txt + ] + + # Not sure why these files are failing on JRuby, but skipping them for now. + if RUBY_ENGINE == "jruby" + skip_all.push("emoji_method_calls.txt", "symbols.txt") + end + + # These files are failing to translate their lexer output into the lexer + # output expected by the parser gem, so we'll skip them for now. + skip_tokens = %w[ + comments.txt + endless_range_in_conditional.txt + heredoc_with_comment.txt + heredoc_with_escaped_newline_at_start.txt + heredocs_leading_whitespace.txt + heredocs_nested.txt + heredocs_with_ignored_newlines_and_non_empty.txt + indented_file_end.txt + non_alphanumeric_methods.txt + range_begin_open_inclusive.txt + single_quote_heredocs.txt + strings.txt + xstring.txt + ] + + Dir["*.txt", base: base].each do |name| + next if skip_all.include?(name) + + define_method("test_#{name}") do + assert_equal_parses(File.join(base, name), compare_tokens: !skip_tokens.include?(name)) + end + end + + private + + def assert_equal_parses(filepath, compare_tokens: true) + buffer = Parser::Source::Buffer.new(filepath, 1) + buffer.source = File.read(filepath) + + parser = Parser::CurrentRuby.default_parser + parser.diagnostics.consumer = ->(*) {} + parser.diagnostics.all_errors_are_fatal = true + + expected_ast, expected_comments, expected_tokens = + begin + parser.tokenize(buffer) + rescue ArgumentError, Parser::SyntaxError + return + end + + actual_ast, actual_comments, actual_tokens = + Prism::Translation::Parser.new.tokenize(buffer) + + assert_equal expected_ast, actual_ast, -> { assert_equal_asts_message(expected_ast, actual_ast) } + assert_equal_tokens(expected_tokens, actual_tokens) if compare_tokens + assert_equal_comments(expected_comments, actual_comments) + end + + def assert_equal_asts_message(expected_ast, actual_ast) + queue = [[expected_ast, actual_ast]] + + while (left, right = queue.shift) + if left.type != right.type + return "expected: #{left.type}\nactual: #{right.type}" + end + + if left.location != right.location + return "expected:\n#{left.inspect}\n#{left.location}\nactual:\n#{right.inspect}\n#{right.location}" + end + + if left.type == :str && left.children[0] != right.children[0] + return "expected: #{left.inspect}\nactual: #{right.inspect}" + end + + left.children.zip(right.children).each do |left_child, right_child| + queue << [left_child, right_child] if left_child.is_a?(Parser::AST::Node) + end + end + + "expected: #{expected_ast.inspect}\nactual: #{actual_ast.inspect}" + end + + def assert_equal_tokens(expected_tokens, actual_tokens) + if expected_tokens != actual_tokens + expected_index = 0 + actual_index = 0 + + while expected_index < expected_tokens.length + expected_token = expected_tokens[expected_index] + actual_token = actual_tokens[actual_index] + + expected_index += 1 + actual_index += 1 + + # The parser gem always has a space before a string end in list + # literals, but we don't. So we'll skip over the space. + if expected_token[0] == :tSPACE && actual_token[0] == :tSTRING_END + expected_index += 1 + next + end + + # There are a lot of tokens that have very specific meaning according + # to the context of the parser. We don't expose that information in + # prism, so we need to normalize these tokens a bit. + case actual_token[0] + when :kDO + actual_token[0] = expected_token[0] if %i[kDO_BLOCK kDO_LAMBDA].include?(expected_token[0]) + when :tLPAREN + actual_token[0] = expected_token[0] if expected_token[0] == :tLPAREN2 + when :tLCURLY + actual_token[0] = expected_token[0] if %i[tLBRACE tLBRACE_ARG].include?(expected_token[0]) + when :tPOW + actual_token[0] = expected_token[0] if expected_token[0] == :tDSTAR + end + + # Now we can assert that the tokens are actually equal. + assert_equal expected_token, actual_token, -> { + "expected: #{expected_token.inspect}\n" \ + "actual: #{actual_token.inspect}" + } + end + end + end + + def assert_equal_comments(expected_comments, actual_comments) + assert_equal expected_comments, actual_comments, -> { + "expected: #{expected_comments.inspect}\n" \ + "actual: #{actual_comments.inspect}" + } + end + end +end From a591e11a7a6f6749044b6bef9c35633ad1930db5 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Fri, 26 Jan 2024 12:29:37 -0800 Subject: [PATCH 580/640] Eliminate 1-2 array allocations for each splat used in a op_asgn method Given code such as: ```ruby h[*a, 1] += 1 h[*b] += 2 ``` Ruby would previously allocate 5 arrays: * splatarray true for a * newarray for 1 * concatarray for [*a, 1] and [1] * newarray for 2 * concatarray for b and [2] This optimizes it to only allocate 2 arrays: * splatarray true for a * splatarray true for b Instead of the newarray/concatarray combination, pushtoarray is used. Note above that there was no splatarray true for b originally. The normal compilation uses splatarray false for b. Instead of trying to find and modify the splatarray false to splatarray true, this adds splatarray true for b, which requires a couple of swap instructions, before the pushtoarray. This could be further optimized to remove the need for those three instructions, but I'm not sure if the complexity is worth it. Additionally, this sets VM_CALL_ARGS_SPLAT_MUT on the call to []= in the h[*b] case, so that if []= has a splat parameter, the new array can be used directly, without additional duplication. --- compile.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/compile.c b/compile.c index 4718ecc9e2b649..a27f4883737a7f 100644 --- a/compile.c +++ b/compile.c @@ -9091,20 +9091,28 @@ compile_op_asgn1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node if (flag & VM_CALL_ARGS_SPLAT) { if (flag & VM_CALL_KW_SPLAT) { ADD_INSN1(ret, node, topn, INT2FIX(2 + boff)); + if (!(flag & VM_CALL_ARGS_SPLAT_MUT)) { + ADD_INSN1(ret, node, splatarray, Qtrue); + flag |= VM_CALL_ARGS_SPLAT_MUT; + } ADD_INSN(ret, node, swap); - ADD_INSN1(ret, node, newarray, INT2FIX(1)); - ADD_INSN(ret, node, concatarray); + ADD_INSN1(ret, node, pushtoarray, INT2FIX(1)); ADD_INSN1(ret, node, setn, INT2FIX(2 + boff)); ADD_INSN(ret, node, pop); } else { - 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 (!(flag & VM_CALL_ARGS_SPLAT_MUT)) { + ADD_INSN(ret, node, swap); + ADD_INSN1(ret, node, splatarray, Qtrue); + ADD_INSN(ret, node, swap); + flag |= VM_CALL_ARGS_SPLAT_MUT; + } + ADD_INSN1(ret, node, pushtoarray, INT2FIX(1)); if (boff > 0) { ADD_INSN1(ret, node, setn, INT2FIX(3)); ADD_INSN(ret, node, pop); @@ -9151,20 +9159,28 @@ compile_op_asgn1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node if (flag & VM_CALL_ARGS_SPLAT) { if (flag & VM_CALL_KW_SPLAT) { ADD_INSN1(ret, node, topn, INT2FIX(2 + boff)); + if (!(flag & VM_CALL_ARGS_SPLAT_MUT)) { + ADD_INSN1(ret, node, splatarray, Qtrue); + flag |= VM_CALL_ARGS_SPLAT_MUT; + } ADD_INSN(ret, node, swap); - ADD_INSN1(ret, node, newarray, INT2FIX(1)); - ADD_INSN(ret, node, concatarray); + ADD_INSN1(ret, node, pushtoarray, INT2FIX(1)); ADD_INSN1(ret, node, setn, INT2FIX(2 + boff)); ADD_INSN(ret, node, pop); } else { - 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 (!(flag & VM_CALL_ARGS_SPLAT_MUT)) { + ADD_INSN(ret, node, swap); + ADD_INSN1(ret, node, splatarray, Qtrue); + ADD_INSN(ret, node, swap); + flag |= VM_CALL_ARGS_SPLAT_MUT; + } + ADD_INSN1(ret, node, pushtoarray, INT2FIX(1)); if (boff > 0) { ADD_INSN1(ret, node, setn, INT2FIX(3)); ADD_INSN(ret, node, pop); From d917bb8e60c283981626876c496cb2670f74ffb7 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Fri, 26 Jan 2024 11:53:49 -0800 Subject: [PATCH 581/640] Eliminate 1-2 array allocations for each splat used in a masgn method Given code such as: ```ruby h[*a, :a], h[*b] = v ``` Ruby would previously allocate 5 arrays for the mass assignment: * splatarray true for a * newarray for v[0] * concatarray for [*a, a] and v[0] * newarray for v[1] * concatarray for b and v[1] This optimizes it to only allocate 2 arrays: * splatarray true for a * splatarray true for b Instead of the newarray/concatarray combination, pushtoarray is used. Note above that there was no splatarray true for b originally. The normal compilation uses splatarray false for b. Instead of trying to find and modify the splatarray false to splatarray true, this adds splatarray true for b, which requires a couple of swap instructions, before the pushtoarray. This could be further optimized to remove the need for those three instructions, but I'm not sure if the complexity is worth it. Additionally, this sets VM_CALL_ARGS_SPLAT_MUT on the call to []= in the h[*b] case, so that if []= has a splat parameter, the new array can be used directly, without additional duplication. --- compile.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/compile.c b/compile.c index a27f4883737a7f..79b17abd9327b1 100644 --- a/compile.c +++ b/compile.c @@ -5401,11 +5401,31 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const ADD_ELEM(lhs, (LINK_ELEMENT *)iobj); if (vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT) { int argc = vm_ci_argc(ci); + bool dupsplat = false; ci = ci_argc_set(iseq, ci, argc - 1); + if (!(vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT_MUT)) { + /* Given h[*a], _ = ary + * setup_args sets VM_CALL_ARGS_SPLAT and not VM_CALL_ARGS_SPLAT_MUT + * `a` must be dupped, because it will be appended with ary[0] + * Since you are dupping `a`, you can set VM_CALL_ARGS_SPLAT_MUT + */ + dupsplat = true; + ci = ci_flag_set(iseq, ci, VM_CALL_ARGS_SPLAT_MUT); + } 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); + /* Given: h[*a], h[*b, 1] = ary + * h[*a] uses splatarray false and does not set VM_CALL_ARGS_SPLAT_MUT, + * so this uses splatarray true on a to dup it before using pushtoarray + * h[*b, 1] uses splatarray true and sets VM_CALL_ARGS_SPLAT_MUT, + * so you can use pushtoarray directly + */ + if (dupsplat) { + INSERT_BEFORE_INSN(iobj, line_node, swap); + INSERT_BEFORE_INSN1(iobj, line_node, splatarray, Qtrue); + INSERT_BEFORE_INSN(iobj, line_node, swap); + } + INSERT_BEFORE_INSN1(iobj, line_node, pushtoarray, INT2FIX(1)); } ADD_INSN(lhs, line_node, pop); if (argc != 1) { From 8a027d111fb5adf87dddd890e846c4814539d866 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Fri, 26 Jan 2024 14:01:55 -0800 Subject: [PATCH 582/640] Remove expandarray/splatarray sequence peephole optimization newarray, duparray, concatarray, and splatarray always leave an array at the top of the stack. expandarray does not, it takes an array from the top of the stack as input, and leaves individual elements on the stack. I assume no Ruby code generates the expandarray/splatarray sequence, or it could break. The only use of expandarray outside the peephole optimizer is in the masgn code, and it does not appear to generate splatarray directly after expandarray. The splatarray/splatarray peephole optimization is probably also wrong in the following case: ``` putobject [1,2] splatarray false splatarray true ``` This instruction sequence should result in a duplicate of [1,2] at the top of the stack, but the peephole optimizer would remove the `splatarray true`, resulting in change that made [1,2] on top of the stack. I'm not sure Ruby code can generate `splatarray false` followed by `splatarray true` (I could get it to generate chains of `splatarray true`), so maybe this has no effect. newarray, duparray, and concatarray all result in newly allocated arrays at the top of the stack, so they shouldn't have an issue with removing either `splatarray true` or `splatarray false`. --- compile.c | 1 - 1 file changed, 1 deletion(-) diff --git a/compile.c b/compile.c index 79b17abd9327b1..492388a4f0ca94 100644 --- a/compile.c +++ b/compile.c @@ -3582,7 +3582,6 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal 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) { From e256d44f984cc80039b7dd0db44a7107214548f1 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Sat, 27 Jan 2024 15:25:04 -0500 Subject: [PATCH 583/640] [ruby/prism] Handle implicit rest in array pattern for parser gem https://github.com/ruby/prism/commit/d3722d6660 --- lib/prism/translation/parser/compiler.rb | 28 +++++++++++++++++------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/prism/translation/parser/compiler.rb b/lib/prism/translation/parser/compiler.rb index e4b4e8ad3a0e58..d03de9efc5507e 100644 --- a/lib/prism/translation/parser/compiler.rb +++ b/lib/prism/translation/parser/compiler.rb @@ -80,10 +80,14 @@ def visit_array_node(node) # foo => [bar] # ^^^^^ def visit_array_pattern_node(node) + elements = [*node.requireds] + elements << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode) + elements.concat(node.posts) + if node.constant - builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.array_pattern(nil, visit_all([*node.requireds, *node.rest, *node.posts]), nil), token(node.closing_loc)) + builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.array_pattern(nil, visit_all(elements), nil), token(node.closing_loc)) else - builder.array_pattern(token(node.opening_loc), visit_all([*node.requireds, *node.rest, *node.posts]), token(node.closing_loc)) + builder.array_pattern(token(node.opening_loc), visit_all(elements), token(node.closing_loc)) end end @@ -603,10 +607,14 @@ def visit_false_node(node) # foo => [*, bar, *] # ^^^^^^^^^^^ def visit_find_pattern_node(node) + elements = [*node.requireds] + elements << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode) + elements.concat(node.posts) + if node.constant - builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.find_pattern(nil, visit_all([node.left, *node.requireds, node.right]), nil), token(node.closing_loc)) + builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.find_pattern(nil, visit_all(elements), nil), token(node.closing_loc)) else - builder.find_pattern(token(node.opening_loc), visit_all([node.left, *node.requireds, node.right]), token(node.closing_loc)) + builder.find_pattern(token(node.opening_loc), visit_all(elements), token(node.closing_loc)) end end @@ -1098,11 +1106,13 @@ def visit_module_node(node) # foo, bar = baz # ^^^^^^^^ def visit_multi_target_node(node) - node = node.copy(rest: nil) if node.rest.is_a?(ImplicitRestNode) + elements = [*node.lefts] + elements << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode) + elements.concat(node.rights) builder.multi_lhs( token(node.lparen_loc), - visit_all([*node.lefts, *node.rest, *node.rights]), + visit_all(elements), token(node.rparen_loc) ) end @@ -1110,12 +1120,14 @@ def visit_multi_target_node(node) # foo, bar = baz # ^^^^^^^^^^^^^^ def visit_multi_write_node(node) - node = node.copy(rest: nil) if node.rest.is_a?(ImplicitRestNode) + elements = [*node.lefts] + elements << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode) + elements.concat(node.rights) builder.multi_assign( builder.multi_lhs( token(node.lparen_loc), - visit_all([*node.lefts, *node.rest, *node.rights]), + visit_all(elements), token(node.rparen_loc) ), token(node.operator_loc), From 0f98d284f338d7480e1849399e38a9f8689e4957 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 28 Jan 2024 00:58:25 +0900 Subject: [PATCH 584/640] Remove unused `nd_resq` from `RNode_ENSURE` --- parse.y | 3 +-- rubyparser.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/parse.y b/parse.y index 180c298a88337b..0af0f4b2cc4af1 100644 --- a/parse.y +++ b/parse.y @@ -11666,7 +11666,6 @@ rb_node_ensure_new(struct parser_params *p, NODE *nd_head, NODE *nd_ensr, const { rb_node_ensure_t *n = NODE_NEWNODE(NODE_ENSURE, rb_node_ensure_t, loc); n->nd_head = nd_head; - n->nd_resq = 0; n->nd_ensr = nd_ensr; return n; @@ -14531,7 +14530,7 @@ reduce_nodes(struct parser_params *p, NODE **body) if (!subnodes(RNODE_WHEN, nd_body, nd_next)) goto end; break; case NODE_ENSURE: - if (!subnodes(RNODE_ENSURE, nd_head, nd_resq)) goto end; + body = &RNODE_ENSURE(node)->nd_head; break; case NODE_RESCUE: newline = 0; // RESBODY should not be a NEWLINE diff --git a/rubyparser.h b/rubyparser.h index e4f06a9052a5a4..e89c5bb1dfa5bf 100644 --- a/rubyparser.h +++ b/rubyparser.h @@ -346,7 +346,6 @@ typedef struct RNode_ENSURE { NODE node; struct RNode *nd_head; - struct RNode *nd_resq; /* Maybe not used other than reduce_nodes */ struct RNode *nd_ensr; } rb_node_ensure_t; From e018036d89e33c5729958130f582f8fb324680d6 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 28 Jan 2024 11:08:23 +0900 Subject: [PATCH 585/640] Rename `nd_head` in `RNode_RESBODY` as `nd_next` --- ast.c | 2 +- compile.c | 2 +- node_dump.c | 2 +- parse.y | 8 ++++---- rubyparser.h | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ast.c b/ast.c index 579110e20a78fd..c938e3e208e628 100644 --- a/ast.c +++ b/ast.c @@ -429,7 +429,7 @@ node_children(rb_ast_t *ast, const NODE *node) case NODE_RESCUE: return rb_ary_new_from_node_args(ast, 3, RNODE_RESCUE(node)->nd_head, RNODE_RESCUE(node)->nd_resq, RNODE_RESCUE(node)->nd_else); case NODE_RESBODY: - return rb_ary_new_from_node_args(ast, 3, RNODE_RESBODY(node)->nd_args, RNODE_RESBODY(node)->nd_body, RNODE_RESBODY(node)->nd_head); + return rb_ary_new_from_node_args(ast, 3, RNODE_RESBODY(node)->nd_args, RNODE_RESBODY(node)->nd_body, RNODE_RESBODY(node)->nd_next); case NODE_ENSURE: return rb_ary_new_from_node_args(ast, 2, RNODE_ENSURE(node)->nd_head, RNODE_ENSURE(node)->nd_ensr); case NODE_AND: diff --git a/compile.c b/compile.c index 492388a4f0ca94..f1deca3c291f71 100644 --- a/compile.c +++ b/compile.c @@ -8275,7 +8275,7 @@ compile_resbody(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, } ADD_INSN(ret, line_node, leave); ADD_LABEL(ret, label_miss); - resq = RNODE_RESBODY(resq)->nd_head; + resq = RNODE_RESBODY(resq)->nd_next; } return COMPILE_OK; } diff --git a/node_dump.c b/node_dump.c index a6f9bff4e3595d..5670279d975390 100644 --- a/node_dump.c +++ b/node_dump.c @@ -351,7 +351,7 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node) F_NODE(nd_args, RNODE_RESBODY, "rescue exceptions"); F_NODE(nd_body, RNODE_RESBODY, "rescue clause"); LAST_NODE; - F_NODE(nd_head, RNODE_RESBODY, "next rescue clause"); + F_NODE(nd_next, RNODE_RESBODY, "next rescue clause"); return; case NODE_ENSURE: diff --git a/parse.y b/parse.y index 0af0f4b2cc4af1..3dd8ecd39f6f8a 100644 --- a/parse.y +++ b/parse.y @@ -1078,7 +1078,7 @@ static rb_node_for_masgn_t *rb_node_for_masgn_new(struct parser_params *p, NODE static rb_node_retry_t *rb_node_retry_new(struct parser_params *p, const YYLTYPE *loc); static rb_node_begin_t *rb_node_begin_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc); static rb_node_rescue_t *rb_node_rescue_new(struct parser_params *p, NODE *nd_head, NODE *nd_resq, NODE *nd_else, const YYLTYPE *loc); -static rb_node_resbody_t *rb_node_resbody_new(struct parser_params *p, NODE *nd_args, NODE *nd_body, NODE *nd_head, const YYLTYPE *loc); +static rb_node_resbody_t *rb_node_resbody_new(struct parser_params *p, NODE *nd_args, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc); static rb_node_ensure_t *rb_node_ensure_new(struct parser_params *p, NODE *nd_head, NODE *nd_ensr, const YYLTYPE *loc); static rb_node_and_t *rb_node_and_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc); static rb_node_or_t *rb_node_or_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc); @@ -11651,12 +11651,12 @@ rb_node_rescue_new(struct parser_params *p, NODE *nd_head, NODE *nd_resq, NODE * } static rb_node_resbody_t * -rb_node_resbody_new(struct parser_params *p, NODE *nd_args, NODE *nd_body, NODE *nd_head, const YYLTYPE *loc) +rb_node_resbody_new(struct parser_params *p, NODE *nd_args, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc) { rb_node_resbody_t *n = NODE_NEWNODE(NODE_RESBODY, rb_node_resbody_t, loc); - n->nd_head = nd_head; - n->nd_body = nd_body; n->nd_args = nd_args; + n->nd_body = nd_body; + n->nd_next = nd_next; return n; } diff --git a/rubyparser.h b/rubyparser.h index e89c5bb1dfa5bf..dff6a42d0b2260 100644 --- a/rubyparser.h +++ b/rubyparser.h @@ -337,9 +337,9 @@ typedef struct RNode_RESCUE { typedef struct RNode_RESBODY { NODE node; - struct RNode *nd_head; - struct RNode *nd_body; struct RNode *nd_args; + struct RNode *nd_body; + struct RNode *nd_next; } rb_node_resbody_t; typedef struct RNode_ENSURE { From 3dde9c1b436e2e03da70306f7e5d08d85c9d3ab0 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 28 Jan 2024 12:00:26 +0900 Subject: [PATCH 586/640] Extract continue-on-error condition to the matrix [ci skip] --- .github/workflows/yjit-macos.yml | 1 + .github/workflows/yjit-ubuntu.yml | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/yjit-macos.yml b/.github/workflows/yjit-macos.yml index 11e200a619da18..93bbb4d93ed587 100644 --- a/.github/workflows/yjit-macos.yml +++ b/.github/workflows/yjit-macos.yml @@ -119,6 +119,7 @@ jobs: TESTS: ${{ matrix.test_task == 'check' && matrix.skipped_tests || '' }} TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' PRECHECK_BUNDLED_GEMS: 'no' + continue-on-error: ${{ matrix.continue-on-test_task || false }} - name: make skipped tests run: | diff --git a/.github/workflows/yjit-ubuntu.yml b/.github/workflows/yjit-ubuntu.yml index 7998e6b2e944a1..437f3d53397083 100644 --- a/.github/workflows/yjit-ubuntu.yml +++ b/.github/workflows/yjit-ubuntu.yml @@ -109,6 +109,7 @@ jobs: - test_task: 'yjit-bench' configure: '--enable-yjit=dev' yjit_bench_opts: '--yjit-stats' + continue-on-test_task: true env: GITPULLOPTIONS: --no-tags origin ${{ github.ref }} @@ -173,7 +174,7 @@ jobs: PRECHECK_BUNDLED_GEMS: 'no' SYNTAX_SUGGEST_TIMEOUT: '5' YJIT_BINDGEN_DIFF_OPTS: '--exit-code' - continue-on-error: ${{ matrix.test_task == 'yjit-bench' }} + continue-on-error: ${{ matrix.continue-on-test_task || false }} - name: Show ${{ github.event.pull_request.base.ref }} GitHub URL for yjit-bench comparison run: echo "https://github.com/${BASE_REPO}/commit/${BASE_SHA}" From e0f4c4e410a0e4c6cda67e9000696c8f1f01d8aa Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 28 Jan 2024 12:46:07 +0900 Subject: [PATCH 587/640] Provisionally ignore panics that happen in these days often [ci skip] ``` ruby: YJIT has panicked. More info to follow... thread '' panicked at src/core.rs:2751:9: assertion `left == right` failed: each stub expects a particular iseq left: 0x7fc8d8e09850 right: 0x7fc8d2c2f3a0 stack backtrace: 0: rust_begin_unwind at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/std/src/panicking.rs:645:5 1: core::panicking::panic_fmt at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/panicking.rs:72:14 2: core::panicking::assert_failed_inner 3: core::panicking::assert_failed at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/core/src/panicking.rs:279:5 4: yjit::core::branch_stub_hit_body at /home/runner/work/ruby/ruby/src/yjit/src/core.rs:2751:9 5: yjit::core::branch_stub_hit::{{closure}}::{{closure}} at /home/runner/work/ruby/ruby/src/yjit/src/core.rs:2696:36 6: yjit::stats::with_compile_time at /home/runner/work/ruby/ruby/src/yjit/src/stats.rs:979:15 7: yjit::core::branch_stub_hit::{{closure}} at /home/runner/work/ruby/ruby/src/yjit/src/core.rs:2696:13 8: std::panicking::try::do_call at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/std/src/panicking.rs:552:40 9: __rust_try 10: std::panicking::try at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/std/src/panicking.rs:516:19 11: std::panic::catch_unwind at /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112/library/std/src/panic.rs:142:14 12: yjit::cruby::with_vm_lock at /home/runner/work/ruby/ruby/src/yjit/src/cruby.rs:647:21 13: yjit::core::branch_stub_hit at /home/runner/work/ruby/ruby/src/yjit/src/core.rs:2695:9 14: ``` --- .github/workflows/yjit-macos.yml | 1 + .github/workflows/yjit-ubuntu.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/yjit-macos.yml b/.github/workflows/yjit-macos.yml index 93bbb4d93ed587..1bab65f53ec9a3 100644 --- a/.github/workflows/yjit-macos.yml +++ b/.github/workflows/yjit-macos.yml @@ -66,6 +66,7 @@ jobs: - test_task: 'check' configure: '--enable-yjit=dev' yjit_opts: '--yjit-call-threshold=1 --yjit-verify-ctx --yjit-code-gc' + continue-on-test_task: true # provisionally fail-fast: false env: diff --git a/.github/workflows/yjit-ubuntu.yml b/.github/workflows/yjit-ubuntu.yml index 437f3d53397083..59c8d21068d333 100644 --- a/.github/workflows/yjit-ubuntu.yml +++ b/.github/workflows/yjit-ubuntu.yml @@ -102,6 +102,7 @@ jobs: - test_task: 'check' configure: '--enable-yjit=dev' yjit_opts: '--yjit-call-threshold=1 --yjit-verify-ctx --yjit-code-gc' + continue-on-test_task: true # provisionally - test_task: 'test-bundled-gems' configure: '--enable-yjit=dev' From f475dc1cd219240b31a1958e6df00b8582a259f5 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 26 Jan 2024 10:56:44 +0900 Subject: [PATCH 588/640] [ruby/digest] [DOC] Add .document https://github.com/ruby/digest/commit/6db96aa99a --- ext/digest/.document | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 ext/digest/.document diff --git a/ext/digest/.document b/ext/digest/.document new file mode 100644 index 00000000000000..beab275b5a015a --- /dev/null +++ b/ext/digest/.document @@ -0,0 +1,3 @@ +digest.c +bubblebabble/bubblebabble.c +*/*init.c From 81702b4b873c0e2b4247095b3b9462bcf34166ff Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 26 Jan 2024 12:13:21 +0900 Subject: [PATCH 589/640] [ruby/digest] Prefer `rb_const_get` over `rb_path2class` for direct constants https://github.com/ruby/digest/commit/e5d30394b3 --- ext/digest/bubblebabble/bubblebabble.c | 7 +++---- ext/digest/md5/md5init.c | 3 +-- ext/digest/rmd160/rmd160init.c | 3 +-- ext/digest/sha1/sha1init.c | 3 +-- ext/digest/sha2/sha2init.c | 5 ++++- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/ext/digest/bubblebabble/bubblebabble.c b/ext/digest/bubblebabble/bubblebabble.c index 358ab416b97b64..dac603c0d7a0e8 100644 --- a/ext/digest/bubblebabble/bubblebabble.c +++ b/ext/digest/bubblebabble/bubblebabble.c @@ -129,15 +129,14 @@ Init_bubblebabble(void) rb_require("digest"); - rb_mDigest = rb_path2class("Digest"); - rb_mDigest_Instance = rb_path2class("Digest::Instance"); - rb_cDigest_Class = rb_path2class("Digest::Class"); - #if 0 rb_mDigest = rb_define_module("Digest"); rb_mDigest_Instance = rb_define_module_under(rb_mDigest, "Instance"); rb_cDigest_Class = rb_define_class_under(rb_mDigest, "Class", rb_cObject); #endif + rb_mDigest = rb_digest_namespace(); + rb_mDigest_Instance = rb_const_get(rb_mDigest, rb_intern_const("Instance")); + rb_cDigest_Class = rb_const_get(rb_mDigest, rb_intern_const("Class")); rb_define_module_function(rb_mDigest, "bubblebabble", rb_digest_s_bubblebabble, 1); rb_define_singleton_method(rb_cDigest_Class, "bubblebabble", rb_digest_class_s_bubblebabble, -1); diff --git a/ext/digest/md5/md5init.c b/ext/digest/md5/md5init.c index 52cba78bf1131c..b81fd9486499db 100644 --- a/ext/digest/md5/md5init.c +++ b/ext/digest/md5/md5init.c @@ -53,9 +53,8 @@ Init_md5(void) mDigest = rb_define_module("Digest"); /* let rdoc know */ #endif mDigest = rb_digest_namespace(); - cDigest_Base = rb_path2class("Digest::Base"); + cDigest_Base = rb_const_get(mDigest, rb_intern_const("Base")); cDigest_MD5 = rb_define_class_under(mDigest, "MD5", cDigest_Base); - rb_iv_set(cDigest_MD5, "metadata", rb_digest_make_metadata(&md5)); } diff --git a/ext/digest/rmd160/rmd160init.c b/ext/digest/rmd160/rmd160init.c index 2ae81ec4d60346..e4b707ed9e0dd8 100644 --- a/ext/digest/rmd160/rmd160init.c +++ b/ext/digest/rmd160/rmd160init.c @@ -49,9 +49,8 @@ Init_rmd160(void) mDigest = rb_define_module("Digest"); /* let rdoc know */ #endif mDigest = rb_digest_namespace(); - cDigest_Base = rb_path2class("Digest::Base"); + cDigest_Base = rb_const_get(mDigest, rb_intern_const("Base")); cDigest_RMD160 = rb_define_class_under(mDigest, "RMD160", cDigest_Base); - rb_iv_set(cDigest_RMD160, "metadata", rb_digest_make_metadata(&rmd160)); } diff --git a/ext/digest/sha1/sha1init.c b/ext/digest/sha1/sha1init.c index f7047bc6d3c3c1..c39959f428ac04 100644 --- a/ext/digest/sha1/sha1init.c +++ b/ext/digest/sha1/sha1init.c @@ -55,9 +55,8 @@ Init_sha1(void) mDigest = rb_define_module("Digest"); /* let rdoc know */ #endif mDigest = rb_digest_namespace(); - cDigest_Base = rb_path2class("Digest::Base"); + cDigest_Base = rb_const_get(mDigest, rb_intern_const("Base")); cDigest_SHA1 = rb_define_class_under(mDigest, "SHA1", cDigest_Base); - rb_iv_set(cDigest_SHA1, "metadata", rb_digest_make_metadata(&sha1)); } diff --git a/ext/digest/sha2/sha2init.c b/ext/digest/sha2/sha2init.c index 94cccf3febb936..ec48f3d8e65cd3 100644 --- a/ext/digest/sha2/sha2init.c +++ b/ext/digest/sha2/sha2init.c @@ -40,8 +40,11 @@ Init_sha2(void) FOREACH_BITLEN(DECLARE_ALGO_CLASS) +#if 0 + mDigest = rb_define_module("Digest"); /* let rdoc know */ +#endif mDigest = rb_digest_namespace(); - cDigest_Base = rb_path2class("Digest::Base"); + cDigest_Base = rb_const_get(mDigest, rb_intern_const("Base")); #define DEFINE_ALGO_CLASS(bitlen) \ cDigest_SHA##bitlen = rb_define_class_under(mDigest, "SHA" #bitlen, cDigest_Base); \ From d3e6bcd37fd10a0356a0d07d079670bb7247299b Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 26 Jan 2024 12:15:59 +0900 Subject: [PATCH 590/640] [ruby/digest] [DOC] Expand `Digest::SHA2` definitions for RDoc Since RDoc searches `var = rb_define_class_under(...)` statements literally, they cannot be built by macros. https://github.com/ruby/digest/commit/d39b684f91 --- ext/digest/sha2/sha2init.c | 42 +++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/ext/digest/sha2/sha2init.c b/ext/digest/sha2/sha2init.c index ec48f3d8e65cd3..3923e3724c3eed 100644 --- a/ext/digest/sha2/sha2init.c +++ b/ext/digest/sha2/sha2init.c @@ -25,32 +25,50 @@ static const rb_digest_metadata_t sha##bitlen = { \ FOREACH_BITLEN(DEFINE_ALGO_METADATA) /* + * Document-class: Digest::SHA256 < Digest::Base + * * Classes for calculating message digests using the SHA-256/384/512 * Secure Hash Algorithm(s) by NIST (the US' National Institute of * Standards and Technology), described in FIPS PUB 180-2. + * + * See SHA2. + */ +/* + * Document-class: Digest::SHA384 < Digest::Base + * + * Classes for calculating message digests using the SHA-256/384/512 + * Secure Hash Algorithm(s) by NIST (the US' National Institute of + * Standards and Technology), described in FIPS PUB 180-2. + * + * See SHA2. + */ +/* + * Document-class: Digest::SHA512 < Digest::Base + * + * Classes for calculating message digests using the SHA-256/384/512 + * Secure Hash Algorithm(s) by NIST (the US' National Institute of + * Standards and Technology), described in FIPS PUB 180-2. + * + * See SHA2. */ void Init_sha2(void) { - VALUE mDigest, cDigest_Base; + VALUE mDigest, cDigest_Base, cDigest_SHA2; ID id_metadata = rb_id_metadata(); -#define DECLARE_ALGO_CLASS(bitlen) \ - VALUE cDigest_SHA##bitlen; - - FOREACH_BITLEN(DECLARE_ALGO_CLASS) - #if 0 mDigest = rb_define_module("Digest"); /* let rdoc know */ #endif mDigest = rb_digest_namespace(); cDigest_Base = rb_const_get(mDigest, rb_intern_const("Base")); -#define DEFINE_ALGO_CLASS(bitlen) \ - 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)); + cDigest_SHA2 = rb_define_class_under(mDigest, "SHA256", cDigest_Base); + rb_ivar_set(cDigest_SHA2, id_metadata, rb_digest_make_metadata(&sha256)); + + cDigest_SHA2 = rb_define_class_under(mDigest, "SHA384", cDigest_Base); + rb_ivar_set(cDigest_SHA2, id_metadata, rb_digest_make_metadata(&sha384)); - FOREACH_BITLEN(DEFINE_ALGO_CLASS) + cDigest_SHA2 = rb_define_class_under(mDigest, "SHA512", cDigest_Base); + rb_ivar_set(cDigest_SHA2, id_metadata, rb_digest_make_metadata(&sha512)); } From fed877c791f1c16a2b1a2c9a167b7f433505794d Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 28 Jan 2024 01:02:11 +0900 Subject: [PATCH 591/640] [Bug #20217] `return` with `ensure` is a void value expression --- parse.y | 17 +++++++++++++++-- test/ruby/test_parse.rb | 7 ++++++- test/ruby/test_syntax.rb | 1 - 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/parse.y b/parse.y index 3dd8ecd39f6f8a..359a0cc261b947 100644 --- a/parse.y +++ b/parse.y @@ -14296,12 +14296,21 @@ value_expr_check(struct parser_params *p, NODE *node) } while (node) { switch (nd_type(node)) { + case NODE_ENSURE: + vn = RNODE_ENSURE(node)->nd_head; + node = RNODE_ENSURE(node)->nd_ensr; + /* nd_ensr should not be NULL, check it out next */ + if (vn && (vn = value_expr_check(p, vn))) { + goto found; + } + break; + case NODE_RETURN: case NODE_BREAK: case NODE_NEXT: case NODE_REDO: case NODE_RETRY: - return void_node ? void_node : node; + goto found; case NODE_CASE3: if (!RNODE_CASE3(node)->nd_body || !nd_type_p(RNODE_CASE3(node)->nd_body, NODE_IN)) { @@ -14312,7 +14321,7 @@ value_expr_check(struct parser_params *p, NODE *node) return NULL; } /* single line pattern matching with "=>" operator */ - return void_node ? void_node : node; + goto found; case NODE_BLOCK: while (RNODE_BLOCK(node)->nd_next) { @@ -14356,6 +14365,10 @@ value_expr_check(struct parser_params *p, NODE *node) } return NULL; + + found: + /* return the first found node */ + return void_node ? void_node : node; } static int diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb index 858c623bcc964c..7d7e7eebc0e583 100644 --- a/test/ruby/test_parse.rb +++ b/test/ruby/test_parse.rb @@ -1434,7 +1434,12 @@ def test_cdmarg_after_command_args_and_tlbrace_arg def test_void_value_in_rhs w = "void value expression" - ["x = return 1", "x = return, 1", "x = 1, return", "x, y = return"].each do |code| + [ + "x = return 1", "x = return, 1", "x = 1, return", "x, y = return", + "x = begin return ensure end", + "x = begin ensure return end", + "x = begin return ensure return end", + ].each do |code| ex = assert_syntax_error(code, w) assert_equal(1, ex.message.scan(w).size, ->{"same #{w.inspect} warning should be just once\n#{w.message}"}) end diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb index 7ca7e2bcf7655a..954ad5615656c7 100644 --- a/test/ruby/test_syntax.rb +++ b/test/ruby/test_syntax.rb @@ -1411,7 +1411,6 @@ def test_return_toplevel "#{return}" raise((return; "should not raise")) begin raise; ensure return; end; self - begin raise; ensure return; end and self nil&defined?0--begin e=no_method_error(); return; 0;end return puts('ignored') #=> ignored BEGIN {return} From 5f733a1ae7e5fd20d4cba61af5408b33204fe8fc Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 28 Jan 2024 11:09:55 +0900 Subject: [PATCH 592/640] [Bug #20217] `rescue` block is void only if all children are void --- parse.y | 20 ++++++++++++++++++++ test/ruby/test_parse.rb | 8 ++++++++ 2 files changed, 28 insertions(+) diff --git a/parse.y b/parse.y index 359a0cc261b947..5b9955a66a93e7 100644 --- a/parse.y +++ b/parse.y @@ -14305,6 +14305,26 @@ value_expr_check(struct parser_params *p, NODE *node) } break; + case NODE_RESCUE: + /* void only if all children are void */ + vn = RNODE_RESCUE(node)->nd_head; + if (!vn || !(vn = value_expr_check(p, vn))) return NULL; + if (!void_node) void_node = vn; + for (NODE *r = RNODE_RESCUE(node)->nd_resq; r; r = RNODE_RESBODY(r)->nd_next) { + if (!nd_type_p(r, NODE_RESBODY)) { + compile_error(p, "unexpected node"); + return NULL; + } + if (!(vn = value_expr_check(p, RNODE_RESBODY(r)->nd_body))) { + void_node = 0; + break; + } + if (!void_node) void_node = vn; + } + node = RNODE_RESCUE(node)->nd_else; + if (!node) return void_node; + break; + case NODE_RETURN: case NODE_BREAK: case NODE_NEXT: diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb index 7d7e7eebc0e583..f68bf96cd1f220 100644 --- a/test/ruby/test_parse.rb +++ b/test/ruby/test_parse.rb @@ -1439,10 +1439,18 @@ def test_void_value_in_rhs "x = begin return ensure end", "x = begin ensure return end", "x = begin return ensure return end", + "x = begin return; rescue; return end", + "x = begin return; rescue; return; else return end", ].each do |code| ex = assert_syntax_error(code, w) assert_equal(1, ex.message.scan(w).size, ->{"same #{w.inspect} warning should be just once\n#{w.message}"}) end + [ + "x = begin return; rescue; end", + "x = begin return; rescue; return; else end", + ].each do |code| + assert_valid_syntax(code) + end end def eval_separately(code) From 23b8337cd10329020d74a2f0d8e43434645c4d5b Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 28 Jan 2024 17:59:13 +0900 Subject: [PATCH 593/640] [Bug #20219] `gettable` returns NULL on error --- parse.y | 5 ++++- test/ruby/test_syntax.rb | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/parse.y b/parse.y index 5b9955a66a93e7..e87c98d4ffb7a0 100644 --- a/parse.y +++ b/parse.y @@ -5879,7 +5879,10 @@ p_var_ref : '^' tIDENTIFIER { /*%%%*/ NODE *n = gettable(p, $2, &@$); - if (!(nd_type_p(n, NODE_LVAR) || nd_type_p(n, NODE_DVAR))) { + if (!n) { + n = NEW_ERROR(&@$); + } + else if (!(nd_type_p(n, NODE_LVAR) || nd_type_p(n, NODE_DVAR))) { compile_error(p, "%"PRIsVALUE": no such local variable", rb_id2str($2)); } $$ = n; diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb index 954ad5615656c7..854fd46027c489 100644 --- a/test/ruby/test_syntax.rb +++ b/test/ruby/test_syntax.rb @@ -381,6 +381,7 @@ def test_keyword_self_reference assert_syntax_error("def foo(var: var) var end", message) assert_syntax_error("def foo(var: bar(var)) var end", message) assert_syntax_error("def foo(var: bar {var}) var end", message) + assert_syntax_error("def foo(var: (1 in ^var)); end", message) o = Object.new assert_warn("") do @@ -446,6 +447,7 @@ def test_optional_self_reference assert_syntax_error("def foo(var = bar {var}) var end", message) assert_syntax_error("def foo(var = (def bar;end; var)) var end", message) assert_syntax_error("def foo(var = (def self.bar;end; var)) var end", message) + assert_syntax_error("def foo(var = (1 in ^var)); end", message) o = Object.new assert_warn("") do From c1666158373398c6f58e637adfe31ddad8c8ce00 Mon Sep 17 00:00:00 2001 From: Masato Nakamura Date: Sun, 28 Jan 2024 21:38:47 +0900 Subject: [PATCH 594/640] [ruby/reline] Add metadata for rubygems.org (https://github.com/ruby/reline/pull/638) https://github.com/ruby/reline/commit/d3a324d22c --- lib/reline/reline.gemspec | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/reline/reline.gemspec b/lib/reline/reline.gemspec index 7bf1f8758bf428..dfaf966728942d 100644 --- a/lib/reline/reline.gemspec +++ b/lib/reline/reline.gemspec @@ -18,6 +18,11 @@ Gem::Specification.new do |spec| spec.files = Dir['BSDL', 'COPYING', 'README.md', 'license_of_rb-readline', 'lib/**/*'] spec.require_paths = ['lib'] + spec.metadata = { + "bug_tracker_uri" => "https://github.com/ruby/reline/issues", + "changelog_uri" => "https://github.com/ruby/reline/releases", + "source_code_uri" => "https://github.com/ruby/reline" + } spec.required_ruby_version = Gem::Requirement.new('>= 2.6') From 853bcf65c767594b37d9c7639df5a2894c716d6a Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 31 Dec 2023 16:07:31 +0900 Subject: [PATCH 595/640] [ruby/win32ole] Rename `WIN32OLE::VARIANT` as `WIN32OLE::VariantType` Prevent name clash with `WIN32OLE::Variant`, of generated document files on case-insensitive filesystems, such as Windows. https://github.com/ruby/win32ole/commit/049e5f0a6e --- ext/win32ole/win32ole_variant_m.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ext/win32ole/win32ole_variant_m.c b/ext/win32ole/win32ole_variant_m.c index c285a001776695..d879506be3b83c 100644 --- a/ext/win32ole/win32ole_variant_m.c +++ b/ext/win32ole/win32ole_variant_m.c @@ -5,16 +5,18 @@ VALUE mWIN32OLE_VARIANT; void Init_win32ole_variant_m(void) { /* - * Document-module: WIN32OLE::VARIANT + * Document-module: WIN32OLE::VariantType * - * The WIN32OLE::VARIANT module includes constants of VARIANT type constants. - * The constants is used when creating WIN32OLE_VARIANT object. + * The +WIN32OLE::VariantType+ module includes constants of VARIANT type constants. + * The constants is used when creating WIN32OLE::Variant object. * - * obj = WIN32OLE_VARIANT.new("2e3", WIN32OLE::VARIANT::VT_R4) + * obj = WIN32OLE::Variant.new("2e3", WIN32OLE::VARIANT::VT_R4) * obj.value # => 2000.0 * */ - mWIN32OLE_VARIANT = rb_define_module_under(cWIN32OLE, "VARIANT"); + mWIN32OLE_VARIANT = rb_define_module_under(cWIN32OLE, "VariantType"); + /* Alias of WIN32OLE::VariantType, for the backward compatibility */ + rb_define_const(cWIN32OLE, "VARIANT", mWIN32OLE_VARIANT); /* * represents VT_EMPTY type constant. From 1bc48684cdaf72375a2b094ae963b7d6d125140f Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 31 Dec 2023 16:38:03 +0900 Subject: [PATCH 596/640] [ruby/win32ole] Rename `WIN32OLE::Typelib` as `WIN32OLE::TypeLib` https://github.com/ruby/win32ole/commit/5feede2cc5 --- ext/win32ole/win32ole_typelib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/win32ole/win32ole_typelib.c b/ext/win32ole/win32ole_typelib.c index fb68bebda875ab..84dca9e0e1f367 100644 --- a/ext/win32ole/win32ole_typelib.c +++ b/ext/win32ole/win32ole_typelib.c @@ -827,7 +827,7 @@ VALUE cWIN32OLE_TYPELIB; void Init_win32ole_typelib(void) { - cWIN32OLE_TYPELIB = rb_define_class_under(cWIN32OLE, "Typelib", rb_cObject); + cWIN32OLE_TYPELIB = rb_define_class_under(cWIN32OLE, "TypeLib", rb_cObject); rb_define_const(rb_cObject, "WIN32OLE_TYPELIB", cWIN32OLE_TYPELIB); rb_define_singleton_method(cWIN32OLE_TYPELIB, "typelibs", foletypelib_s_typelibs, 0); rb_define_alloc_func(cWIN32OLE_TYPELIB, foletypelib_s_allocate); From baef72da3601b541cb04aca310fee63eec18964f Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 31 Dec 2023 16:49:09 +0900 Subject: [PATCH 597/640] [ruby/win32ole] [DOC] Update class names using the scoped names https://github.com/ruby/win32ole/commit/2c5d193da7 --- ext/win32ole/win32ole.c | 92 +++++++++++----------- ext/win32ole/win32ole_event.c | 51 ++++++------ ext/win32ole/win32ole_method.c | 123 ++++++++++++++--------------- ext/win32ole/win32ole_param.c | 85 ++++++++++---------- ext/win32ole/win32ole_record.c | 47 +++++------ ext/win32ole/win32ole_type.c | 130 ++++++++++++++++--------------- ext/win32ole/win32ole_typelib.c | 69 ++++++++-------- ext/win32ole/win32ole_variable.c | 35 +++++---- ext/win32ole/win32ole_variant.c | 63 +++++++-------- 9 files changed, 353 insertions(+), 342 deletions(-) diff --git a/ext/win32ole/win32ole.c b/ext/win32ole/win32ole.c index a060165a1cfd43..d642aab2323515 100644 --- a/ext/win32ole/win32ole.c +++ b/ext/win32ole/win32ole.c @@ -1962,7 +1962,7 @@ ole_bind_obj(VALUE moniker, int argc, VALUE *argv, VALUE self) /* * call-seq: - * WIN32OLE.connect( ole ) --> aWIN32OLE + * connect( ole ) --> aWIN32OLE * * Returns running OLE Automation object or WIN32OLE object from moniker. * 1st argument should be OLE program id or class id or moniker. @@ -2019,7 +2019,7 @@ fole_s_connect(int argc, VALUE *argv, VALUE self) /* * call-seq: - * WIN32OLE.const_load( ole, mod = WIN32OLE) + * const_load( ole, mod = WIN32OLE) * * Defines the constants of OLE Automation server as mod's constants. * The first argument is WIN32OLE object or type library name. @@ -2124,7 +2124,7 @@ reference_count(struct oledata * pole) /* * call-seq: - * WIN32OLE.ole_reference_count(aWIN32OLE) --> number + * ole_reference_count(aWIN32OLE) --> number * * Returns reference counter of Dispatch interface of WIN32OLE object. * You should not use this method because this method @@ -2140,7 +2140,7 @@ fole_s_reference_count(VALUE self, VALUE obj) /* * call-seq: - * WIN32OLE.ole_free(aWIN32OLE) --> number + * ole_free(aWIN32OLE) --> number * * Invokes Release method of Dispatch interface of WIN32OLE object. * You should not use this method because this method @@ -2184,10 +2184,10 @@ ole_show_help(VALUE helpfile, VALUE helpcontext) /* * call-seq: - * WIN32OLE.ole_show_help(obj [,helpcontext]) + * ole_show_help(obj [,helpcontext]) * - * Displays helpfile. The 1st argument specifies WIN32OLE_TYPE - * object or WIN32OLE_METHOD object or helpfile. + * Displays helpfile. The 1st argument specifies WIN32OLE::Type + * object or WIN32OLE::Method object or helpfile. * * excel = WIN32OLE.new('Excel.Application') * typeobj = excel.ole_type @@ -2227,7 +2227,7 @@ fole_s_show_help(int argc, VALUE *argv, VALUE self) /* * call-seq: - * WIN32OLE.codepage + * codepage * * Returns current codepage. * WIN32OLE.codepage # => WIN32OLE::CP_ACP @@ -2258,7 +2258,7 @@ code_page_installed(UINT cp) /* * call-seq: - * WIN32OLE.codepage = CP + * codepage = CP * * Sets current codepage. * The WIN32OLE.codepage is initialized according to @@ -2282,7 +2282,7 @@ fole_s_set_code_page(VALUE self, VALUE vcp) /* * call-seq: - * WIN32OLE.locale -> locale id. + * locale -> locale id. * * Returns current locale id (lcid). The default locale is * WIN32OLE::LOCALE_SYSTEM_DEFAULT. @@ -2316,12 +2316,12 @@ lcid_installed(LCID lcid) /* * call-seq: - * WIN32OLE.locale = lcid + * locale = lcid * * Sets current locale id (lcid). * * WIN32OLE.locale = 1033 # set locale English(U.S) - * obj = WIN32OLE_VARIANT.new("$100,000", WIN32OLE::VARIANT::VT_CY) + * obj = WIN32OLE::Variant.new("$100,000", WIN32OLE::VARIANT::VT_CY) * */ static VALUE @@ -2345,7 +2345,7 @@ fole_s_set_locale(VALUE self, VALUE vlcid) /* * call-seq: - * WIN32OLE.create_guid + * create_guid * * Creates GUID. * WIN32OLE.create_guid # => {1CB530F1-F6B1-404D-BCE6-1959BF91F4A8} @@ -2393,9 +2393,9 @@ fole_s_ole_uninitialize(VALUE self) /* * Document-class: WIN32OLE * - * WIN32OLE objects represent OLE Automation object in Ruby. + * +WIN32OLE+ objects represent OLE Automation object in Ruby. * - * By using WIN32OLE, you can access OLE server like VBScript. + * By using +WIN32OLE+, you can access OLE server like VBScript. * * Here is sample script. * @@ -2419,18 +2419,18 @@ fole_s_ole_uninitialize(VALUE self) * excel.ActiveWorkbook.Close(0); * excel.Quit(); * - * Unfortunately, Win32OLE doesn't support the argument passed by + * Unfortunately, +WIN32OLE+ doesn't support the argument passed by * reference directly. - * Instead, Win32OLE provides WIN32OLE::ARGV or WIN32OLE_VARIANT object. + * Instead, +WIN32OLE+ provides WIN32OLE::ARGV or WIN32OLE::Variant object. * If you want to get the result value of argument passed by reference, - * you can use WIN32OLE::ARGV or WIN32OLE_VARIANT. + * you can use WIN32OLE::ARGV or WIN32OLE::Variant. * * oleobj.method(arg1, arg2, refargv3) * puts WIN32OLE::ARGV[2] # the value of refargv3 after called oleobj.method * * or * - * refargv3 = WIN32OLE_VARIANT.new(XXX, + * refargv3 = WIN32OLE::Variant.new(XXX, * WIN32OLE::VARIANT::VT_BYREF|WIN32OLE::VARIANT::VT_XXX) * oleobj.method(arg1, arg2, refargv3) * p refargv3.value # the value of refargv3 after called oleobj.method. @@ -2439,7 +2439,7 @@ fole_s_ole_uninitialize(VALUE self) /* * call-seq: - * WIN32OLE.new(server, [host]) -> WIN32OLE object + * new(server, [host]) -> WIN32OLE object * WIN32OLE.new(server, license: 'key') -> WIN32OLE object * * Returns a new WIN32OLE object(OLE Automation object). @@ -2826,7 +2826,7 @@ ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket) /* * call-seq: - * WIN32OLE#invoke(method, [arg1,...]) => return value of method. + * invoke(method, [arg1,...]) => return value of method. * * Runs OLE method. * The first argument specifies the method name of OLE Automation object. @@ -3038,7 +3038,7 @@ ole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types, USHORT dispkind) /* * call-seq: - * WIN32OLE#_invoke(dispid, args, types) + * _invoke(dispid, args, types) * * Runs the early binding method. * The 1st argument specifies dispatch ID, @@ -3056,7 +3056,7 @@ fole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types) /* * call-seq: - * WIN32OLE#_getproperty(dispid, args, types) + * _getproperty(dispid, args, types) * * Runs the early binding method to get property. * The 1st argument specifies dispatch ID, @@ -3074,7 +3074,7 @@ fole_getproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types) /* * call-seq: - * WIN32OLE#_setproperty(dispid, args, types) + * _setproperty(dispid, args, types) * * Runs the early binding method to set property. * The 1st argument specifies dispatch ID, @@ -3120,7 +3120,7 @@ fole_setproperty_with_bracket(int argc, VALUE *argv, VALUE self) /* * call-seq: - * WIN32OLE.setproperty('property', [arg1, arg2,...] val) + * setproperty('property', [arg1, arg2,...] val) * * Sets property of OLE object. * When you want to set property with argument, you can use this method. @@ -3226,7 +3226,7 @@ ole_propertyput(VALUE self, VALUE property, VALUE value) /* * call-seq: - * WIN32OLE#ole_free + * ole_free * * invokes Release method of Dispatch interface of WIN32OLE object. * Usually, you do not need to call this method because Release method @@ -3269,7 +3269,7 @@ ole_ienum_free(VALUE pEnumV) /* * call-seq: - * WIN32OLE#each {|i|...} + * each {|i|...} * * Iterates over each item of OLE collection which has IEnumVARIANT interface. * @@ -3340,7 +3340,7 @@ fole_each(VALUE self) /* * call-seq: - * WIN32OLE#method_missing(id [,arg1, arg2, ...]) + * method_missing(id [,arg1, arg2, ...]) * * Calls WIN32OLE#invoke method. */ @@ -3438,9 +3438,9 @@ ole_methods(VALUE self, int mask) /* * call-seq: - * WIN32OLE#ole_methods + * ole_methods * - * Returns the array of WIN32OLE_METHOD object. + * Returns the array of WIN32OLE::Method object. * The element is OLE method of WIN32OLE object. * * excel = WIN32OLE.new('Excel.Application') @@ -3455,9 +3455,9 @@ fole_methods(VALUE self) /* * call-seq: - * WIN32OLE#ole_get_methods + * ole_get_methods * - * Returns the array of WIN32OLE_METHOD object . + * Returns the array of WIN32OLE::Method object . * The element of the array is property (gettable) of WIN32OLE object. * * excel = WIN32OLE.new('Excel.Application') @@ -3471,9 +3471,9 @@ fole_get_methods(VALUE self) /* * call-seq: - * WIN32OLE#ole_put_methods + * ole_put_methods * - * Returns the array of WIN32OLE_METHOD object . + * Returns the array of WIN32OLE::Method object . * The element of the array is property (settable) of WIN32OLE object. * * excel = WIN32OLE.new('Excel.Application') @@ -3487,9 +3487,9 @@ fole_put_methods(VALUE self) /* * call-seq: - * WIN32OLE#ole_func_methods + * ole_func_methods * - * Returns the array of WIN32OLE_METHOD object . + * Returns the array of WIN32OLE::Method object . * The element of the array is property (settable) of WIN32OLE object. * * excel = WIN32OLE.new('Excel.Application') @@ -3504,9 +3504,9 @@ fole_func_methods(VALUE self) /* * call-seq: - * WIN32OLE#ole_type + * ole_type * - * Returns WIN32OLE_TYPE object. + * Returns WIN32OLE::Type object. * * excel = WIN32OLE.new('Excel.Application') * tobj = excel.ole_type @@ -3536,9 +3536,9 @@ fole_type(VALUE self) /* * call-seq: - * WIN32OLE#ole_typelib -> The WIN32OLE_TYPELIB object + * ole_typelib -> The WIN32OLE_TYPELIB object * - * Returns the WIN32OLE_TYPELIB object. The object represents the + * Returns the WIN32OLE::TypeLib object. The object represents the * type library which contains the WIN32OLE object. * * excel = WIN32OLE.new('Excel.Application') @@ -3570,7 +3570,7 @@ fole_typelib(VALUE self) /* * call-seq: - * WIN32OLE#ole_query_interface(iid) -> WIN32OLE object + * ole_query_interface(iid) -> WIN32OLE object * * Returns WIN32OLE object for a specific dispatch or dual * interface specified by iid. @@ -3616,7 +3616,7 @@ fole_query_interface(VALUE self, VALUE str_iid) /* * call-seq: - * WIN32OLE#ole_respond_to?(method) -> true or false + * ole_respond_to?(method) -> true or false * * Returns true when OLE object has OLE method, otherwise returns false. * @@ -3825,9 +3825,9 @@ ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails) /* * call-seq: - * WIN32OLE#ole_method_help(method) + * ole_method_help(method) * - * Returns WIN32OLE_METHOD object corresponding with method + * Returns WIN32OLE::Method object corresponding with method * specified by 1st argument. * * excel = WIN32OLE.new('Excel.Application') @@ -3859,7 +3859,7 @@ fole_method_help(VALUE self, VALUE cmdname) /* * call-seq: - * WIN32OLE#ole_activex_initialize() -> Qnil + * ole_activex_initialize() -> Qnil * * Initialize WIN32OLE object(ActiveX Control) by calling * IPersistMemory::InitNew. @@ -4073,7 +4073,7 @@ Init_win32ole(void) * p c # => 0 * p WIN32OLE::ARGV # => [10, 20, 30] * - * You can use WIN32OLE_VARIANT object to retrieve the value of reference + * You can use WIN32OLE::Variant object to retrieve the value of reference * arguments instead of referring WIN32OLE::ARGV. * */ diff --git a/ext/win32ole/win32ole_event.c b/ext/win32ole/win32ole_event.c index 45ebf13433fb13..ff6835e3e4ebf2 100644 --- a/ext/win32ole/win32ole_event.c +++ b/ext/win32ole/win32ole_event.c @@ -1,9 +1,9 @@ #include "win32ole.h" /* - * Document-class: WIN32OLE_EVENT + * Document-class: WIN32OLE::Event * - * WIN32OLE_EVENT objects controls OLE event. + * +WIN32OLE::Event+ objects controls OLE event. */ RUBY_EXTERN void rb_write_error_str(VALUE mesg); @@ -974,13 +974,13 @@ ev_advise(int argc, VALUE *argv, VALUE self) /* * call-seq: - * WIN32OLE_EVENT.new(ole, event) #=> WIN32OLE_EVENT object. + * new(ole, event) #=> WIN32OLE::Event object. * * Returns OLE event object. * The first argument specifies WIN32OLE object. * The second argument specifies OLE event name. * ie = WIN32OLE.new('InternetExplorer.Application') - * ev = WIN32OLE_EVENT.new(ie, 'DWebBrowserEvents') + * ev = WIN32OLE::Event.new(ie, 'DWebBrowserEvents') */ static VALUE fev_initialize(int argc, VALUE *argv, VALUE self) @@ -1004,7 +1004,7 @@ ole_msg_loop(void) /* * call-seq: - * WIN32OLE_EVENT.message_loop + * message_loop * * Translates and dispatches Windows message. */ @@ -1052,7 +1052,7 @@ ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg) /* * call-seq: - * WIN32OLE_EVENT#on_event([event]){...} + * on_event([event]){...} * * Defines the callback event. * If argument is omitted, this method defines the callback of all events. @@ -1061,12 +1061,12 @@ ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg) * use `return' or :return. * * ie = WIN32OLE.new('InternetExplorer.Application') - * ev = WIN32OLE_EVENT.new(ie) + * ev = WIN32OLE::Event.new(ie) * ev.on_event("NavigateComplete") {|url| puts url} * ev.on_event() {|ev, *args| puts "#{ev} fired"} * * ev.on_event("BeforeNavigate2") {|*args| - * ... + * # ... * # set true to BeforeNavigate reference argument `Cancel'. * # Cancel is 7-th argument of BeforeNavigate, * # so you can use 6 as key of hash instead of 'Cancel'. @@ -1075,7 +1075,7 @@ ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg) * {:Cancel => true} # or {'Cancel' => true} or {6 => true} * } * - * ev.on_event(...) {|*args| + * ev.on_event(event_name) {|*args| * {:return => 1, :xxx => yyy} * } */ @@ -1087,14 +1087,14 @@ fev_on_event(int argc, VALUE *argv, VALUE self) /* * call-seq: - * WIN32OLE_EVENT#on_event_with_outargs([event]){...} + * on_event_with_outargs([event]){...} * * Defines the callback of event. * If you want modify argument in callback, - * you could use this method instead of WIN32OLE_EVENT#on_event. + * you could use this method instead of WIN32OLE::Event#on_event. * * ie = WIN32OLE.new('InternetExplorer.Application') - * ev = WIN32OLE_EVENT.new(ie) + * ev = WIN32OLE::Event.new(ie) * ev.on_event_with_outargs('BeforeNavigate2') {|*args| * args.last[6] = true * } @@ -1107,18 +1107,18 @@ fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self) /* * call-seq: - * WIN32OLE_EVENT#off_event([event]) + * off_event([event]) * * removes the callback of event. * * ie = WIN32OLE.new('InternetExplorer.Application') - * ev = WIN32OLE_EVENT.new(ie) + * ev = WIN32OLE::Event.new(ie) * ev.on_event('BeforeNavigate2') {|*args| * args.last[6] = true * } - * ... + * # ... * ev.off_event('BeforeNavigate2') - * ... + * # ... */ static VALUE fev_off_event(int argc, VALUE *argv, VALUE self) @@ -1145,16 +1145,16 @@ fev_off_event(int argc, VALUE *argv, VALUE self) /* * call-seq: - * WIN32OLE_EVENT#unadvise -> nil + * unadvise -> nil * - * disconnects OLE server. If this method called, then the WIN32OLE_EVENT object + * disconnects OLE server. If this method called, then the WIN32OLE::Event object * does not receive the OLE server event any more. * This method is trial implementation. * * ie = WIN32OLE.new('InternetExplorer.Application') - * ev = WIN32OLE_EVENT.new(ie) - * ev.on_event() {...} - * ... + * ev = WIN32OLE::Event.new(ie) + * ev.on_event() { something } + * # ... * ev.unadvise * */ @@ -1201,7 +1201,7 @@ evs_length(void) /* * call-seq: - * WIN32OLE_EVENT#handler= + * handler= * * sets event handler object. If handler object has onXXX * method according to XXX event, then onXXX method is called @@ -1212,7 +1212,7 @@ evs_length(void) * called and 1-st argument is event name. * * If handler object has onXXX method and there is block - * defined by WIN32OLE_EVENT#on_event('XXX'){}, + * defined by on_event('XXX'){}, * then block is executed but handler object method is not called * when XXX event occurs. * @@ -1230,7 +1230,7 @@ evs_length(void) * * handler = Handler.new * ie = WIN32OLE.new('InternetExplorer.Application') - * ev = WIN32OLE_EVENT.new(ie) + * ev = WIN32OLE::Event.new(ie) * ev.on_event("StatusTextChange") {|*args| * puts "this block executed." * puts "handler.onStatusTextChange method is not called." @@ -1246,7 +1246,7 @@ fev_set_handler(VALUE self, VALUE val) /* * call-seq: - * WIN32OLE_EVENT#handler + * handler * * returns handler object. * @@ -1265,6 +1265,7 @@ Init_win32ole_event(void) rb_gc_register_mark_object(ary_ole_event); id_events = rb_intern("events"); cWIN32OLE_EVENT = rb_define_class_under(cWIN32OLE, "Event", rb_cObject); + /* Alias of WIN32OLE::Event, for the backward compatibility */ rb_define_const(rb_cObject, "WIN32OLE_EVENT", cWIN32OLE_EVENT); rb_define_singleton_method(cWIN32OLE_EVENT, "message_loop", fev_s_msg_loop, 0); rb_define_alloc_func(cWIN32OLE_EVENT, fev_s_allocate); diff --git a/ext/win32ole/win32ole_method.c b/ext/win32ole/win32ole_method.c index 646fdaf60c1e46..4b47ca8eed254e 100644 --- a/ext/win32ole/win32ole_method.c +++ b/ext/win32ole/win32ole_method.c @@ -216,9 +216,9 @@ create_win32ole_method(ITypeInfo *pTypeInfo, VALUE name) } /* - * Document-class: WIN32OLE_METHOD + * Document-class: WIN32OLE::Method * - * WIN32OLE_METHOD objects represent OLE method information. + * +WIN32OLE::Method+ objects represent OLE method information. */ static VALUE @@ -251,16 +251,16 @@ folemethod_s_allocate(VALUE klass) /* * call-seq: - * WIN32OLE_METHOD.new(ole_type, method) -> WIN32OLE_METHOD object + * WIN32OLE::Method.new(ole_type, method) -> WIN32OLE::Method object * - * Returns a new WIN32OLE_METHOD object which represents the information + * Returns a new WIN32OLE::Method object which represents the information * about OLE method. - * The first argument ole_type specifies WIN32OLE_TYPE object. + * The first argument ole_type specifies WIN32OLE::Type object. * The second argument method specifies OLE method name defined OLE class - * which represents WIN32OLE_TYPE object. + * which represents WIN32OLE::Type object. * - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') - * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE::Method.new(tobj, 'SaveAs') */ static VALUE folemethod_initialize(VALUE self, VALUE oletype, VALUE method) @@ -284,12 +284,12 @@ folemethod_initialize(VALUE self, VALUE oletype, VALUE method) /* * call-seq: - * WIN32OLE_METHOD#name + * name * * Returns the name of the method. * - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') - * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE::Method.new(tobj, 'SaveAs') * puts method.name # => SaveAs * */ @@ -317,11 +317,11 @@ ole_method_return_type(ITypeInfo *pTypeInfo, UINT method_index) /* * call-seq: - * WIN32OLE_METHOD#return_type + * return_type * * Returns string of return value type of method. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') - * method = WIN32OLE_METHOD.new(tobj, 'Add') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE::Method.new(tobj, 'Add') * puts method.return_type # => Workbook * */ @@ -351,11 +351,11 @@ ole_method_return_vtype(ITypeInfo *pTypeInfo, UINT method_index) /* * call-seq: - * WIN32OLE_METHOD#return_vtype + * return_vtype * * Returns number of return value type of method. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') - * method = WIN32OLE_METHOD.new(tobj, 'Add') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE::Method.new(tobj, 'Add') * puts method.return_vtype # => 26 * */ @@ -385,12 +385,12 @@ ole_method_return_type_detail(ITypeInfo *pTypeInfo, UINT method_index) /* * call-seq: - * WIN32OLE_METHOD#return_type_detail + * return_type_detail * * Returns detail information of return value type of method. * The information is array. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') - * method = WIN32OLE_METHOD.new(tobj, 'Add') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE::Method.new(tobj, 'Add') * p method.return_type_detail # => ["PTR", "USERDEFINED", "Workbook"] */ static VALUE @@ -437,11 +437,11 @@ ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index) /* * call-seq: - * WIN32OLE_METHOD#invkind + * invkind * * Returns the method invoke kind. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') - * method = WIN32OLE_METHOD.new(tobj, 'Add') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE::Method.new(tobj, 'Add') * puts method.invkind # => 1 * */ @@ -455,13 +455,13 @@ folemethod_invkind(VALUE self) /* * call-seq: - * WIN32OLE_METHOD#invoke_kind + * invoke_kind * * Returns the method kind string. The string is "UNKNOWN" or "PROPERTY" * or "PROPERTY" or "PROPERTYGET" or "PROPERTYPUT" or "PROPERTYPPUTREF" * or "FUNC". - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') - * method = WIN32OLE_METHOD.new(tobj, 'Add') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE::Method.new(tobj, 'Add') * puts method.invoke_kind # => "FUNC" */ static VALUE @@ -494,11 +494,11 @@ ole_method_visible(ITypeInfo *pTypeInfo, UINT method_index) /* * call-seq: - * WIN32OLE_METHOD#visible? + * visible? * * Returns true if the method is public. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') - * method = WIN32OLE_METHOD.new(tobj, 'Add') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE::Method.new(tobj, 'Add') * puts method.visible? # => true */ static VALUE @@ -575,11 +575,11 @@ ole_method_event(ITypeInfo *pTypeInfo, UINT method_index, VALUE method_name) /* * call-seq: - * WIN32OLE_METHOD#event? + * event? * * Returns true if the method is event. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') - * method = WIN32OLE_METHOD.new(tobj, 'SheetActivate') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE::Method.new(tobj, 'SheetActivate') * puts method.event? # => true * */ @@ -597,11 +597,11 @@ folemethod_event(VALUE self) /* * call-seq: - * WIN32OLE_METHOD#event_interface + * event_interface * * Returns event interface name if the method is event. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') - * method = WIN32OLE_METHOD.new(tobj, 'SheetActivate') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE::Method.new(tobj, 'SheetActivate') * puts method.event_interface # => WorkbookEvents */ static VALUE @@ -655,12 +655,12 @@ ole_method_helpstring(ITypeInfo *pTypeInfo, UINT method_index) /* * call-seq: - * WIN32OLE_METHOD#helpstring + * helpstring * * Returns help string of OLE method. If the help string is not found, * then the method returns nil. - * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'IWebBrowser') - * method = WIN32OLE_METHOD.new(tobj, 'Navigate') + * tobj = WIN32OLE::Type.new('Microsoft Internet Controls', 'IWebBrowser') + * method = WIN32OLE::Method.new(tobj, 'Navigate') * puts method.helpstring # => Navigates to a URL or file. * */ @@ -686,12 +686,12 @@ ole_method_helpfile(ITypeInfo *pTypeInfo, UINT method_index) /* * call-seq: - * WIN32OLE_METHOD#helpfile + * helpfile * * Returns help file. If help file is not found, then * the method returns nil. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') - * method = WIN32OLE_METHOD.new(tobj, 'Add') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE::Method.new(tobj, 'Add') * puts method.helpfile # => C:\...\VBAXL9.CHM */ static VALUE @@ -717,11 +717,11 @@ ole_method_helpcontext(ITypeInfo *pTypeInfo, UINT method_index) /* * call-seq: - * WIN32OLE_METHOD#helpcontext + * helpcontext * * Returns help context. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') - * method = WIN32OLE_METHOD.new(tobj, 'Add') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE::Method.new(tobj, 'Add') * puts method.helpcontext # => 65717 */ static VALUE @@ -748,11 +748,11 @@ ole_method_dispid(ITypeInfo *pTypeInfo, UINT method_index) /* * call-seq: - * WIN32OLE_METHOD#dispid + * dispid * * Returns dispatch ID. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') - * method = WIN32OLE_METHOD.new(tobj, 'Add') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE::Method.new(tobj, 'Add') * puts method.dispid # => 181 */ static VALUE @@ -779,11 +779,11 @@ ole_method_offset_vtbl(ITypeInfo *pTypeInfo, UINT method_index) /* * call-seq: - * WIN32OLE_METHOD#offset_vtbl + * offset_vtbl * * Returns the offset ov VTBL. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') - * method = WIN32OLE_METHOD.new(tobj, 'Add') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE::Method.new(tobj, 'Add') * puts method.offset_vtbl # => 40 */ static VALUE @@ -810,11 +810,11 @@ ole_method_size_params(ITypeInfo *pTypeInfo, UINT method_index) /* * call-seq: - * WIN32OLE_METHOD#size_params + * size_params * * Returns the size of arguments of the method. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') - * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE::Method.new(tobj, 'SaveAs') * puts method.size_params # => 11 * */ @@ -842,11 +842,11 @@ ole_method_size_opt_params(ITypeInfo *pTypeInfo, UINT method_index) /* * call-seq: - * WIN32OLE_METHOD#size_opt_params + * size_opt_params * * Returns the size of optional parameters. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') - * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE::Method.new(tobj, 'SaveAs') * puts method.size_opt_params # => 4 */ static VALUE @@ -892,11 +892,11 @@ ole_method_params(ITypeInfo *pTypeInfo, UINT method_index) /* * call-seq: - * WIN32OLE_METHOD#params + * params * - * returns array of WIN32OLE_PARAM object corresponding with method parameters. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') - * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + * returns array of WIN32OLE::Param object corresponding with method parameters. + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE::Method.new(tobj, 'SaveAs') * p method.params # => [Filename, FileFormat, Password, WriteResPassword, * ReadOnlyRecommended, CreateBackup, AccessMode, * ConflictResolution, AddToMru, TextCodepage, @@ -912,7 +912,7 @@ folemethod_params(VALUE self) /* * call-seq: - * WIN32OLE_METHOD#inspect -> String + * inspect -> String * * Returns the method name with class name. * @@ -928,6 +928,7 @@ VALUE cWIN32OLE_METHOD; void Init_win32ole_method(void) { cWIN32OLE_METHOD = rb_define_class_under(cWIN32OLE, "Method", rb_cObject); + /* Alias of WIN32OLE::Method, for the backward compatibility */ rb_define_const(rb_cObject, "WIN32OLE_METHOD", cWIN32OLE_METHOD); rb_define_alloc_func(cWIN32OLE_METHOD, folemethod_s_allocate); rb_define_method(cWIN32OLE_METHOD, "initialize", folemethod_initialize, 2); diff --git a/ext/win32ole/win32ole_param.c b/ext/win32ole/win32ole_param.c index c6f324968b911b..ba29d02821de84 100644 --- a/ext/win32ole/win32ole_param.c +++ b/ext/win32ole/win32ole_param.c @@ -64,9 +64,9 @@ create_win32ole_param(ITypeInfo *pTypeInfo, UINT method_index, UINT index, VALUE } /* - * Document-class: WIN32OLE_PARAM + * Document-class: WIN32OLE::Param * - * WIN32OLE_PARAM objects represent param information of + * +WIN32OLE::Param+ objects represent param information of * the OLE method. */ static VALUE @@ -131,15 +131,15 @@ oleparam_ole_param(VALUE self, VALUE olemethod, int n) /* * call-seq: - * WIN32OLE_PARAM.new(method, n) -> WIN32OLE_PARAM object + * new(method, n) -> WIN32OLE::Param object * - * Returns WIN32OLE_PARAM object which represents OLE parameter information. - * 1st argument should be WIN32OLE_METHOD object. + * Returns WIN32OLE::Param object which represents OLE parameter information. + * 1st argument should be WIN32OLE::Method object. * 2nd argument `n' is n-th parameter of the method specified by 1st argument. * - * tobj = WIN32OLE_TYPE.new('Microsoft Scripting Runtime', 'IFileSystem') - * method = WIN32OLE_METHOD.new(tobj, 'CreateTextFile') - * param = WIN32OLE_PARAM.new(method, 2) # => # + * tobj = WIN32OLE::Type.new('Microsoft Scripting Runtime', 'IFileSystem') + * method = WIN32OLE::Method.new(tobj, 'CreateTextFile') + * param = WIN32OLE::Param.new(method, 2) # => # * */ static VALUE @@ -155,11 +155,11 @@ foleparam_initialize(VALUE self, VALUE olemethod, VALUE n) /* * call-seq: - * WIN32OLE_PARAM#name + * name * * Returns name. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') - * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE::Method.new(tobj, 'SaveAs') * param1 = method.params[0] * puts param1.name # => Filename */ @@ -186,11 +186,11 @@ ole_param_ole_type(ITypeInfo *pTypeInfo, UINT method_index, UINT index) /* * call-seq: - * WIN32OLE_PARAM#ole_type + * ole_type * - * Returns OLE type of WIN32OLE_PARAM object(parameter of OLE method). - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') - * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + * Returns OLE type of WIN32OLE::Param object(parameter of OLE method). + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE::Method.new(tobj, 'SaveAs') * param1 = method.params[0] * puts param1.ole_type # => VARIANT */ @@ -220,11 +220,11 @@ ole_param_ole_type_detail(ITypeInfo *pTypeInfo, UINT method_index, UINT index) /* * call-seq: - * WIN32OLE_PARAM#ole_type_detail + * ole_type_detail * * Returns detail information of type of argument. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'IWorksheetFunction') - * method = WIN32OLE_METHOD.new(tobj, 'SumIf') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'IWorksheetFunction') + * method = WIN32OLE::Method.new(tobj, 'SumIf') * param1 = method.params[0] * p param1.ole_type_detail # => ["PTR", "USERDEFINED", "Range"] */ @@ -254,11 +254,11 @@ ole_param_flag_mask(ITypeInfo *pTypeInfo, UINT method_index, UINT index, USHORT /* * call-seq: - * WIN32OLE_PARAM#input? + * input? * * Returns true if the parameter is input. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') - * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE::Method.new(tobj, 'SaveAs') * param1 = method.params[0] * puts param1.input? # => true */ @@ -273,22 +273,22 @@ foleparam_input(VALUE self) /* * call-seq: - * WIN32OLE#output? + * output? * * Returns true if argument is output. - * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'DWebBrowserEvents') - * method = WIN32OLE_METHOD.new(tobj, 'NewWindow') + * tobj = WIN32OLE::Type.new('Microsoft Internet Controls', 'DWebBrowserEvents') + * method = WIN32OLE::Method.new(tobj, 'NewWindow') * method.params.each do |param| * puts "#{param.name} #{param.output?}" * end * - * The result of above script is following: - * URL false - * Flags false - * TargetFrameName false - * PostData false - * Headers false - * Processed true + * The result of above script is following: + * URL false + * Flags false + * TargetFrameName false + * PostData false + * Headers false + * Processed true */ static VALUE foleparam_output(VALUE self) @@ -301,11 +301,11 @@ foleparam_output(VALUE self) /* * call-seq: - * WIN32OLE_PARAM#optional? + * optional? * * Returns true if argument is optional. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') - * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE::Method.new(tobj, 'SaveAs') * param1 = method.params[0] * puts "#{param1.name} #{param1.optional?}" # => Filename true */ @@ -320,12 +320,12 @@ foleparam_optional(VALUE self) /* * call-seq: - * WIN32OLE_PARAM#retval? + * retval? * * Returns true if argument is return value. - * tobj = WIN32OLE_TYPE.new('DirectX 7 for Visual Basic Type Library', - * 'DirectPlayLobbyConnection') - * method = WIN32OLE_METHOD.new(tobj, 'GetPlayerShortName') + * tobj = WIN32OLE::Type.new('DirectX 7 for Visual Basic Type Library', + * 'DirectPlayLobbyConnection') + * method = WIN32OLE::Method.new(tobj, 'GetPlayerShortName') * param = method.params[0] * puts "#{param.name} #{param.retval?}" # => name true */ @@ -363,12 +363,12 @@ ole_param_default(ITypeInfo *pTypeInfo, UINT method_index, UINT index) /* * call-seq: - * WIN32OLE_PARAM#default + * default * * Returns default value. If the default value does not exist, * this method returns nil. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') - * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE::Method.new(tobj, 'SaveAs') * method.params.each do |param| * if param.default * puts "#{param.name} (= #{param.default})" @@ -401,7 +401,7 @@ foleparam_default(VALUE self) /* * call-seq: - * WIN32OLE_PARAM#inspect -> String + * inspect -> String * * Returns the parameter name with class name. If the parameter has default value, * then returns name=value string with class name. @@ -423,6 +423,7 @@ void Init_win32ole_param(void) { cWIN32OLE_PARAM = rb_define_class_under(cWIN32OLE, "Param", rb_cObject); + /* Alias of WIN32OLE::Param, for the backward compatibility */ rb_define_const(rb_cObject, "WIN32OLE_PARAM", cWIN32OLE_PARAM); rb_define_alloc_func(cWIN32OLE_PARAM, foleparam_s_allocate); rb_define_method(cWIN32OLE_PARAM, "initialize", foleparam_initialize, 2); diff --git a/ext/win32ole/win32ole_record.c b/ext/win32ole/win32ole_record.c index 9e18653db99064..772c3437165a03 100644 --- a/ext/win32ole/win32ole_record.c +++ b/ext/win32ole/win32ole_record.c @@ -177,10 +177,10 @@ create_win32ole_record(IRecordInfo *pri, void *prec) } /* - * Document-class: WIN32OLE_RECORD + * Document-class: WIN32OLE::Record * - * WIN32OLE_RECORD objects represents VT_RECORD OLE variant. - * Win32OLE returns WIN32OLE_RECORD object if the result value of invoking + * +WIN32OLE::Record+ objects represents VT_RECORD OLE variant. + * Win32OLE returns WIN32OLE::Record object if the result value of invoking * OLE methods. * * If COM server in VB.NET ComServer project is the following: @@ -206,7 +206,7 @@ create_win32ole_record(IRecordInfo *pri, void *prec) * require 'win32ole' * obj = WIN32OLE.new('ComServer.ComClass') * book = obj.getBook - * book.class # => WIN32OLE_RECORD + * book.class # => WIN32OLE::Record * book.title # => "The Ruby Book" * book.cost # => 20 * @@ -253,11 +253,11 @@ folerecord_s_allocate(VALUE klass) { /* * call-seq: - * WIN32OLE_RECORD.new(typename, obj) -> WIN32OLE_RECORD object + * new(typename, obj) -> WIN32OLE::Record object * - * Returns WIN32OLE_RECORD object. The first argument is struct name (String + * Returns WIN32OLE::Record object. The first argument is struct name (String * or Symbol). - * The second parameter obj should be WIN32OLE object or WIN32OLE_TYPELIB object. + * The second parameter obj should be WIN32OLE object or WIN32OLE::TypeLib object. * If COM server in VB.NET ComServer project is the following: * * Imports System.Runtime.InteropServices @@ -269,13 +269,13 @@ folerecord_s_allocate(VALUE klass) { * End Structure * End Class * - * then, you can create WIN32OLE_RECORD object is as following: + * then, you can create WIN32OLE::Record object is as following: * * require 'win32ole' * obj = WIN32OLE.new('ComServer.ComClass') - * book1 = WIN32OLE_RECORD.new('Book', obj) # => WIN32OLE_RECORD object + * book1 = WIN32OLE::Record.new('Book', obj) # => WIN32OLE::Record object * tlib = obj.ole_typelib - * book2 = WIN32OLE_RECORD.new('Book', tlib) # => WIN32OLE_RECORD object + * book2 = WIN32OLE::Record.new('Book', tlib) # => WIN32OLE::Record object * */ static VALUE @@ -323,7 +323,7 @@ folerecord_initialize(VALUE self, VALUE typename, VALUE oleobj) { /* * call-seq: - * WIN32OLE_RECORD#to_h #=> Ruby Hash object. + * WIN32OLE::Record#to_h #=> Ruby Hash object. * * Returns Ruby Hash object which represents VT_RECORD variable. * The keys of Hash object are member names of VT_RECORD OLE variable and @@ -346,7 +346,7 @@ folerecord_initialize(VALUE self, VALUE typename, VALUE oleobj) { * End Function * End Class * - * then, the result of WIN32OLE_RECORD#to_h is the following: + * then, the result of WIN32OLE::Record#to_h is the following: * * require 'win32ole' * obj = WIN32OLE.new('ComServer.ComClass') @@ -362,7 +362,7 @@ folerecord_to_h(VALUE self) /* * call-seq: - * WIN32OLE_RECORD#typename #=> String object + * typename #=> String object * * Returns the type name of VT_RECORD OLE variable. * @@ -383,7 +383,7 @@ folerecord_to_h(VALUE self) * End Function * End Class * - * then, the result of WIN32OLE_RECORD#typename is the following: + * then, the result of WIN32OLE::Record#typename is the following: * * require 'win32ole' * obj = WIN32OLE.new('ComServer.ComClass') @@ -423,7 +423,7 @@ olerecord_ivar_set(VALUE self, VALUE name, VALUE val) /* * call-seq: - * WIN32OLE_RECORD#method_missing(name) + * method_missing(name) * * Returns value specified by the member name of VT_RECORD OLE variable. * Or sets value specified by the member name of VT_RECORD OLE variable. @@ -443,7 +443,7 @@ olerecord_ivar_set(VALUE self, VALUE name, VALUE val) * Then getting/setting value from Ruby is as the following: * * obj = WIN32OLE.new('ComServer.ComClass') - * book = WIN32OLE_RECORD.new('Book', obj) + * book = WIN32OLE::Record.new('Book', obj) * book.title # => nil ( book.method_missing(:title) is invoked. ) * book.title = "Ruby" # ( book.method_missing(:title=, "Ruby") is invoked. ) */ @@ -473,7 +473,7 @@ folerecord_method_missing(int argc, VALUE *argv, VALUE self) /* * call-seq: - * WIN32OLE_RECORD#ole_instance_variable_get(name) + * ole_instance_variable_get(name) * * Returns value specified by the member name of VT_RECORD OLE object. * If the member name is not correct, KeyError exception is raised. @@ -494,7 +494,7 @@ folerecord_method_missing(int argc, VALUE *argv, VALUE self) * then accessing object_id of ComObject from Ruby is as the following: * * srver = WIN32OLE.new('ComServer.ComClass') - * obj = WIN32OLE_RECORD.new('ComObject', server) + * obj = WIN32OLE::Record.new('ComObject', server) * # obj.object_id returns Ruby Object#object_id * obj.ole_instance_variable_get(:object_id) # => nil * @@ -515,7 +515,7 @@ folerecord_ole_instance_variable_get(VALUE self, VALUE name) /* * call-seq: - * WIN32OLE_RECORD#ole_instance_variable_set(name, val) + * ole_instance_variable_set(name, val) * * Sets value specified by the member name of VT_RECORD OLE object. * If the member name is not correct, KeyError exception is raised. @@ -534,7 +534,7 @@ folerecord_ole_instance_variable_get(VALUE self, VALUE name) * then setting value of the `title' member is as following: * * srver = WIN32OLE.new('ComServer.ComClass') - * obj = WIN32OLE_RECORD.new('Book', server) + * obj = WIN32OLE::Record.new('Book', server) * obj.ole_instance_variable_set(:title, "The Ruby Book") * */ @@ -554,7 +554,7 @@ folerecord_ole_instance_variable_set(VALUE self, VALUE name, VALUE val) /* * call-seq: - * WIN32OLE_RECORD#inspect -> String + * inspect -> String * * Returns the OLE struct name and member name and the value of member * @@ -570,8 +570,8 @@ folerecord_ole_instance_variable_set(VALUE self, VALUE name, VALUE val) * then * * srver = WIN32OLE.new('ComServer.ComClass') - * obj = WIN32OLE_RECORD.new('Book', server) - * obj.inspect # => nil, "cost" => nil}> + * obj = WIN32OLE::Record.new('Book', server) + * obj.inspect # => nil, "cost" => nil}> * */ static VALUE @@ -595,6 +595,7 @@ void Init_win32ole_record(void) { cWIN32OLE_RECORD = rb_define_class_under(cWIN32OLE, "Record", rb_cObject); + /* Alias of WIN32OLE::Record, for the backward compatibility */ rb_define_const(rb_cObject, "WIN32OLE_RECORD", cWIN32OLE_RECORD); rb_define_alloc_func(cWIN32OLE_RECORD, folerecord_s_allocate); rb_define_method(cWIN32OLE_RECORD, "initialize", folerecord_initialize, 2); diff --git a/ext/win32ole/win32ole_type.c b/ext/win32ole/win32ole_type.c index 1b96aea858787d..715b7a8297979a 100644 --- a/ext/win32ole/win32ole_type.c +++ b/ext/win32ole/win32ole_type.c @@ -54,9 +54,9 @@ static const rb_data_type_t oletype_datatype = { }; /* - * Document-class: WIN32OLE_TYPE + * Document-class: WIN32OLE::Type * - * WIN32OLE_TYPE objects represent OLE type library information. + * +WIN32OLE::Type+ objects represent OLE type library information. */ static void @@ -106,10 +106,12 @@ ole_type_from_itypeinfo(ITypeInfo *pTypeInfo) /* * call-seq: - * WIN32OLE_TYPE.ole_classes(typelib) + * ole_classes(typelib) * - * Returns array of WIN32OLE_TYPE objects defined by the typelib type library. - * This method will be OBSOLETE. Use WIN32OLE_TYPELIB.new(typelib).ole_classes instead. + * Returns array of WIN32OLE::Type objects defined by the typelib type library. + * + * This method will be OBSOLETE. + * Use WIN32OLE::TypeLib.new(typelib).ole_classes instead. */ static VALUE foletype_s_ole_classes(VALUE self, VALUE typelib) @@ -118,8 +120,8 @@ foletype_s_ole_classes(VALUE self, VALUE typelib) /* rb_warn("%s is obsolete; use %s instead.", - "WIN32OLE_TYPE.ole_classes", - "WIN32OLE_TYPELIB.new(typelib).ole_types"); + "WIN32OLE::Type.ole_classes", + "WIN32OLE::TypeLib.new(typelib).ole_types"); */ obj = rb_funcall(cWIN32OLE_TYPELIB, rb_intern("new"), 1, typelib); return rb_funcall(obj, rb_intern("ole_types"), 0); @@ -127,10 +129,12 @@ foletype_s_ole_classes(VALUE self, VALUE typelib) /* * call-seq: - * WIN32OLE_TYPE.typelibs + * typelibs * * Returns array of type libraries. - * This method will be OBSOLETE. Use WIN32OLE_TYPELIB.typelibs.collect{|t| t.name} instead. + * + * This method will be OBSOLETE. + * Use WIN32OLE::TypeLib.typelibs.collect{|t| t.name} instead. * */ static VALUE @@ -138,15 +142,15 @@ foletype_s_typelibs(VALUE self) { /* rb_warn("%s is obsolete. use %s instead.", - "WIN32OLE_TYPE.typelibs", - "WIN32OLE_TYPELIB.typelibs.collect{t|t.name}"); + "WIN32OLE::Type.typelibs", + "WIN32OLE::TypeLib.typelibs.collect{t|t.name}"); */ return rb_eval_string("WIN32OLE_TYPELIB.typelibs.collect{|t|t.name}"); } /* * call-seq: - * WIN32OLE_TYPE.progids + * progids * * Returns array of ProgID. */ @@ -214,7 +218,6 @@ create_win32ole_type(ITypeInfo *pTypeInfo, VALUE name) static VALUE oleclass_from_typelib(VALUE self, ITypeLib *pTypeLib, VALUE oleclass) { - long count; int i; HRESULT hr; @@ -245,14 +248,14 @@ oleclass_from_typelib(VALUE self, ITypeLib *pTypeLib, VALUE oleclass) /* * call-seq: - * WIN32OLE_TYPE.new(typelib, ole_class) -> WIN32OLE_TYPE object + * new(typelib, ole_class) -> WIN32OLE::Type object * - * Returns a new WIN32OLE_TYPE object. + * Returns a new WIN32OLE::Type object. * The first argument typelib specifies OLE type library name. * The second argument specifies OLE class name. * - * WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') - * # => WIN32OLE_TYPE object of Application class of Excel. + * WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Application') + * # => WIN32OLE::Type object of Application class of Excel. */ static VALUE foletype_initialize(VALUE self, VALUE typelib, VALUE oleclass) @@ -284,10 +287,10 @@ foletype_initialize(VALUE self, VALUE typelib, VALUE oleclass) /* * call-seq: - * WIN32OLE_TYPE#name #=> OLE type name + * name #=> OLE type name * * Returns OLE type name. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Application') * puts tobj.name # => Application */ static VALUE @@ -344,10 +347,10 @@ ole_ole_type(ITypeInfo *pTypeInfo) /* * call-seq: - * WIN32OLE_TYPE#ole_type #=> OLE type string. + * ole_type #=> OLE type string. * * returns type of OLE class. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Application') * puts tobj.ole_type # => Class */ static VALUE @@ -378,10 +381,10 @@ ole_type_guid(ITypeInfo *pTypeInfo) /* * call-seq: - * WIN32OLE_TYPE#guid #=> GUID + * guid #=> GUID * * Returns GUID. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Application') * puts tobj.guid # => {00024500-0000-0000-C000-000000000046} */ static VALUE @@ -412,10 +415,10 @@ ole_type_progid(ITypeInfo *pTypeInfo) /* * call-seq: - * WIN32OLE_TYPE#progid #=> ProgID + * progid #=> ProgID * * Returns ProgID if it exists. If not found, then returns nil. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Application') * puts tobj.progid # => Excel.Application.9 */ static VALUE @@ -446,10 +449,10 @@ ole_type_visible(ITypeInfo *pTypeInfo) /* * call-seq: - * WIN32OLE_TYPE#visible? #=> true or false + * visible? #=> true or false * * Returns true if the OLE class is public. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Application') * puts tobj.visible # => true */ static VALUE @@ -475,10 +478,10 @@ ole_type_major_version(ITypeInfo *pTypeInfo) /* * call-seq: - * WIN32OLE_TYPE#major_version + * major_version * * Returns major version. - * tobj = WIN32OLE_TYPE.new('Microsoft Word 10.0 Object Library', 'Documents') + * tobj = WIN32OLE::Type.new('Microsoft Word 10.0 Object Library', 'Documents') * puts tobj.major_version # => 8 */ static VALUE @@ -504,10 +507,10 @@ ole_type_minor_version(ITypeInfo *pTypeInfo) /* * call-seq: - * WIN32OLE_TYPE#minor_version #=> OLE minor version + * minor_version #=> OLE minor version * * Returns minor version. - * tobj = WIN32OLE_TYPE.new('Microsoft Word 10.0 Object Library', 'Documents') + * tobj = WIN32OLE::Type.new('Microsoft Word 10.0 Object Library', 'Documents') * puts tobj.minor_version # => 2 */ static VALUE @@ -533,10 +536,10 @@ ole_type_typekind(ITypeInfo *pTypeInfo) /* * call-seq: - * WIN32OLE_TYPE#typekind #=> number of type. + * typekind #=> number of type. * * Returns number which represents type. - * tobj = WIN32OLE_TYPE.new('Microsoft Word 10.0 Object Library', 'Documents') + * tobj = WIN32OLE::Type.new('Microsoft Word 10.0 Object Library', 'Documents') * puts tobj.typekind # => 4 * */ @@ -561,10 +564,10 @@ ole_type_helpstring(ITypeInfo *pTypeInfo) /* * call-seq: - * WIN32OLE_TYPE#helpstring #=> help string. + * helpstring #=> help string. * * Returns help string. - * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'IWebBrowser') + * tobj = WIN32OLE::Type.new('Microsoft Internet Controls', 'IWebBrowser') * puts tobj.helpstring # => Web Browser interface */ static VALUE @@ -594,10 +597,10 @@ ole_type_src_type(ITypeInfo *pTypeInfo) /* * call-seq: - * WIN32OLE_TYPE#src_type #=> OLE source class + * src_type #=> OLE source class * * Returns source class when the OLE class is 'Alias'. - * tobj = WIN32OLE_TYPE.new('Microsoft Office 9.0 Object Library', 'MsoRGBType') + * tobj = WIN32OLE::Type.new('Microsoft Office 9.0 Object Library', 'MsoRGBType') * puts tobj.src_type # => I4 * */ @@ -622,10 +625,10 @@ ole_type_helpfile(ITypeInfo *pTypeInfo) /* * call-seq: - * WIN32OLE_TYPE#helpfile + * helpfile * * Returns helpfile path. If helpfile is not found, then returns nil. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Worksheet') * puts tobj.helpfile # => C:\...\VBAXL9.CHM * */ @@ -650,10 +653,10 @@ ole_type_helpcontext(ITypeInfo *pTypeInfo) /* * call-seq: - * WIN32OLE_TYPE#helpcontext + * helpcontext * * Returns helpcontext. If helpcontext is not found, then returns nil. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Worksheet') * puts tobj.helpfile # => 131185 */ static VALUE @@ -701,11 +704,11 @@ ole_variables(ITypeInfo *pTypeInfo) /* * call-seq: - * WIN32OLE_TYPE#variables + * variables * - * Returns array of WIN32OLE_VARIABLE objects which represent variables + * Returns array of WIN32OLE::Variable objects which represent variables * defined in OLE class. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') * vars = tobj.variables * vars.each do |v| * puts "#{v.name} = #{v.value}" @@ -728,11 +731,11 @@ foletype_variables(VALUE self) /* * call-seq: - * WIN32OLE_TYPE#ole_methods # the array of WIN32OLE_METHOD objects. + * ole_methods # the array of WIN32OLE::Method objects. * - * Returns array of WIN32OLE_METHOD objects which represent OLE method defined in + * Returns array of WIN32OLE::Method objects which represent OLE method defined in * OLE type library. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Worksheet') * methods = tobj.ole_methods.collect{|m| * m.name * } @@ -747,11 +750,11 @@ foletype_methods(VALUE self) /* * call-seq: - * WIN32OLE_TYPE#ole_typelib + * ole_typelib * - * Returns the WIN32OLE_TYPELIB object which is including the WIN32OLE_TYPE + * Returns the WIN32OLE::TypeLib object which is including the WIN32OLE::Type * object. If it is not found, then returns nil. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Worksheet') * puts tobj.ole_typelib # => 'Microsoft Excel 9.0 Object Library' */ static VALUE @@ -804,11 +807,11 @@ ole_type_impl_ole_types(ITypeInfo *pTypeInfo, int implflags) /* * call-seq: - * WIN32OLE_TYPE#implemented_ole_types + * implemented_ole_types * - * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE + * Returns the array of WIN32OLE::Type object which is implemented by the WIN32OLE::Type * object. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Worksheet') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Worksheet') * p tobj.implemented_ole_types # => [_Worksheet, DocEvents] */ static VALUE @@ -820,11 +823,11 @@ foletype_impl_ole_types(VALUE self) /* * call-seq: - * WIN32OLE_TYPE#source_ole_types + * source_ole_types * - * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE + * Returns the array of WIN32OLE::Type object which is implemented by the WIN32OLE::Type * object and having IMPLTYPEFLAG_FSOURCE. - * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer") + * tobj = WIN32OLE::Type.new('Microsoft Internet Controls', "InternetExplorer") * p tobj.source_ole_types * # => [#, #] */ @@ -837,11 +840,11 @@ foletype_source_ole_types(VALUE self) /* * call-seq: - * WIN32OLE_TYPE#default_event_sources + * default_event_sources * - * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE + * Returns the array of WIN32OLE::Type object which is implemented by the WIN32OLE::Type * object and having IMPLTYPEFLAG_FSOURCE and IMPLTYPEFLAG_FDEFAULT. - * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer") + * tobj = WIN32OLE::Type.new('Microsoft Internet Controls', "InternetExplorer") * p tobj.default_event_sources # => [#] */ static VALUE @@ -853,11 +856,11 @@ foletype_default_event_sources(VALUE self) /* * call-seq: - * WIN32OLE_TYPE#default_ole_types + * default_ole_types * - * Returns the array of WIN32OLE_TYPE object which is implemented by the WIN32OLE_TYPE + * Returns the array of WIN32OLE::Type object which is implemented by the WIN32OLE::Type * object and having IMPLTYPEFLAG_FDEFAULT. - * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', "InternetExplorer") + * tobj = WIN32OLE::Type.new('Microsoft Internet Controls', "InternetExplorer") * p tobj.default_ole_types * # => [#, #] */ @@ -870,7 +873,7 @@ foletype_default_ole_types(VALUE self) /* * call-seq: - * WIN32OLE_TYPE#inspect -> String + * inspect -> String * * Returns the type name with class name. * @@ -888,6 +891,7 @@ VALUE cWIN32OLE_TYPE; void Init_win32ole_type(void) { cWIN32OLE_TYPE = rb_define_class_under(cWIN32OLE, "Type", rb_cObject); + /* Alias of WIN32OLE::Type, for the backward compatibility */ rb_define_const(rb_cObject, "WIN32OLE_TYPE", cWIN32OLE_TYPE); rb_define_singleton_method(cWIN32OLE_TYPE, "ole_classes", foletype_s_ole_classes, 1); rb_define_singleton_method(cWIN32OLE_TYPE, "typelibs", foletype_s_typelibs, 0); diff --git a/ext/win32ole/win32ole_typelib.c b/ext/win32ole/win32ole_typelib.c index 84dca9e0e1f367..ad7e769a98ee0b 100644 --- a/ext/win32ole/win32ole_typelib.c +++ b/ext/win32ole/win32ole_typelib.c @@ -127,19 +127,19 @@ ole_typelib_from_itypeinfo(ITypeInfo *pTypeInfo) } /* - * Document-class: WIN32OLE_TYPELIB + * Document-class: WIN32OLE::TypeLib * - * WIN32OLE_TYPELIB objects represent OLE tyblib information. + * +WIN32OLE::TypeLib+ objects represent OLE tyblib information. */ /* * call-seq: * - * WIN32OLE_TYPELIB.typelibs + * typelibs * - * Returns the array of WIN32OLE_TYPELIB object. + * Returns the array of WIN32OLE::TypeLib object. * - * tlibs = WIN32OLE_TYPELIB.typelibs + * tlibs = WIN32OLE::TypeLib.typelibs * */ static VALUE @@ -364,9 +364,9 @@ oletypelib_search_registry2(VALUE self, VALUE args) /* * call-seq: - * WIN32OLE_TYPELIB.new(typelib [, version1, version2]) -> WIN32OLE_TYPELIB object + * new(typelib [, version1, version2]) -> WIN32OLE::TypeLib object * - * Returns a new WIN32OLE_TYPELIB object. + * Returns a new WIN32OLE::TypeLib object. * * The first argument typelib specifies OLE type library name or GUID or * OLE library file. @@ -376,11 +376,11 @@ oletypelib_search_registry2(VALUE self, VALUE args) * If the first argument is type library name, then the second and third argument * are ignored. * - * tlib1 = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') - * tlib2 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}') - * tlib3 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}', 1.3) - * tlib4 = WIN32OLE_TYPELIB.new('{00020813-0000-0000-C000-000000000046}', 1, 3) - * tlib5 = WIN32OLE_TYPELIB.new("C:\\WINNT\\SYSTEM32\\SHELL32.DLL") + * tlib1 = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library') + * tlib2 = WIN32OLE::TypeLib.new('{00020813-0000-0000-C000-000000000046}') + * tlib3 = WIN32OLE::TypeLib.new('{00020813-0000-0000-C000-000000000046}', 1.3) + * tlib4 = WIN32OLE::TypeLib.new('{00020813-0000-0000-C000-000000000046}', 1, 3) + * tlib5 = WIN32OLE::TypeLib.new("C:\\WINNT\\SYSTEM32\\SHELL32.DLL") * puts tlib1.name # -> 'Microsoft Excel 9.0 Object Library' * puts tlib2.name # -> 'Microsoft Excel 9.0 Object Library' * puts tlib3.name # -> 'Microsoft Excel 9.0 Object Library' @@ -428,11 +428,11 @@ foletypelib_initialize(VALUE self, VALUE args) /* * call-seq: - * WIN32OLE_TYPELIB#guid -> The guid string. + * guid -> The guid string. * * Returns guid string which specifies type library. * - * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') + * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library') * guid = tlib.guid # -> '{00020813-0000-0000-C000-000000000046}' */ static VALUE @@ -456,11 +456,11 @@ foletypelib_guid(VALUE self) /* * call-seq: - * WIN32OLE_TYPELIB#name -> The type library name + * name -> The type library name * * Returns the type library name. * - * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') + * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library') * name = tlib.name # -> 'Microsoft Excel 9.0 Object Library' */ static VALUE @@ -500,11 +500,11 @@ make_version_str(VALUE major, VALUE minor) /* * call-seq: - * WIN32OLE_TYPELIB#version -> The type library version String object. + * version -> The type library version String object. * * Returns the type library version. * - * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') + * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library') * puts tlib.version #-> "1.3" */ static VALUE @@ -523,11 +523,11 @@ foletypelib_version(VALUE self) /* * call-seq: - * WIN32OLE_TYPELIB#major_version -> The type library major version. + * major_version -> The type library major version. * * Returns the type library major version. * - * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') + * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library') * puts tlib.major_version # -> 1 */ static VALUE @@ -546,11 +546,11 @@ foletypelib_major_version(VALUE self) /* * call-seq: - * WIN32OLE_TYPELIB#minor_version -> The type library minor version. + * minor_version -> The type library minor version. * * Returns the type library minor version. * - * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') + * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library') * puts tlib.minor_version # -> 3 */ static VALUE @@ -568,11 +568,11 @@ foletypelib_minor_version(VALUE self) /* * call-seq: - * WIN32OLE_TYPELIB#path -> The type library file path. + * path -> The type library file path. * * Returns the type library file path. * - * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') + * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library') * puts tlib.path #-> 'C:\...\EXCEL9.OLB' */ static VALUE @@ -604,15 +604,15 @@ foletypelib_path(VALUE self) /* * call-seq: - * WIN32OLE_TYPELIB#visible? + * visible? * * Returns true if the type library information is not hidden. * If wLibFlags of TLIBATTR is 0 or LIBFLAG_FRESTRICTED or LIBFLAG_FHIDDEN, * the method returns false, otherwise, returns true. * If the method fails to access the TLIBATTR information, then - * WIN32OLERuntimeError is raised. + * WIN32OLE::RuntimeError is raised. * - * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') + * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library') * tlib.visible? # => true */ static VALUE @@ -636,12 +636,12 @@ foletypelib_visible(VALUE self) /* * call-seq: - * WIN32OLE_TYPELIB#library_name + * library_name * * Returns library name. - * If the method fails to access library name, WIN32OLERuntimeError is raised. + * If the method fails to access library name, WIN32OLE::RuntimeError is raised. * - * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') + * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library') * tlib.library_name # => Excel */ static VALUE @@ -790,11 +790,11 @@ typelib_file(VALUE ole) /* * call-seq: - * WIN32OLE_TYPELIB#ole_types -> The array of WIN32OLE_TYPE object included the type library. + * ole_types -> The array of WIN32OLE::Type object included the type library. * * Returns the type library file path. * - * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') + * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library') * classes = tlib.ole_types.collect{|k| k.name} # -> ['AddIn', 'AddIns' ...] */ static VALUE @@ -809,11 +809,11 @@ foletypelib_ole_types(VALUE self) /* * call-seq: - * WIN32OLE_TYPELIB#inspect -> String + * inspect -> String * * Returns the type library name with class name. * - * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') + * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library') * tlib.inspect # => "<#WIN32OLE_TYPELIB:Microsoft Excel 9.0 Object Library>" */ static VALUE @@ -828,6 +828,7 @@ void Init_win32ole_typelib(void) { cWIN32OLE_TYPELIB = rb_define_class_under(cWIN32OLE, "TypeLib", rb_cObject); + /* Alias of WIN32OLE::TypeLib, for the backward compatibility */ rb_define_const(rb_cObject, "WIN32OLE_TYPELIB", cWIN32OLE_TYPELIB); rb_define_singleton_method(cWIN32OLE_TYPELIB, "typelibs", foletypelib_s_typelibs, 0); rb_define_alloc_func(cWIN32OLE_TYPELIB, foletypelib_s_allocate); diff --git a/ext/win32ole/win32ole_variable.c b/ext/win32ole/win32ole_variable.c index e7f58c891e68b5..e2500388c1c707 100644 --- a/ext/win32ole/win32ole_variable.c +++ b/ext/win32ole/win32ole_variable.c @@ -43,9 +43,9 @@ olevariable_size(const void *ptr) } /* - * Document-class: WIN32OLE_VARIABLE + * Document-class: WIN32OLE::Variable * - * WIN32OLE_VARIABLE objects represent OLE variable information. + * +WIN32OLE::Variable+ objects represent OLE variable information. */ VALUE @@ -63,11 +63,11 @@ create_win32ole_variable(ITypeInfo *pTypeInfo, UINT index, VALUE name) /* * call-seq: - * WIN32OLE_VARIABLE#name + * name * * Returns the name of variable. * - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') * variables = tobj.variables * variables.each do |variable| * puts "#{variable.name}" @@ -103,11 +103,11 @@ ole_variable_ole_type(ITypeInfo *pTypeInfo, UINT var_index) /* * call-seq: - * WIN32OLE_VARIABLE#ole_type + * ole_type * * Returns OLE type string. * - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') * variables = tobj.variables * variables.each do |variable| * puts "#{variable.ole_type} #{variable.name}" @@ -145,11 +145,11 @@ ole_variable_ole_type_detail(ITypeInfo *pTypeInfo, UINT var_index) /* * call-seq: - * WIN32OLE_VARIABLE#ole_type_detail + * ole_type_detail * * Returns detail information of type. The information is array of type. * - * tobj = WIN32OLE_TYPE.new('DirectX 7 for Visual Basic Type Library', 'D3DCLIPSTATUS') + * tobj = WIN32OLE::Type.new('DirectX 7 for Visual Basic Type Library', 'D3DCLIPSTATUS') * variable = tobj.variables.find {|variable| variable.name == 'lFlags'} * tdetail = variable.ole_type_detail * p tdetail # => ["USERDEFINED", "CONST_D3DCLIPSTATUSFLAGS"] @@ -180,12 +180,12 @@ ole_variable_value(ITypeInfo *pTypeInfo, UINT var_index) /* * call-seq: - * WIN32OLE_VARIABLE#value + * value * * Returns value if value is exists. If the value does not exist, * this method returns nil. * - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') * variables = tobj.variables * variables.each do |variable| * puts "#{variable.name} #{variable.value}" @@ -227,11 +227,11 @@ ole_variable_visible(ITypeInfo *pTypeInfo, UINT var_index) /* * call-seq: - * WIN32OLE_VARIABLE#visible? + * visible? * * Returns true if the variable is public. * - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') * variables = tobj.variables * variables.each do |variable| * puts "#{variable.name} #{variable.visible?}" @@ -284,11 +284,11 @@ ole_variable_kind(ITypeInfo *pTypeInfo, UINT var_index) /* * call-seq: - * WIN32OLE_VARIABLE#variable_kind + * variable_kind * * Returns variable kind string. * - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') * variables = tobj.variables * variables.each do |variable| * puts "#{variable.name} #{variable.variable_kind}" @@ -325,10 +325,10 @@ ole_variable_varkind(ITypeInfo *pTypeInfo, UINT var_index) /* * call-seq: - * WIN32OLE_VARIABLE#varkind + * varkind * * Returns the number which represents variable kind. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') + * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'XlSheetType') * variables = tobj.variables * variables.each do |variable| * puts "#{variable.name} #{variable.varkind}" @@ -351,7 +351,7 @@ folevariable_varkind(VALUE self) /* * call-seq: - * WIN32OLE_VARIABLE#inspect -> String + * inspect -> String * * Returns the OLE variable name and the value with class name. * @@ -370,6 +370,7 @@ VALUE cWIN32OLE_VARIABLE; void Init_win32ole_variable(void) { cWIN32OLE_VARIABLE = rb_define_class_under(cWIN32OLE, "Variable", rb_cObject); + /* Alias of WIN32OLE::Variable, for the backward compatibility */ rb_define_const(rb_cObject, "WIN32OLE_VARIABLE", cWIN32OLE_VARIABLE); rb_undef_alloc_func(cWIN32OLE_VARIABLE); rb_define_method(cWIN32OLE_VARIABLE, "name", folevariable_name, 0); diff --git a/ext/win32ole/win32ole_variant.c b/ext/win32ole/win32ole_variant.c index f1d83ed2e1d7e3..fd1cc393a0a058 100644 --- a/ext/win32ole/win32ole_variant.c +++ b/ext/win32ole/win32ole_variant.c @@ -267,7 +267,7 @@ folevariant_s_allocate(VALUE klass) /* * call-seq: - * WIN32OLE_VARIANT.array(ary, vt) + * array(ary, vt) * * Returns Ruby object wrapping OLE variant whose variant type is VT_ARRAY. * The first argument should be Array object which specifies dimensions @@ -277,7 +277,7 @@ folevariant_s_allocate(VALUE klass) * The following create 2 dimensions OLE array. The first dimensions size * is 3, and the second is 4. * - * ole_ary = WIN32OLE_VARIANT.array([3,4], VT_I4) + * ole_ary = WIN32OLE::Variant.array([3,4], VT_I4) * ruby_ary = ole_ary.value # => [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] * */ @@ -364,37 +364,37 @@ check_type_val2variant(VALUE val) } /* - * Document-class: WIN32OLE_VARIANT + * Document-class: WIN32OLE::Variant * - * WIN32OLE_VARIANT objects represents OLE variant. + * +WIN32OLE::Variant+ objects represents OLE variant. * * Win32OLE converts Ruby object into OLE variant automatically when * invoking OLE methods. If OLE method requires the argument which is * different from the variant by automatic conversion of Win32OLE, you - * can convert the specified variant type by using WIN32OLE_VARIANT class. + * can convert the specified variant type by using WIN32OLE::Variant class. * - * param = WIN32OLE_VARIANT.new(10, WIN32OLE::VARIANT::VT_R4) + * param = WIN32OLE::Variant.new(10, WIN32OLE::VARIANT::VT_R4) * oleobj.method(param) * - * WIN32OLE_VARIANT does not support VT_RECORD variant. Use WIN32OLE_RECORD - * class instead of WIN32OLE_VARIANT if the VT_RECORD variant is needed. + * WIN32OLE::Variant does not support VT_RECORD variant. Use WIN32OLE::Record + * class instead of WIN32OLE::Variant if the VT_RECORD variant is needed. */ /* * call-seq: - * WIN32OLE_VARIANT.new(val, vartype) #=> WIN32OLE_VARIANT object. + * new(val, vartype) #=> WIN32OLE::Variant object. * * Returns Ruby object wrapping OLE variant. * The first argument specifies Ruby object to convert OLE variant variable. * The second argument specifies VARIANT type. - * In some situation, you need the WIN32OLE_VARIANT object to pass OLE method + * In some situation, you need the WIN32OLE::Variant object to pass OLE method * * shell = WIN32OLE.new("Shell.Application") * folder = shell.NameSpace("C:\\Windows") * item = folder.ParseName("tmp.txt") * # You can't use Ruby String object to call FolderItem.InvokeVerb. - * # Instead, you have to use WIN32OLE_VARIANT object to call the method. - * shortcut = WIN32OLE_VARIANT.new("Create Shortcut(\&S)") + * # Instead, you have to use WIN32OLE::Variant object to call the method. + * shortcut = WIN32OLE::Variant.new("Create Shortcut(\&S)") * item.invokeVerb(shortcut) * */ @@ -482,22 +482,22 @@ unlock_safe_array(SAFEARRAY *psa) /* * call-seq: - * WIN32OLE_VARIANT[i,j,...] #=> element of OLE array. + * variant[i,j,...] #=> element of OLE array. * - * Returns the element of WIN32OLE_VARIANT object(OLE array). + * Returns the element of WIN32OLE::Variant object(OLE array). * This method is available only when the variant type of - * WIN32OLE_VARIANT object is VT_ARRAY. + * WIN32OLE::Variant object is VT_ARRAY. * * REMARK: * The all indices should be 0 or natural number and * lower than or equal to max indices. * (This point is different with Ruby Array indices.) * - * obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]]) + * obj = WIN32OLE::Variant.new([[1,2,3],[4,5,6]]) * p obj[0,0] # => 1 * p obj[1,0] # => 4 - * p obj[2,0] # => WIN32OLERuntimeError - * p obj[0, -1] # => WIN32OLERuntimeError + * p obj[2,0] # => WIN32OLE::RuntimeError + * p obj[0, -1] # => WIN32OLE::RuntimeError * */ static VALUE @@ -537,23 +537,23 @@ folevariant_ary_aref(int argc, VALUE *argv, VALUE self) /* * call-seq: - * WIN32OLE_VARIANT[i,j,...] = val #=> set the element of OLE array + * variant[i,j,...] = val #=> set the element of OLE array * - * Set the element of WIN32OLE_VARIANT object(OLE array) to val. + * Set the element of WIN32OLE::Variant object(OLE array) to val. * This method is available only when the variant type of - * WIN32OLE_VARIANT object is VT_ARRAY. + * WIN32OLE::Variant object is VT_ARRAY. * * REMARK: * The all indices should be 0 or natural number and * lower than or equal to max indices. * (This point is different with Ruby Array indices.) * - * obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]]) + * obj = WIN32OLE::Variant.new([[1,2,3],[4,5,6]]) * obj[0,0] = 7 * obj[1,0] = 8 * p obj.value # => [[7,2,3], [8,5,6]] - * obj[2,0] = 9 # => WIN32OLERuntimeError - * obj[0, -1] = 9 # => WIN32OLERuntimeError + * obj[2,0] = 9 # => WIN32OLE::RuntimeError + * obj[0, -1] = 9 # => WIN32OLE::RuntimeError * */ static VALUE @@ -598,10 +598,10 @@ folevariant_ary_aset(int argc, VALUE *argv, VALUE self) /* * call-seq: - * WIN32OLE_VARIANT.value #=> Ruby object. + * value #=> Ruby object. * * Returns Ruby object value from OLE variant. - * obj = WIN32OLE_VARIANT.new(1, WIN32OLE::VARIANT::VT_BSTR) + * obj = WIN32OLE::Variant.new(1, WIN32OLE::VARIANT::VT_BSTR) * obj.value # => "1" (not Integer object, but String object "1") * */ @@ -637,10 +637,10 @@ folevariant_value(VALUE self) /* * call-seq: - * WIN32OLE_VARIANT.vartype #=> OLE variant type. + * vartype #=> OLE variant type. * * Returns OLE variant type. - * obj = WIN32OLE_VARIANT.new("string") + * obj = WIN32OLE::Variant.new("string") * obj.vartype # => WIN32OLE::VARIANT::VT_BSTR * */ @@ -654,7 +654,7 @@ folevariant_vartype(VALUE self) /* * call-seq: - * WIN32OLE_VARIANT.value = val #=> set WIN32OLE_VARIANT value to val. + * variant.value = val #=> set WIN32OLE::Variant value to val. * * Sets variant value to val. If the val type does not match variant value * type(vartype), then val is changed to match variant value type(vartype) @@ -662,7 +662,7 @@ folevariant_vartype(VALUE self) * This method is not available when vartype is VT_ARRAY(except VT_UI1|VT_ARRAY). * If the vartype is VT_UI1|VT_ARRAY, the val should be String object. * - * obj = WIN32OLE_VARIANT.new(1) # obj.vartype is WIN32OLE::VARIANT::VT_I4 + * obj = WIN32OLE::Variant.new(1) # obj.vartype is WIN32OLE::VARIANT::VT_I4 * obj.value = 3.2 # 3.2 is changed to 3 when setting value. * p obj.value # => 3 */ @@ -696,6 +696,7 @@ Init_win32ole_variant(void) { #undef rb_intern cWIN32OLE_VARIANT = rb_define_class_under(cWIN32OLE, "Variant", rb_cObject); + /* Alias of WIN32OLE::Variant, for the backward compatibility */ rb_define_const(rb_cObject, "WIN32OLE_VARIANT", cWIN32OLE_VARIANT); rb_define_alloc_func(cWIN32OLE_VARIANT, folevariant_s_allocate); rb_define_singleton_method(cWIN32OLE_VARIANT, "array", folevariant_s_array, 2); @@ -729,7 +730,7 @@ Init_win32ole_variant(void) * This constants is used for not specified parameter. * * fso = WIN32OLE.new("Scripting.FileSystemObject") - * fso.openTextFile(filename, WIN32OLE_VARIANT::NoParam, false) + * fso.openTextFile(filename, WIN32OLE::Variant::NoParam, false) */ rb_define_const(cWIN32OLE_VARIANT, "NoParam", rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, INT2NUM(DISP_E_PARAMNOTFOUND), RB_INT2FIX(VT_ERROR))); From 1e2d088dd3d534958c4e010a6bcb815cce83c1b5 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 31 Dec 2023 17:02:58 +0900 Subject: [PATCH 598/640] [ruby/win32ole] Use the scoped names in `inspect` and error messages https://github.com/ruby/win32ole/commit/2f51493bd1 --- ext/win32ole/win32ole.c | 4 ++-- ext/win32ole/win32ole_method.c | 4 ++-- ext/win32ole/win32ole_param.c | 6 +++--- ext/win32ole/win32ole_record.c | 4 ++-- ext/win32ole/win32ole_type.c | 12 ++++++------ ext/win32ole/win32ole_typelib.c | 4 ++-- ext/win32ole/win32ole_variable.c | 2 +- ext/win32ole/win32ole_variant.c | 4 ++-- test/win32ole/test_win32ole_method.rb | 2 +- test/win32ole/test_win32ole_param.rb | 6 +++--- test/win32ole/test_win32ole_type.rb | 2 +- test/win32ole/test_win32ole_typelib.rb | 2 +- test/win32ole/test_win32ole_variable.rb | 4 ++-- 13 files changed, 28 insertions(+), 28 deletions(-) diff --git a/ext/win32ole/win32ole.c b/ext/win32ole/win32ole.c index d642aab2323515..7b102928d7700b 100644 --- a/ext/win32ole/win32ole.c +++ b/ext/win32ole/win32ole.c @@ -2215,7 +2215,7 @@ fole_s_show_help(int argc, VALUE *argv, VALUE self) helpfile = target; } if (!RB_TYPE_P(helpfile, T_STRING)) { - rb_raise(rb_eTypeError, "1st parameter must be (String|WIN32OLE_TYPE|WIN32OLE_METHOD)"); + rb_raise(rb_eTypeError, "1st parameter must be (String|WIN32OLE::Type|WIN32OLE::Method)"); } hwnd = ole_show_help(helpfile, helpcontext); if(hwnd == 0) { @@ -3529,7 +3529,7 @@ fole_type(VALUE self) type = ole_type_from_itypeinfo(pTypeInfo); OLE_RELEASE(pTypeInfo); if (type == Qnil) { - rb_raise(rb_eRuntimeError, "failed to create WIN32OLE_TYPE obj from ITypeInfo"); + rb_raise(rb_eRuntimeError, "failed to create WIN32OLE::Type obj from ITypeInfo"); } return type; } diff --git a/ext/win32ole/win32ole_method.c b/ext/win32ole/win32ole_method.c index 4b47ca8eed254e..a0278729f02f0a 100644 --- a/ext/win32ole/win32ole_method.c +++ b/ext/win32ole/win32ole_method.c @@ -277,7 +277,7 @@ folemethod_initialize(VALUE self, VALUE oletype, VALUE method) } } else { - rb_raise(rb_eTypeError, "1st argument should be WIN32OLE_TYPE object"); + rb_raise(rb_eTypeError, "1st argument should be WIN32OLE::Type object"); } return obj; } @@ -920,7 +920,7 @@ folemethod_params(VALUE self) static VALUE folemethod_inspect(VALUE self) { - return default_inspect(self, "WIN32OLE_METHOD"); + return default_inspect(self, "WIN32OLE::Method"); } VALUE cWIN32OLE_METHOD; diff --git a/ext/win32ole/win32ole_param.c b/ext/win32ole/win32ole_param.c index ba29d02821de84..0c4b185921c1fe 100644 --- a/ext/win32ole/win32ole_param.c +++ b/ext/win32ole/win32ole_param.c @@ -139,7 +139,7 @@ oleparam_ole_param(VALUE self, VALUE olemethod, int n) * * tobj = WIN32OLE::Type.new('Microsoft Scripting Runtime', 'IFileSystem') * method = WIN32OLE::Method.new(tobj, 'CreateTextFile') - * param = WIN32OLE::Param.new(method, 2) # => # + * param = WIN32OLE::Param.new(method, 2) # => # * */ static VALUE @@ -147,7 +147,7 @@ foleparam_initialize(VALUE self, VALUE olemethod, VALUE n) { int idx; if (!rb_obj_is_kind_of(olemethod, cWIN32OLE_METHOD)) { - rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE_METHOD object"); + rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE::Method object"); } idx = RB_FIX2INT(n); return oleparam_ole_param(self, olemethod, idx); @@ -416,7 +416,7 @@ foleparam_inspect(VALUE self) rb_str_cat2(detail, "="); rb_str_concat(detail, rb_inspect(defval)); } - return make_inspect("WIN32OLE_PARAM", detail); + return make_inspect("WIN32OLE::Param", detail); } void diff --git a/ext/win32ole/win32ole_record.c b/ext/win32ole/win32ole_record.c index 772c3437165a03..02f05a3fa7130d 100644 --- a/ext/win32ole/win32ole_record.c +++ b/ext/win32ole/win32ole_record.c @@ -303,7 +303,7 @@ folerecord_initialize(VALUE self, VALUE typename, VALUE oleobj) { hr = E_FAIL; } } else { - rb_raise(rb_eArgError, "2nd argument should be WIN32OLE object or WIN32OLE_TYPELIB object"); + rb_raise(rb_eArgError, "2nd argument should be WIN32OLE object or WIN32OLE::TypeLib object"); } if (FAILED(hr)) { @@ -584,7 +584,7 @@ folerecord_inspect(VALUE self) tname = rb_inspect(tname); } field = rb_inspect(folerecord_to_h(self)); - return rb_sprintf("#", + return rb_sprintf("#", tname, field); } diff --git a/ext/win32ole/win32ole_type.c b/ext/win32ole/win32ole_type.c index 715b7a8297979a..45b16d6722da32 100644 --- a/ext/win32ole/win32ole_type.c +++ b/ext/win32ole/win32ole_type.c @@ -145,7 +145,7 @@ foletype_s_typelibs(VALUE self) "WIN32OLE::Type.typelibs", "WIN32OLE::TypeLib.typelibs.collect{t|t.name}"); */ - return rb_eval_string("WIN32OLE_TYPELIB.typelibs.collect{|t|t.name}"); + return rb_eval_string("WIN32OLE::TypeLib.typelibs.collect{|t|t.name}"); } /* @@ -829,7 +829,7 @@ foletype_impl_ole_types(VALUE self) * object and having IMPLTYPEFLAG_FSOURCE. * tobj = WIN32OLE::Type.new('Microsoft Internet Controls', "InternetExplorer") * p tobj.source_ole_types - * # => [#, #] + * # => [#, #] */ static VALUE foletype_source_ole_types(VALUE self) @@ -845,7 +845,7 @@ foletype_source_ole_types(VALUE self) * Returns the array of WIN32OLE::Type object which is implemented by the WIN32OLE::Type * object and having IMPLTYPEFLAG_FSOURCE and IMPLTYPEFLAG_FDEFAULT. * tobj = WIN32OLE::Type.new('Microsoft Internet Controls', "InternetExplorer") - * p tobj.default_event_sources # => [#] + * p tobj.default_event_sources # => [#] */ static VALUE foletype_default_event_sources(VALUE self) @@ -862,7 +862,7 @@ foletype_default_event_sources(VALUE self) * object and having IMPLTYPEFLAG_FDEFAULT. * tobj = WIN32OLE::Type.new('Microsoft Internet Controls', "InternetExplorer") * p tobj.default_ole_types - * # => [#, #] + * # => [#, #] */ static VALUE foletype_default_ole_types(VALUE self) @@ -878,12 +878,12 @@ foletype_default_ole_types(VALUE self) * Returns the type name with class name. * * ie = WIN32OLE.new('InternetExplorer.Application') - * ie.ole_type.inspect => # + * ie.ole_type.inspect => # */ static VALUE foletype_inspect(VALUE self) { - return default_inspect(self, "WIN32OLE_TYPE"); + return default_inspect(self, "WIN32OLE::Type"); } VALUE cWIN32OLE_TYPE; diff --git a/ext/win32ole/win32ole_typelib.c b/ext/win32ole/win32ole_typelib.c index ad7e769a98ee0b..e5eda07e762d54 100644 --- a/ext/win32ole/win32ole_typelib.c +++ b/ext/win32ole/win32ole_typelib.c @@ -814,12 +814,12 @@ foletypelib_ole_types(VALUE self) * Returns the type library name with class name. * * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library') - * tlib.inspect # => "<#WIN32OLE_TYPELIB:Microsoft Excel 9.0 Object Library>" + * tlib.inspect # => "<#WIN32OLE::TypeLib:Microsoft Excel 9.0 Object Library>" */ static VALUE foletypelib_inspect(VALUE self) { - return default_inspect(self, "WIN32OLE_TYPELIB"); + return default_inspect(self, "WIN32OLE::TypeLib"); } VALUE cWIN32OLE_TYPELIB; diff --git a/ext/win32ole/win32ole_variable.c b/ext/win32ole/win32ole_variable.c index e2500388c1c707..34435301d4e349 100644 --- a/ext/win32ole/win32ole_variable.c +++ b/ext/win32ole/win32ole_variable.c @@ -362,7 +362,7 @@ folevariable_inspect(VALUE self) VALUE v = rb_inspect(folevariable_value(self)); VALUE n = folevariable_name(self); VALUE detail = rb_sprintf("%"PRIsVALUE"=%"PRIsVALUE, n, v); - return make_inspect("WIN32OLE_VARIABLE", detail); + return make_inspect("WIN32OLE::Variable", detail); } VALUE cWIN32OLE_VARIABLE; diff --git a/ext/win32ole/win32ole_variant.c b/ext/win32ole/win32ole_variant.c index fd1cc393a0a058..45c70b1dc3425f 100644 --- a/ext/win32ole/win32ole_variant.c +++ b/ext/win32ole/win32ole_variant.c @@ -357,7 +357,7 @@ check_type_val2variant(VALUE val) case T_NIL: break; default: - rb_raise(rb_eTypeError, "can not convert WIN32OLE_VARIANT from type %s", + rb_raise(rb_eTypeError, "can not convert WIN32OLE::Variant from type %s", rb_obj_classname(val)); } } @@ -422,7 +422,7 @@ folevariant_initialize(VALUE self, VALUE args) vvt = rb_ary_entry(args, 1); vt = RB_NUM2INT(vvt); if ((vt & VT_TYPEMASK) == VT_RECORD) { - rb_raise(rb_eArgError, "not supported VT_RECORD WIN32OLE_VARIANT object"); + rb_raise(rb_eArgError, "not supported VT_RECORD WIN32OLE::Variant object"); } ole_val2olevariantdata(val, vt, pvar); } diff --git a/test/win32ole/test_win32ole_method.rb b/test/win32ole/test_win32ole_method.rb index a0e113e7f04556..c52c858f719d6a 100644 --- a/test/win32ole/test_win32ole_method.rb +++ b/test/win32ole/test_win32ole_method.rb @@ -127,7 +127,7 @@ def test_to_s end def test_inspect - assert_equal("#", @m_namespace.inspect) + assert_equal("#", @m_namespace.inspect) end end diff --git a/test/win32ole/test_win32ole_param.rb b/test/win32ole/test_win32ole_param.rb index 09452d19270d16..7145ce615438f1 100644 --- a/test/win32ole/test_win32ole_param.rb +++ b/test/win32ole/test_win32ole_param.rb @@ -43,7 +43,7 @@ def test_s_new assert_equal("OverWriteFiles", param.name) assert_equal(WIN32OLE_PARAM, param.class) assert_equal(true, param.default) - assert_equal("#", param.inspect) + assert_equal("#", param.inspect) end def test_name @@ -91,8 +91,8 @@ def test_to_s end def test_inspect - assert_equal("#", @param_source.inspect) - assert_equal("#", @param_overwritefiles.inspect) + assert_equal("#", @param_source.inspect) + assert_equal("#", @param_overwritefiles.inspect) end end end diff --git a/test/win32ole/test_win32ole_type.rb b/test/win32ole/test_win32ole_type.rb index 485b390d5cc0bd..9f4d7f99f3666c 100644 --- a/test/win32ole/test_win32ole_type.rb +++ b/test/win32ole/test_win32ole_type.rb @@ -178,7 +178,7 @@ def test_implemented_ole_types end def test_inspect - assert_equal("#", @ole_type.inspect) + assert_equal("#", @ole_type.inspect) end # WIN32OLE_TYPE.typelibs will be obsoleted. diff --git a/test/win32ole/test_win32ole_typelib.rb b/test/win32ole/test_win32ole_typelib.rb index 321c019e53ee88..a865d5b4b1222c 100644 --- a/test/win32ole/test_win32ole_typelib.rb +++ b/test/win32ole/test_win32ole_typelib.rb @@ -110,7 +110,7 @@ def test_ole_types def test_inspect tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation") - assert_equal("#", tlib.inspect) + assert_equal("#", tlib.inspect) end end diff --git a/test/win32ole/test_win32ole_variable.rb b/test/win32ole/test_win32ole_variable.rb index 8af3f987a8fc7f..cc4e91123bf3d2 100644 --- a/test/win32ole/test_win32ole_variable.rb +++ b/test/win32ole/test_win32ole_variable.rb @@ -58,8 +58,8 @@ def test_to_s end def test_inspect - assert_equal("#", @var1.inspect) - assert_equal("#", @var2.inspect) + assert_equal("#", @var1.inspect) + assert_equal("#", @var2.inspect) end end From 8af4ef30e57759d4f3994a56dbb38a6151f0bbd3 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 31 Dec 2023 17:07:42 +0900 Subject: [PATCH 599/640] [ruby/win32ole] Move `WIN32OLE` prefixed error classes under `WIN32OLE` https://github.com/ruby/win32ole/commit/1c95816168 --- ext/win32ole/lib/win32ole.rb | 2 +- ext/win32ole/win32ole_error.c | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/ext/win32ole/lib/win32ole.rb b/ext/win32ole/lib/win32ole.rb index 5e20f104cdf461..f5c8a52c4adc43 100644 --- a/ext/win32ole/lib/win32ole.rb +++ b/ext/win32ole/lib/win32ole.rb @@ -25,7 +25,7 @@ def methods(*args) def ole_methods_safely ole_methods - rescue WIN32OLEQueryInterfaceError + rescue WIN32OLE::QueryInterfaceError [] end end diff --git a/ext/win32ole/win32ole_error.c b/ext/win32ole/win32ole_error.c index 2bb515626324dd..66b5136dee2dbe 100644 --- a/ext/win32ole/win32ole_error.c +++ b/ext/win32ole/win32ole_error.c @@ -67,7 +67,7 @@ void Init_win32ole_error(void) { /* - * Document-class: WIN32OLERuntimeError + * Document-class: WIN32OLE::RuntimeError * * Raised when OLE processing failed. * @@ -77,11 +77,20 @@ Init_win32ole_error(void) * * raises the exception: * - * WIN32OLERuntimeError: unknown OLE server: `NonExistProgID' + * WIN32OLE::RuntimeError: unknown OLE server: `NonExistProgID' * HRESULT error code:0x800401f3 * Invalid class string * */ - eWIN32OLERuntimeError = rb_define_class("WIN32OLERuntimeError", rb_eRuntimeError); - eWIN32OLEQueryInterfaceError = rb_define_class("WIN32OLEQueryInterfaceError", eWIN32OLERuntimeError); + eWIN32OLERuntimeError = rb_define_class_under(cWIN32OLE, "RuntimeError", rb_eRuntimeError); + /* Alias of WIN32OLE::RuntimeError, for the backward compatibility */ + rb_define_const(rb_cObject, "WIN32OLERuntimeError", eWIN32OLERuntimeError); + /* + * Document-class: WIN32OLE::QueryInterfaceError + * + * Raised when OLE query failed. + */ + eWIN32OLEQueryInterfaceError = rb_define_class_under(cWIN32OLE, "QueryInterfaceError", eWIN32OLERuntimeError); + /* Alias of WIN32OLE::QueryInterfaceError, for the backward compatibility */ + rb_define_const(rb_cObject, "WIN32OLEQueryInterfaceError", eWIN32OLEQueryInterfaceError); } From bd6f98340318ac17213b4328e79217e606912206 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 31 Dec 2023 11:45:56 +0900 Subject: [PATCH 600/640] [ruby/win32ole] Use the scoped names in the tests https://github.com/ruby/win32ole/commit/2b91b6b838 --- test/win32ole/available_ole.rb | 14 +- test/win32ole/err_in_callback.rb | 4 +- test/win32ole/test_err_in_callback.rb | 4 +- test/win32ole/test_folderitem2_invokeverb.rb | 2 +- test/win32ole/test_nil2vtempty.rb | 2 +- test/win32ole/test_propertyputref.rb | 2 +- test/win32ole/test_thread.rb | 2 +- test/win32ole/test_win32ole.rb | 36 +-- test/win32ole/test_win32ole_event.rb | 66 ++-- test/win32ole/test_win32ole_method.rb | 42 +-- test/win32ole/test_win32ole_method_event.rb | 10 +- test/win32ole/test_win32ole_param.rb | 32 +- test/win32ole/test_win32ole_param_event.rb | 2 +- test/win32ole/test_win32ole_record.rb | 54 ++-- test/win32ole/test_win32ole_type.rb | 62 ++-- test/win32ole/test_win32ole_type_event.rb | 4 +- test/win32ole/test_win32ole_typelib.rb | 60 ++-- test/win32ole/test_win32ole_variable.rb | 8 +- test/win32ole/test_win32ole_variant.rb | 304 +++++++++--------- test/win32ole/test_win32ole_variant_outarg.rb | 6 +- test/win32ole/test_word.rb | 2 +- 21 files changed, 359 insertions(+), 359 deletions(-) diff --git a/test/win32ole/available_ole.rb b/test/win32ole/available_ole.rb index ebc9baae66fc38..af397e00b59393 100644 --- a/test/win32ole/available_ole.rb +++ b/test/win32ole/available_ole.rb @@ -8,7 +8,7 @@ module AvailableOLE module_function def sysmon_available? - WIN32OLE_TYPE.new('System Monitor Control', 'SystemMonitor') + WIN32OLE::Type.new('System Monitor Control', 'SystemMonitor') true rescue false @@ -22,18 +22,18 @@ def ado_available? end def msxml_available? - !WIN32OLE_TYPELIB.typelibs.find { |t| t.name.start_with?('Microsoft XML') }.nil? + !WIN32OLE::TypeLib.typelibs.find { |t| t.name.start_with?('Microsoft XML') }.nil? end def event_param method = if msxml_available? - typelib = WIN32OLE_TYPELIB.typelibs.find { |t| t.name.start_with?('Microsoft XML') } - ole_type = WIN32OLE_TYPE.new(typelib.name, 'IVBSAXContentHandler') - WIN32OLE_METHOD.new(ole_type, 'startElement') + typelib = WIN32OLE::TypeLib.typelibs.find { |t| t.name.start_with?('Microsoft XML') } + ole_type = WIN32OLE::Type.new(typelib.name, 'IVBSAXContentHandler') + WIN32OLE::Method.new(ole_type, 'startElement') elsif ado_available? typelib = WIN32OLE.new('ADODB.Connection').ole_typelib - ole_type = WIN32OLE_TYPE.new(typelib.name, 'Connection') - WIN32OLE_METHOD.new(ole_type, 'WillConnect') + ole_type = WIN32OLE::Type.new(typelib.name, 'Connection') + WIN32OLE::Method.new(ole_type, 'WillConnect') end method && method.params[0] end diff --git a/test/win32ole/err_in_callback.rb b/test/win32ole/err_in_callback.rb index aa6c9c7e3a56e9..baecf780b674b9 100644 --- a/test/win32ole/err_in_callback.rb +++ b/test/win32ole/err_in_callback.rb @@ -2,9 +2,9 @@ require 'win32ole' db = WIN32OLE.new('ADODB.Connection') db.connectionString = "Driver={Microsoft Text Driver (*.txt; *.csv)};DefaultDir=.;" -ev = WIN32OLE_EVENT.new(db) +ev = WIN32OLE::Event.new(db) ev.on_event('WillConnect') {|*args| foo } db.open -WIN32OLE_EVENT.message_loop +WIN32OLE::Event.message_loop diff --git a/test/win32ole/test_err_in_callback.rb b/test/win32ole/test_err_in_callback.rb index 9ffaf9125fdc3e..bea5781bc9e70c 100644 --- a/test/win32ole/test_err_in_callback.rb +++ b/test/win32ole/test_err_in_callback.rb @@ -1,7 +1,7 @@ # frozen_string_literal: false # # test Win32OLE avoids cfp consistency error when the exception raised -# in WIN32OLE_EVENT handler block. [ruby-dev:35450] +# in WIN32OLE::Event handler block. [ruby-dev:35450] # begin @@ -31,7 +31,7 @@ def setup def available_adodb? begin WIN32OLE.new('ADODB.Connection') - rescue WIN32OLERuntimeError + rescue WIN32OLE::RuntimeError return false end return true diff --git a/test/win32ole/test_folderitem2_invokeverb.rb b/test/win32ole/test_folderitem2_invokeverb.rb index e11503ca2aae5a..a1c2b2f472c72c 100644 --- a/test/win32ole/test_folderitem2_invokeverb.rb +++ b/test/win32ole/test_folderitem2_invokeverb.rb @@ -44,7 +44,7 @@ def test_invokeverb assert_equal(0, links.size) # Now create shortcut to @dummy_path - arg = WIN32OLE_VARIANT.new("Link") + arg = WIN32OLE::Variant.new("Link") @fi2.InvokeVerb(arg) # Now search shortcut to @dummy_path diff --git a/test/win32ole/test_nil2vtempty.rb b/test/win32ole/test_nil2vtempty.rb index 49757d61b397c2..bd864036766404 100644 --- a/test/win32ole/test_nil2vtempty.rb +++ b/test/win32ole/test_nil2vtempty.rb @@ -28,7 +28,7 @@ def test_openSchema assert(rs) assert_equal("_Recordset", rs.ole_type.name) - rs = con.openSchema(4, [WIN32OLE_VARIANT::Empty, WIN32OLE_VARIANT::Empty, "DUMMY", "TABLE"]) + rs = con.openSchema(4, [WIN32OLE::Variant::Empty, WIN32OLE::Variant::Empty, "DUMMY", "TABLE"]) assert(rs) assert_equal("_Recordset", rs.ole_type.name) end diff --git a/test/win32ole/test_propertyputref.rb b/test/win32ole/test_propertyputref.rb index 93edb508351c95..83418140c2e523 100644 --- a/test/win32ole/test_propertyputref.rb +++ b/test/win32ole/test_propertyputref.rb @@ -11,7 +11,7 @@ def setup begin @sapi = WIN32OLE.new('SAPI.SpVoice') @sv = @sapi.voice - rescue WIN32OLERuntimeError + rescue WIN32OLE::RuntimeError @sapi = nil end end diff --git a/test/win32ole/test_thread.rb b/test/win32ole/test_thread.rb index cb34693064b7f8..b30b2349c5f8aa 100644 --- a/test/win32ole/test_thread.rb +++ b/test/win32ole/test_thread.rb @@ -14,7 +14,7 @@ def assert_creating_win32ole_object_in_thread(meth) t = Thread.__send__(meth) { WIN32OLE.new('Scripting.Dictionary') } - assert_nothing_raised(WIN32OLERuntimeError, "[Bug #2618] Thread.#{meth}") { + assert_nothing_raised(WIN32OLE::RuntimeError, "[Bug #2618] Thread.#{meth}") { t.join } end diff --git a/test/win32ole/test_win32ole.rb b/test/win32ole/test_win32ole.rb index 594830b8fad623..b0c147b3116c15 100644 --- a/test/win32ole/test_win32ole.rb +++ b/test/win32ole/test_win32ole.rb @@ -34,23 +34,23 @@ def test_setproperty_equal_ended assert_equal(1, @dict2.item("one")) end def test_non_exist_property - assert_raise(WIN32OLERuntimeError) { + assert_raise(WIN32OLE::RuntimeError) { @dict1.unknown_property = 1 } end def test_raise_message - exc = assert_raise(WIN32OLERuntimeError) { + exc = assert_raise(WIN32OLE::RuntimeError) { @dict1.add } assert_match(/^\(in OLE method `add': \)/, exc.message) #` - exc = assert_raise(WIN32OLERuntimeError) { + exc = assert_raise(WIN32OLE::RuntimeError) { @dict1._invoke(1, [], []) } assert_match(/^\(in OLE method `': \)/, exc.message) #` - exc = assert_raise(WIN32OLERuntimeError) { + exc = assert_raise(WIN32OLE::RuntimeError) { @dict1.compareMode = -1 } assert_match(/^\(in setting property `compareMode': \)/, exc.message) #` @@ -184,7 +184,7 @@ def test_s_new_DCOM def test_s_new_from_clsid shell = WIN32OLE.new("{13709620-C279-11CE-A49E-444553540000}") assert_instance_of(WIN32OLE, shell) - exc = assert_raise(WIN32OLERuntimeError) { + exc = assert_raise(WIN32OLE::RuntimeError) { WIN32OLE.new("{000}") } assert_match(/unknown OLE server: `\{000\}'/, exc.message) #` @@ -341,13 +341,13 @@ def test_s_codepage_changed fso = WIN32OLE.new("Scripting.FileSystemObject") fname = fso.getTempName begin - obj = WIN32OLE_VARIANT.new([0x3042].pack("U*").force_encoding("UTF-8")) + obj = WIN32OLE::Variant.new([0x3042].pack("U*").force_encoding("UTF-8")) WIN32OLE.codepage = WIN32OLE::CP_UTF8 assert_equal("\xE3\x81\x82".force_encoding("CP65001"), obj.value) begin WIN32OLE.codepage = 932 # Windows-31J - rescue WIN32OLERuntimeError + rescue WIN32OLE::RuntimeError end if (WIN32OLE.codepage == 932) assert_equal("\x82\xA0".force_encoding("CP932"), obj.value) @@ -355,7 +355,7 @@ def test_s_codepage_changed begin WIN32OLE.codepage = 20932 # MS EUC-JP - rescue WIN32OLERuntimeError + rescue WIN32OLE::RuntimeError end if (WIN32OLE.codepage == 20932) assert_equal("\xA4\xA2".force_encoding("CP20932"), obj.value) @@ -378,7 +378,7 @@ def test_s_codepage_changed # This test fail if codepage 20932 (euc) is not installed. begin WIN32OLE.codepage = 20932 - rescue WIN32OLERuntimeError + rescue WIN32OLE::RuntimeError end if (WIN32OLE.codepage == 20932) WIN32OLE.codepage = cp @@ -405,7 +405,7 @@ def test_s_codepage_changed def test_cp51932 cp = WIN32OLE.codepage begin - obj = WIN32OLE_VARIANT.new([0x3042].pack("U*").force_encoding("UTF-8")) + obj = WIN32OLE::Variant.new([0x3042].pack("U*").force_encoding("UTF-8")) begin WIN32OLE.codepage = 51932 rescue @@ -426,13 +426,13 @@ def test_s_locale_set begin begin WIN32OLE.locale = 1041 - rescue WIN32OLERuntimeError + rescue WIN32OLE::RuntimeError STDERR.puts("\n#{__FILE__}:#{__LINE__}:#{self.class.name}.test_s_locale_set is skipped(Japanese locale is not installed)") return end assert_equal(1041, WIN32OLE.locale) WIN32OLE.locale = WIN32OLE::LOCALE_SYSTEM_DEFAULT - assert_raise(WIN32OLERuntimeError) { + assert_raise(WIN32OLE::RuntimeError) { WIN32OLE.locale = 111 } assert_equal(WIN32OLE::LOCALE_SYSTEM_DEFAULT, WIN32OLE.locale) @@ -445,13 +445,13 @@ def test_s_locale_change begin begin WIN32OLE.locale = 0x0411 - rescue WIN32OLERuntimeError + rescue WIN32OLE::RuntimeError end if WIN32OLE.locale == 0x0411 - obj = WIN32OLE_VARIANT.new("\\100,000", WIN32OLE::VARIANT::VT_CY) + obj = WIN32OLE::Variant.new("\\100,000", WIN32OLE::VARIANT::VT_CY) assert_equal("100000", obj.value) - assert_raise(WIN32OLERuntimeError) { - obj = WIN32OLE_VARIANT.new("$100.000", WIN32OLE::VARIANT::VT_CY) + assert_raise(WIN32OLE::RuntimeError) { + obj = WIN32OLE::Variant.new("$100.000", WIN32OLE::VARIANT::VT_CY) } else STDERR.puts("\n#{__FILE__}:#{__LINE__}:#{self.class.name}.test_s_locale_change is skipped(Japanese locale is not installed)") @@ -459,10 +459,10 @@ def test_s_locale_change begin WIN32OLE.locale = 1033 - rescue WIN32OLERuntimeError + rescue WIN32OLE::RuntimeError end if WIN32OLE.locale == 1033 - obj = WIN32OLE_VARIANT.new("$100,000", WIN32OLE::VARIANT::VT_CY) + obj = WIN32OLE::Variant.new("$100,000", WIN32OLE::VARIANT::VT_CY) assert_equal("100000", obj.value) else STDERR.puts("\n#{__FILE__}:#{__LINE__}:#{self.class.name}.test_s_locale_change is skipped(US English locale is not installed)") diff --git a/test/win32ole/test_win32ole_event.rb b/test/win32ole/test_win32ole_event.rb index f02df53be7aef7..da3ee8567e8ebb 100644 --- a/test/win32ole/test_win32ole_event.rb +++ b/test/win32ole/test_win32ole_event.rb @@ -28,17 +28,17 @@ end end -if defined?(WIN32OLE_EVENT) +if defined?(WIN32OLE::Event) class TestWIN32OLE_EVENT < Test::Unit::TestCase def test_s_new_exception assert_raise(TypeError) { - WIN32OLE_EVENT.new("A") + WIN32OLE::Event.new("A") } end def test_s_new_non_exist_event dict = WIN32OLE.new('Scripting.Dictionary') assert_raise(RuntimeError) { - WIN32OLE_EVENT.new(dict) + WIN32OLE::Event.new(dict) } end end @@ -58,7 +58,7 @@ def message_loop(watch_ivar = nil) end 2.times do - WIN32OLE_EVENT.message_loop + WIN32OLE::Event.message_loop sleep 1 end @@ -68,7 +68,7 @@ def message_loop(watch_ivar = nil) seconds = EnvUtil.apply_timeout_scale(1) while tries < 5 && instance_variable_get(watch_ivar) == orig_ivar $stderr.puts "test_win32ole_event.rb: retrying and sleeping #{seconds}s until #{watch_ivar} is changed from #{orig_ivar.inspect}..." - WIN32OLE_EVENT.message_loop + WIN32OLE::Event.message_loop sleep(seconds) tries += 1 seconds *= 2 # sleep at most 31s in total @@ -86,24 +86,24 @@ def handler1 def test_s_new_non_exist_event assert_raise(RuntimeError) { - WIN32OLE_EVENT.new(@sws, 'XXXXX') + WIN32OLE::Event.new(@sws, 'XXXXX') } end def test_s_new - obj = WIN32OLE_EVENT.new(@sws, 'ISWbemSinkEvents') - assert_instance_of(WIN32OLE_EVENT, obj) - obj = WIN32OLE_EVENT.new(@sws) - assert_instance_of(WIN32OLE_EVENT, obj) + obj = WIN32OLE::Event.new(@sws, 'ISWbemSinkEvents') + assert_instance_of(WIN32OLE::Event, obj) + obj = WIN32OLE::Event.new(@sws) + assert_instance_of(WIN32OLE::Event, obj) end def test_s_new_loop exec_notification_query_async - ev = WIN32OLE_EVENT.new(@sws) + ev = WIN32OLE::Event.new(@sws) ev.on_event {|*args| default_handler(*args)} message_loop 10.times do |i| - WIN32OLE_EVENT.new(@sws) + WIN32OLE::Event.new(@sws) message_loop GC.start end @@ -115,7 +115,7 @@ def test_s_new_loop def test_on_event exec_notification_query_async - ev = WIN32OLE_EVENT.new(@sws, 'ISWbemSinkEvents') + ev = WIN32OLE::Event.new(@sws, 'ISWbemSinkEvents') ev.on_event {|*args| default_handler(*args)} message_loop(:@event) assert_match(/OnObjectReady/, @event) @@ -123,7 +123,7 @@ def test_on_event def test_on_event_symbol exec_notification_query_async - ev = WIN32OLE_EVENT.new(@sws) + ev = WIN32OLE::Event.new(@sws) ev.on_event(:OnObjectReady) {|*args| handler1 } @@ -163,7 +163,7 @@ class TestWIN32OLE_EVENT_ADO < Test::Unit::TestCase module ADO end def message_loop - WIN32OLE_EVENT.message_loop + WIN32OLE::Event.message_loop end def default_handler(event, *args) @@ -182,7 +182,7 @@ def setup end def test_on_event2 - ev = WIN32OLE_EVENT.new(@db, 'ConnectionEvents') + ev = WIN32OLE::Event.new(@db, 'ConnectionEvents') ev.on_event('WillConnect') {|*args| handler1} ev.on_event('WillConnect') {|*args| handler2} @db.open @@ -191,7 +191,7 @@ def test_on_event2 end def test_on_event4 - ev = WIN32OLE_EVENT.new(@db, 'ConnectionEvents') + ev = WIN32OLE::Event.new(@db, 'ConnectionEvents') ev.on_event{|*args| handler1} ev.on_event{|*args| handler2} ev.on_event('WillConnect'){|*args| handler3(*args)} @@ -202,7 +202,7 @@ def test_on_event4 end def test_on_event5 - ev = WIN32OLE_EVENT.new(@db, 'ConnectionEvents') + ev = WIN32OLE::Event.new(@db, 'ConnectionEvents') ev.on_event {|*args| default_handler(*args)} ev.on_event('WillConnect'){|*args| handler3(*args)} @db.open @@ -213,7 +213,7 @@ def test_on_event5 end def test_unadvise - ev = WIN32OLE_EVENT.new(@db, 'ConnectionEvents') + ev = WIN32OLE::Event.new(@db, 'ConnectionEvents') ev.on_event {|*args| default_handler(*args)} @db.open message_loop @@ -224,16 +224,16 @@ def test_unadvise @db.open message_loop assert_equal("", @event); - assert_raise(WIN32OLERuntimeError) { + assert_raise(WIN32OLE::RuntimeError) { ev.on_event {|*args| default_handler(*args)} } end def test_on_event_with_outargs - ev = WIN32OLE_EVENT.new(@db) + ev = WIN32OLE::Event.new(@db) @db.connectionString = 'XXX' # set illegal connection string - assert_raise(WIN32OLERuntimeError) { + assert_raise(WIN32OLE::RuntimeError) { @db.open } ev.on_event_with_outargs('WillConnect'){|*args| @@ -245,7 +245,7 @@ def test_on_event_with_outargs end def test_on_event_hash_return - ev = WIN32OLE_EVENT.new(@db) + ev = WIN32OLE::Event.new(@db) ev.on_event('WillConnect'){|*args| {:return => 1, :ConnectionString => CONNSTR} } @@ -255,7 +255,7 @@ def test_on_event_hash_return end def test_on_event_hash_return2 - ev = WIN32OLE_EVENT.new(@db) + ev = WIN32OLE::Event.new(@db) ev.on_event('WillConnect'){|*args| {:ConnectionString => CONNSTR} } @@ -265,7 +265,7 @@ def test_on_event_hash_return2 end def test_on_event_hash_return3 - ev = WIN32OLE_EVENT.new(@db) + ev = WIN32OLE::Event.new(@db) ev.on_event('WillConnect'){|*args| {'ConnectionString' => CONNSTR} } @@ -275,7 +275,7 @@ def test_on_event_hash_return3 end def test_on_event_hash_return4 - ev = WIN32OLE_EVENT.new(@db) + ev = WIN32OLE::Event.new(@db) ev.on_event('WillConnect'){|*args| {'return' => 1, 'ConnectionString' => CONNSTR} } @@ -285,7 +285,7 @@ def test_on_event_hash_return4 end def test_on_event_hash_return5 - ev = WIN32OLE_EVENT.new(@db) + ev = WIN32OLE::Event.new(@db) ev.on_event('WillConnect'){|*args| {0 => CONNSTR} } @@ -295,7 +295,7 @@ def test_on_event_hash_return5 end def test_off_event - ev = WIN32OLE_EVENT.new(@db) + ev = WIN32OLE::Event.new(@db) ev.on_event{handler1} ev.off_event @db.open @@ -304,7 +304,7 @@ def test_off_event end def test_off_event_arg - ev = WIN32OLE_EVENT.new(@db) + ev = WIN32OLE::Event.new(@db) ev.on_event('WillConnect'){handler1} ev.off_event('WillConnect') @db.open @@ -313,7 +313,7 @@ def test_off_event_arg end def test_off_event_arg2 - ev = WIN32OLE_EVENT.new(@db) + ev = WIN32OLE::Event.new(@db) ev.on_event('WillConnect'){handler1} ev.on_event('ConnectComplete'){handler1} ev.off_event('WillConnect') @@ -323,7 +323,7 @@ def test_off_event_arg2 end def test_off_event_sym_arg - ev = WIN32OLE_EVENT.new(@db) + ev = WIN32OLE::Event.new(@db) ev.on_event('WillConnect'){handler1} ev.off_event(:WillConnect) @db.open @@ -382,7 +382,7 @@ def method_missing(ev, *arg) end def test_handler1 - ev = WIN32OLE_EVENT.new(@db) + ev = WIN32OLE::Event.new(@db) h1 = Handler1.new ev.handler = h1 @db.open @@ -395,7 +395,7 @@ def test_handler1 end def test_handler2 - ev = WIN32OLE_EVENT.new(@db) + ev = WIN32OLE::Event.new(@db) h2 = Handler2.new ev.handler = h2 @db.open diff --git a/test/win32ole/test_win32ole_method.rb b/test/win32ole/test_win32ole_method.rb index c52c858f719d6a..4b3e255fdc99fe 100644 --- a/test/win32ole/test_win32ole_method.rb +++ b/test/win32ole/test_win32ole_method.rb @@ -5,42 +5,42 @@ end require "test/unit" -if defined?(WIN32OLE_METHOD) +if defined?(WIN32OLE::Method) class TestWIN32OLE_METHOD < Test::Unit::TestCase def setup - ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell") - @m_open = WIN32OLE_METHOD.new(ole_type, "open") - @m_namespace = WIN32OLE_METHOD.new(ole_type, "namespace") - @m_parent = WIN32OLE_METHOD.new(ole_type, "parent") - @m_invoke = WIN32OLE_METHOD.new(ole_type, "invoke") - @m_browse_for_folder = WIN32OLE_METHOD.new(ole_type, "BrowseForFolder") + ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell") + @m_open = WIN32OLE::Method.new(ole_type, "open") + @m_namespace = WIN32OLE::Method.new(ole_type, "namespace") + @m_parent = WIN32OLE::Method.new(ole_type, "parent") + @m_invoke = WIN32OLE::Method.new(ole_type, "invoke") + @m_browse_for_folder = WIN32OLE::Method.new(ole_type, "BrowseForFolder") - ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "File") - @m_file_name = WIN32OLE_METHOD.new(ole_type, "name") + ole_type = WIN32OLE::Type.new("Microsoft Scripting Runtime", "File") + @m_file_name = WIN32OLE::Method.new(ole_type, "name") end def test_initialize - ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell") + ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell") assert_raise(TypeError) { - WIN32OLE_METHOD.new(1, 2) + WIN32OLE::Method.new(1, 2) } assert_raise(ArgumentError) { - WIN32OLE_METHOD.new("foo") + WIN32OLE::Method.new("foo") } assert_raise(ArgumentError) { - WIN32OLE_METHOD.new(ole_type) + WIN32OLE::Method.new(ole_type) } - assert_raise(WIN32OLERuntimeError) { - WIN32OLE_METHOD.new(ole_type, "NonExistMethod") + assert_raise(WIN32OLE::RuntimeError) { + WIN32OLE::Method.new(ole_type, "NonExistMethod") } assert_raise(TypeError) { - WIN32OLE_METHOD.new(ole_type, 1) + WIN32OLE::Method.new(ole_type, 1) } - method = WIN32OLE_METHOD.new(ole_type, "Open") - assert_instance_of(WIN32OLE_METHOD, method) - method = WIN32OLE_METHOD.new(ole_type, "open") - assert_instance_of(WIN32OLE_METHOD, method) + method = WIN32OLE::Method.new(ole_type, "Open") + assert_instance_of(WIN32OLE::Method, method) + method = WIN32OLE::Method.new(ole_type, "open") + assert_instance_of(WIN32OLE::Method, method) end def test_name @@ -119,7 +119,7 @@ def test_params params = @m_browse_for_folder.params assert_instance_of(Array, params) assert_equal(4, params.size) - assert_instance_of(WIN32OLE_PARAM, params[0]) + assert_instance_of(WIN32OLE::Param, params[0]) end def test_to_s diff --git a/test/win32ole/test_win32ole_method_event.rb b/test/win32ole/test_win32ole_method_event.rb index 77581688725da9..ab409a1f2d533c 100644 --- a/test/win32ole/test_win32ole_method_event.rb +++ b/test/win32ole/test_win32ole_method_event.rb @@ -5,7 +5,7 @@ require 'test/unit' -if defined?(WIN32OLE_METHOD) +if defined?(WIN32OLE::Method) require_relative 'available_ole' class TestWIN32OLE_METHOD_EVENT < Test::Unit::TestCase unless AvailableOLE.sysmon_available? @@ -14,10 +14,10 @@ def test_dummy_for_skip_message end else def setup - ole_type = WIN32OLE_TYPE.new('System Monitor Control', 'SystemMonitor') - @on_dbl_click = WIN32OLE_METHOD.new(ole_type, 'OnDblClick') - ole_type = WIN32OLE_TYPE.new('Microsoft Shell Controls And Automation', 'Shell') - @namespace = WIN32OLE_METHOD.new(ole_type, 'namespace') + ole_type = WIN32OLE::Type.new('System Monitor Control', 'SystemMonitor') + @on_dbl_click = WIN32OLE::Method.new(ole_type, 'OnDblClick') + ole_type = WIN32OLE::Type.new('Microsoft Shell Controls And Automation', 'Shell') + @namespace = WIN32OLE::Method.new(ole_type, 'namespace') end def test_event? diff --git a/test/win32ole/test_win32ole_param.rb b/test/win32ole/test_win32ole_param.rb index 7145ce615438f1..551da537fc7165 100644 --- a/test/win32ole/test_win32ole_param.rb +++ b/test/win32ole/test_win32ole_param.rb @@ -5,43 +5,43 @@ end require "test/unit" -if defined?(WIN32OLE_PARAM) +if defined?(WIN32OLE::Param) class TestWIN32OLE_PARAM < Test::Unit::TestCase def setup - ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellLinkObject") - m_geticonlocation = WIN32OLE_METHOD.new(ole_type, "GetIconLocation") + ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "ShellLinkObject") + m_geticonlocation = WIN32OLE::Method.new(ole_type, "GetIconLocation") @param_pbs = m_geticonlocation.params[0] - ole_type = WIN32OLE_TYPE.new("Microsoft HTML Object Library", "FontNames") - m_count = WIN32OLE_METHOD.new(ole_type, "Count") + ole_type = WIN32OLE::Type.new("Microsoft HTML Object Library", "FontNames") + m_count = WIN32OLE::Method.new(ole_type, "Count") @param_p = m_count.params[0] - ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "FileSystemObject") - m_copyfile = WIN32OLE_METHOD.new(ole_type, "CopyFile") + ole_type = WIN32OLE::Type.new("Microsoft Scripting Runtime", "FileSystemObject") + m_copyfile = WIN32OLE::Method.new(ole_type, "CopyFile") @param_source = m_copyfile.params[0] @param_overwritefiles = m_copyfile.params[2] - ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "Dictionary") - m_add = WIN32OLE_METHOD.new(ole_type, "Add") + ole_type = WIN32OLE::Type.new("Microsoft Scripting Runtime", "Dictionary") + m_add = WIN32OLE::Method.new(ole_type, "Add") @param_key = m_add.params[0] end def test_s_new assert_raise(ArgumentError) { - WIN32OLE_PARAM.new("hoge") + WIN32OLE::Param.new("hoge") } - ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "FileSystemObject") - m_copyfile = WIN32OLE_METHOD.new(ole_type, "CopyFile") + ole_type = WIN32OLE::Type.new("Microsoft Scripting Runtime", "FileSystemObject") + m_copyfile = WIN32OLE::Method.new(ole_type, "CopyFile") assert_raise(IndexError) { - WIN32OLE_PARAM.new(m_copyfile, 4); + WIN32OLE::Param.new(m_copyfile, 4); } assert_raise(IndexError) { - WIN32OLE_PARAM.new(m_copyfile, 0); + WIN32OLE::Param.new(m_copyfile, 0); } - param = WIN32OLE_PARAM.new(m_copyfile, 3) + param = WIN32OLE::Param.new(m_copyfile, 3) assert_equal("OverWriteFiles", param.name) - assert_equal(WIN32OLE_PARAM, param.class) + assert_equal(WIN32OLE::Param, param.class) assert_equal(true, param.default) assert_equal("#", param.inspect) end diff --git a/test/win32ole/test_win32ole_param_event.rb b/test/win32ole/test_win32ole_param_event.rb index a659a6d0f3e18f..f5a16ead7669d3 100644 --- a/test/win32ole/test_win32ole_param_event.rb +++ b/test/win32ole/test_win32ole_param_event.rb @@ -5,7 +5,7 @@ require 'test/unit' -if defined?(WIN32OLE_PARAM) +if defined?(WIN32OLE::Param) require_relative 'available_ole' class TestWIN32OLE_PARAM_EVENT < Test::Unit::TestCase diff --git a/test/win32ole/test_win32ole_record.rb b/test/win32ole/test_win32ole_record.rb index 65fd5f6a3caaba..b2f26403bbcbed 100644 --- a/test/win32ole/test_win32ole_record.rb +++ b/test/win32ole/test_win32ole_record.rb @@ -65,18 +65,18 @@ =end -if defined?(WIN32OLE_RECORD) +if defined?(WIN32OLE::Record) def rbcomtest_exist? WIN32OLE.new(PROGID_RBCOMTEST) true - rescue WIN32OLERuntimeError + rescue WIN32OLE::RuntimeError false end class TestWIN32OLE_RECORD_BY_RBCOMTEST < Test::Unit::TestCase unless rbcomtest_exist? def test_dummy_for_skip_message - omit "#{PROGID_RBCOMTEST} for WIN32OLE_RECORD test is not installed" + omit "#{PROGID_RBCOMTEST} for WIN32OLE::Record test is not installed" end else def setup @@ -84,42 +84,42 @@ def setup end def test_s_new_from_win32ole - rec = WIN32OLE_RECORD.new('Book', @obj) + rec = WIN32OLE::Record.new('Book', @obj) assert(rec) - assert_instance_of(WIN32OLE_RECORD, rec) + assert_instance_of(WIN32OLE::Record, rec) end def test_s_new_from_win32ole_typelib tlib = @obj.ole_typelib - rec = WIN32OLE_RECORD.new('Book', tlib) + rec = WIN32OLE::Record.new('Book', tlib) assert(rec) - assert_instance_of(WIN32OLE_RECORD, rec) + assert_instance_of(WIN32OLE::Record, rec) end def test_s_new_raise - assert_raise(WIN32OLERuntimeError) { - WIN32OLE_RECORD.new('NonExistRecordName', @obj) + assert_raise(WIN32OLE::RuntimeError) { + WIN32OLE::Record.new('NonExistRecordName', @obj) } assert_raise(ArgumentError) { - WIN32OLE_RECORD.new + WIN32OLE::Record.new } assert_raise(ArgumentError) { - WIN32OLE_RECORD.new('NonExistRecordName') + WIN32OLE::Record.new('NonExistRecordName') } end def test_to_h - rec = WIN32OLE_RECORD.new('Book', @obj) + rec = WIN32OLE::Record.new('Book', @obj) assert_equal({'title'=>nil, 'cost'=>nil}, rec.to_h) end def test_typename - rec = WIN32OLE_RECORD.new('Book', @obj) + rec = WIN32OLE::Record.new('Book', @obj) assert_equal('Book', rec.typename) end def test_method_missing_getter - rec = WIN32OLE_RECORD.new('Book', @obj) + rec = WIN32OLE::Record.new('Book', @obj) assert_equal(nil, rec.title) assert_raise(KeyError) { rec.non_exist_name @@ -127,14 +127,14 @@ def test_method_missing_getter end def test_method_missing_setter - rec = WIN32OLE_RECORD.new('Book', @obj) + rec = WIN32OLE::Record.new('Book', @obj) rec.title = "Ruby Book" assert_equal("Ruby Book", rec.title) end def test_get_record_from_comserver rec = @obj.getBook - assert_instance_of(WIN32OLE_RECORD, rec) + assert_instance_of(WIN32OLE::Record, rec) assert_equal("The Ruby Book", rec.title) assert_equal(20, rec.cost) end @@ -143,16 +143,16 @@ def test_get_record_array_from_comserver rec = @obj.getBooks assert_instance_of(Array, rec) assert_equal(2, rec.size) - assert_instance_of(WIN32OLE_RECORD, rec[0]) + assert_instance_of(WIN32OLE::Record, rec[0]) assert_equal("The CRuby Book", rec[0].title) assert_equal(30, rec[0].cost) - assert_instance_of(WIN32OLE_RECORD, rec[1]) + assert_instance_of(WIN32OLE::Record, rec[1]) assert_equal("The JRuby Book", rec[1].title) assert_equal(40, rec[1].cost) end def test_pass_record_parameter - rec = WIN32OLE_RECORD.new('Book', @obj) + rec = WIN32OLE::Record.new('Book', @obj) rec.title = "Ruby Book" rec.cost = 60 book = @obj.getVer2BookByValBook(rec) @@ -161,23 +161,23 @@ def test_pass_record_parameter end def test_pass_variant_parameter_byref - obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_VARIANT|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new(nil, WIN32OLE::VARIANT::VT_VARIANT|WIN32OLE::VARIANT::VT_BYREF) @obj.getBookByRefBook(obj) - assert_instance_of(WIN32OLE_RECORD, obj.value) + assert_instance_of(WIN32OLE::Record, obj.value) book = obj.value assert_equal("The Ruby Reference Book2", book.title) assert_equal(44, book.cost) end def test_pass_record_parameter_byref - book = WIN32OLE_RECORD.new('Book', @obj) + book = WIN32OLE::Record.new('Book', @obj) @obj.getBookByRefBook(book) assert_equal("The Ruby Reference Book2", book.title) assert_equal(44, book.cost) end def test_pass_and_get_record_parameter_byref - book = WIN32OLE_RECORD.new('Book', @obj) + book = WIN32OLE::Record.new('Book', @obj) book.title = "Ruby Book" book.cost = 60 @obj.getVer3BookByRefBook(book) @@ -186,13 +186,13 @@ def test_pass_and_get_record_parameter_byref end def test_ole_instance_variable_get - obj = WIN32OLE_RECORD.new('Book', @obj) + obj = WIN32OLE::Record.new('Book', @obj) assert_equal(nil, obj.ole_instance_variable_get(:title)) assert_equal(nil, obj.ole_instance_variable_get('title')) end def test_ole_instance_variable_set - book = WIN32OLE_RECORD.new('Book', @obj) + book = WIN32OLE::Record.new('Book', @obj) book.ole_instance_variable_set(:title, "Ruby Book") assert_equal("Ruby Book", book.title) book.ole_instance_variable_set('title', "Ruby Book2") @@ -200,8 +200,8 @@ def test_ole_instance_variable_set end def test_inspect - book = WIN32OLE_RECORD.new('Book', @obj) - assert_equal(%q[#nil, "cost"=>nil}>], book.inspect) + book = WIN32OLE::Record.new('Book', @obj) + assert_equal(%q[#nil, "cost"=>nil}>], book.inspect) end end end diff --git a/test/win32ole/test_win32ole_type.rb b/test/win32ole/test_win32ole_type.rb index 9f4d7f99f3666c..32aafcbbad5db6 100644 --- a/test/win32ole/test_win32ole_type.rb +++ b/test/win32ole/test_win32ole_type.rb @@ -5,11 +5,11 @@ end require "test/unit" -if defined?(WIN32OLE_TYPE) +if defined?(WIN32OLE::Type) class TestWIN32OLE_TYPE < Test::Unit::TestCase def test_s_progids - progids = WIN32OLE_TYPE.progids + progids = WIN32OLE::Type.progids assert_instance_of(Array, progids) assert(progids.size > 0) assert_instance_of(String, progids[0]) @@ -18,25 +18,25 @@ def test_s_progids def test_initialize assert_raise(ArgumentError) { - WIN32OLE_TYPE.new + WIN32OLE::Type.new } assert_raise(ArgumentError) { - WIN32OLE_TYPE.new("foo") + WIN32OLE::Type.new("foo") } assert_raise(TypeError) { - WIN32OLE_TYPE.new(1, 2) + WIN32OLE::Type.new(1, 2) } assert_raise(TypeError) { - WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", 1) + WIN32OLE::Type.new("Microsoft Shell Controls And Automation", 1) } - assert_raise(WIN32OLERuntimeError) { - WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "foo") + assert_raise(WIN32OLE::RuntimeError) { + WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "foo") } - assert_raise(WIN32OLERuntimeError) { - WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Application") + assert_raise(WIN32OLE::RuntimeError) { + WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Application") } - ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell") - assert_instance_of(WIN32OLE_TYPE, ole_type) + ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell") + assert_instance_of(WIN32OLE::Type, ole_type) assert_equal("Shell", ole_type.name) assert_equal("Class", ole_type.ole_type) assert_equal("{13709620-C279-11CE-A49E-444553540000}", ole_type.guid) @@ -53,8 +53,8 @@ def test_initialize assert_equal([], ole_type.variables) assert(ole_type.ole_methods.select{|m|/NameSpace/i =~ m.name}.size > 0) - ole_type2 = WIN32OLE_TYPE.new("{13709620-C279-11CE-A49E-444553540000}", "Shell") - assert_instance_of(WIN32OLE_TYPE, ole_type) + ole_type2 = WIN32OLE::Type.new("{13709620-C279-11CE-A49E-444553540000}", "Shell") + assert_instance_of(WIN32OLE::Type, ole_type) assert_equal(ole_type.name, ole_type2.name) assert_equal(ole_type.ole_type, ole_type2.ole_type) assert_equal(ole_type.guid, ole_type2.guid) @@ -76,7 +76,7 @@ def test_initialize end def setup - @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell") + @ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell") end def test_name @@ -97,7 +97,7 @@ def test_progid def test_visible? assert(@ole_type.visible?) - ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "IShellDispatch") + ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "IShellDispatch") assert(!ole_type.visible?) end @@ -107,13 +107,13 @@ def test_to_s def test_major_version assert_equal(0, @ole_type.major_version) - # ole_type = WIN32OLE_TYPE.new("Microsoft Word 11.0 Object Library", "Documents") + # ole_type = WIN32OLE::Type.new("Microsoft Word 11.0 Object Library", "Documents") # assert_equal(8, ole_type.major_version) end def test_minor_version assert_equal(0, @ole_type.minor_version) - # ole_type = WIN32OLE_TYPE.new("Microsoft Word 11.0 Object Library", "Documents") + # ole_type = WIN32OLE::Type.new("Microsoft Word 11.0 Object Library", "Documents") # assert_equal(3, ole_type.minor_version) end @@ -126,20 +126,20 @@ def test_helpstring end def test_src_type - ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "DriveTypeConst") + ole_type = WIN32OLE::Type.new("Microsoft Scripting Runtime", "DriveTypeConst") assert_match(/__MIDL___MIDL_itf_scrrun_/, ole_type.src_type) assert_equal(nil, @ole_type.src_type) end def test_helpfile assert_equal("", @ole_type.helpfile) - ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "Folders") + ole_type = WIN32OLE::Type.new("Microsoft Scripting Runtime", "Folders") assert_match(/VBENLR98\.CHM$/i, ole_type.helpfile) end def test_helpcontext assert_equal(0, @ole_type.helpcontext) - ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "Folders") + ole_type = WIN32OLE::Type.new("Microsoft Scripting Runtime", "Folders") assert_equal(2181929, ole_type.helpcontext) end @@ -148,25 +148,25 @@ def test_variables assert_instance_of(Array, variables) assert(variables.size == 0) - ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants") + ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants") variables = ole_type.variables assert_instance_of(Array, variables) assert(variables.size > 0) - assert_instance_of(WIN32OLE_VARIABLE, variables[0]) + assert_instance_of(WIN32OLE::Variable, variables[0]) end def test_ole_methods methods = @ole_type.ole_methods assert_instance_of(Array, methods) assert(methods.size > 0) - assert_instance_of(WIN32OLE_METHOD, methods[0]); + assert_instance_of(WIN32OLE::Method, methods[0]); assert(methods.collect{|m| m.name}.include?("Application")) end def test_ole_typelib tlib = @ole_type.ole_typelib - assert_instance_of(WIN32OLE_TYPELIB, tlib) + assert_instance_of(WIN32OLE::TypeLib, tlib) assert_equal("Microsoft Shell Controls And Automation", tlib.name) end @@ -181,17 +181,17 @@ def test_inspect assert_equal("#", @ole_type.inspect) end - # WIN32OLE_TYPE.typelibs will be obsoleted. + # WIN32OLE::Type.typelibs will be obsoleted. def test_s_typelibs - tlibs = WIN32OLE_TYPE.typelibs.sort - tlibs2 = WIN32OLE_TYPELIB.typelibs.collect{|t|t.name}.sort + tlibs = WIN32OLE::Type.typelibs.sort + tlibs2 = WIN32OLE::TypeLib.typelibs.collect{|t|t.name}.sort assert_equal(tlibs2, tlibs) end - # WIN32OLE_TYPE.ole_classes will be obsoleted. + # WIN32OLE::Type.ole_classes will be obsoleted. def test_s_ole_classes - ots1 = WIN32OLE_TYPE.ole_classes("Microsoft Shell Controls And Automation") - ots2 = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation").ole_types + ots1 = WIN32OLE::Type.ole_classes("Microsoft Shell Controls And Automation") + ots2 = WIN32OLE::TypeLib.new("Microsoft Shell Controls And Automation").ole_types otns1 = ots1.collect{|t| t.name}.sort otns2 = ots2.collect{|t| t.name}.sort assert_equal(otns2, otns1) diff --git a/test/win32ole/test_win32ole_type_event.rb b/test/win32ole/test_win32ole_type_event.rb index ec46245cae9589..5d1c9fc44c9818 100644 --- a/test/win32ole/test_win32ole_type_event.rb +++ b/test/win32ole/test_win32ole_type_event.rb @@ -6,7 +6,7 @@ require 'test/unit' -if defined?(WIN32OLE_TYPE) +if defined?(WIN32OLE::Type) require_relative 'available_ole' class TestWIN32OLE_TYPE_EVENT < Test::Unit::TestCase @@ -17,7 +17,7 @@ def test_dummy_for_skip_message else def setup - @ole_type = WIN32OLE_TYPE.new('System Monitor Control', 'SystemMonitor') + @ole_type = WIN32OLE::Type.new('System Monitor Control', 'SystemMonitor') end def test_implemented_ole_types diff --git a/test/win32ole/test_win32ole_typelib.rb b/test/win32ole/test_win32ole_typelib.rb index a865d5b4b1222c..f743ad68f90e31 100644 --- a/test/win32ole/test_win32ole_typelib.rb +++ b/test/win32ole/test_win32ole_typelib.rb @@ -5,10 +5,10 @@ end require "test/unit" -if defined?(WIN32OLE_TYPELIB) +if defined?(WIN32OLE::TypeLib) class TestWIN32OLE_TYPELIB < Test::Unit::TestCase def test_s_typelibs - tlibs = WIN32OLE_TYPELIB.typelibs + tlibs = WIN32OLE::TypeLib.typelibs assert_instance_of(Array, tlibs) assert(tlibs.size > 0) tlib = tlibs.find {|t| t.name == "Microsoft Shell Controls And Automation"} @@ -17,99 +17,99 @@ def test_s_typelibs def test_initialize assert_raise(ArgumentError) { - WIN32OLE_TYPELIB.new(1,2,3,4) + WIN32OLE::TypeLib.new(1,2,3,4) } assert_raise(TypeError) { - WIN32OLE_TYPELIB.new(100) + WIN32OLE::TypeLib.new(100) } - tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation") - assert_instance_of(WIN32OLE_TYPELIB, tlib) + tlib = WIN32OLE::TypeLib.new("Microsoft Shell Controls And Automation") + assert_instance_of(WIN32OLE::TypeLib, tlib) - tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation", 1.0) - assert_instance_of(WIN32OLE_TYPELIB, tlib) + tlib = WIN32OLE::TypeLib.new("Microsoft Shell Controls And Automation", 1.0) + assert_instance_of(WIN32OLE::TypeLib, tlib) - tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation", 1, 0) - assert_instance_of(WIN32OLE_TYPELIB, tlib) + tlib = WIN32OLE::TypeLib.new("Microsoft Shell Controls And Automation", 1, 0) + assert_instance_of(WIN32OLE::TypeLib, tlib) guid = tlib.guid - tlib_by_guid = WIN32OLE_TYPELIB.new(guid, 1, 0) - assert_instance_of(WIN32OLE_TYPELIB, tlib_by_guid) + tlib_by_guid = WIN32OLE::TypeLib.new(guid, 1, 0) + assert_instance_of(WIN32OLE::TypeLib, tlib_by_guid) assert_equal("Microsoft Shell Controls And Automation" , tlib_by_guid.name) path = tlib.path - tlib_by_path = WIN32OLE_TYPELIB.new(path) + tlib_by_path = WIN32OLE::TypeLib.new(path) assert_equal("Microsoft Shell Controls And Automation" , tlib_by_path.name) - assert_raise(WIN32OLERuntimeError) { - WIN32OLE_TYPELIB.new("Non Exist Type Library") + assert_raise(WIN32OLE::RuntimeError) { + WIN32OLE::TypeLib.new("Non Exist Type Library") } end # #Bug:3907 [ruby-dev:42338] def test_initialize_with_REG_EXPAND_SZ - tlib = WIN32OLE_TYPELIB.new("Disk Management Snap-In Object Library") - assert_instance_of(WIN32OLE_TYPELIB, tlib) + tlib = WIN32OLE::TypeLib.new("Disk Management Snap-In Object Library") + assert_instance_of(WIN32OLE::TypeLib, tlib) end def test_guid - tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation") + tlib = WIN32OLE::TypeLib.new("Microsoft Shell Controls And Automation") assert_equal("{50A7E9B0-70EF-11D1-B75A-00A0C90564FE}", tlib.guid) end def test_name - tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation") + tlib = WIN32OLE::TypeLib.new("Microsoft Shell Controls And Automation") assert_equal("Microsoft Shell Controls And Automation", tlib.name) - tlib = WIN32OLE_TYPELIB.new("{50A7E9B0-70EF-11D1-B75A-00A0C90564FE}") + tlib = WIN32OLE::TypeLib.new("{50A7E9B0-70EF-11D1-B75A-00A0C90564FE}") assert_equal("Microsoft Shell Controls And Automation", tlib.name) end def test_version - tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation") + tlib = WIN32OLE::TypeLib.new("Microsoft Shell Controls And Automation") assert_equal("1.0", tlib.version) end def test_major_version - tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation") + tlib = WIN32OLE::TypeLib.new("Microsoft Shell Controls And Automation") assert_equal(1, tlib.major_version) end def test_minor_version - tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation") + tlib = WIN32OLE::TypeLib.new("Microsoft Shell Controls And Automation") assert_equal(0, tlib.minor_version) end def test_path - tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation") + tlib = WIN32OLE::TypeLib.new("Microsoft Shell Controls And Automation") assert_match(/shell32\.dll$/i, tlib.path) end def test_visible? - tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation") + tlib = WIN32OLE::TypeLib.new("Microsoft Shell Controls And Automation") assert(tlib.visible?) end def test_library_name - tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation") + tlib = WIN32OLE::TypeLib.new("Microsoft Shell Controls And Automation") assert_equal("Shell32", tlib.library_name) end def test_to_s - tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation") + tlib = WIN32OLE::TypeLib.new("Microsoft Shell Controls And Automation") assert_equal("Microsoft Shell Controls And Automation", tlib.to_s) end def test_ole_types - tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation") + tlib = WIN32OLE::TypeLib.new("Microsoft Shell Controls And Automation") ole_types = tlib.ole_types assert_instance_of(Array, ole_types) assert(ole_types.size > 0) - assert_instance_of(WIN32OLE_TYPE, ole_types[0]) + assert_instance_of(WIN32OLE::Type, ole_types[0]) end def test_inspect - tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation") + tlib = WIN32OLE::TypeLib.new("Microsoft Shell Controls And Automation") assert_equal("#", tlib.inspect) end diff --git a/test/win32ole/test_win32ole_variable.rb b/test/win32ole/test_win32ole_variable.rb index cc4e91123bf3d2..74a6cbd890ad95 100644 --- a/test/win32ole/test_win32ole_variable.rb +++ b/test/win32ole/test_win32ole_variable.rb @@ -5,19 +5,19 @@ end require "test/unit" -if defined?(WIN32OLE_VARIABLE) +if defined?(WIN32OLE::Variable) class TestWIN32OLE_VARIABLE < Test::Unit::TestCase def setup - ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants") + ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants") @var1 = ole_type.variables.find {|v| v.name == 'ssfDESKTOP'} - variables = WIN32OLE_TYPE.new("Microsoft Windows Installer Object Library", "Installer").variables + variables = WIN32OLE::Type.new("Microsoft Windows Installer Object Library", "Installer").variables @var2 = variables.find {|v| v.name == 'UILevel'} end def test_initialize - assert_raise(TypeError) {WIN32OLE_VARIABLE.new} + assert_raise(TypeError) {WIN32OLE::Variable.new} end def test_name diff --git a/test/win32ole/test_win32ole_variant.rb b/test/win32ole/test_win32ole_variant.rb index 1cedf55ef3b5b1..1837a1e1d630f2 100644 --- a/test/win32ole/test_win32ole_variant.rb +++ b/test/win32ole/test_win32ole_variant.rb @@ -5,7 +5,7 @@ end require "test/unit" -if defined?(WIN32OLE_VARIANT) +if defined?(WIN32OLE::Variant) class TestWIN32OLE_VARIANT < Test::Unit::TestCase def setup @@ -18,35 +18,35 @@ def teardown end def test_s_new - obj = WIN32OLE_VARIANT.new('foo') - assert_instance_of(WIN32OLE_VARIANT, obj) + obj = WIN32OLE::Variant.new('foo') + assert_instance_of(WIN32OLE::Variant, obj) end def test_s_new_exc assert_raise(TypeError) { - WIN32OLE_VARIANT.new(/foo/) + WIN32OLE::Variant.new(/foo/) } end def test_s_new_ary - obj = WIN32OLE_VARIANT.new([1]) - assert_instance_of(WIN32OLE_VARIANT, obj) + obj = WIN32OLE::Variant.new([1]) + assert_instance_of(WIN32OLE::Variant, obj) assert_raise(TypeError) { - WIN32OLE_VARIANT.new([/foo/]) + WIN32OLE::Variant.new([/foo/]) } end def test_s_new_no_argument pat = /wrong number of arguments \(.*\b0\b.* 1\.\.3\)/ assert_raise_with_message(ArgumentError, pat) do - WIN32OLE_VARIANT.new + WIN32OLE::Variant.new end end def test_s_new_one_argument ex = nil begin - WIN32OLE_VARIANT.new('foo') + WIN32OLE::Variant.new('foo') rescue ex = $! end @@ -54,247 +54,247 @@ def test_s_new_one_argument end def test_s_new_with_nil - obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_I2) + obj = WIN32OLE::Variant.new(nil, WIN32OLE::VARIANT::VT_I2) assert_equal(0, obj.value) assert_equal(WIN32OLE::VARIANT::VT_I2, obj.vartype) - obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_I4) + obj = WIN32OLE::Variant.new(nil, WIN32OLE::VARIANT::VT_I4) assert_equal(0, obj.value) assert_equal(WIN32OLE::VARIANT::VT_I4, obj.vartype) - obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_R4) + obj = WIN32OLE::Variant.new(nil, WIN32OLE::VARIANT::VT_R4) assert_equal(0, obj.value) assert_equal(WIN32OLE::VARIANT::VT_R4, obj.vartype) - obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_R8) + obj = WIN32OLE::Variant.new(nil, WIN32OLE::VARIANT::VT_R8) assert_equal(0, obj.value) assert_equal(WIN32OLE::VARIANT::VT_R8, obj.vartype) - obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_CY) + obj = WIN32OLE::Variant.new(nil, WIN32OLE::VARIANT::VT_CY) assert_equal("0", obj.value) assert_equal(WIN32OLE::VARIANT::VT_CY, obj.vartype) - obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_DATE) + obj = WIN32OLE::Variant.new(nil, WIN32OLE::VARIANT::VT_DATE) assert_equal(Time.new(1899,12,30), obj.value) assert_equal(WIN32OLE::VARIANT::VT_DATE, obj.vartype) - obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_BSTR) + obj = WIN32OLE::Variant.new(nil, WIN32OLE::VARIANT::VT_BSTR) assert_equal("", obj.value) assert_equal(WIN32OLE::VARIANT::VT_BSTR, obj.vartype) - obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_DISPATCH) + obj = WIN32OLE::Variant.new(nil, WIN32OLE::VARIANT::VT_DISPATCH) assert_nil(obj.value) assert_equal(WIN32OLE::VARIANT::VT_DISPATCH, obj.vartype) - obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_BOOL) + obj = WIN32OLE::Variant.new(nil, WIN32OLE::VARIANT::VT_BOOL) assert_equal(false, obj.value) assert_equal(WIN32OLE::VARIANT::VT_BOOL, obj.vartype) - obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_VARIANT) + obj = WIN32OLE::Variant.new(nil, WIN32OLE::VARIANT::VT_VARIANT) assert_nil(obj.value) assert_equal(WIN32OLE::VARIANT::VT_VARIANT, obj.vartype) - obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_I1) + obj = WIN32OLE::Variant.new(nil, WIN32OLE::VARIANT::VT_I1) assert_equal(0, obj.value) assert_equal(WIN32OLE::VARIANT::VT_I1, obj.vartype) - obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_UI1) + obj = WIN32OLE::Variant.new(nil, WIN32OLE::VARIANT::VT_UI1) assert_equal(0, obj.value) assert_equal(WIN32OLE::VARIANT::VT_UI1, obj.vartype) - obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_UI2) + obj = WIN32OLE::Variant.new(nil, WIN32OLE::VARIANT::VT_UI2) assert_equal(0, obj.value) assert_equal(WIN32OLE::VARIANT::VT_UI2, obj.vartype) - obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_UI4) + obj = WIN32OLE::Variant.new(nil, WIN32OLE::VARIANT::VT_UI4) assert_equal(0, obj.value) assert_equal(WIN32OLE::VARIANT::VT_UI4, obj.vartype) if defined?(WIN32OLE::VARIANT::VT_I8) - obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_I8) + obj = WIN32OLE::Variant.new(nil, WIN32OLE::VARIANT::VT_I8) assert_equal(0, obj.value) assert_equal(WIN32OLE::VARIANT::VT_I8, obj.vartype) end if defined?(WIN32OLE::VARIANT::VT_UI8) - obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_UI8) + obj = WIN32OLE::Variant.new(nil, WIN32OLE::VARIANT::VT_UI8) assert_equal(0, obj.value) assert_equal(WIN32OLE::VARIANT::VT_UI8, obj.vartype) end - obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_INT) + obj = WIN32OLE::Variant.new(nil, WIN32OLE::VARIANT::VT_INT) assert_equal(0, obj.value) assert_equal(WIN32OLE::VARIANT::VT_INT, obj.vartype) - obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_UINT) + obj = WIN32OLE::Variant.new(nil, WIN32OLE::VARIANT::VT_UINT) assert_equal(0, obj.value) assert_equal(WIN32OLE::VARIANT::VT_UINT, obj.vartype) end def test_s_new_with_non_nil - obj = WIN32OLE_VARIANT.new(2, WIN32OLE::VARIANT::VT_I2) + obj = WIN32OLE::Variant.new(2, WIN32OLE::VARIANT::VT_I2) assert_equal(2, obj.value) assert_equal(WIN32OLE::VARIANT::VT_I2, obj.vartype) - obj = WIN32OLE_VARIANT.new(3, WIN32OLE::VARIANT::VT_I4) + obj = WIN32OLE::Variant.new(3, WIN32OLE::VARIANT::VT_I4) assert_equal(3, obj.value) assert_equal(WIN32OLE::VARIANT::VT_I4, obj.vartype) - obj = WIN32OLE_VARIANT.new(4.5, WIN32OLE::VARIANT::VT_R4) + obj = WIN32OLE::Variant.new(4.5, WIN32OLE::VARIANT::VT_R4) assert_equal(4.5, obj.value) assert_equal(WIN32OLE::VARIANT::VT_R4, obj.vartype) - obj = WIN32OLE_VARIANT.new(5.5, WIN32OLE::VARIANT::VT_R8) + obj = WIN32OLE::Variant.new(5.5, WIN32OLE::VARIANT::VT_R8) assert_equal(5.5, obj.value) assert_equal(WIN32OLE::VARIANT::VT_R8, obj.vartype) - obj = WIN32OLE_VARIANT.new(600, WIN32OLE::VARIANT::VT_CY) + obj = WIN32OLE::Variant.new(600, WIN32OLE::VARIANT::VT_CY) assert_equal("600", obj.value) assert_equal(WIN32OLE::VARIANT::VT_CY, obj.vartype) - obj = WIN32OLE_VARIANT.new("2001-06-15 12:17:34", WIN32OLE::VARIANT::VT_DATE) + obj = WIN32OLE::Variant.new("2001-06-15 12:17:34", WIN32OLE::VARIANT::VT_DATE) assert_equal(Time.new(2001,06,15,12,17,34), obj.value) assert_equal(WIN32OLE::VARIANT::VT_DATE, obj.vartype) - obj = WIN32OLE_VARIANT.new("foo", WIN32OLE::VARIANT::VT_BSTR) + obj = WIN32OLE::Variant.new("foo", WIN32OLE::VARIANT::VT_BSTR) assert_equal("foo", obj.value) assert_equal(WIN32OLE::VARIANT::VT_BSTR, obj.vartype) - obj = WIN32OLE_VARIANT.new(true, WIN32OLE::VARIANT::VT_BOOL) + obj = WIN32OLE::Variant.new(true, WIN32OLE::VARIANT::VT_BOOL) assert_equal(true, obj.value) assert_equal(WIN32OLE::VARIANT::VT_BOOL, obj.vartype) - obj = WIN32OLE_VARIANT.new(2, WIN32OLE::VARIANT::VT_I1) + obj = WIN32OLE::Variant.new(2, WIN32OLE::VARIANT::VT_I1) assert_equal(2, obj.value) assert_equal(WIN32OLE::VARIANT::VT_I1, obj.vartype) - obj = WIN32OLE_VARIANT.new(3, WIN32OLE::VARIANT::VT_UI1) + obj = WIN32OLE::Variant.new(3, WIN32OLE::VARIANT::VT_UI1) assert_equal(3, obj.value) assert_equal(WIN32OLE::VARIANT::VT_UI1, obj.vartype) - obj = WIN32OLE_VARIANT.new(4, WIN32OLE::VARIANT::VT_UI2) + obj = WIN32OLE::Variant.new(4, WIN32OLE::VARIANT::VT_UI2) assert_equal(4, obj.value) assert_equal(WIN32OLE::VARIANT::VT_UI2, obj.vartype) - obj = WIN32OLE_VARIANT.new(5, WIN32OLE::VARIANT::VT_UI4) + obj = WIN32OLE::Variant.new(5, WIN32OLE::VARIANT::VT_UI4) assert_equal(5, obj.value) assert_equal(WIN32OLE::VARIANT::VT_UI4, obj.vartype) if defined?(WIN32OLE::VARIANT::VT_I8) - obj = WIN32OLE_VARIANT.new(-123456789012345, WIN32OLE::VARIANT::VT_I8) + obj = WIN32OLE::Variant.new(-123456789012345, WIN32OLE::VARIANT::VT_I8) assert_equal(-123456789012345, obj.value) assert_equal(WIN32OLE::VARIANT::VT_I8, obj.vartype) end if defined?(WIN32OLE::VARIANT::VT_UI8) - obj = WIN32OLE_VARIANT.new(123456789012345, WIN32OLE::VARIANT::VT_UI8) + obj = WIN32OLE::Variant.new(123456789012345, WIN32OLE::VARIANT::VT_UI8) assert_equal(123456789012345, obj.value) assert_equal(WIN32OLE::VARIANT::VT_UI8, obj.vartype) end - obj = WIN32OLE_VARIANT.new(4, WIN32OLE::VARIANT::VT_INT) + obj = WIN32OLE::Variant.new(4, WIN32OLE::VARIANT::VT_INT) assert_equal(4, obj.value) assert_equal(WIN32OLE::VARIANT::VT_INT, obj.vartype) - obj = WIN32OLE_VARIANT.new(5, WIN32OLE::VARIANT::VT_UINT) + obj = WIN32OLE::Variant.new(5, WIN32OLE::VARIANT::VT_UINT) assert_equal(5, obj.value) assert_equal(WIN32OLE::VARIANT::VT_UINT, obj.vartype) end def test_s_new_with_non_nil_byref - obj = WIN32OLE_VARIANT.new(2, WIN32OLE::VARIANT::VT_I2|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new(2, WIN32OLE::VARIANT::VT_I2|WIN32OLE::VARIANT::VT_BYREF) assert_equal(2, obj.value) assert_equal(WIN32OLE::VARIANT::VT_I2|WIN32OLE::VARIANT::VT_BYREF, obj.vartype) - obj = WIN32OLE_VARIANT.new(3, WIN32OLE::VARIANT::VT_I4|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new(3, WIN32OLE::VARIANT::VT_I4|WIN32OLE::VARIANT::VT_BYREF) assert_equal(3, obj.value) assert_equal(WIN32OLE::VARIANT::VT_I4|WIN32OLE::VARIANT::VT_BYREF, obj.vartype) - obj = WIN32OLE_VARIANT.new(4.5, WIN32OLE::VARIANT::VT_R4|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new(4.5, WIN32OLE::VARIANT::VT_R4|WIN32OLE::VARIANT::VT_BYREF) assert_equal(4.5, obj.value) assert_equal(WIN32OLE::VARIANT::VT_R4|WIN32OLE::VARIANT::VT_BYREF, obj.vartype) - obj = WIN32OLE_VARIANT.new(5.5, WIN32OLE::VARIANT::VT_R8|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new(5.5, WIN32OLE::VARIANT::VT_R8|WIN32OLE::VARIANT::VT_BYREF) assert_equal(5.5, obj.value) assert_equal(WIN32OLE::VARIANT::VT_R8|WIN32OLE::VARIANT::VT_BYREF, obj.vartype) - obj = WIN32OLE_VARIANT.new(600, WIN32OLE::VARIANT::VT_CY|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new(600, WIN32OLE::VARIANT::VT_CY|WIN32OLE::VARIANT::VT_BYREF) assert_equal("600", obj.value) assert_equal(WIN32OLE::VARIANT::VT_CY|WIN32OLE::VARIANT::VT_BYREF, obj.vartype) - obj = WIN32OLE_VARIANT.new("2001-06-15 12:17:34", WIN32OLE::VARIANT::VT_DATE|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new("2001-06-15 12:17:34", WIN32OLE::VARIANT::VT_DATE|WIN32OLE::VARIANT::VT_BYREF) assert_equal(Time.new(2001,06,15,12,17,34), obj.value) assert_equal(WIN32OLE::VARIANT::VT_DATE|WIN32OLE::VARIANT::VT_BYREF, obj.vartype) - obj = WIN32OLE_VARIANT.new("foo", WIN32OLE::VARIANT::VT_BSTR|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new("foo", WIN32OLE::VARIANT::VT_BSTR|WIN32OLE::VARIANT::VT_BYREF) assert_equal("foo", obj.value) assert_equal(WIN32OLE::VARIANT::VT_BSTR|WIN32OLE::VARIANT::VT_BYREF, obj.vartype) - obj = WIN32OLE_VARIANT.new(true, WIN32OLE::VARIANT::VT_BOOL|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new(true, WIN32OLE::VARIANT::VT_BOOL|WIN32OLE::VARIANT::VT_BYREF) assert_equal(true, obj.value) assert_equal(WIN32OLE::VARIANT::VT_BOOL|WIN32OLE::VARIANT::VT_BYREF, obj.vartype) - obj = WIN32OLE_VARIANT.new(2, WIN32OLE::VARIANT::VT_I1|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new(2, WIN32OLE::VARIANT::VT_I1|WIN32OLE::VARIANT::VT_BYREF) assert_equal(2, obj.value) assert_equal(WIN32OLE::VARIANT::VT_I1|WIN32OLE::VARIANT::VT_BYREF, obj.vartype) - obj = WIN32OLE_VARIANT.new(3, WIN32OLE::VARIANT::VT_UI1|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new(3, WIN32OLE::VARIANT::VT_UI1|WIN32OLE::VARIANT::VT_BYREF) assert_equal(3, obj.value) assert_equal(WIN32OLE::VARIANT::VT_UI1|WIN32OLE::VARIANT::VT_BYREF, obj.vartype) - obj = WIN32OLE_VARIANT.new(4, WIN32OLE::VARIANT::VT_UI2|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new(4, WIN32OLE::VARIANT::VT_UI2|WIN32OLE::VARIANT::VT_BYREF) assert_equal(4, obj.value) assert_equal(WIN32OLE::VARIANT::VT_UI2|WIN32OLE::VARIANT::VT_BYREF, obj.vartype) - obj = WIN32OLE_VARIANT.new(5, WIN32OLE::VARIANT::VT_UI4|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new(5, WIN32OLE::VARIANT::VT_UI4|WIN32OLE::VARIANT::VT_BYREF) assert_equal(5, obj.value) assert_equal(WIN32OLE::VARIANT::VT_UI4|WIN32OLE::VARIANT::VT_BYREF, obj.vartype) - obj = WIN32OLE_VARIANT.new(4, WIN32OLE::VARIANT::VT_INT|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new(4, WIN32OLE::VARIANT::VT_INT|WIN32OLE::VARIANT::VT_BYREF) assert_equal(4, obj.value) assert_equal(WIN32OLE::VARIANT::VT_INT|WIN32OLE::VARIANT::VT_BYREF, obj.vartype) - obj = WIN32OLE_VARIANT.new(5, WIN32OLE::VARIANT::VT_UINT|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new(5, WIN32OLE::VARIANT::VT_UINT|WIN32OLE::VARIANT::VT_BYREF) assert_equal(5, obj.value) assert_equal(WIN32OLE::VARIANT::VT_UINT|WIN32OLE::VARIANT::VT_BYREF, obj.vartype) end def test_s_new_with_i8_byref - obj = WIN32OLE_VARIANT.new(-123456789012345, WIN32OLE::VARIANT::VT_I8|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new(-123456789012345, WIN32OLE::VARIANT::VT_I8|WIN32OLE::VARIANT::VT_BYREF) assert_equal(-123456789012345, obj.value) assert_equal(WIN32OLE::VARIANT::VT_I8|WIN32OLE::VARIANT::VT_BYREF, obj.vartype) end def test_s_new_with_ui8_byref - obj = WIN32OLE_VARIANT.new(123456789012345, WIN32OLE::VARIANT::VT_UI8|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new(123456789012345, WIN32OLE::VARIANT::VT_UI8|WIN32OLE::VARIANT::VT_BYREF) assert_equal(123456789012345, obj.value) assert_equal(WIN32OLE::VARIANT::VT_UI8|WIN32OLE::VARIANT::VT_BYREF, obj.vartype) end def test_value - obj = WIN32OLE_VARIANT.new('foo') + obj = WIN32OLE::Variant.new('foo') assert_equal('foo', obj.value) end def test_s_new_2_argument - obj = WIN32OLE_VARIANT.new('foo', WIN32OLE::VARIANT::VT_BSTR|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new('foo', WIN32OLE::VARIANT::VT_BSTR|WIN32OLE::VARIANT::VT_BYREF) assert_equal('foo', obj.value); end def test_s_new_2_argument2 - obj = WIN32OLE_VARIANT.new('foo', WIN32OLE::VARIANT::VT_BSTR) + obj = WIN32OLE::Variant.new('foo', WIN32OLE::VARIANT::VT_BSTR) assert_equal('foo', obj.value); end def test_s_new_dispatch_array vt = WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_DISPATCH - obj = WIN32OLE_VARIANT.new(nil, vt) + obj = WIN32OLE::Variant.new(nil, vt) assert_equal(vt, obj.vartype) assert_nil(obj.value) vt = WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_DISPATCH|WIN32OLE::VARIANT::VT_BYREF - obj = WIN32OLE_VARIANT.new(nil, vt) + obj = WIN32OLE::Variant.new(nil, vt) assert_equal(vt, obj.vartype) assert_nil(obj.value) end @@ -302,29 +302,29 @@ def test_s_new_dispatch_array def test_s_new_array # should not occur stack over flow ar = (1..500000).to_a.map{|i| [i]} - ar2 = WIN32OLE_VARIANT.new(ar) + ar2 = WIN32OLE::Variant.new(ar) assert_equal(ar, ar2.value) end def test_s_new_vt_record_exc - # VT_RECORD (= 36) should not be allowed in WIN32OLE_VARIANT#new + # VT_RECORD (= 36) should not be allowed in WIN32OLE::Variant#new assert_raise(ArgumentError) { - WIN32OLE_VARIANT.new(nil, 36) + WIN32OLE::Variant.new(nil, 36) } end def test_s_array - obj = WIN32OLE_VARIANT.array([2,3], WIN32OLE::VARIANT::VT_I4) - assert_instance_of(WIN32OLE_VARIANT, obj) + obj = WIN32OLE::Variant.array([2,3], WIN32OLE::VARIANT::VT_I4) + assert_instance_of(WIN32OLE::Variant, obj) assert_equal(WIN32OLE::VARIANT::VT_I4|WIN32OLE::VARIANT::VT_ARRAY, obj.vartype) assert_equal([[0, 0, 0],[0, 0, 0]], obj.value) - obj = WIN32OLE_VARIANT.array([2,3], WIN32OLE::VARIANT::VT_I4|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.array([2,3], WIN32OLE::VARIANT::VT_I4|WIN32OLE::VARIANT::VT_BYREF) assert_equal(WIN32OLE::VARIANT::VT_I4|WIN32OLE::VARIANT::VT_BYREF|WIN32OLE::VARIANT::VT_ARRAY, obj.vartype) assert_equal([[0, 0, 0],[0, 0, 0]], obj.value) - obj = WIN32OLE_VARIANT.array([2,3], WIN32OLE::VARIANT::VT_I4|WIN32OLE::VARIANT::VT_ARRAY) - assert_instance_of(WIN32OLE_VARIANT, obj) + obj = WIN32OLE::Variant.array([2,3], WIN32OLE::VARIANT::VT_I4|WIN32OLE::VARIANT::VT_ARRAY) + assert_instance_of(WIN32OLE::Variant, obj) assert_equal(WIN32OLE::VARIANT::VT_I4|WIN32OLE::VARIANT::VT_ARRAY, obj.vartype) assert_equal([[0, 0, 0],[0, 0, 0]], obj.value) @@ -334,60 +334,60 @@ def test_s_array obj[0,1] = "13.2" assert_equal([[10, 13, 0],[0, 0, 0]], obj.value) - obj = WIN32OLE_VARIANT.array([3, 2], WIN32OLE::VARIANT::VT_VARIANT) + obj = WIN32OLE::Variant.array([3, 2], WIN32OLE::VARIANT::VT_VARIANT) obj[0,0] = 10 obj[0,1] = "string" obj[1,0] = 12.735 assert_equal([[10, "string"],[12.735, nil],[nil,nil]], obj.value) - obj = WIN32OLE_VARIANT.array([2,3], WIN32OLE::VARIANT::VT_DISPATCH) + obj = WIN32OLE::Variant.array([2,3], WIN32OLE::VARIANT::VT_DISPATCH) assert_equal([[nil, nil, nil],[nil,nil,nil]], obj.value) end def test_s_array_exc assert_raise(TypeError) { - WIN32OLE_VARIANT.array(2, WIN32OLE::VARIANT::VT_I4) + WIN32OLE::Variant.array(2, WIN32OLE::VARIANT::VT_I4) } end def test_conversion_num2str - obj = WIN32OLE_VARIANT.new(124, WIN32OLE::VARIANT::VT_BSTR) + obj = WIN32OLE::Variant.new(124, WIN32OLE::VARIANT::VT_BSTR) assert_equal("124", obj.value); end def test_conversion_float2int - obj = WIN32OLE_VARIANT.new(12.345, WIN32OLE::VARIANT::VT_I4) + obj = WIN32OLE::Variant.new(12.345, WIN32OLE::VARIANT::VT_I4) assert_equal(12, obj.value) - obj = WIN32OLE_VARIANT.new(12.345, WIN32OLE::VARIANT::VT_I4|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new(12.345, WIN32OLE::VARIANT::VT_I4|WIN32OLE::VARIANT::VT_BYREF) assert_equal(12, obj.value) end def test_conversion_str2num - obj = WIN32OLE_VARIANT.new("12.345", WIN32OLE::VARIANT::VT_R8) + obj = WIN32OLE::Variant.new("12.345", WIN32OLE::VARIANT::VT_R8) assert_equal(12.345, obj.value) end def test_conversion_ole_variant2ole_variant - obj = WIN32OLE_VARIANT.new("12.345", WIN32OLE::VARIANT::VT_R4) - obj = WIN32OLE_VARIANT.new(obj, WIN32OLE::VARIANT::VT_I4) + obj = WIN32OLE::Variant.new("12.345", WIN32OLE::VARIANT::VT_R4) + obj = WIN32OLE::Variant.new(obj, WIN32OLE::VARIANT::VT_I4) assert_equal(12, obj.value) end def test_conversion_str2date - obj = WIN32OLE_VARIANT.new("2004-12-24 12:24:45", WIN32OLE::VARIANT::VT_DATE) + obj = WIN32OLE::Variant.new("2004-12-24 12:24:45", WIN32OLE::VARIANT::VT_DATE) assert_equal(Time.new(2004,12,24,12,24,45), obj.value) end def test_conversion_time2date dt = Time.mktime(2004, 12, 24, 12, 24, 45) - obj = WIN32OLE_VARIANT.new(dt, WIN32OLE::VARIANT::VT_DATE) + obj = WIN32OLE::Variant.new(dt, WIN32OLE::VARIANT::VT_DATE) assert_equal(dt, obj.value) end def test_conversion_dbl2date_with_msec # Date is "2014/8/27 12:34:56.789" - obj = WIN32OLE_VARIANT.new(41878.524268391200167, WIN32OLE::VARIANT::VT_DATE) + obj = WIN32OLE::Variant.new(41878.524268391200167, WIN32OLE::VARIANT::VT_DATE) t = obj.value assert_equal("2014-08-27 12:34:56", t.strftime('%Y-%m-%d %H:%M:%S')) assert_in_delta(0.789, t.nsec / 1000000000.0, 0.001) @@ -396,7 +396,7 @@ def test_conversion_dbl2date_with_msec def test_conversion_time2date_with_msec t0 = Time.new(2014, 8, 27, 12, 34, 56) t0 += 0.789 - t1 = WIN32OLE_VARIANT.new(t0).value + t1 = WIN32OLE::Variant.new(t0).value # The t0.nsec is 789000000 and t1.nsec is 789000465 # because of error range by conversion Time between VT_DATE Variant. @@ -406,7 +406,7 @@ def test_conversion_time2date_with_msec t0 = Time.new(2014, 8, 27, 12, 34, 56) t0 += 0.999999999 - t1 = WIN32OLE_VARIANT.new(t0).value + t1 = WIN32OLE::Variant.new(t0).value msg = "Expected:#{t0.strftime('%Y-%m-%dT%H:%M:%S.%N')} but was:#{t1.strftime('%Y-%m-%dT%H:%M:%S.%N')}" # The t0 is "2014/08/27 12:34.56.999999999" and @@ -414,7 +414,7 @@ def test_conversion_time2date_with_msec assert_in_delta(t0, t1, 0.001, msg) t0 = Time.now - t1 = WIN32OLE_VARIANT.new(t0).value + t1 = WIN32OLE::Variant.new(t0).value msg = "Expected:#{t0.strftime('%Y-%m-%dT%H:%M:%S.%N')} but was:#{t1.strftime('%Y-%m-%dT%H:%M:%S.%N')}" assert_in_delta(t0, t1, 0.001, msg) end @@ -426,110 +426,110 @@ def test_conversion_time2date_with_msec # def test_conversion_time_nsec2date # dt = Time.new(2004, 12,24, 12, 24, 45) # dt += 0.1 - # obj = WIN32OLE_VARIANT.new(dt, WIN32OLE::VARIANT::VT_DATE) + # obj = WIN32OLE::Variant.new(dt, WIN32OLE::VARIANT::VT_DATE) # assert_equal(dt, obj.value) # end def test_conversion_str2cy begin WIN32OLE.locale = 0x0411 # set locale Japanese - rescue WIN32OLERuntimeError + rescue WIN32OLE::RuntimeError omit("Japanese locale is not installed") end if WIN32OLE.locale == 0x0411 - obj = WIN32OLE_VARIANT.new("\\10,000", WIN32OLE::VARIANT::VT_CY) + obj = WIN32OLE::Variant.new("\\10,000", WIN32OLE::VARIANT::VT_CY) assert_equal("10000", obj.value) end end def test_create_vt_array - obj = WIN32OLE_VARIANT.new([1.2, 2.3], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_R8) + obj = WIN32OLE::Variant.new([1.2, 2.3], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_R8) assert_equal([1.2, 2.3], obj.value) assert_equal(WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_R8, obj.vartype) - obj = WIN32OLE_VARIANT.new([1.2, 2.3], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_R8|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new([1.2, 2.3], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_R8|WIN32OLE::VARIANT::VT_BYREF) assert_equal([1.2, 2.3], obj.value) assert_equal(WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_R8|WIN32OLE::VARIANT::VT_BYREF, obj.vartype) end def test_create_vt_array2 - obj = WIN32OLE_VARIANT.new([1.2, "a"], WIN32OLE::VARIANT::VT_ARRAY) + obj = WIN32OLE::Variant.new([1.2, "a"], WIN32OLE::VARIANT::VT_ARRAY) assert_equal([1.2, "a"], obj.value) assert_equal(WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_VARIANT, obj.vartype) - obj = WIN32OLE_VARIANT.new([1.2, "a"]) + obj = WIN32OLE::Variant.new([1.2, "a"]) assert_equal([1.2, "a"], obj.value) assert_equal(WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_VARIANT, obj.vartype) end def test_create_vt_nested_array - obj = WIN32OLE_VARIANT.new([[1.2, "a", "b"], [3.4, "C", "D"]], WIN32OLE::VARIANT::VT_ARRAY) + obj = WIN32OLE::Variant.new([[1.2, "a", "b"], [3.4, "C", "D"]], WIN32OLE::VARIANT::VT_ARRAY) assert_equal([[1.2, "a", "b"], [3.4, "C", "D"]], obj.value) - obj = WIN32OLE_VARIANT.new([[1.2, "a", "b"], [3.4, "C", "D"]]) + obj = WIN32OLE::Variant.new([[1.2, "a", "b"], [3.4, "C", "D"]]) assert_equal([[1.2, "a", "b"], [3.4, "C", "D"]], obj.value) - obj = WIN32OLE_VARIANT.new([[1.2, "a", "b"], [3.4, "C", "D"], [5.6, "E", "F"]]) + obj = WIN32OLE::Variant.new([[1.2, "a", "b"], [3.4, "C", "D"], [5.6, "E", "F"]]) assert_equal([[1.2, "a", "b"], [3.4, "C", "D"], [5.6, "E", "F"]], obj.value) - obj = WIN32OLE_VARIANT.new([[[1.2], [3.4]], [[5.6], [7.8]], [[9.1],[9.2]]]) + obj = WIN32OLE::Variant.new([[[1.2], [3.4]], [[5.6], [7.8]], [[9.1],[9.2]]]) assert_equal([[[1.2], [3.4]], [[5.6], [7.8]], [[9.1],[9.2]]], obj.value) end def test_create_vt_array3 - obj = WIN32OLE_VARIANT.new([]) + obj = WIN32OLE::Variant.new([]) assert_equal([], obj.value) - obj = WIN32OLE_VARIANT.new([[]]) + obj = WIN32OLE::Variant.new([[]]) assert_equal([[]], obj.value) - obj = WIN32OLE_VARIANT.new([[],[]]) + obj = WIN32OLE::Variant.new([[],[]]) assert_equal([[],[]], obj.value) - obj = WIN32OLE_VARIANT.new([], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new([], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_BYREF) assert_equal([], obj.value) - obj = WIN32OLE_VARIANT.new([[]], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new([[]], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_BYREF) assert_equal([[]], obj.value) - obj = WIN32OLE_VARIANT.new([[],[]], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new([[],[]], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_BYREF) assert_equal([[],[]], obj.value) end def test_create_vt_array_nil vartype = WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_DISPATCH|WIN32OLE::VARIANT::VT_BYREF - obj = WIN32OLE_VARIANT.new(nil, vartype) + obj = WIN32OLE::Variant.new(nil, vartype) assert_nil(obj.value) assert_equal(vartype, obj.vartype) vartype = WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_DISPATCH - obj = WIN32OLE_VARIANT.new(nil, vartype) + obj = WIN32OLE::Variant.new(nil, vartype) assert_nil(obj.value) assert_equal(vartype, obj.vartype) end def test_create_vt_array_str vartype = WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_BSTR - obj = WIN32OLE_VARIANT.new(["abc", "123"], vartype) + obj = WIN32OLE::Variant.new(["abc", "123"], vartype) assert_equal(vartype, obj.vartype) assert_equal(["abc", "123"], obj.value) vartype = WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_BYREF|WIN32OLE::VARIANT::VT_BSTR - obj = WIN32OLE_VARIANT.new(["abc", "123"], vartype) + obj = WIN32OLE::Variant.new(["abc", "123"], vartype) assert_equal(vartype, obj.vartype) assert_equal(["abc", "123"], obj.value) end def test_create_vt_array_exc exc = assert_raise(TypeError) { - WIN32OLE_VARIANT.new("", WIN32OLE::VARIANT::VT_ARRAY) + WIN32OLE::Variant.new("", WIN32OLE::VARIANT::VT_ARRAY) } assert_match(/wrong argument type String \(expected Array\)/, exc.message) end def test_create_vt_array_str2ui1array - obj = WIN32OLE_VARIANT.new("ABC", WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_UI1) + obj = WIN32OLE::Variant.new("ABC", WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_UI1) assert_equal("ABC", obj.value) obj.value = "DEF" @@ -537,10 +537,10 @@ def test_create_vt_array_str2ui1array obj[0] = 71 assert_equal("GEF", obj.value) - obj = WIN32OLE_VARIANT.new([65, 0].pack("C*"), WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_UI1) + obj = WIN32OLE::Variant.new([65, 0].pack("C*"), WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_UI1) assert_equal([65, 0].pack("C*"), obj.value) - obj = WIN32OLE_VARIANT.new("abc", WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_UI1|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new("abc", WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_UI1|WIN32OLE::VARIANT::VT_BYREF) assert_equal("abc", obj.value) obj.value = "DEF" assert_equal("DEF", obj.value) @@ -551,19 +551,19 @@ def test_create_vt_array_str2ui1array end def test_create_vt_array_int - obj = WIN32OLE_VARIANT.new([65, 0], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_UI1) + obj = WIN32OLE::Variant.new([65, 0], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_UI1) assert_equal([65, 0].pack("C*"), obj.value) - obj = WIN32OLE_VARIANT.new([65, 0]) + obj = WIN32OLE::Variant.new([65, 0]) assert_equal([65, 0], obj.value) - obj = WIN32OLE_VARIANT.new([65, 0], WIN32OLE::VARIANT::VT_I2|WIN32OLE::VARIANT::VT_ARRAY) + obj = WIN32OLE::Variant.new([65, 0], WIN32OLE::VARIANT::VT_I2|WIN32OLE::VARIANT::VT_ARRAY) assert_equal([65, 0], obj.value) end def test_vt_array_bracket - obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]]) + obj = WIN32OLE::Variant.new([[1,2,3],[4,5,6]]) assert_equal(1, obj[0,0]) assert_equal(2, obj[0,1]) assert_equal(3, obj[0,2]) @@ -571,10 +571,10 @@ def test_vt_array_bracket assert_equal(5, obj[1,1]) assert_equal(6, obj[1,2]) - assert_raise(WIN32OLERuntimeError) { + assert_raise(WIN32OLE::RuntimeError) { obj[0,4] } - assert_raise(WIN32OLERuntimeError) { + assert_raise(WIN32OLE::RuntimeError) { obj[0,-1] } assert_raise(ArgumentError) { @@ -585,10 +585,10 @@ def test_vt_array_bracket obj[1,2] = 8 assert_equal([[7,2,3], [4,5,8]], obj.value) - assert_raise(WIN32OLERuntimeError) { + assert_raise(WIN32OLE::RuntimeError) { obj[0,4] = 9 } - assert_raise(WIN32OLERuntimeError) { + assert_raise(WIN32OLE::RuntimeError) { obj[0,-1] = 10 } assert_raise(ArgumentError) { @@ -597,60 +597,60 @@ def test_vt_array_bracket end def test_conversion_vt_date - obj = WIN32OLE_VARIANT.new(-657434, WIN32OLE::VARIANT::VT_DATE) + obj = WIN32OLE::Variant.new(-657434, WIN32OLE::VARIANT::VT_DATE) assert_equal(Time.new(100,1,1), obj.value) - obj = WIN32OLE_VARIANT.new("1500/12/29 23:59:59", WIN32OLE::VARIANT::VT_DATE) + obj = WIN32OLE::Variant.new("1500/12/29 23:59:59", WIN32OLE::VARIANT::VT_DATE) assert_equal(Time.new(1500,12,29,23,59,59), obj.value) - obj = WIN32OLE_VARIANT.new("1500/12/30 00:00:00", WIN32OLE::VARIANT::VT_DATE) + obj = WIN32OLE::Variant.new("1500/12/30 00:00:00", WIN32OLE::VARIANT::VT_DATE) assert_equal(Time.new(1500,12,30), obj.value) - obj = WIN32OLE_VARIANT.new("1500/12/30 00:00:01", WIN32OLE::VARIANT::VT_DATE) + obj = WIN32OLE::Variant.new("1500/12/30 00:00:01", WIN32OLE::VARIANT::VT_DATE) assert_equal(Time.new(1500,12,30,0,0,1), obj.value) - obj = WIN32OLE_VARIANT.new("1899/12/29 23:59:59", WIN32OLE::VARIANT::VT_DATE) + obj = WIN32OLE::Variant.new("1899/12/29 23:59:59", WIN32OLE::VARIANT::VT_DATE) assert_equal(Time.new(1899,12,29,23,59,59), obj.value) - obj = WIN32OLE_VARIANT.new("1899/12/30 00:00:00", WIN32OLE::VARIANT::VT_DATE) + obj = WIN32OLE::Variant.new("1899/12/30 00:00:00", WIN32OLE::VARIANT::VT_DATE) assert_equal(Time.new(1899,12,30), obj.value) - obj = WIN32OLE_VARIANT.new("1899/12/30 00:00:01", WIN32OLE::VARIANT::VT_DATE) + obj = WIN32OLE::Variant.new("1899/12/30 00:00:01", WIN32OLE::VARIANT::VT_DATE) assert_equal(Time.new(1899,12,30,0,0,1), obj.value) - obj = WIN32OLE_VARIANT.new(0, WIN32OLE::VARIANT::VT_DATE) + obj = WIN32OLE::Variant.new(0, WIN32OLE::VARIANT::VT_DATE) assert_equal(Time.new(1899,12,30), obj.value) - obj = WIN32OLE_VARIANT.new("2008/12/29 23:59:59", WIN32OLE::VARIANT::VT_DATE) + obj = WIN32OLE::Variant.new("2008/12/29 23:59:59", WIN32OLE::VARIANT::VT_DATE) assert_equal(Time.new(2008,12,29,23,59,59), obj.value) - obj = WIN32OLE_VARIANT.new("2008/12/30 00:00:00", WIN32OLE::VARIANT::VT_DATE) + obj = WIN32OLE::Variant.new("2008/12/30 00:00:00", WIN32OLE::VARIANT::VT_DATE) assert_equal(Time.new(2008,12,30,0,0,0), obj.value) - obj = WIN32OLE_VARIANT.new("2008/12/30 00:00:01", WIN32OLE::VARIANT::VT_DATE) + obj = WIN32OLE::Variant.new("2008/12/30 00:00:01", WIN32OLE::VARIANT::VT_DATE) assert_equal(Time.new(2008,12,30,0,0,1), obj.value) - obj = WIN32OLE_VARIANT.new("9999/12/31 23:59:59", WIN32OLE::VARIANT::VT_DATE) + obj = WIN32OLE::Variant.new("9999/12/31 23:59:59", WIN32OLE::VARIANT::VT_DATE) assert_equal(Time.new(9999,12,31,23,59,59), obj.value) end def test_create_nil_dispatch - var = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_DISPATCH) + var = WIN32OLE::Variant.new(nil, WIN32OLE::VARIANT::VT_DISPATCH) assert_nil(var.value) end def test_create_variant_byref - obj = WIN32OLE_VARIANT.new("Str", WIN32OLE::VARIANT::VT_VARIANT|WIN32OLE::VARIANT::VT_BYREF); + obj = WIN32OLE::Variant.new("Str", WIN32OLE::VARIANT::VT_VARIANT|WIN32OLE::VARIANT::VT_BYREF); assert_equal("Str", obj.value); end def test_vartype - obj = WIN32OLE_VARIANT.new("Str") + obj = WIN32OLE::Variant.new("Str") assert_equal(WIN32OLE::VARIANT::VT_BSTR, obj.vartype) end def test_set_value - obj = WIN32OLE_VARIANT.new(10) + obj = WIN32OLE::Variant.new(10) obj.value = 12 assert_equal(12, obj.value) assert_equal(WIN32OLE::VARIANT::VT_I4, obj.vartype) @@ -661,57 +661,57 @@ def test_set_value assert_equal(11, obj.value) assert_equal(WIN32OLE::VARIANT::VT_I4, obj.vartype) - obj = WIN32OLE_VARIANT.new([1,2]) - assert_raise(WIN32OLERuntimeError) { + obj = WIN32OLE::Variant.new([1,2]) + assert_raise(WIN32OLE::RuntimeError) { obj.value = [3,4] } - obj = WIN32OLE_VARIANT.new("2007/01/01", WIN32OLE::VARIANT::VT_DATE) - assert_raise(WIN32OLERuntimeError) { + obj = WIN32OLE::Variant.new("2007/01/01", WIN32OLE::VARIANT::VT_DATE) + assert_raise(WIN32OLE::RuntimeError) { obj.value = "hogehoge" } assert_equal(Time.new(2007,1,1), obj.value) - obj2 = WIN32OLE_VARIANT.new("2006/01/01", WIN32OLE::VARIANT::VT_DATE) + obj2 = WIN32OLE::Variant.new("2006/01/01", WIN32OLE::VARIANT::VT_DATE) obj.value = obj2 assert_equal(Time.new(2006,01,01), obj.value) end def test_c_nothing - assert_nil(WIN32OLE_VARIANT::Nothing.value) + assert_nil(WIN32OLE::Variant::Nothing.value) end def test_c_empty - assert_nil(WIN32OLE_VARIANT::Empty.value) + assert_nil(WIN32OLE::Variant::Empty.value) end def test_c_null - assert_nil(WIN32OLE_VARIANT::Null.value) + assert_nil(WIN32OLE::Variant::Null.value) end def test_c_noparam # DISP_E_PARAMNOTFOUND - assert_equal(-2147352572, WIN32OLE_VARIANT::NoParam.value) + assert_equal(-2147352572, WIN32OLE::Variant::NoParam.value) end def test_vt_error_noparam - v = WIN32OLE_VARIANT.new(-1, WIN32OLE::VARIANT::VT_ERROR) + v = WIN32OLE::Variant.new(-1, WIN32OLE::VARIANT::VT_ERROR) assert_equal(-1, v.value) fso = WIN32OLE.new("Scripting.FileSystemObject") - exc = assert_raise(WIN32OLERuntimeError) { + exc = assert_raise(WIN32OLE::RuntimeError) { fso.openTextFile("NonExistingFile", v, false) } assert_match(/Type mismatch/i, exc.message) - exc = assert_raise(WIN32OLERuntimeError) { - fso.openTextFile("NonExistingFile", WIN32OLE_VARIANT::NoParam, false) + exc = assert_raise(WIN32OLE::RuntimeError) { + fso.openTextFile("NonExistingFile", WIN32OLE::Variant::NoParam, false) } # 800A0035 is 'file not found' error. assert_match(/800A0035/, exc.message) # -2147352572 is DISP_E_PARAMNOTFOUND - v = WIN32OLE_VARIANT.new(-2147352572, WIN32OLE::VARIANT::VT_ERROR) - exc = assert_raise(WIN32OLERuntimeError) { - fso.openTextFile("NonExistingFile", WIN32OLE_VARIANT::NoParam, false) + v = WIN32OLE::Variant.new(-2147352572, WIN32OLE::VARIANT::VT_ERROR) + exc = assert_raise(WIN32OLE::RuntimeError) { + fso.openTextFile("NonExistingFile", WIN32OLE::Variant::NoParam, false) } # 800A0035 is 'file not found' error code. assert_match(/800A0035/, exc.message) diff --git a/test/win32ole/test_win32ole_variant_outarg.rb b/test/win32ole/test_win32ole_variant_outarg.rb index f50b04aaf55d10..9301a76aaa563c 100644 --- a/test/win32ole/test_win32ole_variant_outarg.rb +++ b/test/win32ole/test_win32ole_variant_outarg.rb @@ -23,7 +23,7 @@ def ado_csv_installed? installed end -if defined?(WIN32OLE_VARIANT) +if defined?(WIN32OLE::Variant) class TestWIN32OLE_VARIANT_OUTARG < Test::Unit::TestCase module ADO end @@ -48,11 +48,11 @@ def test_variant_ref_and_argv @db.execute(sql, -1) c = WIN32OLE::ARGV[1] assert_equal(1, c) - obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_VARIANT|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new(nil, WIN32OLE::VARIANT::VT_VARIANT|WIN32OLE::VARIANT::VT_BYREF) assert_equal(nil, obj.value) @db.execute(sql , obj) assert_equal(1, obj.value) - obj = WIN32OLE_VARIANT.new(-100, WIN32OLE::VARIANT::VT_VARIANT|WIN32OLE::VARIANT::VT_BYREF) + obj = WIN32OLE::Variant.new(-100, WIN32OLE::VARIANT::VT_VARIANT|WIN32OLE::VARIANT::VT_BYREF) assert_equal(-100, obj.value) @db.execute(sql, obj) assert_equal(1, obj.value) diff --git a/test/win32ole/test_word.rb b/test/win32ole/test_word.rb index a23757f62084e9..34cfbbc2a4dbcb 100644 --- a/test/win32ole/test_word.rb +++ b/test/win32ole/test_word.rb @@ -41,7 +41,7 @@ def test_dummy_for_skip_message def setup begin @obj = WIN32OLE.new('Word.Application') - rescue WIN32OLERuntimeError + rescue WIN32OLE::RuntimeError @obj = nil end end From 703ad99bf8de24137a8d635c13d6c7c8bc6b1f56 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 31 Dec 2023 17:40:32 +0900 Subject: [PATCH 601/640] [ruby/win32ole] Use `end_with?` and fix indent https://github.com/ruby/win32ole/commit/7648ee7e56 --- ext/win32ole/sample/olegen.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/win32ole/sample/olegen.rb b/ext/win32ole/sample/olegen.rb index 4b088a774f2062..9398194cf1be8f 100644 --- a/ext/win32ole/sample/olegen.rb +++ b/ext/win32ole/sample/olegen.rb @@ -70,8 +70,8 @@ def generate_argtype(typedetails) end if ts.empty? ts = 'VT_VARIANT' - elsif ts[-1] == ?| - ts += 'VT_VARIANT' + elsif ts.end_with?(?|) + ts += 'VT_VARIANT' end ts end From 3ad54239b529b1b4b96d06117e8039c1d57f1e89 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 31 Dec 2023 17:44:20 +0900 Subject: [PATCH 602/640] [ruby/win32ole] [DOC] Move sample to toplevel https://github.com/ruby/win32ole/commit/70ea60c4d2 --- {ext/win32ole/sample => sample/win32ole}/excel1.rb | 0 {ext/win32ole/sample => sample/win32ole}/excel2.rb | 0 {ext/win32ole/sample => sample/win32ole}/excel3.rb | 0 {ext/win32ole/sample => sample/win32ole}/ie.rb | 0 {ext/win32ole/sample => sample/win32ole}/ieconst.rb | 0 {ext/win32ole/sample => sample/win32ole}/ienavi.rb | 0 {ext/win32ole/sample => sample/win32ole}/ienavi2.rb | 0 {ext/win32ole/sample => sample/win32ole}/oledirs.rb | 0 {ext/win32ole/sample => sample/win32ole}/olegen.rb | 0 {ext/win32ole/sample => sample/win32ole}/xml.rb | 0 10 files changed, 0 insertions(+), 0 deletions(-) rename {ext/win32ole/sample => sample/win32ole}/excel1.rb (100%) rename {ext/win32ole/sample => sample/win32ole}/excel2.rb (100%) rename {ext/win32ole/sample => sample/win32ole}/excel3.rb (100%) rename {ext/win32ole/sample => sample/win32ole}/ie.rb (100%) rename {ext/win32ole/sample => sample/win32ole}/ieconst.rb (100%) rename {ext/win32ole/sample => sample/win32ole}/ienavi.rb (100%) rename {ext/win32ole/sample => sample/win32ole}/ienavi2.rb (100%) rename {ext/win32ole/sample => sample/win32ole}/oledirs.rb (100%) rename {ext/win32ole/sample => sample/win32ole}/olegen.rb (100%) rename {ext/win32ole/sample => sample/win32ole}/xml.rb (100%) diff --git a/ext/win32ole/sample/excel1.rb b/sample/win32ole/excel1.rb similarity index 100% rename from ext/win32ole/sample/excel1.rb rename to sample/win32ole/excel1.rb diff --git a/ext/win32ole/sample/excel2.rb b/sample/win32ole/excel2.rb similarity index 100% rename from ext/win32ole/sample/excel2.rb rename to sample/win32ole/excel2.rb diff --git a/ext/win32ole/sample/excel3.rb b/sample/win32ole/excel3.rb similarity index 100% rename from ext/win32ole/sample/excel3.rb rename to sample/win32ole/excel3.rb diff --git a/ext/win32ole/sample/ie.rb b/sample/win32ole/ie.rb similarity index 100% rename from ext/win32ole/sample/ie.rb rename to sample/win32ole/ie.rb diff --git a/ext/win32ole/sample/ieconst.rb b/sample/win32ole/ieconst.rb similarity index 100% rename from ext/win32ole/sample/ieconst.rb rename to sample/win32ole/ieconst.rb diff --git a/ext/win32ole/sample/ienavi.rb b/sample/win32ole/ienavi.rb similarity index 100% rename from ext/win32ole/sample/ienavi.rb rename to sample/win32ole/ienavi.rb diff --git a/ext/win32ole/sample/ienavi2.rb b/sample/win32ole/ienavi2.rb similarity index 100% rename from ext/win32ole/sample/ienavi2.rb rename to sample/win32ole/ienavi2.rb diff --git a/ext/win32ole/sample/oledirs.rb b/sample/win32ole/oledirs.rb similarity index 100% rename from ext/win32ole/sample/oledirs.rb rename to sample/win32ole/oledirs.rb diff --git a/ext/win32ole/sample/olegen.rb b/sample/win32ole/olegen.rb similarity index 100% rename from ext/win32ole/sample/olegen.rb rename to sample/win32ole/olegen.rb diff --git a/ext/win32ole/sample/xml.rb b/sample/win32ole/xml.rb similarity index 100% rename from ext/win32ole/sample/xml.rb rename to sample/win32ole/xml.rb From 8074525b2b122be590a8a3d3c2c9fb5ea96a37ad Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 31 Dec 2023 18:24:59 +0900 Subject: [PATCH 603/640] [ruby/win32ole] Move toplevel constant for olegen under `WIN32OLE` https://github.com/ruby/win32ole/commit/78ff137c0f --- ext/win32ole/lib/win32ole/property.rb | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/ext/win32ole/lib/win32ole/property.rb b/ext/win32ole/lib/win32ole/property.rb index fea047cd19b2f4..558056b32b85a3 100644 --- a/ext/win32ole/lib/win32ole/property.rb +++ b/ext/win32ole/lib/win32ole/property.rb @@ -1,7 +1,12 @@ # frozen_string_literal: false -# OLEProperty -# helper class of Property with arguments. -class OLEProperty + +class WIN32OLE +end + +# OLEProperty is a helper class of Property with arguments, used by +# `olegen.rb`-generated files. +class WIN32OLE::Property + # :stopdoc: def initialize(obj, dispid, gettypes, settypes) @obj = obj @dispid = dispid @@ -14,4 +19,11 @@ def [](*args) def []=(*args) @obj._setproperty(@dispid, args, @settypes) end + # :stopdoc: +end + +module WIN32OLE::VariantType + # Alias for `olegen.rb`-generated files, that should include + # WIN32OLE::VARIANT. + OLEProperty = WIN32OLE::Property end From 5ac9c8f01b166f2f172be6068e5dda9755b58c63 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 29 Jan 2024 00:27:05 +0900 Subject: [PATCH 604/640] [ruby/win32ole] [DOC] Remove spaces inside parentheses https://github.com/ruby/win32ole/commit/57e4a38465 --- ext/win32ole/win32ole.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/win32ole/win32ole.c b/ext/win32ole/win32ole.c index 7b102928d7700b..e0342d1e9dc9f2 100644 --- a/ext/win32ole/win32ole.c +++ b/ext/win32ole/win32ole.c @@ -1962,7 +1962,7 @@ ole_bind_obj(VALUE moniker, int argc, VALUE *argv, VALUE self) /* * call-seq: - * connect( ole ) --> aWIN32OLE + * connect(ole) --> aWIN32OLE * * Returns running OLE Automation object or WIN32OLE object from moniker. * 1st argument should be OLE program id or class id or moniker. @@ -2019,7 +2019,7 @@ fole_s_connect(int argc, VALUE *argv, VALUE self) /* * call-seq: - * const_load( ole, mod = WIN32OLE) + * const_load(ole, mod = WIN32OLE) * * Defines the constants of OLE Automation server as mod's constants. * The first argument is WIN32OLE object or type library name. From 6bbbfb4629a4fdb336d5ac4f625e97ce30c15a01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 15 Jan 2024 16:59:09 +0100 Subject: [PATCH 605/640] [rubygems/rubygems] Require vendored_uri file in Bundler https://github.com/rubygems/rubygems/commit/62bc261042 --- .../vendor/net-http-persistent/lib/net/http/persistent.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb b/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb index c702bebc39a018..4d4d4ddcfaeda9 100644 --- a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +++ b/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb @@ -1,5 +1,5 @@ require_relative '../../../../../vendored_net_http' -require_relative '../../../../uri/lib/uri' +require_relative '../../../../../vendored_uri' require 'cgi' # for escaping require_relative '../../../../connection_pool/lib/connection_pool' From d64d0b54231208c7bec899a7fe8c3b98ec2e9a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 15 Jan 2024 20:51:02 +0100 Subject: [PATCH 606/640] Vendor uri gem in RubyGems --- lib/rubygems/commands/sources_command.rb | 4 +- lib/rubygems/gemcutter_utilities.rb | 10 +- .../gemcutter_utilities/webauthn_listener.rb | 2 +- lib/rubygems/local_remote_options.rb | 12 +- lib/rubygems/net-http/lib/net/http.rb | 30 +- .../net-http/lib/net/http/generic_request.rb | 18 +- lib/rubygems/net-http/lib/net/http/header.rb | 4 +- lib/rubygems/net-http/lib/net/http/request.rb | 4 +- .../net-http/lib/net/http/requests.rb | 30 +- .../net-http/lib/net/http/response.rb | 4 +- .../net-http/lib/net/http/responses.rb | 12 +- lib/rubygems/net-http/lib/net/http/status.rb | 2 +- lib/rubygems/optparse/lib/optparse.rb | 2 +- lib/rubygems/optparse/lib/optparse/uri.rb | 4 +- lib/rubygems/remote_fetcher.rb | 4 +- lib/rubygems/request.rb | 8 +- lib/rubygems/resolver/api_set.rb | 2 +- lib/rubygems/resolver/best_set.rb | 2 +- lib/rubygems/s3_uri_signer.rb | 4 +- lib/rubygems/source/git.rb | 4 +- lib/rubygems/source_list.rb | 2 +- lib/rubygems/specification_policy.rb | 8 +- lib/rubygems/uri.rb | 12 +- lib/rubygems/util.rb | 2 +- lib/rubygems/vendor/uri/.document | 1 + lib/rubygems/vendor/uri/LICENSE.txt | 22 + lib/rubygems/vendor/uri/lib/uri.rb | 104 ++ lib/rubygems/vendor/uri/lib/uri/common.rb | 853 +++++++++ lib/rubygems/vendor/uri/lib/uri/file.rb | 100 ++ lib/rubygems/vendor/uri/lib/uri/ftp.rb | 267 +++ lib/rubygems/vendor/uri/lib/uri/generic.rb | 1588 +++++++++++++++++ lib/rubygems/vendor/uri/lib/uri/http.rb | 125 ++ lib/rubygems/vendor/uri/lib/uri/https.rb | 23 + lib/rubygems/vendor/uri/lib/uri/ldap.rb | 261 +++ lib/rubygems/vendor/uri/lib/uri/ldaps.rb | 22 + lib/rubygems/vendor/uri/lib/uri/mailto.rb | 293 +++ .../vendor/uri/lib/uri/rfc2396_parser.rb | 539 ++++++ .../vendor/uri/lib/uri/rfc3986_parser.rb | 183 ++ lib/rubygems/vendor/uri/lib/uri/version.rb | 6 + lib/rubygems/vendor/uri/lib/uri/ws.rb | 83 + lib/rubygems/vendor/uri/lib/uri/wss.rb | 23 + test/rubygems/helper.rb | 4 +- .../rubygems/test_gem_dependency_installer.rb | 2 +- .../rubygems/test_gem_local_remote_options.rb | 12 +- test/rubygems/test_gem_remote_fetcher.rb | 26 +- test/rubygems/test_gem_request.rb | 32 +- .../test_gem_request_connection_pools.rb | 14 +- test/rubygems/test_gem_resolver.rb | 2 +- test/rubygems/test_gem_resolver_api_set.rb | 18 +- .../test_gem_resolver_api_specification.rb | 4 +- test/rubygems/test_gem_resolver_best_set.rb | 6 +- test/rubygems/test_gem_source.rb | 10 +- test/rubygems/test_gem_source_git.rb | 2 +- test/rubygems/test_gem_source_list.rb | 4 +- test/rubygems/test_gem_source_lock.rb | 2 +- .../test_gem_source_subpath_problem.rb | 2 +- test/rubygems/test_gem_spec_fetcher.rb | 2 +- test/rubygems/test_webauthn_listener.rb | 20 +- test/rubygems/utilities.rb | 12 +- 59 files changed, 4673 insertions(+), 180 deletions(-) create mode 100644 lib/rubygems/vendor/uri/.document create mode 100644 lib/rubygems/vendor/uri/LICENSE.txt create mode 100644 lib/rubygems/vendor/uri/lib/uri.rb create mode 100644 lib/rubygems/vendor/uri/lib/uri/common.rb create mode 100644 lib/rubygems/vendor/uri/lib/uri/file.rb create mode 100644 lib/rubygems/vendor/uri/lib/uri/ftp.rb create mode 100644 lib/rubygems/vendor/uri/lib/uri/generic.rb create mode 100644 lib/rubygems/vendor/uri/lib/uri/http.rb create mode 100644 lib/rubygems/vendor/uri/lib/uri/https.rb create mode 100644 lib/rubygems/vendor/uri/lib/uri/ldap.rb create mode 100644 lib/rubygems/vendor/uri/lib/uri/ldaps.rb create mode 100644 lib/rubygems/vendor/uri/lib/uri/mailto.rb create mode 100644 lib/rubygems/vendor/uri/lib/uri/rfc2396_parser.rb create mode 100644 lib/rubygems/vendor/uri/lib/uri/rfc3986_parser.rb create mode 100644 lib/rubygems/vendor/uri/lib/uri/version.rb create mode 100644 lib/rubygems/vendor/uri/lib/uri/ws.rb create mode 100644 lib/rubygems/vendor/uri/lib/uri/wss.rb diff --git a/lib/rubygems/commands/sources_command.rb b/lib/rubygems/commands/sources_command.rb index c9c6ee80ed50a4..976f4a4ea2ae92 100644 --- a/lib/rubygems/commands/sources_command.rb +++ b/lib/rubygems/commands/sources_command.rb @@ -59,7 +59,7 @@ def add_source(source_uri) # :nodoc: say "#{source_uri} added to sources" end - rescue URI::Error, ArgumentError + rescue Gem::URI::Error, ArgumentError say "#{source_uri} is not a URI" terminate_interaction 1 rescue Gem::RemoteFetcher::FetchError => e @@ -81,7 +81,7 @@ def check_typo_squatting(source) end def check_rubygems_https(source_uri) # :nodoc: - uri = URI source_uri + uri = Gem::URI source_uri if uri.scheme && uri.scheme.casecmp("http").zero? && uri.host.casecmp("rubygems.org").zero? diff --git a/lib/rubygems/gemcutter_utilities.rb b/lib/rubygems/gemcutter_utilities.rb index 7fcc0e037d22c7..5e5c9d5a64c133 100644 --- a/lib/rubygems/gemcutter_utilities.rb +++ b/lib/rubygems/gemcutter_utilities.rb @@ -93,8 +93,8 @@ def rubygems_api_request(method, path, host = nil, allowed_push_host = nil, scop end if allowed_push_host - allowed_host_uri = URI.parse(allowed_push_host) - host_uri = URI.parse(self.host) + allowed_host_uri = Gem::URI.parse(allowed_push_host) + host_uri = Gem::URI.parse(self.host) unless (host_uri.scheme == allowed_host_uri.scheme) && (host_uri.host == allowed_host_uri.host) alert_error "#{self.host.inspect} is not allowed by the gemspec, which only allows #{allowed_push_host.inspect}" @@ -102,7 +102,7 @@ def rubygems_api_request(method, path, host = nil, allowed_push_host = nil, scop end end - uri = URI.parse "#{self.host}/#{path}" + uri = Gem::URI.parse "#{self.host}/#{path}" response = request_with_otp(method, uri, &block) if mfa_unauthorized?(response) @@ -136,7 +136,7 @@ def update_scope(scope) sign_in_host, scope: scope) do |request| request.basic_auth email, password request["OTP"] = otp if otp - request.body = URI.encode_www_form({ api_key: api_key }.merge(update_scope_params)) + request.body = Gem::URI.encode_www_form({ api_key: api_key }.merge(update_scope_params)) end with_response response do |_resp| @@ -176,7 +176,7 @@ def sign_in(sign_in_host = nil, scope: nil) sign_in_host, credentials: credentials, scope: scope) do |request| request.basic_auth email, password request["OTP"] = otp if otp - request.body = URI.encode_www_form({ name: key_name }.merge(all_params)) + request.body = Gem::URI.encode_www_form({ name: key_name }.merge(all_params)) end with_response response do |resp| diff --git a/lib/rubygems/gemcutter_utilities/webauthn_listener.rb b/lib/rubygems/gemcutter_utilities/webauthn_listener.rb index bea9d9e397d864..abf65efe37d98d 100644 --- a/lib/rubygems/gemcutter_utilities/webauthn_listener.rb +++ b/lib/rubygems/gemcutter_utilities/webauthn_listener.rb @@ -51,7 +51,7 @@ def wait_for_otp_code(server) request_line = socket.gets method, req_uri, _protocol = request_line.split(" ") - req_uri = URI.parse(req_uri) + req_uri = Gem::URI.parse(req_uri) responder = SocketResponder.new(socket) diff --git a/lib/rubygems/local_remote_options.rb b/lib/rubygems/local_remote_options.rb index e2a008fada83fe..51a61213a50add 100644 --- a/lib/rubygems/local_remote_options.rb +++ b/lib/rubygems/local_remote_options.rb @@ -6,7 +6,7 @@ # See LICENSE.txt for permissions. #++ -require "uri" +require_relative "vendor/uri/lib/uri" require_relative "../rubygems" ## @@ -17,10 +17,10 @@ module Gem::LocalRemoteOptions # Allows Gem::OptionParser to handle HTTP URIs. def accept_uri_http - Gem::OptionParser.accept URI::HTTP do |value| + Gem::OptionParser.accept Gem::URI::HTTP do |value| begin - uri = URI.parse value - rescue URI::InvalidURIError + uri = Gem::URI.parse value + rescue Gem::URI::InvalidURIError raise Gem::OptionParser::InvalidArgument, value end @@ -88,7 +88,7 @@ def add_clear_sources_option def add_proxy_option accept_uri_http - add_option(:"Local/Remote", "-p", "--[no-]http-proxy [URL]", URI::HTTP, + add_option(:"Local/Remote", "-p", "--[no-]http-proxy [URL]", Gem::URI::HTTP, "Use HTTP proxy for remote operations") do |value, options| options[:http_proxy] = value == false ? :no_proxy : value Gem.configuration[:http_proxy] = options[:http_proxy] @@ -101,7 +101,7 @@ def add_proxy_option def add_source_option accept_uri_http - add_option(:"Local/Remote", "-s", "--source URL", URI::HTTP, + add_option(:"Local/Remote", "-s", "--source URL", Gem::URI::HTTP, "Append URL to list of remote gem sources") do |source, options| source << "/" unless source.end_with?("/") diff --git a/lib/rubygems/net-http/lib/net/http.rb b/lib/rubygems/net-http/lib/net/http.rb index 833912e9a235ba..70565d8f5d5905 100644 --- a/lib/rubygems/net-http/lib/net/http.rb +++ b/lib/rubygems/net-http/lib/net/http.rb @@ -21,7 +21,7 @@ # require_relative '../../../net-protocol/lib/net/protocol' -require 'uri' +require_relative '../../../vendor/uri/lib/uri' require_relative '../../../resolv/lib/resolv' autoload :OpenSSL, 'openssl' @@ -106,20 +106,20 @@ class HTTPHeaderSyntaxError < StandardError; end # It consists of some or all of: scheme, hostname, path, query, and fragment; # see {URI syntax}[https://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Syntax]. # - # A Ruby {URI::Generic}[rdoc-ref:URI::Generic] object + # A Ruby {Gem::URI::Generic}[https://docs.ruby-lang.org/en/master/Gem/URI/Generic.html] object # represents an internet URI. # It provides, among others, methods # +scheme+, +hostname+, +path+, +query+, and +fragment+. # # === Schemes # - # An internet \URI has + # An internet \Gem::URI has # a {scheme}[https://en.wikipedia.org/wiki/List_of_URI_schemes]. # # The two schemes supported in \Gem::Net::HTTP are 'https' and 'http': # # uri.scheme # => "https" - # URI('http://example.com').scheme # => "http" + # Gem::URI('http://example.com').scheme # => "http" # # === Hostnames # @@ -146,8 +146,8 @@ class HTTPHeaderSyntaxError < StandardError; end # # _uri = uri.dup # params = {userId: 1, completed: false} - # _uri.query = URI.encode_www_form(params) - # _uri # => # + # _uri.query = Gem::URI.encode_www_form(params) + # _uri # => # # Gem::Net::HTTP.get(_uri) # # === Fragments @@ -273,7 +273,7 @@ class HTTPHeaderSyntaxError < StandardError; end # # You should choose a better exception. # raise ArgumentError, 'Too many HTTP redirects' if limit == 0 # - # res = Gem::Net::HTTP.get_response(URI(uri)) + # res = Gem::Net::HTTP.get_response(Gem::URI(uri)) # case res # when Gem::Net::HTTPSuccess # Any success class. # res @@ -327,9 +327,9 @@ class HTTPHeaderSyntaxError < StandardError; end # # Or if you simply want to make a GET request, you may pass in a URI # object that has an \HTTPS URL. \Gem::Net::HTTP automatically turns on TLS - # verification if the URI object has a 'https' URI scheme: + # verification if the URI object has a 'https' :URI scheme: # - # uri # => # + # uri # => # # Gem::Net::HTTP.get(uri) # # == Proxy Server @@ -371,9 +371,9 @@ class HTTPHeaderSyntaxError < StandardError; end # === Proxy Using 'ENV['http_proxy']' # # When environment variable 'http_proxy' - # is set to a \URI string, + # is set to a \Gem::URI string, # the returned +http+ will have the server at that URI as its proxy; - # note that the \URI string must have a protocol + # note that the \Gem::URI string must have a protocol # such as 'http' or 'https': # # ENV['http_proxy'] = 'http://example.com' @@ -386,7 +386,7 @@ class HTTPHeaderSyntaxError < StandardError; end # http.proxy_user # => nil # http.proxy_pass # => nil # - # The \URI string may include proxy username, password, and port number: + # The \Gem::URI string may include proxy username, password, and port number: # # ENV['http_proxy'] = 'http://pname:ppass@example.com:8000' # http = Gem::Net::HTTP.new(hostname) @@ -790,7 +790,7 @@ def HTTP.get_print(uri_or_host, path_or_headers = nil, port = nil) # # With URI object +uri+ and optional hash argument +headers+: # - # uri = URI('https://jsonplaceholder.typicode.com/todos/1') + # uri = Gem::URI('https://jsonplaceholder.typicode.com/todos/1') # headers = {'Content-type' => 'application/json; charset=UTF-8'} # Gem::Net::HTTP.get(uri, headers) # @@ -1074,7 +1074,7 @@ def HTTP.new(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_p elsif p_addr == :ENV then http.proxy_from_env = true else - if p_addr && p_no_proxy && !URI::Generic.use_proxy?(address, address, port, p_no_proxy) + if p_addr && p_no_proxy && !Gem::URI::Generic.use_proxy?(address, address, port, p_no_proxy) p_addr = nil p_port = nil end @@ -1796,7 +1796,7 @@ def proxy_from_env? # The proxy URI determined from the environment for this connection. def proxy_uri # :nodoc: return if @proxy_uri == false - @proxy_uri ||= URI::HTTP.new( + @proxy_uri ||= Gem::URI::HTTP.new( "http", nil, address, port, nil, nil, nil, nil, nil ).find_proxy || false @proxy_uri || nil diff --git a/lib/rubygems/net-http/lib/net/http/generic_request.rb b/lib/rubygems/net-http/lib/net/http/generic_request.rb index a83f4761f2ea1d..5cfe75a7cde734 100644 --- a/lib/rubygems/net-http/lib/net/http/generic_request.rb +++ b/lib/rubygems/net-http/lib/net/http/generic_request.rb @@ -17,10 +17,10 @@ def initialize(m, reqbody, resbody, uri_or_path, initheader = nil) # :nodoc: @request_has_body = reqbody @response_has_body = resbody - if URI === uri_or_path then - raise ArgumentError, "not an HTTP URI" unless URI::HTTP === uri_or_path + if Gem::URI === uri_or_path then + raise ArgumentError, "not an HTTP Gem::URI" unless Gem::URI::HTTP === uri_or_path hostname = uri_or_path.hostname - raise ArgumentError, "no host component for URI" unless (hostname && hostname.length > 0) + raise ArgumentError, "no host component for Gem::URI" unless (hostname && hostname.length > 0) @uri = uri_or_path.dup host = @uri.hostname.dup host << ":" << @uri.port.to_s if @uri.port != @uri.default_port @@ -71,10 +71,10 @@ def initialize(m, reqbody, resbody, uri_or_path, initheader = nil) # :nodoc: # attr_reader :path - # Returns the URI object for the request, or +nil+ if none: + # Returns the Gem::URI object for the request, or +nil+ if none: # # Gem::Net::HTTP::Get.new(uri).uri - # # => # + # # => # # Gem::Net::HTTP::Get.new('example.com').uri # => nil # attr_reader :uri @@ -213,10 +213,10 @@ def update_uri(addr, port, ssl) # :nodoc: internal use only if ssl scheme = 'https' - klass = URI::HTTPS + klass = Gem::URI::HTTPS else scheme = 'http' - klass = URI::HTTP + klass = Gem::URI::HTTP end if host = self['host'] @@ -225,7 +225,7 @@ def update_uri(addr, port, ssl) # :nodoc: internal use only else host = addr end - # convert the class of the URI + # convert the class of the Gem::URI if @uri.is_a?(klass) @uri.host = host @uri.port = port @@ -286,7 +286,7 @@ def send_request_with_body_stream(sock, ver, path, f) def send_request_with_body_data(sock, ver, path, params) if /\Amultipart\/form-data\z/i !~ self.content_type self.content_type = 'application/x-www-form-urlencoded' - return send_request_with_body(sock, ver, path, URI.encode_www_form(params)) + return send_request_with_body(sock, ver, path, Gem::URI.encode_www_form(params)) end opt = @form_option.dup diff --git a/lib/rubygems/net-http/lib/net/http/header.rb b/lib/rubygems/net-http/lib/net/http/header.rb index 918ffa9c087827..1488e60068215e 100644 --- a/lib/rubygems/net-http/lib/net/http/header.rb +++ b/lib/rubygems/net-http/lib/net/http/header.rb @@ -782,7 +782,7 @@ def set_content_type(type, params = {}) # The resulting request is suitable for HTTP request +POST+ or +PUT+. # # Argument +params+ must be suitable for use as argument +enum+ to - # {URI.encode_www_form}[https://docs.ruby-lang.org/en/master/URI.html#method-c-encode_www_form]. + # {Gem::URI.encode_www_form}[https://docs.ruby-lang.org/en/master/Gem::URI.html#method-c-encode_www_form]. # # With only argument +params+ given, # sets the body to a URL-encoded string with the default separator '&': @@ -810,7 +810,7 @@ def set_content_type(type, params = {}) # # Gem::Net::HTTPHeader#form_data= is an alias for Gem::Net::HTTPHeader#set_form_data. def set_form_data(params, sep = '&') - query = URI.encode_www_form(params) + query = Gem::URI.encode_www_form(params) query.gsub!(/&/, sep) if sep != '&' self.body = query self.content_type = 'application/x-www-form-urlencoded' diff --git a/lib/rubygems/net-http/lib/net/http/request.rb b/lib/rubygems/net-http/lib/net/http/request.rb index 857cbc7f67ff79..53bddc420a37c0 100644 --- a/lib/rubygems/net-http/lib/net/http/request.rb +++ b/lib/rubygems/net-http/lib/net/http/request.rb @@ -6,10 +6,10 @@ # # == Creating a Request # -# An request object may be created with either a URI or a string hostname: +# An request object may be created with either a Gem::URI or a string hostname: # # require 'rubygems/net-http/lib/net/http' -# uri = URI('https://jsonplaceholder.typicode.com/') +# uri = Gem::URI('https://jsonplaceholder.typicode.com/') # req = Gem::Net::HTTP::Get.new(uri) # => # # req = Gem::Net::HTTP::Get.new(uri.hostname) # => # # diff --git a/lib/rubygems/net-http/lib/net/http/requests.rb b/lib/rubygems/net-http/lib/net/http/requests.rb index 3e26be949b4409..fade3a3e86a6c5 100644 --- a/lib/rubygems/net-http/lib/net/http/requests.rb +++ b/lib/rubygems/net-http/lib/net/http/requests.rb @@ -6,7 +6,7 @@ # {HTTP method GET}[https://en.wikipedia.org/w/index.php?title=Hypertext_Transfer_Protocol#GET_method]: # # require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # req = Gem::Net::HTTP::Get.new(uri) # => # # res = Gem::Net::HTTP.start(hostname) do |http| @@ -38,7 +38,7 @@ class Gem::Net::HTTP::Get < Gem::Net::HTTPRequest # {HTTP method HEAD}[https://en.wikipedia.org/w/index.php?title=Hypertext_Transfer_Protocol#HEAD_method]: # # require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # req = Gem::Net::HTTP::Head.new(uri) # => # # res = Gem::Net::HTTP.start(hostname) do |http| @@ -69,7 +69,7 @@ class Gem::Net::HTTP::Head < Gem::Net::HTTPRequest # {HTTP method POST}[https://en.wikipedia.org/w/index.php?title=Hypertext_Transfer_Protocol#POST_method]: # # require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # uri.path = '/posts' # req = Gem::Net::HTTP::Post.new(uri) # => # @@ -104,7 +104,7 @@ class Gem::Net::HTTP::Post < Gem::Net::HTTPRequest # {HTTP method PUT}[https://en.wikipedia.org/w/index.php?title=Hypertext_Transfer_Protocol#PUT_method]: # # require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # uri.path = '/posts' # req = Gem::Net::HTTP::Put.new(uri) # => # @@ -134,7 +134,7 @@ class Gem::Net::HTTP::Put < Gem::Net::HTTPRequest # {HTTP method DELETE}[https://en.wikipedia.org/w/index.php?title=Hypertext_Transfer_Protocol#DELETE_method]: # # require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # uri.path = '/posts/1' # req = Gem::Net::HTTP::Delete.new(uri) # => # @@ -166,7 +166,7 @@ class Gem::Net::HTTP::Delete < Gem::Net::HTTPRequest # {HTTP method OPTIONS}[https://en.wikipedia.org/w/index.php?title=Hypertext_Transfer_Protocol#OPTIONS_method]: # # require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # req = Gem::Net::HTTP::Options.new(uri) # => # # res = Gem::Net::HTTP.start(hostname) do |http| @@ -197,7 +197,7 @@ class Gem::Net::HTTP::Options < Gem::Net::HTTPRequest # {HTTP method TRACE}[https://en.wikipedia.org/w/index.php?title=Hypertext_Transfer_Protocol#TRACE_method]: # # require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # req = Gem::Net::HTTP::Trace.new(uri) # => # # res = Gem::Net::HTTP.start(hostname) do |http| @@ -228,7 +228,7 @@ class Gem::Net::HTTP::Trace < Gem::Net::HTTPRequest # {HTTP method PATCH}[https://en.wikipedia.org/w/index.php?title=Hypertext_Transfer_Protocol#PATCH_method]: # # require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # uri.path = '/posts' # req = Gem::Net::HTTP::Patch.new(uri) # => # @@ -266,7 +266,7 @@ class Gem::Net::HTTP::Patch < Gem::Net::HTTPRequest # {WebDAV method PROPFIND}[http://www.webdav.org/specs/rfc4918.html#METHOD_PROPFIND]: # # require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # req = Gem::Net::HTTP::Propfind.new(uri) # => # # res = Gem::Net::HTTP.start(hostname) do |http| @@ -289,7 +289,7 @@ class Gem::Net::HTTP::Propfind < Gem::Net::HTTPRequest # {WebDAV method PROPPATCH}[http://www.webdav.org/specs/rfc4918.html#METHOD_PROPPATCH]: # # require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # req = Gem::Net::HTTP::Proppatch.new(uri) # => # # res = Gem::Net::HTTP.start(hostname) do |http| @@ -312,7 +312,7 @@ class Gem::Net::HTTP::Proppatch < Gem::Net::HTTPRequest # {WebDAV method MKCOL}[http://www.webdav.org/specs/rfc4918.html#METHOD_MKCOL]: # # require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # req = Gem::Net::HTTP::Mkcol.new(uri) # => # # res = Gem::Net::HTTP.start(hostname) do |http| @@ -335,7 +335,7 @@ class Gem::Net::HTTP::Mkcol < Gem::Net::HTTPRequest # {WebDAV method COPY}[http://www.webdav.org/specs/rfc4918.html#METHOD_COPY]: # # require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # req = Gem::Net::HTTP::Copy.new(uri) # => # # res = Gem::Net::HTTP.start(hostname) do |http| @@ -358,7 +358,7 @@ class Gem::Net::HTTP::Copy < Gem::Net::HTTPRequest # {WebDAV method MOVE}[http://www.webdav.org/specs/rfc4918.html#METHOD_MOVE]: # # require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # req = Gem::Net::HTTP::Move.new(uri) # => # # res = Gem::Net::HTTP.start(hostname) do |http| @@ -381,7 +381,7 @@ class Gem::Net::HTTP::Move < Gem::Net::HTTPRequest # {WebDAV method LOCK}[http://www.webdav.org/specs/rfc4918.html#METHOD_LOCK]: # # require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # req = Gem::Net::HTTP::Lock.new(uri) # => # # res = Gem::Net::HTTP.start(hostname) do |http| @@ -404,7 +404,7 @@ class Gem::Net::HTTP::Lock < Gem::Net::HTTPRequest # {WebDAV method UNLOCK}[http://www.webdav.org/specs/rfc4918.html#METHOD_UNLOCK]: # # require 'rubygems/net-http/lib/net/http' -# uri = URI('http://example.com') +# uri = Gem::URI('http://example.com') # hostname = uri.hostname # => "example.com" # req = Gem::Net::HTTP::Unlock.new(uri) # => # # res = Gem::Net::HTTP.start(hostname) do |http| diff --git a/lib/rubygems/net-http/lib/net/http/response.rb b/lib/rubygems/net-http/lib/net/http/response.rb index 28ee36597882b8..cbbd191d879ba7 100644 --- a/lib/rubygems/net-http/lib/net/http/response.rb +++ b/lib/rubygems/net-http/lib/net/http/response.rb @@ -216,8 +216,8 @@ def initialize(httpv, code, msg) #:nodoc: internal use only attr_reader :message alias msg message # :nodoc: obsolete - # The URI used to fetch this response. The response URI is only available - # if a URI was used to create the request. + # The Gem::URI used to fetch this response. The response Gem::URI is only available + # if a Gem::URI was used to create the request. attr_reader :uri # Set to true automatically when the request did not contain an diff --git a/lib/rubygems/net-http/lib/net/http/responses.rb b/lib/rubygems/net-http/lib/net/http/responses.rb index 95ce9dd46a071c..0f26ae6c26c1ab 100644 --- a/lib/rubygems/net-http/lib/net/http/responses.rb +++ b/lib/rubygems/net-http/lib/net/http/responses.rb @@ -379,7 +379,7 @@ class HTTPFound < HTTPRedirection # Response class for See Other responses (status code 303). # - # The response to the request can be found under another URI using the GET method. + # The response to the request can be found under another Gem::URI using the GET method. # # :include: doc/net-http/included_getters.rdoc # @@ -428,8 +428,8 @@ class HTTPUseProxy < HTTPRedirection # Response class for Temporary Redirect responses (status code 307). # - # The request should be repeated with another URI; - # however, future requests should still use the original URI. + # The request should be repeated with another Gem::URI; + # however, future requests should still use the original Gem::URI. # # :include: doc/net-http/included_getters.rdoc # @@ -445,7 +445,7 @@ class HTTPTemporaryRedirect < HTTPRedirection # Response class for Permanent Redirect responses (status code 308). # - # This and all future requests should be directed to the given URI. + # This and all future requests should be directed to the given Gem::URI. # # :include: doc/net-http/included_getters.rdoc # @@ -690,9 +690,9 @@ class HTTPPayloadTooLarge < HTTPClientError end HTTPRequestEntityTooLarge = HTTPPayloadTooLarge - # Response class for URI Too Long responses (status code 414). + # Response class for Gem::URI Too Long responses (status code 414). # - # The URI provided was too long for the server to process. + # The Gem::URI provided was too long for the server to process. # # :include: doc/net-http/included_getters.rdoc # diff --git a/lib/rubygems/net-http/lib/net/http/status.rb b/lib/rubygems/net-http/lib/net/http/status.rb index 10cbc8e3ee5dfb..9110b108b8e6ed 100644 --- a/lib/rubygems/net-http/lib/net/http/status.rb +++ b/lib/rubygems/net-http/lib/net/http/status.rb @@ -11,7 +11,7 @@ puts puts "Gem::Net::HTTP::STATUS_CODES = {" url = "https://www.iana.org/assignments/http-status-codes/http-status-codes-1.csv" - URI(url).read.each_line do |line| + Gem::URI(url).read.each_line do |line| code, mes, = line.split(',') next if ['(Unused)', 'Unassigned', 'Description'].include?(mes) puts " #{code} => '#{mes}'," diff --git a/lib/rubygems/optparse/lib/optparse.rb b/lib/rubygems/optparse/lib/optparse.rb index 8e700016b06c46..42370bf7cc012f 100644 --- a/lib/rubygems/optparse/lib/optparse.rb +++ b/lib/rubygems/optparse/lib/optparse.rb @@ -158,7 +158,7 @@ # - Date -- Anything accepted by +Date.parse+ (need to require +optparse/date+) # - DateTime -- Anything accepted by +DateTime.parse+ (need to require +optparse/date+) # - Time -- Anything accepted by +Time.httpdate+ or +Time.parse+ (need to require +optparse/time+) -# - URI -- Anything accepted by +URI.parse+ (need to require +optparse/uri+) +# - URI -- Anything accepted by +Gem::URI.parse+ (need to require +optparse/uri+) # - Shellwords -- Anything accepted by +Shellwords.shellwords+ (need to require +optparse/shellwords+) # - String -- Any non-empty string # - Integer -- Any integer. Will convert octal. (e.g. 124, -3, 040) diff --git a/lib/rubygems/optparse/lib/optparse/uri.rb b/lib/rubygems/optparse/lib/optparse/uri.rb index 664d7f2af4f9fb..5c2d0b85140b00 100644 --- a/lib/rubygems/optparse/lib/optparse/uri.rb +++ b/lib/rubygems/optparse/lib/optparse/uri.rb @@ -2,6 +2,6 @@ # -*- ruby -*- require_relative '../optparse' -require 'uri' +require_relative '../../../vendor/uri/lib/uri' -Gem::OptionParser.accept(URI) {|s,| URI.parse(s) if s} +Gem::OptionParser.accept(Gem::URI) {|s,| Gem::URI.parse(s) if s} diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb index 8f14d7bc8dbd93..3c8f79f9a7947b 100644 --- a/lib/rubygems/remote_fetcher.rb +++ b/lib/rubygems/remote_fetcher.rb @@ -76,7 +76,7 @@ def initialize(proxy=nil, dns=nil, headers={}) require_relative "core_ext/tcpsocket_init" if Gem.configuration.ipv4_fallback_enabled require_relative "net/http" require "stringio" - require "uri" + require_relative "vendor/uri/lib/uri" Socket.do_not_reverse_lookup = true @@ -135,7 +135,7 @@ def download(spec, source_uri, install_dir = Gem.dir) scheme = source_uri.scheme - # URI.parse gets confused by MS Windows paths with forward slashes. + # Gem::URI.parse gets confused by MS Windows paths with forward slashes. scheme = nil if /^[a-z]$/i.match?(scheme) # REFACTOR: split this up and dispatch on scheme (eg download_http) diff --git a/lib/rubygems/request.rb b/lib/rubygems/request.rb index 8702e223d67104..a8c1549e09a825 100644 --- a/lib/rubygems/request.rb +++ b/lib/rubygems/request.rb @@ -18,11 +18,11 @@ def self.create_with_proxy(uri, request_class, last_modified, proxy) # :nodoc: end def self.proxy_uri(proxy) # :nodoc: - require "uri" + require_relative "vendor/uri/lib/uri" case proxy when :no_proxy then nil - when URI::HTTP then proxy - else URI.parse(proxy) + when Gem::URI::HTTP then proxy + else Gem::URI.parse(proxy) end end @@ -176,7 +176,7 @@ def self.get_proxy_from_env(scheme = "http") end require "uri" - uri = URI(Gem::UriFormatter.new(env_proxy).normalize) + uri = Gem::URI(Gem::UriFormatter.new(env_proxy).normalize) if uri && uri.user.nil? && uri.password.nil? user = ENV["#{downcase_scheme}_proxy_user"] || ENV["#{upcase_scheme}_PROXY_USER"] diff --git a/lib/rubygems/resolver/api_set.rb b/lib/rubygems/resolver/api_set.rb index e8e37473616ece..3e4dadc40f489e 100644 --- a/lib/rubygems/resolver/api_set.rb +++ b/lib/rubygems/resolver/api_set.rb @@ -30,7 +30,7 @@ class Gem::Resolver::APISet < Gem::Resolver::Set def initialize(dep_uri = "https://index.rubygems.org/info/") super() - dep_uri = URI dep_uri unless URI === dep_uri + dep_uri = Gem::URI dep_uri unless Gem::URI === dep_uri @dep_uri = dep_uri @uri = dep_uri + ".." diff --git a/lib/rubygems/resolver/best_set.rb b/lib/rubygems/resolver/best_set.rb index c2e898204796fa..a983f8c6b69f2f 100644 --- a/lib/rubygems/resolver/best_set.rb +++ b/lib/rubygems/resolver/best_set.rb @@ -60,7 +60,7 @@ def pretty_print(q) # :nodoc: def replace_failed_api_set(error) # :nodoc: uri = error.original_uri - uri = URI uri unless URI === uri + uri = Gem::URI uri unless Gem::URI === uri uri += "." raise error unless api_set = @sets.find do |set| diff --git a/lib/rubygems/s3_uri_signer.rb b/lib/rubygems/s3_uri_signer.rb index 53d49ec432a446..06dee3afe0fdf4 100644 --- a/lib/rubygems/s3_uri_signer.rb +++ b/lib/rubygems/s3_uri_signer.rb @@ -49,7 +49,7 @@ def sign(expiration = 86_400) string_to_sign = generate_string_to_sign(date_time, credential_info, canonical_request) signature = generate_signature(s3_config, date, string_to_sign) - URI.parse("https://#{canonical_host}#{uri.path}?#{query_params}&X-Amz-Signature=#{signature}") + Gem::URI.parse("https://#{canonical_host}#{uri.path}?#{query_params}&X-Amz-Signature=#{signature}") end private @@ -152,7 +152,7 @@ def ec2_metadata_credentials_json end def ec2_metadata_request(url) - uri = URI(url) + uri = Gem::URI(url) @request_pool ||= create_request_pool(uri) request = Gem::Request.new(uri, Gem::Net::HTTP::Get, nil, @request_pool) response = request.fetch diff --git a/lib/rubygems/source/git.rb b/lib/rubygems/source/git.rb index a0d03312b9681a..bda63c6844d92c 100644 --- a/lib/rubygems/source/git.rb +++ b/lib/rubygems/source/git.rb @@ -221,14 +221,14 @@ def specs end ## - # A hash for the git gem based on the git repository URI. + # A hash for the git gem based on the git repository Gem::URI. def uri_hash # :nodoc: require_relative "../openssl" normalized = if @repository.match?(%r{^\w+://(\w+@)?}) - uri = URI(@repository).normalize.to_s.sub %r{/$},"" + uri = Gem::URI(@repository).normalize.to_s.sub %r{/$},"" uri.sub(/\A(\w+)/) { $1.downcase } else @repository diff --git a/lib/rubygems/source_list.rb b/lib/rubygems/source_list.rb index 9e8a9e16ef5788..33db64fbc1513d 100644 --- a/lib/rubygems/source_list.rb +++ b/lib/rubygems/source_list.rb @@ -44,7 +44,7 @@ def initialize_copy(other) # :nodoc: end ## - # Appends +obj+ to the source list which may be a Gem::Source, URI or URI + # Appends +obj+ to the source list which may be a Gem::Source, Gem::URI or URI # String. def <<(obj) diff --git a/lib/rubygems/specification_policy.rb b/lib/rubygems/specification_policy.rb index 4088fb621ad6e9..27c2681533f491 100644 --- a/lib/rubygems/specification_policy.rb +++ b/lib/rubygems/specification_policy.rb @@ -427,13 +427,13 @@ def validate_lazy_metadata # Make sure a homepage is valid HTTP/HTTPS URI if homepage && !homepage.empty? - require "uri" + require_relative "vendor/uri/lib/uri" begin - homepage_uri = URI.parse(homepage) - unless [URI::HTTP, URI::HTTPS].member? homepage_uri.class + homepage_uri = Gem::URI.parse(homepage) + unless [Gem::URI::HTTP, Gem::URI::HTTPS].member? homepage_uri.class error "\"#{homepage}\" is not a valid HTTP URI" end - rescue URI::InvalidURIError + rescue Gem::URI::InvalidURIError error "\"#{homepage}\" is not a valid HTTP URI" end end diff --git a/lib/rubygems/uri.rb b/lib/rubygems/uri.rb index 4b5d035aa09f25..a44aaceba58282 100644 --- a/lib/rubygems/uri.rb +++ b/lib/rubygems/uri.rb @@ -16,9 +16,9 @@ def self.redact(uri) # Parses uri, raising if it's invalid def self.parse!(uri) - require "uri" + require_relative "vendor/uri/lib/uri" - raise URI::InvalidURIError unless uri + raise Gem::URI::InvalidURIError unless uri return uri unless uri.is_a?(String) @@ -28,9 +28,9 @@ def self.parse!(uri) # as "%7BDESede%7D". If this is escaped again the percentage # symbols will be escaped. begin - URI.parse(uri) - rescue URI::InvalidURIError - URI.parse(URI::DEFAULT_PARSER.escape(uri)) + Gem::URI.parse(uri) + rescue Gem::URI::InvalidURIError + Gem::URI.parse(Gem::URI::DEFAULT_PARSER.escape(uri)) end end @@ -39,7 +39,7 @@ def self.parse!(uri) def self.parse(uri) parse!(uri) - rescue URI::InvalidURIError + rescue Gem::URI::InvalidURIError uri end diff --git a/lib/rubygems/util.rb b/lib/rubygems/util.rb index 1815f6af6fb8c7..51f9c2029f33d7 100644 --- a/lib/rubygems/util.rb +++ b/lib/rubygems/util.rb @@ -105,7 +105,7 @@ def self.glob_files_in_dir(glob, base_path) end ## - # Corrects +path+ (usually returned by `URI.parse().path` on Windows), that + # Corrects +path+ (usually returned by `Gem::URI.parse().path` on Windows), that # comes with a leading slash. def self.correct_for_windows_path(path) diff --git a/lib/rubygems/vendor/uri/.document b/lib/rubygems/vendor/uri/.document new file mode 100644 index 00000000000000..0c43bbd6b38177 --- /dev/null +++ b/lib/rubygems/vendor/uri/.document @@ -0,0 +1 @@ +# Vendored files do not need to be documented diff --git a/lib/rubygems/vendor/uri/LICENSE.txt b/lib/rubygems/vendor/uri/LICENSE.txt new file mode 100644 index 00000000000000..a009caefea81f2 --- /dev/null +++ b/lib/rubygems/vendor/uri/LICENSE.txt @@ -0,0 +1,22 @@ +Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. diff --git a/lib/rubygems/vendor/uri/lib/uri.rb b/lib/rubygems/vendor/uri/lib/uri.rb new file mode 100644 index 00000000000000..f1ccc167cc8d54 --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri.rb @@ -0,0 +1,104 @@ +# frozen_string_literal: false +# Gem::URI is a module providing classes to handle Uniform Resource Identifiers +# (RFC2396[http://tools.ietf.org/html/rfc2396]). +# +# == Features +# +# * Uniform way of handling URIs. +# * Flexibility to introduce custom Gem::URI schemes. +# * Flexibility to have an alternate Gem::URI::Parser (or just different patterns +# and regexp's). +# +# == Basic example +# +# require 'rubygems/vendor/uri/lib/uri' +# +# uri = Gem::URI("http://foo.com/posts?id=30&limit=5#time=1305298413") +# #=> # +# +# uri.scheme #=> "http" +# uri.host #=> "foo.com" +# uri.path #=> "/posts" +# uri.query #=> "id=30&limit=5" +# uri.fragment #=> "time=1305298413" +# +# uri.to_s #=> "http://foo.com/posts?id=30&limit=5#time=1305298413" +# +# == Adding custom URIs +# +# module Gem::URI +# class RSYNC < Generic +# DEFAULT_PORT = 873 +# end +# register_scheme 'RSYNC', RSYNC +# end +# #=> Gem::URI::RSYNC +# +# Gem::URI.scheme_list +# #=> {"FILE"=>Gem::URI::File, "FTP"=>Gem::URI::FTP, "HTTP"=>Gem::URI::HTTP, +# # "HTTPS"=>Gem::URI::HTTPS, "LDAP"=>Gem::URI::LDAP, "LDAPS"=>Gem::URI::LDAPS, +# # "MAILTO"=>Gem::URI::MailTo, "RSYNC"=>Gem::URI::RSYNC} +# +# uri = Gem::URI("rsync://rsync.foo.com") +# #=> # +# +# == RFC References +# +# A good place to view an RFC spec is http://www.ietf.org/rfc.html. +# +# Here is a list of all related RFC's: +# - RFC822[http://tools.ietf.org/html/rfc822] +# - RFC1738[http://tools.ietf.org/html/rfc1738] +# - RFC2255[http://tools.ietf.org/html/rfc2255] +# - RFC2368[http://tools.ietf.org/html/rfc2368] +# - RFC2373[http://tools.ietf.org/html/rfc2373] +# - RFC2396[http://tools.ietf.org/html/rfc2396] +# - RFC2732[http://tools.ietf.org/html/rfc2732] +# - RFC3986[http://tools.ietf.org/html/rfc3986] +# +# == Class tree +# +# - Gem::URI::Generic (in uri/generic.rb) +# - Gem::URI::File - (in uri/file.rb) +# - Gem::URI::FTP - (in uri/ftp.rb) +# - Gem::URI::HTTP - (in uri/http.rb) +# - Gem::URI::HTTPS - (in uri/https.rb) +# - Gem::URI::LDAP - (in uri/ldap.rb) +# - Gem::URI::LDAPS - (in uri/ldaps.rb) +# - Gem::URI::MailTo - (in uri/mailto.rb) +# - Gem::URI::Parser - (in uri/common.rb) +# - Gem::URI::REGEXP - (in uri/common.rb) +# - Gem::URI::REGEXP::PATTERN - (in uri/common.rb) +# - Gem::URI::Util - (in uri/common.rb) +# - Gem::URI::Error - (in uri/common.rb) +# - Gem::URI::InvalidURIError - (in uri/common.rb) +# - Gem::URI::InvalidComponentError - (in uri/common.rb) +# - Gem::URI::BadURIError - (in uri/common.rb) +# +# == Copyright Info +# +# Author:: Akira Yamada +# Documentation:: +# Akira Yamada +# Dmitry V. Sabanin +# Vincent Batts +# License:: +# Copyright (c) 2001 akira yamada +# You can redistribute it and/or modify it under the same term as Ruby. +# + +module Gem::URI +end + +require_relative 'uri/version' +require_relative 'uri/common' +require_relative 'uri/generic' +require_relative 'uri/file' +require_relative 'uri/ftp' +require_relative 'uri/http' +require_relative 'uri/https' +require_relative 'uri/ldap' +require_relative 'uri/ldaps' +require_relative 'uri/mailto' +require_relative 'uri/ws' +require_relative 'uri/wss' diff --git a/lib/rubygems/vendor/uri/lib/uri/common.rb b/lib/rubygems/vendor/uri/lib/uri/common.rb new file mode 100644 index 00000000000000..921fb9dd28c0a5 --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/common.rb @@ -0,0 +1,853 @@ +# frozen_string_literal: true +#-- +# = uri/common.rb +# +# Author:: Akira Yamada +# License:: +# You can redistribute it and/or modify it under the same term as Ruby. +# +# See Gem::URI for general documentation +# + +require_relative "rfc2396_parser" +require_relative "rfc3986_parser" + +module Gem::URI + include RFC2396_REGEXP + + REGEXP = RFC2396_REGEXP + Parser = RFC2396_Parser + RFC3986_PARSER = RFC3986_Parser.new + Ractor.make_shareable(RFC3986_PARSER) if defined?(Ractor) + + # Gem::URI::Parser.new + DEFAULT_PARSER = Parser.new + DEFAULT_PARSER.pattern.each_pair do |sym, str| + unless REGEXP::PATTERN.const_defined?(sym) + REGEXP::PATTERN.const_set(sym, str) + end + end + DEFAULT_PARSER.regexp.each_pair do |sym, str| + const_set(sym, str) + end + Ractor.make_shareable(DEFAULT_PARSER) if defined?(Ractor) + + module Util # :nodoc: + def make_components_hash(klass, array_hash) + tmp = {} + if array_hash.kind_of?(Array) && + array_hash.size == klass.component.size - 1 + klass.component[1..-1].each_index do |i| + begin + tmp[klass.component[i + 1]] = array_hash[i].clone + rescue TypeError + tmp[klass.component[i + 1]] = array_hash[i] + end + end + + elsif array_hash.kind_of?(Hash) + array_hash.each do |key, value| + begin + tmp[key] = value.clone + rescue TypeError + tmp[key] = value + end + end + else + raise ArgumentError, + "expected Array of or Hash of components of #{klass} (#{klass.component[1..-1].join(', ')})" + end + tmp[:scheme] = klass.to_s.sub(/\A.*::/, '').downcase + + return tmp + end + module_function :make_components_hash + end + + module Schemes + end + private_constant :Schemes + + # Registers the given +klass+ as the class to be instantiated + # when parsing a \Gem::URI with the given +scheme+: + # + # Gem::URI.register_scheme('MS_SEARCH', Gem::URI::Generic) # => Gem::URI::Generic + # Gem::URI.scheme_list['MS_SEARCH'] # => Gem::URI::Generic + # + # Note that after calling String#upcase on +scheme+, it must be a valid + # constant name. + def self.register_scheme(scheme, klass) + Schemes.const_set(scheme.to_s.upcase, klass) + end + + # Returns a hash of the defined schemes: + # + # Gem::URI.scheme_list + # # => + # {"MAILTO"=>Gem::URI::MailTo, + # "LDAPS"=>Gem::URI::LDAPS, + # "WS"=>Gem::URI::WS, + # "HTTP"=>Gem::URI::HTTP, + # "HTTPS"=>Gem::URI::HTTPS, + # "LDAP"=>Gem::URI::LDAP, + # "FILE"=>Gem::URI::File, + # "FTP"=>Gem::URI::FTP} + # + # Related: Gem::URI.register_scheme. + def self.scheme_list + Schemes.constants.map { |name| + [name.to_s.upcase, Schemes.const_get(name)] + }.to_h + end + + INITIAL_SCHEMES = scheme_list + private_constant :INITIAL_SCHEMES + Ractor.make_shareable(INITIAL_SCHEMES) if defined?(Ractor) + + # Returns a new object constructed from the given +scheme+, +arguments+, + # and +default+: + # + # - The new object is an instance of Gem::URI.scheme_list[scheme.upcase]. + # - The object is initialized by calling the class initializer + # using +scheme+ and +arguments+. + # See Gem::URI::Generic.new. + # + # Examples: + # + # values = ['john.doe', 'www.example.com', '123', nil, '/forum/questions/', nil, 'tag=networking&order=newest', 'top'] + # Gem::URI.for('https', *values) + # # => # + # Gem::URI.for('foo', *values, default: Gem::URI::HTTP) + # # => # + # + def self.for(scheme, *arguments, default: Generic) + const_name = scheme.to_s.upcase + + uri_class = INITIAL_SCHEMES[const_name] + uri_class ||= if /\A[A-Z]\w*\z/.match?(const_name) && Schemes.const_defined?(const_name, false) + Schemes.const_get(const_name, false) + end + uri_class ||= default + + return uri_class.new(scheme, *arguments) + end + + # + # Base class for all Gem::URI exceptions. + # + class Error < StandardError; end + # + # Not a Gem::URI. + # + class InvalidURIError < Error; end + # + # Not a Gem::URI component. + # + class InvalidComponentError < Error; end + # + # Gem::URI is valid, bad usage is not. + # + class BadURIError < Error; end + + # Returns a 9-element array representing the parts of the \Gem::URI + # formed from the string +uri+; + # each array element is a string or +nil+: + # + # names = %w[scheme userinfo host port registry path opaque query fragment] + # values = Gem::URI.split('https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top') + # names.zip(values) + # # => + # [["scheme", "https"], + # ["userinfo", "john.doe"], + # ["host", "www.example.com"], + # ["port", "123"], + # ["registry", nil], + # ["path", "/forum/questions/"], + # ["opaque", nil], + # ["query", "tag=networking&order=newest"], + # ["fragment", "top"]] + # + def self.split(uri) + RFC3986_PARSER.split(uri) + end + + # Returns a new \Gem::URI object constructed from the given string +uri+: + # + # Gem::URI.parse('https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top') + # # => # + # Gem::URI.parse('http://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top') + # # => # + # + # It's recommended to first ::escape string +uri+ + # if it may contain invalid Gem::URI characters. + # + def self.parse(uri) + RFC3986_PARSER.parse(uri) + end + + # Merges the given Gem::URI strings +str+ + # per {RFC 2396}[https://www.rfc-editor.org/rfc/rfc2396.html]. + # + # Each string in +str+ is converted to an + # {RFC3986 Gem::URI}[https://www.rfc-editor.org/rfc/rfc3986.html] before being merged. + # + # Examples: + # + # Gem::URI.join("http://example.com/","main.rbx") + # # => # + # + # Gem::URI.join('http://example.com', 'foo') + # # => # + # + # Gem::URI.join('http://example.com', '/foo', '/bar') + # # => # + # + # Gem::URI.join('http://example.com', '/foo', 'bar') + # # => # + # + # Gem::URI.join('http://example.com', '/foo/', 'bar') + # # => # + # + def self.join(*str) + RFC3986_PARSER.join(*str) + end + + # + # == Synopsis + # + # Gem::URI::extract(str[, schemes][,&blk]) + # + # == Args + # + # +str+:: + # String to extract URIs from. + # +schemes+:: + # Limit Gem::URI matching to specific schemes. + # + # == Description + # + # Extracts URIs from a string. If block given, iterates through all matched URIs. + # Returns nil if block given or array with matches. + # + # == Usage + # + # require "rubygems/vendor/uri/lib/uri" + # + # Gem::URI.extract("text here http://foo.example.org/bla and here mailto:test@example.com and here also.") + # # => ["http://foo.example.com/bla", "mailto:test@example.com"] + # + def self.extract(str, schemes = nil, &block) # :nodoc: + warn "Gem::URI.extract is obsolete", uplevel: 1 if $VERBOSE + DEFAULT_PARSER.extract(str, schemes, &block) + end + + # + # == Synopsis + # + # Gem::URI::regexp([match_schemes]) + # + # == Args + # + # +match_schemes+:: + # Array of schemes. If given, resulting regexp matches to URIs + # whose scheme is one of the match_schemes. + # + # == Description + # + # Returns a Regexp object which matches to Gem::URI-like strings. + # The Regexp object returned by this method includes arbitrary + # number of capture group (parentheses). Never rely on its number. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # # extract first Gem::URI from html_string + # html_string.slice(Gem::URI.regexp) + # + # # remove ftp URIs + # html_string.sub(Gem::URI.regexp(['ftp']), '') + # + # # You should not rely on the number of parentheses + # html_string.scan(Gem::URI.regexp) do |*matches| + # p $& + # end + # + def self.regexp(schemes = nil)# :nodoc: + warn "Gem::URI.regexp is obsolete", uplevel: 1 if $VERBOSE + DEFAULT_PARSER.make_regexp(schemes) + end + + TBLENCWWWCOMP_ = {} # :nodoc: + 256.times do |i| + TBLENCWWWCOMP_[-i.chr] = -('%%%02X' % i) + end + TBLENCURICOMP_ = TBLENCWWWCOMP_.dup.freeze + TBLENCWWWCOMP_[' '] = '+' + TBLENCWWWCOMP_.freeze + TBLDECWWWCOMP_ = {} # :nodoc: + 256.times do |i| + h, l = i>>4, i&15 + TBLDECWWWCOMP_[-('%%%X%X' % [h, l])] = -i.chr + TBLDECWWWCOMP_[-('%%%x%X' % [h, l])] = -i.chr + TBLDECWWWCOMP_[-('%%%X%x' % [h, l])] = -i.chr + TBLDECWWWCOMP_[-('%%%x%x' % [h, l])] = -i.chr + end + TBLDECWWWCOMP_['+'] = ' ' + TBLDECWWWCOMP_.freeze + + # Returns a URL-encoded string derived from the given string +str+. + # + # The returned string: + # + # - Preserves: + # + # - Characters '*', '.', '-', and '_'. + # - Character in ranges 'a'..'z', 'A'..'Z', + # and '0'..'9'. + # + # Example: + # + # Gem::URI.encode_www_form_component('*.-_azAZ09') + # # => "*.-_azAZ09" + # + # - Converts: + # + # - Character ' ' to character '+'. + # - Any other character to "percent notation"; + # the percent notation for character c is '%%%X' % c.ord. + # + # Example: + # + # Gem::URI.encode_www_form_component('Here are some punctuation characters: ,;?:') + # # => "Here+are+some+punctuation+characters%3A+%2C%3B%3F%3A" + # + # Encoding: + # + # - If +str+ has encoding Encoding::ASCII_8BIT, argument +enc+ is ignored. + # - Otherwise +str+ is converted first to Encoding::UTF_8 + # (with suitable character replacements), + # and then to encoding +enc+. + # + # In either case, the returned string has forced encoding Encoding::US_ASCII. + # + # Related: Gem::URI.encode_uri_component (encodes ' ' as '%20'). + def self.encode_www_form_component(str, enc=nil) + _encode_uri_component(/[^*\-.0-9A-Z_a-z]/, TBLENCWWWCOMP_, str, enc) + end + + # Returns a string decoded from the given \URL-encoded string +str+. + # + # The given string is first encoded as Encoding::ASCII-8BIT (using String#b), + # then decoded (as below), and finally force-encoded to the given encoding +enc+. + # + # The returned string: + # + # - Preserves: + # + # - Characters '*', '.', '-', and '_'. + # - Character in ranges 'a'..'z', 'A'..'Z', + # and '0'..'9'. + # + # Example: + # + # Gem::URI.decode_www_form_component('*.-_azAZ09') + # # => "*.-_azAZ09" + # + # - Converts: + # + # - Character '+' to character ' '. + # - Each "percent notation" to an ASCII character. + # + # Example: + # + # Gem::URI.decode_www_form_component('Here+are+some+punctuation+characters%3A+%2C%3B%3F%3A') + # # => "Here are some punctuation characters: ,;?:" + # + # Related: Gem::URI.decode_uri_component (preserves '+'). + def self.decode_www_form_component(str, enc=Encoding::UTF_8) + _decode_uri_component(/\+|%\h\h/, str, enc) + end + + # Like Gem::URI.encode_www_form_component, except that ' ' (space) + # is encoded as '%20' (instead of '+'). + def self.encode_uri_component(str, enc=nil) + _encode_uri_component(/[^*\-.0-9A-Z_a-z]/, TBLENCURICOMP_, str, enc) + end + + # Like Gem::URI.decode_www_form_component, except that '+' is preserved. + def self.decode_uri_component(str, enc=Encoding::UTF_8) + _decode_uri_component(/%\h\h/, str, enc) + end + + def self._encode_uri_component(regexp, table, str, enc) + str = str.to_s.dup + if str.encoding != Encoding::ASCII_8BIT + if enc && enc != Encoding::ASCII_8BIT + str.encode!(Encoding::UTF_8, invalid: :replace, undef: :replace) + str.encode!(enc, fallback: ->(x){"&##{x.ord};"}) + end + str.force_encoding(Encoding::ASCII_8BIT) + end + str.gsub!(regexp, table) + str.force_encoding(Encoding::US_ASCII) + end + private_class_method :_encode_uri_component + + def self._decode_uri_component(regexp, str, enc) + raise ArgumentError, "invalid %-encoding (#{str})" if /%(?!\h\h)/.match?(str) + str.b.gsub(regexp, TBLDECWWWCOMP_).force_encoding(enc) + end + private_class_method :_decode_uri_component + + # Returns a URL-encoded string derived from the given + # {Enumerable}[https://docs.ruby-lang.org/en/master/Enumerable.html#module-Enumerable-label-Enumerable+in+Ruby+Classes] + # +enum+. + # + # The result is suitable for use as form data + # for an \HTTP request whose Content-Type is + # 'application/x-www-form-urlencoded'. + # + # The returned string consists of the elements of +enum+, + # each converted to one or more URL-encoded strings, + # and all joined with character '&'. + # + # Simple examples: + # + # Gem::URI.encode_www_form([['foo', 0], ['bar', 1], ['baz', 2]]) + # # => "foo=0&bar=1&baz=2" + # Gem::URI.encode_www_form({foo: 0, bar: 1, baz: 2}) + # # => "foo=0&bar=1&baz=2" + # + # The returned string is formed using method Gem::URI.encode_www_form_component, + # which converts certain characters: + # + # Gem::URI.encode_www_form('f#o': '/', 'b-r': '$', 'b z': '@') + # # => "f%23o=%2F&b-r=%24&b+z=%40" + # + # When +enum+ is Array-like, each element +ele+ is converted to a field: + # + # - If +ele+ is an array of two or more elements, + # the field is formed from its first two elements + # (and any additional elements are ignored): + # + # name = Gem::URI.encode_www_form_component(ele[0], enc) + # value = Gem::URI.encode_www_form_component(ele[1], enc) + # "#{name}=#{value}" + # + # Examples: + # + # Gem::URI.encode_www_form([%w[foo bar], %w[baz bat bah]]) + # # => "foo=bar&baz=bat" + # Gem::URI.encode_www_form([['foo', 0], ['bar', :baz, 'bat']]) + # # => "foo=0&bar=baz" + # + # - If +ele+ is an array of one element, + # the field is formed from ele[0]: + # + # Gem::URI.encode_www_form_component(ele[0]) + # + # Example: + # + # Gem::URI.encode_www_form([['foo'], [:bar], [0]]) + # # => "foo&bar&0" + # + # - Otherwise the field is formed from +ele+: + # + # Gem::URI.encode_www_form_component(ele) + # + # Example: + # + # Gem::URI.encode_www_form(['foo', :bar, 0]) + # # => "foo&bar&0" + # + # The elements of an Array-like +enum+ may be mixture: + # + # Gem::URI.encode_www_form([['foo', 0], ['bar', 1, 2], ['baz'], :bat]) + # # => "foo=0&bar=1&baz&bat" + # + # When +enum+ is Hash-like, + # each +key+/+value+ pair is converted to one or more fields: + # + # - If +value+ is + # {Array-convertible}[https://docs.ruby-lang.org/en/master/implicit_conversion_rdoc.html#label-Array-Convertible+Objects], + # each element +ele+ in +value+ is paired with +key+ to form a field: + # + # name = Gem::URI.encode_www_form_component(key, enc) + # value = Gem::URI.encode_www_form_component(ele, enc) + # "#{name}=#{value}" + # + # Example: + # + # Gem::URI.encode_www_form({foo: [:bar, 1], baz: [:bat, :bam, 2]}) + # # => "foo=bar&foo=1&baz=bat&baz=bam&baz=2" + # + # - Otherwise, +key+ and +value+ are paired to form a field: + # + # name = Gem::URI.encode_www_form_component(key, enc) + # value = Gem::URI.encode_www_form_component(value, enc) + # "#{name}=#{value}" + # + # Example: + # + # Gem::URI.encode_www_form({foo: 0, bar: 1, baz: 2}) + # # => "foo=0&bar=1&baz=2" + # + # The elements of a Hash-like +enum+ may be mixture: + # + # Gem::URI.encode_www_form({foo: [0, 1], bar: 2}) + # # => "foo=0&foo=1&bar=2" + # + def self.encode_www_form(enum, enc=nil) + enum.map do |k,v| + if v.nil? + encode_www_form_component(k, enc) + elsif v.respond_to?(:to_ary) + v.to_ary.map do |w| + str = encode_www_form_component(k, enc) + unless w.nil? + str << '=' + str << encode_www_form_component(w, enc) + end + end.join('&') + else + str = encode_www_form_component(k, enc) + str << '=' + str << encode_www_form_component(v, enc) + end + end.join('&') + end + + # Returns name/value pairs derived from the given string +str+, + # which must be an ASCII string. + # + # The method may be used to decode the body of Net::HTTPResponse object +res+ + # for which res['Content-Type'] is 'application/x-www-form-urlencoded'. + # + # The returned data is an array of 2-element subarrays; + # each subarray is a name/value pair (both are strings). + # Each returned string has encoding +enc+, + # and has had invalid characters removed via + # {String#scrub}[https://docs.ruby-lang.org/en/master/String.html#method-i-scrub]. + # + # A simple example: + # + # Gem::URI.decode_www_form('foo=0&bar=1&baz') + # # => [["foo", "0"], ["bar", "1"], ["baz", ""]] + # + # The returned strings have certain conversions, + # similar to those performed in Gem::URI.decode_www_form_component: + # + # Gem::URI.decode_www_form('f%23o=%2F&b-r=%24&b+z=%40') + # # => [["f#o", "/"], ["b-r", "$"], ["b z", "@"]] + # + # The given string may contain consecutive separators: + # + # Gem::URI.decode_www_form('foo=0&&bar=1&&baz=2') + # # => [["foo", "0"], ["", ""], ["bar", "1"], ["", ""], ["baz", "2"]] + # + # A different separator may be specified: + # + # Gem::URI.decode_www_form('foo=0--bar=1--baz', separator: '--') + # # => [["foo", "0"], ["bar", "1"], ["baz", ""]] + # + def self.decode_www_form(str, enc=Encoding::UTF_8, separator: '&', use__charset_: false, isindex: false) + raise ArgumentError, "the input of #{self.name}.#{__method__} must be ASCII only string" unless str.ascii_only? + ary = [] + return ary if str.empty? + enc = Encoding.find(enc) + str.b.each_line(separator) do |string| + string.chomp!(separator) + key, sep, val = string.partition('=') + if isindex + if sep.empty? + val = key + key = +'' + end + isindex = false + end + + if use__charset_ and key == '_charset_' and e = get_encoding(val) + enc = e + use__charset_ = false + end + + key.gsub!(/\+|%\h\h/, TBLDECWWWCOMP_) + if val + val.gsub!(/\+|%\h\h/, TBLDECWWWCOMP_) + else + val = +'' + end + + ary << [key, val] + end + ary.each do |k, v| + k.force_encoding(enc) + k.scrub! + v.force_encoding(enc) + v.scrub! + end + ary + end + + private +=begin command for WEB_ENCODINGS_ + curl https://encoding.spec.whatwg.org/encodings.json| + ruby -rjson -e 'H={} + h={ + "shift_jis"=>"Windows-31J", + "euc-jp"=>"cp51932", + "iso-2022-jp"=>"cp50221", + "x-mac-cyrillic"=>"macCyrillic", + } + JSON($<.read).map{|x|x["encodings"]}.flatten.each{|x| + Encoding.find(n=h.fetch(n=x["name"].downcase,n))rescue next + x["labels"].each{|y|H[y]=n} + } + puts "{" + H.each{|k,v|puts %[ #{k.dump}=>#{v.dump},]} + puts "}" +' +=end + WEB_ENCODINGS_ = { + "unicode-1-1-utf-8"=>"utf-8", + "utf-8"=>"utf-8", + "utf8"=>"utf-8", + "866"=>"ibm866", + "cp866"=>"ibm866", + "csibm866"=>"ibm866", + "ibm866"=>"ibm866", + "csisolatin2"=>"iso-8859-2", + "iso-8859-2"=>"iso-8859-2", + "iso-ir-101"=>"iso-8859-2", + "iso8859-2"=>"iso-8859-2", + "iso88592"=>"iso-8859-2", + "iso_8859-2"=>"iso-8859-2", + "iso_8859-2:1987"=>"iso-8859-2", + "l2"=>"iso-8859-2", + "latin2"=>"iso-8859-2", + "csisolatin3"=>"iso-8859-3", + "iso-8859-3"=>"iso-8859-3", + "iso-ir-109"=>"iso-8859-3", + "iso8859-3"=>"iso-8859-3", + "iso88593"=>"iso-8859-3", + "iso_8859-3"=>"iso-8859-3", + "iso_8859-3:1988"=>"iso-8859-3", + "l3"=>"iso-8859-3", + "latin3"=>"iso-8859-3", + "csisolatin4"=>"iso-8859-4", + "iso-8859-4"=>"iso-8859-4", + "iso-ir-110"=>"iso-8859-4", + "iso8859-4"=>"iso-8859-4", + "iso88594"=>"iso-8859-4", + "iso_8859-4"=>"iso-8859-4", + "iso_8859-4:1988"=>"iso-8859-4", + "l4"=>"iso-8859-4", + "latin4"=>"iso-8859-4", + "csisolatincyrillic"=>"iso-8859-5", + "cyrillic"=>"iso-8859-5", + "iso-8859-5"=>"iso-8859-5", + "iso-ir-144"=>"iso-8859-5", + "iso8859-5"=>"iso-8859-5", + "iso88595"=>"iso-8859-5", + "iso_8859-5"=>"iso-8859-5", + "iso_8859-5:1988"=>"iso-8859-5", + "arabic"=>"iso-8859-6", + "asmo-708"=>"iso-8859-6", + "csiso88596e"=>"iso-8859-6", + "csiso88596i"=>"iso-8859-6", + "csisolatinarabic"=>"iso-8859-6", + "ecma-114"=>"iso-8859-6", + "iso-8859-6"=>"iso-8859-6", + "iso-8859-6-e"=>"iso-8859-6", + "iso-8859-6-i"=>"iso-8859-6", + "iso-ir-127"=>"iso-8859-6", + "iso8859-6"=>"iso-8859-6", + "iso88596"=>"iso-8859-6", + "iso_8859-6"=>"iso-8859-6", + "iso_8859-6:1987"=>"iso-8859-6", + "csisolatingreek"=>"iso-8859-7", + "ecma-118"=>"iso-8859-7", + "elot_928"=>"iso-8859-7", + "greek"=>"iso-8859-7", + "greek8"=>"iso-8859-7", + "iso-8859-7"=>"iso-8859-7", + "iso-ir-126"=>"iso-8859-7", + "iso8859-7"=>"iso-8859-7", + "iso88597"=>"iso-8859-7", + "iso_8859-7"=>"iso-8859-7", + "iso_8859-7:1987"=>"iso-8859-7", + "sun_eu_greek"=>"iso-8859-7", + "csiso88598e"=>"iso-8859-8", + "csisolatinhebrew"=>"iso-8859-8", + "hebrew"=>"iso-8859-8", + "iso-8859-8"=>"iso-8859-8", + "iso-8859-8-e"=>"iso-8859-8", + "iso-ir-138"=>"iso-8859-8", + "iso8859-8"=>"iso-8859-8", + "iso88598"=>"iso-8859-8", + "iso_8859-8"=>"iso-8859-8", + "iso_8859-8:1988"=>"iso-8859-8", + "visual"=>"iso-8859-8", + "csisolatin6"=>"iso-8859-10", + "iso-8859-10"=>"iso-8859-10", + "iso-ir-157"=>"iso-8859-10", + "iso8859-10"=>"iso-8859-10", + "iso885910"=>"iso-8859-10", + "l6"=>"iso-8859-10", + "latin6"=>"iso-8859-10", + "iso-8859-13"=>"iso-8859-13", + "iso8859-13"=>"iso-8859-13", + "iso885913"=>"iso-8859-13", + "iso-8859-14"=>"iso-8859-14", + "iso8859-14"=>"iso-8859-14", + "iso885914"=>"iso-8859-14", + "csisolatin9"=>"iso-8859-15", + "iso-8859-15"=>"iso-8859-15", + "iso8859-15"=>"iso-8859-15", + "iso885915"=>"iso-8859-15", + "iso_8859-15"=>"iso-8859-15", + "l9"=>"iso-8859-15", + "iso-8859-16"=>"iso-8859-16", + "cskoi8r"=>"koi8-r", + "koi"=>"koi8-r", + "koi8"=>"koi8-r", + "koi8-r"=>"koi8-r", + "koi8_r"=>"koi8-r", + "koi8-ru"=>"koi8-u", + "koi8-u"=>"koi8-u", + "dos-874"=>"windows-874", + "iso-8859-11"=>"windows-874", + "iso8859-11"=>"windows-874", + "iso885911"=>"windows-874", + "tis-620"=>"windows-874", + "windows-874"=>"windows-874", + "cp1250"=>"windows-1250", + "windows-1250"=>"windows-1250", + "x-cp1250"=>"windows-1250", + "cp1251"=>"windows-1251", + "windows-1251"=>"windows-1251", + "x-cp1251"=>"windows-1251", + "ansi_x3.4-1968"=>"windows-1252", + "ascii"=>"windows-1252", + "cp1252"=>"windows-1252", + "cp819"=>"windows-1252", + "csisolatin1"=>"windows-1252", + "ibm819"=>"windows-1252", + "iso-8859-1"=>"windows-1252", + "iso-ir-100"=>"windows-1252", + "iso8859-1"=>"windows-1252", + "iso88591"=>"windows-1252", + "iso_8859-1"=>"windows-1252", + "iso_8859-1:1987"=>"windows-1252", + "l1"=>"windows-1252", + "latin1"=>"windows-1252", + "us-ascii"=>"windows-1252", + "windows-1252"=>"windows-1252", + "x-cp1252"=>"windows-1252", + "cp1253"=>"windows-1253", + "windows-1253"=>"windows-1253", + "x-cp1253"=>"windows-1253", + "cp1254"=>"windows-1254", + "csisolatin5"=>"windows-1254", + "iso-8859-9"=>"windows-1254", + "iso-ir-148"=>"windows-1254", + "iso8859-9"=>"windows-1254", + "iso88599"=>"windows-1254", + "iso_8859-9"=>"windows-1254", + "iso_8859-9:1989"=>"windows-1254", + "l5"=>"windows-1254", + "latin5"=>"windows-1254", + "windows-1254"=>"windows-1254", + "x-cp1254"=>"windows-1254", + "cp1255"=>"windows-1255", + "windows-1255"=>"windows-1255", + "x-cp1255"=>"windows-1255", + "cp1256"=>"windows-1256", + "windows-1256"=>"windows-1256", + "x-cp1256"=>"windows-1256", + "cp1257"=>"windows-1257", + "windows-1257"=>"windows-1257", + "x-cp1257"=>"windows-1257", + "cp1258"=>"windows-1258", + "windows-1258"=>"windows-1258", + "x-cp1258"=>"windows-1258", + "x-mac-cyrillic"=>"macCyrillic", + "x-mac-ukrainian"=>"macCyrillic", + "chinese"=>"gbk", + "csgb2312"=>"gbk", + "csiso58gb231280"=>"gbk", + "gb2312"=>"gbk", + "gb_2312"=>"gbk", + "gb_2312-80"=>"gbk", + "gbk"=>"gbk", + "iso-ir-58"=>"gbk", + "x-gbk"=>"gbk", + "gb18030"=>"gb18030", + "big5"=>"big5", + "big5-hkscs"=>"big5", + "cn-big5"=>"big5", + "csbig5"=>"big5", + "x-x-big5"=>"big5", + "cseucpkdfmtjapanese"=>"cp51932", + "euc-jp"=>"cp51932", + "x-euc-jp"=>"cp51932", + "csiso2022jp"=>"cp50221", + "iso-2022-jp"=>"cp50221", + "csshiftjis"=>"Windows-31J", + "ms932"=>"Windows-31J", + "ms_kanji"=>"Windows-31J", + "shift-jis"=>"Windows-31J", + "shift_jis"=>"Windows-31J", + "sjis"=>"Windows-31J", + "windows-31j"=>"Windows-31J", + "x-sjis"=>"Windows-31J", + "cseuckr"=>"euc-kr", + "csksc56011987"=>"euc-kr", + "euc-kr"=>"euc-kr", + "iso-ir-149"=>"euc-kr", + "korean"=>"euc-kr", + "ks_c_5601-1987"=>"euc-kr", + "ks_c_5601-1989"=>"euc-kr", + "ksc5601"=>"euc-kr", + "ksc_5601"=>"euc-kr", + "windows-949"=>"euc-kr", + "utf-16be"=>"utf-16be", + "utf-16"=>"utf-16le", + "utf-16le"=>"utf-16le", + } # :nodoc: + Ractor.make_shareable(WEB_ENCODINGS_) if defined?(Ractor) + + # :nodoc: + # return encoding or nil + # http://encoding.spec.whatwg.org/#concept-encoding-get + def self.get_encoding(label) + Encoding.find(WEB_ENCODINGS_[label.to_str.strip.downcase]) rescue nil + end +end # module Gem::URI + +module Gem + + # + # Returns a \Gem::URI object derived from the given +uri+, + # which may be a \Gem::URI string or an existing \Gem::URI object: + # + # # Returns a new Gem::URI. + # uri = Gem::URI('http://github.com/ruby/ruby') + # # => # + # # Returns the given Gem::URI. + # Gem::URI(uri) + # # => # + # + def URI(uri) + if uri.is_a?(Gem::URI::Generic) + uri + elsif uri = String.try_convert(uri) + Gem::URI.parse(uri) + else + raise ArgumentError, + "bad argument (expected Gem::URI object or Gem::URI string)" + end + end + module_function :URI +end diff --git a/lib/rubygems/vendor/uri/lib/uri/file.rb b/lib/rubygems/vendor/uri/lib/uri/file.rb new file mode 100644 index 00000000000000..d419b26055798a --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/file.rb @@ -0,0 +1,100 @@ +# frozen_string_literal: true + +require_relative 'generic' + +module Gem::URI + + # + # The "file" Gem::URI is defined by RFC8089. + # + class File < Generic + # A Default port of nil for Gem::URI::File. + DEFAULT_PORT = nil + + # + # An Array of the available components for Gem::URI::File. + # + COMPONENT = [ + :scheme, + :host, + :path + ].freeze + + # + # == Description + # + # Creates a new Gem::URI::File object from components, with syntax checking. + # + # The components accepted are +host+ and +path+. + # + # The components should be provided either as an Array, or as a Hash + # with keys formed by preceding the component names with a colon. + # + # If an Array is used, the components must be passed in the + # order [host, path]. + # + # A path from e.g. the File class should be escaped before + # being passed. + # + # Examples: + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri1 = Gem::URI::File.build(['host.example.com', '/path/file.zip']) + # uri1.to_s # => "file://host.example.com/path/file.zip" + # + # uri2 = Gem::URI::File.build({:host => 'host.example.com', + # :path => '/ruby/src'}) + # uri2.to_s # => "file://host.example.com/ruby/src" + # + # uri3 = Gem::URI::File.build({:path => Gem::URI::escape('/path/my file.txt')}) + # uri3.to_s # => "file:///path/my%20file.txt" + # + def self.build(args) + tmp = Util::make_components_hash(self, args) + super(tmp) + end + + # Protected setter for the host component +v+. + # + # See also Gem::URI::Generic.host=. + # + def set_host(v) + v = "" if v.nil? || v == "localhost" + @host = v + end + + # do nothing + def set_port(v) + end + + # raise InvalidURIError + def check_userinfo(user) + raise Gem::URI::InvalidURIError, "can not set userinfo for file Gem::URI" + end + + # raise InvalidURIError + def check_user(user) + raise Gem::URI::InvalidURIError, "can not set user for file Gem::URI" + end + + # raise InvalidURIError + def check_password(user) + raise Gem::URI::InvalidURIError, "can not set password for file Gem::URI" + end + + # do nothing + def set_userinfo(v) + end + + # do nothing + def set_user(v) + end + + # do nothing + def set_password(v) + end + end + + register_scheme 'FILE', File +end diff --git a/lib/rubygems/vendor/uri/lib/uri/ftp.rb b/lib/rubygems/vendor/uri/lib/uri/ftp.rb new file mode 100644 index 00000000000000..100498ffb24036 --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/ftp.rb @@ -0,0 +1,267 @@ +# frozen_string_literal: false +# = uri/ftp.rb +# +# Author:: Akira Yamada +# License:: You can redistribute it and/or modify it under the same term as Ruby. +# +# See Gem::URI for general documentation +# + +require_relative 'generic' + +module Gem::URI + + # + # FTP Gem::URI syntax is defined by RFC1738 section 3.2. + # + # This class will be redesigned because of difference of implementations; + # the structure of its path. draft-hoffman-ftp-uri-04 is a draft but it + # is a good summary about the de facto spec. + # http://tools.ietf.org/html/draft-hoffman-ftp-uri-04 + # + class FTP < Generic + # A Default port of 21 for Gem::URI::FTP. + DEFAULT_PORT = 21 + + # + # An Array of the available components for Gem::URI::FTP. + # + COMPONENT = [ + :scheme, + :userinfo, :host, :port, + :path, :typecode + ].freeze + + # + # Typecode is "a", "i", or "d". + # + # * "a" indicates a text file (the FTP command was ASCII) + # * "i" indicates a binary file (FTP command IMAGE) + # * "d" indicates the contents of a directory should be displayed + # + TYPECODE = ['a', 'i', 'd'].freeze + + # Typecode prefix ";type=". + TYPECODE_PREFIX = ';type='.freeze + + def self.new2(user, password, host, port, path, + typecode = nil, arg_check = true) # :nodoc: + # Do not use this method! Not tested. [Bug #7301] + # This methods remains just for compatibility, + # Keep it undocumented until the active maintainer is assigned. + typecode = nil if typecode.size == 0 + if typecode && !TYPECODE.include?(typecode) + raise ArgumentError, + "bad typecode is specified: #{typecode}" + end + + # do escape + + self.new('ftp', + [user, password], + host, port, nil, + typecode ? path + TYPECODE_PREFIX + typecode : path, + nil, nil, nil, arg_check) + end + + # + # == Description + # + # Creates a new Gem::URI::FTP object from components, with syntax checking. + # + # The components accepted are +userinfo+, +host+, +port+, +path+, and + # +typecode+. + # + # The components should be provided either as an Array, or as a Hash + # with keys formed by preceding the component names with a colon. + # + # If an Array is used, the components must be passed in the + # order [userinfo, host, port, path, typecode]. + # + # If the path supplied is absolute, it will be escaped in order to + # make it absolute in the Gem::URI. + # + # Examples: + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri1 = Gem::URI::FTP.build(['user:password', 'ftp.example.com', nil, + # '/path/file.zip', 'i']) + # uri1.to_s # => "ftp://user:password@ftp.example.com/%2Fpath/file.zip;type=i" + # + # uri2 = Gem::URI::FTP.build({:host => 'ftp.example.com', + # :path => 'ruby/src'}) + # uri2.to_s # => "ftp://ftp.example.com/ruby/src" + # + def self.build(args) + + # Fix the incoming path to be generic URL syntax + # FTP path -> URL path + # foo/bar /foo/bar + # /foo/bar /%2Ffoo/bar + # + if args.kind_of?(Array) + args[3] = '/' + args[3].sub(/^\//, '%2F') + else + args[:path] = '/' + args[:path].sub(/^\//, '%2F') + end + + tmp = Util::make_components_hash(self, args) + + if tmp[:typecode] + if tmp[:typecode].size == 1 + tmp[:typecode] = TYPECODE_PREFIX + tmp[:typecode] + end + tmp[:path] << tmp[:typecode] + end + + return super(tmp) + end + + # + # == Description + # + # Creates a new Gem::URI::FTP object from generic URL components with no + # syntax checking. + # + # Unlike build(), this method does not escape the path component as + # required by RFC1738; instead it is treated as per RFC2396. + # + # Arguments are +scheme+, +userinfo+, +host+, +port+, +registry+, +path+, + # +opaque+, +query+, and +fragment+, in that order. + # + def initialize(scheme, + userinfo, host, port, registry, + path, opaque, + query, + fragment, + parser = nil, + arg_check = false) + raise InvalidURIError unless path + path = path.sub(/^\//,'') + path.sub!(/^%2F/,'/') + super(scheme, userinfo, host, port, registry, path, opaque, + query, fragment, parser, arg_check) + @typecode = nil + if tmp = @path.index(TYPECODE_PREFIX) + typecode = @path[tmp + TYPECODE_PREFIX.size..-1] + @path = @path[0..tmp - 1] + + if arg_check + self.typecode = typecode + else + self.set_typecode(typecode) + end + end + end + + # typecode accessor. + # + # See Gem::URI::FTP::COMPONENT. + attr_reader :typecode + + # Validates typecode +v+, + # returns +true+ or +false+. + # + def check_typecode(v) + if TYPECODE.include?(v) + return true + else + raise InvalidComponentError, + "bad typecode(expected #{TYPECODE.join(', ')}): #{v}" + end + end + private :check_typecode + + # Private setter for the typecode +v+. + # + # See also Gem::URI::FTP.typecode=. + # + def set_typecode(v) + @typecode = v + end + protected :set_typecode + + # + # == Args + # + # +v+:: + # String + # + # == Description + # + # Public setter for the typecode +v+ + # (with validation). + # + # See also Gem::URI::FTP.check_typecode. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("ftp://john@ftp.example.com/my_file.img") + # #=> # + # uri.typecode = "i" + # uri + # #=> # + # + def typecode=(typecode) + check_typecode(typecode) + set_typecode(typecode) + typecode + end + + def merge(oth) # :nodoc: + tmp = super(oth) + if self != tmp + tmp.set_typecode(oth.typecode) + end + + return tmp + end + + # Returns the path from an FTP Gem::URI. + # + # RFC 1738 specifically states that the path for an FTP Gem::URI does not + # include the / which separates the Gem::URI path from the Gem::URI host. Example: + # + # ftp://ftp.example.com/pub/ruby + # + # The above Gem::URI indicates that the client should connect to + # ftp.example.com then cd to pub/ruby from the initial login directory. + # + # If you want to cd to an absolute directory, you must include an + # escaped / (%2F) in the path. Example: + # + # ftp://ftp.example.com/%2Fpub/ruby + # + # This method will then return "/pub/ruby". + # + def path + return @path.sub(/^\//,'').sub(/^%2F/,'/') + end + + # Private setter for the path of the Gem::URI::FTP. + def set_path(v) + super("/" + v.sub(/^\//, "%2F")) + end + protected :set_path + + # Returns a String representation of the Gem::URI::FTP. + def to_s + save_path = nil + if @typecode + save_path = @path + @path = @path + TYPECODE_PREFIX + @typecode + end + str = super + if @typecode + @path = save_path + end + + return str + end + end + + register_scheme 'FTP', FTP +end diff --git a/lib/rubygems/vendor/uri/lib/uri/generic.rb b/lib/rubygems/vendor/uri/lib/uri/generic.rb new file mode 100644 index 00000000000000..72c52aa8eed60c --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/generic.rb @@ -0,0 +1,1588 @@ +# frozen_string_literal: true + +# = uri/generic.rb +# +# Author:: Akira Yamada +# License:: You can redistribute it and/or modify it under the same term as Ruby. +# +# See Gem::URI for general documentation +# + +require_relative 'common' +autoload :IPSocket, 'socket' +autoload :IPAddr, 'ipaddr' + +module Gem::URI + + # + # Base class for all Gem::URI classes. + # Implements generic Gem::URI syntax as per RFC 2396. + # + class Generic + include Gem::URI + + # + # A Default port of nil for Gem::URI::Generic. + # + DEFAULT_PORT = nil + + # + # Returns default port. + # + def self.default_port + self::DEFAULT_PORT + end + + # + # Returns default port. + # + def default_port + self.class.default_port + end + + # + # An Array of the available components for Gem::URI::Generic. + # + COMPONENT = [ + :scheme, + :userinfo, :host, :port, :registry, + :path, :opaque, + :query, + :fragment + ].freeze + + # + # Components of the Gem::URI in the order. + # + def self.component + self::COMPONENT + end + + USE_REGISTRY = false # :nodoc: + + def self.use_registry # :nodoc: + self::USE_REGISTRY + end + + # + # == Synopsis + # + # See ::new. + # + # == Description + # + # At first, tries to create a new Gem::URI::Generic instance using + # Gem::URI::Generic::build. But, if exception Gem::URI::InvalidComponentError is raised, + # then it does Gem::URI::Escape.escape all Gem::URI components and tries again. + # + def self.build2(args) + begin + return self.build(args) + rescue InvalidComponentError + if args.kind_of?(Array) + return self.build(args.collect{|x| + if x.is_a?(String) + DEFAULT_PARSER.escape(x) + else + x + end + }) + elsif args.kind_of?(Hash) + tmp = {} + args.each do |key, value| + tmp[key] = if value + DEFAULT_PARSER.escape(value) + else + value + end + end + return self.build(tmp) + end + end + end + + # + # == Synopsis + # + # See ::new. + # + # == Description + # + # Creates a new Gem::URI::Generic instance from components of Gem::URI::Generic + # with check. Components are: scheme, userinfo, host, port, registry, path, + # opaque, query, and fragment. You can provide arguments either by an Array or a Hash. + # See ::new for hash keys to use or for order of array items. + # + def self.build(args) + if args.kind_of?(Array) && + args.size == ::Gem::URI::Generic::COMPONENT.size + tmp = args.dup + elsif args.kind_of?(Hash) + tmp = ::Gem::URI::Generic::COMPONENT.collect do |c| + if args.include?(c) + args[c] + else + nil + end + end + else + component = self.class.component rescue ::Gem::URI::Generic::COMPONENT + raise ArgumentError, + "expected Array of or Hash of components of #{self.class} (#{component.join(', ')})" + end + + tmp << nil + tmp << true + return self.new(*tmp) + end + + # + # == Args + # + # +scheme+:: + # Protocol scheme, i.e. 'http','ftp','mailto' and so on. + # +userinfo+:: + # User name and password, i.e. 'sdmitry:bla'. + # +host+:: + # Server host name. + # +port+:: + # Server port. + # +registry+:: + # Registry of naming authorities. + # +path+:: + # Path on server. + # +opaque+:: + # Opaque part. + # +query+:: + # Query data. + # +fragment+:: + # Part of the Gem::URI after '#' character. + # +parser+:: + # Parser for internal use [Gem::URI::DEFAULT_PARSER by default]. + # +arg_check+:: + # Check arguments [false by default]. + # + # == Description + # + # Creates a new Gem::URI::Generic instance from ``generic'' components without check. + # + def initialize(scheme, + userinfo, host, port, registry, + path, opaque, + query, + fragment, + parser = DEFAULT_PARSER, + arg_check = false) + @scheme = nil + @user = nil + @password = nil + @host = nil + @port = nil + @path = nil + @query = nil + @opaque = nil + @fragment = nil + @parser = parser == DEFAULT_PARSER ? nil : parser + + if arg_check + self.scheme = scheme + self.userinfo = userinfo + self.hostname = host + self.port = port + self.path = path + self.query = query + self.opaque = opaque + self.fragment = fragment + else + self.set_scheme(scheme) + self.set_userinfo(userinfo) + self.set_host(host) + self.set_port(port) + self.set_path(path) + self.query = query + self.set_opaque(opaque) + self.fragment=(fragment) + end + if registry + raise InvalidURIError, + "the scheme #{@scheme} does not accept registry part: #{registry} (or bad hostname?)" + end + + @scheme&.freeze + self.set_path('') if !@path && !@opaque # (see RFC2396 Section 5.2) + self.set_port(self.default_port) if self.default_port && !@port + end + + # + # Returns the scheme component of the Gem::URI. + # + # Gem::URI("http://foo/bar/baz").scheme #=> "http" + # + attr_reader :scheme + + # Returns the host component of the Gem::URI. + # + # Gem::URI("http://foo/bar/baz").host #=> "foo" + # + # It returns nil if no host component exists. + # + # Gem::URI("mailto:foo@example.org").host #=> nil + # + # The component does not contain the port number. + # + # Gem::URI("http://foo:8080/bar/baz").host #=> "foo" + # + # Since IPv6 addresses are wrapped with brackets in URIs, + # this method returns IPv6 addresses wrapped with brackets. + # This form is not appropriate to pass to socket methods such as TCPSocket.open. + # If unwrapped host names are required, use the #hostname method. + # + # Gem::URI("http://[::1]/bar/baz").host #=> "[::1]" + # Gem::URI("http://[::1]/bar/baz").hostname #=> "::1" + # + attr_reader :host + + # Returns the port component of the Gem::URI. + # + # Gem::URI("http://foo/bar/baz").port #=> 80 + # Gem::URI("http://foo:8080/bar/baz").port #=> 8080 + # + attr_reader :port + + def registry # :nodoc: + nil + end + + # Returns the path component of the Gem::URI. + # + # Gem::URI("http://foo/bar/baz").path #=> "/bar/baz" + # + attr_reader :path + + # Returns the query component of the Gem::URI. + # + # Gem::URI("http://foo/bar/baz?search=FooBar").query #=> "search=FooBar" + # + attr_reader :query + + # Returns the opaque part of the Gem::URI. + # + # Gem::URI("mailto:foo@example.org").opaque #=> "foo@example.org" + # Gem::URI("http://foo/bar/baz").opaque #=> nil + # + # The portion of the path that does not make use of the slash '/'. + # The path typically refers to an absolute path or an opaque part. + # (See RFC2396 Section 3 and 5.2.) + # + attr_reader :opaque + + # Returns the fragment component of the Gem::URI. + # + # Gem::URI("http://foo/bar/baz?search=FooBar#ponies").fragment #=> "ponies" + # + attr_reader :fragment + + # Returns the parser to be used. + # + # Unless a Gem::URI::Parser is defined, DEFAULT_PARSER is used. + # + def parser + if !defined?(@parser) || !@parser + DEFAULT_PARSER + else + @parser || DEFAULT_PARSER + end + end + + # Replaces self by other Gem::URI object. + # + def replace!(oth) + if self.class != oth.class + raise ArgumentError, "expected #{self.class} object" + end + + component.each do |c| + self.__send__("#{c}=", oth.__send__(c)) + end + end + private :replace! + + # + # Components of the Gem::URI in the order. + # + def component + self.class.component + end + + # + # Checks the scheme +v+ component against the Gem::URI::Parser Regexp for :SCHEME. + # + def check_scheme(v) + if v && parser.regexp[:SCHEME] !~ v + raise InvalidComponentError, + "bad component(expected scheme component): #{v}" + end + + return true + end + private :check_scheme + + # Protected setter for the scheme component +v+. + # + # See also Gem::URI::Generic.scheme=. + # + def set_scheme(v) + @scheme = v&.downcase + end + protected :set_scheme + + # + # == Args + # + # +v+:: + # String + # + # == Description + # + # Public setter for the scheme component +v+ + # (with validation). + # + # See also Gem::URI::Generic.check_scheme. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("http://my.example.com") + # uri.scheme = "https" + # uri.to_s #=> "https://my.example.com" + # + def scheme=(v) + check_scheme(v) + set_scheme(v) + v + end + + # + # Checks the +user+ and +password+. + # + # If +password+ is not provided, then +user+ is + # split, using Gem::URI::Generic.split_userinfo, to + # pull +user+ and +password. + # + # See also Gem::URI::Generic.check_user, Gem::URI::Generic.check_password. + # + def check_userinfo(user, password = nil) + if !password + user, password = split_userinfo(user) + end + check_user(user) + check_password(password, user) + + return true + end + private :check_userinfo + + # + # Checks the user +v+ component for RFC2396 compliance + # and against the Gem::URI::Parser Regexp for :USERINFO. + # + # Can not have a registry or opaque component defined, + # with a user component defined. + # + def check_user(v) + if @opaque + raise InvalidURIError, + "can not set user with opaque" + end + + return v unless v + + if parser.regexp[:USERINFO] !~ v + raise InvalidComponentError, + "bad component(expected userinfo component or user component): #{v}" + end + + return true + end + private :check_user + + # + # Checks the password +v+ component for RFC2396 compliance + # and against the Gem::URI::Parser Regexp for :USERINFO. + # + # Can not have a registry or opaque component defined, + # with a user component defined. + # + def check_password(v, user = @user) + if @opaque + raise InvalidURIError, + "can not set password with opaque" + end + return v unless v + + if !user + raise InvalidURIError, + "password component depends user component" + end + + if parser.regexp[:USERINFO] !~ v + raise InvalidComponentError, + "bad password component" + end + + return true + end + private :check_password + + # + # Sets userinfo, argument is string like 'name:pass'. + # + def userinfo=(userinfo) + if userinfo.nil? + return nil + end + check_userinfo(*userinfo) + set_userinfo(*userinfo) + # returns userinfo + end + + # + # == Args + # + # +v+:: + # String + # + # == Description + # + # Public setter for the +user+ component + # (with validation). + # + # See also Gem::URI::Generic.check_user. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("http://john:S3nsit1ve@my.example.com") + # uri.user = "sam" + # uri.to_s #=> "http://sam:V3ry_S3nsit1ve@my.example.com" + # + def user=(user) + check_user(user) + set_user(user) + # returns user + end + + # + # == Args + # + # +v+:: + # String + # + # == Description + # + # Public setter for the +password+ component + # (with validation). + # + # See also Gem::URI::Generic.check_password. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("http://john:S3nsit1ve@my.example.com") + # uri.password = "V3ry_S3nsit1ve" + # uri.to_s #=> "http://john:V3ry_S3nsit1ve@my.example.com" + # + def password=(password) + check_password(password) + set_password(password) + # returns password + end + + # Protected setter for the +user+ component, and +password+ if available + # (with validation). + # + # See also Gem::URI::Generic.userinfo=. + # + def set_userinfo(user, password = nil) + unless password + user, password = split_userinfo(user) + end + @user = user + @password = password if password + + [@user, @password] + end + protected :set_userinfo + + # Protected setter for the user component +v+. + # + # See also Gem::URI::Generic.user=. + # + def set_user(v) + set_userinfo(v, @password) + v + end + protected :set_user + + # Protected setter for the password component +v+. + # + # See also Gem::URI::Generic.password=. + # + def set_password(v) + @password = v + # returns v + end + protected :set_password + + # Returns the userinfo +ui+ as [user, password] + # if properly formatted as 'user:password'. + def split_userinfo(ui) + return nil, nil unless ui + user, password = ui.split(':', 2) + + return user, password + end + private :split_userinfo + + # Escapes 'user:password' +v+ based on RFC 1738 section 3.1. + def escape_userpass(v) + parser.escape(v, /[@:\/]/o) # RFC 1738 section 3.1 #/ + end + private :escape_userpass + + # Returns the userinfo, either as 'user' or 'user:password'. + def userinfo + if @user.nil? + nil + elsif @password.nil? + @user + else + @user + ':' + @password + end + end + + # Returns the user component (without Gem::URI decoding). + def user + @user + end + + # Returns the password component (without Gem::URI decoding). + def password + @password + end + + # Returns the user component after Gem::URI decoding. + def decoded_user + Gem::URI.decode_uri_component(@user) if @user + end + + # Returns the password component after Gem::URI decoding. + def decoded_password + Gem::URI.decode_uri_component(@password) if @password + end + + # + # Checks the host +v+ component for RFC2396 compliance + # and against the Gem::URI::Parser Regexp for :HOST. + # + # Can not have a registry or opaque component defined, + # with a host component defined. + # + def check_host(v) + return v unless v + + if @opaque + raise InvalidURIError, + "can not set host with registry or opaque" + elsif parser.regexp[:HOST] !~ v + raise InvalidComponentError, + "bad component(expected host component): #{v}" + end + + return true + end + private :check_host + + # Protected setter for the host component +v+. + # + # See also Gem::URI::Generic.host=. + # + def set_host(v) + @host = v + end + protected :set_host + + # + # == Args + # + # +v+:: + # String + # + # == Description + # + # Public setter for the host component +v+ + # (with validation). + # + # See also Gem::URI::Generic.check_host. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("http://my.example.com") + # uri.host = "foo.com" + # uri.to_s #=> "http://foo.com" + # + def host=(v) + check_host(v) + set_host(v) + v + end + + # Extract the host part of the Gem::URI and unwrap brackets for IPv6 addresses. + # + # This method is the same as Gem::URI::Generic#host except + # brackets for IPv6 (and future IP) addresses are removed. + # + # uri = Gem::URI("http://[::1]/bar") + # uri.hostname #=> "::1" + # uri.host #=> "[::1]" + # + def hostname + v = self.host + v&.start_with?('[') && v.end_with?(']') ? v[1..-2] : v + end + + # Sets the host part of the Gem::URI as the argument with brackets for IPv6 addresses. + # + # This method is the same as Gem::URI::Generic#host= except + # the argument can be a bare IPv6 address. + # + # uri = Gem::URI("http://foo/bar") + # uri.hostname = "::1" + # uri.to_s #=> "http://[::1]/bar" + # + # If the argument seems to be an IPv6 address, + # it is wrapped with brackets. + # + def hostname=(v) + v = "[#{v}]" if !(v&.start_with?('[') && v&.end_with?(']')) && v&.index(':') + self.host = v + end + + # + # Checks the port +v+ component for RFC2396 compliance + # and against the Gem::URI::Parser Regexp for :PORT. + # + # Can not have a registry or opaque component defined, + # with a port component defined. + # + def check_port(v) + return v unless v + + if @opaque + raise InvalidURIError, + "can not set port with registry or opaque" + elsif !v.kind_of?(Integer) && parser.regexp[:PORT] !~ v + raise InvalidComponentError, + "bad component(expected port component): #{v.inspect}" + end + + return true + end + private :check_port + + # Protected setter for the port component +v+. + # + # See also Gem::URI::Generic.port=. + # + def set_port(v) + v = v.empty? ? nil : v.to_i unless !v || v.kind_of?(Integer) + @port = v + end + protected :set_port + + # + # == Args + # + # +v+:: + # String + # + # == Description + # + # Public setter for the port component +v+ + # (with validation). + # + # See also Gem::URI::Generic.check_port. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("http://my.example.com") + # uri.port = 8080 + # uri.to_s #=> "http://my.example.com:8080" + # + def port=(v) + check_port(v) + set_port(v) + port + end + + def check_registry(v) # :nodoc: + raise InvalidURIError, "can not set registry" + end + private :check_registry + + def set_registry(v) #:nodoc: + raise InvalidURIError, "can not set registry" + end + protected :set_registry + + def registry=(v) + raise InvalidURIError, "can not set registry" + end + + # + # Checks the path +v+ component for RFC2396 compliance + # and against the Gem::URI::Parser Regexp + # for :ABS_PATH and :REL_PATH. + # + # Can not have a opaque component defined, + # with a path component defined. + # + def check_path(v) + # raise if both hier and opaque are not nil, because: + # absoluteURI = scheme ":" ( hier_part | opaque_part ) + # hier_part = ( net_path | abs_path ) [ "?" query ] + if v && @opaque + raise InvalidURIError, + "path conflicts with opaque" + end + + # If scheme is ftp, path may be relative. + # See RFC 1738 section 3.2.2, and RFC 2396. + if @scheme && @scheme != "ftp" + if v && v != '' && parser.regexp[:ABS_PATH] !~ v + raise InvalidComponentError, + "bad component(expected absolute path component): #{v}" + end + else + if v && v != '' && parser.regexp[:ABS_PATH] !~ v && + parser.regexp[:REL_PATH] !~ v + raise InvalidComponentError, + "bad component(expected relative path component): #{v}" + end + end + + return true + end + private :check_path + + # Protected setter for the path component +v+. + # + # See also Gem::URI::Generic.path=. + # + def set_path(v) + @path = v + end + protected :set_path + + # + # == Args + # + # +v+:: + # String + # + # == Description + # + # Public setter for the path component +v+ + # (with validation). + # + # See also Gem::URI::Generic.check_path. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("http://my.example.com/pub/files") + # uri.path = "/faq/" + # uri.to_s #=> "http://my.example.com/faq/" + # + def path=(v) + check_path(v) + set_path(v) + v + end + + # + # == Args + # + # +v+:: + # String + # + # == Description + # + # Public setter for the query component +v+. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("http://my.example.com/?id=25") + # uri.query = "id=1" + # uri.to_s #=> "http://my.example.com/?id=1" + # + def query=(v) + return @query = nil unless v + raise InvalidURIError, "query conflicts with opaque" if @opaque + + x = v.to_str + v = x.dup if x.equal? v + v.encode!(Encoding::UTF_8) rescue nil + v.delete!("\t\r\n") + v.force_encoding(Encoding::ASCII_8BIT) + raise InvalidURIError, "invalid percent escape: #{$1}" if /(%\H\H)/n.match(v) + v.gsub!(/(?!%\h\h|[!$-&(-;=?-_a-~])./n.freeze){'%%%02X' % $&.ord} + v.force_encoding(Encoding::US_ASCII) + @query = v + end + + # + # Checks the opaque +v+ component for RFC2396 compliance and + # against the Gem::URI::Parser Regexp for :OPAQUE. + # + # Can not have a host, port, user, or path component defined, + # with an opaque component defined. + # + def check_opaque(v) + return v unless v + + # raise if both hier and opaque are not nil, because: + # absoluteURI = scheme ":" ( hier_part | opaque_part ) + # hier_part = ( net_path | abs_path ) [ "?" query ] + if @host || @port || @user || @path # userinfo = @user + ':' + @password + raise InvalidURIError, + "can not set opaque with host, port, userinfo or path" + elsif v && parser.regexp[:OPAQUE] !~ v + raise InvalidComponentError, + "bad component(expected opaque component): #{v}" + end + + return true + end + private :check_opaque + + # Protected setter for the opaque component +v+. + # + # See also Gem::URI::Generic.opaque=. + # + def set_opaque(v) + @opaque = v + end + protected :set_opaque + + # + # == Args + # + # +v+:: + # String + # + # == Description + # + # Public setter for the opaque component +v+ + # (with validation). + # + # See also Gem::URI::Generic.check_opaque. + # + def opaque=(v) + check_opaque(v) + set_opaque(v) + v + end + + # + # Checks the fragment +v+ component against the Gem::URI::Parser Regexp for :FRAGMENT. + # + # + # == Args + # + # +v+:: + # String + # + # == Description + # + # Public setter for the fragment component +v+ + # (with validation). + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("http://my.example.com/?id=25#time=1305212049") + # uri.fragment = "time=1305212086" + # uri.to_s #=> "http://my.example.com/?id=25#time=1305212086" + # + def fragment=(v) + return @fragment = nil unless v + + x = v.to_str + v = x.dup if x.equal? v + v.encode!(Encoding::UTF_8) rescue nil + v.delete!("\t\r\n") + v.force_encoding(Encoding::ASCII_8BIT) + v.gsub!(/(?!%\h\h|[!-~])./n){'%%%02X' % $&.ord} + v.force_encoding(Encoding::US_ASCII) + @fragment = v + end + + # + # Returns true if Gem::URI is hierarchical. + # + # == Description + # + # Gem::URI has components listed in order of decreasing significance from left to right, + # see RFC3986 https://tools.ietf.org/html/rfc3986 1.2.3. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("http://my.example.com/") + # uri.hierarchical? + # #=> true + # uri = Gem::URI.parse("mailto:joe@example.com") + # uri.hierarchical? + # #=> false + # + def hierarchical? + if @path + true + else + false + end + end + + # + # Returns true if Gem::URI has a scheme (e.g. http:// or https://) specified. + # + def absolute? + if @scheme + true + else + false + end + end + alias absolute absolute? + + # + # Returns true if Gem::URI does not have a scheme (e.g. http:// or https://) specified. + # + def relative? + !absolute? + end + + # + # Returns an Array of the path split on '/'. + # + def split_path(path) + path.split("/", -1) + end + private :split_path + + # + # Merges a base path +base+, with relative path +rel+, + # returns a modified base path. + # + def merge_path(base, rel) + + # RFC2396, Section 5.2, 5) + # RFC2396, Section 5.2, 6) + base_path = split_path(base) + rel_path = split_path(rel) + + # RFC2396, Section 5.2, 6), a) + base_path << '' if base_path.last == '..' + while i = base_path.index('..') + base_path.slice!(i - 1, 2) + end + + if (first = rel_path.first) and first.empty? + base_path.clear + rel_path.shift + end + + # RFC2396, Section 5.2, 6), c) + # RFC2396, Section 5.2, 6), d) + rel_path.push('') if rel_path.last == '.' || rel_path.last == '..' + rel_path.delete('.') + + # RFC2396, Section 5.2, 6), e) + tmp = [] + rel_path.each do |x| + if x == '..' && + !(tmp.empty? || tmp.last == '..') + tmp.pop + else + tmp << x + end + end + + add_trailer_slash = !tmp.empty? + if base_path.empty? + base_path = [''] # keep '/' for root directory + elsif add_trailer_slash + base_path.pop + end + while x = tmp.shift + if x == '..' + # RFC2396, Section 4 + # a .. or . in an absolute path has no special meaning + base_path.pop if base_path.size > 1 + else + # if x == '..' + # valid absolute (but abnormal) path "/../..." + # else + # valid absolute path + # end + base_path << x + tmp.each {|t| base_path << t} + add_trailer_slash = false + break + end + end + base_path.push('') if add_trailer_slash + + return base_path.join('/') + end + private :merge_path + + # + # == Args + # + # +oth+:: + # Gem::URI or String + # + # == Description + # + # Destructive form of #merge. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("http://my.example.com") + # uri.merge!("/main.rbx?page=1") + # uri.to_s # => "http://my.example.com/main.rbx?page=1" + # + def merge!(oth) + t = merge(oth) + if self == t + nil + else + replace!(t) + self + end + end + + # + # == Args + # + # +oth+:: + # Gem::URI or String + # + # == Description + # + # Merges two URIs. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("http://my.example.com") + # uri.merge("/main.rbx?page=1") + # # => "http://my.example.com/main.rbx?page=1" + # + def merge(oth) + rel = parser.__send__(:convert_to_uri, oth) + + if rel.absolute? + #raise BadURIError, "both Gem::URI are absolute" if absolute? + # hmm... should return oth for usability? + return rel + end + + unless self.absolute? + raise BadURIError, "both Gem::URI are relative" + end + + base = self.dup + + authority = rel.userinfo || rel.host || rel.port + + # RFC2396, Section 5.2, 2) + if (rel.path.nil? || rel.path.empty?) && !authority && !rel.query + base.fragment=(rel.fragment) if rel.fragment + return base + end + + base.query = nil + base.fragment=(nil) + + # RFC2396, Section 5.2, 4) + if !authority + base.set_path(merge_path(base.path, rel.path)) if base.path && rel.path + else + # RFC2396, Section 5.2, 4) + base.set_path(rel.path) if rel.path + end + + # RFC2396, Section 5.2, 7) + base.set_userinfo(rel.userinfo) if rel.userinfo + base.set_host(rel.host) if rel.host + base.set_port(rel.port) if rel.port + base.query = rel.query if rel.query + base.fragment=(rel.fragment) if rel.fragment + + return base + end # merge + alias + merge + + # :stopdoc: + def route_from_path(src, dst) + case dst + when src + # RFC2396, Section 4.2 + return '' + when %r{(?:\A|/)\.\.?(?:/|\z)} + # dst has abnormal absolute path, + # like "/./", "/../", "/x/../", ... + return dst.dup + end + + src_path = src.scan(%r{[^/]*/}) + dst_path = dst.scan(%r{[^/]*/?}) + + # discard same parts + while !dst_path.empty? && dst_path.first == src_path.first + src_path.shift + dst_path.shift + end + + tmp = dst_path.join + + # calculate + if src_path.empty? + if tmp.empty? + return './' + elsif dst_path.first.include?(':') # (see RFC2396 Section 5) + return './' + tmp + else + return tmp + end + end + + return '../' * src_path.size + tmp + end + private :route_from_path + # :startdoc: + + # :stopdoc: + def route_from0(oth) + oth = parser.__send__(:convert_to_uri, oth) + if self.relative? + raise BadURIError, + "relative Gem::URI: #{self}" + end + if oth.relative? + raise BadURIError, + "relative Gem::URI: #{oth}" + end + + if self.scheme != oth.scheme + return self, self.dup + end + rel = Gem::URI::Generic.new(nil, # it is relative Gem::URI + self.userinfo, self.host, self.port, + nil, self.path, self.opaque, + self.query, self.fragment, parser) + + if rel.userinfo != oth.userinfo || + rel.host.to_s.downcase != oth.host.to_s.downcase || + rel.port != oth.port + + if self.userinfo.nil? && self.host.nil? + return self, self.dup + end + + rel.set_port(nil) if rel.port == oth.default_port + return rel, rel + end + rel.set_userinfo(nil) + rel.set_host(nil) + rel.set_port(nil) + + if rel.path && rel.path == oth.path + rel.set_path('') + rel.query = nil if rel.query == oth.query + return rel, rel + elsif rel.opaque && rel.opaque == oth.opaque + rel.set_opaque('') + rel.query = nil if rel.query == oth.query + return rel, rel + end + + # you can modify `rel', but can not `oth'. + return oth, rel + end + private :route_from0 + # :startdoc: + + # + # == Args + # + # +oth+:: + # Gem::URI or String + # + # == Description + # + # Calculates relative path from oth to self. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse('http://my.example.com/main.rbx?page=1') + # uri.route_from('http://my.example.com') + # #=> # + # + def route_from(oth) + # you can modify `rel', but can not `oth'. + begin + oth, rel = route_from0(oth) + rescue + raise $!.class, $!.message + end + if oth == rel + return rel + end + + rel.set_path(route_from_path(oth.path, self.path)) + if rel.path == './' && self.query + # "./?foo" -> "?foo" + rel.set_path('') + end + + return rel + end + + alias - route_from + + # + # == Args + # + # +oth+:: + # Gem::URI or String + # + # == Description + # + # Calculates relative path to oth from self. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse('http://my.example.com') + # uri.route_to('http://my.example.com/main.rbx?page=1') + # #=> # + # + def route_to(oth) + parser.__send__(:convert_to_uri, oth).route_from(self) + end + + # + # Returns normalized Gem::URI. + # + # require 'rubygems/vendor/uri/lib/uri' + # + # Gem::URI("HTTP://my.EXAMPLE.com").normalize + # #=> # + # + # Normalization here means: + # + # * scheme and host are converted to lowercase, + # * an empty path component is set to "/". + # + def normalize + uri = dup + uri.normalize! + uri + end + + # + # Destructive version of #normalize. + # + def normalize! + if path&.empty? + set_path('/') + end + if scheme && scheme != scheme.downcase + set_scheme(self.scheme.downcase) + end + if host && host != host.downcase + set_host(self.host.downcase) + end + end + + # + # Constructs String from Gem::URI. + # + def to_s + str = ''.dup + if @scheme + str << @scheme + str << ':' + end + + if @opaque + str << @opaque + else + if @host || %w[file postgres].include?(@scheme) + str << '//' + end + if self.userinfo + str << self.userinfo + str << '@' + end + if @host + str << @host + end + if @port && @port != self.default_port + str << ':' + str << @port.to_s + end + str << @path + if @query + str << '?' + str << @query + end + end + if @fragment + str << '#' + str << @fragment + end + str + end + alias to_str to_s + + # + # Compares two URIs. + # + def ==(oth) + if self.class == oth.class + self.normalize.component_ary == oth.normalize.component_ary + else + false + end + end + + def hash + self.component_ary.hash + end + + def eql?(oth) + self.class == oth.class && + parser == oth.parser && + self.component_ary.eql?(oth.component_ary) + end + +=begin + +--- Gem::URI::Generic#===(oth) + +=end +# def ===(oth) +# raise NotImplementedError +# end + +=begin +=end + + + # Returns an Array of the components defined from the COMPONENT Array. + def component_ary + component.collect do |x| + self.__send__(x) + end + end + protected :component_ary + + # == Args + # + # +components+:: + # Multiple Symbol arguments defined in Gem::URI::HTTP. + # + # == Description + # + # Selects specified components from Gem::URI. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse('http://myuser:mypass@my.example.com/test.rbx') + # uri.select(:userinfo, :host, :path) + # # => ["myuser:mypass", "my.example.com", "/test.rbx"] + # + def select(*components) + components.collect do |c| + if component.include?(c) + self.__send__(c) + else + raise ArgumentError, + "expected of components of #{self.class} (#{self.class.component.join(', ')})" + end + end + end + + def inspect + "#<#{self.class} #{self}>" + end + + # + # == Args + # + # +v+:: + # Gem::URI or String + # + # == Description + # + # Attempts to parse other Gem::URI +oth+, + # returns [parsed_oth, self]. + # + # == Usage + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("http://my.example.com") + # uri.coerce("http://foo.com") + # #=> [#, #] + # + def coerce(oth) + case oth + when String + oth = parser.parse(oth) + else + super + end + + return oth, self + end + + # Returns a proxy Gem::URI. + # The proxy Gem::URI is obtained from environment variables such as http_proxy, + # ftp_proxy, no_proxy, etc. + # If there is no proper proxy, nil is returned. + # + # If the optional parameter +env+ is specified, it is used instead of ENV. + # + # Note that capitalized variables (HTTP_PROXY, FTP_PROXY, NO_PROXY, etc.) + # are examined, too. + # + # But http_proxy and HTTP_PROXY is treated specially under CGI environment. + # It's because HTTP_PROXY may be set by Proxy: header. + # So HTTP_PROXY is not used. + # http_proxy is not used too if the variable is case insensitive. + # CGI_HTTP_PROXY can be used instead. + def find_proxy(env=ENV) + raise BadURIError, "relative Gem::URI: #{self}" if self.relative? + name = self.scheme.downcase + '_proxy' + proxy_uri = nil + if name == 'http_proxy' && env.include?('REQUEST_METHOD') # CGI? + # HTTP_PROXY conflicts with *_proxy for proxy settings and + # HTTP_* for header information in CGI. + # So it should be careful to use it. + pairs = env.reject {|k, v| /\Ahttp_proxy\z/i !~ k } + case pairs.length + when 0 # no proxy setting anyway. + proxy_uri = nil + when 1 + k, _ = pairs.shift + if k == 'http_proxy' && env[k.upcase] == nil + # http_proxy is safe to use because ENV is case sensitive. + proxy_uri = env[name] + else + proxy_uri = nil + end + else # http_proxy is safe to use because ENV is case sensitive. + proxy_uri = env.to_hash[name] + end + if !proxy_uri + # Use CGI_HTTP_PROXY. cf. libwww-perl. + proxy_uri = env["CGI_#{name.upcase}"] + end + elsif name == 'http_proxy' + if RUBY_ENGINE == 'jruby' && p_addr = ENV_JAVA['http.proxyHost'] + p_port = ENV_JAVA['http.proxyPort'] + if p_user = ENV_JAVA['http.proxyUser'] + p_pass = ENV_JAVA['http.proxyPass'] + proxy_uri = "http://#{p_user}:#{p_pass}@#{p_addr}:#{p_port}" + else + proxy_uri = "http://#{p_addr}:#{p_port}" + end + else + unless proxy_uri = env[name] + if proxy_uri = env[name.upcase] + warn 'The environment variable HTTP_PROXY is discouraged. Use http_proxy.', uplevel: 1 + end + end + end + else + proxy_uri = env[name] || env[name.upcase] + end + + if proxy_uri.nil? || proxy_uri.empty? + return nil + end + + if self.hostname + begin + addr = IPSocket.getaddress(self.hostname) + return nil if /\A127\.|\A::1\z/ =~ addr + rescue SocketError + end + end + + name = 'no_proxy' + if no_proxy = env[name] || env[name.upcase] + return nil unless Gem::URI::Generic.use_proxy?(self.hostname, addr, self.port, no_proxy) + end + Gem::URI.parse(proxy_uri) + end + + def self.use_proxy?(hostname, addr, port, no_proxy) # :nodoc: + hostname = hostname.downcase + dothostname = ".#{hostname}" + no_proxy.scan(/([^:,\s]+)(?::(\d+))?/) {|p_host, p_port| + if !p_port || port == p_port.to_i + if p_host.start_with?('.') + return false if hostname.end_with?(p_host.downcase) + else + return false if dothostname.end_with?(".#{p_host.downcase}") + end + if addr + begin + return false if IPAddr.new(p_host).include?(addr) + rescue IPAddr::InvalidAddressError + next + end + end + end + } + true + end + end +end diff --git a/lib/rubygems/vendor/uri/lib/uri/http.rb b/lib/rubygems/vendor/uri/lib/uri/http.rb new file mode 100644 index 00000000000000..bef43490a3f6cd --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/http.rb @@ -0,0 +1,125 @@ +# frozen_string_literal: false +# = uri/http.rb +# +# Author:: Akira Yamada +# License:: You can redistribute it and/or modify it under the same term as Ruby. +# +# See Gem::URI for general documentation +# + +require_relative 'generic' + +module Gem::URI + + # + # The syntax of HTTP URIs is defined in RFC1738 section 3.3. + # + # Note that the Ruby Gem::URI library allows HTTP URLs containing usernames and + # passwords. This is not legal as per the RFC, but used to be + # supported in Internet Explorer 5 and 6, before the MS04-004 security + # update. See . + # + class HTTP < Generic + # A Default port of 80 for Gem::URI::HTTP. + DEFAULT_PORT = 80 + + # An Array of the available components for Gem::URI::HTTP. + COMPONENT = %i[ + scheme + userinfo host port + path + query + fragment + ].freeze + + # + # == Description + # + # Creates a new Gem::URI::HTTP object from components, with syntax checking. + # + # The components accepted are userinfo, host, port, path, query, and + # fragment. + # + # The components should be provided either as an Array, or as a Hash + # with keys formed by preceding the component names with a colon. + # + # If an Array is used, the components must be passed in the + # order [userinfo, host, port, path, query, fragment]. + # + # Example: + # + # uri = Gem::URI::HTTP.build(host: 'www.example.com', path: '/foo/bar') + # + # uri = Gem::URI::HTTP.build([nil, "www.example.com", nil, "/path", + # "query", 'fragment']) + # + # Currently, if passed userinfo components this method generates + # invalid HTTP URIs as per RFC 1738. + # + def self.build(args) + tmp = Util.make_components_hash(self, args) + super(tmp) + end + + # + # == Description + # + # Returns the full path for an HTTP request, as required by Net::HTTP::Get. + # + # If the Gem::URI contains a query, the full path is Gem::URI#path + '?' + Gem::URI#query. + # Otherwise, the path is simply Gem::URI#path. + # + # Example: + # + # uri = Gem::URI::HTTP.build(path: '/foo/bar', query: 'test=true') + # uri.request_uri # => "/foo/bar?test=true" + # + def request_uri + return unless @path + + url = @query ? "#@path?#@query" : @path.dup + url.start_with?(?/.freeze) ? url : ?/ + url + end + + # + # == Description + # + # Returns the authority for an HTTP uri, as defined in + # https://datatracker.ietf.org/doc/html/rfc3986/#section-3.2. + # + # + # Example: + # + # Gem::URI::HTTP.build(host: 'www.example.com', path: '/foo/bar').authority #=> "www.example.com" + # Gem::URI::HTTP.build(host: 'www.example.com', port: 8000, path: '/foo/bar').authority #=> "www.example.com:8000" + # Gem::URI::HTTP.build(host: 'www.example.com', port: 80, path: '/foo/bar').authority #=> "www.example.com" + # + def authority + if port == default_port + host + else + "#{host}:#{port}" + end + end + + # + # == Description + # + # Returns the origin for an HTTP uri, as defined in + # https://datatracker.ietf.org/doc/html/rfc6454. + # + # + # Example: + # + # Gem::URI::HTTP.build(host: 'www.example.com', path: '/foo/bar').origin #=> "http://www.example.com" + # Gem::URI::HTTP.build(host: 'www.example.com', port: 8000, path: '/foo/bar').origin #=> "http://www.example.com:8000" + # Gem::URI::HTTP.build(host: 'www.example.com', port: 80, path: '/foo/bar').origin #=> "http://www.example.com" + # Gem::URI::HTTPS.build(host: 'www.example.com', path: '/foo/bar').origin #=> "https://www.example.com" + # + def origin + "#{scheme}://#{authority}" + end + end + + register_scheme 'HTTP', HTTP +end diff --git a/lib/rubygems/vendor/uri/lib/uri/https.rb b/lib/rubygems/vendor/uri/lib/uri/https.rb new file mode 100644 index 00000000000000..6e8e732e1d2a49 --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/https.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: false +# = uri/https.rb +# +# Author:: Akira Yamada +# License:: You can redistribute it and/or modify it under the same term as Ruby. +# +# See Gem::URI for general documentation +# + +require_relative 'http' + +module Gem::URI + + # The default port for HTTPS URIs is 443, and the scheme is 'https:' rather + # than 'http:'. Other than that, HTTPS URIs are identical to HTTP URIs; + # see Gem::URI::HTTP. + class HTTPS < HTTP + # A Default port of 443 for Gem::URI::HTTPS + DEFAULT_PORT = 443 + end + + register_scheme 'HTTPS', HTTPS +end diff --git a/lib/rubygems/vendor/uri/lib/uri/ldap.rb b/lib/rubygems/vendor/uri/lib/uri/ldap.rb new file mode 100644 index 00000000000000..1a08b5ab7ee8e6 --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/ldap.rb @@ -0,0 +1,261 @@ +# frozen_string_literal: false +# = uri/ldap.rb +# +# Author:: +# Takaaki Tateishi +# Akira Yamada +# License:: +# Gem::URI::LDAP is copyrighted free software by Takaaki Tateishi and Akira Yamada. +# You can redistribute it and/or modify it under the same term as Ruby. +# +# See Gem::URI for general documentation +# + +require_relative 'generic' + +module Gem::URI + + # + # LDAP Gem::URI SCHEMA (described in RFC2255). + #-- + # ldap:///[?[?[?[?]]]] + #++ + class LDAP < Generic + + # A Default port of 389 for Gem::URI::LDAP. + DEFAULT_PORT = 389 + + # An Array of the available components for Gem::URI::LDAP. + COMPONENT = [ + :scheme, + :host, :port, + :dn, + :attributes, + :scope, + :filter, + :extensions, + ].freeze + + # Scopes available for the starting point. + # + # * SCOPE_BASE - the Base DN + # * SCOPE_ONE - one level under the Base DN, not including the base DN and + # not including any entries under this + # * SCOPE_SUB - subtrees, all entries at all levels + # + SCOPE = [ + SCOPE_ONE = 'one', + SCOPE_SUB = 'sub', + SCOPE_BASE = 'base', + ].freeze + + # + # == Description + # + # Creates a new Gem::URI::LDAP object from components, with syntax checking. + # + # The components accepted are host, port, dn, attributes, + # scope, filter, and extensions. + # + # The components should be provided either as an Array, or as a Hash + # with keys formed by preceding the component names with a colon. + # + # If an Array is used, the components must be passed in the + # order [host, port, dn, attributes, scope, filter, extensions]. + # + # Example: + # + # uri = Gem::URI::LDAP.build({:host => 'ldap.example.com', + # :dn => '/dc=example'}) + # + # uri = Gem::URI::LDAP.build(["ldap.example.com", nil, + # "/dc=example;dc=com", "query", nil, nil, nil]) + # + def self.build(args) + tmp = Util::make_components_hash(self, args) + + if tmp[:dn] + tmp[:path] = tmp[:dn] + end + + query = [] + [:extensions, :filter, :scope, :attributes].collect do |x| + next if !tmp[x] && query.size == 0 + query.unshift(tmp[x]) + end + + tmp[:query] = query.join('?') + + return super(tmp) + end + + # + # == Description + # + # Creates a new Gem::URI::LDAP object from generic Gem::URI components as per + # RFC 2396. No LDAP-specific syntax checking is performed. + # + # Arguments are +scheme+, +userinfo+, +host+, +port+, +registry+, +path+, + # +opaque+, +query+, and +fragment+, in that order. + # + # Example: + # + # uri = Gem::URI::LDAP.new("ldap", nil, "ldap.example.com", nil, nil, + # "/dc=example;dc=com", nil, "query", nil) + # + # See also Gem::URI::Generic.new. + # + def initialize(*arg) + super(*arg) + + if @fragment + raise InvalidURIError, 'bad LDAP URL' + end + + parse_dn + parse_query + end + + # Private method to cleanup +dn+ from using the +path+ component attribute. + def parse_dn + raise InvalidURIError, 'bad LDAP URL' unless @path + @dn = @path[1..-1] + end + private :parse_dn + + # Private method to cleanup +attributes+, +scope+, +filter+, and +extensions+ + # from using the +query+ component attribute. + def parse_query + @attributes = nil + @scope = nil + @filter = nil + @extensions = nil + + if @query + attrs, scope, filter, extensions = @query.split('?') + + @attributes = attrs if attrs && attrs.size > 0 + @scope = scope if scope && scope.size > 0 + @filter = filter if filter && filter.size > 0 + @extensions = extensions if extensions && extensions.size > 0 + end + end + private :parse_query + + # Private method to assemble +query+ from +attributes+, +scope+, +filter+, and +extensions+. + def build_path_query + @path = '/' + @dn + + query = [] + [@extensions, @filter, @scope, @attributes].each do |x| + next if !x && query.size == 0 + query.unshift(x) + end + @query = query.join('?') + end + private :build_path_query + + # Returns dn. + def dn + @dn + end + + # Private setter for dn +val+. + def set_dn(val) + @dn = val + build_path_query + @dn + end + protected :set_dn + + # Setter for dn +val+. + def dn=(val) + set_dn(val) + val + end + + # Returns attributes. + def attributes + @attributes + end + + # Private setter for attributes +val+. + def set_attributes(val) + @attributes = val + build_path_query + @attributes + end + protected :set_attributes + + # Setter for attributes +val+. + def attributes=(val) + set_attributes(val) + val + end + + # Returns scope. + def scope + @scope + end + + # Private setter for scope +val+. + def set_scope(val) + @scope = val + build_path_query + @scope + end + protected :set_scope + + # Setter for scope +val+. + def scope=(val) + set_scope(val) + val + end + + # Returns filter. + def filter + @filter + end + + # Private setter for filter +val+. + def set_filter(val) + @filter = val + build_path_query + @filter + end + protected :set_filter + + # Setter for filter +val+. + def filter=(val) + set_filter(val) + val + end + + # Returns extensions. + def extensions + @extensions + end + + # Private setter for extensions +val+. + def set_extensions(val) + @extensions = val + build_path_query + @extensions + end + protected :set_extensions + + # Setter for extensions +val+. + def extensions=(val) + set_extensions(val) + val + end + + # Checks if Gem::URI has a path. + # For Gem::URI::LDAP this will return +false+. + def hierarchical? + false + end + end + + register_scheme 'LDAP', LDAP +end diff --git a/lib/rubygems/vendor/uri/lib/uri/ldaps.rb b/lib/rubygems/vendor/uri/lib/uri/ldaps.rb new file mode 100644 index 00000000000000..b7a5b50e27198e --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/ldaps.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: false +# = uri/ldap.rb +# +# License:: You can redistribute it and/or modify it under the same term as Ruby. +# +# See Gem::URI for general documentation +# + +require_relative 'ldap' + +module Gem::URI + + # The default port for LDAPS URIs is 636, and the scheme is 'ldaps:' rather + # than 'ldap:'. Other than that, LDAPS URIs are identical to LDAP URIs; + # see Gem::URI::LDAP. + class LDAPS < LDAP + # A Default port of 636 for Gem::URI::LDAPS + DEFAULT_PORT = 636 + end + + register_scheme 'LDAPS', LDAPS +end diff --git a/lib/rubygems/vendor/uri/lib/uri/mailto.rb b/lib/rubygems/vendor/uri/lib/uri/mailto.rb new file mode 100644 index 00000000000000..7ae544d194f0de --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/mailto.rb @@ -0,0 +1,293 @@ +# frozen_string_literal: false +# = uri/mailto.rb +# +# Author:: Akira Yamada +# License:: You can redistribute it and/or modify it under the same term as Ruby. +# +# See Gem::URI for general documentation +# + +require_relative 'generic' + +module Gem::URI + + # + # RFC6068, the mailto URL scheme. + # + class MailTo < Generic + include RFC2396_REGEXP + + # A Default port of nil for Gem::URI::MailTo. + DEFAULT_PORT = nil + + # An Array of the available components for Gem::URI::MailTo. + COMPONENT = [ :scheme, :to, :headers ].freeze + + # :stopdoc: + # "hname" and "hvalue" are encodings of an RFC 822 header name and + # value, respectively. As with "to", all URL reserved characters must + # be encoded. + # + # "#mailbox" is as specified in RFC 822 [RFC822]. This means that it + # consists of zero or more comma-separated mail addresses, possibly + # including "phrase" and "comment" components. Note that all URL + # reserved characters in "to" must be encoded: in particular, + # parentheses, commas, and the percent sign ("%"), which commonly occur + # in the "mailbox" syntax. + # + # Within mailto URLs, the characters "?", "=", "&" are reserved. + + # ; RFC 6068 + # hfields = "?" hfield *( "&" hfield ) + # hfield = hfname "=" hfvalue + # hfname = *qchar + # hfvalue = *qchar + # qchar = unreserved / pct-encoded / some-delims + # some-delims = "!" / "$" / "'" / "(" / ")" / "*" + # / "+" / "," / ";" / ":" / "@" + # + # ; RFC3986 + # unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + # pct-encoded = "%" HEXDIG HEXDIG + HEADER_REGEXP = /\A(?(?:%\h\h|[!$'-.0-;@-Z_a-z~])*=(?:%\h\h|[!$'-.0-;@-Z_a-z~])*)(?:&\g)*\z/ + # practical regexp for email address + # https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address + EMAIL_REGEXP = /\A[a-zA-Z0-9.!\#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\z/ + # :startdoc: + + # + # == Description + # + # Creates a new Gem::URI::MailTo object from components, with syntax checking. + # + # Components can be provided as an Array or Hash. If an Array is used, + # the components must be supplied as [to, headers]. + # + # If a Hash is used, the keys are the component names preceded by colons. + # + # The headers can be supplied as a pre-encoded string, such as + # "subject=subscribe&cc=address", or as an Array of Arrays + # like [['subject', 'subscribe'], ['cc', 'address']]. + # + # Examples: + # + # require 'rubygems/vendor/uri/lib/uri' + # + # m1 = Gem::URI::MailTo.build(['joe@example.com', 'subject=Ruby']) + # m1.to_s # => "mailto:joe@example.com?subject=Ruby" + # + # m2 = Gem::URI::MailTo.build(['john@example.com', [['Subject', 'Ruby'], ['Cc', 'jack@example.com']]]) + # m2.to_s # => "mailto:john@example.com?Subject=Ruby&Cc=jack@example.com" + # + # m3 = Gem::URI::MailTo.build({:to => 'listman@example.com', :headers => [['subject', 'subscribe']]}) + # m3.to_s # => "mailto:listman@example.com?subject=subscribe" + # + def self.build(args) + tmp = Util.make_components_hash(self, args) + + case tmp[:to] + when Array + tmp[:opaque] = tmp[:to].join(',') + when String + tmp[:opaque] = tmp[:to].dup + else + tmp[:opaque] = '' + end + + if tmp[:headers] + query = + case tmp[:headers] + when Array + tmp[:headers].collect { |x| + if x.kind_of?(Array) + x[0] + '=' + x[1..-1].join + else + x.to_s + end + }.join('&') + when Hash + tmp[:headers].collect { |h,v| + h + '=' + v + }.join('&') + else + tmp[:headers].to_s + end + unless query.empty? + tmp[:opaque] << '?' << query + end + end + + super(tmp) + end + + # + # == Description + # + # Creates a new Gem::URI::MailTo object from generic URL components with + # no syntax checking. + # + # This method is usually called from Gem::URI::parse, which checks + # the validity of each component. + # + def initialize(*arg) + super(*arg) + + @to = nil + @headers = [] + + # The RFC3986 parser does not normally populate opaque + @opaque = "?#{@query}" if @query && !@opaque + + unless @opaque + raise InvalidComponentError, + "missing opaque part for mailto URL" + end + to, header = @opaque.split('?', 2) + # allow semicolon as a addr-spec separator + # http://support.microsoft.com/kb/820868 + unless /\A(?:[^@,;]+@[^@,;]+(?:\z|[,;]))*\z/ =~ to + raise InvalidComponentError, + "unrecognised opaque part for mailtoURL: #{@opaque}" + end + + if arg[10] # arg_check + self.to = to + self.headers = header + else + set_to(to) + set_headers(header) + end + end + + # The primary e-mail address of the URL, as a String. + attr_reader :to + + # E-mail headers set by the URL, as an Array of Arrays. + attr_reader :headers + + # Checks the to +v+ component. + def check_to(v) + return true unless v + return true if v.size == 0 + + v.split(/[,;]/).each do |addr| + # check url safety as path-rootless + if /\A(?:%\h\h|[!$&-.0-;=@-Z_a-z~])*\z/ !~ addr + raise InvalidComponentError, + "an address in 'to' is invalid as Gem::URI #{addr.dump}" + end + + # check addr-spec + # don't s/\+/ /g + addr.gsub!(/%\h\h/, Gem::URI::TBLDECWWWCOMP_) + if EMAIL_REGEXP !~ addr + raise InvalidComponentError, + "an address in 'to' is invalid as uri-escaped addr-spec #{addr.dump}" + end + end + + true + end + private :check_to + + # Private setter for to +v+. + def set_to(v) + @to = v + end + protected :set_to + + # Setter for to +v+. + def to=(v) + check_to(v) + set_to(v) + v + end + + # Checks the headers +v+ component against either + # * HEADER_REGEXP + def check_headers(v) + return true unless v + return true if v.size == 0 + if HEADER_REGEXP !~ v + raise InvalidComponentError, + "bad component(expected opaque component): #{v}" + end + + true + end + private :check_headers + + # Private setter for headers +v+. + def set_headers(v) + @headers = [] + if v + v.split('&').each do |x| + @headers << x.split(/=/, 2) + end + end + end + protected :set_headers + + # Setter for headers +v+. + def headers=(v) + check_headers(v) + set_headers(v) + v + end + + # Constructs String from Gem::URI. + def to_s + @scheme + ':' + + if @to + @to + else + '' + end + + if @headers.size > 0 + '?' + @headers.collect{|x| x.join('=')}.join('&') + else + '' + end + + if @fragment + '#' + @fragment + else + '' + end + end + + # Returns the RFC822 e-mail text equivalent of the URL, as a String. + # + # Example: + # + # require 'rubygems/vendor/uri/lib/uri' + # + # uri = Gem::URI.parse("mailto:ruby-list@ruby-lang.org?Subject=subscribe&cc=myaddr") + # uri.to_mailtext + # # => "To: ruby-list@ruby-lang.org\nSubject: subscribe\nCc: myaddr\n\n\n" + # + def to_mailtext + to = Gem::URI.decode_www_form_component(@to) + head = '' + body = '' + @headers.each do |x| + case x[0] + when 'body' + body = Gem::URI.decode_www_form_component(x[1]) + when 'to' + to << ', ' + Gem::URI.decode_www_form_component(x[1]) + else + head << Gem::URI.decode_www_form_component(x[0]).capitalize + ': ' + + Gem::URI.decode_www_form_component(x[1]) + "\n" + end + end + + "To: #{to} +#{head} +#{body} +" + end + alias to_rfc822text to_mailtext + end + + register_scheme 'MAILTO', MailTo +end diff --git a/lib/rubygems/vendor/uri/lib/uri/rfc2396_parser.rb b/lib/rubygems/vendor/uri/lib/uri/rfc2396_parser.rb new file mode 100644 index 00000000000000..735a269f2c3391 --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/rfc2396_parser.rb @@ -0,0 +1,539 @@ +# frozen_string_literal: false +#-- +# = uri/common.rb +# +# Author:: Akira Yamada +# License:: +# You can redistribute it and/or modify it under the same term as Ruby. +# +# See Gem::URI for general documentation +# + +module Gem::URI + # + # Includes Gem::URI::REGEXP::PATTERN + # + module RFC2396_REGEXP + # + # Patterns used to parse Gem::URI's + # + module PATTERN + # :stopdoc: + + # RFC 2396 (Gem::URI Generic Syntax) + # RFC 2732 (IPv6 Literal Addresses in URL's) + # RFC 2373 (IPv6 Addressing Architecture) + + # alpha = lowalpha | upalpha + ALPHA = "a-zA-Z" + # alphanum = alpha | digit + ALNUM = "#{ALPHA}\\d" + + # hex = digit | "A" | "B" | "C" | "D" | "E" | "F" | + # "a" | "b" | "c" | "d" | "e" | "f" + HEX = "a-fA-F\\d" + # escaped = "%" hex hex + ESCAPED = "%[#{HEX}]{2}" + # mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | + # "(" | ")" + # unreserved = alphanum | mark + UNRESERVED = "\\-_.!~*'()#{ALNUM}" + # reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | + # "$" | "," + # reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | + # "$" | "," | "[" | "]" (RFC 2732) + RESERVED = ";/?:@&=+$,\\[\\]" + + # domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum + DOMLABEL = "(?:[#{ALNUM}](?:[-#{ALNUM}]*[#{ALNUM}])?)" + # toplabel = alpha | alpha *( alphanum | "-" ) alphanum + TOPLABEL = "(?:[#{ALPHA}](?:[-#{ALNUM}]*[#{ALNUM}])?)" + # hostname = *( domainlabel "." ) toplabel [ "." ] + HOSTNAME = "(?:#{DOMLABEL}\\.)*#{TOPLABEL}\\.?" + + # :startdoc: + end # PATTERN + + # :startdoc: + end # REGEXP + + # Class that parses String's into Gem::URI's. + # + # It contains a Hash set of patterns and Regexp's that match and validate. + # + class RFC2396_Parser + include RFC2396_REGEXP + + # + # == Synopsis + # + # Gem::URI::Parser.new([opts]) + # + # == Args + # + # The constructor accepts a hash as options for parser. + # Keys of options are pattern names of Gem::URI components + # and values of options are pattern strings. + # The constructor generates set of regexps for parsing URIs. + # + # You can use the following keys: + # + # * :ESCAPED (Gem::URI::PATTERN::ESCAPED in default) + # * :UNRESERVED (Gem::URI::PATTERN::UNRESERVED in default) + # * :DOMLABEL (Gem::URI::PATTERN::DOMLABEL in default) + # * :TOPLABEL (Gem::URI::PATTERN::TOPLABEL in default) + # * :HOSTNAME (Gem::URI::PATTERN::HOSTNAME in default) + # + # == Examples + # + # p = Gem::URI::Parser.new(:ESCAPED => "(?:%[a-fA-F0-9]{2}|%u[a-fA-F0-9]{4})") + # u = p.parse("http://example.jp/%uABCD") #=> # + # Gem::URI.parse(u.to_s) #=> raises Gem::URI::InvalidURIError + # + # s = "http://example.com/ABCD" + # u1 = p.parse(s) #=> # + # u2 = Gem::URI.parse(s) #=> # + # u1 == u2 #=> true + # u1.eql?(u2) #=> false + # + def initialize(opts = {}) + @pattern = initialize_pattern(opts) + @pattern.each_value(&:freeze) + @pattern.freeze + + @regexp = initialize_regexp(@pattern) + @regexp.each_value(&:freeze) + @regexp.freeze + end + + # The Hash of patterns. + # + # See also Gem::URI::Parser.initialize_pattern. + attr_reader :pattern + + # The Hash of Regexp. + # + # See also Gem::URI::Parser.initialize_regexp. + attr_reader :regexp + + # Returns a split Gem::URI against +regexp[:ABS_URI]+. + def split(uri) + case uri + when '' + # null uri + + when @regexp[:ABS_URI] + scheme, opaque, userinfo, host, port, + registry, path, query, fragment = $~[1..-1] + + # Gem::URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] + + # absoluteURI = scheme ":" ( hier_part | opaque_part ) + # hier_part = ( net_path | abs_path ) [ "?" query ] + # opaque_part = uric_no_slash *uric + + # abs_path = "/" path_segments + # net_path = "//" authority [ abs_path ] + + # authority = server | reg_name + # server = [ [ userinfo "@" ] hostport ] + + if !scheme + raise InvalidURIError, + "bad Gem::URI(absolute but no scheme): #{uri}" + end + if !opaque && (!path && (!host && !registry)) + raise InvalidURIError, + "bad Gem::URI(absolute but no path): #{uri}" + end + + when @regexp[:REL_URI] + scheme = nil + opaque = nil + + userinfo, host, port, registry, + rel_segment, abs_path, query, fragment = $~[1..-1] + if rel_segment && abs_path + path = rel_segment + abs_path + elsif rel_segment + path = rel_segment + elsif abs_path + path = abs_path + end + + # Gem::URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] + + # relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ] + + # net_path = "//" authority [ abs_path ] + # abs_path = "/" path_segments + # rel_path = rel_segment [ abs_path ] + + # authority = server | reg_name + # server = [ [ userinfo "@" ] hostport ] + + else + raise InvalidURIError, "bad Gem::URI(is not Gem::URI?): #{uri}" + end + + path = '' if !path && !opaque # (see RFC2396 Section 5.2) + ret = [ + scheme, + userinfo, host, port, # X + registry, # X + path, # Y + opaque, # Y + query, + fragment + ] + return ret + end + + # + # == Args + # + # +uri+:: + # String + # + # == Description + # + # Parses +uri+ and constructs either matching Gem::URI scheme object + # (File, FTP, HTTP, HTTPS, LDAP, LDAPS, or MailTo) or Gem::URI::Generic. + # + # == Usage + # + # p = Gem::URI::Parser.new + # p.parse("ldap://ldap.example.com/dc=example?user=john") + # #=> # + # + def parse(uri) + Gem::URI.for(*self.split(uri), self) + end + + # + # == Args + # + # +uris+:: + # an Array of Strings + # + # == Description + # + # Attempts to parse and merge a set of URIs. + # + def join(*uris) + uris[0] = convert_to_uri(uris[0]) + uris.inject :merge + end + + # + # :call-seq: + # extract( str ) + # extract( str, schemes ) + # extract( str, schemes ) {|item| block } + # + # == Args + # + # +str+:: + # String to search + # +schemes+:: + # Patterns to apply to +str+ + # + # == Description + # + # Attempts to parse and merge a set of URIs. + # If no +block+ given, then returns the result, + # else it calls +block+ for each element in result. + # + # See also Gem::URI::Parser.make_regexp. + # + def extract(str, schemes = nil) + if block_given? + str.scan(make_regexp(schemes)) { yield $& } + nil + else + result = [] + str.scan(make_regexp(schemes)) { result.push $& } + result + end + end + + # Returns Regexp that is default +self.regexp[:ABS_URI_REF]+, + # unless +schemes+ is provided. Then it is a Regexp.union with +self.pattern[:X_ABS_URI]+. + def make_regexp(schemes = nil) + unless schemes + @regexp[:ABS_URI_REF] + else + /(?=#{Regexp.union(*schemes)}:)#{@pattern[:X_ABS_URI]}/x + end + end + + # + # :call-seq: + # escape( str ) + # escape( str, unsafe ) + # + # == Args + # + # +str+:: + # String to make safe + # +unsafe+:: + # Regexp to apply. Defaults to +self.regexp[:UNSAFE]+ + # + # == Description + # + # Constructs a safe String from +str+, removing unsafe characters, + # replacing them with codes. + # + def escape(str, unsafe = @regexp[:UNSAFE]) + unless unsafe.kind_of?(Regexp) + # perhaps unsafe is String object + unsafe = Regexp.new("[#{Regexp.quote(unsafe)}]", false) + end + str.gsub(unsafe) do + us = $& + tmp = '' + us.each_byte do |uc| + tmp << sprintf('%%%02X', uc) + end + tmp + end.force_encoding(Encoding::US_ASCII) + end + + # + # :call-seq: + # unescape( str ) + # unescape( str, escaped ) + # + # == Args + # + # +str+:: + # String to remove escapes from + # +escaped+:: + # Regexp to apply. Defaults to +self.regexp[:ESCAPED]+ + # + # == Description + # + # Removes escapes from +str+. + # + def unescape(str, escaped = @regexp[:ESCAPED]) + enc = str.encoding + enc = Encoding::UTF_8 if enc == Encoding::US_ASCII + str.gsub(escaped) { [$&[1, 2]].pack('H2').force_encoding(enc) } + end + + @@to_s = Kernel.instance_method(:to_s) + if @@to_s.respond_to?(:bind_call) + def inspect + @@to_s.bind_call(self) + end + else + def inspect + @@to_s.bind(self).call + end + end + + private + + # Constructs the default Hash of patterns. + def initialize_pattern(opts = {}) + ret = {} + ret[:ESCAPED] = escaped = (opts.delete(:ESCAPED) || PATTERN::ESCAPED) + ret[:UNRESERVED] = unreserved = opts.delete(:UNRESERVED) || PATTERN::UNRESERVED + ret[:RESERVED] = reserved = opts.delete(:RESERVED) || PATTERN::RESERVED + ret[:DOMLABEL] = opts.delete(:DOMLABEL) || PATTERN::DOMLABEL + ret[:TOPLABEL] = opts.delete(:TOPLABEL) || PATTERN::TOPLABEL + ret[:HOSTNAME] = hostname = opts.delete(:HOSTNAME) + + # RFC 2396 (Gem::URI Generic Syntax) + # RFC 2732 (IPv6 Literal Addresses in URL's) + # RFC 2373 (IPv6 Addressing Architecture) + + # uric = reserved | unreserved | escaped + ret[:URIC] = uric = "(?:[#{unreserved}#{reserved}]|#{escaped})" + # uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" | + # "&" | "=" | "+" | "$" | "," + ret[:URIC_NO_SLASH] = uric_no_slash = "(?:[#{unreserved};?:@&=+$,]|#{escaped})" + # query = *uric + ret[:QUERY] = query = "#{uric}*" + # fragment = *uric + ret[:FRAGMENT] = fragment = "#{uric}*" + + # hostname = *( domainlabel "." ) toplabel [ "." ] + # reg-name = *( unreserved / pct-encoded / sub-delims ) # RFC3986 + unless hostname + ret[:HOSTNAME] = hostname = "(?:[a-zA-Z0-9\\-.]|%\\h\\h)+" + end + + # RFC 2373, APPENDIX B: + # IPv6address = hexpart [ ":" IPv4address ] + # IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT + # hexpart = hexseq | hexseq "::" [ hexseq ] | "::" [ hexseq ] + # hexseq = hex4 *( ":" hex4) + # hex4 = 1*4HEXDIG + # + # XXX: This definition has a flaw. "::" + IPv4address must be + # allowed too. Here is a replacement. + # + # IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT + ret[:IPV4ADDR] = ipv4addr = "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}" + # hex4 = 1*4HEXDIG + hex4 = "[#{PATTERN::HEX}]{1,4}" + # lastpart = hex4 | IPv4address + lastpart = "(?:#{hex4}|#{ipv4addr})" + # hexseq1 = *( hex4 ":" ) hex4 + hexseq1 = "(?:#{hex4}:)*#{hex4}" + # hexseq2 = *( hex4 ":" ) lastpart + hexseq2 = "(?:#{hex4}:)*#{lastpart}" + # IPv6address = hexseq2 | [ hexseq1 ] "::" [ hexseq2 ] + ret[:IPV6ADDR] = ipv6addr = "(?:#{hexseq2}|(?:#{hexseq1})?::(?:#{hexseq2})?)" + + # IPv6prefix = ( hexseq1 | [ hexseq1 ] "::" [ hexseq1 ] ) "/" 1*2DIGIT + # unused + + # ipv6reference = "[" IPv6address "]" (RFC 2732) + ret[:IPV6REF] = ipv6ref = "\\[#{ipv6addr}\\]" + + # host = hostname | IPv4address + # host = hostname | IPv4address | IPv6reference (RFC 2732) + ret[:HOST] = host = "(?:#{hostname}|#{ipv4addr}|#{ipv6ref})" + # port = *digit + ret[:PORT] = port = '\d*' + # hostport = host [ ":" port ] + ret[:HOSTPORT] = hostport = "#{host}(?::#{port})?" + + # userinfo = *( unreserved | escaped | + # ";" | ":" | "&" | "=" | "+" | "$" | "," ) + ret[:USERINFO] = userinfo = "(?:[#{unreserved};:&=+$,]|#{escaped})*" + + # pchar = unreserved | escaped | + # ":" | "@" | "&" | "=" | "+" | "$" | "," + pchar = "(?:[#{unreserved}:@&=+$,]|#{escaped})" + # param = *pchar + param = "#{pchar}*" + # segment = *pchar *( ";" param ) + segment = "#{pchar}*(?:;#{param})*" + # path_segments = segment *( "/" segment ) + ret[:PATH_SEGMENTS] = path_segments = "#{segment}(?:/#{segment})*" + + # server = [ [ userinfo "@" ] hostport ] + server = "(?:#{userinfo}@)?#{hostport}" + # reg_name = 1*( unreserved | escaped | "$" | "," | + # ";" | ":" | "@" | "&" | "=" | "+" ) + ret[:REG_NAME] = reg_name = "(?:[#{unreserved}$,;:@&=+]|#{escaped})+" + # authority = server | reg_name + authority = "(?:#{server}|#{reg_name})" + + # rel_segment = 1*( unreserved | escaped | + # ";" | "@" | "&" | "=" | "+" | "$" | "," ) + ret[:REL_SEGMENT] = rel_segment = "(?:[#{unreserved};@&=+$,]|#{escaped})+" + + # scheme = alpha *( alpha | digit | "+" | "-" | "." ) + ret[:SCHEME] = scheme = "[#{PATTERN::ALPHA}][\\-+.#{PATTERN::ALPHA}\\d]*" + + # abs_path = "/" path_segments + ret[:ABS_PATH] = abs_path = "/#{path_segments}" + # rel_path = rel_segment [ abs_path ] + ret[:REL_PATH] = rel_path = "#{rel_segment}(?:#{abs_path})?" + # net_path = "//" authority [ abs_path ] + ret[:NET_PATH] = net_path = "//#{authority}(?:#{abs_path})?" + + # hier_part = ( net_path | abs_path ) [ "?" query ] + ret[:HIER_PART] = hier_part = "(?:#{net_path}|#{abs_path})(?:\\?(?:#{query}))?" + # opaque_part = uric_no_slash *uric + ret[:OPAQUE_PART] = opaque_part = "#{uric_no_slash}#{uric}*" + + # absoluteURI = scheme ":" ( hier_part | opaque_part ) + ret[:ABS_URI] = abs_uri = "#{scheme}:(?:#{hier_part}|#{opaque_part})" + # relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ] + ret[:REL_URI] = rel_uri = "(?:#{net_path}|#{abs_path}|#{rel_path})(?:\\?#{query})?" + + # Gem::URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] + ret[:URI_REF] = "(?:#{abs_uri}|#{rel_uri})?(?:##{fragment})?" + + ret[:X_ABS_URI] = " + (#{scheme}): (?# 1: scheme) + (?: + (#{opaque_part}) (?# 2: opaque) + | + (?:(?: + //(?: + (?:(?:(#{userinfo})@)? (?# 3: userinfo) + (?:(#{host})(?::(\\d*))?))? (?# 4: host, 5: port) + | + (#{reg_name}) (?# 6: registry) + ) + | + (?!//)) (?# XXX: '//' is the mark for hostport) + (#{abs_path})? (?# 7: path) + )(?:\\?(#{query}))? (?# 8: query) + ) + (?:\\#(#{fragment}))? (?# 9: fragment) + " + + ret[:X_REL_URI] = " + (?: + (?: + // + (?: + (?:(#{userinfo})@)? (?# 1: userinfo) + (#{host})?(?::(\\d*))? (?# 2: host, 3: port) + | + (#{reg_name}) (?# 4: registry) + ) + ) + | + (#{rel_segment}) (?# 5: rel_segment) + )? + (#{abs_path})? (?# 6: abs_path) + (?:\\?(#{query}))? (?# 7: query) + (?:\\#(#{fragment}))? (?# 8: fragment) + " + + ret + end + + # Constructs the default Hash of Regexp's. + def initialize_regexp(pattern) + ret = {} + + # for Gem::URI::split + ret[:ABS_URI] = Regexp.new('\A\s*+' + pattern[:X_ABS_URI] + '\s*\z', Regexp::EXTENDED) + ret[:REL_URI] = Regexp.new('\A\s*+' + pattern[:X_REL_URI] + '\s*\z', Regexp::EXTENDED) + + # for Gem::URI::extract + ret[:URI_REF] = Regexp.new(pattern[:URI_REF]) + ret[:ABS_URI_REF] = Regexp.new(pattern[:X_ABS_URI], Regexp::EXTENDED) + ret[:REL_URI_REF] = Regexp.new(pattern[:X_REL_URI], Regexp::EXTENDED) + + # for Gem::URI::escape/unescape + ret[:ESCAPED] = Regexp.new(pattern[:ESCAPED]) + ret[:UNSAFE] = Regexp.new("[^#{pattern[:UNRESERVED]}#{pattern[:RESERVED]}]") + + # for Generic#initialize + ret[:SCHEME] = Regexp.new("\\A#{pattern[:SCHEME]}\\z") + ret[:USERINFO] = Regexp.new("\\A#{pattern[:USERINFO]}\\z") + ret[:HOST] = Regexp.new("\\A#{pattern[:HOST]}\\z") + ret[:PORT] = Regexp.new("\\A#{pattern[:PORT]}\\z") + ret[:OPAQUE] = Regexp.new("\\A#{pattern[:OPAQUE_PART]}\\z") + ret[:REGISTRY] = Regexp.new("\\A#{pattern[:REG_NAME]}\\z") + ret[:ABS_PATH] = Regexp.new("\\A#{pattern[:ABS_PATH]}\\z") + ret[:REL_PATH] = Regexp.new("\\A#{pattern[:REL_PATH]}\\z") + ret[:QUERY] = Regexp.new("\\A#{pattern[:QUERY]}\\z") + ret[:FRAGMENT] = Regexp.new("\\A#{pattern[:FRAGMENT]}\\z") + + ret + end + + def convert_to_uri(uri) + if uri.is_a?(Gem::URI::Generic) + uri + elsif uri = String.try_convert(uri) + parse(uri) + else + raise ArgumentError, + "bad argument (expected Gem::URI object or Gem::URI string)" + end + end + + end # class Parser +end # module Gem::URI diff --git a/lib/rubygems/vendor/uri/lib/uri/rfc3986_parser.rb b/lib/rubygems/vendor/uri/lib/uri/rfc3986_parser.rb new file mode 100644 index 00000000000000..728bb556748f31 --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/rfc3986_parser.rb @@ -0,0 +1,183 @@ +# frozen_string_literal: true +module Gem::URI + class RFC3986_Parser # :nodoc: + # Gem::URI defined in RFC3986 + HOST = %r[ + (?\[(?: + (? + (?:\h{1,4}:){6} + (?\h{1,4}:\h{1,4} + | (?(?[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d) + \.\g\.\g\.\g) + ) + | ::(?:\h{1,4}:){5}\g + | \h{1,4}?::(?:\h{1,4}:){4}\g + | (?:(?:\h{1,4}:)?\h{1,4})?::(?:\h{1,4}:){3}\g + | (?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g + | (?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g + | (?:(?:\h{1,4}:){,4}\h{1,4})?::\g + | (?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4} + | (?:(?:\h{1,4}:){,6}\h{1,4})?:: + ) + | (?v\h++\.[!$&-.0-9:;=A-Z_a-z~]++) + )\]) + | \g + | (?(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])*+) + ]x + + USERINFO = /(?:%\h\h|[!$&-.0-9:;=A-Z_a-z~])*+/ + + SCHEME = %r[[A-Za-z][+\-.0-9A-Za-z]*+].source + SEG = %r[(?:%\h\h|[!$&-.0-9:;=@A-Z_a-z~/])].source + SEG_NC = %r[(?:%\h\h|[!$&-.0-9;=@A-Z_a-z~])].source + FRAGMENT = %r[(?:%\h\h|[!$&-.0-9:;=@A-Z_a-z~/?])*+].source + + RFC3986_URI = %r[\A + (?#{SEG}){0} + (? + (?#{SCHEME}): + (?// + (? + (?:(?#{USERINFO.source})@)? + (?#{HOST.source.delete(" \n")}) + (?::(?\d*+))? + ) + (?(?:/\g*+)?) + | (?/((?!/)\g++)?) + | (?(?!/)\g++) + | (?) + ) + (?:\?(?[^\#]*+))? + (?:\#(?#{FRAGMENT}))? + )\z]x + + RFC3986_relative_ref = %r[\A + (?#{SEG}){0} + (? + (?// + (? + (?:(?#{USERINFO.source})@)? + (?#{HOST.source.delete(" \n")}(?\d*+))? + ) + (?(?:/\g*+)?) + | (?/\g*+) + | (?#{SEG_NC}++(?:/\g*+)?) + | (?) + ) + (?:\?(?[^#]*+))? + (?:\#(?#{FRAGMENT}))? + )\z]x + attr_reader :regexp + + def initialize + @regexp = default_regexp.each_value(&:freeze).freeze + end + + def split(uri) #:nodoc: + begin + uri = uri.to_str + rescue NoMethodError + raise InvalidURIError, "bad Gem::URI(is not Gem::URI?): #{uri.inspect}" + end + uri.ascii_only? or + raise InvalidURIError, "Gem::URI must be ascii only #{uri.dump}" + if m = RFC3986_URI.match(uri) + query = m["query"] + scheme = m["scheme"] + opaque = m["path-rootless"] + if opaque + opaque << "?#{query}" if query + [ scheme, + nil, # userinfo + nil, # host + nil, # port + nil, # registry + nil, # path + opaque, + nil, # query + m["fragment"] + ] + else # normal + [ scheme, + m["userinfo"], + m["host"], + m["port"], + nil, # registry + (m["path-abempty"] || + m["path-absolute"] || + m["path-empty"]), + nil, # opaque + query, + m["fragment"] + ] + end + elsif m = RFC3986_relative_ref.match(uri) + [ nil, # scheme + m["userinfo"], + m["host"], + m["port"], + nil, # registry, + (m["path-abempty"] || + m["path-absolute"] || + m["path-noscheme"] || + m["path-empty"]), + nil, # opaque + m["query"], + m["fragment"] + ] + else + raise InvalidURIError, "bad Gem::URI(is not Gem::URI?): #{uri.inspect}" + end + end + + def parse(uri) # :nodoc: + Gem::URI.for(*self.split(uri), self) + end + + + def join(*uris) # :nodoc: + uris[0] = convert_to_uri(uris[0]) + uris.inject :merge + end + + @@to_s = Kernel.instance_method(:to_s) + if @@to_s.respond_to?(:bind_call) + def inspect + @@to_s.bind_call(self) + end + else + def inspect + @@to_s.bind(self).call + end + end + + private + + def default_regexp # :nodoc: + { + SCHEME: %r[\A#{SCHEME}\z]o, + USERINFO: %r[\A#{USERINFO}\z]o, + HOST: %r[\A#{HOST}\z]o, + ABS_PATH: %r[\A/#{SEG}*+\z]o, + REL_PATH: %r[\A(?!/)#{SEG}++\z]o, + QUERY: %r[\A(?:%\h\h|[!$&-.0-9:;=@A-Z_a-z~/?])*+\z], + FRAGMENT: %r[\A#{FRAGMENT}\z]o, + OPAQUE: %r[\A(?:[^/].*)?\z], + PORT: /\A[\x09\x0a\x0c\x0d ]*+\d*[\x09\x0a\x0c\x0d ]*\z/, + } + end + + def convert_to_uri(uri) + if uri.is_a?(Gem::URI::Generic) + uri + elsif uri = String.try_convert(uri) + parse(uri) + else + raise ArgumentError, + "bad argument (expected Gem::URI object or Gem::URI string)" + end + end + + end # class Parser +end # module Gem::URI diff --git a/lib/rubygems/vendor/uri/lib/uri/version.rb b/lib/rubygems/vendor/uri/lib/uri/version.rb new file mode 100644 index 00000000000000..3c80c334d46aa1 --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/version.rb @@ -0,0 +1,6 @@ +module Gem::URI + # :stopdoc: + VERSION_CODE = '001300'.freeze + VERSION = VERSION_CODE.scan(/../).collect{|n| n.to_i}.join('.').freeze + # :startdoc: +end diff --git a/lib/rubygems/vendor/uri/lib/uri/ws.rb b/lib/rubygems/vendor/uri/lib/uri/ws.rb new file mode 100644 index 00000000000000..0dd2a7a1bb9449 --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/ws.rb @@ -0,0 +1,83 @@ +# frozen_string_literal: false +# = uri/ws.rb +# +# Author:: Matt Muller +# License:: You can redistribute it and/or modify it under the same term as Ruby. +# +# See Gem::URI for general documentation +# + +require_relative 'generic' + +module Gem::URI + + # + # The syntax of WS URIs is defined in RFC6455 section 3. + # + # Note that the Ruby Gem::URI library allows WS URLs containing usernames and + # passwords. This is not legal as per the RFC, but used to be + # supported in Internet Explorer 5 and 6, before the MS04-004 security + # update. See . + # + class WS < Generic + # A Default port of 80 for Gem::URI::WS. + DEFAULT_PORT = 80 + + # An Array of the available components for Gem::URI::WS. + COMPONENT = %i[ + scheme + userinfo host port + path + query + ].freeze + + # + # == Description + # + # Creates a new Gem::URI::WS object from components, with syntax checking. + # + # The components accepted are userinfo, host, port, path, and query. + # + # The components should be provided either as an Array, or as a Hash + # with keys formed by preceding the component names with a colon. + # + # If an Array is used, the components must be passed in the + # order [userinfo, host, port, path, query]. + # + # Example: + # + # uri = Gem::URI::WS.build(host: 'www.example.com', path: '/foo/bar') + # + # uri = Gem::URI::WS.build([nil, "www.example.com", nil, "/path", "query"]) + # + # Currently, if passed userinfo components this method generates + # invalid WS URIs as per RFC 1738. + # + def self.build(args) + tmp = Util.make_components_hash(self, args) + super(tmp) + end + + # + # == Description + # + # Returns the full path for a WS Gem::URI, as required by Net::HTTP::Get. + # + # If the Gem::URI contains a query, the full path is Gem::URI#path + '?' + Gem::URI#query. + # Otherwise, the path is simply Gem::URI#path. + # + # Example: + # + # uri = Gem::URI::WS.build(path: '/foo/bar', query: 'test=true') + # uri.request_uri # => "/foo/bar?test=true" + # + def request_uri + return unless @path + + url = @query ? "#@path?#@query" : @path.dup + url.start_with?(?/.freeze) ? url : ?/ + url + end + end + + register_scheme 'WS', WS +end diff --git a/lib/rubygems/vendor/uri/lib/uri/wss.rb b/lib/rubygems/vendor/uri/lib/uri/wss.rb new file mode 100644 index 00000000000000..0b91d334bbb6d0 --- /dev/null +++ b/lib/rubygems/vendor/uri/lib/uri/wss.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: false +# = uri/wss.rb +# +# Author:: Matt Muller +# License:: You can redistribute it and/or modify it under the same term as Ruby. +# +# See Gem::URI for general documentation +# + +require_relative 'ws' + +module Gem::URI + + # The default port for WSS URIs is 443, and the scheme is 'wss:' rather + # than 'ws:'. Other than that, WSS URIs are identical to WS URIs; + # see Gem::URI::WS. + class WSS < WS + # A Default port of 443 for Gem::URI::WSS + DEFAULT_PORT = 443 + end + + register_scheme 'WSS', WSS +end diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb index e6774ded38f0f3..f830523586b7c3 100644 --- a/test/rubygems/helper.rb +++ b/test/rubygems/helper.rb @@ -17,7 +17,7 @@ require "rubygems/package" require "shellwords" require "tmpdir" -require "uri" +require "rubygems/vendor/uri/lib/uri" require "zlib" require "benchmark" # stdlib require_relative "mock_gem_ui" @@ -395,7 +395,7 @@ def setup Gem::RemoteFetcher.fetcher = Gem::FakeFetcher.new @gem_repo = "http://gems.example.com/" - @uri = URI.parse @gem_repo + @uri = Gem::URI.parse @gem_repo Gem.sources.replace [@gem_repo] Gem.searcher = nil diff --git a/test/rubygems/test_gem_dependency_installer.rb b/test/rubygems/test_gem_dependency_installer.rb index 3740e523c591f9..8999723ba1e2dd 100644 --- a/test/rubygems/test_gem_dependency_installer.rb +++ b/test/rubygems/test_gem_dependency_installer.rb @@ -489,7 +489,7 @@ def test_install_local_dependency_no_network_for_target_gem # compact index is available compact_index_response = Gem::Net::HTTPResponse.new "1.1", 200, "OK" - compact_index_response.uri = URI("http://gems.example.com") + compact_index_response.uri = Gem::URI("http://gems.example.com") @fetcher.data["http://gems.example.com/"] = compact_index_response # but private local gem not present there diff --git a/test/rubygems/test_gem_local_remote_options.rb b/test/rubygems/test_gem_local_remote_options.rb index b84e70e8b88c44..cea9cde82b8551 100644 --- a/test/rubygems/test_gem_local_remote_options.rb +++ b/test/rubygems/test_gem_local_remote_options.rb @@ -34,7 +34,7 @@ def test_both_eh def test_clear_sources_option @cmd.add_local_remote_options - s = URI.parse "http://only-gems.example.com/" + s = Gem::URI.parse "http://only-gems.example.com/" @cmd.handle_options %W[--clear-sources --source #{s}] assert_equal [s.to_s], Gem.sources @@ -76,10 +76,10 @@ def test_remote_eh def test_source_option @cmd.add_source_option - s1 = URI.parse "http://more-gems.example.com/" - s2 = URI.parse "http://even-more-gems.example.com/" - s3 = URI.parse "http://other-gems.example.com/some_subdir" - s4 = URI.parse "http://more-gems.example.com/" # Intentional duplicate + s1 = Gem::URI.parse "http://more-gems.example.com/" + s2 = Gem::URI.parse "http://even-more-gems.example.com/" + s3 = Gem::URI.parse "http://other-gems.example.com/some_subdir" + s4 = Gem::URI.parse "http://more-gems.example.com/" # Intentional duplicate original_sources = Gem.sources.dup @@ -97,7 +97,7 @@ def test_short_source_option original_sources = Gem.sources.dup - source = URI.parse "http://more-gems.example.com/" + source = Gem::URI.parse "http://more-gems.example.com/" @cmd.handle_options %W[-s #{source}] original_sources << source diff --git a/test/rubygems/test_gem_remote_fetcher.rb b/test/rubygems/test_gem_remote_fetcher.rb index 42565b0b16e600..da1d4f818c77d5 100644 --- a/test/rubygems/test_gem_remote_fetcher.rb +++ b/test/rubygems/test_gem_remote_fetcher.rb @@ -162,7 +162,7 @@ def test_no_proxy end def test_cache_update_path - uri = URI "http://example/file" + uri = Gem::URI "http://example/file" path = File.join @tempdir, "file" fetcher = util_fuck_with_fetcher "hello" @@ -176,7 +176,7 @@ def test_cache_update_path def test_cache_update_path_with_utf8_internal_encoding with_internal_encoding("UTF-8") do - uri = URI "http://example/file" + uri = Gem::URI "http://example/file" path = File.join @tempdir, "file" data = String.new("\xC8").force_encoding(Encoding::BINARY) @@ -190,7 +190,7 @@ def test_cache_update_path_with_utf8_internal_encoding end def test_cache_update_path_no_update - uri = URI "http://example/file" + uri = Gem::URI "http://example/file" path = File.join @tempdir, "file" fetcher = util_fuck_with_fetcher "hello" @@ -613,7 +613,7 @@ def fetcher.fetch_http(uri, mtime, head = nil) nil end - assert_nil fetcher.fetch_path(URI.parse(@gem_repo), Time.at(0)) + assert_nil fetcher.fetch_path(Gem::URI.parse(@gem_repo), Time.at(0)) end def test_implicit_no_proxy @@ -671,7 +671,7 @@ def res.body res end - data = fetcher.fetch_http URI.parse(url) + data = fetcher.fetch_http Gem::URI.parse(url) assert_equal "real_path", data end @@ -689,7 +689,7 @@ def fetcher.request(uri, request_class, last_modified = nil) end e = assert_raise Gem::RemoteFetcher::FetchError do - fetcher.fetch_http URI.parse(url) + fetcher.fetch_http Gem::URI.parse(url) end assert_equal "too many redirects (#{url})", e.message @@ -706,7 +706,7 @@ def fetcher.request(uri, request_class, last_modified = nil) end e = assert_raise Gem::RemoteFetcher::FetchError do - fetcher.fetch_http URI.parse(url) + fetcher.fetch_http Gem::URI.parse(url) end assert_equal "redirecting but no redirect location was given (#{url})", e.message @@ -714,7 +714,7 @@ def fetcher.request(uri, request_class, last_modified = nil) def test_fetch_http_with_additional_headers ENV["http_proxy"] = @proxy_uri - ENV["no_proxy"] = URI.parse(@server_uri).host + ENV["no_proxy"] = Gem::URI.parse(@server_uri).host fetcher = Gem::RemoteFetcher.new nil, nil, { "X-Captain" => "murphy" } @fetcher = fetcher assert_equal "murphy", fetcher.fetch_path(@server_uri) @@ -747,7 +747,7 @@ def s3_uri_signer.ec2_metadata_credentials_json s3_uri_signer end - data = fetcher.fetch_s3 URI.parse(url) + data = fetcher.fetch_s3 Gem::URI.parse(url) assert_equal "https://my-bucket.s3.#{region}.amazonaws.com/gems/specs.4.8.gz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=testuser%2F20190624%2F#{region}%2Fs3%2Faws4_request&X-Amz-Date=20190624T050641Z&X-Amz-Expires=86400#{token ? "&X-Amz-Security-Token=" + token : ""}&X-Amz-SignedHeaders=host&X-Amz-Signature=#{signature}", $fetched_uri.to_s assert_equal "success", data @@ -893,7 +893,7 @@ def refute_fetch_s3(url, expected_message) @fetcher = fetcher e = assert_raise Gem::RemoteFetcher::FetchError do - fetcher.fetch_s3 URI.parse(url) + fetcher.fetch_s3 Gem::URI.parse(url) end assert_match expected_message, e.message @@ -936,7 +936,7 @@ def test_fetch_s3_no_secret def test_observe_no_proxy_env_single_host use_ui @stub_ui do ENV["http_proxy"] = @proxy_uri - ENV["no_proxy"] = URI.parse(@server_uri).host + ENV["no_proxy"] = Gem::URI.parse(@server_uri).host fetcher = Gem::RemoteFetcher.new nil @fetcher = fetcher assert_data_from_server fetcher.fetch_path(@server_uri) @@ -946,7 +946,7 @@ def test_observe_no_proxy_env_single_host def test_observe_no_proxy_env_list use_ui @stub_ui do ENV["http_proxy"] = @proxy_uri - ENV["no_proxy"] = "fakeurl.com, #{URI.parse(@server_uri).host}" + ENV["no_proxy"] = "fakeurl.com, #{Gem::URI.parse(@server_uri).host}" fetcher = Gem::RemoteFetcher.new nil @fetcher = fetcher assert_data_from_server fetcher.fetch_path(@server_uri) @@ -958,7 +958,7 @@ def test_request_block @fetcher = fetcher assert_throws :block_called do - fetcher.request URI("http://example"), Gem::Net::HTTP::Get do |req| + fetcher.request Gem::URI("http://example"), Gem::Net::HTTP::Get do |req| assert_kind_of Gem::Net::HTTPGenericRequest, req throw :block_called end diff --git a/test/rubygems/test_gem_request.rb b/test/rubygems/test_gem_request.rb index d5eb2453527c33..5e9b264dacfe9c 100644 --- a/test/rubygems/test_gem_request.rb +++ b/test/rubygems/test_gem_request.rb @@ -34,7 +34,7 @@ def setup super @proxy_uri = "http://localhost:1234" - @uri = URI("http://example") + @uri = Gem::URI("http://example") @request = make_request @uri, nil, nil, nil end @@ -56,7 +56,7 @@ def test_initialize_proxy def test_initialize_proxy_URI proxy_uri = "http://proxy.example.com" - request = make_request @uri, nil, nil, URI(proxy_uri) + request = make_request @uri, nil, nil, Gem::URI(proxy_uri) assert_equal proxy_uri, request.proxy_uri.to_s end @@ -77,18 +77,18 @@ def test_initialize_proxy_ENV def test_initialize_proxy_ENV_https ENV["https_proxy"] = @proxy_uri - request = make_request URI("https://example"), nil, nil, nil + request = make_request Gem::URI("https://example"), nil, nil, nil proxy = request.proxy_uri - assert_equal URI(@proxy_uri), proxy + assert_equal Gem::URI(@proxy_uri), proxy end def test_proxy_ENV ENV["http_proxy"] = "http://proxy" ENV["https_proxy"] = "" - request = make_request URI("https://example"), nil, nil, nil + request = make_request Gem::URI("https://example"), nil, nil, nil proxy = request.proxy_uri @@ -102,7 +102,7 @@ def test_configure_connection_for_https def self.get_cert_files [TestGemRequest::PUBLIC_CERT_FILE] end - end.create_with_proxy URI("https://example"), nil, nil, nil + end.create_with_proxy Gem::URI("https://example"), nil, nil, nil Gem::Request.configure_connection_for_https connection, request.cert_files @@ -121,7 +121,7 @@ def test_configure_connection_for_https_ssl_ca_cert def self.get_cert_files [TestGemRequest::PUBLIC_CERT_FILE] end - end.create_with_proxy URI("https://example"), nil, nil, nil + end.create_with_proxy Gem::URI("https://example"), nil, nil, nil Gem::Request.configure_connection_for_https connection, request.cert_files @@ -138,17 +138,17 @@ def test_get_proxy_from_env_fallback request = make_request @uri, nil, nil, nil proxy = request.proxy_uri - assert_equal URI(@proxy_uri), proxy + assert_equal Gem::URI(@proxy_uri), proxy end def test_get_proxy_from_env_https ENV["https_proxy"] = @proxy_uri - uri = URI("https://example") + uri = Gem::URI("https://example") request = make_request uri, nil, nil, nil proxy = request.proxy_uri - assert_equal URI(@proxy_uri), proxy + assert_equal Gem::URI(@proxy_uri), proxy end def test_get_proxy_from_env_domain @@ -191,7 +191,7 @@ def test_get_proxy_from_env_empty end def test_fetch - uri = Gem::Uri.new(URI.parse("#{@gem_repo}/specs.#{Gem.marshal_version}")) + uri = Gem::Uri.new(Gem::URI.parse("#{@gem_repo}/specs.#{Gem.marshal_version}")) response = util_stub_net_http(body: :junk, code: 200) do @request = make_request(uri, Gem::Net::HTTP::Get, nil, nil) @@ -204,7 +204,7 @@ def test_fetch def test_fetch_basic_auth Gem.configuration.verbose = :really - uri = Gem::Uri.new(URI.parse("https://user:pass@example.rubygems/specs.#{Gem.marshal_version}")) + uri = Gem::Uri.new(Gem::URI.parse("https://user:pass@example.rubygems/specs.#{Gem.marshal_version}")) conn = util_stub_net_http(body: :junk, code: 200) do |c| use_ui @ui do @request = make_request(uri, Gem::Net::HTTP::Get, nil, nil) @@ -220,7 +220,7 @@ def test_fetch_basic_auth def test_fetch_basic_auth_encoded Gem.configuration.verbose = :really - uri = Gem::Uri.new(URI.parse("https://user:%7BDEScede%7Dpass@example.rubygems/specs.#{Gem.marshal_version}")) + uri = Gem::Uri.new(Gem::URI.parse("https://user:%7BDEScede%7Dpass@example.rubygems/specs.#{Gem.marshal_version}")) conn = util_stub_net_http(body: :junk, code: 200) do |c| use_ui @ui do @@ -237,7 +237,7 @@ def test_fetch_basic_auth_encoded def test_fetch_basic_oauth_encoded Gem.configuration.verbose = :really - uri = Gem::Uri.new(URI.parse("https://%7BDEScede%7Dpass:x-oauth-basic@example.rubygems/specs.#{Gem.marshal_version}")) + uri = Gem::Uri.new(Gem::URI.parse("https://%7BDEScede%7Dpass:x-oauth-basic@example.rubygems/specs.#{Gem.marshal_version}")) conn = util_stub_net_http(body: :junk, code: 200) do |c| use_ui @ui do @@ -253,7 +253,7 @@ def test_fetch_basic_oauth_encoded end def test_fetch_head - uri = Gem::Uri.new(URI.parse("#{@gem_repo}/specs.#{Gem.marshal_version}")) + uri = Gem::Uri.new(Gem::URI.parse("#{@gem_repo}/specs.#{Gem.marshal_version}")) response = util_stub_net_http(body: "", code: 200) do |_conn| @request = make_request(uri, Gem::Net::HTTP::Get, nil, nil) @request.fetch @@ -264,7 +264,7 @@ def test_fetch_head end def test_fetch_unmodified - uri = Gem::Uri.new(URI.parse("#{@gem_repo}/specs.#{Gem.marshal_version}")) + uri = Gem::Uri.new(Gem::URI.parse("#{@gem_repo}/specs.#{Gem.marshal_version}")) t = Time.utc(2013, 1, 2, 3, 4, 5) conn, response = util_stub_net_http(body: "", code: 304) do |c| @request = make_request(uri, Gem::Net::HTTP::Get, t, nil) diff --git a/test/rubygems/test_gem_request_connection_pools.rb b/test/rubygems/test_gem_request_connection_pools.rb index 4e1e7de07befb2..7a814d3acb4ef2 100644 --- a/test/rubygems/test_gem_request_connection_pools.rb +++ b/test/rubygems/test_gem_request_connection_pools.rb @@ -18,7 +18,7 @@ def setup @old_client = Gem::Request::ConnectionPools.client Gem::Request::ConnectionPools.client = FakeHttp - @proxy = URI "http://proxy.example" + @proxy = Gem::URI "http://proxy.example" end def teardown @@ -49,7 +49,7 @@ def test_to_proxy_empty_string end def test_checkout_same_connection - uri = URI.parse("http://example/some_endpoint") + uri = Gem::URI.parse("http://example/some_endpoint") pools = Gem::Request::ConnectionPools.new nil, [] pool = pools.pool_for uri @@ -99,7 +99,7 @@ def test_to_proxy_eh_wildcard def test_net_http_args pools = Gem::Request::ConnectionPools.new nil, [] - net_http_args = pools.send :net_http_args, URI("http://example"), nil + net_http_args = pools.send :net_http_args, Gem::URI("http://example"), nil assert_equal ["example", 80], net_http_args end @@ -107,7 +107,7 @@ def test_net_http_args def test_net_http_args_ipv6 pools = Gem::Request::ConnectionPools.new nil, [] - net_http_args = pools.send :net_http_args, URI("http://[::1]"), nil + net_http_args = pools.send :net_http_args, Gem::URI("http://[::1]"), nil assert_equal ["::1", 80], net_http_args end @@ -115,7 +115,7 @@ def test_net_http_args_ipv6 def test_net_http_args_proxy pools = Gem::Request::ConnectionPools.new nil, [] - net_http_args = pools.send :net_http_args, URI("http://example"), @proxy + net_http_args = pools.send :net_http_args, Gem::URI("http://example"), @proxy assert_equal ["example", 80, "proxy.example", 80, nil, nil], net_http_args end @@ -126,7 +126,7 @@ def test_net_http_args_no_proxy pools = Gem::Request::ConnectionPools.new nil, [] - net_http_args = pools.send :net_http_args, URI("http://example"), @proxy + net_http_args = pools.send :net_http_args, Gem::URI("http://example"), @proxy assert_equal ["example", 80, nil, nil], net_http_args ensure @@ -134,7 +134,7 @@ def test_net_http_args_no_proxy end def test_thread_waits_for_connection - uri = URI.parse("http://example/some_endpoint") + uri = Gem::URI.parse("http://example/some_endpoint") pools = Gem::Request::ConnectionPools.new nil, [] pool = pools.pool_for uri diff --git a/test/rubygems/test_gem_resolver.rb b/test/rubygems/test_gem_resolver.rb index c2bdc5332c821f..b7dadda7085cba 100644 --- a/test/rubygems/test_gem_resolver.rb +++ b/test/rubygems/test_gem_resolver.rb @@ -8,7 +8,7 @@ def make_dep(name, *req) end def set(*specs) - source = Gem::Source.new URI @gem_repo + source = Gem::Source.new Gem::URI @gem_repo specs = specs.map do |spec| Gem::Resolver::SpecSpecification.new nil, spec, source diff --git a/test/rubygems/test_gem_resolver_api_set.rb b/test/rubygems/test_gem_resolver_api_set.rb index c0c6d82f198245..5781cf37d26e13 100644 --- a/test/rubygems/test_gem_resolver_api_set.rb +++ b/test/rubygems/test_gem_resolver_api_set.rb @@ -6,30 +6,30 @@ class TestGemResolverAPISet < Gem::TestCase def setup super - @dep_uri = URI "#{@gem_repo}info/" + @dep_uri = Gem::URI "#{@gem_repo}info/" end def test_initialize set = Gem::Resolver::APISet.new - assert_equal URI("https://index.rubygems.org/info/"), set.dep_uri - assert_equal URI("https://index.rubygems.org/"), set.uri - assert_equal Gem::Source.new(URI("https://index.rubygems.org")), set.source + assert_equal Gem::URI("https://index.rubygems.org/info/"), set.dep_uri + assert_equal Gem::URI("https://index.rubygems.org/"), set.uri + assert_equal Gem::Source.new(Gem::URI("https://index.rubygems.org")), set.source end def test_initialize_deeper_uri set = Gem::Resolver::APISet.new "https://rubygemsserver.com/mygems/info" - assert_equal URI("https://rubygemsserver.com/mygems/info"), set.dep_uri - assert_equal URI("https://rubygemsserver.com/"), set.uri - assert_equal Gem::Source.new(URI("https://rubygemsserver.com/")), set.source + assert_equal Gem::URI("https://rubygemsserver.com/mygems/info"), set.dep_uri + assert_equal Gem::URI("https://rubygemsserver.com/"), set.uri + assert_equal Gem::Source.new(Gem::URI("https://rubygemsserver.com/")), set.source end def test_initialize_uri set = Gem::Resolver::APISet.new @dep_uri - assert_equal URI("#{@gem_repo}info/"), set.dep_uri - assert_equal URI(@gem_repo.to_s), set.uri + assert_equal Gem::URI("#{@gem_repo}info/"), set.dep_uri + assert_equal Gem::URI(@gem_repo.to_s), set.uri end def test_find_all diff --git a/test/rubygems/test_gem_resolver_api_specification.rb b/test/rubygems/test_gem_resolver_api_specification.rb index 49f3cc81d0c312..2119d734780b9e 100644 --- a/test/rubygems/test_gem_resolver_api_specification.rb +++ b/test/rubygems/test_gem_resolver_api_specification.rb @@ -124,7 +124,7 @@ def test_spec fetcher.spec "a", 1 end - dep_uri = URI(@gem_repo) + "info" + dep_uri = Gem::URI(@gem_repo) + "info" set = Gem::Resolver::APISet.new dep_uri data = { name: "a", @@ -148,7 +148,7 @@ def test_spec_jruby_platform end end - dep_uri = URI(@gem_repo) + "info" + dep_uri = Gem::URI(@gem_repo) + "info" set = Gem::Resolver::APISet.new dep_uri data = { name: "j", diff --git a/test/rubygems/test_gem_resolver_best_set.rb b/test/rubygems/test_gem_resolver_best_set.rb index 80aa8833644ae2..8a750cdf8fd665 100644 --- a/test/rubygems/test_gem_resolver_best_set.rb +++ b/test/rubygems/test_gem_resolver_best_set.rb @@ -34,7 +34,7 @@ def test_find_all_fallback set = Gem::Resolver::BestSet.new - api_uri = URI(@gem_repo) + api_uri = Gem::URI(@gem_repo) set.sets << Gem::Resolver::APISet.new(api_uri) @@ -94,7 +94,7 @@ def test_prefetch_local def test_replace_failed_api_set set = Gem::Resolver::BestSet.new - api_uri = URI(@gem_repo) + "./info/" + api_uri = Gem::URI(@gem_repo) + "./info/" api_set = Gem::Resolver::APISet.new api_uri set.sets << api_set @@ -131,7 +131,7 @@ def test_replace_failed_api_set_no_api_set def test_replace_failed_api_set_uri_with_credentials set = Gem::Resolver::BestSet.new - api_uri = URI(@gem_repo) + "./info/" + api_uri = Gem::URI(@gem_repo) + "./info/" api_uri.user = "user" api_uri.password = "pass" api_set = Gem::Resolver::APISet.new api_uri diff --git a/test/rubygems/test_gem_source.rb b/test/rubygems/test_gem_source.rb index aa26dd07f08d32..4d445f343765d6 100644 --- a/test/rubygems/test_gem_source.rb +++ b/test/rubygems/test_gem_source.rb @@ -22,7 +22,7 @@ def setup end def test_initialize_invalid_uri - assert_raise URI::InvalidURIError do + assert_raise Gem::URI::InvalidURIError do Gem::Source.new "git@example:a.git" end end @@ -36,7 +36,7 @@ def test_initialize_git end def test_cache_dir_escapes_windows_paths - uri = URI.parse("file:///C:/WINDOWS/Temp/gem_repo") + uri = Gem::URI.parse("file:///C:/WINDOWS/Temp/gem_repo") root = Gem.spec_cache_dir cache_dir = @source.cache_dir(uri).gsub(root, "") assert !cache_dir.include?(":"), "#{cache_dir} should not contain a :" @@ -44,7 +44,7 @@ def test_cache_dir_escapes_windows_paths def test_dependency_resolver_set_bundler_api response = Gem::Net::HTTPResponse.new "1.1", 200, "OK" - response.uri = URI("http://example") + response.uri = Gem::URI("http://example") @fetcher.data[@gem_repo] = response @@ -78,7 +78,7 @@ def test_fetch_spec spec = @source.fetch_spec tuple("a", Gem::Version.new(1), "ruby") assert_equal a1.full_name, spec.full_name - cache_dir = @source.cache_dir URI.parse(spec_uri) + cache_dir = @source.cache_dir Gem::URI.parse(spec_uri) cache_file = File.join cache_dir, a1.spec_name @@ -91,7 +91,7 @@ def test_fetch_spec_cached spec_uri = "#{@gem_repo}/#{Gem::MARSHAL_SPEC_DIR}#{a1.spec_name}" @fetcher.data["#{spec_uri}.rz"] = nil - cache_dir = @source.cache_dir URI.parse(spec_uri) + cache_dir = @source.cache_dir Gem::URI.parse(spec_uri) FileUtils.mkdir_p cache_dir cache_file = File.join cache_dir, a1.spec_name diff --git a/test/rubygems/test_gem_source_git.rb b/test/rubygems/test_gem_source_git.rb index 18265bd814df2e..20e750a0d4000d 100644 --- a/test/rubygems/test_gem_source_git.rb +++ b/test/rubygems/test_gem_source_git.rb @@ -289,7 +289,7 @@ def test_specs_local end def test_uri - assert_equal URI(@repository), @source.uri + assert_equal Gem::URI(@repository), @source.uri end def test_uri_hash diff --git a/test/rubygems/test_gem_source_list.rb b/test/rubygems/test_gem_source_list.rb index fc084830ba4243..64353f8f90df97 100644 --- a/test/rubygems/test_gem_source_list.rb +++ b/test/rubygems/test_gem_source_list.rb @@ -37,7 +37,7 @@ def test_append assert_kind_of Gem::Source, source - assert_kind_of URI, source.uri + assert_kind_of Gem::URI, source.uri assert_equal source.uri.to_s, @uri assert_equal [source], sl.sources @@ -99,7 +99,7 @@ def test_to_a def test_include_eh assert @sl.include?(@uri), "string comparison not working" - assert @sl.include?(URI.parse(@uri)), "uri comparison not working" + assert @sl.include?(Gem::URI.parse(@uri)), "uri comparison not working" end def test_include_matches_a_source diff --git a/test/rubygems/test_gem_source_lock.rb b/test/rubygems/test_gem_source_lock.rb index ece55581ecc26b..91ffee68f23e99 100644 --- a/test/rubygems/test_gem_source_lock.rb +++ b/test/rubygems/test_gem_source_lock.rb @@ -110,6 +110,6 @@ def test_uri remote = Gem::Source.new @gem_repo lock = Gem::Source::Lock.new remote - assert_equal URI(@gem_repo), lock.uri + assert_equal Gem::URI(@gem_repo), lock.uri end end diff --git a/test/rubygems/test_gem_source_subpath_problem.rb b/test/rubygems/test_gem_source_subpath_problem.rb index 1ca9b671599f72..a451a81a25cb4a 100644 --- a/test/rubygems/test_gem_source_subpath_problem.rb +++ b/test/rubygems/test_gem_source_subpath_problem.rb @@ -22,7 +22,7 @@ def setup def test_dependency_resolver_set response = Gem::Net::HTTPResponse.new "1.1", 200, "OK" - response.uri = URI("http://example") + response.uri = Gem::URI("http://example") @fetcher.data["#{@gem_repo}/"] = response diff --git a/test/rubygems/test_gem_spec_fetcher.rb b/test/rubygems/test_gem_spec_fetcher.rb index 0fca9f0c48e965..cb4a4f7204778e 100644 --- a/test/rubygems/test_gem_spec_fetcher.rb +++ b/test/rubygems/test_gem_spec_fetcher.rb @@ -11,7 +11,7 @@ def tuple(*args) def setup super - @uri = URI.parse @gem_repo + @uri = Gem::URI.parse @gem_repo @source = Gem::Source.new(@uri) @sf = Gem::SpecFetcher.new diff --git a/test/rubygems/test_webauthn_listener.rb b/test/rubygems/test_webauthn_listener.rb index e3f7c8c3957eab..08edabceb26dc9 100644 --- a/test/rubygems/test_webauthn_listener.rb +++ b/test/rubygems/test_webauthn_listener.rb @@ -19,7 +19,7 @@ def teardown def test_listener_thread_retreives_otp_code thread = Gem::GemcutterUtilities::WebauthnListener.listener_thread(Gem.host, @server) - Gem::MockBrowser.get URI("http://localhost:#{@port}?code=xyz") + Gem::MockBrowser.get Gem::URI("http://localhost:#{@port}?code=xyz") thread.join assert_equal "xyz", thread[:otp] @@ -27,7 +27,7 @@ def test_listener_thread_retreives_otp_code def test_listener_thread_sets_error thread = Gem::GemcutterUtilities::WebauthnListener.listener_thread(Gem.host, @server) - Gem::MockBrowser.post URI("http://localhost:#{@port}?code=xyz") + Gem::MockBrowser.post Gem::URI("http://localhost:#{@port}?code=xyz") thread.join assert_equal "Security device verification failed: Invalid HTTP method POST received.", thread[:error].message @@ -35,13 +35,13 @@ def test_listener_thread_sets_error def test_wait_for_otp_code_get_follows_options wait_for_otp_code - assert Gem::MockBrowser.options(URI("http://localhost:#{@port}?code=xyz")).is_a? Gem::Net::HTTPNoContent - assert Gem::MockBrowser.get(URI("http://localhost:#{@port}?code=xyz")).is_a? Gem::Net::HTTPOK + assert Gem::MockBrowser.options(Gem::URI("http://localhost:#{@port}?code=xyz")).is_a? Gem::Net::HTTPNoContent + assert Gem::MockBrowser.get(Gem::URI("http://localhost:#{@port}?code=xyz")).is_a? Gem::Net::HTTPOK end def test_wait_for_otp_code_options_request wait_for_otp_code - response = Gem::MockBrowser.options URI("http://localhost:#{@port}?code=xyz") + response = Gem::MockBrowser.options Gem::URI("http://localhost:#{@port}?code=xyz") assert response.is_a? Gem::Net::HTTPNoContent assert_equal Gem.host, response["access-control-allow-origin"] @@ -52,7 +52,7 @@ def test_wait_for_otp_code_options_request def test_wait_for_otp_code_get_request wait_for_otp_code - response = Gem::MockBrowser.get URI("http://localhost:#{@port}?code=xyz") + response = Gem::MockBrowser.get Gem::URI("http://localhost:#{@port}?code=xyz") assert response.is_a? Gem::Net::HTTPOK assert_equal "text/plain; charset=utf-8", response["Content-Type"] @@ -69,7 +69,7 @@ def test_wait_for_otp_code_get_request def test_wait_for_otp_code_invalid_post_req_method wait_for_otp_code_expect_error_with_message("Security device verification failed: Invalid HTTP method POST received.") - response = Gem::MockBrowser.post URI("http://localhost:#{@port}?code=xyz") + response = Gem::MockBrowser.post Gem::URI("http://localhost:#{@port}?code=xyz") assert response assert response.is_a? Gem::Net::HTTPMethodNotAllowed @@ -82,7 +82,7 @@ def test_wait_for_otp_code_invalid_post_req_method def test_wait_for_otp_code_incorrect_path wait_for_otp_code_expect_error_with_message("Security device verification failed: Page at /path not found.") - response = Gem::MockBrowser.post URI("http://localhost:#{@port}/path?code=xyz") + response = Gem::MockBrowser.post Gem::URI("http://localhost:#{@port}/path?code=xyz") assert response.is_a? Gem::Net::HTTPNotFound assert_equal "close", response["Connection"] @@ -93,7 +93,7 @@ def test_wait_for_otp_code_incorrect_path def test_wait_for_otp_code_no_params_response wait_for_otp_code_expect_error_with_message("Security device verification failed: Did not receive OTP from https://rubygems.org.") - response = Gem::MockBrowser.get URI("http://localhost:#{@port}") + response = Gem::MockBrowser.get Gem::URI("http://localhost:#{@port}") assert response.is_a? Gem::Net::HTTPBadRequest assert_equal "text/plain; charset=utf-8", response["Content-Type"] @@ -107,7 +107,7 @@ def test_wait_for_otp_code_no_params_response def test_wait_for_otp_code_incorrect_params wait_for_otp_code_expect_error_with_message("Security device verification failed: Did not receive OTP from https://rubygems.org.") - response = Gem::MockBrowser.get URI("http://localhost:#{@port}?param=xyz") + response = Gem::MockBrowser.get Gem::URI("http://localhost:#{@port}?param=xyz") assert response.is_a? Gem::Net::HTTPBadRequest assert_equal "text/plain; charset=utf-8", response["Content-Type"] diff --git a/test/rubygems/utilities.rb b/test/rubygems/utilities.rb index 996b1f3440bf52..357379f88d8aaa 100644 --- a/test/rubygems/utilities.rb +++ b/test/rubygems/utilities.rb @@ -40,16 +40,16 @@ def initialize end def find_data(path) - return Gem.read_binary path.path if URI === path && path.scheme == "file" + return Gem.read_binary path.path if Gem::URI === path && path.scheme == "file" - if URI === path && "URI::#{path.scheme.upcase}" != path.class.name + if Gem::URI === path && "Gem::URI::#{path.scheme.upcase}" != path.class.name raise ArgumentError, "mismatch for scheme #{path.scheme} and class #{path.class}" end path = path.to_s @paths << path - raise ArgumentError, "need full URI" unless path.start_with?("https://", "http://") + raise ArgumentError, "need full Gem::URI" unless path.start_with?("https://", "http://") unless @data.key? path raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", path) @@ -194,7 +194,7 @@ def self.create(body:, code:, msg:, headers: {}) # Example: # # # Sends a get request to http://localhost:5678 -# Gem::MockBrowser.get URI("http://localhost:5678") +# Gem::MockBrowser.get Gem::URI("http://localhost:5678") # # See RubyGems' tests for more examples of MockBrowser. # @@ -368,12 +368,12 @@ def setup_fetcher # :nodoc: begin gem_repo = @test.gem_repo @test.gem_repo = @repository - @test.uri = URI @repository + @test.uri = Gem::URI @repository @test.util_setup_spec_fetcher(*@downloaded) ensure @test.gem_repo = gem_repo - @test.uri = URI gem_repo + @test.uri = Gem::URI gem_repo end @gems.each do |spec, gem| From f3123f8af2c79d3e40719865fc3700277fe1ae72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 15 Jan 2024 20:51:35 +0100 Subject: [PATCH 607/640] [rubygems/rubygems] Use rubygems vendored uri from Bundler when available https://github.com/rubygems/rubygems/commit/5d6a8f2fb4 --- lib/bundler/cli.rb | 2 +- lib/bundler/fetcher.rb | 4 +- lib/bundler/fetcher/downloader.rb | 2 +- lib/bundler/mirror.rb | 6 +-- lib/bundler/plugin/api/source.rb | 4 +- lib/bundler/settings.rb | 8 ++-- lib/bundler/source/git.rb | 2 +- lib/bundler/source/git/git_proxy.rb | 2 +- lib/bundler/source/rubygems.rb | 4 +- lib/bundler/source/rubygems/remote.rb | 2 +- lib/bundler/uri_credentials_filter.rb | 4 +- .../lib/net/http/persistent.rb | 42 +++++++++---------- lib/bundler/vendored_uri.rb | 19 ++++++++- spec/bundler/bundler/fetcher/base_spec.rb | 6 +-- .../bundler/fetcher/compact_index_spec.rb | 2 +- .../bundler/fetcher/dependency_spec.rb | 4 +- .../bundler/fetcher/downloader_spec.rb | 28 ++++++------- spec/bundler/bundler/fetcher/index_spec.rb | 2 +- spec/bundler/bundler/fetcher_spec.rb | 4 +- spec/bundler/bundler/mirror_spec.rb | 16 +++---- .../bundler/rubygems_integration_spec.rb | 4 +- spec/bundler/bundler/settings_spec.rb | 10 ++--- .../bundler/source/rubygems/remote_spec.rb | 20 ++++----- spec/bundler/bundler/source_list_spec.rb | 4 +- .../bundler/uri_credentials_filter_spec.rb | 10 ++--- .../install/gems/compact_index_spec.rb | 2 +- .../install/gems/dependency_api_spec.rb | 2 +- spec/bundler/realworld/edgecases_spec.rb | 2 +- 28 files changed, 117 insertions(+), 100 deletions(-) diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb index 244ab55967f450..36405367620b7b 100644 --- a/lib/bundler/cli.rb +++ b/lib/bundler/cli.rb @@ -785,7 +785,7 @@ def warn_on_outdated_bundler return unless SharedHelpers.md5_available? latest = Fetcher::CompactIndex. - new(nil, Source::Rubygems::Remote.new(Bundler::URI("https://rubygems.org")), nil, nil). + new(nil, Source::Rubygems::Remote.new(Gem::URI("https://rubygems.org")), nil, nil). send(:compact_index_client). instance_variable_get(:@cache). dependencies("bundler"). diff --git a/lib/bundler/fetcher.rb b/lib/bundler/fetcher.rb index 42bd2c0984d80e..6288b22dcd0636 100644 --- a/lib/bundler/fetcher.rb +++ b/lib/bundler/fetcher.rb @@ -111,7 +111,7 @@ def fetch_spec(spec) spec -= [nil, "ruby", ""] spec_file_name = "#{spec.join "-"}.gemspec" - uri = Bundler::URI.parse("#{remote_uri}#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}.rz") + uri = Gem::URI.parse("#{remote_uri}#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}.rz") spec = if uri.scheme == "file" path = Gem::Util.correct_for_windows_path(uri.path) Bundler.safe_load_marshal Bundler.rubygems.inflate(Gem.read_binary(path)) @@ -255,7 +255,7 @@ def connection con = Gem::Net::HTTP::Persistent.new name: "bundler", proxy: :ENV if gem_proxy = Gem.configuration[:http_proxy] - con.proxy = Bundler::URI.parse(gem_proxy) if gem_proxy != :no_proxy + con.proxy = Gem::URI.parse(gem_proxy) if gem_proxy != :no_proxy end if remote_uri.scheme == "https" diff --git a/lib/bundler/fetcher/downloader.rb b/lib/bundler/fetcher/downloader.rb index b5282a322e0626..868b39b959c79c 100644 --- a/lib/bundler/fetcher/downloader.rb +++ b/lib/bundler/fetcher/downloader.rb @@ -23,7 +23,7 @@ def fetch(uri, headers = {}, counter = 0) when Gem::Net::HTTPSuccess, Gem::Net::HTTPNotModified response when Gem::Net::HTTPRedirection - new_uri = Bundler::URI.parse(response["location"]) + new_uri = Gem::URI.parse(response["location"]) if new_uri.host == uri.host new_uri.user = uri.user new_uri.password = uri.password diff --git a/lib/bundler/mirror.rb b/lib/bundler/mirror.rb index 9d437a095139ca..494a6d6aef183d 100644 --- a/lib/bundler/mirror.rb +++ b/lib/bundler/mirror.rb @@ -47,7 +47,7 @@ def parse(key, value) def fetch_valid_mirror_for(uri) downcased = uri.to_s.downcase - mirror = @mirrors[downcased] || @mirrors[Bundler::URI(downcased).host] || Mirror.new(uri) + mirror = @mirrors[downcased] || @mirrors[Gem::URI(downcased).host] || Mirror.new(uri) mirror.validate!(@prober) mirror = Mirror.new(uri) unless mirror.valid? mirror @@ -74,7 +74,7 @@ def uri=(uri) @uri = if uri.nil? nil else - Bundler::URI(uri.to_s) + Gem::URI(uri.to_s) end @valid = nil end @@ -126,7 +126,7 @@ def initialize(config_line, value) if uri == "all" @all = true else - @uri = Bundler::URI(uri).absolute? ? Settings.normalize_uri(uri) : uri + @uri = Gem::URI(uri).absolute? ? Settings.normalize_uri(uri) : uri end @value = value end diff --git a/lib/bundler/plugin/api/source.rb b/lib/bundler/plugin/api/source.rb index f051f938c2d2ed..8563ee358aca64 100644 --- a/lib/bundler/plugin/api/source.rb +++ b/lib/bundler/plugin/api/source.rb @@ -107,7 +107,7 @@ def post_install(spec, disable_exts = false) def install_path @install_path ||= begin - base_name = File.basename(Bundler::URI.parse(uri).normalize.path) + base_name = File.basename(Gem::URI.parse(uri).normalize.path) gem_install_dir.join("#{base_name}-#{uri_hash[0..11]}") end @@ -176,7 +176,7 @@ def unlock! # # This is used by `app_cache_path` def app_cache_dirname - base_name = File.basename(Bundler::URI.parse(uri).normalize.path) + base_name = File.basename(Gem::URI.parse(uri).normalize.path) "#{base_name}-#{uri_hash}" end diff --git a/lib/bundler/settings.rb b/lib/bundler/settings.rb index 8f941c448d3d81..d84089ee414201 100644 --- a/lib/bundler/settings.rb +++ b/lib/bundler/settings.rb @@ -189,7 +189,7 @@ def local_overrides def mirror_for(uri) if uri.is_a?(String) require_relative "vendored_uri" - uri = Bundler::URI(uri) + uri = Gem::URI(uri) end gem_mirrors.for(uri.to_s).uri @@ -549,7 +549,7 @@ def self.normalize_uri(uri) end uri = URINormalizer.normalize_suffix(uri) require_relative "vendored_uri" - uri = Bundler::URI(uri) + uri = Gem::URI(uri) unless uri.absolute? raise ArgumentError, format("Gem sources must be absolute. You provided '%s'.", uri) end @@ -564,7 +564,7 @@ def self.key_to_s(key) key when Symbol key.name - when Bundler::URI::HTTP + when Gem::URI::HTTP key.to_s else raise ArgumentError, "Invalid key: #{key.inspect}" @@ -577,7 +577,7 @@ def self.key_to_s(key) key when Symbol key.to_s - when Bundler::URI::HTTP + when Gem::URI::HTTP key.to_s else raise ArgumentError, "Invalid key: #{key.inspect}" diff --git a/lib/bundler/source/git.rb b/lib/bundler/source/git.rb index 831a13cba3ce9f..198e335bb6e76b 100644 --- a/lib/bundler/source/git.rb +++ b/lib/bundler/source/git.rb @@ -326,7 +326,7 @@ def uri_hash if %r{^\w+://(\w+@)?}.match?(uri) # Downcase the domain component of the URI # and strip off a trailing slash, if one is present - input = Bundler::URI.parse(uri).normalize.to_s.sub(%r{/$}, "") + input = Gem::URI.parse(uri).normalize.to_s.sub(%r{/$}, "") else # If there is no URI scheme, assume it is an ssh/git URI input = uri diff --git a/lib/bundler/source/git/git_proxy.rb b/lib/bundler/source/git/git_proxy.rb index 8b6d4208846658..645851286cda69 100644 --- a/lib/bundler/source/git/git_proxy.rb +++ b/lib/bundler/source/git/git_proxy.rb @@ -320,7 +320,7 @@ def verify(reference) # Adds credentials to the URI def configured_uri if /https?:/.match?(uri) - remote = Bundler::URI(uri) + remote = Gem::URI(uri) config_auth = Bundler.settings[remote.to_s] || Bundler.settings[remote.host] remote.userinfo ||= config_auth remote.to_s diff --git a/lib/bundler/source/rubygems.rb b/lib/bundler/source/rubygems.rb index dfcedb5b16d5ba..861aa8bbebb687 100644 --- a/lib/bundler/source/rubygems.rb +++ b/lib/bundler/source/rubygems.rb @@ -349,9 +349,9 @@ def package_path(cache_path, spec) def normalize_uri(uri) uri = URINormalizer.normalize_suffix(uri.to_s) require_relative "../vendored_uri" - uri = Bundler::URI(uri) + uri = Gem::URI(uri) raise ArgumentError, "The source must be an absolute URI. For example:\n" \ - "source 'https://rubygems.org'" if !uri.absolute? || (uri.is_a?(Bundler::URI::HTTP) && uri.host.nil?) + "source 'https://rubygems.org'" if !uri.absolute? || (uri.is_a?(Gem::URI::HTTP) && uri.host.nil?) uri end diff --git a/lib/bundler/source/rubygems/remote.rb b/lib/bundler/source/rubygems/remote.rb index 82c850ffbb2197..9c5c06de24f72d 100644 --- a/lib/bundler/source/rubygems/remote.rb +++ b/lib/bundler/source/rubygems/remote.rb @@ -48,7 +48,7 @@ def apply_auth(uri, auth) end uri - rescue Bundler::URI::InvalidComponentError + rescue Gem::URI::InvalidComponentError error_message = "Please CGI escape your usernames and passwords before " \ "setting them for authentication." raise HTTPError.new(error_message) diff --git a/lib/bundler/uri_credentials_filter.rb b/lib/bundler/uri_credentials_filter.rb index ccfaf0bc5de0cc..a83f5304e202f5 100644 --- a/lib/bundler/uri_credentials_filter.rb +++ b/lib/bundler/uri_credentials_filter.rb @@ -11,7 +11,7 @@ def credential_filtered_uri(uri_to_anonymize) return uri if File.exist?(uri) require_relative "vendored_uri" - uri = Bundler::URI(uri) + uri = Gem::URI(uri) end if uri.userinfo @@ -25,7 +25,7 @@ def credential_filtered_uri(uri_to_anonymize) end return uri.to_s if uri_to_anonymize.is_a?(String) uri - rescue Bundler::URI::InvalidURIError # uri is not canonical uri scheme + rescue Gem::URI::InvalidURIError # uri is not canonical uri scheme uri end diff --git a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb b/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb index 4d4d4ddcfaeda9..c15b3463301e8b 100644 --- a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +++ b/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb @@ -22,7 +22,7 @@ # # require 'bundler/vendor/net-http-persistent/lib/net/http/persistent' # -# uri = Bundler::URI 'http://example.com/awesome/web/service' +# uri = Gem::URI 'http://example.com/awesome/web/service' # # http = Gem::Net::HTTP::Persistent.new # @@ -39,17 +39,17 @@ # post = Gem::Net::HTTP::Post.new post_uri.path # post.set_form_data 'some' => 'cool data' # -# # perform the POST, the Bundler::URI is always required +# # perform the POST, the Gem::URI is always required # response http.request post_uri, post # # Note that for GET, HEAD and other requests that do not have a body you want -# to use Bundler::URI#request_uri not Bundler::URI#path. The request_uri contains the query +# to use Gem::URI#request_uri not Gem::URI#path. The request_uri contains the query # params which are sent in the body for other requests. # # == TLS/SSL # # TLS connections are automatically created depending upon the scheme of the -# Bundler::URI. TLS connections are automatically verified against the default +# Gem::URI. TLS connections are automatically verified against the default # certificate store for your computer. You can override this by changing # verify_mode or by specifying an alternate cert_store. # @@ -72,7 +72,7 @@ # == Proxies # # A proxy can be set through #proxy= or at initialization time by providing a -# second argument to ::new. The proxy may be the Bundler::URI of the proxy server or +# second argument to ::new. The proxy may be the Gem::URI of the proxy server or # :ENV which will consult environment variables. # # See #proxy= and #proxy_from_env for details. @@ -197,7 +197,7 @@ class Error < StandardError; end # NOTE: This may not work on ruby > 1.9. def self.detect_idle_timeout uri, max = 10 - uri = Bundler::URI uri unless Bundler::URI::Generic === uri + uri = Gem::URI uri unless Gem::URI::Generic === uri uri += '/' req = Gem::Net::HTTP::Head.new uri.request_uri @@ -455,13 +455,13 @@ def self.detect_idle_timeout uri, max = 10 # Set a +name+ for fun. Your library name should be good enough, but this # otherwise has no purpose. # - # +proxy+ may be set to a Bundler::URI::HTTP or :ENV to pick up proxy options from + # +proxy+ may be set to a Gem::URI::HTTP or :ENV to pick up proxy options from # the environment. See proxy_from_env for details. # - # In order to use a Bundler::URI for the proxy you may need to do some extra work - # beyond Bundler::URI parsing if the proxy requires a password: + # In order to use a Gem::URI for the proxy you may need to do some extra work + # beyond Gem::URI parsing if the proxy requires a password: # - # proxy = Bundler::URI 'http://proxy.example' + # proxy = Gem::URI 'http://proxy.example' # proxy.user = 'AzureDiamond' # proxy.password = 'hunter2' # @@ -510,7 +510,7 @@ def initialize name: nil, proxy: nil, pool_size: DEFAULT_POOL_SIZE @verify_mode = nil @cert_store = nil - @generation = 0 # incremented when proxy Bundler::URI changes + @generation = 0 # incremented when proxy Gem::URI changes if HAVE_OPENSSL then @verify_mode = OpenSSL::SSL::VERIFY_PEER @@ -720,12 +720,12 @@ def private_key= key alias key= private_key= ## - # Sets the proxy server. The +proxy+ may be the Bundler::URI of the proxy server, + # Sets the proxy server. The +proxy+ may be the Gem::URI of the proxy server, # the symbol +:ENV+ which will read the proxy from the environment or nil to # disable use of a proxy. See #proxy_from_env for details on setting the # proxy from the environment. # - # If the proxy Bundler::URI is set after requests have been made, the next request + # If the proxy Gem::URI is set after requests have been made, the next request # will shut-down and re-open all connections. # # The +no_proxy+ query parameter can be used to specify hosts which shouldn't @@ -736,9 +736,9 @@ def private_key= key def proxy= proxy @proxy_uri = case proxy when :ENV then proxy_from_env - when Bundler::URI::HTTP then proxy + when Gem::URI::HTTP then proxy when nil then # ignore - else raise ArgumentError, 'proxy must be :ENV or a Bundler::URI::HTTP' + else raise ArgumentError, 'proxy must be :ENV or a Gem::URI::HTTP' end @no_proxy.clear @@ -763,13 +763,13 @@ def proxy= proxy end ## - # Creates a Bundler::URI for an HTTP proxy server from ENV variables. + # Creates a Gem::URI for an HTTP proxy server from ENV variables. # # If +HTTP_PROXY+ is set a proxy will be returned. # - # If +HTTP_PROXY_USER+ or +HTTP_PROXY_PASS+ are set the Bundler::URI is given the + # If +HTTP_PROXY_USER+ or +HTTP_PROXY_PASS+ are set the Gem::URI is given the # indicated user and password unless HTTP_PROXY contains either of these in - # the Bundler::URI. + # the Gem::URI. # # The +NO_PROXY+ ENV variable can be used to specify hosts which shouldn't # be reached via proxy; if set it should be a comma separated list of @@ -785,7 +785,7 @@ def proxy_from_env return nil if env_proxy.nil? or env_proxy.empty? - uri = Bundler::URI normalize_uri env_proxy + uri = Gem::URI normalize_uri env_proxy env_no_proxy = ENV['no_proxy'] || ENV['NO_PROXY'] @@ -863,7 +863,7 @@ def reset connection # +req+ must be a Gem::Net::HTTPGenericRequest subclass (see Gem::Net::HTTP for a list). def request uri, req = nil, &block - uri = Bundler::URI uri + uri = Gem::URI uri req = request_setup req || uri response = nil @@ -896,7 +896,7 @@ def request uri, req = nil, &block end ## - # Creates a GET request if +req_or_uri+ is a Bundler::URI and adds headers to the + # Creates a GET request if +req_or_uri+ is a Gem::URI and adds headers to the # request. # # Returns the request. diff --git a/lib/bundler/vendored_uri.rb b/lib/bundler/vendored_uri.rb index 905e8158e8ed2b..2efddc65f997a8 100644 --- a/lib/bundler/vendored_uri.rb +++ b/lib/bundler/vendored_uri.rb @@ -1,4 +1,21 @@ # frozen_string_literal: true module Bundler; end -require_relative "vendor/uri/lib/uri" + +# Use RubyGems vendored copy when available. Otherwise fallback to Bundler +# vendored copy. The vendored copy in Bundler can be removed once support for +# RubyGems 3.5 is dropped. + +begin + require "rubygems/vendor/uri/lib/uri" +rescue LoadError + require_relative "vendor/uri/lib/uri" + Gem::URI = Bundler::URI + + module Gem + def URI(uri) # rubocop:disable Naming/MethodName + Bundler::URI(uri) + end + module_function :URI + end +end diff --git a/spec/bundler/bundler/fetcher/base_spec.rb b/spec/bundler/bundler/fetcher/base_spec.rb index fa1021ecf77988..b8c6b57b10ef96 100644 --- a/spec/bundler/bundler/fetcher/base_spec.rb +++ b/spec/bundler/bundler/fetcher/base_spec.rb @@ -37,7 +37,7 @@ class TestClass < described_class; end end describe "#fetch_uri" do - let(:remote_uri_obj) { Bundler::URI("http://rubygems.org") } + let(:remote_uri_obj) { Gem::URI("http://rubygems.org") } before { allow(subject).to receive(:remote_uri).and_return(remote_uri_obj) } @@ -50,10 +50,10 @@ class TestClass < described_class; end end context "when the remote uri's host is not rubygems.org" do - let(:remote_uri_obj) { Bundler::URI("http://otherhost.org") } + let(:remote_uri_obj) { Gem::URI("http://otherhost.org") } it "should return the remote uri" do - expect(subject.fetch_uri).to eq(Bundler::URI("http://otherhost.org")) + expect(subject.fetch_uri).to eq(Gem::URI("http://otherhost.org")) end end diff --git a/spec/bundler/bundler/fetcher/compact_index_spec.rb b/spec/bundler/bundler/fetcher/compact_index_spec.rb index 9889d3cedeb0fc..a988171f341858 100644 --- a/spec/bundler/bundler/fetcher/compact_index_spec.rb +++ b/spec/bundler/bundler/fetcher/compact_index_spec.rb @@ -5,7 +5,7 @@ RSpec.describe Bundler::Fetcher::CompactIndex do let(:downloader) { double(:downloader) } - let(:display_uri) { Bundler::URI("http://sampleuri.com") } + let(:display_uri) { Gem::URI("http://sampleuri.com") } let(:remote) { double(:remote, cache_slug: "lsjdf", uri: display_uri) } let(:gem_remote_fetcher) { nil } let(:compact_index) { described_class.new(downloader, remote, display_uri, gem_remote_fetcher) } diff --git a/spec/bundler/bundler/fetcher/dependency_spec.rb b/spec/bundler/bundler/fetcher/dependency_spec.rb index 262ae39463b296..c420b7c07f2022 100644 --- a/spec/bundler/bundler/fetcher/dependency_spec.rb +++ b/spec/bundler/bundler/fetcher/dependency_spec.rb @@ -2,7 +2,7 @@ RSpec.describe Bundler::Fetcher::Dependency do let(:downloader) { double(:downloader) } - let(:remote) { double(:remote, uri: Bundler::URI("http://localhost:5000")) } + let(:remote) { double(:remote, uri: Gem::URI("http://localhost:5000")) } let(:display_uri) { "http://sample_uri.com" } let(:gem_remote_fetcher) { nil } @@ -255,7 +255,7 @@ end describe "#dependency_api_uri" do - let(:uri) { Bundler::URI("http://gem-api.com") } + let(:uri) { Gem::URI("http://gem-api.com") } context "with gem names" do let(:gem_names) { %w[foo bar bundler rubocop] } diff --git a/spec/bundler/bundler/fetcher/downloader_spec.rb b/spec/bundler/bundler/fetcher/downloader_spec.rb index 88a8c174f11ae3..d5c32f47305d5e 100644 --- a/spec/bundler/bundler/fetcher/downloader_spec.rb +++ b/spec/bundler/bundler/fetcher/downloader_spec.rb @@ -3,7 +3,7 @@ RSpec.describe Bundler::Fetcher::Downloader do let(:connection) { double(:connection) } let(:redirect_limit) { 5 } - let(:uri) { Bundler::URI("http://www.uri-to-fetch.com/api/v2/endpoint") } + let(:uri) { Gem::URI("http://www.uri-to-fetch.com/api/v2/endpoint") } let(:options) { double(:options) } subject { described_class.new(connection, redirect_limit) } @@ -41,19 +41,19 @@ before { http_response["location"] = "http://www.redirect-uri.com/api/v2/endpoint" } it "should try to fetch the redirect uri and iterate the # requests counter" do - expect(subject).to receive(:fetch).with(Bundler::URI("http://www.uri-to-fetch.com/api/v2/endpoint"), options, 0).and_call_original - expect(subject).to receive(:fetch).with(Bundler::URI("http://www.redirect-uri.com/api/v2/endpoint"), options, 1) + expect(subject).to receive(:fetch).with(Gem::URI("http://www.uri-to-fetch.com/api/v2/endpoint"), options, 0).and_call_original + expect(subject).to receive(:fetch).with(Gem::URI("http://www.redirect-uri.com/api/v2/endpoint"), options, 1) subject.fetch(uri, options, counter) end context "when the redirect uri and original uri are the same" do - let(:uri) { Bundler::URI("ssh://username:password@www.uri-to-fetch.com/api/v2/endpoint") } + let(:uri) { Gem::URI("ssh://username:password@www.uri-to-fetch.com/api/v2/endpoint") } before { http_response["location"] = "ssh://www.uri-to-fetch.com/api/v1/endpoint" } it "should set the same user and password for the redirect uri" do - expect(subject).to receive(:fetch).with(Bundler::URI("ssh://username:password@www.uri-to-fetch.com/api/v2/endpoint"), options, 0).and_call_original - expect(subject).to receive(:fetch).with(Bundler::URI("ssh://username:password@www.uri-to-fetch.com/api/v1/endpoint"), options, 1) + expect(subject).to receive(:fetch).with(Gem::URI("ssh://username:password@www.uri-to-fetch.com/api/v2/endpoint"), options, 0).and_call_original + expect(subject).to receive(:fetch).with(Gem::URI("ssh://username:password@www.uri-to-fetch.com/api/v1/endpoint"), options, 1) subject.fetch(uri, options, counter) end end @@ -89,7 +89,7 @@ end context "when the there are credentials provided in the request" do - let(:uri) { Bundler::URI("http://user:password@www.uri-to-fetch.com") } + let(:uri) { Gem::URI("http://user:password@www.uri-to-fetch.com") } it "should raise a Bundler::Fetcher::BadAuthenticationError that doesn't contain the password" do expect { subject.fetch(uri, options, counter) }. @@ -100,7 +100,7 @@ context "when the request response is a Gem::Net::HTTPForbidden" do let(:http_response) { Gem::Net::HTTPForbidden.new("1.1", 403, "Forbidden") } - let(:uri) { Bundler::URI("http://user:password@www.uri-to-fetch.com") } + let(:uri) { Gem::URI("http://user:password@www.uri-to-fetch.com") } it "should raise a Bundler::Fetcher::AuthenticationForbiddenError with the uri host" do expect { subject.fetch(uri, options, counter) }.to raise_error(Bundler::Fetcher::AuthenticationForbiddenError, @@ -117,7 +117,7 @@ end context "when the there are credentials provided in the request" do - let(:uri) { Bundler::URI("http://username:password@www.uri-to-fetch.com/api/v2/endpoint") } + let(:uri) { Gem::URI("http://username:password@www.uri-to-fetch.com/api/v2/endpoint") } it "should raise a Bundler::Fetcher::FallbackError that doesn't contain the password" do expect { subject.fetch(uri, options, counter) }. @@ -152,7 +152,7 @@ context "when there is a user provided in the request" do context "and there is also a password provided" do context "that contains cgi escaped characters" do - let(:uri) { Bundler::URI("http://username:password%24@www.uri-to-fetch.com/api/v2/endpoint") } + let(:uri) { Gem::URI("http://username:password%24@www.uri-to-fetch.com/api/v2/endpoint") } it "should request basic authentication with the username and password" do expect(net_http_get).to receive(:basic_auth).with("username", "password$") @@ -161,7 +161,7 @@ end context "that is all unescaped characters" do - let(:uri) { Bundler::URI("http://username:password@www.uri-to-fetch.com/api/v2/endpoint") } + let(:uri) { Gem::URI("http://username:password@www.uri-to-fetch.com/api/v2/endpoint") } it "should request basic authentication with the username and proper cgi compliant password" do expect(net_http_get).to receive(:basic_auth).with("username", "password") subject.request(uri, options) @@ -170,7 +170,7 @@ end context "and there is no password provided" do - let(:uri) { Bundler::URI("http://username@www.uri-to-fetch.com/api/v2/endpoint") } + let(:uri) { Gem::URI("http://username@www.uri-to-fetch.com/api/v2/endpoint") } it "should request basic authentication with just the user" do expect(net_http_get).to receive(:basic_auth).with("username", nil) @@ -179,7 +179,7 @@ end context "that contains cgi escaped characters" do - let(:uri) { Bundler::URI("http://username%24@www.uri-to-fetch.com/api/v2/endpoint") } + let(:uri) { Gem::URI("http://username%24@www.uri-to-fetch.com/api/v2/endpoint") } it "should request basic authentication with the proper cgi compliant password user" do expect(net_http_get).to receive(:basic_auth).with("username$", nil) @@ -230,7 +230,7 @@ end context "when the there are credentials provided in the request" do - let(:uri) { Bundler::URI("http://username:password@www.uri-to-fetch.com/api/v2/endpoint") } + let(:uri) { Gem::URI("http://username:password@www.uri-to-fetch.com/api/v2/endpoint") } before do allow(net_http_get).to receive(:basic_auth).with("username", "password") end diff --git a/spec/bundler/bundler/fetcher/index_spec.rb b/spec/bundler/bundler/fetcher/index_spec.rb index eea0050a6ba05e..dff9ccc3cc4cbd 100644 --- a/spec/bundler/bundler/fetcher/index_spec.rb +++ b/spec/bundler/bundler/fetcher/index_spec.rb @@ -20,7 +20,7 @@ end context "error handling" do - let(:remote_uri) { Bundler::URI("http://remote-uri.org") } + let(:remote_uri) { Gem::URI("http://remote-uri.org") } before do allow(rubygems).to receive(:fetch_all_remote_specs) { raise Gem::RemoteFetcher::FetchError.new(error_message, display_uri) } allow(subject).to receive(:remote_uri).and_return(remote_uri) diff --git a/spec/bundler/bundler/fetcher_spec.rb b/spec/bundler/bundler/fetcher_spec.rb index 5a2c5686939cc7..e20f7e7c481a7d 100644 --- a/spec/bundler/bundler/fetcher_spec.rb +++ b/spec/bundler/bundler/fetcher_spec.rb @@ -3,7 +3,7 @@ require "bundler/fetcher" RSpec.describe Bundler::Fetcher do - let(:uri) { Bundler::URI("https://example.com") } + let(:uri) { Gem::URI("https://example.com") } let(:remote) { double("remote", uri: uri, original_uri: nil) } subject(:fetcher) { Bundler::Fetcher.new(remote) } @@ -45,7 +45,7 @@ end context "when a rubygems source mirror is set" do - let(:orig_uri) { Bundler::URI("http://zombo.com") } + let(:orig_uri) { Gem::URI("http://zombo.com") } let(:remote_with_mirror) do double("remote", uri: uri, original_uri: orig_uri, anonymized_uri: uri) end diff --git a/spec/bundler/bundler/mirror_spec.rb b/spec/bundler/bundler/mirror_spec.rb index 1eaf1e9a8e01d0..ba1c6ed413daf8 100644 --- a/spec/bundler/bundler/mirror_spec.rb +++ b/spec/bundler/bundler/mirror_spec.rb @@ -36,12 +36,12 @@ it "takes a string for the uri but returns an uri object" do mirror.uri = "http://localhost:9292" - expect(mirror.uri).to eq(Bundler::URI("http://localhost:9292")) + expect(mirror.uri).to eq(Gem::URI("http://localhost:9292")) end it "takes an uri object for the uri" do - mirror.uri = Bundler::URI("http://localhost:9293") - expect(mirror.uri).to eq(Bundler::URI("http://localhost:9293")) + mirror.uri = Gem::URI("http://localhost:9293") + expect(mirror.uri).to eq(Gem::URI("http://localhost:9293")) end context "without a uri" do @@ -145,7 +145,7 @@ end RSpec.describe Bundler::Settings::Mirrors do - let(:localhost_uri) { Bundler::URI("http://localhost:9292") } + let(:localhost_uri) { Gem::URI("http://localhost:9292") } context "with a just created mirror" do let(:mirrors) do @@ -260,7 +260,7 @@ before { mirrors.parse("mirror.all.fallback_timeout", "true") } it "returns the source uri, not localhost" do - expect(mirrors.for("http://whatever.com").uri).to eq(Bundler::URI("http://whatever.com/")) + expect(mirrors.for("http://whatever.com").uri).to eq(Gem::URI("http://whatever.com/")) end end end @@ -270,7 +270,7 @@ context "without a fallback timeout" do it "returns the uri that is not mirrored" do - expect(mirrors.for("http://whatever.com").uri).to eq(Bundler::URI("http://whatever.com/")) + expect(mirrors.for("http://whatever.com").uri).to eq(Gem::URI("http://whatever.com/")) end it "returns localhost for rubygems.org" do @@ -282,11 +282,11 @@ before { mirrors.parse("mirror.http://rubygems.org/.fallback_timeout", "true") } it "returns the uri that is not mirrored" do - expect(mirrors.for("http://whatever.com").uri).to eq(Bundler::URI("http://whatever.com/")) + expect(mirrors.for("http://whatever.com").uri).to eq(Gem::URI("http://whatever.com/")) end it "returns rubygems.org for rubygems.org" do - expect(mirrors.for("http://rubygems.org/").uri).to eq(Bundler::URI("http://rubygems.org/")) + expect(mirrors.for("http://rubygems.org/").uri).to eq(Gem::URI("http://rubygems.org/")) end end end diff --git a/spec/bundler/bundler/rubygems_integration_spec.rb b/spec/bundler/bundler/rubygems_integration_spec.rb index 431f1256e3261b..b6bda9f43ece12 100644 --- a/spec/bundler/bundler/rubygems_integration_spec.rb +++ b/spec/bundler/bundler/rubygems_integration_spec.rb @@ -32,7 +32,7 @@ describe "#download_gem" do let(:bundler_retry) { double(Bundler::Retry) } - let(:uri) { Bundler::URI.parse("https://foo.bar") } + let(:uri) { Gem::URI.parse("https://foo.bar") } let(:cache_dir) { "#{Gem.path.first}/cache" } let(:spec) do spec = Gem::Specification.new("Foo", Gem::Version.new("2.5.2")) @@ -58,7 +58,7 @@ let(:prerelease_specs_response) { Marshal.dump(["prerelease_specs"]) } context "when a rubygems source mirror is set" do - let(:orig_uri) { Bundler::URI("http://zombo.com") } + let(:orig_uri) { Gem::URI("http://zombo.com") } let(:remote_with_mirror) { double("remote", uri: uri, original_uri: orig_uri) } it "sets the 'X-Gemfile-Source' header containing the original source" do diff --git a/spec/bundler/bundler/settings_spec.rb b/spec/bundler/bundler/settings_spec.rb index 27686e0c7aa00e..469af2b8c6cc75 100644 --- a/spec/bundler/bundler/settings_spec.rb +++ b/spec/bundler/bundler/settings_spec.rb @@ -179,7 +179,7 @@ end describe "#mirror_for" do - let(:uri) { Bundler::URI("https://rubygems.org/") } + let(:uri) { Gem::URI("https://rubygems.org/") } context "with no configured mirror" do it "returns the original URI" do @@ -192,7 +192,7 @@ end context "with a configured mirror" do - let(:mirror_uri) { Bundler::URI("https://rubygems-mirror.org/") } + let(:mirror_uri) { Gem::URI("https://rubygems-mirror.org/") } before { settings.set_local "mirror.https://rubygems.org/", mirror_uri.to_s } @@ -213,7 +213,7 @@ end context "with a file URI" do - let(:mirror_uri) { Bundler::URI("file:/foo/BAR/baz/qUx/") } + let(:mirror_uri) { Gem::URI("file:/foo/BAR/baz/qUx/") } it "returns the mirror URI" do expect(settings.mirror_for(uri)).to eq(mirror_uri) @@ -231,7 +231,7 @@ end describe "#credentials_for" do - let(:uri) { Bundler::URI("https://gemserver.example.org/") } + let(:uri) { Gem::URI("https://gemserver.example.org/") } let(:credentials) { "username:password" } context "with no configured credentials" do @@ -291,7 +291,7 @@ it "reads older keys without trailing slashes" do settings.set_local "mirror.https://rubygems.org", "http://rubygems-mirror.org" expect(settings.mirror_for("https://rubygems.org/")).to eq( - Bundler::URI("http://rubygems-mirror.org/") + Gem::URI("http://rubygems-mirror.org/") ) end diff --git a/spec/bundler/bundler/source/rubygems/remote_spec.rb b/spec/bundler/bundler/source/rubygems/remote_spec.rb index 07ce4f968e947a..56f3bee45915d3 100644 --- a/spec/bundler/bundler/source/rubygems/remote_spec.rb +++ b/spec/bundler/bundler/source/rubygems/remote_spec.rb @@ -11,8 +11,8 @@ def remote(uri) allow(Digest(:MD5)).to receive(:hexdigest).with(duck_type(:to_s)) {|string| "MD5HEX(#{string})" } end - let(:uri_no_auth) { Bundler::URI("https://gems.example.com") } - let(:uri_with_auth) { Bundler::URI("https://#{credentials}@gems.example.com") } + let(:uri_no_auth) { Gem::URI("https://gems.example.com") } + let(:uri_with_auth) { Gem::URI("https://#{credentials}@gems.example.com") } let(:credentials) { "username:password" } context "when the original URI has no credentials" do @@ -89,11 +89,11 @@ def remote(uri) end context "when the original URI has only a username" do - let(:uri) { Bundler::URI("https://SeCrEt-ToKeN@gem.fury.io/me/") } + let(:uri) { Gem::URI("https://SeCrEt-ToKeN@gem.fury.io/me/") } describe "#anonymized_uri" do it "returns the URI without username and password" do - expect(remote(uri).anonymized_uri).to eq(Bundler::URI("https://gem.fury.io/me/")) + expect(remote(uri).anonymized_uri).to eq(Gem::URI("https://gem.fury.io/me/")) end end @@ -105,9 +105,9 @@ def remote(uri) end context "when a mirror with inline credentials is configured for the URI" do - let(:uri) { Bundler::URI("https://rubygems.org/") } - let(:mirror_uri_with_auth) { Bundler::URI("https://username:password@rubygems-mirror.org/") } - let(:mirror_uri_no_auth) { Bundler::URI("https://rubygems-mirror.org/") } + let(:uri) { Gem::URI("https://rubygems.org/") } + let(:mirror_uri_with_auth) { Gem::URI("https://username:password@rubygems-mirror.org/") } + let(:mirror_uri_no_auth) { Gem::URI("https://rubygems-mirror.org/") } before { Bundler.settings.temporary("mirror.https://rubygems.org/" => mirror_uri_with_auth.to_s) } @@ -131,9 +131,9 @@ def remote(uri) end context "when a mirror with configured credentials is configured for the URI" do - let(:uri) { Bundler::URI("https://rubygems.org/") } - let(:mirror_uri_with_auth) { Bundler::URI("https://#{credentials}@rubygems-mirror.org/") } - let(:mirror_uri_no_auth) { Bundler::URI("https://rubygems-mirror.org/") } + let(:uri) { Gem::URI("https://rubygems.org/") } + let(:mirror_uri_with_auth) { Gem::URI("https://#{credentials}@rubygems-mirror.org/") } + let(:mirror_uri_no_auth) { Gem::URI("https://rubygems-mirror.org/") } before do Bundler.settings.temporary("mirror.https://rubygems.org/" => mirror_uri_no_auth.to_s) diff --git a/spec/bundler/bundler/source_list_spec.rb b/spec/bundler/bundler/source_list_spec.rb index 15811f83dc80d0..13453cb2a33a0d 100644 --- a/spec/bundler/bundler/source_list_spec.rb +++ b/spec/bundler/bundler/source_list_spec.rb @@ -125,8 +125,8 @@ it "adds the provided remote to the beginning of the aggregate source" do source_list.add_global_rubygems_remote("https://othersource.org") expect(returned_source.remotes).to eq [ - Bundler::URI("https://othersource.org/"), - Bundler::URI("https://rubygems.org/"), + Gem::URI("https://othersource.org/"), + Gem::URI("https://rubygems.org/"), ] end end diff --git a/spec/bundler/bundler/uri_credentials_filter_spec.rb b/spec/bundler/bundler/uri_credentials_filter_spec.rb index 466c1b8594ba5d..ed24744a1c2149 100644 --- a/spec/bundler/bundler/uri_credentials_filter_spec.rb +++ b/spec/bundler/bundler/uri_credentials_filter_spec.rb @@ -16,7 +16,7 @@ let(:credentials) { "oauth_token:x-oauth-basic@" } it "returns the uri without the oauth token" do - expect(subject.credential_filtered_uri(uri).to_s).to eq(Bundler::URI("https://x-oauth-basic@github.com/company/private-repo").to_s) + expect(subject.credential_filtered_uri(uri).to_s).to eq(Gem::URI("https://x-oauth-basic@github.com/company/private-repo").to_s) end it_behaves_like "original type of uri is maintained" @@ -26,7 +26,7 @@ let(:credentials) { "oauth_token:x@" } it "returns the uri without the oauth token" do - expect(subject.credential_filtered_uri(uri).to_s).to eq(Bundler::URI("https://x@github.com/company/private-repo").to_s) + expect(subject.credential_filtered_uri(uri).to_s).to eq(Gem::URI("https://x@github.com/company/private-repo").to_s) end it_behaves_like "original type of uri is maintained" @@ -37,7 +37,7 @@ let(:credentials) { "username1:hunter3@" } it "returns the uri without the password" do - expect(subject.credential_filtered_uri(uri).to_s).to eq(Bundler::URI("https://username1@github.com/company/private-repo").to_s) + expect(subject.credential_filtered_uri(uri).to_s).to eq(Gem::URI("https://username1@github.com/company/private-repo").to_s) end it_behaves_like "original type of uri is maintained" @@ -55,7 +55,7 @@ end context "uri is a uri object" do - let(:uri) { Bundler::URI("https://#{credentials}github.com/company/private-repo") } + let(:uri) { Gem::URI("https://#{credentials}github.com/company/private-repo") } it_behaves_like "sensitive credentials in uri are filtered out" end @@ -90,7 +90,7 @@ describe "#credential_filtered_string" do let(:str_to_filter) { "This is a git message containing a uri #{uri}!" } let(:credentials) { "" } - let(:uri) { Bundler::URI("https://#{credentials}github.com/company/private-repo") } + let(:uri) { Gem::URI("https://#{credentials}github.com/company/private-repo") } context "with a uri that contains credentials" do let(:credentials) { "oauth_token:x-oauth-basic@" } diff --git a/spec/bundler/install/gems/compact_index_spec.rb b/spec/bundler/install/gems/compact_index_spec.rb index 1375d8cab13bf8..50add8743bc6c2 100644 --- a/spec/bundler/install/gems/compact_index_spec.rb +++ b/spec/bundler/install/gems/compact_index_spec.rb @@ -575,7 +575,7 @@ def require(*args) let(:user) { "user" } let(:password) { "pass" } let(:basic_auth_source_uri) do - uri = Bundler::URI.parse(source_uri) + uri = Gem::URI.parse(source_uri) uri.user = user uri.password = password diff --git a/spec/bundler/install/gems/dependency_api_spec.rb b/spec/bundler/install/gems/dependency_api_spec.rb index e21164aec096dd..35468b3a1c012e 100644 --- a/spec/bundler/install/gems/dependency_api_spec.rb +++ b/spec/bundler/install/gems/dependency_api_spec.rb @@ -531,7 +531,7 @@ def require(*args) let(:user) { "user" } let(:password) { "pass" } let(:basic_auth_source_uri) do - uri = Bundler::URI.parse(source_uri) + uri = Gem::URI.parse(source_uri) uri.user = user uri.password = password diff --git a/spec/bundler/realworld/edgecases_spec.rb b/spec/bundler/realworld/edgecases_spec.rb index dc70271b6e6b98..94ca3554b11bf0 100644 --- a/spec/bundler/realworld/edgecases_spec.rb +++ b/spec/bundler/realworld/edgecases_spec.rb @@ -8,7 +8,7 @@ def rubygems_version(name, requirement) require "bundler/source/rubygems/remote" require "bundler/fetcher" rubygem = Bundler.ui.silence do - remote = Bundler::Source::Rubygems::Remote.new(Bundler::URI("https://rubygems.org")) + remote = Bundler::Source::Rubygems::Remote.new(Gem::URI("https://rubygems.org")) source = Bundler::Source::Rubygems.new fetcher = Bundler::Fetcher.new(remote) index = fetcher.specs([#{name.dump}], source) From 5f9c1200734ff3291e4b3d93a4d48158ef8b5ae6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 25 Jan 2024 16:44:08 +0100 Subject: [PATCH 608/640] [rubygems/rubygems] Remove no longer needed uri install during specs https://github.com/rubygems/rubygems/commit/7f35dc19c5 --- spec/bundler/runtime/inline_spec.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/spec/bundler/runtime/inline_spec.rb b/spec/bundler/runtime/inline_spec.rb index 22831fc3540a11..ffac30d6d83084 100644 --- a/spec/bundler/runtime/inline_spec.rb +++ b/spec/bundler/runtime/inline_spec.rb @@ -601,8 +601,6 @@ def confirm(msg, newline = nil) realworld_system_gems "pathname --version 0.2.0" - realworld_system_gems "uri" # this spec uses net/http which requires this default gem - script <<-RUBY, dir: tmp("path_without_gemfile"), env: { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s } require "bundler/inline" From 5a884c2e009381d6fb7d2ebc9ffe48bd3e1472be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 25 Jan 2024 16:46:29 +0100 Subject: [PATCH 609/640] [rubygems/rubygems] Add a spec to prove uri is no longer loaded https://github.com/rubygems/rubygems/commit/3a262f55c8 --- spec/bundler/runtime/setup_spec.rb | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/spec/bundler/runtime/setup_spec.rb b/spec/bundler/runtime/setup_spec.rb index ba53f3b1db32ee..d51e63e17ba72f 100644 --- a/spec/bundler/runtime/setup_spec.rb +++ b/spec/bundler/runtime/setup_spec.rb @@ -1337,6 +1337,33 @@ def lock_with(ruby_version = nil) expect(out).to eq("undefined\nconstant") end + it "does not load uri while reading gemspecs", rubygems: ">= 3.6.0.dev" do + Dir.mkdir bundled_app("test") + + create_file(bundled_app("test/test.gemspec"), <<-G) + Gem::Specification.new do |s| + s.name = "test" + s.version = "1.0.0" + s.summary = "test" + s.authors = ['John Doe'] + s.homepage = 'https://example.com' + end + G + + install_gemfile <<-G + source "#{file_uri_for(gem_repo1)}" + gem "test", path: "#{bundled_app("test")}" + G + + ruby <<-RUBY + require "bundler/setup" + puts defined?(URI) || "undefined" + require "uri" + puts defined?(URI) || "undefined" + RUBY + expect(out).to eq("undefined\nconstant") + end + describe "default gem activation" do let(:exemptions) do exempts = %w[did_you_mean bundler uri pathname] From 2956d3a5115fdbfb5591dcb63e482c24c9c175b9 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 29 Jan 2024 12:18:26 +0900 Subject: [PATCH 610/640] Removed duplicated license file --- lib/rubygems/vendor/uri/LICENSE.txt | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 lib/rubygems/vendor/uri/LICENSE.txt diff --git a/lib/rubygems/vendor/uri/LICENSE.txt b/lib/rubygems/vendor/uri/LICENSE.txt deleted file mode 100644 index a009caefea81f2..00000000000000 --- a/lib/rubygems/vendor/uri/LICENSE.txt +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. From 355480dec6692b35b1404ef398da9360c02705b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 15 Jan 2024 15:03:29 +0100 Subject: [PATCH 611/640] [rubygems/rubygems] Properly restore empty env vars https://github.com/rubygems/rubygems/commit/e0d68a8688 --- lib/bundler/environment_preserver.rb | 4 ++-- .../bundler/environment_preserver_spec.rb | 16 ++++++++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/lib/bundler/environment_preserver.rb b/lib/bundler/environment_preserver.rb index 57013f5d507d8d..19eb6b1b7496b5 100644 --- a/lib/bundler/environment_preserver.rb +++ b/lib/bundler/environment_preserver.rb @@ -58,7 +58,7 @@ def backup env = @original.clone @keys.each do |key| value = env[key] - if !value.nil? && !value.empty? + if !value.nil? env[@prefix + key] ||= value elsif value.nil? env[@prefix + key] ||= INTENTIONALLY_NIL @@ -72,7 +72,7 @@ def restore env = @original.clone @keys.each do |key| value_original = env[@prefix + key] - next if value_original.nil? || value_original.empty? + next if value_original.nil? if value_original == INTENTIONALLY_NIL env.delete(key) else diff --git a/spec/bundler/bundler/environment_preserver_spec.rb b/spec/bundler/bundler/environment_preserver_spec.rb index 530ca6f8356d70..6c7066d0c604a6 100644 --- a/spec/bundler/bundler/environment_preserver_spec.rb +++ b/spec/bundler/bundler/environment_preserver_spec.rb @@ -27,8 +27,12 @@ context "when a key is empty" do let(:env) { { "foo" => "" } } - it "should not create backup entries" do - expect(subject).not_to have_key "BUNDLER_ORIG_foo" + it "should keep the original entry" do + expect(subject["foo"]).to be_empty + end + + it "should still create backup entries" do + expect(subject).to have_key "BUNDLER_ORIG_foo" end end @@ -71,8 +75,12 @@ context "when the original key is empty" do let(:env) { { "foo" => "my-foo", "BUNDLER_ORIG_foo" => "" } } - it "should keep the current value" do - expect(subject["foo"]).to eq("my-foo") + it "should restore the original value" do + expect(subject["foo"]).to be_empty + end + + it "should delete the backup value" do + expect(subject.key?("BUNDLER_ORIG_foo")).to eq(false) end end end From 1991c6d7a03b9b38bb3ff58949a08271f40cbc38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 17 Jan 2024 14:04:35 +0100 Subject: [PATCH 612/640] [rubygems/rubygems] Remove now unnecessary elseif https://github.com/rubygems/rubygems/commit/d05b9e659b Co-authored-by: Samuel Giddins --- lib/bundler/environment_preserver.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/bundler/environment_preserver.rb b/lib/bundler/environment_preserver.rb index 19eb6b1b7496b5..c4c1b53fa4044c 100644 --- a/lib/bundler/environment_preserver.rb +++ b/lib/bundler/environment_preserver.rb @@ -60,7 +60,7 @@ def backup value = env[key] if !value.nil? env[@prefix + key] ||= value - elsif value.nil? + else env[@prefix + key] ||= INTENTIONALLY_NIL end end From 5ea4df6a8fe67762b4f204e04c0134d17ce471a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 16 Dec 2022 17:33:26 +0100 Subject: [PATCH 613/640] [rubygems/rubygems] Remove annoying debug info Sometimes you want this, sometimes you don't. And when you don't, this hides other debugging puts you may have added. https://github.com/rubygems/rubygems/commit/df37582c81 --- test/rubygems/test_gem_installer.rb | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/test/rubygems/test_gem_installer.rb b/test/rubygems/test_gem_installer.rb index edcc2216bd2b03..61609a26c9a0e3 100644 --- a/test/rubygems/test_gem_installer.rb +++ b/test/rubygems/test_gem_installer.rb @@ -1652,19 +1652,6 @@ def test_install_extension_flat installer.install end assert_path_exist so - rescue StandardError - puts "-" * 78 - puts File.read File.join(@gemhome, "gems", "a-2", "Makefile") - puts "-" * 78 - - path = File.join(@gemhome, "gems", "a-2", "gem_make.out") - - if File.exist?(path) - puts File.read(path) - puts "-" * 78 - end - - raise end end From e99951edfad6c636f561f1e6f3eda2e0609e8fbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 15 Dec 2022 23:59:13 +0100 Subject: [PATCH 614/640] [rubygems/rubygems] Simplify how extensions are built https://github.com/rubygems/rubygems/commit/0b8faf1e39 --- lib/rubygems/ext/builder.rb | 15 ++++++++---- lib/rubygems/ext/ext_conf_builder.rb | 35 +++++++++------------------ test/rubygems/test_gem_ext_builder.rb | 12 ++++----- 3 files changed, 27 insertions(+), 35 deletions(-) diff --git a/lib/rubygems/ext/builder.rb b/lib/rubygems/ext/builder.rb index be1ba3031cc9ee..cc067c710aa821 100644 --- a/lib/rubygems/ext/builder.rb +++ b/lib/rubygems/ext/builder.rb @@ -19,7 +19,14 @@ def self.class_name $1.downcase end - def self.make(dest_path, results, make_dir = Dir.pwd, sitedir = nil, targets = ["clean", "", "install"]) + def self.make(dest_path, results, make_dir = Dir.pwd, targets_or_sitedir = ["clean", "", "install"], old_targets = ["clean", "", "install"]) + if !targets_or_sitedir.is_a?(Array) + verbose { "sitedir parameter to Gem::Ext::Builder.make is getting ignored. sitearchdir and sitelibdir are now always set to the first argument passed to this method. Please stop passing this parameter" } + targets = old_targets + else + targets = targets_or_sitedir + end + unless File.exist? File.join(make_dir, "Makefile") raise Gem::InstallError, "Makefile not found" end @@ -35,10 +42,8 @@ def self.make(dest_path, results, make_dir = Dir.pwd, sitedir = nil, targets = [ env = [destdir] - if sitedir - env << format("sitearchdir=%s", sitedir) - env << format("sitelibdir=%s", sitedir) - end + env << format("sitearchdir=%s", dest_path) + env << format("sitelibdir=%s", dest_path) targets.each do |target| # Pass DESTDIR via command line to override what's in MAKEFLAGS diff --git a/lib/rubygems/ext/ext_conf_builder.rb b/lib/rubygems/ext/ext_conf_builder.rb index f38fe5947ec7b3..3eed37f485906e 100644 --- a/lib/rubygems/ext/ext_conf_builder.rb +++ b/lib/rubygems/ext/ext_conf_builder.rb @@ -9,15 +9,6 @@ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder def self.build(extension, dest_path, results, args=[], lib_dir=nil, extension_dir=Dir.pwd) require "fileutils" - require "tempfile" - - tmp_dest = Dir.mktmpdir(".gem.", extension_dir) - - # Some versions of `mktmpdir` return absolute paths, which will break make - # if the paths contain spaces. - # - # As such, we convert to a relative path. - tmp_dest_relative = get_relative_path(tmp_dest.clone, extension_dir) destdir = ENV["DESTDIR"] @@ -39,35 +30,31 @@ def self.build(extension, dest_path, results, args=[], lib_dir=nil, extension_di ENV["DESTDIR"] = nil - make dest_path, results, extension_dir, tmp_dest_relative - - full_tmp_dest = File.join(extension_dir, tmp_dest_relative) + rel_dest_path = get_relative_path(dest_path, extension_dir) + make rel_dest_path, results, extension_dir # TODO: remove in RubyGems 4 if Gem.install_extension_in_lib && lib_dir FileUtils.mkdir_p lib_dir - entries = Dir.entries(full_tmp_dest) - %w[. ..] - entries = entries.map {|entry| File.join full_tmp_dest, entry } + entries = Dir.entries(dest_path) - %w[. ..] + entries = entries.map {|entry| File.join dest_path, entry } FileUtils.cp_r entries, lib_dir, remove_destination: true end - FileUtils::Entry_.new(full_tmp_dest).traverse do |ent| - destent = ent.class.new(dest_path, ent.rel) - destent.exist? || FileUtils.mv(ent.path, destent.path) - end - - make dest_path, results, extension_dir, tmp_dest_relative, ["clean"] + make dest_path, results, extension_dir, ["clean"] ensure ENV["DESTDIR"] = destdir end results - ensure - FileUtils.rm_rf tmp_dest if tmp_dest end def self.get_relative_path(path, base) - path[0..base.length - 1] = "." if path.start_with?(base) - path + path.split("/").zip(base.split("/")).inject(String.new) do |result, (path_component, base_component)| + next result if path_component == base_component + result.prepend("../") if base_component + result.concat("#{path_component}/") if path_component + result + end end end diff --git a/test/rubygems/test_gem_ext_builder.rb b/test/rubygems/test_gem_ext_builder.rb index baf61404685540..0da029de8781d8 100644 --- a/test/rubygems/test_gem_ext_builder.rb +++ b/test/rubygems/test_gem_ext_builder.rb @@ -48,9 +48,9 @@ def test_class_make results = results.join("\n").b - assert_match(/DESTDIR\\=#{ENV["DESTDIR"]} clean$/, results) - assert_match(/DESTDIR\\=#{ENV["DESTDIR"]}$/, results) - assert_match(/DESTDIR\\=#{ENV["DESTDIR"]} install$/, results) + assert_match(/DESTDIR\\=#{ENV["DESTDIR"]} sitearchdir\\=#{@dest_path} sitelibdir\\=#{@dest_path} clean$/, results) + assert_match(/DESTDIR\\=#{ENV["DESTDIR"]} sitearchdir\\=#{@dest_path} sitelibdir\\=#{@dest_path}$/, results) + assert_match(/DESTDIR\\=#{ENV["DESTDIR"]} sitearchdir\\=#{@dest_path} sitelibdir\\=#{@dest_path} install/, results) unless results.include?("nmake") assert_match(/^clean: destination$/, results) @@ -77,9 +77,9 @@ def test_class_make_no_clean results = results.join("\n").b - assert_match(/DESTDIR\\=#{ENV["DESTDIR"]} clean$/, results) - assert_match(/DESTDIR\\=#{ENV["DESTDIR"]}$/, results) - assert_match(/DESTDIR\\=#{ENV["DESTDIR"]} install$/, results) + assert_match(/DESTDIR\\=#{ENV["DESTDIR"]} sitearchdir\\=#{@dest_path} sitelibdir\\=#{@dest_path} clean$/, results) + assert_match(/DESTDIR\\=#{ENV["DESTDIR"]} sitearchdir\\=#{@dest_path} sitelibdir\\=#{@dest_path}$/, results) + assert_match(/DESTDIR\\=#{ENV["DESTDIR"]} sitearchdir\\=#{@dest_path} sitelibdir\\=#{@dest_path} install$/, results) end def test_custom_make_with_options From 933ede5d768a0e411336ea27840727442c42d3df Mon Sep 17 00:00:00 2001 From: Masato Ohba Date: Sat, 27 Jan 2024 22:35:38 +0900 Subject: [PATCH 615/640] [rubygems/rubygems] Remove `travis_removal_info` `travis_removal_info` is added by https://github.com/rubygems/rubygems/pull/6150. According to the comment, it's supposed to be removed at bundler v2.5.0 but it hasn't. https://github.com/rubygems/rubygems/commit/e18797d43f --- lib/bundler/cli/gem.rb | 14 --------- spec/bundler/commands/newgem_spec.rb | 30 ------------------- .../test_gem_commands_setup_command.rb | 2 -- 3 files changed, 46 deletions(-) diff --git a/lib/bundler/cli/gem.rb b/lib/bundler/cli/gem.rb index f0bb3aab188906..b6571d0e86ccd2 100644 --- a/lib/bundler/cli/gem.rb +++ b/lib/bundler/cli/gem.rb @@ -32,7 +32,6 @@ def initialize(options, gem_name, thor) validate_ext_name if @extension validate_rust_builder_rubygems_version if @extension == "rust" - travis_removal_info end def run @@ -448,19 +447,6 @@ def standard_version "1.3" end - # TODO: remove at next minor release - def travis_removal_info - if options[:ci] == "travis" - Bundler.ui.error "Support for Travis CI was removed from gem skeleton generator." - exit 1 - end - - if Bundler.settings["gem.ci"] == "travis" - Bundler.ui.error "Support for Travis CI was removed from gem skeleton generator, but it is present in bundle config. Please configure another provider using `bundle config set gem.ci SERVICE` (where SERVICE is one of github/gitlab/circle) or unset configuration using `bundle config unset gem.ci`." - exit 1 - end - end - def validate_rust_builder_rubygems_version if Gem::Version.new(rust_builder_required_rubygems_version) > Gem.rubygems_version Bundler.ui.error "Your RubyGems version (#{Gem.rubygems_version}) is too old to build Rust extension. Please update your RubyGems using `gem update --system` or any other way and try again." diff --git a/spec/bundler/commands/newgem_spec.rb b/spec/bundler/commands/newgem_spec.rb index 7aafc0e49be779..199340b1314ccd 100644 --- a/spec/bundler/commands/newgem_spec.rb +++ b/spec/bundler/commands/newgem_spec.rb @@ -932,24 +932,6 @@ def create_temporary_dir(dir) end end - context "--ci set to travis" do - it "generates a GitHub Actions config file" do - bundle "gem #{gem_name} --ci=travis", raise_on_error: false - expect(err).to include("Support for Travis CI was removed from gem skeleton generator.") - - expect(bundled_app("#{gem_name}/.travis.yml")).to_not exist - end - end - - context "--ci set to travis" do - it "generates a GitHub Actions config file" do - bundle "gem #{gem_name} --ci=travis", raise_on_error: false - expect(err).to include("Support for Travis CI was removed from gem skeleton generator.") - - expect(bundled_app("#{gem_name}/.travis.yml")).to_not exist - end - end - context "--ci set to github" do it "generates a GitHub Actions config file" do bundle "gem #{gem_name} --ci=github" @@ -1000,18 +982,6 @@ def create_temporary_dir(dir) end end - context "gem.ci setting set to travis" do - it "errors with friendly message" do - bundle "config set gem.ci travis" - bundle "gem #{gem_name}", raise_on_error: false - - expect(err).to include("Support for Travis CI was removed from gem skeleton generator,") - expect(err).to include("bundle config unset gem.ci") - - expect(bundled_app("#{gem_name}/.travis.yml")).to_not exist - end - end - context "gem.ci setting set to github" do it "generates a GitHub Actions config file" do bundle "config set gem.ci github" diff --git a/test/rubygems/test_gem_commands_setup_command.rb b/test/rubygems/test_gem_commands_setup_command.rb index 6859d7a5cbf1c6..43f695f147a7d3 100644 --- a/test/rubygems/test_gem_commands_setup_command.rb +++ b/test/rubygems/test_gem_commands_setup_command.rb @@ -31,7 +31,6 @@ def setup bundler/lib/bundler/man/gemfile.5 bundler/lib/bundler/man/gemfile.5.ronn bundler/lib/bundler/templates/.circleci/config.yml - bundler/lib/bundler/templates/.travis.yml ] create_dummy_files(filelist) @@ -178,7 +177,6 @@ def test_install_lib assert_path_exist File.join(dir, "bundler/b.rb") assert_path_exist File.join(dir, "bundler/templates/.circleci/config.yml") - assert_path_exist File.join(dir, "bundler/templates/.travis.yml") end end From 8bff7e996cf65159b4ed7b55c284de6651b7e637 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 29 Jan 2024 17:16:49 +0900 Subject: [PATCH 616/640] [DOC] Move "Execution Shell on Windows" under "Execution Shell" --- process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/process.c b/process.c index c2ef3979d85776..a7cbee7e82f73b 100644 --- a/process.c +++ b/process.c @@ -9077,7 +9077,7 @@ proc_warmup(VALUE _) * * /bin/bash: CONTRIBUTING.md COPYING COPYING.ja * - * === Execution Shell on Windows + * ==== Execution Shell on Windows * * On Windows, the shell invoked is determined by environment variable * +RUBYSHELL+, if defined, or +COMSPEC+ otherwise; the entire string From 0d4de0f4b1b9ac90be437bf1bac6851dd1d96fd0 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Mon, 29 Jan 2024 09:49:15 +0000 Subject: [PATCH 617/640] wasm: align fiber stack pointer to 16 bytes In WebAssembly C ABI, the linear stack pointer must be always aligned to 16 bytes like other archs. The misaligned stack pointer causes some weird memory corruption since compiler assumes the aligned stack pointer. --- coroutine/asyncify/Context.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/coroutine/asyncify/Context.h b/coroutine/asyncify/Context.h index 7dba829a1dfd50..71791a400492b5 100644 --- a/coroutine/asyncify/Context.h +++ b/coroutine/asyncify/Context.h @@ -13,6 +13,7 @@ #include #include +#include #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; } From 3e6e3ca2627b1aa71b17de902cc1b8188246a828 Mon Sep 17 00:00:00 2001 From: Hiroya Fujinami Date: Mon, 29 Jan 2024 23:51:26 +0900 Subject: [PATCH 618/640] Correctly handle consecutive lookarounds (#9738) Fix [Bug #20207] Fix [Bug #20212] Handling consecutive lookarounds in init_cache_opcodes is buggy, so it causes invalid memory access reported in [Bug #20207] and [Bug #20212]. This fixes it by using recursive functions to detected lookarounds nesting correctly. --- regexec.c | 223 ++++++++++++++++++++++++--------------- test/ruby/test_regexp.rb | 12 +++ 2 files changed, 150 insertions(+), 85 deletions(-) diff --git a/regexec.c b/regexec.c index 56e3ab8967d367..150d36ccc89745 100644 --- a/regexec.c +++ b/regexec.c @@ -258,18 +258,19 @@ We encode a match cache point to an integer value by the following equation: A bit-array for memoizing (recording) match cache points once backtracked. */ -/* count the total number of cache opcodes for allocating a match cache buffer. */ -static OnigPosition -count_num_cache_opcodes(const regex_t* reg, long* num_cache_opcodes_ptr) +static OnigPosition count_num_cache_opcodes_inner( + const regex_t* reg, + MemNumType current_repeat_mem, int lookaround_nesting, + UChar** pp, long* num_cache_opcodes_ptr +) { - UChar* p = reg->p; - UChar* pend = p + reg->used; + UChar* p = *pp; + UChar* pend = reg->p + reg->used; LengthType len; MemNumType repeat_mem; OnigEncoding enc = reg->enc; - MemNumType current_repeat_mem = -1; - long num_cache_opcodes = 0; - int lookaround_nesting = 0; + long num_cache_opcodes = *num_cache_opcodes_ptr; + OnigPosition result; while (p < pend) { switch (*p++) { @@ -402,7 +403,16 @@ count_num_cache_opcodes(const regex_t* reg, long* num_cache_opcodes_ptr) if (reg->repeat_range[repeat_mem].lower == 0) { num_cache_opcodes++; } - current_repeat_mem = repeat_mem; + result = count_num_cache_opcodes_inner(reg, repeat_mem, lookaround_nesting, &p, &num_cache_opcodes); + if (result < 0 || num_cache_opcodes < 0) { + goto fail; + } + { + OnigRepeatRange *repeat_range = ®->repeat_range[repeat_mem]; + if (repeat_range->lower < repeat_range->upper) { + num_cache_opcodes++; + } + } break; case OP_REPEAT_INC: case OP_REPEAT_INC_NG: @@ -411,14 +421,7 @@ count_num_cache_opcodes(const regex_t* reg, long* num_cache_opcodes_ptr) // A lone or invalid OP_REPEAT_INC is found. goto impossible; } - { - OnigRepeatRange *repeat_range = ®->repeat_range[repeat_mem]; - if (repeat_range->lower < repeat_range->upper) { - num_cache_opcodes++; - } - current_repeat_mem = -1; - } - break; + goto exit; case OP_REPEAT_INC_SG: case OP_REPEAT_INC_NG_SG: goto impossible; @@ -438,7 +441,10 @@ count_num_cache_opcodes(const regex_t* reg, long* num_cache_opcodes_ptr) // A look-around nested in a atomic grouping is found. goto impossible; } - lookaround_nesting++; + result = count_num_cache_opcodes_inner(reg, current_repeat_mem, lookaround_nesting + 1, &p, &num_cache_opcodes); + if (result < 0 || num_cache_opcodes < 0) { + goto fail; + } break; case OP_PUSH_POS_NOT: if (lookaround_nesting < 0) { @@ -446,7 +452,10 @@ count_num_cache_opcodes(const regex_t* reg, long* num_cache_opcodes_ptr) goto impossible; } p += SIZE_RELADDR; - lookaround_nesting++; + result = count_num_cache_opcodes_inner(reg, current_repeat_mem, lookaround_nesting + 1, &p, &num_cache_opcodes); + if (result < 0 || num_cache_opcodes < 0) { + goto fail; + } break; case OP_PUSH_LOOK_BEHIND_NOT: if (lookaround_nesting < 0) { @@ -455,25 +464,26 @@ count_num_cache_opcodes(const regex_t* reg, long* num_cache_opcodes_ptr) } p += SIZE_RELADDR; p += SIZE_LENGTH; - lookaround_nesting++; - break; - case OP_POP_POS: - case OP_FAIL_POS: - case OP_FAIL_LOOK_BEHIND_NOT: - lookaround_nesting--; + result = count_num_cache_opcodes_inner(reg, current_repeat_mem, lookaround_nesting + 1, &p, &num_cache_opcodes); + if (result < 0 || num_cache_opcodes < 0) { + goto fail; + } break; case OP_PUSH_STOP_BT: if (lookaround_nesting != 0) { // A nested atomic grouping is found. goto impossible; } - lookaround_nesting++; - lookaround_nesting *= -1; + result = count_num_cache_opcodes_inner(reg, current_repeat_mem, -1, &p, &num_cache_opcodes); + if (result < 0 || num_cache_opcodes < 0) { + goto fail; + } break; + case OP_POP_POS: + case OP_FAIL_POS: + case OP_FAIL_LOOK_BEHIND_NOT: case OP_POP_STOP_BT: - lookaround_nesting *= -1; - lookaround_nesting--; - break; + goto exit; case OP_LOOK_BEHIND: p += SIZE_LENGTH; break; @@ -507,9 +517,15 @@ count_num_cache_opcodes(const regex_t* reg, long* num_cache_opcodes_ptr) } } +exit: + *pp = p; *num_cache_opcodes_ptr = num_cache_opcodes; return 0; +fail: + *num_cache_opcodes_ptr = num_cache_opcodes; + return result; + impossible: *num_cache_opcodes_ptr = NUM_CACHE_OPCODES_IMPOSSIBLE; return 0; @@ -518,48 +534,49 @@ count_num_cache_opcodes(const regex_t* reg, long* num_cache_opcodes_ptr) return ONIGERR_UNDEFINED_BYTECODE; } -/* collect cache opcodes from the given regex program, and compute the total number of cache points. */ +/* count the total number of cache opcodes for allocating a match cache buffer. */ static OnigPosition -init_cache_opcodes(const regex_t* reg, OnigCacheOpcode* cache_opcodes, long* num_cache_points_ptr) +count_num_cache_opcodes(const regex_t* reg, long* num_cache_opcodes_ptr) { - UChar* pbegin; UChar* p = reg->p; - UChar* pend = p + reg->used; + *num_cache_opcodes_ptr = 0; + OnigPosition result = count_num_cache_opcodes_inner(reg, -1, 0, &p, num_cache_opcodes_ptr); + if (result == 0 && *num_cache_opcodes_ptr >= 0 && p != reg->p + reg->used) { + return ONIGERR_UNDEFINED_BYTECODE; + } + + return result; +} + +static OnigPosition +init_cache_opcodes_inner( + const regex_t* reg, + MemNumType current_repeat_mem, int lookaround_nesting, + OnigCacheOpcode** cache_opcodes_ptr, UChar** pp, long* num_cache_points_ptr +) +{ + UChar* p = *pp; + UChar* pend = reg->p + reg->used; + UChar* pbegin; LengthType len; MemNumType repeat_mem; OnigEncoding enc = reg->enc; - MemNumType current_repeat_mem = -1; - long cache_point = 0; - long num_cache_points_at_repeat = 0; - int lookaround_nesting = 0; - const OnigCacheOpcode* cache_opcodes_begin = cache_opcodes; - OnigCacheOpcode* cache_opcodes_at_repeat = NULL; + long cache_point = *num_cache_points_ptr; + OnigCacheOpcode *cache_opcodes = *cache_opcodes_ptr; + OnigPosition result; # define INC_CACHE_OPCODES do {\ cache_opcodes->addr = pbegin;\ - cache_opcodes->cache_point = cache_point - num_cache_points_at_repeat;\ + cache_opcodes->cache_point = cache_point;\ cache_opcodes->outer_repeat_mem = current_repeat_mem;\ - cache_opcodes->num_cache_points_at_outer_repeat = num_cache_points_at_repeat;\ + cache_opcodes->num_cache_points_at_outer_repeat = 0;\ cache_opcodes->num_cache_points_in_outer_repeat = 0;\ cache_opcodes->lookaround_nesting = lookaround_nesting;\ + cache_opcodes->match_addr = NULL;\ cache_point += lookaround_nesting != 0 ? 2 : 1;\ cache_opcodes++;\ } while (0) -# define INC_LOOKAROUND_NESTING lookaround_nesting++ -# define DEC_LOOKAROUND_NESTING do {\ - UChar* match_addr = p - 1;\ - OnigCacheOpcode* cache_opcodes_in_lookaround = cache_opcodes - 1;\ - while (\ - cache_opcodes_in_lookaround >= cache_opcodes_begin &&\ - cache_opcodes_in_lookaround->lookaround_nesting == lookaround_nesting\ - ) {\ - cache_opcodes_in_lookaround->match_addr = match_addr;\ - cache_opcodes_in_lookaround--;\ - }\ - lookaround_nesting--;\ - } while (0) - while (p < pend) { pbegin = p; switch (*p++) { @@ -692,33 +709,31 @@ init_cache_opcodes(const regex_t* reg, OnigCacheOpcode* cache_opcodes, long* num if (reg->repeat_range[repeat_mem].lower == 0) { INC_CACHE_OPCODES; } - current_repeat_mem = repeat_mem; - num_cache_points_at_repeat = cache_point; - cache_opcodes_at_repeat = cache_opcodes; - break; - case OP_REPEAT_INC: - case OP_REPEAT_INC_NG: - GET_MEMNUM_INC(repeat_mem, p); { - long num_cache_points_in_repeat = cache_point - num_cache_points_at_repeat; + long num_cache_points_in_repeat = 0; + long num_cache_points_at_repeat = cache_point; + OnigCacheOpcode* cache_opcodes_in_repeat = cache_opcodes; + result = init_cache_opcodes_inner(reg, repeat_mem, lookaround_nesting, &cache_opcodes, &p, &num_cache_points_in_repeat); + if (result != 0) { + goto fail; + } OnigRepeatRange *repeat_range = ®->repeat_range[repeat_mem]; if (repeat_range->lower < repeat_range->upper) { INC_CACHE_OPCODES; cache_point -= lookaround_nesting != 0 ? 2 : 1; } - cache_point -= num_cache_points_in_repeat; int repeat_bounds = repeat_range->upper == 0x7fffffff ? 1 : repeat_range->upper - repeat_range->lower; cache_point += num_cache_points_in_repeat * repeat_range->lower + (num_cache_points_in_repeat + (lookaround_nesting != 0 ? 2 : 1)) * repeat_bounds; - OnigCacheOpcode* cache_opcodes_in_repeat = cache_opcodes - 1; - while (cache_opcodes_at_repeat <= cache_opcodes_in_repeat) { + for (; cache_opcodes_in_repeat < cache_opcodes; cache_opcodes_in_repeat++) { + cache_opcodes_in_repeat->num_cache_points_at_outer_repeat = num_cache_points_at_repeat; cache_opcodes_in_repeat->num_cache_points_in_outer_repeat = num_cache_points_in_repeat; - cache_opcodes_in_repeat--; } - current_repeat_mem = -1; - num_cache_points_at_repeat = 0; - cache_opcodes_at_repeat = NULL; } break; + case OP_REPEAT_INC: + case OP_REPEAT_INC_NG: + p += SIZE_MEMNUM; + goto exit; case OP_REPEAT_INC_SG: case OP_REPEAT_INC_NG_SG: goto unexpected_bytecode_error; @@ -734,33 +749,51 @@ init_cache_opcodes(const regex_t* reg, OnigCacheOpcode* cache_opcodes, long* num break; case OP_PUSH_POS: - INC_LOOKAROUND_NESTING; + lookaround: + { + OnigCacheOpcode* cache_opcodes_in_lookaround = cache_opcodes; + result = init_cache_opcodes_inner(reg, current_repeat_mem, lookaround_nesting + 1, &cache_opcodes, &p, &cache_point); + if (result != 0) { + goto fail; + } + UChar* match_addr = p - 1; + for (; cache_opcodes_in_lookaround < cache_opcodes; cache_opcodes_in_lookaround++) { + if (cache_opcodes_in_lookaround->match_addr == NULL) { + cache_opcodes_in_lookaround->match_addr = match_addr; + } + } + } break; case OP_PUSH_POS_NOT: p += SIZE_RELADDR; - INC_LOOKAROUND_NESTING; - break; + goto lookaround; case OP_PUSH_LOOK_BEHIND_NOT: p += SIZE_RELADDR; p += SIZE_LENGTH; - INC_LOOKAROUND_NESTING; + goto lookaround; + case OP_PUSH_STOP_BT: + { + OnigCacheOpcode* cache_opcodes_in_atomic = cache_opcodes; + result = init_cache_opcodes_inner(reg, current_repeat_mem, -1, &cache_opcodes, &p, &cache_point); + if (result != 0) { + goto fail; + } + UChar* match_addr = p - 1; + for (; cache_opcodes_in_atomic < cache_opcodes; cache_opcodes_in_atomic++) { + if (cache_opcodes_in_atomic->match_addr == NULL) { + cache_opcodes_in_atomic->match_addr = match_addr; + } + } + } break; case OP_POP_POS: case OP_FAIL_POS: case OP_FAIL_LOOK_BEHIND_NOT: - DEC_LOOKAROUND_NESTING; - break; - case OP_PUSH_STOP_BT: - INC_LOOKAROUND_NESTING; - lookaround_nesting *= -1; - break; case OP_POP_STOP_BT: - lookaround_nesting *= -1; - DEC_LOOKAROUND_NESTING; - break; + goto exit; case OP_LOOK_BEHIND: p += SIZE_LENGTH; - break; + break; case OP_ABSENT_END: case OP_ABSENT: @@ -790,15 +823,35 @@ init_cache_opcodes(const regex_t* reg, OnigCacheOpcode* cache_opcodes, long* num } } +exit: + *cache_opcodes_ptr = cache_opcodes; + *pp = p; *num_cache_points_ptr = cache_point; return 0; +fail: + return result; + unexpected_bytecode_error: return ONIGERR_UNEXPECTED_BYTECODE; bytecode_error: return ONIGERR_UNDEFINED_BYTECODE; } + +/* collect cache opcodes from the given regex program, and compute the total number of cache points. */ +static OnigPosition +init_cache_opcodes(const regex_t* reg, OnigCacheOpcode* cache_opcodes_ptr, long* num_cache_points_ptr) +{ + UChar* p = reg->p; + *num_cache_points_ptr = 0; + OnigPosition result = init_cache_opcodes_inner(reg, -1, 0, &cache_opcodes_ptr, &p, num_cache_points_ptr); + if (result == 0 && p != reg->p + reg->used) { + return ONIGERR_UNDEFINED_BYTECODE; + } + + return result; +} #else static OnigPosition count_num_cache_opcodes(regex_t* reg, long* num_cache_opcodes) diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb index 7206e858d04b61..390a8cb1938d5b 100644 --- a/test/ruby/test_regexp.rb +++ b/test/ruby/test_regexp.rb @@ -2016,6 +2016,18 @@ def test_bug_20098 # [Bug #20098] assert(/^(?:.+){2,4}?b|b/.match? "aaaabaa") end + def test_bug_20207 # [Bug #20207] + assert(!'clan'.match?(/(?=.*a)(?!.*n)/)) + end + + def test_bug_20212 # [Bug #20212] + regex = Regexp.new( + /\A((?=.*?[a-z])(?!.*--)[a-z\d]+[a-z\d-]*[a-z\d]+).((?=.*?[a-z])(?!.*--)[a-z\d]+[a-z\d-]*[a-z\d]+).((?=.*?[a-z])(?!.*--)[a-zd]+[a-zd-]*[a-zd]+).((?=.*?[a-z])(?!.*--)[a-zd]+[a-zd-]*[a-zd]+)\Z/x + ) + string = "www.google.com" + 100.times.each { assert(regex.match?(string)) } + end + def test_linear_time_p assert_send [Regexp, :linear_time?, /a/] assert_send [Regexp, :linear_time?, 'a'] From c422805bbb95b1a45de1873d51cc1ec4fbbd27a0 Mon Sep 17 00:00:00 2001 From: Matt Valentine-House Date: Mon, 29 Jan 2024 14:11:34 +0000 Subject: [PATCH 619/640] [PRISM] Fix encoding for interpolated strings. This wasn't taking into account strings with flags set on the containing node that could affect the encoding. It does now --- prism_compile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prism_compile.c b/prism_compile.c index ecbe8810ba8fd0..88172716afb38c 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -737,7 +737,7 @@ pm_interpolated_node_compile(pm_node_list_t *parts, rb_iseq_t *iseq, NODE dummy_ if (PM_NODE_TYPE_P(part, PM_STRING_NODE)) { pm_string_node_t *string_node = (pm_string_node_t *)part; - VALUE string_value = parse_string(&string_node->unescaped, parser); + VALUE string_value = parse_string_encoded((pm_node_t *)string_node, &string_node->unescaped, parser); if (RTEST(current_string)) { current_string = rb_str_concat(current_string, string_value); } From fde3d065e65d804ce5d8fc982aafd4c2d94d4388 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Fri, 26 Jan 2024 12:19:54 -0500 Subject: [PATCH 620/640] Add removable and refcnt output to labels Co-Authored-By: Kevin Newton --- compile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compile.c b/compile.c index f1deca3c291f71..3221c6d98141c6 100644 --- a/compile.c +++ b/compile.c @@ -10859,7 +10859,7 @@ dump_disasm_list_with_cursor(const LINK_ELEMENT *link, const LINK_ELEMENT *curr, case ISEQ_ELEMENT_LABEL: { lobj = (LABEL *)link; - printf(LABEL_FORMAT" [sp: %d]%s\n", lobj->label_no, lobj->sp, + printf(LABEL_FORMAT" [sp: %d, unremovable: %d, refcnt: %d]%s\n", lobj->label_no, lobj->sp, lobj->unremovable, lobj->refcnt, dest == lobj ? " <---" : ""); break; } From adf29c9a986cb3510b9ddd55e0738b18076f41ad Mon Sep 17 00:00:00 2001 From: Maxime Chevalier-Boisvert Date: Mon, 29 Jan 2024 10:36:34 -0500 Subject: [PATCH 621/640] YJIT: add asm comment when we clear local types (#9713) Small PR to add a comment when we clear local variable types, so we can be aware that it's happening when looking at the disasm. --- yjit/src/backend/ir.rs | 7 +++++++ yjit/src/codegen.rs | 10 +++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/yjit/src/backend/ir.rs b/yjit/src/backend/ir.rs index 303026d830d500..3dae4b6f7c9f62 100644 --- a/yjit/src/backend/ir.rs +++ b/yjit/src/backend/ir.rs @@ -1173,6 +1173,13 @@ impl Assembler } } + /// Erase local variable type information + /// eg: because of a call we can't track + pub fn clear_local_types(&mut self) { + asm_comment!(self, "clear local variable types"); + self.ctx.clear_local_types(); + } + /// Spill all live stack temps from registers to the stack pub fn spill_temps(&mut self) { // Forget registers above the stack top diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index a8c77b8d01b46d..cb979b247bfd7d 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -356,7 +356,7 @@ fn jit_prepare_routine_call( // In case the routine calls Ruby methods, it can set local variables // through Kernel#binding and other means. - asm.ctx.clear_local_types(); + asm.clear_local_types(); } /// Record the current codeblock write position for rewriting into a jump into @@ -5892,7 +5892,7 @@ fn gen_send_cfunc( asm.store(ec_cfp_opnd, CFP); // cfunc calls may corrupt types - asm.ctx.clear_local_types(); + asm.clear_local_types(); // Note: the return block of gen_send_iseq() has ctx->sp_offset == 1 // which allows for sharing the same successor. @@ -6951,7 +6951,7 @@ fn gen_send_iseq( callee_ctx.upgrade_opnd_type(SelfOpnd, recv_type); // The callee might change locals through Kernel#binding and other means. - asm.ctx.clear_local_types(); + asm.clear_local_types(); // Pop arguments and receiver in return context and // mark it as a continuation of gen_leave() @@ -8012,7 +8012,7 @@ fn gen_invokeblock_specialized( asm.mov(stack_ret, ret); // cfunc calls may corrupt types - asm.ctx.clear_local_types(); + asm.clear_local_types(); // Share the successor with other chains jump_to_next_insn(jit, asm, ocb); @@ -8170,7 +8170,7 @@ fn gen_invokesuper_specialized( jit.assume_method_lookup_stable(asm, ocb, cme); // Method calls may corrupt types - asm.ctx.clear_local_types(); + asm.clear_local_types(); match cme_def_type { VM_METHOD_TYPE_ISEQ => { From e050097bebe64e86e97e915fa74a3fc010c588e8 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 29 Jan 2024 11:02:11 -0500 Subject: [PATCH 622/640] [ruby/prism] Raise diagnostics for parser https://github.com/ruby/prism/commit/102b4a16f5 --- lib/prism/translation/parser.rb | 57 +++++++++++++++++------- lib/prism/translation/parser/compiler.rb | 9 +++- 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/lib/prism/translation/parser.rb b/lib/prism/translation/parser.rb index 7cc18ac5de32ed..589b33b6fee56a 100644 --- a/lib/prism/translation/parser.rb +++ b/lib/prism/translation/parser.rb @@ -9,6 +9,20 @@ module Translation # the parser gem, and overrides the parse* methods to parse with prism and # then translate. class Parser < ::Parser::Base + # The parser gem has a list of diagnostics with a hard-coded set of error + # messages. We create our own diagnostic class in order to set our own + # error messages. + class Diagnostic < ::Parser::Diagnostic + # The message generated by prism. + attr_reader :message + + # Initialize a new diagnostic with the given message and location. + def initialize(message, location) + @message = message + super(:error, :prism_error, {}, location, []) + end + end + Racc_debug_parser = false # :nodoc: def version # :nodoc: @@ -28,10 +42,9 @@ def parse(source_buffer) @source_buffer = source_buffer source = source_buffer.source - build_ast( - Prism.parse(source, filepath: source_buffer.name).value, - build_offset_cache(source) - ) + result = unwrap(Prism.parse(source, filepath: source_buffer.name)) + + build_ast(result.value, build_offset_cache(source)) ensure @source_buffer = nil end @@ -42,7 +55,7 @@ def parse_with_comments(source_buffer) source = source_buffer.source offset_cache = build_offset_cache(source) - result = Prism.parse(source, filepath: source_buffer.name) + result = unwrap(Prism.parse(source, filepath: source_buffer.name)) [ build_ast(result.value, offset_cache), @@ -59,7 +72,8 @@ def tokenize(source_buffer, _recover = false) source = source_buffer.source offset_cache = build_offset_cache(source) - result = Prism.parse_lex(source, filepath: source_buffer.name) + result = unwrap(Prism.parse_lex(source, filepath: source_buffer.name)) + program, tokens = result.value [ @@ -79,6 +93,18 @@ def try_declare_numparam(node) private + # If there was a error generated during the parse, then raise an + # appropriate syntax error. Otherwise return the result. + def unwrap(result) + return result if result.success? + + error = result.errors.first + offset_cache = build_offset_cache(source_buffer.source) + + diagnostic = Diagnostic.new(error.message, build_range(error.location, offset_cache)) + raise ::Parser::SyntaxError, diagnostic + end + # Prism deals with offsets in bytes, while the parser gem deals with # offsets in characters. We need to handle this conversion in order to # build the parser gem AST. @@ -109,15 +135,7 @@ def build_ast(program, offset_cache) # Build the parser gem comments from the prism comments. def build_comments(comments, offset_cache) comments.map do |comment| - location = comment.location - - ::Parser::Source::Comment.new( - ::Parser::Source::Range.new( - source_buffer, - offset_cache[location.start_offset], - offset_cache[location.end_offset] - ) - ) + ::Parser::Source::Comment.new(build_range(comment.location, offset_cache)) end end @@ -126,6 +144,15 @@ def build_tokens(tokens, offset_cache) Lexer.new(source_buffer, tokens.map(&:first), offset_cache).to_a end + # Build a range from a prism location. + def build_range(location, offset_cache) + ::Parser::Source::Range.new( + source_buffer, + offset_cache[location.start_offset], + offset_cache[location.end_offset] + ) + end + require_relative "parser/compiler" require_relative "parser/lexer" diff --git a/lib/prism/translation/parser/compiler.rb b/lib/prism/translation/parser/compiler.rb index d03de9efc5507e..ccd02c2181b738 100644 --- a/lib/prism/translation/parser/compiler.rb +++ b/lib/prism/translation/parser/compiler.rb @@ -83,11 +83,16 @@ def visit_array_pattern_node(node) elements = [*node.requireds] elements << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode) elements.concat(node.posts) + visited = visit_all(elements) + + if node.rest.is_a?(ImplicitRestNode) + visited[-1] = builder.match_with_trailing_comma(visited[-1], token(node.rest.location)) + end if node.constant - builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.array_pattern(nil, visit_all(elements), nil), token(node.closing_loc)) + builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.array_pattern(nil, visited, nil), token(node.closing_loc)) else - builder.array_pattern(token(node.opening_loc), visit_all(elements), token(node.closing_loc)) + builder.array_pattern(token(node.opening_loc), visited, token(node.closing_loc)) end end From 9a5a11f3d0e5d9b595d51aafe8fdadfe384568ad Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 29 Jan 2024 09:47:52 -0500 Subject: [PATCH 623/640] [PRISM] Use the splatkw instruction Fixes ruby/prism#2272. --- prism_compile.c | 12 ++++++++---- test/ruby/test_compile_prism.rb | 22 ++++++++++++++++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 88172716afb38c..1d9f6f9e62fb8b 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2749,12 +2749,16 @@ pm_compile_call(rb_iseq_t *iseq, const pm_call_node_t *call_node, LINK_ANCHOR *c else if (!popped) { ADD_INSN1(ret, &dummy_line_node, setn, INT2FIX(orig_argc + 1)); } + } - ADD_SEND_R(ret, &dummy_line_node, method_id, INT2FIX(orig_argc), block_iseq, INT2FIX(flags), kw_arg); - PM_POP_UNLESS_POPPED; + if ((flags & VM_CALL_KW_SPLAT) && (flags & VM_CALL_ARGS_BLOCKARG) && !(flags & VM_CALL_KW_SPLAT_MUT)) { + ADD_INSN(ret, &dummy_line_node, splatkw); } - else { - ADD_SEND_R(ret, &dummy_line_node, method_id, INT2FIX(orig_argc), block_iseq, INT2FIX(flags), kw_arg); + + ADD_SEND_R(ret, &dummy_line_node, method_id, INT2FIX(orig_argc), block_iseq, INT2FIX(flags), kw_arg); + + if (pm_node->flags & PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE) { + PM_POP_UNLESS_POPPED; } if (call_node->base.flags & PM_CALL_NODE_FLAGS_SAFE_NAVIGATION) { diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index ff0a252b71db60..93dcd4245046ee 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -827,6 +827,28 @@ def o.bar(**) = Hash(**) o.bar(hello: "world") RUBY + + # Test that AssocSplatNode is evaluated before BlockArgumentNode using + # the splatkw instruction + assert_prism_eval(<<~RUBY) + o = Struct.new(:ary) do + def to_hash + ary << :to_hash + {} + end + + def to_proc + ary << :to_proc + -> {} + end + + def t(...); end + end.new + o.ary = [] + + o.t(**o, &o) + o.ary + RUBY end def test_HashNode From b0711b1cf152afad0a480ee2f9bedd142a0d24ac Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Mon, 29 Jan 2024 12:21:17 -0500 Subject: [PATCH 624/640] YJIT: Fix tailcall and JIT entry eating up FINISH frames (#9729) Suppose YJIT runs a rb_vm_opt_send_without_block() fallback and the control frame stack looks like: ``` will_tailcall_bar [FINISH] caller_that_used_fallback ``` will_tailcall_bar() runs in the interpreter and sets up a tailcall. Right before JIT_EXEC() in the `send` instruction, the stack will look like: ``` bar [FINISH] caller_that_used_fallback ``` Previously, JIT_EXEC() ran bar() in JIT code, which caused the `FINISH` flag to return to the interpreter instead of to the JIT code running caller_that_used_fallback(), causing code to run twice and probably crash. Recent flaky failures on CI about "each stub expects a particular iseq" are probably due to leaving methods twice in `test_optimizations.rb`. Only run JIT code from the interpreter if a new frame is pushed. --- test/ruby/test_optimization.rb | 11 +++++++++++ vm_exec.h | 3 ++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb index 8d669e502ccc61..70b6bde6ed611b 100644 --- a/test/ruby/test_optimization.rb +++ b/test/ruby/test_optimization.rb @@ -451,6 +451,17 @@ def one_plus_two assert_equal(3, one_plus_two) end + def test_tailcall_and_post_arg + tailcall(<<~RUBY) + def ret_const = :ok + + def post_arg(_a = 1, _b) = ret_const + RUBY + + # YJIT probably uses a fallback on the call to post_arg + assert_equal(:ok, post_arg(0)) + end + def test_tailcall_interrupted_by_sigint bug12576 = 'ruby-core:76327' script = "#{<<-"begin;"}\n#{<<~'end;'}" diff --git a/vm_exec.h b/vm_exec.h index 152410a6a738bf..b1eeb506607454 100644 --- a/vm_exec.h +++ b/vm_exec.h @@ -176,7 +176,8 @@ default: \ // Run the JIT from the interpreter #define JIT_EXEC(ec, val) do { \ rb_jit_func_t func; \ - if (val == Qundef && (func = jit_compile(ec))) { \ + /* don't run tailcalls since that breaks FINISH */ \ + if (val == Qundef && GET_CFP() != ec->cfp && (func = jit_compile(ec))) { \ val = func(ec, ec->cfp); \ RESTORE_REGS(); /* fix cfp for tailcall */ \ if (ec->tag->state) THROW_EXCEPTION(val); \ From d42330d702b2bb3b8aad105c4e55b0585ce23928 Mon Sep 17 00:00:00 2001 From: Willian Tenfen W Date: Sun, 31 Dec 2023 14:29:53 -0300 Subject: [PATCH 625/640] [rubygems/rubygems] Improve gem login scope selection https://github.com/rubygems/rubygems/commit/26c7abe5f6 --- lib/rubygems/gemcutter_utilities.rb | 29 +++++-- .../test_gem_commands_signin_command.rb | 75 +++++++++++++++---- test/rubygems/test_gem_gemcutter_utilities.rb | 2 +- 3 files changed, 86 insertions(+), 20 deletions(-) diff --git a/lib/rubygems/gemcutter_utilities.rb b/lib/rubygems/gemcutter_utilities.rb index 5e5c9d5a64c133..796938c40b4a22 100644 --- a/lib/rubygems/gemcutter_utilities.rb +++ b/lib/rubygems/gemcutter_utilities.rb @@ -10,7 +10,8 @@ module Gem::GemcutterUtilities ERROR_CODE = 1 - API_SCOPES = [:index_rubygems, :push_rubygem, :yank_rubygem, :add_owner, :remove_owner, :access_webhooks, :show_dashboard].freeze + API_SCOPES = [:index_rubygems, :push_rubygem, :yank_rubygem, :add_owner, :remove_owner, :access_webhooks].freeze + EXCLUSIVELY_API_SCOPES = [:show_dashboard].freeze include Gem::Text @@ -309,15 +310,31 @@ def pretty_host(host) end def get_scope_params(scope) - scope_params = {} + scope_params = { index_rubygems: true } if scope scope_params = { scope => true } else - say "Please select scopes you want to enable for the API key (y/n)" - API_SCOPES.each do |s| - selected = ask_yes_no(s.to_s, false) - scope_params[s] = true if selected + say "The default access scope is:" + scope_params.each do |k, _v| + say " #{k}: y" + end + say "\n" + customise = ask_yes_no("Do you want to customise scopes?", false) + if customise + EXCLUSIVELY_API_SCOPES.each do |excl_scope| + selected = ask_yes_no("#{excl_scope} (exclusive scope, answering yes will not prompt for other scopes)", false) + next unless selected + + return { excl_scope => true } + end + + scope_params = {} + + API_SCOPES.each do |s| + selected = ask_yes_no(s.to_s, false) + scope_params[s] = true if selected + end end say "\n" end diff --git a/test/rubygems/test_gem_commands_signin_command.rb b/test/rubygems/test_gem_commands_signin_command.rb index fd4ffb414a3fba..29e5edceb7c822 100644 --- a/test/rubygems/test_gem_commands_signin_command.rb +++ b/test/rubygems/test_gem_commands_signin_command.rb @@ -85,7 +85,7 @@ def test_execute_with_host_permanent_redirect headers: { "location" => redirected_uri } ) Gem::RemoteFetcher.fetcher = fetcher - ui = Gem::MockGemUi.new("you@example.com\nsecret\n\n\n\n\n\n\n\n\n") + ui = Gem::MockGemUi.new("you@example.com\nsecret\n\n\n") assert_raise Gem::MockGemUi::TermError do use_ui ui do @@ -106,51 +106,98 @@ def test_execute_with_valid_creds_set_for_default_host assert_equal api_key, credentials[:rubygems_api_key] end - def test_execute_with_key_name_and_scope + def test_execute_with_key_name_default_scope email = "you@example.com" password = "secret" api_key = "1234abcd" fetcher = Gem::RemoteFetcher.fetcher - key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\n\ny\n\n\n\n\n\n" + key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\n\n" util_capture(key_name_ui, nil, api_key, fetcher) { @cmd.execute } user = ENV["USER"] || ENV["USERNAME"] assert_match "API Key name [#{Socket.gethostname}-#{user}", key_name_ui.output + assert_match "The default access scope is:", key_name_ui.output + assert_match "index_rubygems: y", key_name_ui.output + assert_match "Do you want to customise scopes? [yN]", key_name_ui.output + assert_equal "name=test-key&index_rubygems=true", fetcher.last_request.body + + credentials = load_yaml_file Gem.configuration.credentials_path + assert_equal api_key, credentials[:rubygems_api_key] + end + + def test_execute_with_key_name_and_custom_scope + email = "you@example.com" + password = "secret" + api_key = "1234abcd" + fetcher = Gem::RemoteFetcher.fetcher + + key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\ny\n\n\ny\n\n\n\n\n\n\n" + util_capture(key_name_ui, nil, api_key, fetcher) { @cmd.execute } + + user = ENV["USER"] || ENV["USERNAME"] + + assert_match "API Key name [#{Socket.gethostname}-#{user}", key_name_ui.output + assert_match "The default access scope is:", key_name_ui.output + assert_match "Do you want to customise scopes? [yN]", key_name_ui.output + assert_match "show_dashboard (exclusive scope, answering yes will not prompt for other scopes) [yN]", key_name_ui.output assert_match "index_rubygems [yN]", key_name_ui.output assert_match "push_rubygem [yN]", key_name_ui.output assert_match "yank_rubygem [yN]", key_name_ui.output assert_match "add_owner [yN]", key_name_ui.output assert_match "remove_owner [yN]", key_name_ui.output assert_match "access_webhooks [yN]", key_name_ui.output - assert_match "show_dashboard [yN]", key_name_ui.output assert_equal "name=test-key&push_rubygem=true", fetcher.last_request.body credentials = load_yaml_file Gem.configuration.credentials_path assert_equal api_key, credentials[:rubygems_api_key] end - def test_execute_with_key_name_scope_and_mfa_level_of_ui_only + def test_execute_with_key_name_and_exclusive_scope + email = "you@example.com" + password = "secret" + api_key = "1234abcd" + fetcher = Gem::RemoteFetcher.fetcher + + key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\ny\ny\n" + util_capture(key_name_ui, nil, api_key, fetcher) { @cmd.execute } + + user = ENV["USER"] || ENV["USERNAME"] + + assert_match "API Key name [#{Socket.gethostname}-#{user}", key_name_ui.output + assert_match "The default access scope is:", key_name_ui.output + assert_match "index_rubygems: y", key_name_ui.output + assert_match "Do you want to customise scopes? [yN]", key_name_ui.output + assert_match "show_dashboard (exclusive scope, answering yes will not prompt for other scopes) [yN]", key_name_ui.output + assert_equal "name=test-key&show_dashboard=true", fetcher.last_request.body + + credentials = load_yaml_file Gem.configuration.credentials_path + assert_equal api_key, credentials[:rubygems_api_key] + end + + def test_execute_with_key_name_custom_scope_and_mfa_level_of_ui_only email = "you@example.com" password = "secret" api_key = "1234abcd" fetcher = Gem::RemoteFetcher.fetcher mfa_level = "ui_only" - key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\n\ny\n\n\n\n\n\ny" + key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\ny\n\n\ny\n\n\n\n\n\n\ny" util_capture(key_name_ui, nil, api_key, fetcher, mfa_level) { @cmd.execute } user = ENV["USER"] || ENV["USERNAME"] assert_match "API Key name [#{Socket.gethostname}-#{user}", key_name_ui.output + assert_match "The default access scope is:", key_name_ui.output + assert_match "Do you want to customise scopes? [yN]", key_name_ui.output + assert_match "show_dashboard (exclusive scope, answering yes will not prompt for other scopes) [yN]", key_name_ui.output assert_match "index_rubygems [yN]", key_name_ui.output assert_match "push_rubygem [yN]", key_name_ui.output assert_match "yank_rubygem [yN]", key_name_ui.output assert_match "add_owner [yN]", key_name_ui.output assert_match "remove_owner [yN]", key_name_ui.output assert_match "access_webhooks [yN]", key_name_ui.output - assert_match "show_dashboard [yN]", key_name_ui.output assert_match "Would you like to enable MFA for this key? (strongly recommended) [yn]", key_name_ui.output assert_equal "name=test-key&push_rubygem=true&mfa=true", fetcher.last_request.body @@ -158,26 +205,28 @@ def test_execute_with_key_name_scope_and_mfa_level_of_ui_only assert_equal api_key, credentials[:rubygems_api_key] end - def test_execute_with_key_name_scope_and_mfa_level_of_gem_signin + def test_execute_with_key_name_custom_scope_and_mfa_level_of_gem_signin email = "you@example.com" password = "secret" api_key = "1234abcd" fetcher = Gem::RemoteFetcher.fetcher mfa_level = "ui_and_gem_signin" - key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\n\ny\n\n\n\n\n\ny" + key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\ny\n\n\ny\n\n\n\n\n\n\ny" util_capture(key_name_ui, nil, api_key, fetcher, mfa_level) { @cmd.execute } user = ENV["USER"] || ENV["USERNAME"] assert_match "API Key name [#{Socket.gethostname}-#{user}", key_name_ui.output + assert_match "The default access scope is:", key_name_ui.output + assert_match "Do you want to customise scopes? [yN]", key_name_ui.output + assert_match "show_dashboard (exclusive scope, answering yes will not prompt for other scopes) [yN]", key_name_ui.output assert_match "index_rubygems [yN]", key_name_ui.output assert_match "push_rubygem [yN]", key_name_ui.output assert_match "yank_rubygem [yN]", key_name_ui.output assert_match "add_owner [yN]", key_name_ui.output assert_match "remove_owner [yN]", key_name_ui.output assert_match "access_webhooks [yN]", key_name_ui.output - assert_match "show_dashboard [yN]", key_name_ui.output assert_match "Would you like to enable MFA for this key? (strongly recommended) [yn]", key_name_ui.output assert_equal "name=test-key&push_rubygem=true&mfa=true", fetcher.last_request.body @@ -207,7 +256,7 @@ def test_execute_on_gemserver_without_profile_me_endpoint api_key = "1234abcd" fetcher = Gem::RemoteFetcher.fetcher - key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\n\ny\n\n\n\n\n\ny" + key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\ny\n\n\ny\n\n\n\n\n\n\ny" # Set the expected response for the Web-API supplied ENV["RUBYGEMS_HOST"] = host @@ -221,13 +270,13 @@ def test_execute_on_gemserver_without_profile_me_endpoint user = ENV["USER"] || ENV["USERNAME"] assert_match "API Key name [#{Socket.gethostname}-#{user}", key_name_ui.output + assert_match "show_dashboard (exclusive scope, answering yes will not prompt for other scopes) [yN]", key_name_ui.output assert_match "index_rubygems [yN]", key_name_ui.output assert_match "push_rubygem [yN]", key_name_ui.output assert_match "yank_rubygem [yN]", key_name_ui.output assert_match "add_owner [yN]", key_name_ui.output assert_match "remove_owner [yN]", key_name_ui.output assert_match "access_webhooks [yN]", key_name_ui.output - assert_match "show_dashboard [yN]", key_name_ui.output assert_equal "name=test-key&push_rubygem=true", fetcher.last_request.body end @@ -248,7 +297,7 @@ def util_capture(ui_stub = nil, host = nil, api_key = nil, fetcher = Gem::FakeFe fetcher.data[profile] = profile_response Gem::RemoteFetcher.fetcher = fetcher - sign_in_ui = ui_stub || Gem::MockGemUi.new("#{email}\n#{password}\n\n\n\n\n\n\n\n\n") + sign_in_ui = ui_stub || Gem::MockGemUi.new("#{email}\n#{password}\n\n\n") use_ui sign_in_ui do yield diff --git a/test/rubygems/test_gem_gemcutter_utilities.rb b/test/rubygems/test_gem_gemcutter_utilities.rb index 31933c9419ebd9..a3236e62768256 100644 --- a/test/rubygems/test_gem_gemcutter_utilities.rb +++ b/test/rubygems/test_gem_gemcutter_utilities.rb @@ -306,7 +306,7 @@ def util_sign_in(args: [], extra_input: "") ENV["RUBYGEMS_HOST"] = @fetcher.host Gem::RemoteFetcher.fetcher = @fetcher - @sign_in_ui = Gem::MockGemUi.new("#{email}\n#{password}\n\n\n\n\n\n\n\n\n" + extra_input) + @sign_in_ui = Gem::MockGemUi.new("#{email}\n#{password}\n\n\n" + extra_input) use_ui @sign_in_ui do if args.length > 0 From 1005b7d29ff78ab3d4dc60fa062c84bd03c44d6c Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Mon, 29 Jan 2024 09:23:29 -0800 Subject: [PATCH 626/640] Revert "Provisionally ignore panics that happen in these days often" This reverts commit e0f4c4e410a0e4c6cda67e9000696c8f1f01d8aa. We expect https://github.com/ruby/ruby/pull/9729 to address the failure. --- .github/workflows/yjit-macos.yml | 1 - .github/workflows/yjit-ubuntu.yml | 1 - 2 files changed, 2 deletions(-) diff --git a/.github/workflows/yjit-macos.yml b/.github/workflows/yjit-macos.yml index 1bab65f53ec9a3..93bbb4d93ed587 100644 --- a/.github/workflows/yjit-macos.yml +++ b/.github/workflows/yjit-macos.yml @@ -66,7 +66,6 @@ jobs: - test_task: 'check' configure: '--enable-yjit=dev' yjit_opts: '--yjit-call-threshold=1 --yjit-verify-ctx --yjit-code-gc' - continue-on-test_task: true # provisionally fail-fast: false env: diff --git a/.github/workflows/yjit-ubuntu.yml b/.github/workflows/yjit-ubuntu.yml index 59c8d21068d333..437f3d53397083 100644 --- a/.github/workflows/yjit-ubuntu.yml +++ b/.github/workflows/yjit-ubuntu.yml @@ -102,7 +102,6 @@ jobs: - test_task: 'check' configure: '--enable-yjit=dev' yjit_opts: '--yjit-call-threshold=1 --yjit-verify-ctx --yjit-code-gc' - continue-on-test_task: true # provisionally - test_task: 'test-bundled-gems' configure: '--enable-yjit=dev' From d39d9e066fb55694abf007da86f658c6c4855a89 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 29 Jan 2024 13:37:22 -0500 Subject: [PATCH 627/640] [ruby/prism] Fix binding power for modifier rescue https://github.com/ruby/prism/commit/f614863d79 --- prism/prism.c | 12 +-- test/prism/fixtures/rescue.txt | 2 + test/prism/snapshots/rescue.txt | 171 ++++++++++++++++++++------------ 3 files changed, 115 insertions(+), 70 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 69f896cbb6b716..36699f589456bf 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -10385,8 +10385,8 @@ parser_lex(pm_parser_t *parser) { typedef enum { PM_BINDING_POWER_UNSET = 0, // used to indicate this token cannot be used as an infix operator PM_BINDING_POWER_STATEMENT = 2, - PM_BINDING_POWER_MODIFIER = 4, // if unless until while - PM_BINDING_POWER_MODIFIER_RESCUE = 6, // rescue + PM_BINDING_POWER_MODIFIER_RESCUE = 4, // rescue + PM_BINDING_POWER_MODIFIER = 6, // if unless until while PM_BINDING_POWER_COMPOSITION = 8, // and or PM_BINDING_POWER_NOT = 10, // not PM_BINDING_POWER_MATCH = 12, // => in @@ -10440,15 +10440,15 @@ typedef struct { #define RIGHT_ASSOCIATIVE_UNARY(precedence) { precedence, precedence, false, false } pm_binding_powers_t pm_binding_powers[PM_TOKEN_MAXIMUM] = { + // rescue + [PM_TOKEN_KEYWORD_RESCUE_MODIFIER] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_MODIFIER_RESCUE), + // if unless until while [PM_TOKEN_KEYWORD_IF_MODIFIER] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_MODIFIER), [PM_TOKEN_KEYWORD_UNLESS_MODIFIER] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_MODIFIER), [PM_TOKEN_KEYWORD_UNTIL_MODIFIER] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_MODIFIER), [PM_TOKEN_KEYWORD_WHILE_MODIFIER] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_MODIFIER), - // rescue - [PM_TOKEN_KEYWORD_RESCUE_MODIFIER] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_MODIFIER_RESCUE), - // and or [PM_TOKEN_KEYWORD_AND] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_COMPOSITION), [PM_TOKEN_KEYWORD_OR] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_COMPOSITION), @@ -17472,7 +17472,7 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc case PM_UNDEF_NODE: // These expressions are statements, and cannot be followed by // operators (except modifiers). - if (pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER_RESCUE) { + if (pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER) { return node; } break; diff --git a/test/prism/fixtures/rescue.txt b/test/prism/fixtures/rescue.txt index 0d26fd2523f4a7..90530b70212729 100644 --- a/test/prism/fixtures/rescue.txt +++ b/test/prism/fixtures/rescue.txt @@ -29,3 +29,5 @@ def a a b: rescue end + +foo if bar rescue baz diff --git a/test/prism/snapshots/rescue.txt b/test/prism/snapshots/rescue.txt index 9627d4d9ce944c..939ba115aef47b 100644 --- a/test/prism/snapshots/rescue.txt +++ b/test/prism/snapshots/rescue.txt @@ -1,8 +1,8 @@ -@ ProgramNode (location: (1,0)-(31,3)) +@ ProgramNode (location: (1,0)-(33,21)) ├── locals: [:a] └── statements: - @ StatementsNode (location: (1,0)-(31,3)) - └── body: (length: 12) + @ StatementsNode (location: (1,0)-(33,21)) + └── body: (length: 13) ├── @ RescueModifierNode (location: (1,0)-(1,14)) │ ├── expression: │ │ @ CallNode (location: (1,0)-(1,3)) @@ -321,71 +321,114 @@ │ ├── rparen_loc: ∅ │ ├── equal_loc: (26,16)-(26,17) = "=" │ └── end_keyword_loc: ∅ - └── @ DefNode (location: (28,0)-(31,3)) - ├── name: :a - ├── name_loc: (28,4)-(28,5) = "a" - ├── receiver: ∅ - ├── parameters: ∅ - ├── body: - │ @ BeginNode (location: (29,2)-(31,3)) - │ ├── begin_keyword_loc: ∅ + ├── @ DefNode (location: (28,0)-(31,3)) + │ ├── name: :a + │ ├── name_loc: (28,4)-(28,5) = "a" + │ ├── receiver: ∅ + │ ├── parameters: ∅ + │ ├── body: + │ │ @ BeginNode (location: (29,2)-(31,3)) + │ │ ├── begin_keyword_loc: ∅ + │ │ ├── statements: + │ │ │ @ StatementsNode (location: (29,2)-(29,6)) + │ │ │ └── body: (length: 1) + │ │ │ └── @ CallNode (location: (29,2)-(29,6)) + │ │ │ ├── flags: ignore_visibility + │ │ │ ├── receiver: ∅ + │ │ │ ├── call_operator_loc: ∅ + │ │ │ ├── name: :a + │ │ │ ├── message_loc: (29,2)-(29,3) = "a" + │ │ │ ├── opening_loc: ∅ + │ │ │ ├── arguments: + │ │ │ │ @ ArgumentsNode (location: (29,4)-(29,6)) + │ │ │ │ ├── flags: ∅ + │ │ │ │ └── arguments: (length: 1) + │ │ │ │ └── @ KeywordHashNode (location: (29,4)-(29,6)) + │ │ │ │ ├── flags: symbol_keys + │ │ │ │ └── elements: (length: 1) + │ │ │ │ └── @ AssocNode (location: (29,4)-(29,6)) + │ │ │ │ ├── key: + │ │ │ │ │ @ SymbolNode (location: (29,4)-(29,6)) + │ │ │ │ │ ├── flags: forced_us_ascii_encoding + │ │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ │ ├── value_loc: (29,4)-(29,5) = "b" + │ │ │ │ │ ├── closing_loc: (29,5)-(29,6) = ":" + │ │ │ │ │ └── unescaped: "b" + │ │ │ │ ├── value: + │ │ │ │ │ @ ImplicitNode (location: (29,4)-(29,6)) + │ │ │ │ │ └── value: + │ │ │ │ │ @ CallNode (location: (29,4)-(29,6)) + │ │ │ │ │ ├── flags: ignore_visibility + │ │ │ │ │ ├── receiver: ∅ + │ │ │ │ │ ├── call_operator_loc: ∅ + │ │ │ │ │ ├── name: :b + │ │ │ │ │ ├── message_loc: (29,4)-(29,5) = "b" + │ │ │ │ │ ├── opening_loc: ∅ + │ │ │ │ │ ├── arguments: ∅ + │ │ │ │ │ ├── closing_loc: ∅ + │ │ │ │ │ └── block: ∅ + │ │ │ │ └── operator_loc: ∅ + │ │ │ ├── closing_loc: ∅ + │ │ │ └── block: ∅ + │ │ ├── rescue_clause: + │ │ │ @ RescueNode (location: (30,0)-(30,6)) + │ │ │ ├── keyword_loc: (30,0)-(30,6) = "rescue" + │ │ │ ├── exceptions: (length: 0) + │ │ │ ├── operator_loc: ∅ + │ │ │ ├── reference: ∅ + │ │ │ ├── statements: ∅ + │ │ │ └── consequent: ∅ + │ │ ├── else_clause: ∅ + │ │ ├── ensure_clause: ∅ + │ │ └── end_keyword_loc: (31,0)-(31,3) = "end" + │ ├── locals: [] + │ ├── locals_body_index: 0 + │ ├── def_keyword_loc: (28,0)-(28,3) = "def" + │ ├── operator_loc: ∅ + │ ├── lparen_loc: ∅ + │ ├── rparen_loc: ∅ + │ ├── equal_loc: ∅ + │ └── end_keyword_loc: (31,0)-(31,3) = "end" + └── @ RescueModifierNode (location: (33,0)-(33,21)) + ├── expression: + │ @ IfNode (location: (33,0)-(33,10)) + │ ├── if_keyword_loc: (33,4)-(33,6) = "if" + │ ├── predicate: + │ │ @ CallNode (location: (33,7)-(33,10)) + │ │ ├── flags: variable_call, ignore_visibility + │ │ ├── receiver: ∅ + │ │ ├── call_operator_loc: ∅ + │ │ ├── name: :bar + │ │ ├── message_loc: (33,7)-(33,10) = "bar" + │ │ ├── opening_loc: ∅ + │ │ ├── arguments: ∅ + │ │ ├── closing_loc: ∅ + │ │ └── block: ∅ + │ ├── then_keyword_loc: ∅ │ ├── statements: - │ │ @ StatementsNode (location: (29,2)-(29,6)) + │ │ @ StatementsNode (location: (33,0)-(33,3)) │ │ └── body: (length: 1) - │ │ └── @ CallNode (location: (29,2)-(29,6)) - │ │ ├── flags: ignore_visibility + │ │ └── @ CallNode (location: (33,0)-(33,3)) + │ │ ├── flags: variable_call, ignore_visibility │ │ ├── receiver: ∅ │ │ ├── call_operator_loc: ∅ - │ │ ├── name: :a - │ │ ├── message_loc: (29,2)-(29,3) = "a" + │ │ ├── name: :foo + │ │ ├── message_loc: (33,0)-(33,3) = "foo" │ │ ├── opening_loc: ∅ - │ │ ├── arguments: - │ │ │ @ ArgumentsNode (location: (29,4)-(29,6)) - │ │ │ ├── flags: ∅ - │ │ │ └── arguments: (length: 1) - │ │ │ └── @ KeywordHashNode (location: (29,4)-(29,6)) - │ │ │ ├── flags: symbol_keys - │ │ │ └── elements: (length: 1) - │ │ │ └── @ AssocNode (location: (29,4)-(29,6)) - │ │ │ ├── key: - │ │ │ │ @ SymbolNode (location: (29,4)-(29,6)) - │ │ │ │ ├── flags: forced_us_ascii_encoding - │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ ├── value_loc: (29,4)-(29,5) = "b" - │ │ │ │ ├── closing_loc: (29,5)-(29,6) = ":" - │ │ │ │ └── unescaped: "b" - │ │ │ ├── value: - │ │ │ │ @ ImplicitNode (location: (29,4)-(29,6)) - │ │ │ │ └── value: - │ │ │ │ @ CallNode (location: (29,4)-(29,6)) - │ │ │ │ ├── flags: ignore_visibility - │ │ │ │ ├── receiver: ∅ - │ │ │ │ ├── call_operator_loc: ∅ - │ │ │ │ ├── name: :b - │ │ │ │ ├── message_loc: (29,4)-(29,5) = "b" - │ │ │ │ ├── opening_loc: ∅ - │ │ │ │ ├── arguments: ∅ - │ │ │ │ ├── closing_loc: ∅ - │ │ │ │ └── block: ∅ - │ │ │ └── operator_loc: ∅ + │ │ ├── arguments: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ ├── rescue_clause: - │ │ @ RescueNode (location: (30,0)-(30,6)) - │ │ ├── keyword_loc: (30,0)-(30,6) = "rescue" - │ │ ├── exceptions: (length: 0) - │ │ ├── operator_loc: ∅ - │ │ ├── reference: ∅ - │ │ ├── statements: ∅ - │ │ └── consequent: ∅ - │ ├── else_clause: ∅ - │ ├── ensure_clause: ∅ - │ └── end_keyword_loc: (31,0)-(31,3) = "end" - ├── locals: [] - ├── locals_body_index: 0 - ├── def_keyword_loc: (28,0)-(28,3) = "def" - ├── operator_loc: ∅ - ├── lparen_loc: ∅ - ├── rparen_loc: ∅ - ├── equal_loc: ∅ - └── end_keyword_loc: (31,0)-(31,3) = "end" + │ ├── consequent: ∅ + │ └── end_keyword_loc: ∅ + ├── keyword_loc: (33,11)-(33,17) = "rescue" + └── rescue_expression: + @ CallNode (location: (33,18)-(33,21)) + ├── flags: variable_call, ignore_visibility + ├── receiver: ∅ + ├── call_operator_loc: ∅ + ├── name: :baz + ├── message_loc: (33,18)-(33,21) = "baz" + ├── opening_loc: ∅ + ├── arguments: ∅ + ├── closing_loc: ∅ + └── block: ∅ From f634c7a268a175a917bdb8542b4495219196a0e2 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Fri, 26 Jan 2024 15:18:21 -0500 Subject: [PATCH 628/640] [PRISM] Support UTF-8 symbols Fixes ruby/prism#2242. --- prism_compile.c | 19 ++++++++++--------- test/ruby/test_compile_prism.rb | 6 ++++++ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 1d9f6f9e62fb8b..71ca6540b0c160 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -200,23 +200,24 @@ parse_string_encoded(const pm_node_t *node, const pm_string_t *string, const pm_ } static inline ID -parse_symbol(const uint8_t *start, const uint8_t *end, const pm_parser_t *parser) +parse_symbol(const uint8_t *start, const uint8_t *end, const char *encoding) { - rb_encoding *enc = rb_enc_from_index(rb_enc_find_index(parser->encoding->name)); + rb_encoding *enc = rb_enc_from_index(rb_enc_find_index(encoding)); return rb_intern3((const char *) start, end - start, enc); } static inline ID -parse_string_symbol(const pm_string_t *string, const pm_parser_t *parser) +parse_string_symbol(const pm_symbol_node_t *symbol, const pm_parser_t *parser) { - const uint8_t *start = pm_string_source(string); - return parse_symbol(start, start + pm_string_length(string), parser); + const char *encoding = symbol->base.flags & PM_SYMBOL_FLAGS_FORCED_UTF8_ENCODING ? "UTF-8" : parser->encoding->name; + const uint8_t *start = pm_string_source(&symbol->unescaped); + return parse_symbol(start, start + pm_string_length(&symbol->unescaped), encoding); } static inline ID parse_location_symbol(const pm_location_t *location, const pm_parser_t *parser) { - return parse_symbol(location->start, location->end, parser); + return parse_symbol(location->start, location->end, parser->encoding->name); } static int @@ -395,7 +396,7 @@ pm_static_literal_value(const pm_node_t *node, const pm_scope_node_t *scope_node case PM_STRING_NODE: return parse_string(&((pm_string_node_t *) node)->unescaped, parser); case PM_SYMBOL_NODE: - return ID2SYM(parse_string_symbol(&((pm_symbol_node_t *) node)->unescaped, parser)); + return ID2SYM(parse_string_symbol((pm_symbol_node_t *)node, parser)); case PM_TRUE_NODE: return Qtrue; default: @@ -1870,7 +1871,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t const pm_node_t *key = ((const pm_assoc_node_t *) element)->key; assert(PM_NODE_TYPE_P(key, PM_SYMBOL_NODE)); - VALUE symbol = ID2SYM(parse_string_symbol(&((const pm_symbol_node_t *) key)->unescaped, scope_node->parser)); + VALUE symbol = ID2SYM(parse_string_symbol((const pm_symbol_node_t *)key, scope_node->parser)); rb_ary_push(keys, symbol); } } @@ -1915,7 +1916,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t const pm_node_t *key = assoc->key; assert(PM_NODE_TYPE_P(key, PM_SYMBOL_NODE)); - VALUE symbol = ID2SYM(parse_string_symbol(&((const pm_symbol_node_t *) key)->unescaped, scope_node->parser)); + VALUE symbol = ID2SYM(parse_string_symbol((const pm_symbol_node_t *)key, scope_node->parser)); ADD_INSN(ret, &line.node, dup); ADD_INSN1(ret, &line.node, putobject, symbol); ADD_SEND(ret, &line.node, rb_intern("key?"), INT2FIX(1)); diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 93dcd4245046ee..075dffc1b41fd7 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -779,6 +779,12 @@ def test_StringNode def test_SymbolNode assert_prism_eval(":pit") + + # Test UTF-8 symbol in a US-ASCII file + assert_prism_eval(<<~'RUBY', raw: true) + # -*- coding: us-ascii -*- + :"\u{e9}" + RUBY end def test_XStringNode From d980c89273e4f2910042fd5e010f182766f056ac Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Fri, 26 Jan 2024 15:56:30 -0500 Subject: [PATCH 629/640] [PRISM] Support ASCII-8BIT symbols --- prism_compile.c | 8 +++++++- test/ruby/test_compile_prism.rb | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/prism_compile.c b/prism_compile.c index 71ca6540b0c160..9f5ab24f0d649f 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -209,7 +209,13 @@ parse_symbol(const uint8_t *start, const uint8_t *end, const char *encoding) static inline ID parse_string_symbol(const pm_symbol_node_t *symbol, const pm_parser_t *parser) { - const char *encoding = symbol->base.flags & PM_SYMBOL_FLAGS_FORCED_UTF8_ENCODING ? "UTF-8" : parser->encoding->name; + const char *encoding = parser->encoding->name; + if (symbol->base.flags & PM_SYMBOL_FLAGS_FORCED_UTF8_ENCODING) { + encoding = "UTF-8"; + } + else if (symbol->base.flags & PM_SYMBOL_FLAGS_FORCED_BINARY_ENCODING) { + encoding = "ASCII-8BIT"; + } const uint8_t *start = pm_string_source(&symbol->unescaped); return parse_symbol(start, start + pm_string_length(&symbol->unescaped), encoding); } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 075dffc1b41fd7..6033c44d212dc6 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -785,6 +785,12 @@ def test_SymbolNode # -*- coding: us-ascii -*- :"\u{e9}" RUBY + + # Test ASCII-8BIT symbol in a US-ASCII file + assert_prism_eval(<<~'RUBY', raw: true) + # -*- coding: us-ascii -*- + :"\xff" + RUBY end def test_XStringNode From 3d3d9e8397a3a84075692b6411647b031a19bf5d Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Fri, 26 Jan 2024 16:13:04 -0500 Subject: [PATCH 630/640] [PRISM] Support US-ASCII symbols --- prism_compile.c | 3 +++ test/ruby/test_compile_prism.rb | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/prism_compile.c b/prism_compile.c index 9f5ab24f0d649f..94c0a5f82797f4 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -216,6 +216,9 @@ parse_string_symbol(const pm_symbol_node_t *symbol, const pm_parser_t *parser) else if (symbol->base.flags & PM_SYMBOL_FLAGS_FORCED_BINARY_ENCODING) { encoding = "ASCII-8BIT"; } + else if (symbol->base.flags & PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING) { + encoding = "US-ASCII"; + } const uint8_t *start = pm_string_source(&symbol->unescaped); return parse_symbol(start, start + pm_string_length(&symbol->unescaped), encoding); } diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 6033c44d212dc6..be8d8650a7b7a4 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -791,6 +791,12 @@ def test_SymbolNode # -*- coding: us-ascii -*- :"\xff" RUBY + + # Test US-ASCII symbol in a ASCII-8BIT file + assert_prism_eval(<<~'RUBY', raw: true) + # -*- coding: ascii-8bit -*- + :a + RUBY end def test_XStringNode From d7501c403130b575219a672073a06792e81dcdb4 Mon Sep 17 00:00:00 2001 From: Matt Valentine-House Date: Mon, 29 Jan 2024 15:29:49 +0000 Subject: [PATCH 631/640] [PRISM] Fix InterpolatedStringNode If the first element of an interpolated string node is an embedded statement, CRuby "pre-initializes" the interpolation with a string of known encoding to concat into. This patch replicates thate behaviour in Prism --- prism_compile.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/prism_compile.c b/prism_compile.c index 94c0a5f82797f4..c9b3e932b3c55b 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -5365,7 +5365,12 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, } case PM_INTERPOLATED_STRING_NODE: { pm_interpolated_string_node_t *interp_string_node = (pm_interpolated_string_node_t *) node; - int number_of_items_pushed = pm_interpolated_node_compile(&interp_string_node->parts, iseq, dummy_line_node, ret, src, popped, scope_node, parser); + int number_of_items_pushed = 0; + if (!PM_NODE_TYPE_P(interp_string_node->parts.nodes[0], PM_STRING_NODE)) { + ADD_INSN1(ret, &dummy_line_node, putstring, rb_str_new(0, 0)); + number_of_items_pushed++; + } + number_of_items_pushed += pm_interpolated_node_compile(&interp_string_node->parts, iseq, dummy_line_node, ret, src, popped, scope_node, parser); if (number_of_items_pushed > 1) { ADD_INSN1(ret, &dummy_line_node, concatstrings, INT2FIX(number_of_items_pushed)); From 32bbf4750097f7b3358e06e9d8efd81a2089d139 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 29 Jan 2024 11:58:26 -0500 Subject: [PATCH 632/640] [PRISM] Use opt_str_freeze instruction Fixes ruby/prism#2290. --- prism_compile.c | 14 ++++++++++++-- test/ruby/test_compile_prism.rb | 10 ++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index c9b3e932b3c55b..83423370235170 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -3970,11 +3970,21 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, if (call_node->receiver == NULL) { PM_PUTSELF; - } else { + pm_compile_call(iseq, call_node, ret, src, popped, scope_node, method_id, start); + } + else if (method_id == idFreeze && + PM_NODE_TYPE_P(call_node->receiver, PM_STRING_NODE) && + call_node->arguments == NULL && + call_node->block == NULL && + ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) { + VALUE str = rb_fstring(parse_string_encoded(call_node->receiver, &((pm_string_node_t *)call_node->receiver)->unescaped, parser)); + ADD_INSN2(ret, &dummy_line_node, opt_str_freeze, str, new_callinfo(iseq, idFreeze, 0, 0, NULL, FALSE)); + } + else { PM_COMPILE_NOT_POPPED(call_node->receiver); + pm_compile_call(iseq, call_node, ret, src, popped, scope_node, method_id, start); } - pm_compile_call(iseq, call_node, ret, src, popped, scope_node, method_id, start); return; } case PM_CALL_AND_WRITE_NODE: { diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index be8d8650a7b7a4..48912c31f63816 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -1986,6 +1986,16 @@ def self.test_prism_call_node end test_prism_call_node CODE + + # Test opt_str_freeze instruction when calling #freeze on a string literal + assert_prism_eval(<<~RUBY) + "foo".freeze.equal?("foo".freeze) + RUBY + # Test encoding in opt_str_freeze + assert_prism_eval(<<~'RUBY', raw: true) + # -*- coding: us-ascii -*- + "\xff".freeze.encoding + RUBY end def test_CallAndWriteNode From bc10b958d2cc45b61e23c41d0aa892cbb82efafd Mon Sep 17 00:00:00 2001 From: Maxime Chevalier-Boisvert Date: Mon, 29 Jan 2024 16:17:12 -0500 Subject: [PATCH 633/640] YJIT: print warning when disasm options used without a dev build (#9744) * YJIT: print warning when disasm options used without a dev build I was confused for a few minutes the other way then --yjit-dump-disasm printed nothing, so I figured this would be useful for end-users (and future me). * Fix lone extraneous space --- yjit/src/options.rs | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/yjit/src/options.rs b/yjit/src/options.rs index 5a60bc8f4990c5..9a146512bb839e 100644 --- a/yjit/src/options.rs +++ b/yjit/src/options.rs @@ -228,21 +228,31 @@ pub fn parse_option(str_ptr: *const std::os::raw::c_char) -> Option<()> { _ => return None, }, - ("dump-disasm", _) => match opt_val { - "" => unsafe { OPTIONS.dump_disasm = Some(DumpDisasm::Stdout) }, - directory => { - let path = format!("{directory}/yjit_{}.log", std::process::id()); - match File::options().create(true).append(true).open(&path) { - Ok(_) => { - eprintln!("YJIT disasm dump: {path}"); - unsafe { OPTIONS.dump_disasm = Some(DumpDisasm::File(path)) } + ("dump-disasm", _) => { + if !cfg!(feature = "disasm") { + eprintln!("WARNING: the {} option is only available when YJIT is built in dev mode, i.e. ./configure --enable-yjit=dev", opt_name); + } + + match opt_val { + "" => unsafe { OPTIONS.dump_disasm = Some(DumpDisasm::Stdout) }, + directory => { + let path = format!("{directory}/yjit_{}.log", std::process::id()); + match File::options().create(true).append(true).open(&path) { + Ok(_) => { + eprintln!("YJIT disasm dump: {path}"); + unsafe { OPTIONS.dump_disasm = Some(DumpDisasm::File(path)) } + } + Err(err) => eprintln!("Failed to create {path}: {err}"), } - Err(err) => eprintln!("Failed to create {path}: {err}"), } } - }, + }, ("dump-iseq-disasm", _) => unsafe { + if !cfg!(feature = "disasm") { + eprintln!("WARNING: the {} option is only available when YJIT is built in dev mode, i.e. ./configure --enable-yjit=dev", opt_name); + } + OPTIONS.dump_iseq_disasm = Some(opt_val.to_string()); }, From 8e1fe15b4a73e511731accc5e244cead990e3cba Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 29 Jan 2024 14:58:49 -0500 Subject: [PATCH 634/640] [PRISM] Implement opt_str_uminus --- prism_compile.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 83423370235170..702428dd76eb1d 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -3972,13 +3972,18 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, PM_PUTSELF; pm_compile_call(iseq, call_node, ret, src, popped, scope_node, method_id, start); } - else if (method_id == idFreeze && + else if ((method_id == idUMinus || method_id == idFreeze) && PM_NODE_TYPE_P(call_node->receiver, PM_STRING_NODE) && call_node->arguments == NULL && call_node->block == NULL && ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) { VALUE str = rb_fstring(parse_string_encoded(call_node->receiver, &((pm_string_node_t *)call_node->receiver)->unescaped, parser)); - ADD_INSN2(ret, &dummy_line_node, opt_str_freeze, str, new_callinfo(iseq, idFreeze, 0, 0, NULL, FALSE)); + if (method_id == idUMinus) { + ADD_INSN2(ret, &dummy_line_node, opt_str_uminus, str, new_callinfo(iseq, idUMinus, 0, 0, NULL, FALSE)); + } + else { + ADD_INSN2(ret, &dummy_line_node, opt_str_freeze, str, new_callinfo(iseq, idFreeze, 0, 0, NULL, FALSE)); + } } else { PM_COMPILE_NOT_POPPED(call_node->receiver); From 3fb741069d1d0f28367940bf8536466bb78ff837 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 29 Jan 2024 16:03:03 -0500 Subject: [PATCH 635/640] [PRISM] Fix rescue frame label --- prism_compile.c | 51 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 702428dd76eb1d..c4fe029dcbec4e 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -68,6 +68,13 @@ pm_iseq_new_with_opt(pm_scope_node_t *scope_node, pm_parser_t *parser, VALUE nam int first_lineno, const rb_iseq_t *parent, int isolated_depth, enum rb_iseq_type type, const rb_compile_option_t *option); +static int +pm_line_number(const pm_parser_t *parser, const pm_node_t *node) +{ + pm_line_column_t line_column = pm_newline_list_line_column(&parser->newline_list, node->location.start); + return (int) line_column.line; +} + static VALUE parse_integer(const pm_integer_node_t *node) { @@ -3528,11 +3535,15 @@ pm_compile_rescue(rb_iseq_t *iseq, pm_begin_node_t *begin_node, LINK_ANCHOR *con LABEL *lcont = NEW_LABEL(lineno); pm_scope_node_t rescue_scope_node; - pm_scope_node_init((pm_node_t *)begin_node->rescue_clause, &rescue_scope_node, scope_node, parser); - rb_iseq_t *rescue_iseq = NEW_CHILD_ISEQ(&rescue_scope_node, - rb_str_concat(rb_str_new2("rescue in"), - ISEQ_BODY(iseq)->location.label), - ISEQ_TYPE_RESCUE, 1); + pm_scope_node_init((pm_node_t *) begin_node->rescue_clause, &rescue_scope_node, scope_node, parser); + + rb_iseq_t *rescue_iseq = NEW_CHILD_ISEQ( + &rescue_scope_node, + rb_str_concat(rb_str_new2("rescue in "), ISEQ_BODY(iseq)->location.label), + ISEQ_TYPE_RESCUE, + pm_line_number(parser, (const pm_node_t *) begin_node->rescue_clause) + ); + pm_scope_node_destroy(&rescue_scope_node); lstart->rescued = LABEL_RESCUE_BEG; @@ -3599,9 +3610,14 @@ pm_compile_ensure(rb_iseq_t *iseq, pm_begin_node_t *begin_node, LINK_ANCHOR *con pm_scope_node_t next_scope_node; pm_scope_node_init((pm_node_t *)begin_node->ensure_clause, &next_scope_node, scope_node, parser); - rb_iseq_t * child_iseq = NEW_CHILD_ISEQ(&next_scope_node, - rb_str_new2("ensure in"), - ISEQ_TYPE_ENSURE, lineno); + + rb_iseq_t *child_iseq = NEW_CHILD_ISEQ( + &next_scope_node, + rb_str_concat(rb_str_new2("ensure in "), ISEQ_BODY(iseq)->location.label), + ISEQ_TYPE_ENSURE, + pm_line_number(parser, (const pm_node_t *) begin_node->ensure_clause) + ); + pm_scope_node_destroy(&next_scope_node); ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq; @@ -6167,7 +6183,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // If we have statements to execute, we'll compile them here. Otherwise // we'll push nil onto the stack. if (cast->statements) { - // We'll temporarily remove the end_label location from the iseq // when compiling the statements so that next/redo statements // inside the body will throw to the correct place instead of @@ -6199,14 +6214,18 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, return; } case PM_RESCUE_MODIFIER_NODE: { - pm_rescue_modifier_node_t *rescue_node = (pm_rescue_modifier_node_t *)node; + pm_rescue_modifier_node_t *cast = (pm_rescue_modifier_node_t *) node; pm_scope_node_t rescue_scope_node; - pm_scope_node_init((pm_node_t *)rescue_node, &rescue_scope_node, scope_node, parser); - rb_iseq_t *rescue_iseq = NEW_CHILD_ISEQ(&rescue_scope_node, - rb_str_concat(rb_str_new2("rescue in"), - ISEQ_BODY(iseq)->location.label), - ISEQ_TYPE_RESCUE, 1); + pm_scope_node_init((pm_node_t *) cast, &rescue_scope_node, scope_node, parser); + + rb_iseq_t *rescue_iseq = NEW_CHILD_ISEQ( + &rescue_scope_node, + rb_str_concat(rb_str_new2("rescue in "), ISEQ_BODY(iseq)->location.label), + ISEQ_TYPE_RESCUE, + pm_line_number(parser, cast->rescue_expression) + ); + pm_scope_node_destroy(&rescue_scope_node); LABEL *lstart = NEW_LABEL(lineno); @@ -6216,7 +6235,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, lstart->rescued = LABEL_RESCUE_BEG; lend->rescued = LABEL_RESCUE_END; ADD_LABEL(ret, lstart); - PM_COMPILE_NOT_POPPED((pm_node_t *)rescue_node->expression); + PM_COMPILE_NOT_POPPED(cast->expression); ADD_LABEL(ret, lend); PM_NOP; ADD_LABEL(ret, lcont); From 2d6f7d0864d0a19b2ab38ebb2022487d34568c24 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 29 Jan 2024 16:22:08 -0500 Subject: [PATCH 636/640] Fix test/ruby/test_rubyoptions.rb + --parser=prism --- test/ruby/test_rubyoptions.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/ruby/test_rubyoptions.rb b/test/ruby/test_rubyoptions.rb index 97d78ba1667bbe..f753ba5574e53c 100644 --- a/test/ruby/test_rubyoptions.rb +++ b/test/ruby/test_rubyoptions.rb @@ -10,6 +10,11 @@ class TestRubyOptions < Test::Unit::TestCase def self.rjit_enabled? = defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? def self.yjit_enabled? = defined?(RubyVM::YJIT.enabled?) && RubyVM::YJIT.enabled? + # Here we're defining our own RUBY_DESCRIPTION without "+PRISM". We do this + # here so that the various tests that reference RUBY_DESCRIPTION don't have to + # worry about it. The flag itself is tested in its own test. + RUBY_DESCRIPTION = ::RUBY_DESCRIPTION.sub(/\+PRISM /, '') + NO_JIT_DESCRIPTION = if rjit_enabled? RUBY_DESCRIPTION.sub(/\+RJIT /, '') From 4cf3c026de54499e79f61ae284b834565a6706e4 Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Mon, 29 Jan 2024 16:37:37 -0500 Subject: [PATCH 637/640] Fix RegExp warning causing flaky Ripper failure Sometimes this file get picked up and break Ripper tests: TestRipper::Generic#test_parse_files:test/ruby assert_separately failed with error message pid 63392 exit 0 | test_regexp.rb:2025: warning: character class has duplicated range https://github.com/ruby/ruby/actions/runs/7699956651/job/20982702553#step:12:103 --- test/ruby/test_regexp.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb index 390a8cb1938d5b..2de622f9a5e7d0 100644 --- a/test/ruby/test_regexp.rb +++ b/test/ruby/test_regexp.rb @@ -2022,7 +2022,7 @@ def test_bug_20207 # [Bug #20207] def test_bug_20212 # [Bug #20212] regex = Regexp.new( - /\A((?=.*?[a-z])(?!.*--)[a-z\d]+[a-z\d-]*[a-z\d]+).((?=.*?[a-z])(?!.*--)[a-z\d]+[a-z\d-]*[a-z\d]+).((?=.*?[a-z])(?!.*--)[a-zd]+[a-zd-]*[a-zd]+).((?=.*?[a-z])(?!.*--)[a-zd]+[a-zd-]*[a-zd]+)\Z/x + /\A((?=.*?[a-z])(?!.*--)[a-z\d]+[a-z\d-]*[a-z\d]+).((?=.*?[a-z])(?!.*--)[a-z\d]+[a-z\d-]*[a-z\d]+).((?=.*?[a-z])(?!.*--)[a-z]+[a-z-]*[a-z]+).((?=.*?[a-z])(?!.*--)[a-z]+[a-z-]*[a-z]+)\Z/x ) string = "www.google.com" 100.times.each { assert(regex.match?(string)) } From bbb7ab906ec64b963bd4b5d37e47b14796d64371 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Mon, 29 Jan 2024 16:35:54 -0500 Subject: [PATCH 638/640] [PRISM] Fix crash when multiple underscores Fixes ruby/prism#2295. --- prism_compile.c | 6 ++++-- test/ruby/test_compile_prism.rb | 5 +++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index c4fe029dcbec4e..baab1a55fc9804 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2881,8 +2881,10 @@ pm_compile_destructured_param_locals(const pm_multi_target_node_t *node, st_tabl const pm_node_t *left = node->lefts.nodes[index]; if (PM_NODE_TYPE_P(left, PM_REQUIRED_PARAMETER_NODE)) { - pm_insert_local_index(((const pm_required_parameter_node_t *) left)->name, local_index, index_lookup_table, local_table_for_iseq, scope_node); - local_index++; + if (!PM_NODE_FLAG_P(left, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) { + pm_insert_local_index(((const pm_required_parameter_node_t *) left)->name, local_index, index_lookup_table, local_table_for_iseq, scope_node); + local_index++; + } } else { RUBY_ASSERT(PM_NODE_TYPE_P(left, PM_MULTI_TARGET_NODE)); local_index = pm_compile_destructured_param_locals((const pm_multi_target_node_t *) left, index_lookup_table, local_table_for_iseq, scope_node, local_index); diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb index 48912c31f63816..901cc0741e7436 100644 --- a/test/ruby/test_compile_prism.rb +++ b/test/ruby/test_compile_prism.rb @@ -2203,6 +2203,11 @@ def test_BlockParametersNode assert_prism_eval("Object.tap { || }") assert_prism_eval("[1].map { |num| num }") assert_prism_eval("[1].map { |a; b| b = 2; a + b}") + + # Test block parameters with multiple _ + assert_prism_eval(<<~RUBY) + [[1, 2, 3, 4, 5, 6]].map { |(_, _, _, _, _, _)| _ } + RUBY end def test_FowardingParameterNode From db5d9429a0d30213915fa36f2c6641065d01854a Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Mon, 29 Jan 2024 16:42:03 -0500 Subject: [PATCH 639/640] YJIT: No need to RESTORE_REG now that we reject tailcalls Thanks to Kokubun for noticing. Follow-up: b0711b1cf152afad0a480ee2f9bedd142a0d24ac --- vm_exec.h | 1 - 1 file changed, 1 deletion(-) diff --git a/vm_exec.h b/vm_exec.h index b1eeb506607454..11b89c30fc79ab 100644 --- a/vm_exec.h +++ b/vm_exec.h @@ -179,7 +179,6 @@ default: \ /* don't run tailcalls since that breaks FINISH */ \ if (val == Qundef && GET_CFP() != ec->cfp && (func = jit_compile(ec))) { \ val = func(ec, ec->cfp); \ - RESTORE_REGS(); /* fix cfp for tailcall */ \ if (ec->tag->state) THROW_EXCEPTION(val); \ } \ } while (0) From 83966a57fe6a271e64fb2629e7bbb8f0c34948a2 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 29 Jan 2024 16:39:46 -0500 Subject: [PATCH 640/640] [PRISM] Method location for calls --- prism_compile.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/prism_compile.c b/prism_compile.c index baab1a55fc9804..46ce25e4855788 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -2697,8 +2697,13 @@ pm_compile_call(rb_iseq_t *iseq, const pm_call_node_t *call_node, LINK_ANCHOR *c { pm_parser_t *parser = scope_node->parser; pm_newline_list_t newline_list = parser->newline_list; - int lineno = (int)pm_newline_list_line_column(&newline_list, ((pm_node_t *)call_node)->location.start).line; + + const uint8_t *call_start = call_node->message_loc.start; + if (call_start == NULL) call_start = call_node->base.location.start; + + int lineno = (int) pm_newline_list_line_column(&newline_list, call_start).line; NODE dummy_line_node = generate_dummy_line_node(lineno, lineno); + LABEL *else_label = NEW_LABEL(lineno); LABEL *end_label = NEW_LABEL(lineno);