From be1c7e50e1e8809ea56f2c9d472eccd8ffd73a97 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 04:57:58 +0200 Subject: Adding upstream version 1.44.3. Signed-off-by: Daniel Baumann --- .../mrbgems/mruby-bin-debugger/bintest/mrdb.rb | 286 ++++++++ .../mrbgems/mruby-bin-debugger/bintest/print.rb | 701 +++++++++++++++++++ .../mruby/mrbgems/mruby-bin-debugger/mrbgem.rake | 9 + .../mruby-bin-debugger/tools/mrdb/apibreak.c | 507 ++++++++++++++ .../mruby-bin-debugger/tools/mrdb/apibreak.h | 26 + .../mruby-bin-debugger/tools/mrdb/apilist.c | 239 +++++++ .../mruby-bin-debugger/tools/mrdb/apilist.h | 14 + .../mruby-bin-debugger/tools/mrdb/apiprint.c | 78 +++ .../mruby-bin-debugger/tools/mrdb/apiprint.h | 13 + .../mruby-bin-debugger/tools/mrdb/cmdbreak.c | 436 ++++++++++++ .../mruby-bin-debugger/tools/mrdb/cmdmisc.c | 501 ++++++++++++++ .../mruby-bin-debugger/tools/mrdb/cmdprint.c | 58 ++ .../mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c | 64 ++ .../mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c | 759 +++++++++++++++++++++ .../mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h | 165 +++++ .../mruby-bin-debugger/tools/mrdb/mrdbconf.h | 16 + .../mruby-bin-debugger/tools/mrdb/mrdberror.h | 20 + 17 files changed, 3892 insertions(+) create mode 100644 web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/bintest/mrdb.rb create mode 100644 web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/bintest/print.rb create mode 100644 web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/mrbgem.rake create mode 100644 web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c create mode 100644 web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h create mode 100644 web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c create mode 100644 web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h create mode 100644 web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c create mode 100644 web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h create mode 100644 web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c create mode 100644 web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c create mode 100644 web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c create mode 100644 web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c create mode 100644 web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c create mode 100644 web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h create mode 100644 web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdbconf.h create mode 100644 web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdberror.h (limited to 'web/server/h2o/libh2o/deps/mruby/mrbgems/mruby-bin-debugger') 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 = #"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 = #"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'$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 +#include +#include +#include "mrdb.h" +#include +#include +#include +#include +#include +#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; ibpnum; 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; ibpnum; 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 +#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 +#include +#include + +#include "mrdb.h" +#include "mrdberror.h" +#include "apilist.h" +#include +#include +#include + +#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 +#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 +#include "mrdb.h" +#include +#include +#include +#include +#include +#include +#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 +#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 +#include +#include +#include +#include +#include +#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; iwcnt; 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; iwcnt; 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 +#include +#include + +#include "apilist.h" +#include + +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] ::= | ':' | */ + 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 +#include "mrdb.h" +#include +#include +#include +#include +#include +#include +#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; wcntwcnt; 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 +#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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#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; icommand[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->wcntwcnt++) { + 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; iwcnt; i++) { + printf("%d: %s\n", i, mrdb->words[i]); + } +#endif + if (!cmd) { + printf("invalid command ("); + for (i=0; iwcnt; 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 + +#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 + -- cgit v1.2.3