summaryrefslogtreecommitdiffstats
path: root/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/bintest/mrdb.rb286
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/bintest/print.rb701
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/mrbgem.rake9
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c507
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h26
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c239
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h14
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c78
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h13
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c436
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c501
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c58
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c64
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c759
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h165
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdbconf.h16
-rw-r--r--web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdberror.h20
17 files changed, 3892 insertions, 0 deletions
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/bintest/mrdb.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/bintest/mrdb.rb
new file mode 100644
index 00000000..26f3138a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/bintest/mrdb.rb
@@ -0,0 +1,286 @@
+require 'open3'
+require 'tempfile'
+
+class BinTest_MrubyBinDebugger
+ @debug1=false
+ @debug2=true
+ @debug3=true
+ def self.test(rubysource, testcase)
+ script, bin = Tempfile.new(['test', '.rb']), Tempfile.new(['test', '.mrb'])
+
+ # .rb
+ script.write rubysource
+ script.flush
+
+ # compile
+ `./bin/mrbc -g -o "#{bin.path}" "#{script.path}"`
+
+ # add mrdb quit
+ testcase << {:cmd=>"quit"}
+
+ stdin_data = testcase.map{|t| t[:cmd]}.join("\n") << "\n"
+
+ ["bin/mrdb #{script.path}","bin/mrdb -b #{bin.path}"].each do |cmd|
+ o, s = Open3.capture2(cmd, :stdin_data => stdin_data)
+
+ exp_vals = testcase.map{|t| t.fetch(:exp, nil)}
+ unexp_vals = testcase.map{|t| t.fetch(:unexp, nil)}
+
+if @debug1
+ o.split("\n").each_with_index do |i,actual|
+ p [i,actual]
+ end
+end
+ # compare actual / expected
+ o.split("\n").each do |actual|
+ next if actual.empty?
+ exp = exp_vals.shift
+if @debug2
+ a = true
+ a = actual.include?(exp) unless exp.nil?
+ p [actual, exp] unless a
+end
+ assert_true actual.include?(exp) unless exp.nil?
+ end
+ # compare actual / unexpected
+ o.split("\n").each do |actual|
+ next if actual.empty?
+ unexp = unexp_vals.shift
+if @debug3
+ a = false
+ a = actual.include?(unexp) unless unexp.nil?
+ p [actual, unexp] if a
+end
+ assert_false actual.include?(unexp) unless unexp.nil?
+ end
+ end
+ end
+end
+
+INVCMD = "invalid command"
+
+assert('mruby-bin-debugger(mrdb) command line') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ str = ""
+ 103.times {
+ str += "1234567890"
+ }
+ cmd = "p a=#{str}"
+
+ # test case
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>cmd[0...1023], :unexp=>'command line too long.'}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>cmd[0...1024], :unexp=>'command line too long.'}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>cmd[0...1025], :exp=>'command line too long.'}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "break"') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"b", :unexp=>INVCMD}
+ tc << {:cmd=>"br", :unexp=>INVCMD}
+ tc << {:cmd=>"brea", :unexp=>INVCMD}
+ tc << {:cmd=>"break", :unexp=>INVCMD}
+ BinTest_MrubyBinDebugger.test(src, tc)
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"bl", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"breaka", :exp=>INVCMD}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "continue"') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"c", :unexp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"co", :unexp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"continu", :unexp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"continue", :unexp=>INVCMD}])
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"cn", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"continuee", :exp=>INVCMD}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "delete"') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"d 1", :unexp=>INVCMD}
+ tc << {:cmd=>"de 1", :unexp=>INVCMD}
+ tc << {:cmd=>"delet 1", :unexp=>INVCMD}
+ tc << {:cmd=>"delete 1", :unexp=>INVCMD}
+ BinTest_MrubyBinDebugger.test(src, tc)
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"dd 1", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"deletee 1", :exp=>INVCMD}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "disable"') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"dis", :unexp=>INVCMD}
+ tc << {:cmd=>"disa", :unexp=>INVCMD}
+ tc << {:cmd=>"disabl", :unexp=>INVCMD}
+ tc << {:cmd=>"disable", :unexp=>INVCMD}
+ BinTest_MrubyBinDebugger.test(src, tc)
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"di", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"disb", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"disablee", :exp=>INVCMD}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "enable"') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"en", :unexp=>INVCMD}
+ tc << {:cmd=>"ena", :unexp=>INVCMD}
+ tc << {:cmd=>"enabl", :unexp=>INVCMD}
+ tc << {:cmd=>"enable", :unexp=>INVCMD}
+ BinTest_MrubyBinDebugger.test(src, tc)
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"e", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"enb", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"enablee", :exp=>INVCMD}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "eval"') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"ev", :unexp=>INVCMD}
+ tc << {:cmd=>"eva", :unexp=>INVCMD}
+ tc << {:cmd=>"eval", :unexp=>INVCMD}
+ BinTest_MrubyBinDebugger.test(src, tc)
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"e", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"evl", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"evall", :exp=>INVCMD}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "help"') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"h", :unexp=>INVCMD}
+ tc << {:cmd=>"he", :unexp=>INVCMD}
+ tc << {:cmd=>"hel", :unexp=>INVCMD}
+ tc << {:cmd=>"help", :unexp=>INVCMD}
+ BinTest_MrubyBinDebugger.test(src, tc)
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"hl", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"helpp", :exp=>INVCMD}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "info breakpoints"') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"i b", :unexp=>INVCMD}
+ tc << {:cmd=>"in b", :unexp=>INVCMD}
+ tc << {:cmd=>"i br", :unexp=>INVCMD}
+ tc << {:cmd=>"inf breakpoint", :unexp=>INVCMD}
+ tc << {:cmd=>"info breakpoints", :unexp=>INVCMD}
+ BinTest_MrubyBinDebugger.test(src, tc)
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"ii b", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"i bb", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"infoo breakpoints", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"info breakpointss", :exp=>INVCMD}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "list"') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"l", :unexp=>INVCMD}
+ tc << {:cmd=>"li", :unexp=>INVCMD}
+ tc << {:cmd=>"lis", :unexp=>INVCMD}
+ tc << {:cmd=>"list", :unexp=>INVCMD}
+ BinTest_MrubyBinDebugger.test(src, tc)
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"ll", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"listt", :exp=>INVCMD}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "print"') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"p", :unexp=>INVCMD}
+ tc << {:cmd=>"pr", :unexp=>INVCMD}
+ tc << {:cmd=>"prin", :unexp=>INVCMD}
+ tc << {:cmd=>"print", :unexp=>INVCMD}
+ BinTest_MrubyBinDebugger.test(src, tc)
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"pp", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"printt", :exp=>INVCMD}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "quit"') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"q", :unexp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"qu", :unexp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"qui", :unexp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"quit", :unexp=>INVCMD}])
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"qq", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"quitt", :exp=>INVCMD}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "run"') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"r", :unexp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"ru", :unexp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"run", :unexp=>INVCMD}])
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"rr", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"runn", :exp=>INVCMD}])
+end
+
+assert('mruby-bin-debugger(mrdb) command: "step"') do
+ # ruby source
+ src = <<"SRC"
+while true
+ foo = 'foo'
+end
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>"s", :unexp=>INVCMD}
+ tc << {:cmd=>"st", :unexp=>INVCMD}
+ tc << {:cmd=>"ste", :unexp=>INVCMD}
+ tc << {:cmd=>"step", :unexp=>INVCMD}
+ BinTest_MrubyBinDebugger.test(src, tc)
+
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"ss", :exp=>INVCMD}])
+ BinTest_MrubyBinDebugger.test(src, [{:cmd=>"stepp", :exp=>INVCMD}])
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/bintest/print.rb b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/bintest/print.rb
new file mode 100644
index 00000000..1bc96c47
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/bintest/print.rb
@@ -0,0 +1,701 @@
+require 'open3'
+require 'tempfile'
+
+class BinTest_MrubyBinDebugger
+ @debug1=false
+ @debug2=true
+ def self.test(rubysource, testcase)
+ script, bin = Tempfile.new(['test', '.rb']), Tempfile.new(['test', '.mrb'])
+
+ # .rb
+ script.write rubysource
+ script.flush
+
+ # compile
+ `./bin/mrbc -g -o "#{bin.path}" "#{script.path}"`
+
+ # add mrdb quit
+ testcase << {:cmd=>"quit"}
+
+ stdin_data = testcase.map{|t| t[:cmd]}.join("\n") << "\n"
+
+ ["bin/mrdb #{script.path}","bin/mrdb -b #{bin.path}"].each do |cmd|
+ o, s = Open3.capture2(cmd, :stdin_data => stdin_data)
+
+ exp_vals = testcase.map{|t| t.fetch(:exp, nil)}
+=begin
+if @debug1
+ o.split("\n").each_with_index do |i,actual|
+ p [i,actual]
+ end
+end
+ # compare actual / expected
+ o.split("\n").each do |actual|
+ next if actual.empty?
+ exp = exp_vals.shift
+if @debug2
+ a = true
+ a = actual.include?(exp) unless exp.nil?
+ p [actual, exp] unless a
+end
+ assert_true actual.include?(exp) unless exp.nil?
+ end
+=end
+ idx = 0
+ exp_vals.each do |exp|
+ next if exp.nil?
+ idx = o.index(exp, idx)
+ assert_false idx.nil?
+ break unless idx
+ idx += 1
+ end
+ end
+ end
+end
+
+assert('mruby-bin-debugger(print) invalid arguments') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"p", :exp=>"Parameter not specified."}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) nomal') do
+ # ruby source
+ src = <<"SRC"
+foo = 'foo'
+bar = foo
+baz = bar
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>"s"}
+ tc << {:cmd=>"p (1+2)", :exp=>'$1 = 3'}
+ tc << {:cmd=>"p foo", :exp=>'$2 = "foo"'}
+ tc << {:cmd=>"p foo*=2", :exp=>'$3 = "foofoo"'}
+ tc << {:cmd=>"s"}
+ tc << {:cmd=>"p bar", :exp=>'$4 = "foofoo"'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) error') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"p (1+2", :exp=>'$1 = SyntaxError'}
+ tc << {:cmd=>"p bar", :exp=>'$2 = NoMethodError'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+# Kernel#instance_eval(string) does't work multiple statements.
+=begin
+assert('mruby-bin-debugger(print) multiple statements') do
+ # ruby source
+ src = <<"SRC"
+x = 0
+y = 0
+z = 0
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>"s",}
+ tc << {:cmd=>"p x=1;x+=2", :exp=>"3"}
+ tc << {:cmd=>"s",}
+ tc << {:cmd=>"p x", :exp=>"3"}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+=end
+
+assert('mruby-bin-debugger(print) scope:top') do
+ # ruby source (bp is break point)
+ src = "bp=nil\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"p self", :exp=>'$1 = main'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) scope:class') do
+ # ruby source (bp is break point)
+ src = <<"SRC"
+class TestClassScope
+ bp = nil
+end
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>"s"}
+ tc << {:cmd=>"p self", :exp=>'$1 = TestClassScope'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) scope:module') do
+ # ruby source (bp is break point)
+ src = <<"SRC"
+class TestModuleScope
+ bp = nil
+end
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>"s"}
+ tc << {:cmd=>"p self", :exp=>'$1 = TestModuleScope'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) scope:instance method') do
+ # ruby source (bp is break point)
+ src = <<"SRC"
+class TestMethodScope
+ def m
+ bp = nil
+ end
+end
+TestMethodScope.new.m
+SRC
+
+ tc = []
+ tc << {:cmd=>"b 3"}
+ tc << {:cmd=>"r"}
+ tc << {:cmd=>"p self", :exp=>'$1 = #<TestMethodScope:'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) scope:class method') do
+ # ruby source (bp is break point)
+ src = <<"SRC"
+class TestClassMethodScope
+ def self.cm
+ bp = nil
+ end
+end
+TestClassMethodScope.cm
+SRC
+
+ tc = []
+ tc << {:cmd=>"b 3"}
+ tc << {:cmd=>"r"}
+ tc << {:cmd=>"p self", :exp=>'$1 = TestClassMethodScope'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) scope:block') do
+ # ruby source (bp is break point)
+ src = <<"SRC"
+1.times do
+ bp = nil
+end
+class TestBlockScope
+ 1.times do
+ bp = nil
+ end
+ def m
+ 1.times do
+ bp = nil
+ end
+ end
+end
+TestBlockScope.new.m
+SRC
+
+ tc = []
+ tc << {:cmd=>"b 2"}
+ tc << {:cmd=>"b 6"}
+ tc << {:cmd=>"b 10"}
+ tc << {:cmd=>"c"}
+ tc << {:cmd=>"p self", :exp=>'$1 = main'}
+ tc << {:cmd=>"c"}
+ tc << {:cmd=>"p self", :exp=>'$2 = TestBlockScope'}
+ tc << {:cmd=>"c"}
+ tc << {:cmd=>"p self", :exp=>'$3 = #<TestBlockScope:'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) same name:local variabe') do
+ # ruby source (bp is break point)
+ src = <<"SRC"
+lv = 'top'
+class TestLocalVariableName
+ lv = 'class'
+ def m
+ lv = 'instance method'
+ bp = nil
+ end
+ bp = nil
+end
+TestLocalVariableName.new.m
+bp = nil
+SRC
+
+ tc = []
+ tc << {:cmd=>"b 6"}
+ tc << {:cmd=>"b 8"}
+ tc << {:cmd=>"b 11"}
+ tc << {:cmd=>"r"}
+ tc << {:cmd=>"p lv", :exp=>'$1 = "class"'}
+ tc << {:cmd=>"c"}
+ tc << {:cmd=>"p lv", :exp=>'$2 = "instance method"'}
+ tc << {:cmd=>"c"}
+ tc << {:cmd=>"p lv", :exp=>'$3 = "top"'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) same name:instance variabe') do
+ # ruby source (bp is break point)
+ src = <<"SRC"
+@iv = 'top'
+class TestInstanceVariableName
+ def initialize(v)
+ @iv = v
+ end
+ def m
+ bp = nil
+ end
+end
+i1 = TestInstanceVariableName.new('instance1')
+i2 = TestInstanceVariableName.new('instance2')
+i1.m
+i2.m
+bp = nil
+SRC
+
+ tc = []
+ tc << {:cmd=>"b 7"}
+ tc << {:cmd=>"b 14"}
+ tc << {:cmd=>"r"}
+ tc << {:cmd=>"p @iv", :exp=>'$1 = "instance1"'}
+ tc << {:cmd=>"c"}
+ tc << {:cmd=>"p @iv", :exp=>'$2 = "instance2"'}
+ tc << {:cmd=>"c"}
+ tc << {:cmd=>"p @iv", :exp=>'$3 = "top"'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+# Kernel#instance_eval(string) does't work const.
+=begin
+assert('mruby-bin-debugger(print) same name:const') do
+ # ruby source (bp is break point)
+ src = <<"SRC"
+CONST='top'
+class TestConstNameSuperClass
+ CONST='super class'
+ def m
+ bp = nil
+ end
+end
+class TestConstNameSubClass < TestConstNameSuperClass
+ CONST='sub class'
+ def m
+ bp = nil
+ end
+end
+
+TestConstNameSuperClass.new.m()
+TestConstNameSubClass.new.m()
+bp = nil
+SRC
+
+ # todo: wait for 'break' to be implimented
+ tc = []
+ 9.times { tc << {:cmd=>"s"} }
+ tc << {:cmd=>"p CONST", :exp=>"super class"}
+ 3.times { tc << {:cmd=>"s"} }
+ tc << {:cmd=>"p CONST", :exp=>"sub class"}
+ 1.times { tc << {:cmd=>"s"} }
+ tc << {:cmd=>"p CONST", :exp=>"top"}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+=end
+
+assert('mruby-bin-debugger(print) Literal:Numeric') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>"p 100", :exp=>'$1 = 100'}
+ tc << {:cmd=>"p -0b100", :exp=>'$2 = -4'}
+ tc << {:cmd=>"p +0100", :exp=>'$3 = 64'}
+ tc << {:cmd=>"p 0x100", :exp=>'$4 = 256'}
+ tc << {:cmd=>"p 1_234", :exp=>'$5 = 1234'}
+ tc << {:cmd=>"p 0b1000_0000", :exp=>"$6 = #{0b1000_0000}"}
+ tc << {:cmd=>"p 0x1000_0000", :exp=>"$7 = #{0x1000_0000}"}
+
+ tc << {:cmd=>"p 3.14", :exp=>'$8 = 3.14'}
+ tc << {:cmd=>"p -12.3", :exp=>'$9 = -12.3'}
+ tc << {:cmd=>"p +12.000", :exp=>'$10 = 12.0'}
+ tc << {:cmd=>"p 1e4", :exp=>'$11 = 10000.0'}
+ tc << {:cmd=>"p -0.1e-2", :exp=>'$12 = -0.001'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) Literal:String') do
+ # ruby source
+ src = <<"SRC"
+foo = 'foo'
+bar = "bar"
+baz = "baz"
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>"s"}
+ tc << {:cmd=>"s"}
+
+ tc << {:cmd=>'p "str"', :exp=>'$1 = "str"'}
+ tc << {:cmd=>'p "s\tt\rr\n"', :exp=>'$2 = "s\\tt\\rr\\n"'}
+ tc << {:cmd=>'p "\C-a\C-z"', :exp=>'$3 = "\\001\\032"'}
+ tc << {:cmd=>'p "#{foo+bar}"', :exp=>'$4 = "foobar"'}
+
+ tc << {:cmd=>'p \'str\'', :exp=>'$5 = "str"'}
+ tc << {:cmd=>'p \'s\\tt\\rr\\n\'', :exp=>'$6 = "s\\\\tt\\\\rr\\\\n"'}
+ tc << {:cmd=>'p \'\\C-a\\C-z\'', :exp=>'$7 = "\\\\C-a\\\\C-z"'}
+ tc << {:cmd=>'p \'#{foo+bar}\'', :exp=>'$8 = "#{foo+bar}"'}
+
+ tc << {:cmd=>'p %!str!', :exp=>'$9 = "str"'}
+ tc << {:cmd=>'p %!s\tt\rr\n!', :exp=>'$10 = "s\\tt\\rr\\n"'}
+ tc << {:cmd=>'p %!\C-a\C-z!', :exp=>'$11 = "\\001\\032"'}
+ tc << {:cmd=>'p %!#{foo+bar}!', :exp=>'$12 = "foobar"'}
+
+ tc << {:cmd=>'p %Q!str!', :exp=>'$13 = "str"'}
+ tc << {:cmd=>'p %Q!s\tt\rr\n!', :exp=>'$14 = "s\\tt\\rr\\n"'}
+ tc << {:cmd=>'p %Q!\C-a\C-z!', :exp=>'$15 = "\\001\\032"'}
+ tc << {:cmd=>'p %Q!#{foo+bar}!', :exp=>'$16 = "foobar"'}
+
+ tc << {:cmd=>'p %q!str!', :exp=>'$17 = "str"'}
+ tc << {:cmd=>'p %q!s\\tt\\rr\\n!', :exp=>'$18 = "s\\\\tt\\\\rr\\\\n"'}
+ tc << {:cmd=>'p %q!\\C-a\\C-z!', :exp=>'$19 = "\\\\C-a\\\\C-z"'}
+ tc << {:cmd=>'p %q!#{foo+bar}!', :exp=>'$20 = "#{foo+bar}"'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) Literal:Array') do
+ # ruby source
+ src = <<"SRC"
+foo = 'foo'
+bar = "bar"
+baz = "baz"
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>"s"}
+ tc << {:cmd=>"s"}
+
+ tc << {:cmd=>'p []', :exp=>'$1 = []'}
+ tc << {:cmd=>'p [ 5, 12, 8, 10, ]', :exp=>'$2 = [5, 12, 8, 10]'}
+ tc << {:cmd=>'p [1,2.5,"#{foo+bar}"]', :exp=>'$3 = [1, 2.5, "foobar"]'}
+ tc << {:cmd=>'p %w[3.14 A\ &\ B #{foo}]', :exp=>'$4 = ["3.14", "A & B", "#{foo}"]'}
+ tc << {:cmd=>'p %W[3.14 A\ &\ B #{foo}]', :exp=>'$5 = ["3.14", "A & B", "foo"]'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) Literal:Hash') do
+ # ruby source
+ src = <<"SRC"
+foo = 'foo'
+bar = "bar"
+baz = "baz"
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>"s"}
+ tc << {:cmd=>"s"}
+
+ tc << {:cmd=>'p {}', :exp=>'$1 = {}'}
+ tc << {:cmd=>'p {"one"=>1,"two"=>2}', :exp=>'$2 = {"one"=>1, "two"=>2}'}
+ tc << {:cmd=>'p {:eins=>"1", :zwei=>"2", }', :exp=>'$3 = {:eins=>"1", :zwei=>"2"}'}
+ tc << {:cmd=>'p {uno:"one", dos: 2}', :exp=>'$4 = {:uno=>"one", :dos=>2}'}
+ tc << {:cmd=>'p {"one"=>1, :zwei=>2, tres:3}', :exp=>'$5 = {"one"=>1, :zwei=>2, :tres=>3}'}
+ tc << {:cmd=>'p {:foo=>"#{foo}",:bar=>"#{bar}"}', :exp=>'$6 = {:foo=>"foo", :bar=>"bar"}'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) Literal:Range') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>'p 1..10', :exp=>'$1 = 1..10'}
+ tc << {:cmd=>'p 1...10', :exp=>'$2 = 1...10'}
+ tc << {:cmd=>'p 100..10', :exp=>'$3 = 100..10'}
+ tc << {:cmd=>'p 1 ... 10', :exp=>'$4 = 1...10'}
+
+ tc << {:cmd=>'p "1" .. "9"', :exp=>'$5 = "1".."9"'}
+ tc << {:cmd=>'p "A" ... "Z"', :exp=>'$6 = "A"..."Z"'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) Literal:Symbol') do
+ # ruby source
+ src = <<"SRC"
+foo = 'foo'
+bar = "bar"
+baz = "baz"
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>"s"}
+ tc << {:cmd=>"s"}
+
+ tc << {:cmd=>'p :sym', :exp=>'$1 = :sym'}
+ tc << {:cmd=>'p :"sd"', :exp=>'$2 = :sd'}
+ tc << {:cmd=>"p :'ss'", :exp=>'$3 = :ss'}
+ tc << {:cmd=>'p :"123"', :exp=>'$4 = :"123"'}
+ tc << {:cmd=>'p :"#{foo} baz"', :exp=>'$5 = :"foo baz"'}
+ tc << {:cmd=>'p %s!symsym!', :exp=>'$6 = :symsym'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) Unary operation') do
+ # ruby source
+ src = "foo = 'foo'\n"
+
+ # test case
+ tc = []
+ tc << {:cmd=>'p +10', :exp=>'$1 = 10'}
+ tc << {:cmd=>'p -100', :exp=>'$2 = -100'}
+ tc << {:cmd=>'p !true', :exp=>'$3 = false'}
+ tc << {:cmd=>'p !false', :exp=>'$4 = true'}
+ tc << {:cmd=>'p !nil', :exp=>'$5 = true'}
+ tc << {:cmd=>'p !1', :exp=>'$6 = false'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) Binary operation') do
+ # ruby source
+ src = <<"SRC"
+CONST = 100
+a,b,c = 1, 5, 8
+foo,bar,baz = 'foo','bar','baz'
+ary = []
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>'s'}
+ tc << {:cmd=>'s'}
+ tc << {:cmd=>'s'}
+
+ tc << {:cmd=>'p a+1', :exp=>'$1 = 2'}
+ tc << {:cmd=>'p 2-b', :exp=>'$2 = -3'}
+ tc << {:cmd=>'p c * 3', :exp=>'$3 = 24'}
+ tc << {:cmd=>'p a/b', :exp=>'$4 = 0.2'}
+ tc << {:cmd=>'p c%b', :exp=>'$5 = 3'}
+ tc << {:cmd=>'p 2**10', :exp=>'$6 = 1024'}
+ tc << {:cmd=>'p ~3', :exp=>'$7 = -4'}
+
+ tc << {:cmd=>'p 1<<2', :exp=>'$8 = 4'}
+ tc << {:cmd=>'p 64>>5', :exp=>'$9 = 2'}
+
+ tc << {:cmd=>'p a|c', :exp=>'$10 = 9'}
+ tc << {:cmd=>'p a&b', :exp=>'$11 = 1'}
+ tc << {:cmd=>'p a^b', :exp=>'$12 = 4'}
+
+ tc << {:cmd=>'p a>b', :exp=>'$13 = false'}
+ tc << {:cmd=>'p a<b', :exp=>'$14 = true'}
+ tc << {:cmd=>'p b>=5', :exp=>'$15 = true'}
+ tc << {:cmd=>'p b<=5', :exp=>'$16 = true'}
+
+ tc << {:cmd=>'p "A"<=>"B"', :exp=>'$17 = -1'}
+ tc << {:cmd=>'p "A"=="B"', :exp=>'$18 = false'}
+ tc << {:cmd=>'p "A"==="B"', :exp=>'$19 = false'}
+ tc << {:cmd=>'p "A"!="B"', :exp=>'$20 = true'}
+
+ tc << {:cmd=>'p false || true', :exp=>'$21 = true'}
+ tc << {:cmd=>'p false && true', :exp=>'$22 = false'}
+
+ tc << {:cmd=>'p not nil', :exp=>'$23 = true'}
+ tc << {:cmd=>'p false or true', :exp=>'$24 = true'}
+ tc << {:cmd=>'p false and true', :exp=>'$25 = false'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) Ternary operation') do
+ # ruby source
+ src = <<"SRC"
+CONST = 100
+a,b,c = 1, 5, -10
+foo,bar,baz = 'foo','bar','baz'
+ary = []
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>'s'}
+ tc << {:cmd=>'s'}
+ tc << {:cmd=>'s'}
+
+ tc << {:cmd=>'p (a < b) ? a : b', :exp=>'$1 = 1'}
+ tc << {:cmd=>'p (a > b) ? a : b', :exp=>'$2 = 5'}
+ tc << {:cmd=>'p true ? "true" : "false"', :exp=>'$3 = "true"'}
+ tc << {:cmd=>'p false ? "true" : "false"', :exp=>'$4 = "false"'}
+ tc << {:cmd=>'p nil ? "true" : "false"', :exp=>'$5 = "false"'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) Substitution:simple') do
+ # ruby source
+ src = <<"SRC"
+CONST = 100
+a,b,c = 1, 5, -10
+foo,bar,baz = 'foo','bar','baz'
+ary = []
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>'s'}
+ tc << {:cmd=>'s'}
+ tc << {:cmd=>'s'}
+
+ tc << {:cmd=>'p a=2', :exp=>'$1 = 2'}
+ tc << {:cmd=>'p foo=[foo,bar,baz]', :exp=>'$2 = ["foo", "bar", "baz"]'}
+
+ tc << {:cmd=>'p undefined=-1', :exp=>'$3 = -1'}
+ tc << {:cmd=>'p "#{undefined}"', :exp=>'$4 = NoMethodError'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) Substitution:self') do
+ # ruby source
+ src = <<"SRC"
+CONST = 100
+a,b,c = 1, 5, -10
+foo,bar,baz = 'foo','bar','baz'
+ary = []
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>'s'}
+ tc << {:cmd=>'s'}
+ tc << {:cmd=>'s'}
+
+ tc << {:cmd=>'p a+=9', :exp=>'$1 = 10'}
+ tc << {:cmd=>'p b-=c', :exp=>'$2 = 15'}
+ tc << {:cmd=>'p bar*=2', :exp=>'$3 = "barbar"'}
+ tc << {:cmd=>'p a/=4', :exp=>'$4 = 2.5'}
+ tc << {:cmd=>'p c%=4', :exp=>'$5 = 2'}
+
+ tc << {:cmd=>'p b&=0b0101', :exp=>'$6 = 5'}
+ tc << {:cmd=>'p c|=0x10', :exp=>'$7 = 18'}
+
+ tc << {:cmd=>'p "#{a} #{b} #{c}"', :exp=>'$8 = "2.5 5 18"'}
+ tc << {:cmd=>'p "#{foo}#{bar}#{baz}"', :exp=>'$9 = "foobarbarbaz"'}
+
+ tc << {:cmd=>'p a,b,c=[10,20,30]',:exp=>'$10 = [10, 20, 30]'}
+ tc << {:cmd=>'p [a,b,c]', :exp=>'$11 = [10, 20, 30]'}
+ tc << {:cmd=>'p a,b=b,a', :exp=>'$12 = [20, 10]'}
+ tc << {:cmd=>'p [a,b]', :exp=>'$13 = [20, 10]'}
+
+ tc << {:cmd=>'p undefined=-1', :exp=>'$14 = -1'}
+ tc << {:cmd=>'p "#{undefined}"', :exp=>'$15 = NoMethodError'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) Substitution:multiple') do
+ # ruby source
+ src = <<"SRC"
+CONST = 100
+a,b,c = 1, 5, -10
+foo,bar,baz = 'foo','bar','baz'
+ary = []
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>'s'}
+ tc << {:cmd=>'s'}
+ tc << {:cmd=>'s'}
+
+ tc << {:cmd=>'p a,b=[10,20]', :exp=>'$1 = [10, 20]'}
+ tc << {:cmd=>'p [a,b,c]', :exp=>'$2 = [10, 20, -10]'}
+
+ tc << {:cmd=>'p foo,bar=["FOO","BAR","BAZ"]', :exp=>'$3 = ["FOO", "BAR", "BAZ"]'}
+ tc << {:cmd=>'p [foo,bar,baz]', :exp=>'$4 = ["FOO", "BAR", "baz"]'}
+
+ tc << {:cmd=>'p a,foo=foo,a', :exp=>'$5 = ["FOO", 10]'}
+ tc << {:cmd=>'p [a,foo]', :exp=>'$6 = ["FOO", 10]'}
+
+# tc << {:cmd=>'p a,*b=[123, 456, 789]'}
+# tc << {:cmd=>'p [a,b]', :exp=>'[123, [456, 789]]'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
+assert('mruby-bin-debugger(print) Substitution:self') do
+ # ruby source
+ src = <<"SRC"
+CONST = 100
+a,b,c = 1, 5, -10
+foo,bar,baz = 'foo','bar','baz'
+ary = []
+SRC
+
+ # test case
+ tc = []
+ tc << {:cmd=>'s'}
+ tc << {:cmd=>'s'}
+ tc << {:cmd=>'s'}
+
+ tc << {:cmd=>'p a+=9', :exp=>'$1 = 10'}
+ tc << {:cmd=>'p b-=c', :exp=>'$2 = 15'}
+ tc << {:cmd=>'p bar*=2', :exp=>'$3 = "barbar"'}
+ tc << {:cmd=>'p a/=4', :exp=>'$4 = 2.5'}
+ tc << {:cmd=>'p c%=4', :exp=>'$5 = 2'}
+
+ tc << {:cmd=>'p b&=0b0101', :exp=>'$6 = 5'}
+ tc << {:cmd=>'p c|=0x10', :exp=>'$7 = 18'}
+
+ tc << {:cmd=>'p "#{a} #{b} #{c}"', :exp=>'$8 = "2.5 5 18"'}
+ tc << {:cmd=>'p "#{foo}#{bar}#{baz}"', :exp=>'$9 = "foobarbarbaz"'}
+
+ tc << {:cmd=>'p a,b,c=[10,20,30]',:exp=>'$10 = [10, 20, 30]'}
+ tc << {:cmd=>'p [a,b,c]', :exp=>'$11 = [10, 20, 30]'}
+ tc << {:cmd=>'p a,b=b,a', :exp=>'$12 = [20, 10]'}
+ tc << {:cmd=>'p [a,b]', :exp=>'$13 = [20, 10]'}
+
+ tc << {:cmd=>'p undefined=-1', :exp=>'$14 = -1'}
+ tc << {:cmd=>'p "#{undefined}"', :exp=>'$15 = NoMethodError'}
+
+ BinTest_MrubyBinDebugger.test(src, tc)
+end
+
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/mrbgem.rake b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/mrbgem.rake
new file mode 100644
index 00000000..764f431a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/mrbgem.rake
@@ -0,0 +1,9 @@
+MRuby::Gem::Specification.new('mruby-bin-debugger') do |spec|
+ spec.license = 'MIT'
+ spec.author = 'mruby developers'
+ spec.summary = 'mruby debugger command'
+
+ spec.add_dependency('mruby-eval', :core => 'mruby-eval')
+
+ spec.bins = %w(mrdb)
+end
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c
new file mode 100644
index 00000000..dead4b2a
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c
@@ -0,0 +1,507 @@
+/*
+** apibreak.c
+**
+*/
+
+#include <string.h>
+#include <mruby.h>
+#include <mruby/irep.h>
+#include "mrdb.h"
+#include <mruby/debug.h>
+#include <mruby/opcode.h>
+#include <mruby/class.h>
+#include <mruby/proc.h>
+#include <mruby/variable.h>
+#include "mrdberror.h"
+#include "apibreak.h"
+
+#define MAX_BREAKPOINTNO (MAX_BREAKPOINT * 1024)
+#define MRB_DEBUG_BP_FILE_OK (0x0001)
+#define MRB_DEBUG_BP_LINENO_OK (0x0002)
+
+static uint16_t
+check_lineno(mrb_irep_debug_info_file *info_file, uint16_t lineno)
+{
+ uint32_t count = info_file->line_entry_count;
+ uint16_t l_idx;
+
+ if (info_file->line_type == mrb_debug_line_ary) {
+ for (l_idx = 0; l_idx < count; ++l_idx) {
+ if (lineno == info_file->lines.ary[l_idx]) {
+ return lineno;
+ }
+ }
+ }
+ else {
+ for (l_idx = 0; l_idx < count; ++l_idx) {
+ if (lineno == info_file->lines.flat_map[l_idx].line) {
+ return lineno;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int32_t
+get_break_index(mrb_debug_context *dbg, uint32_t bpno)
+{
+ uint32_t i;
+ int32_t index;
+ char hit = FALSE;
+
+ for(i = 0 ; i < dbg->bpnum; i++) {
+ if (dbg->bp[i].bpno == bpno) {
+ hit = TRUE;
+ index = i;
+ break;
+ }
+ }
+
+ if (hit == FALSE) {
+ return MRB_DEBUG_BREAK_INVALID_NO;
+ }
+
+ return index;
+}
+
+static void
+free_breakpoint(mrb_state *mrb, mrb_debug_breakpoint *bp)
+{
+ switch(bp->type) {
+ case MRB_DEBUG_BPTYPE_LINE:
+ mrb_free(mrb, (void*)bp->point.linepoint.file);
+ break;
+ case MRB_DEBUG_BPTYPE_METHOD:
+ mrb_free(mrb, (void*)bp->point.methodpoint.method_name);
+ if (bp->point.methodpoint.class_name != NULL) {
+ mrb_free(mrb, (void*)bp->point.methodpoint.class_name);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static uint16_t
+check_file_lineno(struct mrb_irep *irep, const char *file, uint16_t lineno)
+{
+ mrb_irep_debug_info_file *info_file;
+ uint16_t result = 0;
+ uint16_t f_idx;
+ uint16_t fix_lineno;
+ uint16_t i;
+
+ for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) {
+ info_file = irep->debug_info->files[f_idx];
+ if (!strcmp(info_file->filename, file)) {
+ result = MRB_DEBUG_BP_FILE_OK;
+
+ fix_lineno = check_lineno(info_file, lineno);
+ if (fix_lineno != 0) {
+ return result | MRB_DEBUG_BP_LINENO_OK;
+ }
+ }
+ for (i=0; i < irep->rlen; ++i) {
+ result |= check_file_lineno(irep->reps[i], file, lineno);
+ if (result == (MRB_DEBUG_BP_FILE_OK | MRB_DEBUG_BP_LINENO_OK)) {
+ return result;
+ }
+ }
+ }
+ return result;
+}
+
+static int32_t
+compare_break_method(mrb_state *mrb, mrb_debug_breakpoint *bp, struct RClass *class_obj, mrb_sym method_sym, mrb_bool* isCfunc)
+{
+ const char* class_name;
+ const char* method_name;
+ struct RProc* m;
+ struct RClass* sc;
+ const char* sn;
+ mrb_sym ssym;
+ mrb_debug_methodpoint *method_p;
+ mrb_bool is_defined;
+
+ method_name = mrb_sym2name(mrb, method_sym);
+
+ method_p = &bp->point.methodpoint;
+ if (strcmp(method_p->method_name, method_name) == 0) {
+ class_name = mrb_class_name(mrb, class_obj);
+ if (class_name == NULL) {
+ if (method_p->class_name == NULL) {
+ return bp->bpno;
+ }
+ }
+ else if (method_p->class_name != NULL) {
+ m = mrb_method_search_vm(mrb, &class_obj, method_sym);
+ if (m == NULL) {
+ return MRB_DEBUG_OK;
+ }
+ if (MRB_PROC_CFUNC_P(m)) {
+ *isCfunc = TRUE;
+ }
+
+ is_defined = mrb_class_defined(mrb, method_p->class_name);
+ if (is_defined == FALSE) {
+ return MRB_DEBUG_OK;
+ }
+
+ sc = mrb_class_get(mrb, method_p->class_name);
+ ssym = mrb_symbol(mrb_check_intern_cstr(mrb, method_p->method_name));
+ m = mrb_method_search_vm(mrb, &sc, ssym);
+ if (m == NULL) {
+ return MRB_DEBUG_OK;
+ }
+
+ class_name = mrb_class_name(mrb, class_obj);
+ sn = mrb_class_name(mrb, sc);
+ if (strcmp(sn, class_name) == 0) {
+ return bp->bpno;
+ }
+ }
+ }
+ return MRB_DEBUG_OK;
+}
+
+int32_t
+mrb_debug_set_break_line(mrb_state *mrb, mrb_debug_context *dbg, const char *file, uint16_t lineno)
+{
+ int32_t index;
+ char* set_file;
+ uint16_t result;
+
+ if ((mrb == NULL)||(dbg == NULL)||(file == NULL)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ if (dbg->bpnum >= MAX_BREAKPOINT) {
+ return MRB_DEBUG_BREAK_NUM_OVER;
+ }
+
+ if (dbg->next_bpno > MAX_BREAKPOINTNO) {
+ return MRB_DEBUG_BREAK_NO_OVER;
+ }
+
+ /* file and lineno check (line type mrb_debug_line_ary only.) */
+ result = check_file_lineno(dbg->root_irep, file, lineno);
+ if (result == 0) {
+ return MRB_DEBUG_BREAK_INVALID_FILE;
+ }
+ else if (result == MRB_DEBUG_BP_FILE_OK) {
+ return MRB_DEBUG_BREAK_INVALID_LINENO;
+ }
+
+ set_file = mrb_malloc(mrb, strlen(file) + 1);
+
+ index = dbg->bpnum;
+ dbg->bp[index].bpno = dbg->next_bpno;
+ dbg->next_bpno++;
+ dbg->bp[index].enable = TRUE;
+ dbg->bp[index].type = MRB_DEBUG_BPTYPE_LINE;
+ dbg->bp[index].point.linepoint.lineno = lineno;
+ dbg->bpnum++;
+
+ strncpy(set_file, file, strlen(file) + 1);
+
+ dbg->bp[index].point.linepoint.file = set_file;
+
+ return dbg->bp[index].bpno;
+}
+
+int32_t
+mrb_debug_set_break_method(mrb_state *mrb, mrb_debug_context *dbg, const char *class_name, const char *method_name)
+{
+ int32_t index;
+ char* set_class;
+ char* set_method;
+
+ if ((mrb == NULL) || (dbg == NULL) || (method_name == NULL)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ if (dbg->bpnum >= MAX_BREAKPOINT) {
+ return MRB_DEBUG_BREAK_NUM_OVER;
+ }
+
+ if (dbg->next_bpno > MAX_BREAKPOINTNO) {
+ return MRB_DEBUG_BREAK_NO_OVER;
+ }
+
+ if (class_name != NULL) {
+ set_class = mrb_malloc(mrb, strlen(class_name) + 1);
+ strncpy(set_class, class_name, strlen(class_name) + 1);
+ }
+ else {
+ set_class = NULL;
+ }
+
+ set_method = mrb_malloc(mrb, strlen(method_name) + 1);
+
+ strncpy(set_method, method_name, strlen(method_name) + 1);
+
+ index = dbg->bpnum;
+ dbg->bp[index].bpno = dbg->next_bpno;
+ dbg->next_bpno++;
+ dbg->bp[index].enable = TRUE;
+ dbg->bp[index].type = MRB_DEBUG_BPTYPE_METHOD;
+ dbg->bp[index].point.methodpoint.method_name = set_method;
+ dbg->bp[index].point.methodpoint.class_name = set_class;
+ dbg->bpnum++;
+
+ return dbg->bp[index].bpno;
+}
+
+int32_t
+mrb_debug_get_breaknum(mrb_state *mrb, mrb_debug_context *dbg)
+{
+ if ((mrb == NULL) || (dbg == NULL)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ return dbg->bpnum;
+}
+
+int32_t
+mrb_debug_get_break_all(mrb_state *mrb, mrb_debug_context *dbg, uint32_t size, mrb_debug_breakpoint *bp)
+{
+ uint32_t get_size = 0;
+
+ if ((mrb == NULL) || (dbg == NULL) || (bp == NULL)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ if (dbg->bpnum >= size) {
+ get_size = size;
+ }
+ else {
+ get_size = dbg->bpnum;
+ }
+
+ memcpy(bp, dbg->bp, sizeof(mrb_debug_breakpoint) * get_size);
+
+ return get_size;
+}
+
+int32_t
+mrb_debug_get_break(mrb_state *mrb, mrb_debug_context *dbg, uint32_t bpno, mrb_debug_breakpoint *bp)
+{
+ int32_t index;
+
+ if ((mrb == NULL) || (dbg == NULL) || (bp == NULL)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ index = get_break_index(dbg, bpno);
+ if (index == MRB_DEBUG_BREAK_INVALID_NO) {
+ return MRB_DEBUG_BREAK_INVALID_NO;
+ }
+
+ bp->bpno = dbg->bp[index].bpno;
+ bp->enable = dbg->bp[index].enable;
+ bp->point = dbg->bp[index].point;
+ bp->type = dbg->bp[index].type;
+
+ return 0;
+}
+
+int32_t
+mrb_debug_delete_break(mrb_state *mrb, mrb_debug_context *dbg, uint32_t bpno)
+{
+ uint32_t i;
+ int32_t index;
+
+ if ((mrb == NULL) ||(dbg == NULL)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ index = get_break_index(dbg, bpno);
+ if (index == MRB_DEBUG_BREAK_INVALID_NO) {
+ return MRB_DEBUG_BREAK_INVALID_NO;
+ }
+
+ free_breakpoint(mrb, &dbg->bp[index]);
+
+ for(i = index ; i < dbg->bpnum; i++) {
+ if ((i + 1) == dbg->bpnum) {
+ memset(&dbg->bp[i], 0, sizeof(mrb_debug_breakpoint));
+ }
+ else {
+ memcpy(&dbg->bp[i], &dbg->bp[i + 1], sizeof(mrb_debug_breakpoint));
+ }
+ }
+
+ dbg->bpnum--;
+
+ return MRB_DEBUG_OK;
+}
+
+int32_t
+mrb_debug_delete_break_all(mrb_state *mrb, mrb_debug_context *dbg)
+{
+ uint32_t i;
+
+ if ((mrb == NULL) || (dbg == NULL)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ for(i = 0 ; i < dbg->bpnum ; i++) {
+ free_breakpoint(mrb, &dbg->bp[i]);
+ }
+
+ dbg->bpnum = 0;
+
+ return MRB_DEBUG_OK;
+}
+
+int32_t
+mrb_debug_enable_break(mrb_state *mrb, mrb_debug_context *dbg, uint32_t bpno)
+{
+ int32_t index = 0;
+
+ if ((mrb == NULL) || (dbg == NULL)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ index = get_break_index(dbg, bpno);
+ if (index == MRB_DEBUG_BREAK_INVALID_NO) {
+ return MRB_DEBUG_BREAK_INVALID_NO;
+ }
+
+ dbg->bp[index].enable = TRUE;
+
+ return MRB_DEBUG_OK;
+}
+
+int32_t
+mrb_debug_enable_break_all(mrb_state *mrb, mrb_debug_context *dbg)
+{
+ uint32_t i;
+
+ if ((mrb == NULL) || (dbg == NULL)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ for(i = 0 ; i < dbg->bpnum; i++) {
+ dbg->bp[i].enable = TRUE;
+ }
+
+ return MRB_DEBUG_OK;
+}
+
+int32_t
+mrb_debug_disable_break(mrb_state *mrb, mrb_debug_context *dbg, uint32_t bpno)
+{
+ int32_t index = 0;
+
+ if ((mrb == NULL) || (dbg == NULL)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ index = get_break_index(dbg, bpno);
+ if (index == MRB_DEBUG_BREAK_INVALID_NO) {
+ return MRB_DEBUG_BREAK_INVALID_NO;
+ }
+
+ dbg->bp[index].enable = FALSE;
+
+ return MRB_DEBUG_OK;
+}
+
+int32_t
+mrb_debug_disable_break_all(mrb_state *mrb, mrb_debug_context *dbg)
+{
+ uint32_t i;
+
+ if ((mrb == NULL) || (dbg == NULL)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ for(i = 0 ; i < dbg->bpnum; i++) {
+ dbg->bp[i].enable = FALSE;
+ }
+
+ return MRB_DEBUG_OK;
+}
+
+static mrb_bool
+check_start_pc_for_line(mrb_irep *irep, mrb_code *pc, uint16_t line)
+{
+ if (pc > irep->iseq) {
+ if (line == mrb_debug_get_line(irep, pc - irep->iseq - 1)) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+int32_t
+mrb_debug_check_breakpoint_line(mrb_state *mrb, mrb_debug_context *dbg, const char *file, uint16_t line)
+{
+ mrb_debug_breakpoint *bp;
+ mrb_debug_linepoint *line_p;
+ uint32_t i;
+
+ if ((mrb == NULL) || (dbg == NULL) || (file == NULL) || (line <= 0)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ if (!check_start_pc_for_line(dbg->irep, dbg->pc, line)) {
+ return MRB_DEBUG_OK;
+ }
+
+ bp = dbg->bp;
+ for(i=0; i<dbg->bpnum; i++) {
+ switch (bp->type) {
+ case MRB_DEBUG_BPTYPE_LINE:
+ if (bp->enable == TRUE) {
+ line_p = &bp->point.linepoint;
+ if ((strcmp(line_p->file, file) == 0) && (line_p->lineno == line)) {
+ return bp->bpno;
+ }
+ }
+ break;
+ case MRB_DEBUG_BPTYPE_METHOD:
+ break;
+ case MRB_DEBUG_BPTYPE_NONE:
+ default:
+ return MRB_DEBUG_OK;
+ }
+ bp++;
+ }
+ return MRB_DEBUG_OK;
+}
+
+
+int32_t
+mrb_debug_check_breakpoint_method(mrb_state *mrb, mrb_debug_context *dbg, struct RClass *class_obj, mrb_sym method_sym, mrb_bool* isCfunc)
+{
+ mrb_debug_breakpoint *bp;
+ int32_t bpno;
+ uint32_t i;
+
+ if ((mrb == NULL) || (dbg == NULL) || (class_obj == NULL)) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ bp = dbg->bp;
+ for(i=0; i<dbg->bpnum; i++) {
+ if (bp->type == MRB_DEBUG_BPTYPE_METHOD) {
+ if (bp->enable == TRUE) {
+ bpno = compare_break_method(mrb, bp, class_obj, method_sym, isCfunc);
+ if (bpno > 0) {
+ return bpno;
+ }
+ }
+ }
+ else if (bp->type == MRB_DEBUG_BPTYPE_NONE) {
+ break;
+ }
+ bp++;
+ }
+
+ return 0;
+}
+
+
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h
new file mode 100644
index 00000000..08f1d808
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h
@@ -0,0 +1,26 @@
+/*
+** apibreak.h
+**
+*/
+
+#ifndef APIBREAK_H_
+#define APIBREAK_H_
+
+#include <mruby.h>
+#include "mrdb.h"
+
+int32_t mrb_debug_set_break_line(mrb_state *, mrb_debug_context *, const char *, uint16_t);
+int32_t mrb_debug_set_break_method(mrb_state *, mrb_debug_context *, const char *, const char *);
+int32_t mrb_debug_get_breaknum(mrb_state *, mrb_debug_context *);
+int32_t mrb_debug_get_break_all(mrb_state *, mrb_debug_context *, uint32_t, mrb_debug_breakpoint bp[]);
+int32_t mrb_debug_get_break(mrb_state *, mrb_debug_context *, uint32_t, mrb_debug_breakpoint *);
+int32_t mrb_debug_delete_break(mrb_state *, mrb_debug_context *, uint32_t);
+int32_t mrb_debug_delete_break_all(mrb_state *, mrb_debug_context *);
+int32_t mrb_debug_enable_break(mrb_state *, mrb_debug_context *, uint32_t);
+int32_t mrb_debug_enable_break_all(mrb_state *, mrb_debug_context *);
+int32_t mrb_debug_disable_break(mrb_state *, mrb_debug_context *, uint32_t);
+int32_t mrb_debug_disable_break_all(mrb_state *, mrb_debug_context *);
+int32_t mrb_debug_check_breakpoint_line(mrb_state *, mrb_debug_context *, const char *, uint16_t);
+int32_t mrb_debug_check_breakpoint_method(mrb_state *, mrb_debug_context *, struct RClass *, mrb_sym, mrb_bool*);
+
+#endif /* APIBREAK_H_ */
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c
new file mode 100644
index 00000000..8aaa30bc
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c
@@ -0,0 +1,239 @@
+/*
+ * apilist.c
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mrdb.h"
+#include "mrdberror.h"
+#include "apilist.h"
+#include <mruby/compile.h>
+#include <mruby/irep.h>
+#include <mruby/debug.h>
+
+#define LINE_BUF_SIZE MAX_COMMAND_LINE
+
+typedef struct source_file {
+ char *path;
+ uint16_t lineno;
+ FILE *fp;
+} source_file;
+
+static void
+source_file_free(mrb_state *mrb, source_file *file)
+{
+ if (file != NULL) {
+ if (file->path != NULL) {
+ mrb_free(mrb, file->path);
+ }
+ if (file->fp != NULL) {
+ fclose(file->fp);
+ file->fp = NULL;
+ }
+ mrb_free(mrb, file);
+ }
+}
+
+static char*
+build_path(mrb_state *mrb, const char *dir, const char *base)
+{
+ int len;
+ char *path = NULL;
+
+ len = strlen(base) + 1;
+
+ if (strcmp(dir, ".")) {
+ len += strlen(dir) + sizeof("/") - 1;
+ }
+
+ path = mrb_malloc(mrb, len);
+ memset(path, 0, len);
+
+ if (strcmp(dir, ".")) {
+ strcat(path, dir);
+ strcat(path, "/");
+ }
+ strcat(path, base);
+
+ return path;
+}
+
+static char*
+dirname(mrb_state *mrb, const char *path)
+{
+ size_t len;
+ char *p, *dir;
+
+ if (path == NULL) {
+ return NULL;
+ }
+
+ p = strrchr(path, '/');
+ len = p != NULL ? (size_t)(p - path) : strlen(path);
+
+ dir = mrb_malloc(mrb, len + 1);
+ strncpy(dir, path, len);
+ dir[len] = '\0';
+
+ return dir;
+}
+
+static source_file*
+source_file_new(mrb_state *mrb, mrb_debug_context *dbg, char *filename)
+{
+ source_file *file = NULL;
+
+ file = mrb_malloc(mrb, sizeof(source_file));
+
+ memset(file, '\0', sizeof(source_file));
+ file->fp = fopen(filename, "rb");
+
+ if (file->fp == NULL) {
+ source_file_free(mrb, file);
+ return NULL;
+ }
+
+ file->lineno = 1;
+ file->path = mrb_malloc(mrb, strlen(filename) + 1);
+ strcpy(file->path, filename);
+ return file;
+}
+
+static mrb_bool
+remove_newlines(char *s, FILE *fp)
+{
+ int c;
+ char *p;
+ size_t len;
+
+ if ((len = strlen(s)) == 0) {
+ return FALSE;
+ }
+
+ p = s + len - 1;
+
+ if (*p != '\r' && *p != '\n') {
+ return FALSE;
+ }
+
+ if (*p == '\r') {
+ /* peek the next character and skip '\n' */
+ if ((c = fgetc(fp)) != '\n') {
+ ungetc(c, fp);
+ }
+ }
+
+ /* remove trailing newline characters */
+ while (s <= p && (*p == '\r' || *p == '\n')) {
+ *p-- = '\0';
+ }
+
+ return TRUE;
+}
+
+static void
+show_lines(source_file *file, uint16_t line_min, uint16_t line_max)
+{
+ char buf[LINE_BUF_SIZE];
+ int show_lineno = 1, found_newline = 0, is_printed = 0;
+
+ if (file->fp == NULL) {
+ return;
+ }
+
+ while (fgets(buf, sizeof(buf), file->fp) != NULL) {
+ found_newline = remove_newlines(buf, file->fp);
+
+ if (line_min <= file->lineno) {
+ if (show_lineno) {
+ printf("%-8d", file->lineno);
+ }
+ show_lineno = found_newline;
+ printf(found_newline ? "%s\n" : "%s", buf);
+ is_printed = 1;
+ }
+
+ if (found_newline) {
+ if (line_max < ++file->lineno) {
+ break;
+ }
+ }
+ }
+
+ if (is_printed && !found_newline) {
+ printf("\n");
+ }
+}
+
+char*
+mrb_debug_get_source(mrb_state *mrb, mrdb_state *mrdb, const char *srcpath, const char *filename)
+{
+ int i;
+ FILE *fp;
+ const char *search_path[3];
+ char *path = NULL;
+ const char *srcname = strrchr(filename, '/');
+
+ if (srcname) srcname++;
+ else srcname = filename;
+
+ search_path[0] = srcpath;
+ search_path[1] = dirname(mrb, mrb_debug_get_filename(mrdb->dbg->irep, 0));
+ search_path[2] = ".";
+
+ for (i = 0; i < 3; i++) {
+ if (search_path[i] == NULL) {
+ continue;
+ }
+
+ if ((path = build_path(mrb, search_path[i], srcname)) == NULL) {
+ continue;
+ }
+
+ if ((fp = fopen(path, "rb")) == NULL) {
+ mrb_free(mrb, path);
+ path = NULL;
+ continue;
+ }
+ fclose(fp);
+ break;
+ }
+
+ mrb_free(mrb, (void *)search_path[1]);
+
+ return path;
+}
+
+int32_t
+mrb_debug_list(mrb_state *mrb, mrb_debug_context *dbg, char *filename, uint16_t line_min, uint16_t line_max)
+{
+ char *ext;
+ source_file *file;
+
+ if (mrb == NULL || dbg == NULL || filename == NULL) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ ext = strrchr(filename, '.');
+
+ if (ext == NULL || strcmp(ext, ".rb")) {
+ printf("List command only supports .rb file.\n");
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ if (line_min > line_max) {
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+
+ if ((file = source_file_new(mrb, dbg, filename)) != NULL) {
+ show_lines(file, line_min, line_max);
+ source_file_free(mrb, file);
+ return MRB_DEBUG_OK;
+ }
+ else {
+ printf("Invalid source file named %s.\n", filename);
+ return MRB_DEBUG_INVALID_ARGUMENT;
+ }
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h
new file mode 100644
index 00000000..6c410788
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h
@@ -0,0 +1,14 @@
+/*
+ * apilist.h
+ */
+
+#ifndef APILIST_H_
+#define APILIST_H_
+
+#include <mruby.h>
+#include "mrdb.h"
+
+int32_t mrb_debug_list(mrb_state *, mrb_debug_context *, char *, uint16_t, uint16_t);
+char* mrb_debug_get_source(mrb_state *, mrdb_state *, const char *, const char *);
+
+#endif /* APILIST_H_ */
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c
new file mode 100644
index 00000000..a9c895b5
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c
@@ -0,0 +1,78 @@
+/*
+** apiprint.c
+**
+*/
+
+#include <string.h>
+#include "mrdb.h"
+#include <mruby/value.h>
+#include <mruby/class.h>
+#include <mruby/compile.h>
+#include <mruby/error.h>
+#include <mruby/numeric.h>
+#include <mruby/string.h>
+#include "apiprint.h"
+
+static void
+mrdb_check_syntax(mrb_state *mrb, mrb_debug_context *dbg, const char *expr, size_t len)
+{
+ mrbc_context *c;
+
+ c = mrbc_context_new(mrb);
+ c->no_exec = TRUE;
+ c->capture_errors = TRUE;
+ c->filename = (char*)dbg->prvfile;
+ c->lineno = dbg->prvline;
+
+ /* Load program */
+ mrb_load_nstring_cxt(mrb, expr, len, c);
+
+ mrbc_context_free(mrb, c);
+}
+
+mrb_value
+mrb_debug_eval(mrb_state *mrb, mrb_debug_context *dbg, const char *expr, size_t len, mrb_bool *exc)
+{
+ void (*tmp)(struct mrb_state *, struct mrb_irep *, mrb_code *, mrb_value *);
+ mrb_value ruby_code;
+ mrb_value s;
+ mrb_value v;
+ mrb_value recv;
+
+ /* disable code_fetch_hook */
+ tmp = mrb->code_fetch_hook;
+ mrb->code_fetch_hook = NULL;
+
+ mrdb_check_syntax(mrb, dbg, expr, len);
+ if (mrb->exc) {
+ v = mrb_obj_value(mrb->exc);
+ mrb->exc = 0;
+ }
+ else {
+ /*
+ * begin
+ * expr
+ * rescue => e
+ * e
+ * end
+ */
+ ruby_code = mrb_str_new_lit(mrb, "begin\n");
+ ruby_code = mrb_str_cat(mrb, ruby_code, expr, len);
+ ruby_code = mrb_str_cat_lit(mrb, ruby_code, "\nrescue => e\ne\nend");
+
+ recv = dbg->regs[0];
+
+ v = mrb_funcall(mrb, recv, "instance_eval", 1, ruby_code);
+ }
+
+ if (exc) {
+ *exc = mrb_obj_is_kind_of(mrb, v, mrb->eException_class);
+ }
+
+ s = mrb_funcall(mrb, v, "inspect", 0);
+
+ /* enable code_fetch_hook */
+ mrb->code_fetch_hook = tmp;
+
+ return s;
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h
new file mode 100644
index 00000000..e256f626
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h
@@ -0,0 +1,13 @@
+/*
+ * apiprint.h
+ */
+
+#ifndef APIPRINT_H_
+#define APIPRINT_H_
+
+#include <mruby.h>
+#include "mrdb.h"
+
+mrb_value mrb_debug_eval(mrb_state*, mrb_debug_context*, const char*, size_t, mrb_bool*);
+
+#endif /* APIPRINT_H_ */
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c
new file mode 100644
index 00000000..8e590175
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c
@@ -0,0 +1,436 @@
+/*
+** cmdbreak.c
+**
+*/
+
+#include <ctype.h>
+#include <string.h>
+#include <mruby.h>
+#include <mruby/dump.h>
+#include <mruby/debug.h>
+#include <mruby/string.h>
+#include "mrdb.h"
+#include "mrdberror.h"
+#include "apibreak.h"
+
+#define BREAK_SET_MSG_LINE "Breakpoint %d: file %s, line %d.\n"
+#define BREAK_SET_MSG_METHOD "Breakpoint %d: method %s.\n"
+#define BREAK_SET_MSG_CLASS_METHOD "Breakpoint %d: class %s, method %s.\n"
+#define BREAK_INFO_MSG_HEADER "Num Type Enb What"
+#define BREAK_INFO_MSG_LINEBREAK "%-8ubreakpoint %s at %s:%u\n"
+#define BREAK_INFO_MSG_METHODBREAK "%-8ubreakpoint %s in %s:%s\n"
+#define BREAK_INFO_MSG_METHODBREAK_NOCLASS "%-8ubreakpoint %s in %s\n"
+#define BREAK_INFO_MSG_ENABLE "y"
+#define BREAK_INFO_MSG_DISABLE "n"
+
+#define BREAK_ERR_MSG_INVALIDARG "Internal error."
+#define BREAK_ERR_MSG_BLANK "Try \'help break\' for more information."
+#define BREAK_ERR_MSG_RANGEOVER "The line number range is from 1 to 65535."
+#define BREAK_ERR_MSG_NUMOVER "Exceeded the setable number of breakpoint."
+#define BREAK_ERR_MSG_NOOVER "Breakno is over the available number.Please 'quit' and restart mrdb."
+#define BREAK_ERR_MSG_INVALIDSTR "String \'%s\' is invalid.\n"
+#define BREAK_ERR_MSG_INVALIDLINENO "Line %d in file \"%s\" is unavailable.\n"
+#define BREAK_ERR_MSG_INVALIDCLASS "Class name \'%s\' is invalid.\n"
+#define BREAK_ERR_MSG_INVALIDMETHOD "Method name \'%s\' is invalid.\n"
+#define BREAK_ERR_MSG_INVALIDFILE "Source file named \"%s\" is unavailable.\n"
+#define BREAK_ERR_MSG_INVALIDBPNO "warning: bad breakpoint number at or near '%s'\n"
+#define BREAK_ERR_MSG_INVALIDBPNO_INFO "Args must be numbers variables."
+#define BREAK_ERR_MSG_NOBPNO "No breakpoint number %d.\n"
+#define BREAK_ERR_MSG_NOBPNO_INFO "No breakpoint matching '%d'\n"
+#define BREAK_ERR_MSG_NOBPNO_INFOALL "No breakpoints."
+
+#define LINENO_MAX_DIGIT 6
+#define BPNO_LETTER_NUM 9
+
+typedef int32_t (*all_command_func)(mrb_state *, mrb_debug_context *);
+typedef int32_t (*select_command_func)(mrb_state *, mrb_debug_context *, uint32_t);
+
+static void
+print_api_common_error(int32_t error)
+{
+ switch(error) {
+ case MRB_DEBUG_INVALID_ARGUMENT:
+ puts(BREAK_ERR_MSG_INVALIDARG);
+ break;
+ default:
+ break;
+ }
+}
+
+#undef STRTOUL
+#define STRTOUL(ul,s) { \
+ int i; \
+ ul = 0; \
+ for(i=0; ISDIGIT(s[i]); i++) ul = 10*ul + (s[i] -'0'); \
+}
+
+static int32_t
+parse_breakpoint_no(char* args)
+{
+ char* ps = args;
+ uint32_t l;
+
+ if ((*ps == '0')||(strlen(ps) >= BPNO_LETTER_NUM)) {
+ return 0;
+ }
+
+ while (!(ISBLANK(*ps)||ISCNTRL(*ps))) {
+ if (!ISDIGIT(*ps)) {
+ return 0;
+ }
+ ps++;
+ }
+
+ STRTOUL(l, args);
+ return l;
+}
+
+static mrb_bool
+exe_set_command_all(mrb_state *mrb, mrdb_state *mrdb, all_command_func func)
+{
+ int32_t ret = MRB_DEBUG_OK;
+
+ if (mrdb->wcnt == 1) {
+ ret = func(mrb, mrdb->dbg);
+ print_api_common_error(ret);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+exe_set_command_select(mrb_state *mrb, mrdb_state *mrdb, select_command_func func)
+{
+ char* ps;
+ int32_t ret = MRB_DEBUG_OK;
+ int32_t bpno = 0;
+ int32_t i;
+
+ for(i=1; i<mrdb->wcnt; i++) {
+ ps = mrdb->words[i];
+ bpno = parse_breakpoint_no(ps);
+ if (bpno == 0) {
+ printf(BREAK_ERR_MSG_INVALIDBPNO, ps);
+ break;
+ }
+ ret = func(mrb, mrdb->dbg, (uint32_t)bpno);
+ if (ret == MRB_DEBUG_BREAK_INVALID_NO) {
+ printf(BREAK_ERR_MSG_NOBPNO, bpno);
+ }
+ else if (ret != MRB_DEBUG_OK) {
+ print_api_common_error(ret);
+ }
+ }
+}
+
+mrb_debug_bptype
+check_bptype(char* args)
+{
+ char* ps = args;
+
+ if (ISBLANK(*ps)||ISCNTRL(*ps)) {
+ puts(BREAK_ERR_MSG_BLANK);
+ return MRB_DEBUG_BPTYPE_NONE;
+ }
+
+ if (!ISDIGIT(*ps)) {
+ return MRB_DEBUG_BPTYPE_METHOD;
+ }
+
+ while (!(ISBLANK(*ps)||ISCNTRL(*ps))) {
+ if (!ISDIGIT(*ps)) {
+ printf(BREAK_ERR_MSG_INVALIDSTR, args);
+ return MRB_DEBUG_BPTYPE_NONE;
+ }
+ ps++;
+ }
+
+ if ((*args == '0')||(strlen(args) >= LINENO_MAX_DIGIT)) {
+ puts(BREAK_ERR_MSG_RANGEOVER);
+ return MRB_DEBUG_BPTYPE_NONE;
+ }
+
+ return MRB_DEBUG_BPTYPE_LINE;
+}
+
+static void
+print_breakpoint(mrb_debug_breakpoint *bp)
+{
+ const char* enable_letter[] = {BREAK_INFO_MSG_DISABLE, BREAK_INFO_MSG_ENABLE};
+
+ if (bp->type == MRB_DEBUG_BPTYPE_LINE) {
+ printf(BREAK_INFO_MSG_LINEBREAK,
+ bp->bpno, enable_letter[bp->enable], bp->point.linepoint.file, bp->point.linepoint.lineno);
+ }
+ else {
+ if (bp->point.methodpoint.class_name == NULL) {
+ printf(BREAK_INFO_MSG_METHODBREAK_NOCLASS,
+ bp->bpno, enable_letter[bp->enable], bp->point.methodpoint.method_name);
+ }
+ else {
+ printf(BREAK_INFO_MSG_METHODBREAK,
+ bp->bpno, enable_letter[bp->enable], bp->point.methodpoint.class_name, bp->point.methodpoint.method_name);
+ }
+ }
+}
+
+static void
+info_break_all(mrb_state *mrb, mrdb_state *mrdb)
+{
+ int32_t bpnum = 0;
+ int32_t i = 0;
+ int32_t ret = MRB_DEBUG_OK;
+ mrb_debug_breakpoint *bp_list;
+
+ bpnum = mrb_debug_get_breaknum(mrb, mrdb->dbg);
+ if (bpnum < 0) {
+ print_api_common_error(bpnum);
+ return;
+ }
+ else if (bpnum == 0) {
+ puts(BREAK_ERR_MSG_NOBPNO_INFOALL);
+ return;
+ }
+ bp_list = (mrb_debug_breakpoint*)mrb_malloc(mrb, bpnum * sizeof(mrb_debug_breakpoint));
+
+ ret = mrb_debug_get_break_all(mrb, mrdb->dbg, (uint32_t)bpnum, bp_list);
+ if (ret < 0) {
+ print_api_common_error(ret);
+ return;
+ }
+ puts(BREAK_INFO_MSG_HEADER);
+ for(i = 0 ; i < bpnum ; i++) {
+ print_breakpoint(&bp_list[i]);
+ }
+
+ mrb_free(mrb, bp_list);
+}
+
+static void
+info_break_select(mrb_state *mrb, mrdb_state *mrdb)
+{
+ int32_t ret = MRB_DEBUG_OK;
+ int32_t bpno = 0;
+ char* ps = mrdb->command;
+ mrb_debug_breakpoint bp;
+ mrb_bool isFirst = TRUE;
+ int32_t i;
+
+ for(i=2; i<mrdb->wcnt; i++) {
+ ps = mrdb->words[i];
+ bpno = parse_breakpoint_no(ps);
+ if (bpno == 0) {
+ puts(BREAK_ERR_MSG_INVALIDBPNO_INFO);
+ break;
+ }
+
+ ret = mrb_debug_get_break(mrb, mrdb->dbg, bpno, &bp);
+ if (ret == MRB_DEBUG_BREAK_INVALID_NO) {
+ printf(BREAK_ERR_MSG_NOBPNO_INFO, bpno);
+ break;
+ }
+ else if (ret != MRB_DEBUG_OK) {
+ print_api_common_error(ret);
+ break;
+ }
+ else if (isFirst == TRUE) {
+ isFirst = FALSE;
+ puts(BREAK_INFO_MSG_HEADER);
+ }
+ print_breakpoint(&bp);
+ }
+}
+
+mrb_debug_bptype
+parse_breakcommand(mrdb_state *mrdb, const char **file, uint32_t *line, char **cname, char **method)
+{
+ mrb_debug_context *dbg = mrdb->dbg;
+ char *args;
+ char *body;
+ mrb_debug_bptype type;
+ uint32_t l;
+
+ if (mrdb->wcnt <= 1) {
+ puts(BREAK_ERR_MSG_BLANK);
+ return MRB_DEBUG_BPTYPE_NONE;
+ }
+
+ args = mrdb->words[1];
+ if ((body = strrchr(args, ':')) == NULL) {
+ body = args;
+ type = check_bptype(body);
+ }
+ else {
+ if (body == args) {
+ printf(BREAK_ERR_MSG_INVALIDSTR, args);
+ return MRB_DEBUG_BPTYPE_NONE;
+ }
+ *body = '\0';
+ type = check_bptype(++body);
+ }
+
+ switch(type) {
+ case MRB_DEBUG_BPTYPE_LINE:
+ STRTOUL(l, body);
+ if (l <= 65535) {
+ *line = l;
+ *file = (body == args)? mrb_debug_get_filename(dbg->irep, dbg->pc - dbg->irep->iseq): args;
+ }
+ else {
+ puts(BREAK_ERR_MSG_RANGEOVER);
+ type = MRB_DEBUG_BPTYPE_NONE;
+ }
+ break;
+ case MRB_DEBUG_BPTYPE_METHOD:
+ if (body == args) {
+ /* method only */
+ if (ISUPPER(*body)||ISLOWER(*body)||(*body == '_')) {
+ *method = body;
+ *cname = NULL;
+ }
+ else {
+ printf(BREAK_ERR_MSG_INVALIDMETHOD, args);
+ type = MRB_DEBUG_BPTYPE_NONE;
+ }
+ }
+ else {
+ if (ISUPPER(*args)) {
+ switch(*body) {
+ case '@': case '$': case '?': case '.': case ',': case ':':
+ case ';': case '#': case '\\': case '\'': case '\"':
+ printf(BREAK_ERR_MSG_INVALIDMETHOD, body);
+ type = MRB_DEBUG_BPTYPE_NONE;
+ break;
+ default:
+ *method = body;
+ *cname = args;
+ break;
+ }
+ }
+ else {
+ printf(BREAK_ERR_MSG_INVALIDCLASS, args);
+ type = MRB_DEBUG_BPTYPE_NONE;
+ }
+ }
+ break;
+ case MRB_DEBUG_BPTYPE_NONE:
+ default:
+ break;
+ }
+
+ return type;
+}
+
+dbgcmd_state
+dbgcmd_break(mrb_state *mrb, mrdb_state *mrdb)
+{
+ mrb_debug_bptype type;
+ mrb_debug_context *dbg = mrdb->dbg;
+ const char *file = NULL;
+ uint32_t line = 0;
+ char *cname = NULL;
+ char *method = NULL;
+ int32_t ret;
+
+ type = parse_breakcommand(mrdb, &file, &line, &cname, &method);
+ switch (type) {
+ case MRB_DEBUG_BPTYPE_LINE:
+ ret = mrb_debug_set_break_line(mrb, dbg, file, line);
+ break;
+ case MRB_DEBUG_BPTYPE_METHOD:
+ ret = mrb_debug_set_break_method(mrb, dbg, cname, method);
+ break;
+ case MRB_DEBUG_BPTYPE_NONE:
+ default:
+ return DBGST_PROMPT;
+ }
+
+ if (ret >= 0) {
+ if (type == MRB_DEBUG_BPTYPE_LINE) {
+ printf(BREAK_SET_MSG_LINE, ret, file, line);
+ }
+ else if ((type == MRB_DEBUG_BPTYPE_METHOD)&&(cname == NULL)) {
+ printf(BREAK_SET_MSG_METHOD, ret, method);
+ }
+ else {
+ printf(BREAK_SET_MSG_CLASS_METHOD, ret, cname, method);
+ }
+ }
+ else {
+ switch (ret) {
+ case MRB_DEBUG_BREAK_INVALID_LINENO:
+ printf(BREAK_ERR_MSG_INVALIDLINENO, line, file);
+ break;
+ case MRB_DEBUG_BREAK_INVALID_FILE:
+ printf(BREAK_ERR_MSG_INVALIDFILE, file);
+ break;
+ case MRB_DEBUG_BREAK_NUM_OVER:
+ puts(BREAK_ERR_MSG_NUMOVER);
+ break;
+ case MRB_DEBUG_BREAK_NO_OVER:
+ puts(BREAK_ERR_MSG_NOOVER);
+ break;
+ case MRB_DEBUG_INVALID_ARGUMENT:
+ puts(BREAK_ERR_MSG_INVALIDARG);
+ break;
+ case MRB_DEBUG_NOBUF:
+ puts("T.B.D.");
+ break;
+ default:
+ break;
+ }
+ }
+
+ return DBGST_PROMPT;
+}
+
+dbgcmd_state
+dbgcmd_info_break(mrb_state *mrb, mrdb_state *mrdb)
+{
+ if (mrdb->wcnt == 2) {
+ info_break_all(mrb, mrdb);
+ }
+ else {
+ info_break_select(mrb, mrdb);
+ }
+
+ return DBGST_PROMPT;
+}
+
+dbgcmd_state
+dbgcmd_delete(mrb_state *mrb, mrdb_state *mrdb)
+{
+ mrb_bool ret = FALSE;
+
+ ret = exe_set_command_all(mrb, mrdb, mrb_debug_delete_break_all);
+ if (ret != TRUE) {
+ exe_set_command_select(mrb, mrdb, mrb_debug_delete_break);
+ }
+
+ return DBGST_PROMPT;
+}
+
+dbgcmd_state
+dbgcmd_enable(mrb_state *mrb, mrdb_state *mrdb)
+{
+ mrb_bool ret = FALSE;
+
+ ret = exe_set_command_all(mrb, mrdb, mrb_debug_enable_break_all);
+ if (ret != TRUE) {
+ exe_set_command_select(mrb, mrdb, mrb_debug_enable_break);
+ }
+
+ return DBGST_PROMPT;
+}
+
+dbgcmd_state
+dbgcmd_disable(mrb_state *mrb, mrdb_state *mrdb)
+{
+ mrb_bool ret = FALSE;
+
+ ret = exe_set_command_all(mrb, mrdb, mrb_debug_disable_break_all);
+ if (ret != TRUE) {
+ exe_set_command_select(mrb, mrdb, mrb_debug_disable_break);
+ }
+ return DBGST_PROMPT;
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c
new file mode 100644
index 00000000..5984b623
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c
@@ -0,0 +1,501 @@
+/*
+** cmdmisc.c - mruby debugger miscellaneous command functions
+**
+*/
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "apilist.h"
+#include <mruby/compile.h>
+
+typedef struct help_msg {
+ const char *cmd1;
+ const char *cmd2;
+ const char *short_msg;
+ const char *long_msg;
+} help_msg;
+
+static help_msg help_msg_list[] = {
+ {
+ "b[reak]", NULL, "Set breakpoint",
+ "Usage: break [file:]line\n"
+ " break [class:]method\n"
+ "\n"
+ "Set breakpoint at specified line or method.\n"
+ "If \'[file:]line\' is specified, break at start of code for that line (in a file).\n"
+ "If \'[class:]method\' is specified, break at start of code for that method (of the class).\n"
+ },
+ {
+ "c[ontinue]", NULL, "Continue program being debugged",
+ "Usage: continue [N]\n"
+ "\n"
+ "Continue program stopped by a breakpoint.\n"
+ "If N, which is non negative value, is passed,\n"
+ "proceed program until the N-th breakpoint is coming.\n"
+ "If N is not passed, N is assumed 1.\n"
+ },
+ {
+ "d[elete]", NULL, "Delete some breakpoints",
+ "Usage: delete [bpno1 [bpno2 [... [bpnoN]]]]\n"
+ "\n"
+ "Delete some breakpoints.\n"
+ "Arguments are breakpoint numbers with spaces in between.\n"
+ "To delete all breakpoints, give no argument.\n"
+ },
+ {
+ "dis[able]", NULL, "Disable some breakpoints",
+ "Usage: disable [bpno1 [bpno2 [... [bpnoN]]]]\n"
+ "\n"
+ "Disable some breakpoints.\n"
+ "Arguments are breakpoint numbers with spaces in between.\n"
+ "To disable all breakpoints, give no argument.\n"
+ },
+ {
+ "en[able]", NULL, "Enable some breakpoints",
+ "Usage: enable [bpno1 [bpno2 [... [bpnoN]]]]\n"
+ "\n"
+ "Enable some breakpoints.\n"
+ "Arguments are breakpoint numbers with spaces in between.\n"
+ "To enable all breakpoints, give no argument.\n"
+ },
+ {
+ "ev[al]", NULL, "Evaluate expression",
+ "Usage: eval expr\n"
+ "\n"
+ "It evaluates and prints the value of the mruby expression.\n"
+ "This is equivalent to the \'print\' command.\n"
+ },
+ {
+ "h[elp]", NULL, "Print this help",
+ "Usage: help [command]\n"
+ "\n"
+ "With no arguments, help displays a short list of commands.\n"
+ "With a command name as help argument, help displays how to use that command.\n"
+ },
+ {
+ "i[nfo]", "b[reakpoints]", "Status of breakpoints",
+ "Usage: info breakpoints [bpno1 [bpno2 [... [bpnoN]]]]\n"
+ "\n"
+ "Status of specified breakpoints (all user-settable breakpoints if no argument).\n"
+ "Arguments are breakpoint numbers with spaces in between.\n"
+ },
+ {
+ "l[ist]", NULL, "List specified line",
+ "Usage: list\n"
+ " list first[,last]\n"
+ " list filename:first[,last]\n"
+ "\n"
+ "Print lines from a source file.\n"
+ "\n"
+ "With first and last, list prints lines from first to last.\n"
+ "When last is empty, it stands for ten lines away from first.\n"
+ "With filename, list prints lines in the specified source file.\n"
+ },
+ {
+ "p[rint]", NULL, "Print value of expression",
+ "Usage: print expr\n"
+ "\n"
+ "It evaluates and prints the value of the mruby expression.\n"
+ "This is equivalent to the \'eval\' command.\n"
+ },
+ {
+ "q[uit]", NULL, "Exit mrdb",
+ "Usage: quit\n"
+ "\n"
+ "Exit mrdb.\n"
+ },
+ {
+ "r[un]", NULL, "Start debugged program",
+ "Usage: run\n"
+ "\n"
+ "Start debugged program.\n"
+ },
+ {
+ "s[tep]", NULL, "Step program until it reaches a different source line",
+ "Usage: step\n"
+ "\n"
+ "Step program until it reaches a different source line.\n"
+ },
+ { NULL, NULL, NULL, NULL }
+};
+
+typedef struct listcmd_parser_state {
+ mrb_bool parse_error;
+ mrb_bool has_line_min;
+ mrb_bool has_line_max;
+ char *filename;
+ uint16_t line_min;
+ uint16_t line_max;
+} listcmd_parser_state;
+
+static listcmd_parser_state*
+listcmd_parser_state_new(mrb_state *mrb)
+{
+ listcmd_parser_state *st = mrb_malloc(mrb, sizeof(listcmd_parser_state));
+ memset(st, 0, sizeof(listcmd_parser_state));
+ return st;
+}
+
+static void
+listcmd_parser_state_free(mrb_state *mrb, listcmd_parser_state *st)
+{
+ if (st != NULL) {
+ if (st->filename != NULL) {
+ mrb_free(mrb, st->filename);
+ }
+ mrb_free(mrb, st);
+ }
+}
+
+static mrb_bool
+parse_uint(char **sp, uint16_t *n)
+{
+ char *p;
+ int i;
+
+ if (*sp == NULL || **sp == '\0') {
+ return FALSE;
+ }
+
+ for (p = *sp; *p != '\0' && ISDIGIT(*p); p++) ;
+
+ if (p != *sp && (i = atoi(*sp)) >= 0) {
+ *n = (uint16_t)i;
+ *sp = p;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static mrb_bool
+skip_char(char **sp, char c)
+{
+ if (*sp != NULL && **sp == c) {
+ ++*sp;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static mrb_bool
+parse_lineno(mrb_state *mrb, char **sp, listcmd_parser_state *st)
+{
+ if (*sp == NULL || **sp == '\0') {
+ return FALSE;
+ }
+
+ st->has_line_min = FALSE;
+ st->has_line_max = FALSE;
+
+ if (parse_uint(sp, &st->line_min)) {
+ st->has_line_min = TRUE;
+ }
+ else {
+ return FALSE;
+ }
+
+ if (skip_char(sp, ',')) {
+ if (parse_uint(sp, &st->line_max)) {
+ st->has_line_max = TRUE;
+ }
+ else {
+ st->parse_error = TRUE;
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+static mrb_bool
+parse_filename(mrb_state *mrb, char **sp, listcmd_parser_state *st)
+{
+ char *p;
+ int len;
+
+ if (st->filename != NULL) {
+ mrb_free(mrb, st->filename);
+ st->filename = NULL;
+ }
+
+ if ((p = strchr(*sp, ':')) != NULL) {
+ len = p - *sp;
+ }
+ else {
+ len = strlen(*sp);
+ }
+
+ if (len > 0) {
+ st->filename = mrb_malloc(mrb, len + 1);
+ strncpy(st->filename, *sp, len);
+ st->filename[len] = '\0';
+ *sp += len;
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+char*
+replace_ext(mrb_state *mrb, const char *filename, const char *ext)
+{
+ size_t len;
+ char *p, *s;
+
+ if (filename == NULL) {
+ return NULL;
+ }
+
+ if ((p = strrchr(filename, '.')) != NULL && strchr(p, '/') == NULL) {
+ len = p - filename;
+ }
+ else {
+ len = strlen(filename);
+ }
+
+ s = mrb_malloc(mrb, len + strlen(ext) + 1);
+ memset(s, '\0', len + strlen(ext) + 1);
+ strncpy(s, filename, len);
+ strcat(s, ext);
+
+ return s;
+}
+
+static mrb_bool
+parse_listcmd_args(mrb_state *mrb, mrdb_state *mrdb, listcmd_parser_state *st)
+{
+ char *p;
+
+ switch (mrdb->wcnt) {
+ case 2:
+ p = mrdb->words[1];
+
+ /* mrdb->words[1] ::= <lineno> | <filename> ':' <lineno> | <filename> */
+ if (!parse_lineno(mrb, &p, st)) {
+ if (parse_filename(mrb, &p, st)) {
+ if (skip_char(&p, ':')) {
+ if (!parse_lineno(mrb, &p, st)) {
+ st->parse_error = TRUE;
+ }
+ }
+ }
+ else {
+ st->parse_error = TRUE;
+ }
+ }
+ if (*p != '\0') {
+ st->parse_error = TRUE;
+ }
+ break;
+ case 1:
+ case 0:
+ /* do nothing */
+ break;
+ default:
+ st->parse_error = TRUE;
+ printf("too many arguments\n");
+ break;
+ }
+
+ if (!st->parse_error) {
+ if (!st->has_line_min) {
+ st->line_min = (!st->filename && mrdb->dbg->prvline > 0) ? mrdb->dbg->prvline : 1;
+ }
+
+ if (!st->has_line_max) {
+ st->line_max = st->line_min + 9;
+ }
+
+ if (st->filename == NULL) {
+ if (mrdb->dbg->prvfile && strcmp(mrdb->dbg->prvfile, "-")) {
+ st->filename = replace_ext(mrb, mrdb->dbg->prvfile, ".rb");
+ }
+ }
+ }
+
+ if (st->parse_error || st->filename == NULL) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static mrb_bool
+check_cmd_pattern(const char *pattern, const char *cmd)
+{
+ char *lbracket, *rbracket, *p, *q;
+
+ if (pattern == NULL && cmd == NULL) {
+ return TRUE;
+ }
+ if (pattern == NULL || cmd == NULL) {
+ return FALSE;
+ }
+ if ((lbracket = strchr(pattern, '[')) == NULL) {
+ return !strcmp(pattern, cmd);
+ }
+ if ((rbracket = strchr(pattern, ']')) == NULL) {
+ return FALSE;
+ }
+ if (strncmp(pattern, cmd, lbracket - pattern)) {
+ return FALSE;
+ }
+
+ p = lbracket + 1;
+ q = (char *)cmd + (lbracket - pattern);
+
+ for ( ; p < rbracket && *q != '\0'; p++, q++) {
+ if (*p != *q) {
+ break;
+ }
+ }
+ return *q == '\0';
+}
+
+static help_msg*
+get_help_msg(char *cmd1, char *cmd2)
+{
+ help_msg *p;
+
+ if (cmd1 == NULL) {
+ return NULL;
+ }
+ for (p = help_msg_list; p->cmd1 != NULL; p++) {
+ if (check_cmd_pattern(p->cmd1, cmd1) && check_cmd_pattern(p->cmd2, cmd2)) {
+ return p;
+ }
+ }
+ return NULL;
+}
+
+static mrb_bool
+show_short_help(void)
+{
+ help_msg *p;
+
+ printf("Commands\n");
+
+ for (p = help_msg_list; p->cmd1 != NULL; p++) {
+ if (p->cmd2 == NULL) {
+ printf(" %s -- %s\n", p->cmd1, p->short_msg);
+ }
+ else {
+ printf(" %s %s -- %s\n", p->cmd1, p->cmd2, p->short_msg);
+ }
+ }
+ return TRUE;
+}
+
+static mrb_bool
+show_long_help(char *cmd1, char *cmd2)
+{
+ help_msg *help;
+
+ if ((help = get_help_msg(cmd1, cmd2)) == NULL) {
+ return FALSE;
+ }
+ printf("%s", help->long_msg);
+ return TRUE;
+}
+
+dbgcmd_state
+dbgcmd_list(mrb_state *mrb, mrdb_state *mrdb)
+{
+ char *filename;
+ listcmd_parser_state *st = listcmd_parser_state_new(mrb);
+
+ if (parse_listcmd_args(mrb, mrdb, st)) {
+ if ((filename = mrb_debug_get_source(mrb, mrdb, mrdb->srcpath, st->filename)) == NULL) {
+ filename = st->filename;
+ }
+ mrb_debug_list(mrb, mrdb->dbg, filename, st->line_min, st->line_max);
+
+ if (filename != NULL && filename != st->filename) {
+ mrb_free(mrb, filename);
+ }
+ listcmd_parser_state_free(mrb, st);
+ }
+
+ return DBGST_PROMPT;
+}
+
+dbgcmd_state
+dbgcmd_help(mrb_state *mrb, mrdb_state *mrdb)
+{
+ mrb_bool is_valid;
+ int i;
+
+ switch (mrdb->wcnt) {
+ case 0:
+ case 1:
+ is_valid = show_short_help();
+ break;
+ case 2:
+ is_valid = show_long_help(mrdb->words[1], NULL);
+ break;
+ case 3:
+ is_valid = show_long_help(mrdb->words[1], mrdb->words[2]);
+ break;
+ default:
+ is_valid = FALSE;
+ break;
+ }
+
+ if (!is_valid) {
+ printf("Invalid command \"");
+ for (i = 1; i < mrdb->wcnt; i++) {
+ printf("%s%s", i == 1 ? "" : " ", mrdb->words[i]);
+ }
+ printf("\". Try \"help\".\n");
+ }
+
+ return DBGST_PROMPT;
+}
+
+dbgcmd_state
+dbgcmd_quit(mrb_state *mrb, mrdb_state *mrdb)
+{
+ switch (mrdb->dbg->xm) {
+ case DBG_RUN:
+ case DBG_STEP:
+ case DBG_NEXT:
+ while (1) {
+ char c;
+ int buf;
+
+ printf("The program is running. Exit anyway? (y or n) ");
+ fflush(stdout);
+
+ if ((buf = getchar()) == EOF) {
+ mrdb->dbg->xm = DBG_QUIT;
+ break;
+ }
+ c = buf;
+ while (buf != '\n' && (buf = getchar()) != EOF) ;
+
+ if (c == 'y' || c == 'Y') {
+ mrdb->dbg->xm = DBG_QUIT;
+ break;
+ }
+ else if (c == 'n' || c == 'N') {
+ break;
+ }
+ else {
+ printf("Please answer y or n.\n");
+ }
+ }
+ break;
+ default:
+ mrdb->dbg->xm = DBG_QUIT;
+ break;
+ }
+
+ if (mrdb->dbg->xm == DBG_QUIT) {
+ struct RClass *exc;
+ exc = mrb_define_class(mrb, "DebuggerExit", mrb_class_get(mrb, "Exception"));
+ mrb_raise(mrb, exc, "Exit mrdb.");
+ }
+ return DBGST_PROMPT;
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c
new file mode 100644
index 00000000..cca63671
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c
@@ -0,0 +1,58 @@
+/*
+** cmdprint.c - mruby debugger print command functions
+**
+*/
+
+#include <string.h>
+#include "mrdb.h"
+#include <mruby/value.h>
+#include <mruby/class.h>
+#include <mruby/compile.h>
+#include <mruby/error.h>
+#include <mruby/numeric.h>
+#include <mruby/string.h>
+#include "apiprint.h"
+
+dbgcmd_state
+dbgcmd_print(mrb_state *mrb, mrdb_state *mrdb)
+{
+ mrb_value expr;
+ mrb_value result;
+ mrb_value s;
+ uint8_t wcnt;
+ int ai;
+
+ if (mrdb->wcnt <= 1) {
+ puts("Parameter not specified.");
+ return DBGST_PROMPT;
+ }
+
+ ai = mrb_gc_arena_save(mrb);
+
+ /* eval expr */
+ expr = mrb_str_new_cstr(mrb, NULL);
+ for (wcnt=1; wcnt<mrdb->wcnt; wcnt++) {
+ expr = mrb_str_cat_lit(mrb, expr, " ");
+ expr = mrb_str_cat_cstr(mrb, expr, mrdb->words[wcnt]);
+ }
+
+ result = mrb_debug_eval(mrb, mrdb->dbg, RSTRING_PTR(expr), RSTRING_LEN(expr), NULL);
+
+ /* $print_no = result */
+ s = mrb_str_cat_lit(mrb, result, "\0");
+ printf("$%lu = %s\n", (unsigned long)mrdb->print_no++, RSTRING_PTR(s));
+
+ if (mrdb->print_no == 0) {
+ mrdb->print_no = 1;
+ }
+
+ mrb_gc_arena_restore(mrb, ai);
+
+ return DBGST_PROMPT;
+}
+
+dbgcmd_state
+dbgcmd_eval(mrb_state *mrb, mrdb_state *mrdb)
+{
+ return dbgcmd_print(mrb, mrdb);
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c
new file mode 100644
index 00000000..cb4c738f
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c
@@ -0,0 +1,64 @@
+/*
+** cmdrun.c - mruby debugger run command functions
+**
+*/
+
+#include <mruby/opcode.h>
+#include "mrdb.h"
+
+dbgcmd_state
+dbgcmd_run(mrb_state *mrb, mrdb_state *mrdb)
+{
+ mrb_debug_context *dbg = mrdb->dbg;
+
+ if (dbg->xm == DBG_INIT){
+ dbg->xm = DBG_RUN;
+ }
+ else {
+ dbg->xm = DBG_QUIT;
+ if (dbg->xphase == DBG_PHASE_RUNNING){
+ struct RClass *exc;
+ puts("Start it from the beginning.");
+ exc = mrb_define_class(mrb, "DebuggerRestart", mrb_class_get(mrb, "Exception"));
+ mrb_raise(mrb, exc, "Restart mrdb.");
+ }
+ }
+
+ return DBGST_RESTART;
+}
+
+dbgcmd_state
+dbgcmd_continue(mrb_state *mrb, mrdb_state *mrdb)
+{
+ mrb_debug_context *dbg = mrdb->dbg;
+ int ccnt = 1;
+
+ if (mrdb->wcnt > 1){
+ sscanf(mrdb->words[1], "%d", &ccnt);
+ }
+ dbg->ccnt = (uint16_t)(ccnt > 0 ? ccnt : 1); /* count of continue */
+
+ if (dbg->xphase == DBG_PHASE_AFTER_RUN){
+ puts("The program is not running.");
+ dbg->xm = DBG_QUIT;
+ }
+ else {
+ dbg->xm = DBG_RUN;
+ }
+ return DBGST_CONTINUE;
+}
+
+dbgcmd_state
+dbgcmd_step(mrb_state *mrb, mrdb_state *mrdb)
+{
+ mrdb->dbg->xm = DBG_STEP;
+ return DBGST_CONTINUE;
+}
+
+dbgcmd_state
+dbgcmd_next(mrb_state *mrb, mrdb_state *mrdb)
+{
+ mrdb->dbg->xm = DBG_NEXT;
+ mrdb->dbg->prvci = mrb->c->ci;
+ return DBGST_CONTINUE;
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c
new file mode 100644
index 00000000..d12dcd5d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c
@@ -0,0 +1,759 @@
+/*
+** mrdb.c - mruby debugger
+**
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include <mruby.h>
+#include <mruby/dump.h>
+#include <mruby/debug.h>
+#include <mruby/class.h>
+#include <mruby/opcode.h>
+#include <mruby/variable.h>
+
+#include "mrdb.h"
+#include "apibreak.h"
+#include "apilist.h"
+
+void mrdb_state_free(mrb_state *);
+
+static mrb_debug_context *_debug_context = NULL;
+static mrdb_state *_mrdb_state = NULL;
+
+struct _args {
+ FILE *rfp;
+ char* fname;
+ char* srcpath;
+ int argc;
+ char** argv;
+ mrb_bool mrbfile : 1;
+};
+
+typedef struct debug_command {
+ const char *cmd1;
+ const char *cmd2;
+ uint8_t len1;
+ uint8_t len2;
+ uint8_t div;
+ debug_command_id id;
+ debug_command_func func;
+} debug_command;
+
+static const debug_command debug_command_list[] = {
+ {"break", NULL, 1, 0, 0, DBGCMD_BREAK, dbgcmd_break}, /* b[reak] */
+ {"continue", NULL, 1, 0, 0, DBGCMD_CONTINUE, dbgcmd_continue}, /* c[ontinue] */
+ {"delete", NULL, 1, 0, 1, DBGCMD_DELETE, dbgcmd_delete}, /* d[elete] */
+ {"disable", NULL, 3, 0, 1, DBGCMD_DISABLE, dbgcmd_disable}, /* dis[able] */
+ {"enable", NULL, 2, 0, 1, DBGCMD_ENABLE, dbgcmd_enable}, /* en[able] */
+ {"eval", NULL, 2, 0, 0, DBGCMD_EVAL, dbgcmd_eval}, /* ev[al] */
+ {"help", NULL, 1, 0, 1, DBGCMD_HELP, dbgcmd_help}, /* h[elp] */
+ {"info", "breakpoints", 1, 1, 1, DBGCMD_INFO_BREAK, dbgcmd_info_break}, /* i[nfo] b[reakpoints] */
+ {"list", NULL, 1, 0, 1, DBGCMD_LIST, dbgcmd_list}, /* l[ist] */
+ {"print", NULL, 1, 0, 0, DBGCMD_PRINT, dbgcmd_print}, /* p[rint] */
+ {"quit", NULL, 1, 0, 0, DBGCMD_QUIT, dbgcmd_quit}, /* q[uit] */
+ {"run", NULL, 1, 0, 0, DBGCMD_RUN, dbgcmd_run}, /* r[un] */
+ {"step", NULL, 1, 0, 1, DBGCMD_STEP, dbgcmd_step}, /* s[tep] */
+ {"next", NULL, 1, 0, 1, DBGCMD_NEXT, dbgcmd_next}, /* n[ext] */
+ {NULL}
+};
+
+
+static void
+usage(const char *name)
+{
+ static const char *const usage_msg[] = {
+ "switches:",
+ "-b load and execute RiteBinary (mrb) file",
+ "-d specify source directory",
+ "--version print the version",
+ "--copyright print the copyright",
+ NULL
+ };
+ const char *const *p = usage_msg;
+
+ printf("Usage: %s [switches] programfile\n", name);
+ while (*p) {
+ printf(" %s\n", *p++);
+ }
+}
+
+static int
+parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
+{
+ char **origargv = argv;
+ static const struct _args args_zero = { 0 };
+
+ *args = args_zero;
+
+ for (argc--,argv++; argc > 0; argc--,argv++) {
+ char *item;
+ if (argv[0][0] != '-') break;
+
+ item = argv[0] + 1;
+ switch (*item++) {
+ case 'b':
+ args->mrbfile = TRUE;
+ break;
+ case 'd':
+ if (item[0]) {
+ goto append_srcpath;
+ }
+ else if (argc > 1) {
+ argc--; argv++;
+ item = argv[0];
+append_srcpath:
+ if (!args->srcpath) {
+ size_t buflen;
+ char *buf;
+
+ buflen = strlen(item) + 1;
+ buf = (char *)mrb_malloc(mrb, buflen);
+ memcpy(buf, item, buflen);
+ args->srcpath = buf;
+ }
+ else {
+ size_t srcpathlen;
+ size_t itemlen;
+
+ srcpathlen = strlen(args->srcpath);
+ itemlen = strlen(item);
+ args->srcpath =
+ (char *)mrb_realloc(mrb, args->srcpath, srcpathlen + itemlen + 2);
+ args->srcpath[srcpathlen] = '\n';
+ memcpy(args->srcpath + srcpathlen + 1, item, itemlen + 1);
+ }
+ }
+ else {
+ printf("%s: No path specified for -d\n", *origargv);
+ return EXIT_SUCCESS;
+ }
+ break;
+ case '-':
+ if (strcmp((*argv) + 2, "version") == 0) {
+ mrb_show_version(mrb);
+ exit(EXIT_SUCCESS);
+ }
+ else if (strcmp((*argv) + 2, "copyright") == 0) {
+ mrb_show_copyright(mrb);
+ exit(EXIT_SUCCESS);
+ }
+ default:
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (args->rfp == NULL) {
+ if (*argv == NULL) {
+ printf("%s: Program file not specified.\n", *origargv);
+ return EXIT_FAILURE;
+ }
+ else {
+ args->rfp = fopen(argv[0], args->mrbfile ? "rb" : "r");
+ if (args->rfp == NULL) {
+ printf("%s: Cannot open program file. (%s)\n", *origargv, *argv);
+ return EXIT_FAILURE;
+ }
+ args->fname = argv[0];
+ argc--; argv++;
+ }
+ }
+ args->argv = (char **)mrb_realloc(mrb, args->argv, sizeof(char*) * (argc + 1));
+ memcpy(args->argv, argv, (argc+1) * sizeof(char*));
+ args->argc = argc;
+
+ return EXIT_SUCCESS;
+}
+
+static void
+cleanup(mrb_state *mrb, struct _args *args)
+{
+ if (args->rfp)
+ fclose(args->rfp);
+ if (args->srcpath)
+ mrb_free(mrb, args->srcpath);
+ if (args->argv)
+ mrb_free(mrb, args->argv);
+ mrdb_state_free(mrb);
+ mrb_close(mrb);
+}
+
+static mrb_debug_context*
+mrb_debug_context_new(mrb_state *mrb)
+{
+ mrb_debug_context *dbg = mrb_malloc(mrb, sizeof(mrb_debug_context));
+
+ memset(dbg, 0, sizeof(mrb_debug_context));
+
+ dbg->xm = DBG_INIT;
+ dbg->xphase = DBG_PHASE_BEFORE_RUN;
+ dbg->next_bpno = 1;
+
+ return dbg;
+}
+
+mrb_debug_context*
+mrb_debug_context_get(mrb_state *mrb)
+{
+ if (!_debug_context) {
+ _debug_context = mrb_debug_context_new(mrb);
+ }
+ return _debug_context;
+}
+
+void
+mrb_debug_context_set(mrb_debug_context *dbg)
+{
+ _debug_context = dbg;
+}
+
+void
+mrb_debug_context_free(mrb_state *mrb)
+{
+ if (_debug_context) {
+ mrb_debug_delete_break_all(mrb, _debug_context);
+ mrb_free(mrb, _debug_context);
+ _debug_context = NULL;
+ }
+}
+
+static mrdb_state*
+mrdb_state_new(mrb_state *mrb)
+{
+ mrdb_state *mrdb = mrb_malloc(mrb, sizeof(mrdb_state));
+
+ memset(mrdb, 0, sizeof(mrdb_state));
+
+ mrdb->dbg = mrb_debug_context_get(mrb);
+ mrdb->command = mrb_malloc(mrb, MAX_COMMAND_LINE+1);
+ mrdb->print_no = 1;
+
+ return mrdb;
+}
+
+mrdb_state*
+mrdb_state_get(mrb_state *mrb)
+{
+ if (!_mrdb_state) {
+ _mrdb_state = mrdb_state_new(mrb);
+ }
+ return _mrdb_state;
+}
+
+void
+mrdb_state_set(mrdb_state *mrdb)
+{
+ _mrdb_state = mrdb;
+}
+
+void
+mrdb_state_free(mrb_state *mrb)
+{
+ mrb_debug_context_free(mrb);
+ if (_mrdb_state) {
+ mrb_free(mrb, _mrdb_state->command);
+ mrb_free(mrb, _mrdb_state);
+ _mrdb_state = NULL;
+ }
+}
+
+static char*
+get_command(mrb_state *mrb, mrdb_state *mrdb)
+{
+ int i;
+ int c;
+
+ for (i=0; i<MAX_COMMAND_LINE; i++) {
+ if ((c=getchar()) == EOF || c == '\n') break;
+ mrdb->command[i] = c;
+ }
+
+ if (i == 0 && feof(stdin)) {
+ clearerr(stdin);
+ strcpy(mrdb->command, "quit");
+ i += sizeof("quit") - 1;
+ }
+
+ if (i == MAX_COMMAND_LINE) {
+ for ( ; (c=getchar()) != EOF && c !='\n'; i++) ;
+ }
+
+ if (i > MAX_COMMAND_LINE) {
+ printf("command line too long.\n");
+ i = 0; /* discard command data */
+ }
+ mrdb->command[i] = '\0';
+
+ return mrdb->command;
+}
+
+static char*
+pick_out_word(mrb_state *mrb, char **pp)
+{
+ char *ps;
+
+ for (ps=*pp; ISBLANK(*ps); ps++) ;
+ if (*ps == '\0') {
+ return NULL;
+ }
+
+ if (*ps == '\"' || *ps == '\'') {
+ *pp = strchr(ps+1, *ps);
+ if (*pp) (*pp)++;
+ }
+ else {
+ *pp = strpbrk(ps, " \t");
+ }
+
+ if (!*pp) {
+ *pp = ps + strlen(ps);
+ }
+
+ if (**pp != '\0') {
+ **pp = '\0';
+ (*pp)++;
+ }
+
+ return ps;
+}
+
+static debug_command*
+parse_command(mrb_state *mrb, mrdb_state *mrdb, char *buf)
+{
+ debug_command *cmd = NULL;
+ char *p = buf;
+ size_t wlen;
+
+ /* get word #1 */
+ mrdb->words[0] = pick_out_word(mrb, &p);
+ if (!mrdb->words[0]) {
+ return NULL;
+ }
+ mrdb->wcnt = 1;
+ /* set remain parameter */
+ for ( ; *p && ISBLANK(*p); p++) ;
+ if (*p) {
+ mrdb->words[mrdb->wcnt++] = p;
+ }
+
+ /* check word #1 */
+ for (cmd=(debug_command*)debug_command_list; cmd->cmd1; cmd++) {
+ wlen = strlen(mrdb->words[0]);
+ if (wlen >= cmd->len1 &&
+ strncmp(mrdb->words[0], cmd->cmd1, wlen) == 0) {
+ break;
+ }
+ }
+
+ if (cmd->cmd2) {
+ if (mrdb->wcnt > 1) {
+ /* get word #2 */
+ mrdb->words[1] = pick_out_word(mrb, &p);
+ if (mrdb->words[1]) {
+ /* update remain parameter */
+ for ( ; *p && ISBLANK(*p); p++) ;
+ if (*p) {
+ mrdb->words[mrdb->wcnt++] = p;
+ }
+ }
+ }
+
+ /* check word #1,#2 */
+ for ( ; cmd->cmd1; cmd++) {
+ wlen = strlen(mrdb->words[0]);
+ if (wlen < cmd->len1 ||
+ strncmp(mrdb->words[0], cmd->cmd1, wlen)) {
+ continue;
+ }
+
+ if (!cmd->cmd2) break; /* word #1 only */
+
+ if (mrdb->wcnt == 1) continue; /* word #2 not specified */
+
+ wlen = strlen(mrdb->words[1]);
+ if (wlen >= cmd->len2 &&
+ strncmp(mrdb->words[1], cmd->cmd2, wlen) == 0) {
+ break; /* word #1 and #2 */
+ }
+ }
+ }
+
+ /* divide remain parameters */
+ if (cmd->cmd1 && cmd->div) {
+ p = mrdb->words[--mrdb->wcnt];
+ for ( ; mrdb->wcnt<MAX_COMMAND_WORD; mrdb->wcnt++) {
+ mrdb->words[mrdb->wcnt] = pick_out_word(mrb, &p);
+ if (!mrdb->words[mrdb->wcnt]) {
+ break;
+ }
+ }
+ }
+
+ return cmd->cmd1 ? cmd : NULL;
+}
+
+static void
+print_info_stopped_break(mrb_state *mrb, mrdb_state *mrdb)
+{
+ mrb_debug_breakpoint bp;
+ int32_t ret;
+ uint16_t lineno;
+ const char *file;
+ const char *method_name;
+ const char *class_name;
+
+ ret = mrb_debug_get_break(mrb, mrdb->dbg, mrdb->dbg->stopped_bpno, &bp);
+ if (ret == 0) {
+ switch(bp.type) {
+ case MRB_DEBUG_BPTYPE_LINE:
+ file = bp.point.linepoint.file;
+ lineno = bp.point.linepoint.lineno;
+ printf("Breakpoint %d, at %s:%d\n", bp.bpno, file, lineno);
+ break;
+ case MRB_DEBUG_BPTYPE_METHOD:
+ method_name = bp.point.methodpoint.method_name;
+ class_name = bp.point.methodpoint.class_name;
+ if (class_name == NULL) {
+ printf("Breakpoint %d, %s\n", bp.bpno, method_name);
+ }
+ else {
+ printf("Breakpoint %d, %s:%s\n", bp.bpno, class_name, method_name);
+ }
+ if (mrdb->dbg->isCfunc) {
+ printf("Stopped before calling the C function.\n");
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void
+print_info_stopped_step_next(mrb_state *mrb, mrdb_state *mrdb)
+{
+ const char* file = mrdb->dbg->prvfile;
+ uint16_t lineno = mrdb->dbg->prvline;
+ printf("%s:%d\n", file, lineno);
+}
+
+static void
+print_info_stopped_code(mrb_state *mrb, mrdb_state *mrdb)
+{
+ char* file = mrb_debug_get_source(mrb, mrdb, mrdb->srcpath, mrdb->dbg->prvfile);
+ uint16_t lineno = mrdb->dbg->prvline;
+ if (file != NULL) {
+ mrb_debug_list(mrb, mrdb->dbg, file, lineno, lineno);
+ mrb_free(mrb, file);
+ }
+}
+
+static void
+print_info_stopped(mrb_state *mrb, mrdb_state *mrdb)
+{
+ switch(mrdb->dbg->bm) {
+ case BRK_BREAK:
+ print_info_stopped_break(mrb, mrdb);
+ print_info_stopped_code(mrb, mrdb);
+ break;
+ case BRK_STEP:
+ case BRK_NEXT:
+ print_info_stopped_step_next(mrb, mrdb);
+ print_info_stopped_code(mrb, mrdb);
+ break;
+ default:
+ break;
+ }
+}
+
+static debug_command*
+get_and_parse_command(mrb_state *mrb, mrdb_state *mrdb)
+{
+ debug_command *cmd = NULL;
+ char *p;
+ int i;
+
+ while (!cmd) {
+ for (p=NULL; !p || *p=='\0'; ) {
+ printf("(%s:%d) ", mrdb->dbg->prvfile, mrdb->dbg->prvline);
+ fflush(stdout);
+ p = get_command(mrb, mrdb);
+ }
+
+ cmd = parse_command(mrb, mrdb, p);
+#ifdef _DBG_MRDB_PARSER_
+ for (i=0; i<mrdb->wcnt; i++) {
+ printf("%d: %s\n", i, mrdb->words[i]);
+ }
+#endif
+ if (!cmd) {
+ printf("invalid command (");
+ for (i=0; i<mrdb->wcnt; i++) {
+ if (i>0) {
+ printf(" ");
+ }
+ printf("%s", mrdb->words[i]);
+ }
+ puts(")");
+ }
+ }
+ return cmd;
+}
+
+static int32_t
+check_method_breakpoint(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value *regs)
+{
+ struct RClass* c;
+ mrb_sym sym;
+ int32_t bpno;
+ mrb_bool isCfunc;
+
+ mrb_debug_context *dbg = mrb_debug_context_get(mrb);
+
+ isCfunc = FALSE;
+ bpno = dbg->method_bpno;
+ dbg->method_bpno = 0;
+
+ switch(GET_OPCODE(*pc)) {
+ case OP_SEND:
+ case OP_SENDB:
+ c = mrb_class(mrb, regs[GETARG_A(*pc)]);
+ sym = irep->syms[GETARG_B(*pc)];
+ break;
+ case OP_SUPER:
+ c = mrb->c->ci->target_class->super;
+ sym = mrb->c->ci->mid;
+ break;
+ default:
+ sym = 0;
+ break;
+ }
+ if (sym != 0) {
+ dbg->method_bpno = mrb_debug_check_breakpoint_method(mrb, dbg, c, sym, &isCfunc);
+ if (isCfunc) {
+ bpno = dbg->method_bpno;
+ dbg->method_bpno = 0;
+ }
+ }
+ dbg->isCfunc = isCfunc;
+ return bpno;
+}
+
+static void
+mrb_code_fetch_hook(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value *regs)
+{
+ const char *file;
+ int32_t line;
+ int32_t bpno;
+
+ mrb_debug_context *dbg = mrb_debug_context_get(mrb);
+
+ mrb_assert(dbg);
+
+ dbg->irep = irep;
+ dbg->pc = pc;
+ dbg->regs = regs;
+
+ if (dbg->xphase == DBG_PHASE_RESTART) {
+ dbg->root_irep = irep;
+ dbg->prvfile = NULL;
+ dbg->prvline = 0;
+ dbg->prvci = NULL;
+ dbg->xm = DBG_RUN;
+ dbg->xphase = DBG_PHASE_RUNNING;
+ }
+
+ file = mrb_debug_get_filename(irep, pc - irep->iseq);
+ line = mrb_debug_get_line(irep, pc - irep->iseq);
+
+ switch (dbg->xm) {
+ case DBG_STEP:
+ if (!file || (dbg->prvfile == file && dbg->prvline == line)) {
+ return;
+ }
+ dbg->method_bpno = 0;
+ dbg->bm = BRK_STEP;
+ break;
+
+ case DBG_NEXT:
+ if (!file || (dbg->prvfile == file && dbg->prvline == line)) {
+ return;
+ }
+ if ((intptr_t)(dbg->prvci) < (intptr_t)(mrb->c->ci)) {
+ return;
+ }
+ dbg->prvci = NULL;
+ dbg->method_bpno = 0;
+ dbg->bm = BRK_NEXT;
+ break;
+
+ case DBG_RUN:
+ bpno = check_method_breakpoint(mrb, irep, pc, regs);
+ if (bpno > 0) {
+ dbg->stopped_bpno = bpno;
+ dbg->bm = BRK_BREAK;
+ break;
+ }
+ if (dbg->prvfile != file || dbg->prvline != line) {
+ bpno = mrb_debug_check_breakpoint_line(mrb, dbg, file, line);
+ if (bpno > 0) {
+ dbg->stopped_bpno = bpno;
+ dbg->bm = BRK_BREAK;
+ break;
+ }
+ }
+ dbg->prvfile = file;
+ dbg->prvline = line;
+ return;
+ case DBG_INIT:
+ dbg->root_irep = irep;
+ dbg->bm = BRK_INIT;
+ if (!file || line < 0) {
+ puts("Cannot get debugging information.");
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ dbg->prvfile = file;
+ dbg->prvline = line;
+
+ if (dbg->bm == BRK_BREAK && --dbg->ccnt > 0) {
+ return;
+ }
+ dbg->break_hook(mrb, dbg);
+
+ dbg->xphase = DBG_PHASE_RUNNING;
+}
+
+static mrdb_exemode
+mrb_debug_break_hook(mrb_state *mrb, mrb_debug_context *dbg)
+{
+ debug_command *cmd;
+ dbgcmd_state st = DBGST_CONTINUE;
+ mrdb_state *mrdb = mrdb_state_get(mrb);
+
+ print_info_stopped(mrb, mrdb);
+
+ while (1) {
+ cmd = get_and_parse_command(mrb, mrdb);
+ mrb_assert(cmd);
+
+ st = cmd->func(mrb, mrdb);
+
+ if ((st == DBGST_CONTINUE) || (st == DBGST_RESTART)) break;
+ }
+ return dbg->xm;
+}
+
+int
+main(int argc, char **argv)
+{
+ mrb_state *mrb = mrb_open();
+ int n = -1;
+ struct _args args;
+ mrb_value v;
+ mrdb_state *mrdb;
+ mrdb_state *mrdb_backup;
+ mrb_debug_context* dbg_backup;
+ debug_command *cmd;
+
+ l_restart:
+
+ if (mrb == NULL) {
+ fputs("Invalid mrb_state, exiting mruby\n", stderr);
+ return EXIT_FAILURE;
+ }
+
+ /* parse command parameters */
+ n = parse_args(mrb, argc, argv, &args);
+ if (n == EXIT_FAILURE || args.rfp == NULL) {
+ cleanup(mrb, &args);
+ usage(argv[0]);
+ return n;
+ }
+
+ /* initialize debugger information */
+ mrdb = mrdb_state_get(mrb);
+ mrb_assert(mrdb && mrdb->dbg);
+ mrdb->srcpath = args.srcpath;
+
+ if (mrdb->dbg->xm == DBG_QUIT) {
+ mrdb->dbg->xphase = DBG_PHASE_RESTART;
+ }
+ else {
+ mrdb->dbg->xphase = DBG_PHASE_BEFORE_RUN;
+ }
+ mrdb->dbg->xm = DBG_INIT;
+ mrdb->dbg->ccnt = 1;
+
+ /* setup hook functions */
+ mrb->code_fetch_hook = mrb_code_fetch_hook;
+ mrdb->dbg->break_hook = mrb_debug_break_hook;
+
+ if (args.mrbfile) { /* .mrb */
+ v = mrb_load_irep_file(mrb, args.rfp);
+ }
+ else { /* .rb */
+ mrbc_context *cc = mrbc_context_new(mrb);
+ mrbc_filename(mrb, cc, args.fname);
+ v = mrb_load_file_cxt(mrb, args.rfp, cc);
+ mrbc_context_free(mrb, cc);
+ }
+ if (mrdb->dbg->xm == DBG_QUIT && !mrb_undef_p(v) && mrb->exc) {
+ const char *classname = mrb_obj_classname(mrb, mrb_obj_value(mrb->exc));
+ if (!strcmp(classname, "DebuggerExit")) {
+ cleanup(mrb, &args);
+ return 0;
+ }
+ if (!strcmp(classname, "DebuggerRestart")) {
+ mrdb_backup = mrdb_state_get(mrb);
+ dbg_backup = mrb_debug_context_get(mrb);
+
+ mrdb_state_set(NULL);
+ mrb_debug_context_set(NULL);
+
+ cleanup(mrb, &args);
+ mrb = mrb_open();
+
+ mrdb_state_set(mrdb_backup);
+ mrb_debug_context_set(dbg_backup);
+
+ goto l_restart;
+ }
+ }
+ puts("mruby application exited.");
+ mrdb->dbg->xphase = DBG_PHASE_AFTER_RUN;
+ if (!mrb_undef_p(v)) {
+ if (mrb->exc) {
+ mrb_print_error(mrb);
+ }
+ else {
+ printf(" => ");
+ mrb_p(mrb, v);
+ }
+ }
+
+ mrdb->dbg->prvfile = "-";
+ mrdb->dbg->prvline = 0;
+
+ while (1) {
+ cmd = get_and_parse_command(mrb, mrdb);
+ mrb_assert(cmd);
+
+ if (cmd->id == DBGCMD_QUIT) {
+ break;
+ }
+
+ if ( cmd->func(mrb, mrdb) == DBGST_RESTART ) goto l_restart;
+ }
+
+ cleanup(mrb, &args);
+
+ return 0;
+}
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h
new file mode 100644
index 00000000..5ac12c1c
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h
@@ -0,0 +1,165 @@
+/*
+** mrdb.h - mruby debugger
+**
+*/
+
+#ifndef MRDB_H
+#define MRDB_H
+
+#include <mruby.h>
+
+#include "mrdbconf.h"
+
+#ifdef _MSC_VER
+# define __func__ __FUNCTION__
+#endif
+
+#define MAX_COMMAND_WORD (16)
+
+typedef enum debug_command_id {
+ DBGCMD_RUN,
+ DBGCMD_CONTINUE,
+ DBGCMD_NEXT,
+ DBGCMD_STEP,
+ DBGCMD_BREAK,
+ DBGCMD_INFO_BREAK,
+ DBGCMD_WATCH,
+ DBGCMD_INFO_WATCH,
+ DBGCMD_ENABLE,
+ DBGCMD_DISABLE,
+ DBGCMD_DELETE,
+ DBGCMD_PRINT,
+ DBGCMD_DISPLAY,
+ DBGCMD_INFO_DISPLAY,
+ DBGCMD_DELETE_DISPLAY,
+ DBGCMD_EVAL,
+ DBGCMD_BACKTRACE,
+ DBGCMD_LIST,
+ DBGCMD_HELP,
+ DBGCMD_QUIT,
+ DBGCMD_UNKNOWN
+} debug_command_id;
+
+typedef enum dbgcmd_state {
+ DBGST_CONTINUE,
+ DBGST_PROMPT,
+ DBGST_COMMAND_ERROR,
+ DBGST_MAX,
+ DBGST_RESTART
+} dbgcmd_state;
+
+typedef enum mrdb_exemode {
+ DBG_INIT,
+ DBG_RUN,
+ DBG_STEP,
+ DBG_NEXT,
+ DBG_QUIT,
+} mrdb_exemode;
+
+typedef enum mrdb_exephase {
+ DBG_PHASE_BEFORE_RUN,
+ DBG_PHASE_RUNNING,
+ DBG_PHASE_AFTER_RUN,
+ DBG_PHASE_RESTART,
+} mrdb_exephase;
+
+typedef enum mrdb_brkmode {
+ BRK_INIT,
+ BRK_BREAK,
+ BRK_STEP,
+ BRK_NEXT,
+ BRK_QUIT,
+} mrdb_brkmode;
+
+typedef enum {
+ MRB_DEBUG_BPTYPE_NONE,
+ MRB_DEBUG_BPTYPE_LINE,
+ MRB_DEBUG_BPTYPE_METHOD,
+} mrb_debug_bptype;
+
+struct mrb_irep;
+struct mrbc_context;
+struct mrb_debug_context;
+
+typedef struct mrb_debug_linepoint {
+ const char *file;
+ uint16_t lineno;
+} mrb_debug_linepoint;
+
+typedef struct mrb_debug_methodpoint {
+ const char *class_name;
+ const char *method_name;
+} mrb_debug_methodpoint;
+
+typedef struct mrb_debug_breakpoint {
+ uint32_t bpno;
+ uint8_t enable;
+ mrb_debug_bptype type;
+ union point {
+ mrb_debug_linepoint linepoint;
+ mrb_debug_methodpoint methodpoint;
+ } point;
+} mrb_debug_breakpoint;
+
+typedef struct mrb_debug_context {
+ struct mrb_irep *root_irep;
+ struct mrb_irep *irep;
+ mrb_code *pc;
+ mrb_value *regs;
+
+ const char *prvfile;
+ int32_t prvline;
+ mrb_callinfo *prvci;
+
+ mrdb_exemode xm;
+ mrdb_exephase xphase;
+ mrdb_brkmode bm;
+ int16_t bmi;
+
+ uint16_t ccnt;
+ uint16_t scnt;
+
+ mrb_debug_breakpoint bp[MAX_BREAKPOINT];
+ uint32_t bpnum;
+ int32_t next_bpno;
+ int32_t method_bpno;
+ int32_t stopped_bpno;
+ mrb_bool isCfunc;
+
+ mrdb_exemode (*break_hook)(mrb_state *mrb, struct mrb_debug_context *dbg);
+
+} mrb_debug_context;
+
+typedef struct mrdb_state {
+ char *command;
+ uint8_t wcnt;
+ uint8_t pi;
+ char *words[MAX_COMMAND_WORD];
+ const char *srcpath;
+ uint32_t print_no;
+
+ mrb_debug_context *dbg;
+} mrdb_state;
+
+typedef dbgcmd_state (*debug_command_func)(mrb_state*, mrdb_state*);
+
+/* cmdrun.c */
+dbgcmd_state dbgcmd_run(mrb_state*, mrdb_state*);
+dbgcmd_state dbgcmd_continue(mrb_state*, mrdb_state*);
+dbgcmd_state dbgcmd_step(mrb_state*, mrdb_state*);
+dbgcmd_state dbgcmd_next(mrb_state*, mrdb_state*);
+/* cmdbreak.c */
+dbgcmd_state dbgcmd_break(mrb_state*, mrdb_state*);
+dbgcmd_state dbgcmd_info_break(mrb_state*, mrdb_state*);
+dbgcmd_state dbgcmd_delete(mrb_state*, mrdb_state*);
+dbgcmd_state dbgcmd_enable(mrb_state*, mrdb_state*);
+dbgcmd_state dbgcmd_disable(mrb_state*, mrdb_state*);
+/* cmdprint.c */
+dbgcmd_state dbgcmd_print(mrb_state*, mrdb_state*);
+dbgcmd_state dbgcmd_eval(mrb_state*, mrdb_state*);
+/* cmdmisc.c */
+dbgcmd_state dbgcmd_list(mrb_state*, mrdb_state*);
+dbgcmd_state dbgcmd_help(mrb_state*, mrdb_state*);
+dbgcmd_state dbgcmd_quit(mrb_state*, mrdb_state*);
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdbconf.h b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdbconf.h
new file mode 100644
index 00000000..f17f9c57
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdbconf.h
@@ -0,0 +1,16 @@
+/*
+** mrdbconf.h - mruby debugger configuration
+**
+*/
+
+#ifndef MRDBCONF_H
+#define MRDBCONF_H
+
+/* configuration options: */
+/* maximum size for command buffer */
+#define MAX_COMMAND_LINE 1024
+
+/* maximum number of setable breakpoint */
+#define MAX_BREAKPOINT 5
+
+#endif
diff --git a/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdberror.h b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdberror.h
new file mode 100644
index 00000000..c7812b0d
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdberror.h
@@ -0,0 +1,20 @@
+/*
+** mrdberror.h - mruby debugger error code
+**
+*/
+
+#ifndef MRDBERROR_H
+#define MRDBERROR_H
+
+#define MRB_DEBUG_OK (0)
+#define MRB_DEBUG_NOBUF (-1)
+#define MRB_DEBUG_INVALID_ARGUMENT (-2)
+
+#define MRB_DEBUG_BREAK_INVALID_LINENO (-11)
+#define MRB_DEBUG_BREAK_INVALID_FILE (-12)
+#define MRB_DEBUG_BREAK_INVALID_NO (-13)
+#define MRB_DEBUG_BREAK_NUM_OVER (-14)
+#define MRB_DEBUG_BREAK_NO_OVER (-15)
+
+#endif
+