From fcbf63e62c627deae76c1b8cb8c0876c536ed811 Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Mon, 16 Mar 2020 18:49:26 +0900 Subject: Fresh start --- jni/ruby/lib/irb/cmd/chws.rb | 33 + jni/ruby/lib/irb/cmd/fork.rb | 38 + jni/ruby/lib/irb/cmd/help.rb | 41 + jni/ruby/lib/irb/cmd/load.rb | 66 ++ jni/ruby/lib/irb/cmd/nop.rb | 38 + jni/ruby/lib/irb/cmd/pushws.rb | 40 + jni/ruby/lib/irb/cmd/subirb.rb | 42 + jni/ruby/lib/irb/completion.rb | 227 ++++++ jni/ruby/lib/irb/context.rb | 419 ++++++++++ jni/ruby/lib/irb/ext/change-ws.rb | 45 ++ jni/ruby/lib/irb/ext/history.rb | 118 +++ jni/ruby/lib/irb/ext/loader.rb | 128 +++ jni/ruby/lib/irb/ext/math-mode.rb | 47 ++ jni/ruby/lib/irb/ext/multi-irb.rb | 265 +++++++ jni/ruby/lib/irb/ext/save-history.rb | 103 +++ jni/ruby/lib/irb/ext/tracer.rb | 71 ++ jni/ruby/lib/irb/ext/use-loader.rb | 73 ++ jni/ruby/lib/irb/ext/workspaces.rb | 66 ++ jni/ruby/lib/irb/extend-command.rb | 308 ++++++++ jni/ruby/lib/irb/frame.rb | 80 ++ jni/ruby/lib/irb/help.rb | 36 + jni/ruby/lib/irb/init.rb | 304 ++++++++ jni/ruby/lib/irb/input-method.rb | 191 +++++ jni/ruby/lib/irb/inspector.rb | 131 ++++ jni/ruby/lib/irb/lc/.document | 4 + jni/ruby/lib/irb/lc/error.rb | 31 + jni/ruby/lib/irb/lc/help-message | 50 ++ jni/ruby/lib/irb/lc/ja/encoding_aliases.rb | 10 + jni/ruby/lib/irb/lc/ja/error.rb | 30 + jni/ruby/lib/irb/lc/ja/help-message | 53 ++ jni/ruby/lib/irb/locale.rb | 181 +++++ jni/ruby/lib/irb/magic-file.rb | 37 + jni/ruby/lib/irb/notifier.rb | 231 ++++++ jni/ruby/lib/irb/output-method.rb | 91 +++ jni/ruby/lib/irb/ruby-lex.rb | 1170 ++++++++++++++++++++++++++++ jni/ruby/lib/irb/ruby-token.rb | 266 +++++++ jni/ruby/lib/irb/slex.rb | 281 +++++++ jni/ruby/lib/irb/src_encoding.rb | 4 + jni/ruby/lib/irb/version.rb | 15 + jni/ruby/lib/irb/workspace.rb | 114 +++ jni/ruby/lib/irb/ws-for-case-2.rb | 14 + jni/ruby/lib/irb/xmp.rb | 169 ++++ 42 files changed, 5661 insertions(+) create mode 100644 jni/ruby/lib/irb/cmd/chws.rb create mode 100644 jni/ruby/lib/irb/cmd/fork.rb create mode 100644 jni/ruby/lib/irb/cmd/help.rb create mode 100644 jni/ruby/lib/irb/cmd/load.rb create mode 100644 jni/ruby/lib/irb/cmd/nop.rb create mode 100644 jni/ruby/lib/irb/cmd/pushws.rb create mode 100644 jni/ruby/lib/irb/cmd/subirb.rb create mode 100644 jni/ruby/lib/irb/completion.rb create mode 100644 jni/ruby/lib/irb/context.rb create mode 100644 jni/ruby/lib/irb/ext/change-ws.rb create mode 100644 jni/ruby/lib/irb/ext/history.rb create mode 100644 jni/ruby/lib/irb/ext/loader.rb create mode 100644 jni/ruby/lib/irb/ext/math-mode.rb create mode 100644 jni/ruby/lib/irb/ext/multi-irb.rb create mode 100644 jni/ruby/lib/irb/ext/save-history.rb create mode 100644 jni/ruby/lib/irb/ext/tracer.rb create mode 100644 jni/ruby/lib/irb/ext/use-loader.rb create mode 100644 jni/ruby/lib/irb/ext/workspaces.rb create mode 100644 jni/ruby/lib/irb/extend-command.rb create mode 100644 jni/ruby/lib/irb/frame.rb create mode 100644 jni/ruby/lib/irb/help.rb create mode 100644 jni/ruby/lib/irb/init.rb create mode 100644 jni/ruby/lib/irb/input-method.rb create mode 100644 jni/ruby/lib/irb/inspector.rb create mode 100644 jni/ruby/lib/irb/lc/.document create mode 100644 jni/ruby/lib/irb/lc/error.rb create mode 100644 jni/ruby/lib/irb/lc/help-message create mode 100644 jni/ruby/lib/irb/lc/ja/encoding_aliases.rb create mode 100644 jni/ruby/lib/irb/lc/ja/error.rb create mode 100644 jni/ruby/lib/irb/lc/ja/help-message create mode 100644 jni/ruby/lib/irb/locale.rb create mode 100644 jni/ruby/lib/irb/magic-file.rb create mode 100644 jni/ruby/lib/irb/notifier.rb create mode 100644 jni/ruby/lib/irb/output-method.rb create mode 100644 jni/ruby/lib/irb/ruby-lex.rb create mode 100644 jni/ruby/lib/irb/ruby-token.rb create mode 100644 jni/ruby/lib/irb/slex.rb create mode 100644 jni/ruby/lib/irb/src_encoding.rb create mode 100644 jni/ruby/lib/irb/version.rb create mode 100644 jni/ruby/lib/irb/workspace.rb create mode 100644 jni/ruby/lib/irb/ws-for-case-2.rb create mode 100644 jni/ruby/lib/irb/xmp.rb (limited to 'jni/ruby/lib/irb') diff --git a/jni/ruby/lib/irb/cmd/chws.rb b/jni/ruby/lib/irb/cmd/chws.rb new file mode 100644 index 0000000..bc39fd1 --- /dev/null +++ b/jni/ruby/lib/irb/cmd/chws.rb @@ -0,0 +1,33 @@ +# +# change-ws.rb - +# $Release Version: 0.9.6$ +# $Revision: 47112 $ +# by Keiju ISHITSUKA(keiju@ruby-lang.org) +# +# -- +# +# +# + +require "irb/cmd/nop.rb" +require "irb/ext/change-ws.rb" + +# :stopdoc: +module IRB + module ExtendCommand + + class CurrentWorkingWorkspace == === =~ > >= >> [] []= ^ ! != !~] + + def self.select_message(receiver, message, candidates, sep = ".") + candidates.grep(/^#{message}/).collect do |e| + case e + when /^[a-zA-Z_]/ + receiver + sep + e + when /^[0-9]/ + when *Operators + #receiver + " " + e + end + end + end + end +end + +if Readline.respond_to?("basic_word_break_characters=") + Readline.basic_word_break_characters= " \t\n`><=;|&{(" +end +Readline.completion_append_character = nil +Readline.completion_proc = IRB::InputCompletor::CompletionProc diff --git a/jni/ruby/lib/irb/context.rb b/jni/ruby/lib/irb/context.rb new file mode 100644 index 0000000..0006186 --- /dev/null +++ b/jni/ruby/lib/irb/context.rb @@ -0,0 +1,419 @@ +# +# irb/context.rb - irb context +# $Release Version: 0.9.6$ +# $Revision: 47114 $ +# by Keiju ISHITSUKA(keiju@ruby-lang.org) +# +# -- +# +# +# +require "irb/workspace" +require "irb/inspector" + +module IRB + # A class that wraps the current state of the irb session, including the + # configuration of IRB.conf. + class Context + # Creates a new IRB context. + # + # The optional +input_method+ argument: + # + # +nil+:: uses stdin or Readline + # +String+:: uses a File + # +other+:: uses this as InputMethod + def initialize(irb, workspace = nil, input_method = nil, output_method = nil) + @irb = irb + if workspace + @workspace = workspace + else + @workspace = WorkSpace.new + end + @thread = Thread.current if defined? Thread + + # copy of default configuration + @ap_name = IRB.conf[:AP_NAME] + @rc = IRB.conf[:RC] + @load_modules = IRB.conf[:LOAD_MODULES] + + @use_readline = IRB.conf[:USE_READLINE] + @verbose = IRB.conf[:VERBOSE] + @io = nil + + self.inspect_mode = IRB.conf[:INSPECT_MODE] + self.math_mode = IRB.conf[:MATH_MODE] if IRB.conf[:MATH_MODE] + self.use_tracer = IRB.conf[:USE_TRACER] if IRB.conf[:USE_TRACER] + self.use_loader = IRB.conf[:USE_LOADER] if IRB.conf[:USE_LOADER] + self.eval_history = IRB.conf[:EVAL_HISTORY] if IRB.conf[:EVAL_HISTORY] + + @ignore_sigint = IRB.conf[:IGNORE_SIGINT] + @ignore_eof = IRB.conf[:IGNORE_EOF] + + @back_trace_limit = IRB.conf[:BACK_TRACE_LIMIT] + + self.prompt_mode = IRB.conf[:PROMPT_MODE] + + if IRB.conf[:SINGLE_IRB] or !defined?(IRB::JobManager) + @irb_name = IRB.conf[:IRB_NAME] + else + @irb_name = IRB.conf[:IRB_NAME]+"#"+IRB.JobManager.n_jobs.to_s + end + @irb_path = "(" + @irb_name + ")" + + case input_method + when nil + case use_readline? + when nil + if (defined?(ReadlineInputMethod) && STDIN.tty? && + IRB.conf[:PROMPT_MODE] != :INF_RUBY) + @io = ReadlineInputMethod.new + else + @io = StdioInputMethod.new + end + when false + @io = StdioInputMethod.new + when true + if defined?(ReadlineInputMethod) + @io = ReadlineInputMethod.new + else + @io = StdioInputMethod.new + end + end + + when String + @io = FileInputMethod.new(input_method) + @irb_name = File.basename(input_method) + @irb_path = input_method + else + @io = input_method + end + self.save_history = IRB.conf[:SAVE_HISTORY] if IRB.conf[:SAVE_HISTORY] + + if output_method + @output_method = output_method + else + @output_method = StdioOutputMethod.new + end + + @echo = IRB.conf[:ECHO] + if @echo.nil? + @echo = true + end + self.debug_level = IRB.conf[:DEBUG_LEVEL] + end + + # The top-level workspace, see WorkSpace#main + def main + @workspace.main + end + + # The toplevel workspace, see #home_workspace + attr_reader :workspace_home + # WorkSpace in the current context + attr_accessor :workspace + # The current thread in this context + attr_reader :thread + # The current input method + # + # Can be either StdioInputMethod, ReadlineInputMethod, FileInputMethod or + # other specified when the context is created. See ::new for more + # information on +input_method+. + attr_accessor :io + + # Current irb session + attr_accessor :irb + # A copy of the default IRB.conf[:AP_NAME] + attr_accessor :ap_name + # A copy of the default IRB.conf[:RC] + attr_accessor :rc + # A copy of the default IRB.conf[:LOAD_MODULES] + attr_accessor :load_modules + # Can be either name from IRB.conf[:IRB_NAME], or the number of + # the current job set by JobManager, such as irb#2 + attr_accessor :irb_name + # Can be either the #irb_name surrounded by parenthesis, or the + # +input_method+ passed to Context.new + attr_accessor :irb_path + + # Whether +Readline+ is enabled or not. + # + # A copy of the default IRB.conf[:USE_READLINE] + # + # See #use_readline= for more information. + attr_reader :use_readline + # A copy of the default IRB.conf[:INSPECT_MODE] + attr_reader :inspect_mode + + # A copy of the default IRB.conf[:PROMPT_MODE] + attr_reader :prompt_mode + # Standard IRB prompt + # + # See IRB@Customizing+the+IRB+Prompt for more information. + attr_accessor :prompt_i + # IRB prompt for continuated strings + # + # See IRB@Customizing+the+IRB+Prompt for more information. + attr_accessor :prompt_s + # IRB prompt for continuated statement (e.g. immediately after an +if+) + # + # See IRB@Customizing+the+IRB+Prompt for more information. + attr_accessor :prompt_c + # See IRB@Customizing+the+IRB+Prompt for more information. + attr_accessor :prompt_n + # Can be either the default IRB.conf[:AUTO_INDENT], or the + # mode set by #prompt_mode= + # + # To enable auto-indentation in irb: + # + # IRB.conf[:AUTO_INDENT] = true + # + # or + # + # irb_context.auto_indent_mode = true + # + # or + # + # IRB.CurrentContext.auto_indent_mode = true + # + # See IRB@Configuration for more information. + attr_accessor :auto_indent_mode + # The format of the return statement, set by #prompt_mode= using the + # +:RETURN+ of the +mode+ passed to set the current #prompt_mode. + attr_accessor :return_format + + # Whether ^C (+control-c+) will be ignored or not. + # + # If set to +false+, ^C will quit irb. + # + # If set to +true+, + # + # * during input: cancel input then return to top level. + # * during execute: abandon current execution. + attr_accessor :ignore_sigint + # Whether ^D (+control-d+) will be ignored or not. + # + # If set to +false+, ^D will quit irb. + attr_accessor :ignore_eof + # Whether to echo the return value to output or not. + # + # Uses IRB.conf[:ECHO] if available, or defaults to +true+. + # + # puts "hello" + # # hello + # #=> nil + # IRB.CurrentContext.echo = false + # puts "omg" + # # omg + attr_accessor :echo + # Whether verbose messages are displayed or not. + # + # A copy of the default IRB.conf[:VERBOSE] + attr_accessor :verbose + # The debug level of irb + # + # See #debug_level= for more information. + attr_reader :debug_level + + # The limit of backtrace lines displayed as top +n+ and tail +n+. + # + # The default value is 16. + # + # Can also be set using the +--back-trace-limit+ command line option. + # + # See IRB@Command+line+options for more command line options. + attr_accessor :back_trace_limit + + # Alias for #use_readline + alias use_readline? use_readline + # Alias for #rc + alias rc? rc + alias ignore_sigint? ignore_sigint + alias ignore_eof? ignore_eof + alias echo? echo + + # Returns whether messages are displayed or not. + def verbose? + if @verbose.nil? + if defined?(ReadlineInputMethod) && @io.kind_of?(ReadlineInputMethod) + false + elsif !STDIN.tty? or @io.kind_of?(FileInputMethod) + true + else + false + end + else + @verbose + end + end + + # Whether #verbose? is +true+, and +input_method+ is either + # StdioInputMethod or ReadlineInputMethod, see #io for more information. + def prompting? + verbose? || (STDIN.tty? && @io.kind_of?(StdioInputMethod) || + (defined?(ReadlineInputMethod) && @io.kind_of?(ReadlineInputMethod))) + end + + # The return value of the last statement evaluated. + attr_reader :last_value + + # Sets the return value from the last statement evaluated in this context + # to #last_value. + def set_last_value(value) + @last_value = value + @workspace.evaluate self, "_ = IRB.CurrentContext.last_value" + end + + # Sets the +mode+ of the prompt in this context. + # + # See IRB@Customizing+the+IRB+Prompt for more information. + def prompt_mode=(mode) + @prompt_mode = mode + pconf = IRB.conf[:PROMPT][mode] + @prompt_i = pconf[:PROMPT_I] + @prompt_s = pconf[:PROMPT_S] + @prompt_c = pconf[:PROMPT_C] + @prompt_n = pconf[:PROMPT_N] + @return_format = pconf[:RETURN] + if ai = pconf.include?(:AUTO_INDENT) + @auto_indent_mode = ai + else + @auto_indent_mode = IRB.conf[:AUTO_INDENT] + end + end + + # Whether #inspect_mode is set or not, see #inspect_mode= for more detail. + def inspect? + @inspect_mode.nil? or @inspect_mode + end + + # Whether #io uses a File for the +input_method+ passed when creating the + # current context, see ::new + def file_input? + @io.class == FileInputMethod + end + + # Specifies the inspect mode with +opt+: + # + # +true+:: display +inspect+ + # +false+:: display +to_s+ + # +nil+:: inspect mode in non-math mode, + # non-inspect mode in math mode + # + # See IRB::Inspector for more information. + # + # Can also be set using the +--inspect+ and +--noinspect+ command line + # options. + # + # See IRB@Command+line+options for more command line options. + def inspect_mode=(opt) + + if i = Inspector::INSPECTORS[opt] + @inspect_mode = opt + @inspect_method = i + i.init + else + case opt + when nil + if Inspector.keys_with_inspector(Inspector::INSPECTORS[true]).include?(@inspect_mode) + self.inspect_mode = false + elsif Inspector.keys_with_inspector(Inspector::INSPECTORS[false]).include?(@inspect_mode) + self.inspect_mode = true + else + puts "Can't switch inspect mode." + return + end + when /^\s*\{.*\}\s*$/ + begin + inspector = eval "proc#{opt}" + rescue Exception + puts "Can't switch inspect mode(#{opt})." + return + end + self.inspect_mode = inspector + when Proc + self.inspect_mode = IRB::Inspector(opt) + when Inspector + prefix = "usr%d" + i = 1 + while Inspector::INSPECTORS[format(prefix, i)]; i += 1; end + @inspect_mode = format(prefix, i) + @inspect_method = opt + Inspector.def_inspector(format(prefix, i), @inspect_method) + else + puts "Can't switch inspect mode(#{opt})." + return + end + end + print "Switch to#{unless @inspect_mode; ' non';end} inspect mode.\n" if verbose? + @inspect_mode + end + + # Obsolete method. + # + # Can be set using the +--noreadline+ and +--readline+ command line + # options. + # + # See IRB@Command+line+options for more command line options. + def use_readline=(opt) + print "This method is obsolete." + print "Do nothing." + end + + # Sets the debug level of irb + # + # Can also be set using the +--irb_debug+ command line option. + # + # See IRB@Command+line+options for more command line options. + def debug_level=(value) + @debug_level = value + RubyLex.debug_level = value + end + + # Whether or not debug mode is enabled, see #debug_level=. + def debug? + @debug_level > 0 + end + + def evaluate(line, line_no) # :nodoc: + @line_no = line_no + set_last_value(@workspace.evaluate(self, line, irb_path, line_no)) + end + + def inspect_last_value # :nodoc: + @inspect_method.inspect_value(@last_value) + end + + alias __exit__ exit + # Exits the current session, see IRB.irb_exit + def exit(ret = 0) + IRB.irb_exit(@irb, ret) + end + + NOPRINTING_IVARS = ["@last_value"] # :nodoc: + NO_INSPECTING_IVARS = ["@irb", "@io"] # :nodoc: + IDNAME_IVARS = ["@prompt_mode"] # :nodoc: + + alias __inspect__ inspect + def inspect # :nodoc: + array = [] + for ivar in instance_variables.sort{|e1, e2| e1 <=> e2} + ivar = ivar.to_s + name = ivar.sub(/^@(.*)$/, '\1') + val = instance_eval(ivar) + case ivar + when *NOPRINTING_IVARS + array.push format("conf.%s=%s", name, "...") + when *NO_INSPECTING_IVARS + array.push format("conf.%s=%s", name, val.to_s) + when *IDNAME_IVARS + array.push format("conf.%s=:%s", name, val.id2name) + else + array.push format("conf.%s=%s", name, val.inspect) + end + end + array.join("\n") + end + alias __to_s__ to_s + alias to_s inspect + end +end diff --git a/jni/ruby/lib/irb/ext/change-ws.rb b/jni/ruby/lib/irb/ext/change-ws.rb new file mode 100644 index 0000000..866a710 --- /dev/null +++ b/jni/ruby/lib/irb/ext/change-ws.rb @@ -0,0 +1,45 @@ +# +# irb/ext/cb.rb - +# $Release Version: 0.9.6$ +# $Revision: 47114 $ +# by Keiju ISHITSUKA(keiju@ruby-lang.org) +# +# -- +# +# +# + +module IRB # :nodoc: + class Context + + # Inherited from +TOPLEVEL_BINDING+. + def home_workspace + if defined? @home_workspace + @home_workspace + else + @home_workspace = @workspace + end + end + + # Changes the current workspace to given object or binding. + # + # If the optional argument is omitted, the workspace will be + # #home_workspace which is inherited from +TOPLEVEL_BINDING+ or the main + # object, IRB.conf[:MAIN_CONTEXT] when irb was initialized. + # + # See IRB::WorkSpace.new for more information. + def change_workspace(*_main) + if _main.empty? + @workspace = home_workspace + return main + end + + @workspace = WorkSpace.new(_main[0]) + + if !(class<= 0 + @contents.find{|no, val| no == idx}[1] + else + @contents[idx][1] + end + rescue NameError + nil + end + end + + def push(no, val) + @contents.push [no, val] + @contents.shift if @size != 0 && @contents.size > @size + end + + alias real_inspect inspect + + def inspect + if @contents.empty? + return real_inspect + end + + unless (last = @contents.pop)[1].equal?(self) + @contents.push last + last = nil + end + str = @contents.collect{|no, val| + if val.equal?(self) + "#{no} ...self-history..." + else + "#{no} #{val.inspect}" + end + }.join("\n") + if str == "" + str = "Empty." + end + @contents.push last if last + str + end + end +end + + diff --git a/jni/ruby/lib/irb/ext/loader.rb b/jni/ruby/lib/irb/ext/loader.rb new file mode 100644 index 0000000..4c6b2ba --- /dev/null +++ b/jni/ruby/lib/irb/ext/loader.rb @@ -0,0 +1,128 @@ +# +# loader.rb - +# $Release Version: 0.9.6$ +# $Revision: 47266 $ +# by Keiju ISHITSUKA(keiju@ruby-lang.org) +# +# -- +# +# +# + + +module IRB # :nodoc: + # Raised in the event of an exception in a file loaded from an Irb session + class LoadAbort < Exception;end + + # Provides a few commands for loading files within an irb session. + # + # See ExtendCommandBundle for more information. + module IrbLoader + + alias ruby_load load + alias ruby_require require + + # Loads the given file similarly to Kernel#load + def irb_load(fn, priv = nil) + path = search_file_from_ruby_path(fn) + raise LoadError, "No such file to load -- #{fn}" unless path + + load_file(path, priv) + end + + def search_file_from_ruby_path(fn) # :nodoc: + if /^#{Regexp.quote(File::Separator)}/ =~ fn + return fn if File.exist?(fn) + return nil + end + + for path in $: + if File.exist?(f = File.join(path, fn)) + return f + end + end + return nil + end + + # Loads a given file in the current session and displays the source lines + # + # See Irb#suspend_input_method for more information. + def source_file(path) + irb.suspend_name(path, File.basename(path)) do + irb.suspend_input_method(FileInputMethod.new(path)) do + |back_io| + irb.signal_status(:IN_LOAD) do + if back_io.kind_of?(FileInputMethod) + irb.eval_input + else + begin + irb.eval_input + rescue LoadAbort + print "load abort!!\n" + end + end + end + end + end + end + + # Loads the given file in the current session's context and evaluates it. + # + # See Irb#suspend_input_method for more information. + def load_file(path, priv = nil) + irb.suspend_name(path, File.basename(path)) do + + if priv + ws = WorkSpace.new(Module.new) + else + ws = WorkSpace.new + end + irb.suspend_workspace(ws) do + irb.suspend_input_method(FileInputMethod.new(path)) do + |back_io| + irb.signal_status(:IN_LOAD) do + if back_io.kind_of?(FileInputMethod) + irb.eval_input + else + begin + irb.eval_input + rescue LoadAbort + print "load abort!!\n" + end + end + end + end + end + end + end + + def old # :nodoc: + back_io = @io + back_path = @irb_path + back_name = @irb_name + back_scanner = @irb.scanner + begin + @io = FileInputMethod.new(path) + @irb_name = File.basename(path) + @irb_path = path + @irb.signal_status(:IN_LOAD) do + if back_io.kind_of?(FileInputMethod) + @irb.eval_input + else + begin + @irb.eval_input + rescue LoadAbort + print "load abort!!\n" + end + end + end + ensure + @io = back_io + @irb_name = back_name + @irb_path = back_path + @irb.scanner = back_scanner + end + end + end +end + diff --git a/jni/ruby/lib/irb/ext/math-mode.rb b/jni/ruby/lib/irb/ext/math-mode.rb new file mode 100644 index 0000000..33e9968 --- /dev/null +++ b/jni/ruby/lib/irb/ext/math-mode.rb @@ -0,0 +1,47 @@ +# +# math-mode.rb - +# $Release Version: 0.9.6$ +# $Revision: 47112 $ +# by Keiju ISHITSUKA(keiju@ruby-lang.org) +# +# -- +# +# +# +require "mathn" + +module IRB + class Context + # Returns whether bc mode is enabled. + # + # See #math_mode= + attr_reader :math_mode + # Alias for #math_mode + alias math? math_mode + + # Sets bc mode, which loads +lib/mathn.rb+ so fractions or matrix are + # available. + # + # Also available as the +-m+ command line option. + # + # See IRB@Command+line+options and the unix manpage bc(1) for + # more information. + def math_mode=(opt) + if @math_mode == true && !opt + IRB.fail CantReturnToNormalMode + return + end + + @math_mode = opt + if math_mode + main.extend Math + print "start math mode\n" if verbose? + end + end + + def inspect? + @inspect_mode.nil? && !@math_mode or @inspect_mode + end + end +end + diff --git a/jni/ruby/lib/irb/ext/multi-irb.rb b/jni/ruby/lib/irb/ext/multi-irb.rb new file mode 100644 index 0000000..294f4e2 --- /dev/null +++ b/jni/ruby/lib/irb/ext/multi-irb.rb @@ -0,0 +1,265 @@ +# +# irb/multi-irb.rb - multiple irb module +# $Release Version: 0.9.6$ +# $Revision: 47266 $ +# by Keiju ISHITSUKA(keiju@ruby-lang.org) +# +# -- +# +# +# +IRB.fail CantShiftToMultiIrbMode unless defined?(Thread) +require "thread" + +module IRB + class JobManager + + # Creates a new JobManager object + def initialize + @jobs = [] + @current_job = nil + end + + # The active irb session + attr_accessor :current_job + + # The total number of irb sessions, used to set +irb_name+ of the current + # Context. + def n_jobs + @jobs.size + end + + # Returns the thread for the given +key+ object, see #search for more + # information. + def thread(key) + th, = search(key) + th + end + + # Returns the irb session for the given +key+ object, see #search for more + # information. + def irb(key) + _, irb = search(key) + irb + end + + # Returns the top level thread. + def main_thread + @jobs[0][0] + end + + # Returns the top level irb session. + def main_irb + @jobs[0][1] + end + + # Add the given +irb+ session to the jobs Array. + def insert(irb) + @jobs.push [Thread.current, irb] + end + + # Changes the current active irb session to the given +key+ in the jobs + # Array. + # + # Raises an IrbAlreadyDead exception if the given +key+ is no longer alive. + # + # If the given irb session is already active, an IrbSwitchedToCurrentThread + # exception is raised. + def switch(key) + th, irb = search(key) + IRB.fail IrbAlreadyDead unless th.alive? + IRB.fail IrbSwitchedToCurrentThread if th == Thread.current + @current_job = irb + th.run + Thread.stop + @current_job = irb(Thread.current) + end + + # Terminates the irb sessions specified by the given +keys+. + # + # Raises an IrbAlreadyDead exception if one of the given +keys+ is already + # terminated. + # + # See Thread#exit for more information. + def kill(*keys) + for key in keys + th, _ = search(key) + IRB.fail IrbAlreadyDead unless th.alive? + th.exit + end + end + + # Returns the associated job for the given +key+. + # + # If given an Integer, it will return the +key+ index for the jobs Array. + # + # When an instance of Irb is given, it will return the irb session + # associated with +key+. + # + # If given an instance of Thread, it will return the associated thread + # +key+ using Object#=== on the jobs Array. + # + # Otherwise returns the irb session with the same top-level binding as the + # given +key+. + # + # Raises a NoSuchJob exception if no job can be found with the given +key+. + def search(key) + job = case key + when Integer + @jobs[key] + when Irb + @jobs.find{|k, v| v.equal?(key)} + when Thread + @jobs.assoc(key) + else + @jobs.find{|k, v| v.context.main.equal?(key)} + end + IRB.fail NoSuchJob, key if job.nil? + job + end + + # Deletes the job at the given +key+. + def delete(key) + case key + when Integer + IRB.fail NoSuchJob, key unless @jobs[key] + @jobs[key] = nil + else + catch(:EXISTS) do + @jobs.each_index do + |i| + if @jobs[i] and (@jobs[i][0] == key || + @jobs[i][1] == key || + @jobs[i][1].context.main.equal?(key)) + @jobs[i] = nil + throw :EXISTS + end + end + IRB.fail NoSuchJob, key + end + end + until assoc = @jobs.pop; end unless @jobs.empty? + @jobs.push assoc + end + + # Outputs a list of jobs, see the irb command +irb_jobs+, or +jobs+. + def inspect + ary = [] + @jobs.each_index do + |i| + th, irb = @jobs[i] + next if th.nil? + + if th.alive? + if th.stop? + t_status = "stop" + else + t_status = "running" + end + else + t_status = "exited" + end + ary.push format("#%d->%s on %s (%s: %s)", + i, + irb.context.irb_name, + irb.context.main, + th, + t_status) + end + ary.join("\n") + end + end + + @JobManager = JobManager.new + + # The current JobManager in the session + def IRB.JobManager + @JobManager + end + + # The current Context in this session + def IRB.CurrentContext + IRB.JobManager.irb(Thread.current).context + end + + # Creates a new IRB session, see Irb.new. + # + # The optional +file+ argument is given to Context.new, along with the + # workspace created with the remaining arguments, see WorkSpace.new + def IRB.irb(file = nil, *main) + workspace = WorkSpace.new(*main) + parent_thread = Thread.current + Thread.start do + begin + irb = Irb.new(workspace, file) + rescue + print "Subirb can't start with context(self): ", workspace.main.inspect, "\n" + print "return to main irb\n" + Thread.pass + Thread.main.wakeup + Thread.exit + end + @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC] + @JobManager.insert(irb) + @JobManager.current_job = irb + begin + system_exit = false + catch(:IRB_EXIT) do + irb.eval_input + end + rescue SystemExit + system_exit = true + raise + #fail + ensure + unless system_exit + @JobManager.delete(irb) + if @JobManager.current_job == irb + if parent_thread.alive? + @JobManager.current_job = @JobManager.irb(parent_thread) + parent_thread.run + else + @JobManager.current_job = @JobManager.main_irb + @JobManager.main_thread.run + end + end + end + end + end + Thread.stop + @JobManager.current_job = @JobManager.irb(Thread.current) + end + + @CONF[:SINGLE_IRB_MODE] = false + @JobManager.insert(@CONF[:MAIN_CONTEXT].irb) + @JobManager.current_job = @CONF[:MAIN_CONTEXT].irb + + class Irb + def signal_handle + unless @context.ignore_sigint? + print "\nabort!!\n" if @context.verbose? + exit + end + + case @signal_status + when :IN_INPUT + print "^C\n" + IRB.JobManager.thread(self).raise RubyLex::TerminateLineInput + when :IN_EVAL + IRB.irb_abort(self) + when :IN_LOAD + IRB.irb_abort(self, LoadAbort) + when :IN_IRB + # ignore + else + # ignore other cases as well + end + end + end + + trap("SIGINT") do + @JobManager.current_job.signal_handle + Thread.stop + end + +end diff --git a/jni/ruby/lib/irb/ext/save-history.rb b/jni/ruby/lib/irb/ext/save-history.rb new file mode 100644 index 0000000..575b276 --- /dev/null +++ b/jni/ruby/lib/irb/ext/save-history.rb @@ -0,0 +1,103 @@ +# save-history.rb - +# $Release Version: 0.9.6$ +# $Revision: 47266 $ +# by Keiju ISHITSUKA(keiju@ruby-lang.org) +# +# -- +# +# +# + +require "readline" + +module IRB + module HistorySavingAbility # :nodoc: + end + + class Context + def init_save_history# :nodoc: + unless (class<<@io;self;end).include?(HistorySavingAbility) + @io.extend(HistorySavingAbility) + end + end + + # A copy of the default IRB.conf[:SAVE_HISTORY] + def save_history + IRB.conf[:SAVE_HISTORY] + end + + # Sets IRB.conf[:SAVE_HISTORY] to the given +val+ and calls + # #init_save_history with this context. + # + # Will store the number of +val+ entries of history in the #history_file + # + # Add the following to your +.irbrc+ to change the number of history + # entries stored to 1000: + # + # IRB.conf[:SAVE_HISTORY] = 1000 + def save_history=(val) + IRB.conf[:SAVE_HISTORY] = val + if val + main_context = IRB.conf[:MAIN_CONTEXT] + main_context = self unless main_context + main_context.init_save_history + end + end + + # A copy of the default IRB.conf[:HISTORY_FILE] + def history_file + IRB.conf[:HISTORY_FILE] + end + + # Set IRB.conf[:HISTORY_FILE] to the given +hist+. + def history_file=(hist) + IRB.conf[:HISTORY_FILE] = hist + end + end + + module HistorySavingAbility # :nodoc: + include Readline + + def HistorySavingAbility.extended(obj) + IRB.conf[:AT_EXIT].push proc{obj.save_history} + obj.load_history + obj + end + + def load_history + if history_file = IRB.conf[:HISTORY_FILE] + history_file = File.expand_path(history_file) + end + history_file = IRB.rc_file("_history") unless history_file + if File.exist?(history_file) + open(history_file) do |f| + f.each {|l| HISTORY << l.chomp} + end + end + end + + def save_history + if num = IRB.conf[:SAVE_HISTORY] and (num = num.to_i) > 0 + if history_file = IRB.conf[:HISTORY_FILE] + history_file = File.expand_path(history_file) + end + history_file = IRB.rc_file("_history") unless history_file + + # Change the permission of a file that already exists[BUG #7694] + begin + if File.stat(history_file).mode & 066 != 0 + File.chmod(0600, history_file) + end + rescue Errno::ENOENT + rescue + raise + end + + open(history_file, 'w', 0600 ) do |f| + hist = HISTORY.to_a + f.puts(hist[-num..-1] || hist) + end + end + end + end +end diff --git a/jni/ruby/lib/irb/ext/tracer.rb b/jni/ruby/lib/irb/ext/tracer.rb new file mode 100644 index 0000000..691215a --- /dev/null +++ b/jni/ruby/lib/irb/ext/tracer.rb @@ -0,0 +1,71 @@ +# +# irb/lib/tracer.rb - +# $Release Version: 0.9.6$ +# $Revision: 47112 $ +# by Keiju ISHITSUKA(keiju@ruby-lang.org) +# +# -- +# +# +# +require "tracer" + +module IRB + + # initialize tracing function + def IRB.initialize_tracer + Tracer.verbose = false + Tracer.add_filter { + |event, file, line, id, binding, *rests| + /^#{Regexp.quote(@CONF[:IRB_LIB_PATH])}/ !~ file and + File::basename(file) != "irb.rb" + } + end + + class Context + # Whether Tracer is used when evaluating statements in this context. + # + # See +lib/tracer.rb+ for more information. + attr_reader :use_tracer + alias use_tracer? use_tracer + + # Sets whether or not to use the Tracer library when evaluating statements + # in this context. + # + # See +lib/tracer.rb+ for more information. + def use_tracer=(opt) + if opt + Tracer.set_get_line_procs(@irb_path) { + |line_no, *rests| + @io.line(line_no) + } + elsif !opt && @use_tracer + Tracer.off + end + @use_tracer=opt + end + end + + class WorkSpace + alias __evaluate__ evaluate + # Evaluate the context of this workspace and use the Tracer library to + # output the exact lines of code are being executed in chronological order. + # + # See +lib/tracer.rb+ for more information. + def evaluate(context, statements, file = nil, line = nil) + if context.use_tracer? && file != nil && line != nil + Tracer.on + begin + __evaluate__(context, statements, file, line) + ensure + Tracer.off + end + else + __evaluate__(context, statements, file || __FILE__, line || __LINE__) + end + end + end + + IRB.initialize_tracer +end + diff --git a/jni/ruby/lib/irb/ext/use-loader.rb b/jni/ruby/lib/irb/ext/use-loader.rb new file mode 100644 index 0000000..7282995 --- /dev/null +++ b/jni/ruby/lib/irb/ext/use-loader.rb @@ -0,0 +1,73 @@ +# +# use-loader.rb - +# $Release Version: 0.9.6$ +# $Revision: 47112 $ +# by Keiju ISHITSUKA(keiju@ruby-lang.org) +# +# -- +# +# +# + +require "irb/cmd/load" +require "irb/ext/loader" + +class Object + alias __original__load__IRB_use_loader__ load + alias __original__require__IRB_use_loader__ require +end + +module IRB + module ExtendCommandBundle + # Loads the given file similarly to Kernel#load, see IrbLoader#irb_load + def irb_load(*opts, &b) + ExtendCommand::Load.execute(irb_context, *opts, &b) + end + # Loads the given file similarly to Kernel#require + def irb_require(*opts, &b) + ExtendCommand::Require.execute(irb_context, *opts, &b) + end + end + + class Context + + IRB.conf[:USE_LOADER] = false + + # Returns whether +irb+'s own file reader method is used by + # +load+/+require+ or not. + # + # This mode is globally affected (irb-wide). + def use_loader + IRB.conf[:USE_LOADER] + end + + alias use_loader? use_loader + + # Sets IRB.conf[:USE_LOADER] + # + # See #use_loader for more information. + def use_loader=(opt) + + if IRB.conf[:USE_LOADER] != opt + IRB.conf[:USE_LOADER] = opt + if opt + if !$".include?("irb/cmd/load") + end + (class<<@workspace.main;self;end).instance_eval { + alias_method :load, :irb_load + alias_method :require, :irb_require + } + else + (class<<@workspace.main;self;end).instance_eval { + alias_method :load, :__original__load__IRB_use_loader__ + alias_method :require, :__original__require__IRB_use_loader__ + } + end + end + print "Switch to load/require#{unless use_loader; ' non';end} trace mode.\n" if verbose? + opt + end + end +end + + diff --git a/jni/ruby/lib/irb/ext/workspaces.rb b/jni/ruby/lib/irb/ext/workspaces.rb new file mode 100644 index 0000000..a11cea3 --- /dev/null +++ b/jni/ruby/lib/irb/ext/workspaces.rb @@ -0,0 +1,66 @@ +# +# push-ws.rb - +# $Release Version: 0.9.6$ +# $Revision: 47112 $ +# by Keiju ISHITSUKA(keiju@ruby-lang.org) +# +# -- +# +# +# + +module IRB # :nodoc: + class Context + + # Size of the current WorkSpace stack + def irb_level + workspace_stack.size + end + + # WorkSpaces in the current stack + def workspaces + if defined? @workspaces + @workspaces + else + @workspaces = [] + end + end + + # Creates a new workspace with the given object or binding, and appends it + # onto the current #workspaces stack. + # + # See IRB::Context#change_workspace and IRB::WorkSpace.new for more + # information. + def push_workspace(*_main) + if _main.empty? + if workspaces.empty? + print "No other workspace\n" + return nil + end + ws = workspaces.pop + workspaces.push @workspace + @workspace = ws + return workspaces + end + + workspaces.push @workspace + @workspace = WorkSpace.new(@workspace.binding, _main[0]) + if !(class<IRB.CurrentContext.exit. + def irb_exit(ret = 0) + irb_context.exit(ret) + end + + # Displays current configuration. + # + # Modifing the configuration is achieved by sending a message to IRB.conf. + def irb_context + IRB.CurrentContext + end + + @ALIASES = [ + [:context, :irb_context, NO_OVERRIDE], + [:conf, :irb_context, NO_OVERRIDE], + [:irb_quit, :irb_exit, OVERRIDE_PRIVATE_ONLY], + [:exit, :irb_exit, OVERRIDE_PRIVATE_ONLY], + [:quit, :irb_exit, OVERRIDE_PRIVATE_ONLY], + ] + + @EXTEND_COMMANDS = [ + [:irb_current_working_workspace, :CurrentWorkingWorkspace, "irb/cmd/chws", + [:irb_print_working_workspace, OVERRIDE_ALL], + [:irb_cwws, OVERRIDE_ALL], + [:irb_pwws, OVERRIDE_ALL], + [:cwws, NO_OVERRIDE], + [:pwws, NO_OVERRIDE], + [:irb_current_working_binding, OVERRIDE_ALL], + [:irb_print_working_binding, OVERRIDE_ALL], + [:irb_cwb, OVERRIDE_ALL], + [:irb_pwb, OVERRIDE_ALL], + ], + [:irb_change_workspace, :ChangeWorkspace, "irb/cmd/chws", + [:irb_chws, OVERRIDE_ALL], + [:irb_cws, OVERRIDE_ALL], + [:chws, NO_OVERRIDE], + [:cws, NO_OVERRIDE], + [:irb_change_binding, OVERRIDE_ALL], + [:irb_cb, OVERRIDE_ALL], + [:cb, NO_OVERRIDE]], + + [:irb_workspaces, :Workspaces, "irb/cmd/pushws", + [:workspaces, NO_OVERRIDE], + [:irb_bindings, OVERRIDE_ALL], + [:bindings, NO_OVERRIDE]], + [:irb_push_workspace, :PushWorkspace, "irb/cmd/pushws", + [:irb_pushws, OVERRIDE_ALL], + [:pushws, NO_OVERRIDE], + [:irb_push_binding, OVERRIDE_ALL], + [:irb_pushb, OVERRIDE_ALL], + [:pushb, NO_OVERRIDE]], + [:irb_pop_workspace, :PopWorkspace, "irb/cmd/pushws", + [:irb_popws, OVERRIDE_ALL], + [:popws, NO_OVERRIDE], + [:irb_pop_binding, OVERRIDE_ALL], + [:irb_popb, OVERRIDE_ALL], + [:popb, NO_OVERRIDE]], + + [:irb_load, :Load, "irb/cmd/load"], + [:irb_require, :Require, "irb/cmd/load"], + [:irb_source, :Source, "irb/cmd/load", + [:source, NO_OVERRIDE]], + + [:irb, :IrbCommand, "irb/cmd/subirb"], + [:irb_jobs, :Jobs, "irb/cmd/subirb", + [:jobs, NO_OVERRIDE]], + [:irb_fg, :Foreground, "irb/cmd/subirb", + [:fg, NO_OVERRIDE]], + [:irb_kill, :Kill, "irb/cmd/subirb", + [:kill, OVERRIDE_PRIVATE_ONLY]], + + [:irb_help, :Help, "irb/cmd/help", + [:help, NO_OVERRIDE]], + + ] + + # Installs the default irb commands: + # + # +irb_current_working_workspace+:: Context#main + # +irb_change_workspace+:: Context#change_workspace + # +irb_workspaces+:: Context#workspaces + # +irb_push_workspace+:: Context#push_workspace + # +irb_pop_workspace+:: Context#pop_workspace + # +irb_load+:: #irb_load + # +irb_require+:: #irb_require + # +irb_source+:: IrbLoader#source_file + # +irb+:: IRB.irb + # +irb_jobs+:: JobManager + # +irb_fg+:: JobManager#switch + # +irb_kill+:: JobManager#kill + # +irb_help+:: IRB@Command+line+options + def self.install_extend_commands + for args in @EXTEND_COMMANDS + def_extend_command(*args) + end + end + + # Evaluate the given +cmd_name+ on the given +cmd_class+ Class. + # + # Will also define any given +aliases+ for the method. + # + # The optional +load_file+ parameter will be required within the method + # definition. + def self.def_extend_command(cmd_name, cmd_class, load_file = nil, *aliases) + case cmd_class + when Symbol + cmd_class = cmd_class.id2name + when String + when Class + cmd_class = cmd_class.name + end + + if load_file + line = __LINE__; eval %[ + def #{cmd_name}(*opts, &b) + require "#{load_file}" + arity = ExtendCommand::#{cmd_class}.instance_method(:execute).arity + args = (1..(arity < 0 ? ~arity : arity)).map {|i| "arg" + i.to_s } + args << "*opts" if arity < 0 + args << "&block" + args = args.join(", ") + line = __LINE__; eval %[ + def #{cmd_name}(\#{args}) + ExtendCommand::#{cmd_class}.execute(irb_context, \#{args}) + end + ], nil, __FILE__, line + send :#{cmd_name}, *opts, &b + end + ], nil, __FILE__, line + else + line = __LINE__; eval %[ + def #{cmd_name}(*opts, &b) + ExtendCommand::#{cmd_class}.execute(irb_context, *opts, &b) + end + ], nil, __FILE__, line + end + + for ali, flag in aliases + @ALIASES.push [ali, cmd_name, flag] + end + end + + # Installs alias methods for the default irb commands, see + # ::install_extend_commands. + def install_alias_method(to, from, override = NO_OVERRIDE) + to = to.id2name unless to.kind_of?(String) + from = from.id2name unless from.kind_of?(String) + + if override == OVERRIDE_ALL or + (override == OVERRIDE_PRIVATE_ONLY) && !respond_to?(to) or + (override == NO_OVERRIDE) && !respond_to?(to, true) + target = self + (class << self; self; end).instance_eval{ + if target.respond_to?(to, true) && + !target.respond_to?(EXCB.irb_original_method_name(to), true) + alias_method(EXCB.irb_original_method_name(to), to) + end + alias_method to, from + } + else + print "irb: warn: can't alias #{to} from #{from}.\n" + end + end + + def self.irb_original_method_name(method_name) # :nodoc: + "irb_" + method_name + "_org" + end + + # Installs alias methods for the default irb commands on the given object + # using #install_alias_method. + def self.extend_object(obj) + unless (class << obj; ancestors; end).include?(EXCB) + super + for ali, com, flg in @ALIASES + obj.install_alias_method(ali, com, flg) + end + end + end + + install_extend_commands + end + + # Extends methods for the Context module + module ContextExtender + CE = ContextExtender # :nodoc: + + @EXTEND_COMMANDS = [ + [:eval_history=, "irb/ext/history.rb"], + [:use_tracer=, "irb/ext/tracer.rb"], + [:math_mode=, "irb/ext/math-mode.rb"], + [:use_loader=, "irb/ext/use-loader.rb"], + [:save_history=, "irb/ext/save-history.rb"], + ] + + # Installs the default context extensions as irb commands: + # + # Context#eval_history=:: +irb/ext/history.rb+ + # Context#use_tracer=:: +irb/ext/tracer.rb+ + # Context#math_mode=:: +irb/ext/math-mode.rb+ + # Context#use_loader=:: +irb/ext/use-loader.rb+ + # Context#save_history=:: +irb/ext/save-history.rb+ + def self.install_extend_commands + for args in @EXTEND_COMMANDS + def_extend_command(*args) + end + end + + # Evaluate the given +command+ from the given +load_file+ on the Context + # module. + # + # Will also define any given +aliases+ for the method. + def self.def_extend_command(cmd_name, load_file, *aliases) + line = __LINE__; Context.module_eval %[ + def #{cmd_name}(*opts, &b) + Context.module_eval {remove_method(:#{cmd_name})} + require "#{load_file}" + send :#{cmd_name}, *opts, &b + end + for ali in aliases + alias_method ali, cmd_name + end + ], __FILE__, line + end + + CE.install_extend_commands + end + + # A convenience module for extending Ruby methods. + module MethodExtender + # Extends the given +base_method+ with a prefix call to the given + # +extend_method+. + def def_pre_proc(base_method, extend_method) + base_method = base_method.to_s + extend_method = extend_method.to_s + + alias_name = new_alias_name(base_method) + module_eval %[ + alias_method alias_name, base_method + def #{base_method}(*opts) + send :#{extend_method}, *opts + send :#{alias_name}, *opts + end + ] + end + + # Extends the given +base_method+ with a postfix call to the given + # +extend_method+. + def def_post_proc(base_method, extend_method) + base_method = base_method.to_s + extend_method = extend_method.to_s + + alias_name = new_alias_name(base_method) + module_eval %[ + alias_method alias_name, base_method + def #{base_method}(*opts) + send :#{alias_name}, *opts + send :#{extend_method}, *opts + end + ] + end + + # Returns a unique method name to use as an alias for the given +name+. + # + # Usually returns #{prefix}#{name}#{postfix}, example: + # + # new_alias_name('foo') #=> __alias_of__foo__ + # def bar; end + # new_alias_name('bar') #=> __alias_of__bar__2 + def new_alias_name(name, prefix = "__alias_of__", postfix = "__") + base_name = "#{prefix}#{name}#{postfix}" + all_methods = instance_methods(true) + private_instance_methods(true) + same_methods = all_methods.grep(/^#{Regexp.quote(base_name)}[0-9]*$/) + return base_name if same_methods.empty? + no = same_methods.size + while !same_methods.include?(alias_name = base_name + no) + no += 1 + end + alias_name + end + end +end + diff --git a/jni/ruby/lib/irb/frame.rb b/jni/ruby/lib/irb/frame.rb new file mode 100644 index 0000000..4a1d080 --- /dev/null +++ b/jni/ruby/lib/irb/frame.rb @@ -0,0 +1,80 @@ +# +# frame.rb - +# $Release Version: 0.9$ +# $Revision: 47112 $ +# by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd) +# +# -- +# +# +# + +require "e2mmap" + +module IRB + class Frame + extend Exception2MessageMapper + def_exception :FrameOverflow, "frame overflow" + def_exception :FrameUnderflow, "frame underflow" + + # Default number of stack frames + INIT_STACK_TIMES = 3 + # Default number of frames offset + CALL_STACK_OFFSET = 3 + + # Creates a new stack frame + def initialize + @frames = [TOPLEVEL_BINDING] * INIT_STACK_TIMES + end + + # Used by Kernel#set_trace_func to register each event in the call stack + def trace_func(event, file, line, id, binding) + case event + when 'call', 'class' + @frames.push binding + when 'return', 'end' + @frames.pop + end + end + + # Returns the +n+ number of frames on the call stack from the last frame + # initialized. + # + # Raises FrameUnderflow if there are no frames in the given stack range. + def top(n = 0) + bind = @frames[-(n + CALL_STACK_OFFSET)] + Fail FrameUnderflow unless bind + bind + end + + # Returns the +n+ number of frames on the call stack from the first frame + # initialized. + # + # Raises FrameOverflow if there are no frames in the given stack range. + def bottom(n = 0) + bind = @frames[n] + Fail FrameOverflow unless bind + bind + end + + # Convenience method for Frame#bottom + def Frame.bottom(n = 0) + @backtrace.bottom(n) + end + + # Convenience method for Frame#top + def Frame.top(n = 0) + @backtrace.top(n) + end + + # Returns the binding context of the caller from the last frame initialized + def Frame.sender + eval "self", @backtrace.top + end + + @backtrace = Frame.new + set_trace_func proc{|event, file, line, id, binding, klass| + @backtrace.trace_func(event, file, line, id, binding) + } + end +end diff --git a/jni/ruby/lib/irb/help.rb b/jni/ruby/lib/irb/help.rb new file mode 100644 index 0000000..c0160f0 --- /dev/null +++ b/jni/ruby/lib/irb/help.rb @@ -0,0 +1,36 @@ +# +# irb/help.rb - print usage module +# $Release Version: 0.9.6$ +# $Revision: 47112 $ +# by Keiju ISHITSUKA(keiju@ishitsuka.com) +# +# -- +# +# +# + +require 'irb/magic-file' + +module IRB + # Outputs the irb help message, see IRB@Command+line+options. + def IRB.print_usage + lc = IRB.conf[:LC_MESSAGES] + path = lc.find("irb/help-message") + space_line = false + IRB::MagicFile.open(path){|f| + f.each_line do |l| + if /^\s*$/ =~ l + lc.puts l unless space_line + space_line = true + next + end + space_line = false + + l.sub!(/#.*$/, "") + next if /^\s*$/ =~ l + lc.puts l + end + } + end +end + diff --git a/jni/ruby/lib/irb/init.rb b/jni/ruby/lib/irb/init.rb new file mode 100644 index 0000000..98289b3 --- /dev/null +++ b/jni/ruby/lib/irb/init.rb @@ -0,0 +1,304 @@ +# +# irb/init.rb - irb initialize module +# $Release Version: 0.9.6$ +# $Revision: 47114 $ +# by Keiju ISHITSUKA(keiju@ruby-lang.org) +# +# -- +# +# +# + +module IRB # :nodoc: + + # initialize config + def IRB.setup(ap_path) + IRB.init_config(ap_path) + IRB.init_error + IRB.parse_opts + IRB.run_config + IRB.load_modules + + unless @CONF[:PROMPT][@CONF[:PROMPT_MODE]] + IRB.fail(UndefinedPromptMode, @CONF[:PROMPT_MODE]) + end + end + + # @CONF default setting + def IRB.init_config(ap_path) + # class instance variables + @TRACER_INITIALIZED = false + + # default configurations + unless ap_path and @CONF[:AP_NAME] + ap_path = File.join(File.dirname(File.dirname(__FILE__)), "irb.rb") + end + @CONF[:AP_NAME] = File::basename(ap_path, ".rb") + + @CONF[:IRB_NAME] = "irb" + @CONF[:IRB_LIB_PATH] = File.dirname(__FILE__) + + @CONF[:RC] = true + @CONF[:LOAD_MODULES] = [] + @CONF[:IRB_RC] = nil + + @CONF[:MATH_MODE] = false + @CONF[:USE_READLINE] = false unless defined?(ReadlineInputMethod) + @CONF[:INSPECT_MODE] = true + @CONF[:USE_TRACER] = false + @CONF[:USE_LOADER] = false + @CONF[:IGNORE_SIGINT] = true + @CONF[:IGNORE_EOF] = false + @CONF[:ECHO] = nil + @CONF[:VERBOSE] = nil + + @CONF[:EVAL_HISTORY] = nil + @CONF[:SAVE_HISTORY] = nil + + @CONF[:BACK_TRACE_LIMIT] = 16 + + @CONF[:PROMPT] = { + :NULL => { + :PROMPT_I => nil, + :PROMPT_N => nil, + :PROMPT_S => nil, + :PROMPT_C => nil, + :RETURN => "%s\n" + }, + :DEFAULT => { + :PROMPT_I => "%N(%m):%03n:%i> ", + :PROMPT_N => "%N(%m):%03n:%i> ", + :PROMPT_S => "%N(%m):%03n:%i%l ", + :PROMPT_C => "%N(%m):%03n:%i* ", + :RETURN => "=> %s\n" + }, + :CLASSIC => { + :PROMPT_I => "%N(%m):%03n:%i> ", + :PROMPT_N => "%N(%m):%03n:%i> ", + :PROMPT_S => "%N(%m):%03n:%i%l ", + :PROMPT_C => "%N(%m):%03n:%i* ", + :RETURN => "%s\n" + }, + :SIMPLE => { + :PROMPT_I => ">> ", + :PROMPT_N => ">> ", + :PROMPT_S => nil, + :PROMPT_C => "?> ", + :RETURN => "=> %s\n" + }, + :INF_RUBY => { + :PROMPT_I => "%N(%m):%03n:%i> ", + :PROMPT_N => nil, + :PROMPT_S => nil, + :PROMPT_C => nil, + :RETURN => "%s\n", + :AUTO_INDENT => true + }, + :XMP => { + :PROMPT_I => nil, + :PROMPT_N => nil, + :PROMPT_S => nil, + :PROMPT_C => nil, + :RETURN => " ==>%s\n" + } + } + + @CONF[:PROMPT_MODE] = (STDIN.tty? ? :DEFAULT : :NULL) + @CONF[:AUTO_INDENT] = false + + @CONF[:CONTEXT_MODE] = 3 # use binding in function on TOPLEVEL_BINDING + @CONF[:SINGLE_IRB] = false + + @CONF[:LC_MESSAGES] = Locale.new + + @CONF[:AT_EXIT] = [] + + @CONF[:DEBUG_LEVEL] = 0 + end + + def IRB.init_error + @CONF[:LC_MESSAGES].load("irb/error.rb") + end + + # option analyzing + def IRB.parse_opts + load_path = [] + while opt = ARGV.shift + case opt + when "-f" + @CONF[:RC] = false + when "-m" + @CONF[:MATH_MODE] = true + when "-d" + $DEBUG = true + $VERBOSE = true + when "-w" + $VERBOSE = true + when /^-W(.+)?/ + opt = $1 || ARGV.shift + case opt + when "0" + $VERBOSE = nil + when "1" + $VERBOSE = false + else + $VERBOSE = true + end + when /^-r(.+)?/ + opt = $1 || ARGV.shift + @CONF[:LOAD_MODULES].push opt if opt + when /^-I(.+)?/ + opt = $1 || ARGV.shift + load_path.concat(opt.split(File::PATH_SEPARATOR)) if opt + when '-U' + set_encoding("UTF-8", "UTF-8") + when /^-E(.+)?/, /^--encoding(?:=(.+))?/ + opt = $1 || ARGV.shift + set_encoding(*opt.split(':', 2)) + when "--inspect" + if /^-/ !~ ARGV.first + @CONF[:INSPECT_MODE] = ARGV.shift + else + @CONF[:INSPECT_MODE] = true + end + when "--noinspect" + @CONF[:INSPECT_MODE] = false + when "--readline" + @CONF[:USE_READLINE] = true + when "--noreadline" + @CONF[:USE_READLINE] = false + when "--echo" + @CONF[:ECHO] = true + when "--noecho" + @CONF[:ECHO] = false + when "--verbose" + @CONF[:VERBOSE] = true + when "--noverbose" + @CONF[:VERBOSE] = false + when /^--prompt-mode(?:=(.+))?/, /^--prompt(?:=(.+))?/ + opt = $1 || ARGV.shift + prompt_mode = opt.upcase.tr("-", "_").intern + @CONF[:PROMPT_MODE] = prompt_mode + when "--noprompt" + @CONF[:PROMPT_MODE] = :NULL + when "--inf-ruby-mode" + @CONF[:PROMPT_MODE] = :INF_RUBY + when "--sample-book-mode", "--simple-prompt" + @CONF[:PROMPT_MODE] = :SIMPLE + when "--tracer" + @CONF[:USE_TRACER] = true + when /^--back-trace-limit(?:=(.+))?/ + @CONF[:BACK_TRACE_LIMIT] = ($1 || ARGV.shift).to_i + when /^--context-mode(?:=(.+))?/ + @CONF[:CONTEXT_MODE] = ($1 || ARGV.shift).to_i + when "--single-irb" + @CONF[:SINGLE_IRB] = true + when /^--irb_debug(?:=(.+))?/ + @CONF[:DEBUG_LEVEL] = ($1 || ARGV.shift).to_i + when "-v", "--version" + print IRB.version, "\n" + exit 0 + when "-h", "--help" + require "irb/help" + IRB.print_usage + exit 0 + when "--" + if opt = ARGV.shift + @CONF[:SCRIPT] = opt + $0 = opt + end + break + when /^-/ + IRB.fail UnrecognizedSwitch, opt + else + @CONF[:SCRIPT] = opt + $0 = opt + break + end + end + load_path.collect! do |path| + /\A\.\// =~ path ? path : File.expand_path(path) + end + $LOAD_PATH.unshift(*load_path) + + end + + # running config + def IRB.run_config + if @CONF[:RC] + begin + load rc_file + rescue LoadError, Errno::ENOENT + rescue # StandardError, ScriptError + print "load error: #{rc_file}\n" + print $!.class, ": ", $!, "\n" + for err in $@[0, $@.size - 2] + print "\t", err, "\n" + end + end + end + end + + IRBRC_EXT = "rc" + def IRB.rc_file(ext = IRBRC_EXT) + if !@CONF[:RC_NAME_GENERATOR] + rc_file_generators do |rcgen| + @CONF[:RC_NAME_GENERATOR] ||= rcgen + if File.exist?(rcgen.call(IRBRC_EXT)) + @CONF[:RC_NAME_GENERATOR] = rcgen + break + end + end + end + case rc_file = @CONF[:RC_NAME_GENERATOR].call(ext) + when String + return rc_file + else + IRB.fail IllegalRCNameGenerator + end + end + + # enumerate possible rc-file base name generators + def IRB.rc_file_generators + if irbrc = ENV["IRBRC"] + yield proc{|rc| rc == "rc" ? irbrc : irbrc+rc} + end + if home = ENV["HOME"] + yield proc{|rc| home+"/.irb#{rc}"} + end + home = Dir.pwd + yield proc{|rc| home+"/.irb#{rc}"} + yield proc{|rc| home+"/irb#{rc.sub(/\A_?/, '.')}"} + yield proc{|rc| home+"/_irb#{rc}"} + yield proc{|rc| home+"/$irb#{rc}"} + end + + # loading modules + def IRB.load_modules + for m in @CONF[:LOAD_MODULES] + begin + require m + rescue LoadError => err + warn err.backtrace[0] << ":#{err.class}: #{err}" + end + end + end + + + DefaultEncodings = Struct.new(:external, :internal) + class << IRB + private + def set_encoding(extern, intern = nil) + verbose, $VERBOSE = $VERBOSE, nil + Encoding.default_external = extern unless extern.nil? || extern.empty? + Encoding.default_internal = intern unless intern.nil? || intern.empty? + @CONF[:ENCODINGS] = IRB::DefaultEncodings.new(extern, intern) + [$stdin, $stdout, $stderr].each do |io| + io.set_encoding(extern, intern) + end + @CONF[:LC_MESSAGES].instance_variable_set(:@encoding, extern) + ensure + $VERBOSE = verbose + end + end +end diff --git a/jni/ruby/lib/irb/input-method.rb b/jni/ruby/lib/irb/input-method.rb new file mode 100644 index 0000000..97add92 --- /dev/null +++ b/jni/ruby/lib/irb/input-method.rb @@ -0,0 +1,191 @@ +# +# irb/input-method.rb - input methods used irb +# $Release Version: 0.9.6$ +# $Revision: 47266 $ +# by Keiju ISHITSUKA(keiju@ruby-lang.org) +# +# -- +# +# +# +require 'irb/src_encoding' +require 'irb/magic-file' + +module IRB + STDIN_FILE_NAME = "(line)" # :nodoc: + class InputMethod + + # Creates a new input method object + def initialize(file = STDIN_FILE_NAME) + @file_name = file + end + # The file name of this input method, usually given during initialization. + attr_reader :file_name + + # The irb prompt associated with this input method + attr_accessor :prompt + + # Reads the next line from this input method. + # + # See IO#gets for more information. + def gets + IRB.fail NotImplementedError, "gets" + end + public :gets + + # Whether this input method is still readable when there is no more data to + # read. + # + # See IO#eof for more information. + def readable_after_eof? + false + end + end + + class StdioInputMethod < InputMethod + # Creates a new input method object + def initialize + super + @line_no = 0 + @line = [] + @stdin = IO.open(STDIN.to_i, :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-") + @stdout = IO.open(STDOUT.to_i, 'w', :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-") + end + + # Reads the next line from this input method. + # + # See IO#gets for more information. + def gets + print @prompt + line = @stdin.gets + @line[@line_no += 1] = line + end + + # Whether the end of this input method has been reached, returns +true+ if + # there is no more data to read. + # + # See IO#eof? for more information. + def eof? + @stdin.eof? + end + + # Whether this input method is still readable when there is no more data to + # read. + # + # See IO#eof for more information. + def readable_after_eof? + true + end + + # Returns the current line number for #io. + # + # #line counts the number of times #gets is called. + # + # See IO#lineno for more information. + def line(line_no) + @line[line_no] + end + + # The external encoding for standard input. + def encoding + @stdin.external_encoding + end + end + + # Use a File for IO with irb, see InputMethod + class FileInputMethod < InputMethod + # Creates a new input method object + def initialize(file) + super + @io = IRB::MagicFile.open(file) + end + # The file name of this input method, usually given during initialization. + attr_reader :file_name + + # Whether the end of this input method has been reached, returns +true+ if + # there is no more data to read. + # + # See IO#eof? for more information. + def eof? + @io.eof? + end + + # Reads the next line from this input method. + # + # See IO#gets for more information. + def gets + print @prompt + l = @io.gets + l + end + + # The external encoding for standard input. + def encoding + @io.external_encoding + end + end + + begin + require "readline" + class ReadlineInputMethod < InputMethod + include Readline + # Creates a new input method object using Readline + def initialize + super + + @line_no = 0 + @line = [] + @eof = false + + @stdin = IO.open(STDIN.to_i, :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-") + @stdout = IO.open(STDOUT.to_i, 'w', :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-") + end + + # Reads the next line from this input method. + # + # See IO#gets for more information. + def gets + Readline.input = @stdin + Readline.output = @stdout + if l = readline(@prompt, false) + HISTORY.push(l) if !l.empty? + @line[@line_no += 1] = l + "\n" + else + @eof = true + l + end + end + + # Whether the end of this input method has been reached, returns +true+ + # if there is no more data to read. + # + # See IO#eof? for more information. + def eof? + @eof + end + + # Whether this input method is still readable when there is no more data to + # read. + # + # See IO#eof for more information. + def readable_after_eof? + true + end + + # Returns the current line number for #io. + # + # #line counts the number of times #gets is called. + # + # See IO#lineno for more information. + def line(line_no) + @line[line_no] + end + + # The external encoding for standard input. + def encoding + @stdin.external_encoding + end + end + rescue LoadError + end +end diff --git a/jni/ruby/lib/irb/inspector.rb b/jni/ruby/lib/irb/inspector.rb new file mode 100644 index 0000000..f09b129 --- /dev/null +++ b/jni/ruby/lib/irb/inspector.rb @@ -0,0 +1,131 @@ +# +# irb/inspector.rb - inspect methods +# $Release Version: 0.9.6$ +# $Revision: 1.19 $ +# $Date: 2002/06/11 07:51:31 $ +# by Keiju ISHITSUKA(keiju@ruby-lang.org) +# +# -- +# +# +# + +module IRB # :nodoc: + + + # Convenience method to create a new Inspector, using the given +inspect+ + # proc, and optional +init+ proc and passes them to Inspector.new + # + # irb(main):001:0> ins = IRB::Inspector(proc{ |v| "omg! #{v}" }) + # irb(main):001:0> IRB.CurrentContext.inspect_mode = ins # => omg! # + # irb(main):001:0> "what?" #=> omg! what? + # + def IRB::Inspector(inspect, init = nil) + Inspector.new(inspect, init) + end + + # An irb inspector + # + # In order to create your own custom inspector there are two things you + # should be aware of: + # + # Inspector uses #inspect_value, or +inspect_proc+, for output of return values. + # + # This also allows for an optional #init+, or +init_proc+, which is called + # when the inspector is activated. + # + # Knowing this, you can create a rudimentary inspector as follows: + # + # irb(main):001:0> ins = IRB::Inspector.new(proc{ |v| "omg! #{v}" }) + # irb(main):001:0> IRB.CurrentContext.inspect_mode = ins # => omg! # + # irb(main):001:0> "what?" #=> omg! what? + # + class Inspector + # Default inspectors available to irb, this includes: + # + # +:pp+:: Using Kernel#pretty_inspect + # +:yaml+:: Using YAML.dump + # +:marshal+:: Using Marshal.dump + INSPECTORS = {} + + # Determines the inspector to use where +inspector+ is one of the keys passed + # during inspector definition. + def self.keys_with_inspector(inspector) + INSPECTORS.select{|k,v| v == inspector}.collect{|k, v| k} + end + + # Example + # + # Inspector.def_inspector(key, init_p=nil){|v| v.inspect} + # Inspector.def_inspector([key1,..], init_p=nil){|v| v.inspect} + # Inspector.def_inspector(key, inspector) + # Inspector.def_inspector([key1,...], inspector) + def self.def_inspector(key, arg=nil, &block) + if block_given? + inspector = IRB::Inspector(block, arg) + else + inspector = arg + end + + case key + when Array + for k in key + def_inspector(k, inspector) + end + when Symbol + INSPECTORS[key] = inspector + INSPECTORS[key.to_s] = inspector + when String + INSPECTORS[key] = inspector + INSPECTORS[key.intern] = inspector + else + INSPECTORS[key] = inspector + end + end + + # Creates a new inspector object, using the given +inspect_proc+ when + # output return values in irb. + def initialize(inspect_proc, init_proc = nil) + @init = init_proc + @inspect = inspect_proc + end + + # Proc to call when the inspector is activated, good for requiring + # dependent libraries. + def init + @init.call if @init + end + + # Proc to call when the input is evaluated and output in irb. + def inspect_value(v) + @inspect.call(v) + end + end + + Inspector.def_inspector([false, :to_s, :raw]){|v| v.to_s} + Inspector.def_inspector([true, :p, :inspect]){|v| + begin + v.inspect + rescue NoMethodError + puts "(Object doesn't support #inspect)" + end + } + Inspector.def_inspector([:pp, :pretty_inspect], proc{require "pp"}){|v| v.pretty_inspect.chomp} + Inspector.def_inspector([:yaml, :YAML], proc{require "yaml"}){|v| + begin + YAML.dump(v) + rescue + puts "(can't dump yaml. use inspect)" + v.inspect + end + } + + Inspector.def_inspector([:marshal, :Marshal, :MARSHAL, Marshal]){|v| + Marshal.dump(v) + } +end + + + + + diff --git a/jni/ruby/lib/irb/lc/.document b/jni/ruby/lib/irb/lc/.document new file mode 100644 index 0000000..524bb94 --- /dev/null +++ b/jni/ruby/lib/irb/lc/.document @@ -0,0 +1,4 @@ +# hide help-message files which contain usage information +error.rb +ja/encoding_aliases.rb +ja/error.rb diff --git a/jni/ruby/lib/irb/lc/error.rb b/jni/ruby/lib/irb/lc/error.rb new file mode 100644 index 0000000..a0d0dc8 --- /dev/null +++ b/jni/ruby/lib/irb/lc/error.rb @@ -0,0 +1,31 @@ +# +# irb/lc/error.rb - +# $Release Version: 0.9.6$ +# $Revision: 38600 $ +# by Keiju ISHITSUKA(keiju@ruby-lang.org) +# +# -- +# +# +# +require "e2mmap" + +# :stopdoc: +module IRB + + # exceptions + extend Exception2MessageMapper + def_exception :UnrecognizedSwitch, "Unrecognized switch: %s" + def_exception :NotImplementedError, "Need to define `%s'" + def_exception :CantReturnToNormalMode, "Can't return to normal mode." + def_exception :IllegalParameter, "Invalid parameter(%s)." + def_exception :IrbAlreadyDead, "Irb is already dead." + def_exception :IrbSwitchedToCurrentThread, "Switched to current thread." + def_exception :NoSuchJob, "No such job(%s)." + def_exception :CantShiftToMultiIrbMode, "Can't shift to multi irb mode." + def_exception :CantChangeBinding, "Can't change binding to (%s)." + def_exception :UndefinedPromptMode, "Undefined prompt mode(%s)." + def_exception :IllegalRCGenerator, 'Define illegal RC_NAME_GENERATOR.' + +end +# :startdoc: diff --git a/jni/ruby/lib/irb/lc/help-message b/jni/ruby/lib/irb/lc/help-message new file mode 100644 index 0000000..7ac1b2a --- /dev/null +++ b/jni/ruby/lib/irb/lc/help-message @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# +# irb/lc/help-message.rb - +# $Release Version: 0.9.6$ +# $Revision: 41028 $ +# by Keiju ISHITSUKA(keiju@ruby-lang.org) +# +# -- +# +# +# +Usage: irb.rb [options] [programfile] [arguments] + -f Suppress read of ~/.irbrc + -m Bc mode (load mathn, fraction or matrix are available) + -d Set $DEBUG to true (same as `ruby -d') + -r load-module Same as `ruby -r' + -I path Specify $LOAD_PATH directory + -U Same as `ruby -U` + -E enc Same as `ruby -E` + -w Same as `ruby -w` + -W[level=2] Same as `ruby -W` + --context-mode n Set n[0-3] to method to create Binding Object, + when new workspace was created + --echo Show result(default) + --noecho Don't show result + --inspect Use `inspect' for output (default except for bc mode) + --noinspect Don't use inspect for output + --readline Use Readline extension module + --noreadline Don't use Readline extension module + --prompt prompt-mode/--prompt-mode prompt-mode + Switch prompt mode. Pre-defined prompt modes are + `default', `simple', `xmp' and `inf-ruby' + --inf-ruby-mode Use prompt appropriate for inf-ruby-mode on emacs. + Suppresses --readline. + --sample-book-mode/--simple-prompt + Simple prompt mode + --noprompt No prompt mode + --single-irb Share self with sub-irb. + --tracer Display trace for each execution of commands. + --back-trace-limit n + Display backtrace top n and tail n. The default + value is 16. + --irb_debug n Set internal debug level to n (not for popular use) + --verbose Show details + --noverbose Don't show details + -v, --version Print the version of irb + -h, --help Print help + -- Separate options of irb from the list of command-line args + +# vim:fileencoding=utf-8 diff --git a/jni/ruby/lib/irb/lc/ja/encoding_aliases.rb b/jni/ruby/lib/irb/lc/ja/encoding_aliases.rb new file mode 100644 index 0000000..5bef32e --- /dev/null +++ b/jni/ruby/lib/irb/lc/ja/encoding_aliases.rb @@ -0,0 +1,10 @@ +# :stopdoc: +module IRB + class Locale + @@legacy_encoding_alias_map = { + 'ujis' => Encoding::EUC_JP, + 'euc' => Encoding::EUC_JP + }.freeze + end +end +# :startdoc: diff --git a/jni/ruby/lib/irb/lc/ja/error.rb b/jni/ruby/lib/irb/lc/ja/error.rb new file mode 100644 index 0000000..6532777 --- /dev/null +++ b/jni/ruby/lib/irb/lc/ja/error.rb @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# irb/lc/ja/error.rb - +# $Release Version: 0.9.6$ +# $Revision: 38600 $ +# by Keiju ISHITSUKA(keiju@ruby-lang.org) +# +# -- +# +# +# +require "e2mmap" + +# :stopdoc: +module IRB + # exceptions + extend Exception2MessageMapper + def_exception :UnrecognizedSwitch, 'スイッチ(%s)が分りません' + def_exception :NotImplementedError, '`%s\'の定義が必要です' + def_exception :CantReturnToNormalMode, 'Normalモードに戻れません.' + def_exception :IllegalParameter, 'パラメータ(%s)が間違っています.' + def_exception :IrbAlreadyDead, 'Irbは既に死んでいます.' + def_exception :IrbSwitchedToCurrentThread, 'カレントスレッドに切り替わりました.' + def_exception :NoSuchJob, 'そのようなジョブ(%s)はありません.' + def_exception :CantShiftToMultiIrbMode, 'multi-irb modeに移れません.' + def_exception :CantChangeBinding, 'バインディング(%s)に変更できません.' + def_exception :UndefinedPromptMode, 'プロンプトモード(%s)は定義されていません.' + def_exception :IllegalRCNameGenerator, 'RC_NAME_GENERATORが正しく定義されていません.' +end +# :startdoc: +# vim:fileencoding=utf-8 diff --git a/jni/ruby/lib/irb/lc/ja/help-message b/jni/ruby/lib/irb/lc/ja/help-message new file mode 100644 index 0000000..1483892 --- /dev/null +++ b/jni/ruby/lib/irb/lc/ja/help-message @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# irb/lc/ja/help-message.rb - +# $Release Version: 0.9.6$ +# $Revision: 41071 $ +# by Keiju ISHITSUKA(keiju@ruby-lang.org) +# +# -- +# +# +# +Usage: irb.rb [options] [programfile] [arguments] + -f ~/.irbrc を読み込まない. + -m bcモード(分数, 行列の計算ができる) + -d $DEBUG をtrueにする(ruby -d と同じ) + -r load-module ruby -r と同じ. + -I path $LOAD_PATH に path を追加する. + -U ruby -U と同じ. + -E enc ruby -E と同じ. + -w ruby -w と同じ. + -W[level=2] ruby -W と同じ. + --context-mode n 新しいワークスペースを作成した時に関連する Binding + オブジェクトの作成方法を 0 から 3 のいずれかに設定する. + --echo 実行結果を表示する(デフォルト). + --noecho 実行結果を表示しない. + --inspect 結果出力にinspectを用いる(bcモード以外はデフォルト). + --noinspect 結果出力にinspectを用いない. + --readline readlineライブラリを利用する. + --noreadline readlineライブラリを利用しない. + --prompt prompt-mode/--prompt-mode prompt-mode + プロンプトモードを切替えます. 現在定義されているプ + ロンプトモードは, default, simple, xmp, inf-rubyが + 用意されています. + --inf-ruby-mode emacsのinf-ruby-mode用のプロンプト表示を行なう. 特 + に指定がない限り, readlineライブラリは使わなくなる. + --sample-book-mode/--simple-prompt + 非常にシンプルなプロンプトを用いるモードです. + --noprompt プロンプト表示を行なわない. + --single-irb irb 中で self を実行して得られるオブジェクトをサ + ブ irb と共有する. + --tracer コマンド実行時にトレースを行なう. + --back-trace-limit n + バックトレース表示をバックトレースの頭から n, 後ろ + からnだけ行なう. デフォルトは16 + + --irb_debug n irbのデバッグレベルをnに設定する(非推奨). + + --verbose 詳細なメッセージを出力する. + --noverbose 詳細なメッセージを出力しない(デフォルト). + -v, --version irbのバージョンを表示する. + -h, --help irb のヘルプを表示する. + -- 以降のコマンドライン引数をオプションとして扱わない. + +# vim:fileencoding=utf-8 diff --git a/jni/ruby/lib/irb/locale.rb b/jni/ruby/lib/irb/locale.rb new file mode 100644 index 0000000..f3bd2d7 --- /dev/null +++ b/jni/ruby/lib/irb/locale.rb @@ -0,0 +1,181 @@ +# +# irb/locale.rb - internationalization module +# $Release Version: 0.9.6$ +# $Revision: 47266 $ +# by Keiju ISHITSUKA(keiju@ruby-lang.org) +# +# -- +# +# +# +module IRB # :nodoc: + class Locale + + LOCALE_NAME_RE = %r[ + (?[[:alpha:]]{2,3}) + (?:_ (?[[:alpha:]]{2,3}) )? + (?:\. (?[^@]+) )? + (?:@ (?.*) )? + ]x + LOCALE_DIR = "/lc/" + + @@legacy_encoding_alias_map = {}.freeze + + def initialize(locale = nil) + @lang = @territory = @encoding_name = @modifier = nil + @locale = locale || ENV["IRB_LANG"] || ENV["LC_MESSAGES"] || ENV["LC_ALL"] || ENV["LANG"] || "C" + if m = LOCALE_NAME_RE.match(@locale) + @lang, @territory, @encoding_name, @modifier = m[:language], m[:territory], m[:codeset], m[:modifier] + + if @encoding_name + begin load 'irb/encoding_aliases.rb'; rescue LoadError; end + if @encoding = @@legacy_encoding_alias_map[@encoding_name] + warn "%s is obsolete. use %s" % ["#{@lang}_#{@territory}.#{@encoding_name}", "#{@lang}_#{@territory}.#{@encoding.name}"] + end + @encoding = Encoding.find(@encoding_name) rescue nil + end + end + @encoding ||= (Encoding.find('locale') rescue Encoding::ASCII_8BIT) + end + + attr_reader :lang, :territory, :encoding, :modifier + + def String(mes) + mes = super(mes) + if @encoding + mes.encode(@encoding, undef: :replace) + else + mes + end + end + + def format(*opts) + String(super(*opts)) + end + + def gets(*rs) + String(super(*rs)) + end + + def readline(*rs) + String(super(*rs)) + end + + def print(*opts) + ary = opts.collect{|opt| String(opt)} + super(*ary) + end + + def printf(*opts) + s = format(*opts) + print s + end + + def puts(*opts) + ary = opts.collect{|opt| String(opt)} + super(*ary) + end + + def require(file, priv = nil) + rex = Regexp.new("lc/#{Regexp.quote(file)}\.(so|o|sl|rb)?") + return false if $".find{|f| f =~ rex} + + case file + when /\.rb$/ + begin + load(file, priv) + $".push file + return true + rescue LoadError + end + when /\.(so|o|sl)$/ + return super + end + + begin + load(f = file + ".rb") + $".push f #" + return true + rescue LoadError + return ruby_require(file) + end + end + + alias toplevel_load load + + def load(file, priv=nil) + found = find(file) + if found + return real_load(found, priv) + else + raise LoadError, "No such file to load -- #{file}" + end + end + + def find(file , paths = $:) + dir = File.dirname(file) + dir = "" if dir == "." + base = File.basename(file) + + if dir.start_with?('/') + return each_localized_path(dir, base).find{|full_path| File.readable? full_path} + else + return search_file(paths, dir, base) + end + end + + private + def real_load(path, priv) + src = MagicFile.open(path){|f| f.read} + if priv + eval("self", TOPLEVEL_BINDING).extend(Module.new {eval(src, nil, path)}) + else + eval(src, TOPLEVEL_BINDING, path) + end + end + + # @param paths load paths in which IRB find a localized file. + # @param dir directory + # @param file basename to be localized + # + # typically, for the parameters and a in paths, it searches + # /// + def search_file(lib_paths, dir, file) + each_localized_path(dir, file) do |lc_path| + lib_paths.each do |libpath| + full_path = File.join(libpath, lc_path) + return full_path if File.readable?(full_path) + end + redo if defined?(Gem) and Gem.try_activate(lc_path) + end + nil + end + + def each_localized_path(dir, file) + return enum_for(:each_localized_path) unless block_given? + each_sublocale do |lc| + yield lc.nil? ? File.join(dir, LOCALE_DIR, file) : File.join(dir, LOCALE_DIR, lc, file) + end + end + + def each_sublocale + if @lang + if @territory + if @encoding_name + yield "#{@lang}_#{@territory}.#{@encoding_name}@#{@modifier}" if @modifier + yield "#{@lang}_#{@territory}.#{@encoding_name}" + end + yield "#{@lang}_#{@territory}@#{@modifier}" if @modifier + yield "#{@lang}_#{@territory}" + end + if @encoding_name + yield "#{@lang}.#{@encoding_name}@#{@modifier}" if @modifier + yield "#{@lang}.#{@encoding_name}" + end + yield "#{@lang}@#{@modifier}" if @modifier + yield "#{@lang}" + end + yield nil + end + end +end diff --git a/jni/ruby/lib/irb/magic-file.rb b/jni/ruby/lib/irb/magic-file.rb new file mode 100644 index 0000000..339ed60 --- /dev/null +++ b/jni/ruby/lib/irb/magic-file.rb @@ -0,0 +1,37 @@ +module IRB + class << (MagicFile = Object.new) + # see parser_magic_comment in parse.y + ENCODING_SPEC_RE = %r"coding\s*[=:]\s*([[:alnum:]\-_]+)" + + def open(path) + io = File.open(path, 'rb') + line = io.gets + line = io.gets if line[0,2] == "#!" + encoding = detect_encoding(line) + internal_encoding = encoding + encoding ||= default_src_encoding + io.rewind + io.set_encoding(encoding, internal_encoding) + + if block_given? + begin + return (yield io) + ensure + io.close + end + else + return io + end + end + + private + def detect_encoding(line) + return unless line[0] == ?# + line = line[1..-1] + line = $1 if line[/-\*-\s*(.*?)\s*-*-$/] + return nil unless ENCODING_SPEC_RE =~ line + encoding = $1 + return encoding.sub(/-(?:mac|dos|unix)/i, '') + end + end +end diff --git a/jni/ruby/lib/irb/notifier.rb b/jni/ruby/lib/irb/notifier.rb new file mode 100644 index 0000000..b08d201 --- /dev/null +++ b/jni/ruby/lib/irb/notifier.rb @@ -0,0 +1,231 @@ +# +# notifier.rb - output methods used by irb +# $Release Version: 0.9.6$ +# $Revision: 47112 $ +# by Keiju ISHITSUKA(keiju@ruby-lang.org) +# +# -- +# +# +# + +require "e2mmap" +require "irb/output-method" + +module IRB + # An output formatter used internally by the lexer. + module Notifier + extend Exception2MessageMapper + def_exception :ErrUndefinedNotifier, + "undefined notifier level: %d is specified" + def_exception :ErrUnrecognizedLevel, + "unrecognized notifier level: %s is specified" + + # Define a new Notifier output source, returning a new CompositeNotifier + # with the given +prefix+ and +output_method+. + # + # The optional +prefix+ will be appended to all objects being inspected + # during output, using the given +output_method+ as the output source. If + # no +output_method+ is given, StdioOutputMethod will be used, and all + # expressions will be sent directly to STDOUT without any additional + # formatting. + def def_notifier(prefix = "", output_method = StdioOutputMethod.new) + CompositeNotifier.new(prefix, output_method) + end + module_function :def_notifier + + # An abstract class, or superclass, for CompositeNotifier and + # LeveledNotifier to inherit. It provides several wrapper methods for the + # OutputMethod object used by the Notifier. + class AbstractNotifier + # Creates a new Notifier object + def initialize(prefix, base_notifier) + @prefix = prefix + @base_notifier = base_notifier + end + + # The +prefix+ for this Notifier, which is appended to all objects being + # inspected during output. + attr_reader :prefix + + # A wrapper method used to determine whether notifications are enabled. + # + # Defaults to +true+. + def notify? + true + end + + # See OutputMethod#print for more detail. + def print(*opts) + @base_notifier.print prefix, *opts if notify? + end + + # See OutputMethod#printn for more detail. + def printn(*opts) + @base_notifier.printn prefix, *opts if notify? + end + + # See OutputMethod#printf for more detail. + def printf(format, *opts) + @base_notifier.printf(prefix + format, *opts) if notify? + end + + # See OutputMethod#puts for more detail. + def puts(*objs) + if notify? + @base_notifier.puts(*objs.collect{|obj| prefix + obj.to_s}) + end + end + + # Same as #ppx, except it uses the #prefix given during object + # initialization. + # See OutputMethod#ppx for more detail. + def pp(*objs) + if notify? + @base_notifier.ppx @prefix, *objs + end + end + + # Same as #pp, except it concatenates the given +prefix+ with the #prefix + # given during object initialization. + # + # See OutputMethod#ppx for more detail. + def ppx(prefix, *objs) + if notify? + @base_notifier.ppx @prefix+prefix, *objs + end + end + + # Execute the given block if notifications are enabled. + def exec_if + yield(@base_notifier) if notify? + end + end + + # A class that can be used to create a group of notifier objects with the + # intent of representing a leveled notification system for irb. + # + # This class will allow you to generate other notifiers, and assign them + # the appropriate level for output. + # + # The Notifier class provides a class-method Notifier.def_notifier to + # create a new composite notifier. Using the first composite notifier + # object you create, sibling notifiers can be initialized with + # #def_notifier. + class CompositeNotifier(other) + @level <=> other.level + end + + # Whether to output messages to the output method, depending on the level + # of this notifier object. + def notify? + @base_notifier.level >= self + end + end + + # NoMsgNotifier is a LeveledNotifier that's used as the default notifier + # when creating a new CompositeNotifier. + # + # This notifier is used as the +zero+ index, or level +0+, for + # CompositeNotifier#notifiers, and will not output messages of any sort. + class NoMsgNotifier [#0- +] + # (\*|\*[1-9][0-9]*\$|[1-9][0-9]*) + # .(\*|\*[1-9][0-9]*\$|[1-9][0-9]*|)? + # #(hh|h|l|ll|L|q|j|z|t) + # [diouxXeEfgGcsb%] + def parse_printf_format(format, opts) + return format, opts if $1.size % 2 == 1 + end + + # Calls #print on each element in the given +objs+, followed by a newline + # character. + def puts(*objs) + for obj in objs + print(*obj) + print "\n" + end + end + + # Prints the given +objs+ calling Object#inspect on each. + # + # See #puts for more detail. + def pp(*objs) + puts(*objs.collect{|obj| obj.inspect}) + end + + # Prints the given +objs+ calling Object#inspect on each and appending the + # given +prefix+. + # + # See #puts for more detail. + def ppx(prefix, *objs) + puts(*objs.collect{|obj| prefix+obj.inspect}) + end + + end + + # A standard output printer + class StdioOutputMethod 0 + end + end + @debug_level = 0 + + def initialize + lex_init + set_input(STDIN) + + @seek = 0 + @exp_line_no = @line_no = 1 + @base_char_no = 0 + @char_no = 0 + @rests = [] + @readed = [] + @here_readed = [] + + @indent = 0 + @indent_stack = [] + @lex_state = EXPR_BEG + @space_seen = false + @here_header = false + @post_symbeg = false + + @continue = false + @line = "" + + @skip_space = false + @readed_auto_clean_up = false + @exception_on_syntax_error = true + + @prompt = nil + end + + attr_accessor :skip_space + attr_accessor :readed_auto_clean_up + attr_accessor :exception_on_syntax_error + + attr_reader :seek + attr_reader :char_no + attr_reader :line_no + attr_reader :indent + + # io functions + def set_input(io, p = nil, &block) + @io = io + if p.respond_to?(:call) + @input = p + elsif block_given? + @input = block + else + @input = Proc.new{@io.gets} + end + end + + def get_readed + if idx = @readed.rindex("\n") + @base_char_no = @readed.size - (idx + 1) + else + @base_char_no += @readed.size + end + + readed = @readed.join("") + @readed = [] + readed + end + + def getc + while @rests.empty? + @rests.push nil unless buf_input + end + c = @rests.shift + if @here_header + @here_readed.push c + else + @readed.push c + end + @seek += 1 + if c == "\n" + @line_no += 1 + @char_no = 0 + else + @char_no += 1 + end + c + end + + def gets + l = "" + while c = getc + l.concat(c) + break if c == "\n" + end + return nil if l == "" and c.nil? + l + end + + def eof? + @io.eof? + end + + def getc_of_rests + if @rests.empty? + nil + else + getc + end + end + + def ungetc(c = nil) + if @here_readed.empty? + c2 = @readed.pop + else + c2 = @here_readed.pop + end + c = c2 unless c + @rests.unshift c #c = + @seek -= 1 + if c == "\n" + @line_no -= 1 + if idx = @readed.rindex("\n") + @char_no = idx + 1 + else + @char_no = @base_char_no + @readed.size + end + else + @char_no -= 1 + end + end + + def peek_equal?(str) + chrs = str.split(//) + until @rests.size >= chrs.size + return false unless buf_input + end + @rests[0, chrs.size] == chrs + end + + def peek_match?(regexp) + while @rests.empty? + return false unless buf_input + end + regexp =~ @rests.join("") + end + + def peek(i = 0) + while @rests.size <= i + return nil unless buf_input + end + @rests[i] + end + + def buf_input + prompt + line = @input.call + return nil unless line + @rests.concat line.chars.to_a + true + end + private :buf_input + + def set_prompt(p = nil, &block) + p = block if block_given? + if p.respond_to?(:call) + @prompt = p + else + @prompt = Proc.new{print p} + end + end + + def prompt + if @prompt + @prompt.call(@ltype, @indent, @continue, @line_no) + end + end + + def initialize_input + @ltype = nil + @quoted = nil + @indent = 0 + @indent_stack = [] + @lex_state = EXPR_BEG + @space_seen = false + @here_header = false + + @continue = false + @post_symbeg = false + + prompt + + @line = "" + @exp_line_no = @line_no + end + + def each_top_level_statement + initialize_input + catch(:TERM_INPUT) do + loop do + begin + @continue = false + prompt + unless l = lex + throw :TERM_INPUT if @line == '' + else + @line.concat l + if @ltype or @continue or @indent > 0 + next + end + end + if @line != "\n" + @line.force_encoding(@io.encoding) + yield @line, @exp_line_no + end + break unless l + @line = '' + @exp_line_no = @line_no + + @indent = 0 + @indent_stack = [] + prompt + rescue TerminateLineInput + initialize_input + prompt + get_readed + end + end + end + end + + def lex + until (((tk = token).kind_of?(TkNL) || tk.kind_of?(TkEND_OF_SCRIPT)) && + !@continue or + tk.nil?) + end + line = get_readed + if line == "" and tk.kind_of?(TkEND_OF_SCRIPT) || tk.nil? + nil + else + line + end + end + + def token + @prev_seek = @seek + @prev_line_no = @line_no + @prev_char_no = @char_no + begin + begin + tk = @OP.match(self) + @space_seen = tk.kind_of?(TkSPACE) + @lex_state = EXPR_END if @post_symbeg && tk.kind_of?(TkOp) + @post_symbeg = tk.kind_of?(TkSYMBEG) + rescue SyntaxError + raise if @exception_on_syntax_error + tk = TkError.new(@seek, @line_no, @char_no) + end + end while @skip_space and tk.kind_of?(TkSPACE) + if @readed_auto_clean_up + get_readed + end + tk + end + + ENINDENT_CLAUSE = [ + "case", "class", "def", "do", "for", "if", + "module", "unless", "until", "while", "begin" + ] + DEINDENT_CLAUSE = ["end" + ] + + PERCENT_LTYPE = { + "q" => "\'", + "Q" => "\"", + "x" => "\`", + "r" => "/", + "w" => "]", + "W" => "]", + "i" => "]", + "I" => "]", + "s" => ":" + } + + PERCENT_PAREN = { + "{" => "}", + "[" => "]", + "<" => ">", + "(" => ")" + } + + Ltype2Token = { + "\'" => TkSTRING, + "\"" => TkSTRING, + "\`" => TkXSTRING, + "/" => TkREGEXP, + "]" => TkDSTRING, + ":" => TkSYMBOL + } + DLtype2Token = { + "\"" => TkDSTRING, + "\`" => TkDXSTRING, + "/" => TkDREGEXP, + } + + def lex_init() + @OP = IRB::SLex.new + @OP.def_rules("\0", "\004", "\032") do |op, io| + Token(TkEND_OF_SCRIPT) + end + + @OP.def_rules(" ", "\t", "\f", "\r", "\13") do |op, io| + @space_seen = true + while getc =~ /[ \t\f\r\13]/; end + ungetc + Token(TkSPACE) + end + + @OP.def_rule("#") do |op, io| + identify_comment + end + + @OP.def_rule("=begin", + proc{|op, io| @prev_char_no == 0 && peek(0) =~ /\s/}) do + |op, io| + @ltype = "=" + until getc == "\n"; end + until peek_equal?("=end") && peek(4) =~ /\s/ + until getc == "\n"; end + end + gets + @ltype = nil + Token(TkRD_COMMENT) + end + + @OP.def_rule("\n") do |op, io| + print "\\n\n" if RubyLex.debug? + case @lex_state + when EXPR_BEG, EXPR_FNAME, EXPR_DOT + @continue = true + else + @continue = false + @lex_state = EXPR_BEG + until (@indent_stack.empty? || + [TkLPAREN, TkLBRACK, TkLBRACE, + TkfLPAREN, TkfLBRACK, TkfLBRACE].include?(@indent_stack.last)) + @indent_stack.pop + end + end + @here_header = false + @here_readed = [] + Token(TkNL) + end + + @OP.def_rules("*", "**", + "=", "==", "===", + "=~", "<=>", + "<", "<=", + ">", ">=", ">>", + "!", "!=", "!~") do + |op, io| + case @lex_state + when EXPR_FNAME, EXPR_DOT + @lex_state = EXPR_ARG + else + @lex_state = EXPR_BEG + end + Token(op) + end + + @OP.def_rules("<<") do + |op, io| + tk = nil + if @lex_state != EXPR_END && @lex_state != EXPR_CLASS && + (@lex_state != EXPR_ARG || @space_seen) + c = peek(0) + if /\S/ =~ c && (/["'`]/ =~ c || /\w/ =~ c || c == "-") + tk = identify_here_document + end + end + unless tk + tk = Token(op) + case @lex_state + when EXPR_FNAME, EXPR_DOT + @lex_state = EXPR_ARG + else + @lex_state = EXPR_BEG + end + end + tk + end + + @OP.def_rules("'", '"') do + |op, io| + identify_string(op) + end + + @OP.def_rules("`") do + |op, io| + if @lex_state == EXPR_FNAME + @lex_state = EXPR_END + Token(op) + else + identify_string(op) + end + end + + @OP.def_rules('?') do + |op, io| + if @lex_state == EXPR_END + @lex_state = EXPR_BEG + Token(TkQUESTION) + else + ch = getc + if @lex_state == EXPR_ARG && ch =~ /\s/ + ungetc + @lex_state = EXPR_BEG; + Token(TkQUESTION) + else + if (ch == '\\') + read_escape + end + @lex_state = EXPR_END + Token(TkINTEGER) + end + end + end + + @OP.def_rules("&", "&&", "|", "||") do + |op, io| + @lex_state = EXPR_BEG + Token(op) + end + + @OP.def_rules("+=", "-=", "*=", "**=", + "&=", "|=", "^=", "<<=", ">>=", "||=", "&&=") do + |op, io| + @lex_state = EXPR_BEG + op =~ /^(.*)=$/ + Token(TkOPASGN, $1) + end + + @OP.def_rule("+@", proc{|op, io| @lex_state == EXPR_FNAME}) do + |op, io| + @lex_state = EXPR_ARG + Token(op) + end + + @OP.def_rule("-@", proc{|op, io| @lex_state == EXPR_FNAME}) do + |op, io| + @lex_state = EXPR_ARG + Token(op) + end + + @OP.def_rules("+", "-") do + |op, io| + catch(:RET) do + if @lex_state == EXPR_ARG + if @space_seen and peek(0) =~ /[0-9]/ + throw :RET, identify_number + else + @lex_state = EXPR_BEG + end + elsif @lex_state != EXPR_END and peek(0) =~ /[0-9]/ + throw :RET, identify_number + else + @lex_state = EXPR_BEG + end + Token(op) + end + end + + @OP.def_rule(".") do + |op, io| + @lex_state = EXPR_BEG + if peek(0) =~ /[0-9]/ + ungetc + identify_number + else + # for "obj.if" etc. + @lex_state = EXPR_DOT + Token(TkDOT) + end + end + + @OP.def_rules("..", "...") do + |op, io| + @lex_state = EXPR_BEG + Token(op) + end + + lex_int2 + end + + def lex_int2 + @OP.def_rules("]", "}", ")") do + |op, io| + @lex_state = EXPR_END + @indent -= 1 + @indent_stack.pop + Token(op) + end + + @OP.def_rule(":") do + |op, io| + if @lex_state == EXPR_END || peek(0) =~ /\s/ + @lex_state = EXPR_BEG + Token(TkCOLON) + else + @lex_state = EXPR_FNAME + Token(TkSYMBEG) + end + end + + @OP.def_rule("::") do + |op, io| + if @lex_state == EXPR_BEG or @lex_state == EXPR_ARG && @space_seen + @lex_state = EXPR_BEG + Token(TkCOLON3) + else + @lex_state = EXPR_DOT + Token(TkCOLON2) + end + end + + @OP.def_rule("/") do + |op, io| + if @lex_state == EXPR_BEG || @lex_state == EXPR_MID + identify_string(op) + elsif peek(0) == '=' + getc + @lex_state = EXPR_BEG + Token(TkOPASGN, "/") #/) + elsif @lex_state == EXPR_ARG and @space_seen and peek(0) !~ /\s/ + identify_string(op) + else + @lex_state = EXPR_BEG + Token("/") #/) + end + end + + @OP.def_rules("^") do + |op, io| + @lex_state = EXPR_BEG + Token("^") + end + + @OP.def_rules(",") do + |op, io| + @lex_state = EXPR_BEG + Token(op) + end + + @OP.def_rules(";") do + |op, io| + @lex_state = EXPR_BEG + until (@indent_stack.empty? || + [TkLPAREN, TkLBRACK, TkLBRACE, + TkfLPAREN, TkfLBRACK, TkfLBRACE].include?(@indent_stack.last)) + @indent_stack.pop + end + Token(op) + end + + @OP.def_rule("~") do + |op, io| + @lex_state = EXPR_BEG + Token("~") + end + + @OP.def_rule("~@", proc{|op, io| @lex_state == EXPR_FNAME}) do + |op, io| + @lex_state = EXPR_BEG + Token("~") + end + + @OP.def_rule("(") do + |op, io| + @indent += 1 + if @lex_state == EXPR_BEG || @lex_state == EXPR_MID + @lex_state = EXPR_BEG + tk_c = TkfLPAREN + else + @lex_state = EXPR_BEG + tk_c = TkLPAREN + end + @indent_stack.push tk_c + Token(tk_c) + end + + @OP.def_rule("[]", proc{|op, io| @lex_state == EXPR_FNAME}) do + |op, io| + @lex_state = EXPR_ARG + Token("[]") + end + + @OP.def_rule("[]=", proc{|op, io| @lex_state == EXPR_FNAME}) do + |op, io| + @lex_state = EXPR_ARG + Token("[]=") + end + + @OP.def_rule("[") do + |op, io| + @indent += 1 + if @lex_state == EXPR_FNAME + tk_c = TkfLBRACK + else + if @lex_state == EXPR_BEG || @lex_state == EXPR_MID + tk_c = TkLBRACK + elsif @lex_state == EXPR_ARG && @space_seen + tk_c = TkLBRACK + else + tk_c = TkfLBRACK + end + @lex_state = EXPR_BEG + end + @indent_stack.push tk_c + Token(tk_c) + end + + @OP.def_rule("{") do + |op, io| + @indent += 1 + if @lex_state != EXPR_END && @lex_state != EXPR_ARG + tk_c = TkLBRACE + else + tk_c = TkfLBRACE + end + @lex_state = EXPR_BEG + @indent_stack.push tk_c + Token(tk_c) + end + + @OP.def_rule('\\') do + |op, io| + if getc == "\n" + @space_seen = true + @continue = true + Token(TkSPACE) + else + read_escape + Token("\\") + end + end + + @OP.def_rule('%') do + |op, io| + if @lex_state == EXPR_BEG || @lex_state == EXPR_MID + identify_quotation + elsif peek(0) == '=' + getc + Token(TkOPASGN, :%) + elsif @lex_state == EXPR_ARG and @space_seen and peek(0) !~ /\s/ + identify_quotation + else + @lex_state = EXPR_BEG + Token("%") #)) + end + end + + @OP.def_rule('$') do + |op, io| + identify_gvar + end + + @OP.def_rule('@') do + |op, io| + if peek(0) =~ /[\w@]/ + ungetc + identify_identifier + else + Token("@") + end + end + + @OP.def_rule("") do + |op, io| + printf "MATCH: start %s: %s\n", op, io.inspect if RubyLex.debug? + if peek(0) =~ /[0-9]/ + t = identify_number + elsif peek(0) =~ /[^\x00-\/:-@\[-^`{-\x7F]/ + t = identify_identifier + end + printf "MATCH: end %s: %s\n", op, io.inspect if RubyLex.debug? + t + end + + p @OP if RubyLex.debug? + end + + def identify_gvar + @lex_state = EXPR_END + + case ch = getc + when /[~_*$?!@\/\\;,=:<>".]/ #" + Token(TkGVAR, "$" + ch) + when "-" + Token(TkGVAR, "$-" + getc) + when "&", "`", "'", "+" + Token(TkBACK_REF, "$"+ch) + when /[1-9]/ + while getc =~ /[0-9]/; end + ungetc + Token(TkNTH_REF) + when /\w/ + ungetc + ungetc + identify_identifier + else + ungetc + Token("$") + end + end + + def identify_identifier + token = "" + if peek(0) =~ /[$@]/ + token.concat(c = getc) + if c == "@" and peek(0) == "@" + token.concat getc + end + end + + while (ch = getc) =~ /[^\x00-\/:-@\[-^`{-\x7F]/ + print ":", ch, ":" if RubyLex.debug? + token.concat ch + end + ungetc + + if (ch == "!" || ch == "?") && token[0,1] =~ /\w/ && peek(0) != "=" + token.concat getc + end + + # almost fix token + + case token + when /^\$/ + return Token(TkGVAR, token) + when /^\@\@/ + @lex_state = EXPR_END + # p Token(TkCVAR, token) + return Token(TkCVAR, token) + when /^\@/ + @lex_state = EXPR_END + return Token(TkIVAR, token) + end + + if @lex_state != EXPR_DOT + print token, "\n" if RubyLex.debug? + + token_c, *trans = TkReading2Token[token] + if token_c + # reserved word? + + if (@lex_state != EXPR_BEG && + @lex_state != EXPR_FNAME && + trans[1]) + # modifiers + token_c = TkSymbol2Token[trans[1]] + @lex_state = trans[0] + else + if @lex_state != EXPR_FNAME + if ENINDENT_CLAUSE.include?(token) + # check for ``class = val'' etc. + valid = true + case token + when "class" + valid = false unless peek_match?(/^\s*(<<|\w|::)/) + when "def" + valid = false if peek_match?(/^\s*(([+\-\/*&\|^]|<<|>>|\|\||\&\&)=|\&\&|\|\|)/) + when "do" + valid = false if peek_match?(/^\s*([+\-\/*]?=|\*|<|>|\&)/) + when *ENINDENT_CLAUSE + valid = false if peek_match?(/^\s*([+\-\/*]?=|\*|<|>|\&|\|)/) + else + # no nothing + end + if valid + if token == "do" + if ![TkFOR, TkWHILE, TkUNTIL].include?(@indent_stack.last) + @indent += 1 + @indent_stack.push token_c + end + else + @indent += 1 + @indent_stack.push token_c + end + end + + elsif DEINDENT_CLAUSE.include?(token) + @indent -= 1 + @indent_stack.pop + end + @lex_state = trans[0] + else + @lex_state = EXPR_END + end + end + return Token(token_c, token) + end + end + + if @lex_state == EXPR_FNAME + @lex_state = EXPR_END + if peek(0) == '=' + token.concat getc + end + elsif @lex_state == EXPR_BEG || @lex_state == EXPR_DOT + @lex_state = EXPR_ARG + else + @lex_state = EXPR_END + end + + if token[0, 1] =~ /[A-Z]/ + return Token(TkCONSTANT, token) + elsif token[token.size - 1, 1] =~ /[!?]/ + return Token(TkFID, token) + else + return Token(TkIDENTIFIER, token) + end + end + + def identify_here_document + ch = getc + if ch == "-" + ch = getc + indent = true + end + if /['"`]/ =~ ch + lt = ch + quoted = "" + while (c = getc) && c != lt + quoted.concat c + end + else + lt = '"' + quoted = ch.dup + while (c = getc) && c =~ /\w/ + quoted.concat c + end + ungetc + end + + ltback, @ltype = @ltype, lt + reserve = [] + while ch = getc + reserve.push ch + if ch == "\\" + reserve.push ch = getc + elsif ch == "\n" + break + end + end + + @here_header = false + + line = "" + while ch = getc + if ch == "\n" + if line == quoted + break + end + line = "" + else + line.concat ch unless indent && line == "" && /\s/ =~ ch + if @ltype != "'" && ch == "#" && peek(0) == "{" + identify_string_dvar + end + end + end + + @here_header = true + @here_readed.concat reserve + while ch = reserve.pop + ungetc ch + end + + @ltype = ltback + @lex_state = EXPR_END + Token(Ltype2Token[lt]) + end + + def identify_quotation + ch = getc + if lt = PERCENT_LTYPE[ch] + ch = getc + elsif ch =~ /\W/ + lt = "\"" + else + RubyLex.fail SyntaxError, "unknown type of %string" + end + @quoted = ch unless @quoted = PERCENT_PAREN[ch] + identify_string(lt, @quoted) + end + + def identify_number + @lex_state = EXPR_END + + if peek(0) == "0" && peek(1) !~ /[.eE]/ + getc + case peek(0) + when /[xX]/ + ch = getc + match = /[0-9a-fA-F_]/ + when /[bB]/ + ch = getc + match = /[01_]/ + when /[oO]/ + ch = getc + match = /[0-7_]/ + when /[dD]/ + ch = getc + match = /[0-9_]/ + when /[0-7]/ + match = /[0-7_]/ + when /[89]/ + RubyLex.fail SyntaxError, "Invalid octal digit" + else + return Token(TkINTEGER) + end + + len0 = true + non_digit = false + while ch = getc + if match =~ ch + if ch == "_" + if non_digit + RubyLex.fail SyntaxError, "trailing `#{ch}' in number" + else + non_digit = ch + end + else + non_digit = false + len0 = false + end + else + ungetc + if len0 + RubyLex.fail SyntaxError, "numeric literal without digits" + end + if non_digit + RubyLex.fail SyntaxError, "trailing `#{non_digit}' in number" + end + break + end + end + return Token(TkINTEGER) + end + + type = TkINTEGER + allow_point = true + allow_e = true + non_digit = false + while ch = getc + case ch + when /[0-9]/ + non_digit = false + when "_" + non_digit = ch + when allow_point && "." + if non_digit + RubyLex.fail SyntaxError, "trailing `#{non_digit}' in number" + end + type = TkFLOAT + if peek(0) !~ /[0-9]/ + type = TkINTEGER + ungetc + break + end + allow_point = false + when allow_e && "e", allow_e && "E" + if non_digit + RubyLex.fail SyntaxError, "trailing `#{non_digit}' in number" + end + type = TkFLOAT + if peek(0) =~ /[+-]/ + getc + end + allow_e = false + allow_point = false + non_digit = ch + else + if non_digit + RubyLex.fail SyntaxError, "trailing `#{non_digit}' in number" + end + ungetc + break + end + end + Token(type) + end + + def identify_string(ltype, quoted = ltype) + @ltype = ltype + @quoted = quoted + subtype = nil + begin + nest = 0 + while ch = getc + if @quoted == ch and nest == 0 + break + elsif @ltype != "'" && ch == "#" && peek(0) == "{" + identify_string_dvar + elsif @ltype != "'" && @ltype != "]" && @ltype != ":" and ch == "#" + subtype = true + elsif ch == '\\' and @ltype == "'" #' + case ch = getc + when "\\", "\n", "'" + else + ungetc + end + elsif ch == '\\' #' + read_escape + end + if PERCENT_PAREN.values.include?(@quoted) + if PERCENT_PAREN[ch] == @quoted + nest += 1 + elsif ch == @quoted + nest -= 1 + end + end + end + if @ltype == "/" + while /[imxoesun]/ =~ peek(0) + getc + end + end + if subtype + Token(DLtype2Token[ltype]) + else + Token(Ltype2Token[ltype]) + end + ensure + @ltype = nil + @quoted = nil + @lex_state = EXPR_END + end + end + + def identify_string_dvar + begin + getc + + reserve_continue = @continue + reserve_ltype = @ltype + reserve_indent = @indent + reserve_indent_stack = @indent_stack + reserve_state = @lex_state + reserve_quoted = @quoted + + @ltype = nil + @quoted = nil + @indent = 0 + @indent_stack = [] + @lex_state = EXPR_BEG + + loop do + @continue = false + prompt + tk = token + if @ltype or @continue or @indent >= 0 + next + end + break if tk.kind_of?(TkRBRACE) + end + ensure + @continue = reserve_continue + @ltype = reserve_ltype + @indent = reserve_indent + @indent_stack = reserve_indent_stack + @lex_state = reserve_state + @quoted = reserve_quoted + end + end + + def identify_comment + @ltype = "#" + + while ch = getc + if ch == "\n" + @ltype = nil + ungetc + break + end + end + return Token(TkCOMMENT) + end + + def read_escape + case ch = getc + when "\n", "\r", "\f" + when "\\", "n", "t", "r", "f", "v", "a", "e", "b", "s" #" + when /[0-7]/ + ungetc ch + 3.times do + case ch = getc + when /[0-7]/ + when nil + break + else + ungetc + break + end + end + + when "x" + 2.times do + case ch = getc + when /[0-9a-fA-F]/ + when nil + break + else + ungetc + break + end + end + + when "M" + if (ch = getc) != '-' + ungetc + else + if (ch = getc) == "\\" #" + read_escape + end + end + + when "C", "c" #, "^" + if ch == "C" and (ch = getc) != "-" + ungetc + elsif (ch = getc) == "\\" #" + read_escape + end + else + # other characters + end + end +end +# :startdoc: diff --git a/jni/ruby/lib/irb/ruby-token.rb b/jni/ruby/lib/irb/ruby-token.rb new file mode 100644 index 0000000..cb95955 --- /dev/null +++ b/jni/ruby/lib/irb/ruby-token.rb @@ -0,0 +1,266 @@ +# +# irb/ruby-token.rb - ruby tokens +# $Release Version: 0.9.6$ +# $Revision: 47298 $ +# by Keiju ISHITSUKA(keiju@ruby-lang.org) +# +# -- +# +# +# +# :stopdoc: +module RubyToken + EXPR_BEG = :EXPR_BEG + EXPR_MID = :EXPR_MID + EXPR_END = :EXPR_END + EXPR_ARG = :EXPR_ARG + EXPR_FNAME = :EXPR_FNAME + EXPR_DOT = :EXPR_DOT + EXPR_CLASS = :EXPR_CLASS + + class Token + def initialize(seek, line_no, char_no) + @seek = seek + @line_no = line_no + @char_no = char_no + end + attr_reader :seek, :line_no, :char_no + end + + class TkNode < Token + def initialize(seek, line_no, char_no) + super + end + attr_reader :node + end + + class TkId < Token + def initialize(seek, line_no, char_no, name) + super(seek, line_no, char_no) + @name = name + end + attr_reader :name + end + + class TkVal < Token + def initialize(seek, line_no, char_no, value = nil) + super(seek, line_no, char_no) + @value = value + end + attr_reader :value + end + + class TkOp < Token + attr_accessor :name + end + + class TkOPASGN < TkOp + def initialize(seek, line_no, char_no, op) + super(seek, line_no, char_no) + op = TkReading2Token[op][0] unless op.kind_of?(Symbol) + @op = op + end + attr_reader :op + end + + class TkUnknownChar < Token + def initialize(seek, line_no, char_no, id) + super(seek, line_no, char_no) + @name = name + end + attr_reader :name + end + + class TkError < Token + end + + def Token(token, value = nil) + case token + when String + if (tk = TkReading2Token[token]).nil? + IRB.fail TkReading2TokenNoKey, token + end + tk = Token(tk[0], value) + if tk.kind_of?(TkOp) + tk.name = token + end + return tk + when Symbol + if (tk = TkSymbol2Token[token]).nil? + IRB.fail TkSymbol2TokenNoKey, token + end + return Token(tk[0], value) + else + if (token.ancestors & [TkId, TkVal, TkOPASGN, TkUnknownChar]).empty? + token.new(@prev_seek, @prev_line_no, @prev_char_no) + else + token.new(@prev_seek, @prev_line_no, @prev_char_no, value) + end + end + end + + TokenDefinitions = [ + [:TkCLASS, TkId, "class", EXPR_CLASS], + [:TkMODULE, TkId, "module", EXPR_BEG], + [:TkDEF, TkId, "def", EXPR_FNAME], + [:TkUNDEF, TkId, "undef", EXPR_FNAME], + [:TkBEGIN, TkId, "begin", EXPR_BEG], + [:TkRESCUE, TkId, "rescue", EXPR_MID], + [:TkENSURE, TkId, "ensure", EXPR_BEG], + [:TkEND, TkId, "end", EXPR_END], + [:TkIF, TkId, "if", EXPR_BEG, :TkIF_MOD], + [:TkUNLESS, TkId, "unless", EXPR_BEG, :TkUNLESS_MOD], + [:TkTHEN, TkId, "then", EXPR_BEG], + [:TkELSIF, TkId, "elsif", EXPR_BEG], + [:TkELSE, TkId, "else", EXPR_BEG], + [:TkCASE, TkId, "case", EXPR_BEG], + [:TkWHEN, TkId, "when", EXPR_BEG], + [:TkWHILE, TkId, "while", EXPR_BEG, :TkWHILE_MOD], + [:TkUNTIL, TkId, "until", EXPR_BEG, :TkUNTIL_MOD], + [:TkFOR, TkId, "for", EXPR_BEG], + [:TkBREAK, TkId, "break", EXPR_END], + [:TkNEXT, TkId, "next", EXPR_END], + [:TkREDO, TkId, "redo", EXPR_END], + [:TkRETRY, TkId, "retry", EXPR_END], + [:TkIN, TkId, "in", EXPR_BEG], + [:TkDO, TkId, "do", EXPR_BEG], + [:TkRETURN, TkId, "return", EXPR_MID], + [:TkYIELD, TkId, "yield", EXPR_END], + [:TkSUPER, TkId, "super", EXPR_END], + [:TkSELF, TkId, "self", EXPR_END], + [:TkNIL, TkId, "nil", EXPR_END], + [:TkTRUE, TkId, "true", EXPR_END], + [:TkFALSE, TkId, "false", EXPR_END], + [:TkAND, TkId, "and", EXPR_BEG], + [:TkOR, TkId, "or", EXPR_BEG], + [:TkNOT, TkId, "not", EXPR_BEG], + [:TkIF_MOD, TkId], + [:TkUNLESS_MOD, TkId], + [:TkWHILE_MOD, TkId], + [:TkUNTIL_MOD, TkId], + [:TkALIAS, TkId, "alias", EXPR_FNAME], + [:TkDEFINED, TkId, "defined?", EXPR_END], + [:TklBEGIN, TkId, "BEGIN", EXPR_END], + [:TklEND, TkId, "END", EXPR_END], + [:Tk__LINE__, TkId, "__LINE__", EXPR_END], + [:Tk__FILE__, TkId, "__FILE__", EXPR_END], + + [:TkIDENTIFIER, TkId], + [:TkFID, TkId], + [:TkGVAR, TkId], + [:TkCVAR, TkId], + [:TkIVAR, TkId], + [:TkCONSTANT, TkId], + + [:TkINTEGER, TkVal], + [:TkFLOAT, TkVal], + [:TkSTRING, TkVal], + [:TkXSTRING, TkVal], + [:TkREGEXP, TkVal], + [:TkSYMBOL, TkVal], + + [:TkDSTRING, TkNode], + [:TkDXSTRING, TkNode], + [:TkDREGEXP, TkNode], + [:TkNTH_REF, TkNode], + [:TkBACK_REF, TkNode], + + [:TkUPLUS, TkOp, "+@"], + [:TkUMINUS, TkOp, "-@"], + [:TkPOW, TkOp, "**"], + [:TkCMP, TkOp, "<=>"], + [:TkEQ, TkOp, "=="], + [:TkEQQ, TkOp, "==="], + [:TkNEQ, TkOp, "!="], + [:TkGEQ, TkOp, ">="], + [:TkLEQ, TkOp, "<="], + [:TkANDOP, TkOp, "&&"], + [:TkOROP, TkOp, "||"], + [:TkMATCH, TkOp, "=~"], + [:TkNMATCH, TkOp, "!~"], + [:TkDOT2, TkOp, ".."], + [:TkDOT3, TkOp, "..."], + [:TkAREF, TkOp, "[]"], + [:TkASET, TkOp, "[]="], + [:TkLSHFT, TkOp, "<<"], + [:TkRSHFT, TkOp, ">>"], + [:TkCOLON2, TkOp], + [:TkCOLON3, TkOp], + [:TkASSOC, TkOp, "=>"], + [:TkQUESTION, TkOp, "?"], #? + [:TkCOLON, TkOp, ":"], #: + + [:TkfLPAREN], # func( # + [:TkfLBRACK], # func[ # + [:TkfLBRACE], # func{ # + [:TkSTAR], # *arg + [:TkAMPER], # &arg # + [:TkSYMBEG], # :SYMBOL + + [:TkGT, TkOp, ">"], + [:TkLT, TkOp, "<"], + [:TkPLUS, TkOp, "+"], + [:TkMINUS, TkOp, "-"], + [:TkMULT, TkOp, "*"], + [:TkDIV, TkOp, "/"], + [:TkMOD, TkOp, "%"], + [:TkBITOR, TkOp, "|"], + [:TkBITXOR, TkOp, "^"], + [:TkBITAND, TkOp, "&"], + [:TkBITNOT, TkOp, "~"], + [:TkNOTOP, TkOp, "!"], + + [:TkBACKQUOTE, TkOp, "`"], + + [:TkASSIGN, Token, "="], + [:TkDOT, Token, "."], + [:TkLPAREN, Token, "("], #(exp) + [:TkLBRACK, Token, "["], #[arry] + [:TkLBRACE, Token, "{"], #{hash} + [:TkRPAREN, Token, ")"], + [:TkRBRACK, Token, "]"], + [:TkRBRACE, Token, "}"], + [:TkCOMMA, Token, ","], + [:TkSEMICOLON, Token, ";"], + + [:TkCOMMENT], + [:TkRD_COMMENT], + [:TkSPACE], + [:TkNL], + [:TkEND_OF_SCRIPT], + + [:TkBACKSLASH, TkUnknownChar, "\\"], + [:TkAT, TkUnknownChar, "@"], + [:TkDOLLAR, TkUnknownChar, "$"], + ] + + # {reading => token_class} + # {reading => [token_class, *opt]} + TkReading2Token = {} + TkSymbol2Token = {} + + def RubyToken.def_token(token_n, super_token = Token, reading = nil, *opts) + token_n = token_n.id2name if token_n.kind_of?(Symbol) + if RubyToken.const_defined?(token_n) + IRB.fail AlreadyDefinedToken, token_n + end + token_c = eval("class #{token_n} < #{super_token}; end; #{token_n}") + + if reading + if TkReading2Token[reading] + IRB.fail TkReading2TokenDuplicateError, token_n, reading + end + if opts.empty? + TkReading2Token[reading] = [token_c] + else + TkReading2Token[reading] = [token_c].concat(opts) + end + end + TkSymbol2Token[token_n.intern] = token_c + end + + for defs in TokenDefinitions + def_token(*defs) + end +end +# :startdoc: diff --git a/jni/ruby/lib/irb/slex.rb b/jni/ruby/lib/irb/slex.rb new file mode 100644 index 0000000..54429cf --- /dev/null +++ b/jni/ruby/lib/irb/slex.rb @@ -0,0 +1,281 @@ +# +# irb/slex.rb - simple lex analyzer +# $Release Version: 0.9.6$ +# $Revision: 47266 $ +# by Keiju ISHITSUKA(keiju@ruby-lang.org) +# +# -- +# +# +# + +require "e2mmap" +require "irb/notifier" + +# :stopdoc: +module IRB + class SLex + + extend Exception2MessageMapper + def_exception :ErrNodeNothing, "node nothing" + def_exception :ErrNodeAlreadyExists, "node already exists" + + DOUT = Notifier::def_notifier("SLex::") + D_WARN = DOUT::def_notifier(1, "Warn: ") + D_DEBUG = DOUT::def_notifier(2, "Debug: ") + D_DETAIL = DOUT::def_notifier(4, "Detail: ") + + DOUT.level = Notifier::D_NOMSG + + def initialize + @head = Node.new("") + end + + def def_rule(token, preproc = nil, postproc = nil, &block) + D_DETAIL.pp token + + postproc = block if block_given? + create(token, preproc, postproc) + end + + def def_rules(*tokens, &block) + if block_given? + p = block + end + for token in tokens + def_rule(token, nil, p) + end + end + + def preproc(token, proc) + node = search(token) + node.preproc=proc + end + + #$BMW%A%'%C%/(B? + def postproc(token) + node = search(token, proc) + node.postproc=proc + end + + def search(token) + @head.search(token.split(//)) + end + + def create(token, preproc = nil, postproc = nil) + @head.create_subnode(token.split(//), preproc, postproc) + end + + def match(token) + case token + when Array + when String + return match(token.split(//)) + else + return @head.match_io(token) + end + ret = @head.match(token) + D_DETAIL.exec_if{D_DETAIL.printf "match end: %s:%s\n", ret, token.inspect} + ret + end + + def inspect + format("", @head.inspect) + end + + #---------------------------------------------------------------------- + # + # class Node - + # + #---------------------------------------------------------------------- + class Node + # if postproc is nil, this node is an abstract node. + # if postproc is non-nil, this node is a real node. + def initialize(preproc = nil, postproc = nil) + @Tree = {} + @preproc = preproc + @postproc = postproc + end + + attr_accessor :preproc + attr_accessor :postproc + + def search(chrs, opt = nil) + return self if chrs.empty? + ch = chrs.shift + if node = @Tree[ch] + node.search(chrs, opt) + else + if opt + chrs.unshift ch + self.create_subnode(chrs) + else + SLex.fail ErrNodeNothing + end + end + end + + def create_subnode(chrs, preproc = nil, postproc = nil) + if chrs.empty? + if @postproc + D_DETAIL.pp node + SLex.fail ErrNodeAlreadyExists + else + D_DEBUG.puts "change abstract node to real node." + @preproc = preproc + @postproc = postproc + end + return self + end + + ch = chrs.shift + if node = @Tree[ch] + if chrs.empty? + if node.postproc + DebugLogger.pp node + DebugLogger.pp self + DebugLogger.pp ch + DebugLogger.pp chrs + SLex.fail ErrNodeAlreadyExists + else + D_WARN.puts "change abstract node to real node" + node.preproc = preproc + node.postproc = postproc + end + else + node.create_subnode(chrs, preproc, postproc) + end + else + if chrs.empty? + node = Node.new(preproc, postproc) + else + node = Node.new + node.create_subnode(chrs, preproc, postproc) + end + @Tree[ch] = node + end + node + end + + # + # chrs: String + # character array + # io must have getc()/ungetc(); and ungetc() must be + # able to be called arbitrary number of times. + # + def match(chrs, op = "") + D_DETAIL.print "match>: ", chrs, "op:", op, "\n" + if chrs.empty? + if @preproc.nil? || @preproc.call(op, chrs) + DOUT.printf(D_DETAIL, "op1: %s\n", op) + @postproc.call(op, chrs) + else + nil + end + else + ch = chrs.shift + if node = @Tree[ch] + if ret = node.match(chrs, op+ch) + return ret + else + chrs.unshift ch + if @postproc and @preproc.nil? || @preproc.call(op, chrs) + DOUT.printf(D_DETAIL, "op2: %s\n", op.inspect) + ret = @postproc.call(op, chrs) + return ret + else + return nil + end + end + else + chrs.unshift ch + if @postproc and @preproc.nil? || @preproc.call(op, chrs) + DOUT.printf(D_DETAIL, "op3: %s\n", op) + @postproc.call(op, chrs) + return "" + else + return nil + end + end + end + end + + def match_io(io, op = "") + if op == "" + ch = io.getc + if ch == nil + return nil + end + else + ch = io.getc_of_rests + end + if ch.nil? + if @preproc.nil? || @preproc.call(op, io) + D_DETAIL.printf("op1: %s\n", op) + @postproc.call(op, io) + else + nil + end + else + if node = @Tree[ch] + if ret = node.match_io(io, op+ch) + ret + else + io.ungetc ch + if @postproc and @preproc.nil? || @preproc.call(op, io) + DOUT.exec_if{D_DETAIL.printf "op2: %s\n", op.inspect} + @postproc.call(op, io) + else + nil + end + end + else + io.ungetc ch + if @postproc and @preproc.nil? || @preproc.call(op, io) + D_DETAIL.printf("op3: %s\n", op) + @postproc.call(op, io) + else + nil + end + end + end + end + end + end +end +# :startdoc: + +if $0 == __FILE__ + case $1 + when "1" + tr = SLex.new + print "0: ", tr.inspect, "\n" + tr.def_rule("=") {print "=\n"} + print "1: ", tr.inspect, "\n" + tr.def_rule("==") {print "==\n"} + print "2: ", tr.inspect, "\n" + + print "case 1:\n" + print tr.match("="), "\n" + print "case 2:\n" + print tr.match("=="), "\n" + print "case 3:\n" + print tr.match("=>"), "\n" + + when "2" + tr = SLex.new + print "0: ", tr.inspect, "\n" + tr.def_rule("=") {print "=\n"} + print "1: ", tr.inspect, "\n" + tr.def_rule("==", proc{false}) {print "==\n"} + print "2: ", tr.inspect, "\n" + + print "case 1:\n" + print tr.match("="), "\n" + print "case 2:\n" + print tr.match("=="), "\n" + print "case 3:\n" + print tr.match("=>"), "\n" + end + exit +end diff --git a/jni/ruby/lib/irb/src_encoding.rb b/jni/ruby/lib/irb/src_encoding.rb new file mode 100644 index 0000000..958cef1 --- /dev/null +++ b/jni/ruby/lib/irb/src_encoding.rb @@ -0,0 +1,4 @@ +# DO NOT WRITE ANY MAGIC COMMENT HERE. +def default_src_encoding + return __ENCODING__ +end diff --git a/jni/ruby/lib/irb/version.rb b/jni/ruby/lib/irb/version.rb new file mode 100644 index 0000000..a0e556e --- /dev/null +++ b/jni/ruby/lib/irb/version.rb @@ -0,0 +1,15 @@ +# +# irb/version.rb - irb version definition file +# $Release Version: 0.9.6$ +# $Revision: 38358 $ +# by Keiju ISHITSUKA(keiju@ishitsuka.com) +# +# -- +# +# +# + +module IRB # :nodoc: + @RELEASE_VERSION = "0.9.6" + @LAST_UPDATE_DATE = "09/06/30" +end diff --git a/jni/ruby/lib/irb/workspace.rb b/jni/ruby/lib/irb/workspace.rb new file mode 100644 index 0000000..b7eb810 --- /dev/null +++ b/jni/ruby/lib/irb/workspace.rb @@ -0,0 +1,114 @@ +# +# irb/workspace-binding.rb - +# $Release Version: 0.9.6$ +# $Revision: 47112 $ +# by Keiju ISHITSUKA(keiju@ruby-lang.org) +# +# -- +# +# +# +module IRB # :nodoc: + class WorkSpace + # Creates a new workspace. + # + # set self to main if specified, otherwise + # inherit main from TOPLEVEL_BINDING. + def initialize(*main) + if main[0].kind_of?(Binding) + @binding = main.shift + elsif IRB.conf[:SINGLE_IRB] + @binding = TOPLEVEL_BINDING + else + case IRB.conf[:CONTEXT_MODE] + when 0 # binding in proc on TOPLEVEL_BINDING + @binding = eval("proc{binding}.call", + TOPLEVEL_BINDING, + __FILE__, + __LINE__) + when 1 # binding in loaded file + require "tempfile" + f = Tempfile.open("irb-binding") + f.print <IRB.conf[:__MAIN__] + attr_reader :main + + # Evaluate the given +statements+ within the context of this workspace. + def evaluate(context, statements, file = __FILE__, line = __LINE__) + eval(statements, @binding, file, line) + end + + # error message manipulator + def filter_backtrace(bt) + case IRB.conf[:CONTEXT_MODE] + when 0 + return nil if bt =~ /\(irb_local_binding\)/ + when 1 + if(bt =~ %r!/tmp/irb-binding! or + bt =~ %r!irb/.*\.rb! or + bt =~ /irb\.rb/) + return nil + end + when 2 + return nil if bt =~ /irb\/.*\.rb/ + return nil if bt =~ /irb\.rb/ + when 3 + return nil if bt =~ /irb\/.*\.rb/ + return nil if bt =~ /irb\.rb/ + bt = bt.sub(/:\s*in `irb_binding'/, '') + end + bt + end + + def IRB.delete_caller + end + end +end diff --git a/jni/ruby/lib/irb/ws-for-case-2.rb b/jni/ruby/lib/irb/ws-for-case-2.rb new file mode 100644 index 0000000..a70183e --- /dev/null +++ b/jni/ruby/lib/irb/ws-for-case-2.rb @@ -0,0 +1,14 @@ +# +# irb/ws-for-case-2.rb - +# $Release Version: 0.9.6$ +# $Revision: 29726 $ +# by Keiju ISHITSUKA(keiju@ruby-lang.org) +# +# -- +# +# +# + +while true + IRB::BINDING_QUEUE.push _ = binding +end diff --git a/jni/ruby/lib/irb/xmp.rb b/jni/ruby/lib/irb/xmp.rb new file mode 100644 index 0000000..395a562 --- /dev/null +++ b/jni/ruby/lib/irb/xmp.rb @@ -0,0 +1,169 @@ +# +# xmp.rb - irb version of gotoken xmp +# $Release Version: 0.9$ +# $Revision: 47266 $ +# by Keiju ISHITSUKA(Nippon Rational Inc.) +# +# -- +# +# +# + +require "irb" +require "irb/frame" + +# An example printer for irb. +# +# It's much like the standard library PrettyPrint, that shows the value of each +# expression as it runs. +# +# In order to use this library, you must first require it: +# +# require 'irb/xmp' +# +# Now, you can take advantage of the Object#xmp convenience method. +# +# xmp < foo = "bar" +# #==>"bar" +# #=> baz = 42 +# #==>42 +# +# You can also create an XMP object, with an optional binding to print +# expressions in the given binding: +# +# ctx = binding +# x = XMP.new ctx +# x.puts +# #=> today = "a good day" +# #==>"a good day" +# ctx.eval 'today # is what?' +# #=> "a good day" +class XMP + + # Creates a new XMP object. + # + # The top-level binding or, optional +bind+ parameter will be used when + # creating the workspace. See WorkSpace.new for more information. + # + # This uses the +:XMP+ prompt mode, see IRB@Customizing+the+IRB+Prompt for + # full detail. + def initialize(bind = nil) + IRB.init_config(nil) + + IRB.conf[:PROMPT_MODE] = :XMP + + bind = IRB::Frame.top(1) unless bind + ws = IRB::WorkSpace.new(bind) + @io = StringInputMethod.new + @irb = IRB::Irb.new(ws, @io) + @irb.context.ignore_sigint = false + + IRB.conf[:MAIN_CONTEXT] = @irb.context + end + + # Evaluates the given +exps+, for example: + # + # require 'irb/xmp' + # x = XMP.new + # + # x.puts '{:a => 1, :b => 2, :c => 3}' + # #=> {:a => 1, :b => 2, :c => 3} + # # ==>{:a=>1, :b=>2, :c=>3} + # x.puts 'foo = "bar"' + # # => foo = "bar" + # # ==>"bar" + def puts(exps) + @io.puts exps + + if @irb.context.ignore_sigint + begin + trap_proc_b = trap("SIGINT"){@irb.signal_handle} + catch(:IRB_EXIT) do + @irb.eval_input + end + ensure + trap("SIGINT", trap_proc_b) + end + else + catch(:IRB_EXIT) do + @irb.eval_input + end + end + end + + # A custom InputMethod class used by XMP for evaluating string io. + class StringInputMethod < IRB::InputMethod + # Creates a new StringInputMethod object + def initialize + super + @exps = [] + end + + # Whether there are any expressions left in this printer. + def eof? + @exps.empty? + end + + # Reads the next expression from this printer. + # + # See IO#gets for more information. + def gets + while l = @exps.shift + next if /^\s+$/ =~ l + l.concat "\n" + print @prompt, l + break + end + l + end + + # Concatenates all expressions in this printer, separated by newlines. + # + # An Encoding::CompatibilityError is raised of the given +exps+'s encoding + # doesn't match the previous expression evaluated. + def puts(exps) + if @encoding and exps.encoding != @encoding + enc = Encoding.compatible?(@exps.join("\n"), exps) + if enc.nil? + raise Encoding::CompatibilityError, "Encoding in which the passed expression is encoded is not compatible to the preceding's one" + else + @encoding = enc + end + else + @encoding = exps.encoding + end + @exps.concat exps.split(/\n/) + end + + # Returns the encoding of last expression printed by #puts. + attr_reader :encoding + end +end + +# A convenience method that's only available when the you require the IRB::XMP standard library. +# +# Creates a new XMP object, using the given expressions as the +exps+ +# parameter, and optional binding as +bind+ or uses the top-level binding. Then +# evaluates the given expressions using the +:XMP+ prompt mode. +# +# For example: +# +# require 'irb/xmp' +# ctx = binding +# xmp 'foo = "bar"', ctx +# #=> foo = "bar" +# #==>"bar" +# ctx.eval 'foo' +# #=> "bar" +# +# See XMP.new for more information. +def xmp(exps, bind = nil) + bind = IRB::Frame.top(1) unless bind + xmp = XMP.new(bind) + xmp.puts exps + xmp +end -- cgit v1.2.3