summaryrefslogtreecommitdiff
path: root/sample/rbc.rb
diff options
context:
space:
mode:
author(no author) <(no author)@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>1998-01-16 12:19:22 +0000
committer(no author) <(no author)@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>1998-01-16 12:19:22 +0000
commitf12baed5df6d3c213dd75d2f0d9f36bb179fb843 (patch)
treec39f9c14cd6f8bcf85b6b842a2774cafb102bc2e /sample/rbc.rb
parent22ab6d39643b1bbc997e15b763d2b12996b1f1b9 (diff)
This commit was manufactured by cvs2svn to create branch 'RUBY'.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/RUBY@9 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'sample/rbc.rb')
-rw-r--r--sample/rbc.rb962
1 files changed, 962 insertions, 0 deletions
diff --git a/sample/rbc.rb b/sample/rbc.rb
new file mode 100644
index 0000000000..88a5b2d069
--- /dev/null
+++ b/sample/rbc.rb
@@ -0,0 +1,962 @@
+#!/usr/local/bin/ruby
+#
+# rbc.rb -
+# $Release Version: 0.6 $
+# $Revision: 1.2 $
+# $Date: 1997/11/27 13:46:06 $
+# by Keiju ISHITSUKA(Nippon Rational Inc.)
+#
+# --
+# Usage:
+#
+# rbc.rb [options] file_name opts
+# options:
+# -d デバッグモード(利用しない方が良いでしょう)
+# -m bcモード(分数, 行列の計算ができます)
+# -r load-module ruby -r と同じ
+# --inspect 結果出力にinspectを用いる(bcモード以外はデ
+# フォルト).
+# --noinspect 結果出力にinspectを用いない.
+# --noreadline readlineライブラリを利用しない(デフォルト
+# ではreadlineライブラリを利用しようとする).
+#
+# 追加 private method:
+# exit, quit 終了する.
+# inspect(sw = nil) インスペクトモードのトグル
+# trace_load(sw = nil) load/require時にrbcのfile読み込み機能を用
+# いるモードのスイッチ(デフォルトはトレース
+# モード)
+#
+require "e2mmap.rb"
+
+$stdout.sync = TRUE
+
+module BC_APPLICATION__
+ RCS_ID='-$Header: /home/keiju/var/src/var.lib/ruby/ruby/RCS/rbc.rb,v 1.2 1997/11/27 13:46:06 keiju Exp keiju $-'
+
+ extend Exception2MessageMapper
+ def_exception :UnrecognizedSwitch, "Unrecognized switch: %s"
+
+ $DEBUG = FALSE
+ $INSPECT = nil
+
+ CONFIG = {}
+ CONFIG[0] = $0
+ CONFIG[:USE_READLINE] = TRUE
+ CONFIG[:LOAD_MODULES] = []
+ CONFIG[:INSPECT] = nil
+ CONFIG[:TRACE_LOAD] = TRUE
+
+ while opt = ARGV.shift
+ case opt
+ when "-d"
+ $DEBUG = TRUE
+ when "-m"
+ CONFIG[:INSPECT] = FALSE if CONFIG[:INSPECT].nil?
+ require "mathn.rb"
+ include Math
+ when "-r"
+ opt = ARGV.shift
+ CONFIG[:LOAD_MODULES].push opt if opt
+ when "--inspect"
+ CONFIG[:INSPECT] = TRUE
+ when "--noinspect"
+ CONFIG[:INSPECT] = FALSE
+ when "--noreadline"
+ CONFIG[:USE_READLINE] = FALSE
+ when /^-/
+ # print UnrecognizedSwitch.inspect, "\n"
+ BC.fail UnrecognizedSwitch, opt
+ else
+ CONFIG[:USE_READLINE] = FALSE
+ $0 = opt
+ break
+ end
+ end
+ CONFIG[:INSPECT] = TRUE if CONFIG[:INSPECT].nil?
+
+ PROMPTi = "rbc%d> "
+ PROMPTs = "rbc%d%s "
+ PROMPTe = "rbc%d* "
+
+ class BC
+ def initialize
+ lex_init
+ end
+
+ def eval_input(io, cont, bind)
+ line = ''
+ @io = io
+ @ltype = nil
+ @quoted = nil
+ @indent = 0
+ @lex_state = EXPR_BEG
+
+ @io.prompt = format(PROMPTi, @indent)
+
+ loop do
+ @continue = FALSE
+ l = @io.gets
+
+ unless l
+ break if line == ''
+ else
+ line = line + l
+
+ lex(l) if l != "\n"
+ print @quoted.inspect, "\n" if $DEBUG
+ if @ltype
+ @io.prompt = format(PROMPTs, @indent, @ltype)
+ next
+ elsif @continue
+ @io.prompt = format(PROMPTe, @indent)
+ next
+ elsif @indent > 0
+ @io.prompt = format(PROMPTi, @indent)
+ next
+ end
+ end
+
+ if line != "\n"
+ begin
+ if CONFIG[:INSPECT]
+ print (cont._=eval(line, bind)).inspect, "\n"
+ else
+ print (cont._=eval(line, bind)), "\n"
+ end
+ rescue
+ # $! = 'exception raised' unless $!
+ # print "ERR: ", $!, "\n"
+ $! = RuntimeError.new("exception raised") unless $!
+ print $!.type, ": ", $!, "\n"
+ end
+ end
+ break if not l
+ line = ''
+ indent = 0
+ @io.prompt = format(PROMPTi, indent)
+ end
+ print "\n"
+ end
+
+ EXPR_BEG = :EXPR_BEG
+ EXPR_MID = :EXPR_MID
+ EXPR_END = :EXPR_END
+ EXPR_ARG = :EXPR_ARG
+ EXPR_FNAME = :EXPR_FNAME
+
+ CLAUSE_STATE_TRANS = {
+ "alias" => EXPR_FNAME,
+ "and" => EXPR_BEG,
+ "begin" => EXPR_BEG,
+ "case" => EXPR_BEG,
+ "class" => EXPR_BEG,
+ "def" => EXPR_FNAME,
+ "defined?" => EXPR_END,
+ "do" => EXPR_BEG,
+ "else" => EXPR_BEG,
+ "elsif" => EXPR_BEG,
+ "end" => EXPR_END,
+ "ensure" => EXPR_BEG,
+ "for" => EXPR_BEG,
+ "if" => EXPR_BEG,
+ "in" => EXPR_BEG,
+ "module" => EXPR_BEG,
+ "nil" => EXPR_END,
+ "not" => EXPR_BEG,
+ "or" => EXPR_BEG,
+ "rescue" => EXPR_MID,
+ "return" => EXPR_MID,
+ "self" => EXPR_END,
+ "super" => EXPR_END,
+ "then" => EXPR_BEG,
+ "undef" => EXPR_FNAME,
+ "unless" => EXPR_BEG,
+ "until" => EXPR_BEG,
+ "when" => EXPR_BEG,
+ "while" => EXPR_BEG,
+ "yield" => EXPR_END
+ }
+
+ ENINDENT_CLAUSE = [
+ "case", "class", "def", "do", "for", "if",
+ "module", "unless", "until", "while", "begin" #, "when"
+ ]
+ DEINDENT_CLAUSE = ["end"]
+
+ PARCENT_LTYPE = {
+ "q" => "\'",
+ "Q" => "\"",
+ "x" => "\`",
+ "r" => "\/"
+ }
+
+ PARCENT_PAREN = {
+ "{" => "}",
+ "[" => "]",
+ "<" => ">",
+ "(" => ")"
+ }
+
+ def lex_init()
+ @OP = Trie.new
+ @OP.def_rules("\0", "\004", "\032"){}
+ @OP.def_rules(" ", "\t", "\f", "\r", "\13") do
+ @space_seen = TRUE
+ next
+ end
+ @OP.def_rule("#") do
+ |op, rests|
+ @ltype = "#"
+ identify_comment(rests)
+ end
+ @OP.def_rule("\n") do
+ print "\\n\n" if $DEBUG
+ if @lex_state == EXPR_BEG || @lex_state == EXPR_FNAME
+ @continue = TRUE
+ else
+ @lex_state = EXPR_BEG
+ end
+ end
+ @OP.def_rules("*", "*=", "**=", "**") {@lex_state = EXPR_BEG}
+ @OP.def_rules("!", "!=", "!~") {@lex_state = EXPR_BEG}
+ @OP.def_rules("=", "==", "===", "=~", "=>") {@lex_state = EXPR_BEG}
+ @OP.def_rules("<", "<=", "<=>", "<<", "<=") {@lex_state = EXPR_BEG}
+ @OP.def_rules(">", ">=", ">>", ">=") {@lex_state = EXPR_BEG}
+ @OP.def_rules("'", '"') do
+ |op, rests|
+ @ltype = op
+ @quoted = op
+ identify_string(rests)
+ end
+ @OP.def_rules("`") do
+ |op, rests|
+ if @lex_state != EXPR_FNAME
+ @ltype = op
+ @quoted = op
+ identify_string(rests)
+ end
+ end
+ @OP.def_rules('?') do
+ |op, rests|
+ @lex_state = EXPR_END
+ identify_question(rests)
+ end
+ @OP.def_rules("&", "&&", "&=", "|", "||", "|=") do
+ @lex_state = EXPR_BEG
+ end
+ @OP.def_rule("+@", proc{@lex_state == EXPR_FNAME}) {}
+ @OP.def_rule("-@", proc{@lex_state == EXPR_FNAME}) {}
+ @OP.def_rules("+=", "-=") {@lex_state = EXPR_BEG}
+ @OP.def_rules("+", "-") do
+ |op, rests|
+ if @lex_state == EXPR_ARG
+ if @space_seen and rests[0] =~ /[0-9]/
+ identify_number(rests)
+ else
+ @lex_state = EXPR_BEG
+ end
+ elsif @lex_state != EXPR_END and rests[0] =~ /[0-9]/
+ identify_number(rests)
+ else
+ @lex_state = EXPR_BEG
+ end
+ end
+ @OP.def_rule(".") do
+ |op, rests|
+ @lex_state = EXPR_BEG
+ if rests[0] =~ /[0-9]/
+ rests.unshift op
+ identify_number(rests)
+ end
+ end
+ @OP.def_rules("..", "...") {@lex_state = EXPR_BEG}
+
+ lex_int2
+ end
+
+ def lex_int2
+ @OP.def_rules("]", "}", ")") do
+ @lex_state = EXPR_END
+ @indent -= 1
+ end
+ @OP.def_rule(":") {}
+ @OP.def_rule("::") {@lex_state = EXPR_BEG}
+ @OP.def_rule("/") do
+ |op, rests|
+ if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
+ @ltype = op
+ @quoted = op
+ identify_string(rests)
+ elsif rests[0] == '='
+ rests.shift
+ @lex_state = EXPR_BEG
+ elsif @lex_state == EXPR_ARG and @space_seen and rests[0] =~ /\s/
+ @ltype = op
+ @quoted = op
+ identify_string(rests)
+ else
+ @lex_state = EXPR_BEG
+ end
+ end
+ @OP.def_rules("^", "^=") {@lex_state = EXPR_BEG}
+ @OP.def_rules(",", ";") {@lex_state = EXPR_BEG}
+ @OP.def_rule("~") {@lex_state = EXPR_BEG}
+ @OP.def_rule("~@", proc{@lex_state = EXPR_FNAME}) {}
+ @OP.def_rule("(") do
+ @lex_state = EXPR_BEG
+ @indent += 1
+ end
+ @OP.def_rule("[]", proc{@lex_state == EXPR_FNAME}) {}
+ @OP.def_rule("[]=", proc{@lex_state == EXPR_FNAME}) {}
+ @OP.def_rule("[") do
+ @indent += 1
+ if @lex_state != EXPR_FNAME
+ @lex_state = EXPR_BEG
+ end
+ end
+ @OP.def_rule("{") do
+ @lex_state = EXPR_BEG
+ @indent += 1
+ end
+ @OP.def_rule('\\') {|op, rests| identify_escape(rests)} #')
+ @OP.def_rule('%') do
+ |op, rests|
+ if @lex_state == EXPR_BEG || @lex_state == EXPR_MID
+ identify_quotation(rests)
+ elsif rests[0] == '='
+ rests.shift
+ elsif @lex_state == EXPR_ARG and @space_seen and rests[0] =~ /\s/
+ identify_quotation(rests)
+ else
+ @lex_state = EXPR_BEG
+ end
+ end
+ @OP.def_rule('$') do
+ |op, rests|
+ identify_gvar(rests)
+ end
+ @OP.def_rule('@') do
+ |op, rests|
+ if rests[0] =~ /[\w_]/
+ rests.unshift op
+ identify_identifier(rests)
+ end
+ end
+ @OP.def_rule("") do
+ |op, rests|
+ printf "match: start %s: %s", op, rests.inspect if $DEBUG
+ if rests[0] =~ /[0-9]/
+ identify_number(rests)
+ elsif rests[0] =~ /[\w_]/
+ identify_identifier(rests)
+ end
+ printf "match: end %s: %s", op, rests.inspect if $DEBUG
+ end
+ end
+
+ def lex(l)
+ chrs = l.split(//)
+ tokens = []
+
+ case @ltype
+ when "'", '"', '`', '/'
+ identify_string(chrs)
+ return if chrs.empty?
+ when "#"
+ identify_comment(chrs)
+ return
+ when "="
+ if l =~ /^=end/
+ $ltype = nil
+ return
+ end
+ else
+ if l =~ /^=begin/
+ $ltype = "="
+ return
+ end
+ end
+
+ until chrs.empty?
+ @space_seen = FALSE
+ printf "perse: %s\n", chrs.join("") if $DEBUG
+ @OP.match(chrs)
+ printf "lex_state: %s continue: %s\n", @lex_state.id2name, @continue if $DEBUG
+ end
+ end
+
+ def identify_gvar(chrs)
+ @lex_state = EXPR_END
+
+ ch = chrs.shift
+ case ch
+ when /[_~*$?!@/\\;,.=:<>"]/ #"
+ return
+
+ when "-"
+ ch = chrs.shift
+ return
+
+ when "&", "`", "'", "+"
+ return
+
+ when /[1-9]/
+ chrs.unshift ch
+ v = "$"
+ while (ch = chrs.shift) =~ /[0-9]/
+ end
+ chrs.unshift ch
+ return
+
+ when /\w/
+ chrs.unshift ch
+ chrs.unshift "$"
+ identify_identifier(chrs)
+ return
+
+ else
+ chrs.unshift ch
+ return
+ end
+ end
+
+ def identify_identifier(chrs)
+ token = ""
+ token.concat chrs.shift if chrs[0] =~ /[$@]/
+ while (ch = chrs.shift) =~ /\w|_/
+ print ":", ch, ":" if $DEBUG
+ token.concat ch
+ end
+ chrs.unshift ch
+
+ if ch == "!" or ch == "?"
+ chrs.shift
+ token.concat ch
+ end
+ # fix token
+
+ if token =~ /^[$@]/
+ @lex_state = EXPR_END
+ return
+ end
+
+ print token, "\n" if $DEBUG
+ if state = CLAUSE_STATE_TRANS[token]
+ if @lex_state != EXPR_BEG and token =~ /^(if|unless|while|until)/
+ # 修飾子
+ else
+ if ENINDENT_CLAUSE.include?(token)
+ @indent += 1
+ elsif DEINDENT_CLAUSE.include?(token)
+ @indent -= 1
+ end
+ end
+ @lex_state = state
+ return
+ end
+ if @lex_state == EXPR_FNAME
+ @lex_state = EXPR_END
+ if chrs[0] == '='
+ chrs.shift
+ end
+ elsif @lex_state == EXPR_BEG
+ @lex_state = EXPR_ARG
+ else
+ @lex_state = EXPR_END
+ end
+ end
+
+ def identify_quotation(chrs)
+ ch = chrs.shift
+ if lt = PARCENT_LTYPE[ch]
+ ch = chrs.shift
+ else
+ lt = "\""
+ end
+ if ch !~ /\W/
+ chrs.unshift ch
+ next
+ end
+ @ltype = lt
+ unless @quoted = PARCENT_PAREN[ch]
+ @quoted = ch
+ end
+ identify_string(chrs)
+ end
+
+ def identify_number(chrs)
+ @lex_state = EXPR_END
+
+ ch = chrs.shift
+ case ch
+ when /0/
+ if (ch = chrs[0]) == "x"
+ chrs.shift
+ match = /[0-9a-f_]/
+ else
+ match = /[0-7_]/
+ end
+ while ch = chrs.shift
+ if ch !~ match
+ chrs.unshift ch
+ break
+ end
+ end
+ return
+ end
+
+ while ch = chrs.shift
+ case ch
+ when /[0-9]/
+ when "e", "E"
+ # type = FLOAT
+ unless (ch = chrs.shift) == "+" or ch == "-"
+ chrs.unshift ch
+ end
+ when "."
+ # type = FLOAT
+ when "_"
+ else
+ chrs.unshift ch
+ return
+ end
+ end
+ end
+
+ def identify_question(chrs)
+ @lex_state = EXPR_END
+
+ if chrs.shift == "\\" #"
+ identify_escape(chrs)
+ end
+ end
+
+ def identify_string(chrs)
+ while ch = chrs.shift
+ if @quoted == ch
+ if @ltype == "/"
+ if chrs[0] =~ /i|o|n|e|s/
+ chrs.shift
+ end
+ end
+ @ltype = nil
+ @quoted = nil
+ @lex_state = EXPR_END
+ break
+ elsif ch == '\\' #'
+ identify_escape(chrs)
+ end
+ end
+ end
+
+ def identify_comment(chrs)
+ while ch = chrs.shift
+ if ch == "\\" #"
+ identify_escape(chrs)
+ end
+ if ch == "\n"
+ @ltype = nil
+ chrs.unshift ch
+ break
+ end
+ end
+ end
+
+ def identify_escape(chrs)
+ ch = chrs.shift
+ case ch
+ when "\n", "\r", "\f"
+ @continue = TRUE
+ when "\\", "n", "t", "r", "f", "v", "a", "e", "b" #"
+ when /[0-7]/
+ chrs.unshift ch
+ 3.times do
+ ch = chrs.shift
+ case ch
+ when /[0-7]/
+ when nil
+ break
+ else
+ chrs.unshift ch
+ break
+ end
+ end
+ when "x"
+ 2.times do
+ ch = chrs.shift
+ case ch
+ when /[0-9a-fA-F]/
+ when nil
+ break
+ else
+ chrs.unshift ch
+ break
+ end
+ end
+ when "M"
+ if (ch = chrs.shift) != '-'
+ chrs.unshift ch
+ elsif (ch = chrs.shift) == "\\" #"
+ identify_escape(chrs)
+ end
+ return
+ when "C", "c", "^"
+ if ch == "C" and (ch = chrs.shift) != "-"
+ chrs.unshift ch
+ elsif (ch = chrs.shift) == "\\" #"
+ identify_escape(chrs)
+ end
+ return
+ end
+ end
+ end
+
+ class Trie
+ extend Exception2MessageMapper
+ def_exception :ErrNodeNothing, "node nothing"
+ def_exception :ErrNodeAlreadyExists, "node already exists"
+
+ class Node
+ # postprocがなければ抽象ノード, nilじゃなければ具象ノード
+ def initialize(preproc = nil, postproc = nil)
+ @Tree = {}
+ @preproc = preproc
+ @postproc = postproc
+ end
+
+ def preproc(p)
+ @preproc = p
+ end
+
+ def postproc(p)
+ @postproc = p
+ end
+
+ 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
+ Trie.fail ErrNodeNothing
+ end
+ end
+ end
+
+ def create_subnode(chrs, preproc = nil, postproc = nil)
+ ch = chrs.shift
+ if node = @Tree[ch]
+ if chrs.empty?
+ Trie.fail ErrNodeAlreadyExists
+ 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
+
+ def match(chrs, op = "")
+ print "match: ", chrs, ":", op, "\n" if $DEBUG
+ if chrs.empty?
+ if @preproc.nil? || @preproc.call(op, chrs)
+ printf "op1: %s\n", op if $DEBUG
+ @postproc.call(op, chrs)
+ ""
+ else
+ nil
+ end
+ else
+ ch = chrs.shift
+ if node = @Tree[ch]
+ if ret = node.match(chrs, op+ch)
+ return ch+ret
+ elsif @postproc and @preproc.nil? || @preproc.call(op, chrs)
+ chrs.unshift ch
+ printf "op2: %s\n", op if $DEBUG
+ @postproc.call(op, chrs)
+ return ""
+ else
+ chrs.unshift ch
+ return nil
+ end
+ else
+ if @postproc and @preproc.nil? || @preproc.call(op, chrs)
+ printf "op3: %s\n", op if $DEBUG
+ chrs.unshift ch
+ @postproc.call(op, chrs)
+ return ""
+ else
+ chrs.unshift ch
+ return nil
+ end
+ end
+ end
+ end
+ end
+
+ def initialize
+ @head = Node.new("")
+ end
+
+ def def_rule(token, preproc = nil, postproc = nil)
+ node = search(token, :CREATE)
+# print node.inspect, "\n" if $DEBUG
+ node.preproc(preproc)
+ if iterator?
+ node.postproc(proc)
+ elsif postproc
+ node.postproc(postproc)
+ end
+ end
+
+ def def_rules(*tokens)
+ if iterator?
+ p = proc
+ end
+ for token in tokens
+ def_rule(token, nil, p)
+ end
+ end
+
+ def preporc(token)
+ node = search(token)
+ node.preproc proc
+ end
+
+ def postproc(token)
+ node = search(token)
+ node.postproc proc
+ end
+
+ def search(token, opt = nil)
+ @head.search(token.split(//), opt)
+ end
+
+ def match(token)
+ token = token.split(//) if token.kind_of?(String)
+ ret = @head.match(token)
+ printf "match end: %s:%s", ret, token.inspect if $DEBUG
+ ret
+ end
+
+ def inspect
+ format("<Trie: @head = %s>", @head.inspect)
+ end
+ end
+
+ if /^-tt(.*)$/ =~ ARGV[0]
+# Tracer.on
+ case $1
+ when "1"
+ tr = Trie.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 = Trie.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
+
+ module CONTEXT
+ def _=(value)
+ @_ = value
+ end
+
+ def _
+ @_
+ end
+
+ def quit
+ exit
+ end
+
+ def trace_load(opt = nil)
+ if opt
+ @Trace_require = opt
+ else
+ @Trace_require = !@Trace_require
+ end
+ print "Switch to load/require #{unless @Trace_require; ' non';end} trace mode.\n"
+ if @Trace_require
+ eval %{
+ class << self
+ alias load rbc_load
+ alias require rbc_require
+ end
+ }
+ else
+ eval %{
+ class << self
+ alias load rbc_load_org
+ alias require rbc_require_org
+ end
+ }
+ end
+ @Trace_require
+ end
+
+ alias rbc_load_org load
+ def rbc_load(file_name)
+ return true if load_sub(file_name)
+ raise LoadError, "No such file to load -- #{file_name}"
+ end
+
+ alias rbc_require_org require
+ def rbc_require(file_name)
+ rex = Regexp.new("#{Regexp.quote(file_name)}(\.o|\.rb)?")
+ return false if $".find{|f| f =~ rex}
+
+ case file_name
+ when /\.rb$/
+ if load_sub(file_name)
+ $:.push file_name
+ return true
+ end
+ when /\.(so|o|sl)$/
+ require_org(file_name)
+ end
+
+ if load_sub(f = file_name + ".rb")
+ $:.push f
+ end
+ require(file_name)
+ end
+
+ def load_sub(fn)
+ if fn =~ /^#{Regexp.quote(File::Separator)}/
+ return false unless File.exist?(fn)
+ BC.new.eval_input FileInputMethod.new(fn), self, CONFIG[:BIND]
+ return true
+ end
+
+ for path in $:
+ if File.exist?(f = File.join(path, fn))
+ BC.new.eval_input FileInputMethod.new(f), self, CONFIG[:BIND]
+ return true
+ end
+ end
+ return false
+ end
+
+ def inspect(opt = nil)
+ if opt
+ CONFIG[:INSPECT] = opt
+ else
+ CONFIG[:INSPECT] = !$INSPECT
+ end
+ print "Switch to#{unless $INSPECT; ' non';end} inspect mode.\n"
+ $INSPECT
+ end
+
+ def run
+ CONFIG[:BIND] = proc
+
+ if CONFIG[:TRACE_LOAD]
+ trace_load true
+ end
+
+ for m in CONFIG[:LOAD_MODULES]
+ begin
+ require m
+ rescue
+ print $@[0], ":", $!.type, ": ", $!, "\n"
+ end
+ end
+
+ if !$0.equal?(CONFIG[0])
+ io = FileInputMethod.new($0)
+ elsif defined? Readline
+ io = ReadlineInputMethod.new
+ else
+ io = StdioInputMethod.new
+ end
+
+ BC.new.eval_input io, self, CONFIG[:BIND]
+ end
+ end
+
+ class InputMethod
+ attr :prompt, TRUE
+
+ def gets
+ end
+ public :gets
+ end
+
+ class StdioInputMethod < InputMethod
+ def gets
+ print @prompt
+ $stdin.gets
+ end
+ end
+
+ class FileInputMethod < InputMethod
+ def initialize(file)
+ @io = open(file)
+ end
+
+ def gets
+ l = @io.gets
+ print @prompt, l
+ l
+ end
+ end
+
+ if CONFIG[:USE_READLINE]
+ begin
+ require "readline"
+ print "use readline module\n"
+ class ReadlineInputMethod < InputMethod
+ include Readline
+ def gets
+ if l = readline(@prompt, TRUE)
+ l + "\n"
+ else
+ l
+ end
+ end
+ end
+ rescue
+ CONFIG[:USE_READLINE] = FALSE
+ end
+ end
+end
+
+extend BC_APPLICATION__::CONTEXT
+run{}