Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mruby
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
mruby
Commits
4e4bfb08
Commit
4e4bfb08
authored
Nov 19, 2014
by
Hiroshi Mimaki
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2640 from mruby-Forum/v1.1.0
mruby-1.1.0
parents
5c6d6309
b473043a
Changes
24
Show whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
4267 additions
and
7 deletions
+4267
-7
AUTHORS
AUTHORS
+11
-0
Rakefile
Rakefile
+10
-0
build_config.rb
build_config.rb
+25
-0
doc/debugger/README.md
doc/debugger/README.md
+341
-0
include/mruby.h
include/mruby.h
+2
-0
include/mruby/version.h
include/mruby/version.h
+6
-6
mrbgems/full-core.gembox
mrbgems/full-core.gembox
+1
-1
mrbgems/mruby-bin-debugger/bintest/mrdb.rb
mrbgems/mruby-bin-debugger/bintest/mrdb.rb
+286
-0
mrbgems/mruby-bin-debugger/bintest/print.rb
mrbgems/mruby-bin-debugger/bintest/print.rb
+701
-0
mrbgems/mruby-bin-debugger/mrbgem.rake
mrbgems/mruby-bin-debugger/mrbgem.rake
+9
-0
mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c
mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c
+529
-0
mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h
mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h
+26
-0
mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c
mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c
+232
-0
mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h
mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h
+14
-0
mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c
mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c
+78
-0
mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h
mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h
+13
-0
mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c
mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c
+426
-0
mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c
mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c
+500
-0
mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c
mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c
+58
-0
mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c
mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c
+54
-0
mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c
mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c
+746
-0
mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h
mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h
+163
-0
mrbgems/mruby-bin-debugger/tools/mrdb/mrdbconf.h
mrbgems/mruby-bin-debugger/tools/mrdb/mrdbconf.h
+16
-0
mrbgems/mruby-bin-debugger/tools/mrdb/mrdberror.h
mrbgems/mruby-bin-debugger/tools/mrdb/mrdberror.h
+20
-0
No files found.
AUTHORS
View file @
4e4bfb08
...
...
@@ -20,3 +20,14 @@ Original Authors "mruby developers" are:
Tatsuhiko Kubo
Takeshi Watanabe
Yuki Kurihara
specified non-profit corporation mruby Forum
Kazuaki Tanaka
Hiromasa Ishii
Hiroshi Mimaki
Satoshi Odawara
Mitsubishi Electric Micro-Computer Application Software Co.,Ltd.
Hiroyuki Matsuzaki
Yuhei Okazaki
Manycolors, Inc.
Shota Nakano
Yuichi Osawa
Rakefile
View file @
4e4bfb08
...
...
@@ -75,6 +75,16 @@ MRuby.each_target do |target|
FileUtils
.
cp
t
.
prerequisites
.
first
,
t
.
name
,
{
:verbose
=>
$verbose
}
end
depfiles
+=
[
install_path
]
elsif
target
==
MRuby
.
targets
[
'host-debug'
]
unless
MRuby
.
targets
[
'host'
].
gems
.
map
{
|
g
|
g
.
bins
}.
include?
([
bin
])
install_path
=
MRuby
.
targets
[
'host-debug'
].
exefile
(
"
#{
MRUBY_ROOT
}
/bin/
#{
bin
}
"
)
file
install_path
=>
exec
do
|
t
|
FileUtils
.
rm_f
t
.
name
,
{
:verbose
=>
$verbose
}
FileUtils
.
cp
t
.
prerequisites
.
first
,
t
.
name
,
{
:verbose
=>
$verbose
}
end
depfiles
+=
[
install_path
]
end
else
depfiles
+=
[
exec
]
end
...
...
build_config.rb
View file @
4e4bfb08
...
...
@@ -83,6 +83,31 @@ MRuby::Build.new do |conf|
# conf.enable_bintest
end
MRuby
::
Build
.
new
(
'host-debug'
)
do
|
conf
|
# load specific toolchain settings
# Gets set by the VS command prompts.
if
ENV
[
'VisualStudioVersion'
]
||
ENV
[
'VSINSTALLDIR'
]
toolchain
:visualcpp
else
toolchain
:gcc
end
enable_debug
# include the default GEMs
conf
.
gembox
'default'
# C compiler settings
conf
.
cc
.
defines
=
%w(ENABLE_DEBUG)
# Generate mruby debugger command (require mruby-eval)
conf
.
gem
:core
=>
"mruby-bin-debugger"
# bintest
# conf.enable_bintest
end
# Define cross build settings
# MRuby::CrossBuild.new('32bit') do |conf|
# toolchain :gcc
...
...
doc/debugger/README.md
0 → 100755
View file @
4e4bfb08
# How to use mruby debugger mrdb
copyright (c) 2014 Specified Non-Profit Coorporation mruby Forum
## 1.Summary
This file documents the method for using the mruby debugger 'mrdb'
## 2 debugging with mrdb
## 2.1 Building mrdb
The trunk of the mruby source tree can be checked out with following command/
```
bash
$
git clone https://github.com/Kumikomi-Ruby/forum-mruby.git mruby
```
Run make command
```
bash
$
cd
mruby
$
make
```
By default, make command will install debugger files into mruby/bin.
You can add the path for mrdb on your host environment with following command
```
bash
$
echo
"export PATH=
\$
PATH:MRUBY_ROOT/bin"
>>
~/.bashrc
$
source
~/.bashrc
```
*
MRUBY_ROOT is the directory in which mruby source cords will be installed.
To confirm mrdb was instaleed properly,run mrdb with --version option
```
bash
$
mrdb
--version
mruby 1.1.0
(
2014-11-19
)
```
## 2.2 Bassic Operation
### 2.2.1 debugging mruby script file(rb file) with mrdb
To invoke mruby debugger, just type mrdb.
To specify the script file ,
```
bash
$
mrdb
[
option] file name
```
For example : Debugging sample.rb
```
bash
$
mrdb sample.rb
```
You can excute shell commands listed below
|command|description|
|:-:|:--|
|run|execute programs|
|step|execute stepping|
|continue|execute continuing program|
|break|configure the breaking point|
|delete|deleting the breaking points|
|disable|disabling the breaking points|
|enable|enabling the breaking points|
|info breakpoints|showing list of the breaking points|
|print|eavaluating and printing the values of the mruby expressions in the script|
|list|displaying the source cords|
|help|showing help|
|quit|terminating the mruby debugger|
### 2.2.2 debugging mruby binary file(mrb file) with mrdb
You can debugg the mruby binary files
#### 2.2.2.1 debuggg the binary files
*
notice
To debugg mruby binary files, you need to compile mruby files with option -g.
```
bash
$
mrbc
-g
sample.rb
```
You can debugg the mruby binary files with following command and the option -b.
```
bash
$
mrdb
-b
sample.mrb
```
Then you can execute all debugger shell commands.
#### break command
you can give any breakpoint to stop the program by specifiyng the line number and method name.
And the breakpoint list will be displayed after you finished to set the breakpoint succesfully.
Usage:
```
break [file:]lineno
b [file:]lineno
break [class:]method
b [class:]method
```
The breakpoint will be numbered in serial order from 1.The number which was given to deleted breakpoint will not be given to another breakpoint again.
You can give multiple breakpoints to specified the line number and method.
Be ware that breakpoint command will not check the validity of the class name and method name.
You can see the current breakpoint information by following options.
breakpoint breakpoint number : file name. line number
breakpoint breakpoint number : [class name,] method name
#### continue command
Usage:
```
continue [N]
c [N]
```
N: the next breakpoint number
Resuming the program and will stop the program at breakpoint at N (N-1 breakpoint will be ignored)
When you run continue command without any specifying N ,Program will be stopped at next breakpoint.
Example:
```
(foo.rb:1) continue 3
```
Resuming the program and stopping the program at the third breakpoint.
#### delete command
Deleting specified breakpoint
Usage:
```
delete [breakpointno]
d [breakpointno]
```
breakpointno: breakpoint number
Example:
```
(foo.rb:1) delete
```
Deleting all brealpoint
```
(foo.rb:1) delete 1 3
```
Deleting the breakpoint 1 and 3
#### diable command
Disabling the specified breakpoint
Usage:
```
disable [breakpointno]
dis [breakpointno]
```
brealpointno: breakpoint number
Example:
```
(foo.rb:1) disable
```
Desabling all brealpoint
```
(foo.rb:1) disable 1 3
```
Disabling the breakpoint 1 and 3
#### enable command
Enababling the specified breakpoint
Usage:
```
enable [breakpointno]
e [breakpointno]
```
brealpointno: breakpoint number
Example:
```
(foo.rb:1) enable
```
Enabling all brealpoint
```
(foo.rb:1) enable 1 3
```
Enabling the breakpoint 1 and 3
#### eval command
Evaluating the string as source code and printing the value.
Same as print command, please see print command.
#### help command
Displaying the help message.
Usage:
```
help [comand]
h [command]
```
Typing help without any option will displays the command list.
#### info breakpoints command
Displaying the specified breakpoint information.
Usage:
```
info breakpoints [breakpointno]
i b [breakpointno]
```
breakpointno: breakpoint number
Typing "info breakpoints" without ant option will display all breakpoint information.
Example
```
(sample.rb:1) info breakpoints
Num Type Enb What
1 breakpoint y at sample.rb:3 -> file name,line number
2 breakpoint n in Sample_class:sample_class_method -> [class:]method name
3 breakpoint y in sample_global_method
```
Displaying specified the breakpoint number
```
(foo.rb:1) info breakpoints 1 3
Num Type Enb What
1 breakpoint y at sample.rb:3
3 breakpoint y in sample_global_method
```
#### list command
Displaying the cords of the source file.
Usage:
```
list [filename:]first[,last]
l [filename]:first[,last]
```
first: the opening row number
last : the closing row number
When you specify first , but not specify option "last" , you will get 10 rows.
When you don not specify both of first and last, you will next 10 rows.
Example:
```
Specifying file name and first row number
sample.rb:1) list sample2.rb:5
```
Specifying file name and first and last row number
```
(sample.rb:1) list sample2.rb:6,7
```
#### print command
Evaluating the string as source code and printing the value.
Usage:
```
print [expr]
p [expr]
```
expr: expression
To specify the expression is indispensableness.
The displayed expressions will be numbered in serial order from 1.
If an exception occurs, the exception information will be displayed and the debugging will be continued.
Example:
```
(sample.rb:1) print 1+2
$1 = 3
(sample.rb:1) print self
$2 = main
```
below is the case of the exception:
```
(sample.rb:1) print (1+2
$1 = SyntaxError: line 1: syntax error, unexpected $end, expecting ')'
```
#### quit command
Quitting the debugger.
Usage:
```
quit
q
```
#### run command
Running the program and stopping at the first breakpoint.
Usage:
```
run
r
```
#### step command
Running the program step by step.
When the method and the block will be invoked, the program will be stop at the first row.
The program which is developed by C language will be ignored.
period
include/mruby.h
View file @
4e4bfb08
...
...
@@ -359,6 +359,8 @@ MRB_API mrb_value mrb_obj_clone(mrb_state *mrb, mrb_value self);
#define ISALPHA(c) (ISASCII(c) && isalpha((int)(unsigned char)(c)))
#define ISDIGIT(c) (ISASCII(c) && isdigit((int)(unsigned char)(c)))
#define ISXDIGIT(c) (ISASCII(c) && isxdigit((int)(unsigned char)(c)))
#define ISBLANK(c) (ISASCII(c) && isblank((int)(unsigned char)(c)))
#define ISCNTRL(c) (ISASCII(c) && iscntrl((int)(unsigned char)(c)))
#define TOUPPER(c) (ISASCII(c) ? toupper((int)(unsigned char)(c)) : (c))
#define TOLOWER(c) (ISASCII(c) ? tolower((int)(unsigned char)(c)) : (c))
#endif
...
...
include/mruby/version.h
View file @
4e4bfb08
...
...
@@ -10,15 +10,15 @@
#define MRUBY_RUBY_VERSION "1.9"
#define MRUBY_RUBY_ENGINE "mruby"
#define MRUBY_VERSION "1.
0.1
"
#define MRUBY_VERSION "1.
1.0
"
#define MRUBY_RELEASE_MAJOR 1
#define MRUBY_RELEASE_MINOR
0
#define MRUBY_RELEASE_MINOR
1
#define MRUBY_RELEASE_TEENY 1
#define MRUBY_RELEASE_NO 10
0
01
#define MRUBY_RELEASE_DATE "2014-
01-10
"
#define MRUBY_RELEASE_NO 10
1
01
#define MRUBY_RELEASE_DATE "2014-
11-19
"
#define MRUBY_RELEASE_YEAR 2014
#define MRUBY_RELEASE_MONTH 1
#define MRUBY_RELEASE_DAY 1
0
#define MRUBY_RELEASE_MONTH 1
1
#define MRUBY_RELEASE_DAY 1
9
#define MRUBY_BIRTH_YEAR 2010
...
...
mrbgems/full-core.gembox
View file @
4e4bfb08
...
...
@@ -4,6 +4,6 @@ MRuby::GemBox.new do |conf|
Dir.glob("#{root}/mrbgems/mruby-*/mrbgem.rake") do |x|
g = File.basename File.dirname x
conf.gem :core => g unless g =~ /^mruby-(print|sprintf)$/
conf.gem :core => g unless g =~ /^mruby-(print|sprintf
|bin-debugger
)$/
end
end
mrbgems/mruby-bin-debugger/bintest/mrdb.rb
0 → 100755
View file @
4e4bfb08
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
mrbgems/mruby-bin-debugger/bintest/print.rb
0 → 100755
View file @
4e4bfb08
require
'open3'
require
'tempfile'
class
BinTest_MrubyBinDebugger
@debug1
=
false
@debug2
=
true
def
self
.
test
(
rubysource
,
testcase
)
script
,
bin
=
Tempfile
.
new
([
'test'
,
'.rb'
]),
Tempfile
.
new
([
'test'
,
'.mrb'
])
# .rb
script
.
write
rubysource
script
.
flush
# compile
`./bin/mrbc -g -o "
#{
bin
.
path
}
" "
#{
script
.
path
}
"`
# add mrdb quit
testcase
<<
{
:cmd
=>
"quit"
}
stdin_data
=
testcase
.
map
{
|
t
|
t
[
:cmd
]}.
join
(
"
\n
"
)
<<
"
\n
"
[
"bin/mrdb
#{
script
.
path
}
"
,
"bin/mrdb -b
#{
bin
.
path
}
"
].
each
do
|
cmd
|
o
,
s
=
Open3
.
capture2
(
cmd
,
:stdin_data
=>
stdin_data
)
exp_vals
=
testcase
.
map
{
|
t
|
t
.
fetch
(
:exp
,
nil
)}
=begin
if @debug1
o.split("\n").each_with_index do |i,actual|
p [i,actual]
end
end
# compare actual / expected
o.split("\n").each do |actual|
next if actual.empty?
exp = exp_vals.shift
if @debug2
a = true
a = actual.include?(exp) unless exp.nil?
p [actual, exp] unless a
end
assert_true actual.include?(exp) unless exp.nil?
end
=end
idx
=
0
exp_vals
.
each
do
|
exp
|
next
if
exp
.
nil?
idx
=
o
.
index
(
exp
,
idx
)
assert_false
idx
.
nil?
break
unless
idx
idx
+=
1
end
end
end
end
assert
(
'mruby-bin-debugger(print) invalid arguments'
)
do
# ruby source
src
=
"foo = 'foo'
\n
"
# test case
tc
=
[]
tc
<<
{
:cmd
=>
"p"
,
:exp
=>
"Parameter not specified."
}
BinTest_MrubyBinDebugger
.
test
(
src
,
tc
)
end
assert
(
'mruby-bin-debugger(print) nomal'
)
do
# ruby source
src
=
<<
"SRC"
foo = 'foo'
bar = foo
baz = bar
SRC
# test case
tc
=
[]
tc
<<
{
:cmd
=>
"s"
}
tc
<<
{
:cmd
=>
"p (1+2)"
,
:exp
=>
'$1 = 3'
}
tc
<<
{
:cmd
=>
"p foo"
,
:exp
=>
'$2 = "foo"'
}
tc
<<
{
:cmd
=>
"p foo*=2"
,
:exp
=>
'$3 = "foofoo"'
}
tc
<<
{
:cmd
=>
"s"
}
tc
<<
{
:cmd
=>
"p bar"
,
:exp
=>
'$4 = "foofoo"'
}
BinTest_MrubyBinDebugger
.
test
(
src
,
tc
)
end
assert
(
'mruby-bin-debugger(print) error'
)
do
# ruby source
src
=
"foo = 'foo'
\n
"
# test case
tc
=
[]
tc
<<
{
:cmd
=>
"p (1+2"
,
:exp
=>
'$1 = SyntaxError'
}
tc
<<
{
:cmd
=>
"p bar"
,
:exp
=>
'$2 = NoMethodError'
}
BinTest_MrubyBinDebugger
.
test
(
src
,
tc
)
end
# Kernel#instance_eval(string) does't work multiple statements.
=begin
assert('mruby-bin-debugger(print) multiple statements') do
# ruby source
src = <<"SRC"
x = 0
y = 0
z = 0
SRC
# test case
tc = []
tc << {:cmd=>"s",}
tc << {:cmd=>"p x=1;x+=2", :exp=>"3"}
tc << {:cmd=>"s",}
tc << {:cmd=>"p x", :exp=>"3"}
BinTest_MrubyBinDebugger.test(src, tc)
end
=end
assert
(
'mruby-bin-debugger(print) scope:top'
)
do
# ruby source (bp is break point)
src
=
"bp=nil
\n
"
# test case
tc
=
[]
tc
<<
{
:cmd
=>
"p self"
,
:exp
=>
'$1 = main'
}
BinTest_MrubyBinDebugger
.
test
(
src
,
tc
)
end
assert
(
'mruby-bin-debugger(print) scope:class'
)
do
# ruby source (bp is break point)
src
=
<<
"SRC"
class TestClassScope
bp = nil
end
SRC
# test case
tc
=
[]
tc
<<
{
:cmd
=>
"s"
}
tc
<<
{
:cmd
=>
"p self"
,
:exp
=>
'$1 = TestClassScope'
}
BinTest_MrubyBinDebugger
.
test
(
src
,
tc
)
end
assert
(
'mruby-bin-debugger(print) scope:module'
)
do
# ruby source (bp is break point)
src
=
<<
"SRC"
class TestModuleScope
bp = nil
end
SRC
# test case
tc
=
[]
tc
<<
{
:cmd
=>
"s"
}
tc
<<
{
:cmd
=>
"p self"
,
:exp
=>
'$1 = TestModuleScope'
}
BinTest_MrubyBinDebugger
.
test
(
src
,
tc
)
end
assert
(
'mruby-bin-debugger(print) scope:instance method'
)
do
# ruby source (bp is break point)
src
=
<<
"SRC"
class TestMethodScope
def m
bp = nil
end
end
TestMethodScope.new.m
SRC
tc
=
[]
tc
<<
{
:cmd
=>
"b 3"
}
tc
<<
{
:cmd
=>
"r"
}
tc
<<
{
:cmd
=>
"p self"
,
:exp
=>
'$1 = #<TestMethodScope:'
}
BinTest_MrubyBinDebugger
.
test
(
src
,
tc
)
end
assert
(
'mruby-bin-debugger(print) scope:class method'
)
do
# ruby source (bp is break point)
src
=
<<
"SRC"
class TestClassMethodScope
def self.cm
bp = nil
end
end
TestClassMethodScope.cm
SRC
tc
=
[]
tc
<<
{
:cmd
=>
"b 3"
}
tc
<<
{
:cmd
=>
"r"
}
tc
<<
{
:cmd
=>
"p self"
,
:exp
=>
'$1 = TestClassMethodScope'
}
BinTest_MrubyBinDebugger
.
test
(
src
,
tc
)
end
assert
(
'mruby-bin-debugger(print) scope:block'
)
do
# ruby source (bp is break point)
src
=
<<
"SRC"
1.times do
bp = nil
end
class TestBlockScope
1.times do
bp = nil
end
def m
1.times do
bp = nil
end
end
end
TestBlockScope.new.m
SRC
tc
=
[]
tc
<<
{
:cmd
=>
"b 2"
}
tc
<<
{
:cmd
=>
"b 6"
}
tc
<<
{
:cmd
=>
"b 10"
}
tc
<<
{
:cmd
=>
"c"
}
tc
<<
{
:cmd
=>
"p self"
,
:exp
=>
'$1 = main'
}
tc
<<
{
:cmd
=>
"c"
}
tc
<<
{
:cmd
=>
"p self"
,
:exp
=>
'$2 = TestBlockScope'
}
tc
<<
{
:cmd
=>
"c"
}
tc
<<
{
:cmd
=>
"p self"
,
:exp
=>
'$3 = #<TestBlockScope:'
}
BinTest_MrubyBinDebugger
.
test
(
src
,
tc
)
end
assert
(
'mruby-bin-debugger(print) same name:local variabe'
)
do
# ruby source (bp is break point)
src
=
<<
"SRC"
lv = 'top'
class TestLocalVariableName
lv = 'class'
def m
lv = 'instance method'
bp = nil
end
bp = nil
end
TestLocalVariableName.new.m
bp = nil
SRC
tc
=
[]
tc
<<
{
:cmd
=>
"b 6"
}
tc
<<
{
:cmd
=>
"b 8"
}
tc
<<
{
:cmd
=>
"b 11"
}
tc
<<
{
:cmd
=>
"r"
}
tc
<<
{
:cmd
=>
"p lv"
,
:exp
=>
'$1 = "class"'
}
tc
<<
{
:cmd
=>
"c"
}
tc
<<
{
:cmd
=>
"p lv"
,
:exp
=>
'$2 = "instance method"'
}
tc
<<
{
:cmd
=>
"c"
}
tc
<<
{
:cmd
=>
"p lv"
,
:exp
=>
'$3 = "top"'
}
BinTest_MrubyBinDebugger
.
test
(
src
,
tc
)
end
assert
(
'mruby-bin-debugger(print) same name:instance variabe'
)
do
# ruby source (bp is break point)
src
=
<<
"SRC"
@iv = 'top'
class TestInstanceVariableName
def initialize(v)
@iv = v
end
def m
bp = nil
end
end
i1 = TestInstanceVariableName.new('instance1')
i2 = TestInstanceVariableName.new('instance2')
i1.m
i2.m
bp = nil
SRC
tc
=
[]
tc
<<
{
:cmd
=>
"b 7"
}
tc
<<
{
:cmd
=>
"b 14"
}
tc
<<
{
:cmd
=>
"r"
}
tc
<<
{
:cmd
=>
"p @iv"
,
:exp
=>
'$1 = "instance1"'
}
tc
<<
{
:cmd
=>
"c"
}
tc
<<
{
:cmd
=>
"p @iv"
,
:exp
=>
'$2 = "instance2"'
}
tc
<<
{
:cmd
=>
"c"
}
tc
<<
{
:cmd
=>
"p @iv"
,
:exp
=>
'$3 = "top"'
}
BinTest_MrubyBinDebugger
.
test
(
src
,
tc
)
end
# Kernel#instance_eval(string) does't work const.
=begin
assert('mruby-bin-debugger(print) same name:const') do
# ruby source (bp is break point)
src = <<"SRC"
CONST='top'
class TestConstNameSuperClass
CONST='super class'
def m
bp = nil
end
end
class TestConstNameSubClass < TestConstNameSuperClass
CONST='sub class'
def m
bp = nil
end
end
TestConstNameSuperClass.new.m()
TestConstNameSubClass.new.m()
bp = nil
SRC
# todo: wait for 'break' to be implimented
tc = []
9.times { tc << {:cmd=>"s"} }
tc << {:cmd=>"p CONST", :exp=>"super class"}
3.times { tc << {:cmd=>"s"} }
tc << {:cmd=>"p CONST", :exp=>"sub class"}
1.times { tc << {:cmd=>"s"} }
tc << {:cmd=>"p CONST", :exp=>"top"}
BinTest_MrubyBinDebugger.test(src, tc)
end
=end
assert
(
'mruby-bin-debugger(print) Literal:Numeric'
)
do
# ruby source
src
=
"foo = 'foo'
\n
"
# test case
tc
=
[]
tc
<<
{
:cmd
=>
"p 100"
,
:exp
=>
'$1 = 100'
}
tc
<<
{
:cmd
=>
"p -0b100"
,
:exp
=>
'$2 = -4'
}
tc
<<
{
:cmd
=>
"p +0100"
,
:exp
=>
'$3 = 64'
}
tc
<<
{
:cmd
=>
"p 0x100"
,
:exp
=>
'$4 = 256'
}
tc
<<
{
:cmd
=>
"p 1_234"
,
:exp
=>
'$5 = 1234'
}
tc
<<
{
:cmd
=>
"p 0b1000_0000"
,
:exp
=>
"$6 =
#{
0b1000_0000
.
to_s
}
"
}
tc
<<
{
:cmd
=>
"p 0x1000_0000"
,
:exp
=>
"$7 =
#{
0x1000_0000
.
to_s
}
"
}
tc
<<
{
:cmd
=>
"p 3.14"
,
:exp
=>
'$8 = 3.14'
}
tc
<<
{
:cmd
=>
"p -12.3"
,
:exp
=>
'$9 = -12.3'
}
tc
<<
{
:cmd
=>
"p +12.000"
,
:exp
=>
'$10 = 12.0'
}
tc
<<
{
:cmd
=>
"p 1e4"
,
:exp
=>
'$11 = 10000.0'
}
tc
<<
{
:cmd
=>
"p -0.1e-2"
,
:exp
=>
'$12 = -0.001'
}
BinTest_MrubyBinDebugger
.
test
(
src
,
tc
)
end
assert
(
'mruby-bin-debugger(print) Literal:String'
)
do
# ruby source
src
=
<<
"SRC"
foo = 'foo'
bar = "bar"
baz = "baz"
SRC
# test case
tc
=
[]
tc
<<
{
:cmd
=>
"s"
}
tc
<<
{
:cmd
=>
"s"
}
tc
<<
{
:cmd
=>
'p "str"'
,
:exp
=>
'$1 = "str"'
}
tc
<<
{
:cmd
=>
'p "s\tt\rr\n"'
,
:exp
=>
'$2 = "s\\tt\\rr\\n"'
}
tc
<<
{
:cmd
=>
'p "\C-a\C-z"'
,
:exp
=>
'$3 = "\\001\\032"'
}
tc
<<
{
:cmd
=>
'p "#{foo+bar}"'
,
:exp
=>
'$4 = "foobar"'
}
tc
<<
{
:cmd
=>
'p \'str\''
,
:exp
=>
'$5 = "str"'
}
tc
<<
{
:cmd
=>
'p \'s\\tt\\rr\\n\''
,
:exp
=>
'$6 = "s\\\\tt\\\\rr\\\\n"'
}
tc
<<
{
:cmd
=>
'p \'\\C-a\\C-z\''
,
:exp
=>
'$7 = "\\\\C-a\\\\C-z"'
}
tc
<<
{
:cmd
=>
'p \'#{foo+bar}\''
,
:exp
=>
'$8 = "#{foo+bar}"'
}
tc
<<
{
:cmd
=>
'p %!str!'
,
:exp
=>
'$9 = "str"'
}
tc
<<
{
:cmd
=>
'p %!s\tt\rr\n!'
,
:exp
=>
'$10 = "s\\tt\\rr\\n"'
}
tc
<<
{
:cmd
=>
'p %!\C-a\C-z!'
,
:exp
=>
'$11 = "\\001\\032"'
}
tc
<<
{
:cmd
=>
'p %!#{foo+bar}!'
,
:exp
=>
'$12 = "foobar"'
}
tc
<<
{
:cmd
=>
'p %Q!str!'
,
:exp
=>
'$13 = "str"'
}
tc
<<
{
:cmd
=>
'p %Q!s\tt\rr\n!'
,
:exp
=>
'$14 = "s\\tt\\rr\\n"'
}
tc
<<
{
:cmd
=>
'p %Q!\C-a\C-z!'
,
:exp
=>
'$15 = "\\001\\032"'
}
tc
<<
{
:cmd
=>
'p %Q!#{foo+bar}!'
,
:exp
=>
'$16 = "foobar"'
}
tc
<<
{
:cmd
=>
'p %q!str!'
,
:exp
=>
'$17 = "str"'
}
tc
<<
{
:cmd
=>
'p %q!s\\tt\\rr\\n!'
,
:exp
=>
'$18 = "s\\\\tt\\\\rr\\\\n"'
}
tc
<<
{
:cmd
=>
'p %q!\\C-a\\C-z!'
,
:exp
=>
'$19 = "\\\\C-a\\\\C-z"'
}
tc
<<
{
:cmd
=>
'p %q!#{foo+bar}!'
,
:exp
=>
'$20 = "#{foo+bar}"'
}
BinTest_MrubyBinDebugger
.
test
(
src
,
tc
)
end
assert
(
'mruby-bin-debugger(print) Literal:Array'
)
do
# ruby source
src
=
<<
"SRC"
foo = 'foo'
bar = "bar"
baz = "baz"
SRC
# test case
tc
=
[]
tc
<<
{
:cmd
=>
"s"
}
tc
<<
{
:cmd
=>
"s"
}
tc
<<
{
:cmd
=>
'p []'
,
:exp
=>
'$1 = []'
}
tc
<<
{
:cmd
=>
'p [ 5, 12, 8, 10, ]'
,
:exp
=>
'$2 = [5, 12, 8, 10]'
}
tc
<<
{
:cmd
=>
'p [1,2.5,"#{foo+bar}"]'
,
:exp
=>
'$3 = [1, 2.5, "foobar"]'
}
tc
<<
{
:cmd
=>
'p %w[3.14 A\ &\ B #{foo}]'
,
:exp
=>
'$4 = ["3.14", "A & B", "#{foo}"]'
}
tc
<<
{
:cmd
=>
'p %W[3.14 A\ &\ B #{foo}]'
,
:exp
=>
'$5 = ["3.14", "A & B", "foo"]'
}
BinTest_MrubyBinDebugger
.
test
(
src
,
tc
)
end
assert
(
'mruby-bin-debugger(print) Literal:Hash'
)
do
# ruby source
src
=
<<
"SRC"
foo = 'foo'
bar = "bar"
baz = "baz"
SRC
# test case
tc
=
[]
tc
<<
{
:cmd
=>
"s"
}
tc
<<
{
:cmd
=>
"s"
}
tc
<<
{
:cmd
=>
'p {}'
,
:exp
=>
'$1 = {}'
}
tc
<<
{
:cmd
=>
'p {"one"=>1,"two"=>2}'
,
:exp
=>
'$2 = {"one"=>1, "two"=>2}'
}
tc
<<
{
:cmd
=>
'p {:eins=>"1", :zwei=>"2", }'
,
:exp
=>
'$3 = {:eins=>"1", :zwei=>"2"}'
}
tc
<<
{
:cmd
=>
'p {uno:"one", dos: 2}'
,
:exp
=>
'$4 = {:uno=>"one", :dos=>2}'
}
tc
<<
{
:cmd
=>
'p {"one"=>1, :zwei=>2, tres:3}'
,
:exp
=>
'$5 = {"one"=>1, :zwei=>2, :tres=>3}'
}
tc
<<
{
:cmd
=>
'p {:foo=>"#{foo}",:bar=>"#{bar}"}'
,
:exp
=>
'$6 = {:foo=>"foo", :bar=>"bar"}'
}
BinTest_MrubyBinDebugger
.
test
(
src
,
tc
)
end
assert
(
'mruby-bin-debugger(print) Literal:Range'
)
do
# ruby source
src
=
"foo = 'foo'
\n
"
# test case
tc
=
[]
tc
<<
{
:cmd
=>
'p 1..10'
,
:exp
=>
'$1 = 1..10'
}
tc
<<
{
:cmd
=>
'p 1...10'
,
:exp
=>
'$2 = 1...10'
}
tc
<<
{
:cmd
=>
'p 100..10'
,
:exp
=>
'$3 = 100..10'
}
tc
<<
{
:cmd
=>
'p 1 ... 10'
,
:exp
=>
'$4 = 1...10'
}
tc
<<
{
:cmd
=>
'p "1" .. "9"'
,
:exp
=>
'$5 = "1".."9"'
}
tc
<<
{
:cmd
=>
'p "A" ... "Z"'
,
:exp
=>
'$6 = "A"..."Z"'
}
BinTest_MrubyBinDebugger
.
test
(
src
,
tc
)
end
assert
(
'mruby-bin-debugger(print) Literal:Symbol'
)
do
# ruby source
src
=
<<
"SRC"
foo = 'foo'
bar = "bar"
baz = "baz"
SRC
# test case
tc
=
[]
tc
<<
{
:cmd
=>
"s"
}
tc
<<
{
:cmd
=>
"s"
}
tc
<<
{
:cmd
=>
'p :sym'
,
:exp
=>
'$1 = :sym'
}
tc
<<
{
:cmd
=>
'p :"sd"'
,
:exp
=>
'$2 = :sd'
}
tc
<<
{
:cmd
=>
"p :'ss'"
,
:exp
=>
'$3 = :ss'
}
tc
<<
{
:cmd
=>
'p :"123"'
,
:exp
=>
'$4 = :"123"'
}
tc
<<
{
:cmd
=>
'p :"#{foo} baz"'
,
:exp
=>
'$5 = :"foo baz"'
}
tc
<<
{
:cmd
=>
'p %s!symsym!'
,
:exp
=>
'$6 = :symsym'
}
BinTest_MrubyBinDebugger
.
test
(
src
,
tc
)
end
assert
(
'mruby-bin-debugger(print) Unary operation'
)
do
# ruby source
src
=
"foo = 'foo'
\n
"
# test case
tc
=
[]
tc
<<
{
:cmd
=>
'p +10'
,
:exp
=>
'$1 = 10'
}
tc
<<
{
:cmd
=>
'p -100'
,
:exp
=>
'$2 = -100'
}
tc
<<
{
:cmd
=>
'p !true'
,
:exp
=>
'$3 = false'
}
tc
<<
{
:cmd
=>
'p !false'
,
:exp
=>
'$4 = true'
}
tc
<<
{
:cmd
=>
'p !nil'
,
:exp
=>
'$5 = true'
}
tc
<<
{
:cmd
=>
'p !1'
,
:exp
=>
'$6 = false'
}
BinTest_MrubyBinDebugger
.
test
(
src
,
tc
)
end
assert
(
'mruby-bin-debugger(print) Binary operation'
)
do
# ruby source
src
=
<<
"SRC"
CONST = 100
a,b,c = 1, 5, 8
foo,bar,baz = 'foo','bar','baz'
ary = []
SRC
# test case
tc
=
[]
tc
<<
{
:cmd
=>
's'
}
tc
<<
{
:cmd
=>
's'
}
tc
<<
{
:cmd
=>
's'
}
tc
<<
{
:cmd
=>
'p a+1'
,
:exp
=>
'$1 = 2'
}
tc
<<
{
:cmd
=>
'p 2-b'
,
:exp
=>
'$2 = -3'
}
tc
<<
{
:cmd
=>
'p c * 3'
,
:exp
=>
'$3 = 24'
}
tc
<<
{
:cmd
=>
'p a/b'
,
:exp
=>
'$4 = 0.2'
}
tc
<<
{
:cmd
=>
'p c%b'
,
:exp
=>
'$5 = 3'
}
tc
<<
{
:cmd
=>
'p 2**10'
,
:exp
=>
'$6 = 1024'
}
tc
<<
{
:cmd
=>
'p ~3'
,
:exp
=>
'$7 = -4'
}
tc
<<
{
:cmd
=>
'p 1<<2'
,
:exp
=>
'$8 = 4'
}
tc
<<
{
:cmd
=>
'p 64>>5'
,
:exp
=>
'$9 = 2'
}
tc
<<
{
:cmd
=>
'p a|c'
,
:exp
=>
'$10 = 9'
}
tc
<<
{
:cmd
=>
'p a&b'
,
:exp
=>
'$11 = 1'
}
tc
<<
{
:cmd
=>
'p a^b'
,
:exp
=>
'$12 = 4'
}
tc
<<
{
:cmd
=>
'p a>b'
,
:exp
=>
'$13 = false'
}
tc
<<
{
:cmd
=>
'p a<b'
,
:exp
=>
'$14 = true'
}
tc
<<
{
:cmd
=>
'p b>=5'
,
:exp
=>
'$15 = true'
}
tc
<<
{
:cmd
=>
'p b<=5'
,
:exp
=>
'$16 = true'
}
tc
<<
{
:cmd
=>
'p "A"<=>"B"'
,
:exp
=>
'$17 = -1'
}
tc
<<
{
:cmd
=>
'p "A"=="B"'
,
:exp
=>
'$18 = false'
}
tc
<<
{
:cmd
=>
'p "A"==="B"'
,
:exp
=>
'$19 = false'
}
tc
<<
{
:cmd
=>
'p "A"!="B"'
,
:exp
=>
'$20 = true'
}
tc
<<
{
:cmd
=>
'p false || true'
,
:exp
=>
'$21 = true'
}
tc
<<
{
:cmd
=>
'p false && true'
,
:exp
=>
'$22 = false'
}
tc
<<
{
:cmd
=>
'p not nil'
,
:exp
=>
'$23 = true'
}
tc
<<
{
:cmd
=>
'p false or true'
,
:exp
=>
'$24 = true'
}
tc
<<
{
:cmd
=>
'p false and true'
,
:exp
=>
'$25 = false'
}
BinTest_MrubyBinDebugger
.
test
(
src
,
tc
)
end
assert
(
'mruby-bin-debugger(print) Ternary operation'
)
do
# ruby source
src
=
<<
"SRC"
CONST = 100
a,b,c = 1, 5, -10
foo,bar,baz = 'foo','bar','baz'
ary = []
SRC
# test case
tc
=
[]
tc
<<
{
:cmd
=>
's'
}
tc
<<
{
:cmd
=>
's'
}
tc
<<
{
:cmd
=>
's'
}
tc
<<
{
:cmd
=>
'p (a < b) ? a : b'
,
:exp
=>
'$1 = 1'
}
tc
<<
{
:cmd
=>
'p (a > b) ? a : b'
,
:exp
=>
'$2 = 5'
}
tc
<<
{
:cmd
=>
'p true ? "true" : "false"'
,
:exp
=>
'$3 = "true"'
}
tc
<<
{
:cmd
=>
'p false ? "true" : "false"'
,
:exp
=>
'$4 = "false"'
}
tc
<<
{
:cmd
=>
'p nil ? "true" : "false"'
,
:exp
=>
'$5 = "false"'
}
BinTest_MrubyBinDebugger
.
test
(
src
,
tc
)
end
assert
(
'mruby-bin-debugger(print) Substitution:simple'
)
do
# ruby source
src
=
<<
"SRC"
CONST = 100
a,b,c = 1, 5, -10
foo,bar,baz = 'foo','bar','baz'
ary = []
SRC
# test case
tc
=
[]
tc
<<
{
:cmd
=>
's'
}
tc
<<
{
:cmd
=>
's'
}
tc
<<
{
:cmd
=>
's'
}
tc
<<
{
:cmd
=>
'p a=2'
,
:exp
=>
'$1 = 2'
}
tc
<<
{
:cmd
=>
'p foo=[foo,bar,baz]'
,
:exp
=>
'$2 = ["foo", "bar", "baz"]'
}
tc
<<
{
:cmd
=>
'p undefined=-1'
,
:exp
=>
'$3 = -1'
}
tc
<<
{
:cmd
=>
'p "#{undefined}"'
,
:exp
=>
'$4 = NoMethodError'
}
BinTest_MrubyBinDebugger
.
test
(
src
,
tc
)
end
assert
(
'mruby-bin-debugger(print) Substitution:self'
)
do
# ruby source
src
=
<<
"SRC"
CONST = 100
a,b,c = 1, 5, -10
foo,bar,baz = 'foo','bar','baz'
ary = []
SRC
# test case
tc
=
[]
tc
<<
{
:cmd
=>
's'
}
tc
<<
{
:cmd
=>
's'
}
tc
<<
{
:cmd
=>
's'
}
tc
<<
{
:cmd
=>
'p a+=9'
,
:exp
=>
'$1 = 10'
}
tc
<<
{
:cmd
=>
'p b-=c'
,
:exp
=>
'$2 = 15'
}
tc
<<
{
:cmd
=>
'p bar*=2'
,
:exp
=>
'$3 = "barbar"'
}
tc
<<
{
:cmd
=>
'p a/=4'
,
:exp
=>
'$4 = 2.5'
}
tc
<<
{
:cmd
=>
'p c%=4'
,
:exp
=>
'$5 = 2'
}
tc
<<
{
:cmd
=>
'p b&=0b0101'
,
:exp
=>
'$6 = 5'
}
tc
<<
{
:cmd
=>
'p c|=0x10'
,
:exp
=>
'$7 = 18'
}
tc
<<
{
:cmd
=>
'p "#{a} #{b} #{c}"'
,
:exp
=>
'$8 = "2.5 5 18"'
}
tc
<<
{
:cmd
=>
'p "#{foo}#{bar}#{baz}"'
,
:exp
=>
'$9 = "foobarbarbaz"'
}
tc
<<
{
:cmd
=>
'p a,b,c=[10,20,30]'
,
:exp
=>
'$10 = [10, 20, 30]'
}
tc
<<
{
:cmd
=>
'p [a,b,c]'
,
:exp
=>
'$11 = [10, 20, 30]'
}
tc
<<
{
:cmd
=>
'p a,b=b,a'
,
:exp
=>
'$12 = [20, 10]'
}
tc
<<
{
:cmd
=>
'p [a,b]'
,
:exp
=>
'$13 = [20, 10]'
}
tc
<<
{
:cmd
=>
'p undefined=-1'
,
:exp
=>
'$14 = -1'
}
tc
<<
{
:cmd
=>
'p "#{undefined}"'
,
:exp
=>
'$15 = NoMethodError'
}
BinTest_MrubyBinDebugger
.
test
(
src
,
tc
)
end
assert
(
'mruby-bin-debugger(print) Substitution:multiple'
)
do
# ruby source
src
=
<<
"SRC"
CONST = 100
a,b,c = 1, 5, -10
foo,bar,baz = 'foo','bar','baz'
ary = []
SRC
# test case
tc
=
[]
tc
<<
{
:cmd
=>
's'
}
tc
<<
{
:cmd
=>
's'
}
tc
<<
{
:cmd
=>
's'
}
tc
<<
{
:cmd
=>
'p a,b=[10,20]'
,
:exp
=>
'$1 = [10, 20]'
}
tc
<<
{
:cmd
=>
'p [a,b,c]'
,
:exp
=>
'$2 = [10, 20, -10]'
}
tc
<<
{
:cmd
=>
'p foo,bar=["FOO","BAR","BAZ"]'
,
:exp
=>
'$3 = ["FOO", "BAR", "BAZ"]'
}
tc
<<
{
:cmd
=>
'p [foo,bar,baz]'
,
:exp
=>
'$4 = ["FOO", "BAR", "baz"]'
}
tc
<<
{
:cmd
=>
'p a,foo=foo,a'
,
:exp
=>
'$5 = ["FOO", 10]'
}
tc
<<
{
:cmd
=>
'p [a,foo]'
,
:exp
=>
'$6 = ["FOO", 10]'
}
# tc << {:cmd=>'p a,*b=[123, 456, 789]'}
# tc << {:cmd=>'p [a,b]', :exp=>'[123, [456, 789]]'}
BinTest_MrubyBinDebugger
.
test
(
src
,
tc
)
end
assert
(
'mruby-bin-debugger(print) Substitution:self'
)
do
# ruby source
src
=
<<
"SRC"
CONST = 100
a,b,c = 1, 5, -10
foo,bar,baz = 'foo','bar','baz'
ary = []
SRC
# test case
tc
=
[]
tc
<<
{
:cmd
=>
's'
}
tc
<<
{
:cmd
=>
's'
}
tc
<<
{
:cmd
=>
's'
}
tc
<<
{
:cmd
=>
'p a+=9'
,
:exp
=>
'$1 = 10'
}
tc
<<
{
:cmd
=>
'p b-=c'
,
:exp
=>
'$2 = 15'
}
tc
<<
{
:cmd
=>
'p bar*=2'
,
:exp
=>
'$3 = "barbar"'
}
tc
<<
{
:cmd
=>
'p a/=4'
,
:exp
=>
'$4 = 2.5'
}
tc
<<
{
:cmd
=>
'p c%=4'
,
:exp
=>
'$5 = 2'
}
tc
<<
{
:cmd
=>
'p b&=0b0101'
,
:exp
=>
'$6 = 5'
}
tc
<<
{
:cmd
=>
'p c|=0x10'
,
:exp
=>
'$7 = 18'
}
tc
<<
{
:cmd
=>
'p "#{a} #{b} #{c}"'
,
:exp
=>
'$8 = "2.5 5 18"'
}
tc
<<
{
:cmd
=>
'p "#{foo}#{bar}#{baz}"'
,
:exp
=>
'$9 = "foobarbarbaz"'
}
tc
<<
{
:cmd
=>
'p a,b,c=[10,20,30]'
,
:exp
=>
'$10 = [10, 20, 30]'
}
tc
<<
{
:cmd
=>
'p [a,b,c]'
,
:exp
=>
'$11 = [10, 20, 30]'
}
tc
<<
{
:cmd
=>
'p a,b=b,a'
,
:exp
=>
'$12 = [20, 10]'
}
tc
<<
{
:cmd
=>
'p [a,b]'
,
:exp
=>
'$13 = [20, 10]'
}
tc
<<
{
:cmd
=>
'p undefined=-1'
,
:exp
=>
'$14 = -1'
}
tc
<<
{
:cmd
=>
'p "#{undefined}"'
,
:exp
=>
'$15 = NoMethodError'
}
BinTest_MrubyBinDebugger
.
test
(
src
,
tc
)
end
mrbgems/mruby-bin-debugger/mrbgem.rake
0 → 100755
View file @
4e4bfb08
MRuby
::
Gem
::
Specification
.
new
(
'mruby-bin-debugger'
)
do
|
spec
|
spec
.
license
=
'MIT'
spec
.
author
=
'mruby developers'
spec
.
summary
=
'mruby debuggeer command'
spec
.
add_dependency
(
'mruby-eval'
,
:core
=>
'mruby-eval'
)
spec
.
bins
=
%w(mrdb)
end
mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c
0 → 100755
View file @
4e4bfb08
/*
** apibreak.c
**
*/
#include <string.h>
#include "mruby.h"
#include "mruby/irep.h"
#include "mrdb.h"
#include "mruby/debug.h"
#include "mruby/opcode.h"
#include "mruby/class.h"
#include "mruby/proc.h"
#include "mruby/variable.h"
#include "mrdberror.h"
#include "apibreak.h"
#define MAX_BREAKPOINTNO (MAX_BREAKPOINT * 1024)
#define MRB_DEBUG_BP_FILE_OK (0x0001)
#define MRB_DEBUG_BP_LINENO_OK (0x0002)
static
uint16_t
check_lineno
(
mrb_irep_debug_info_file
*
info_file
,
uint16_t
lineno
)
{
uint32_t
count
=
info_file
->
line_entry_count
;
uint16_t
l_idx
;
if
(
info_file
->
line_type
==
mrb_debug_line_ary
)
{
for
(
l_idx
=
0
;
l_idx
<
count
;
++
l_idx
)
{
if
(
lineno
==
info_file
->
lines
.
ary
[
l_idx
])
{
return
lineno
;
}
}
}
else
{
for
(
l_idx
=
0
;
l_idx
<
count
;
++
l_idx
)
{
if
(
lineno
==
info_file
->
lines
.
flat_map
[
l_idx
].
line
)
{
return
lineno
;
}
}
}
return
0
;
}
static
int32_t
get_break_index
(
mrb_debug_context
*
dbg
,
int32_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
const
char
*
get_class_name
(
mrb_state
*
mrb
,
struct
RClass
*
class_obj
)
{
struct
RClass
*
outer
;
mrb_sym
class_sym
;
outer
=
mrb_class_outer_module
(
mrb
,
class_obj
);
class_sym
=
mrb_class_sym
(
mrb
,
class_obj
,
outer
);
return
mrb_sym2name
(
mrb
,
class_sym
);
}
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
=
get_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
=
get_class_name
(
mrb
,
class_obj
);
sn
=
get_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
);
if
(
set_file
==
NULL
)
{
return
MRB_DEBUG_NOBUF
;
}
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
);
if
(
set_class
==
NULL
)
{
return
MRB_DEBUG_NOBUF
;
}
strncpy
(
set_class
,
class_name
,
strlen
(
class_name
)
+
1
);
}
else
{
set_class
=
NULL
;
}
set_method
=
mrb_malloc
(
mrb
,
strlen
(
method_name
)
+
1
);
if
(
set_method
==
NULL
)
{
if
(
set_class
!=
NULL
)
{
mrb_free
(
mrb
,
(
void
*
)
set_class
);
}
return
MRB_DEBUG_NOBUF
;
}
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
)
{
uint32_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
(
dbg
->
bp
[
i
+
1
].
type
==
MRB_DEBUG_BPTYPE_NONE
)
{
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
,
(
uint32_t
)(
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
;
int
i
;
if
((
mrb
==
NULL
)
||
(
dbg
==
NULL
)
||
(
file
==
NULL
)
||
(
line
<=
0
))
{
return
MRB_DEBUG_INVALID_ARGUMENT
;
}
if
(
!
check_start_pc_for_line
(
dbg
->
irep
,
dbg
->
pc
,
line
))
{
return
MRB_DEBUG_OK
;
}
bp
=
dbg
->
bp
;
for
(
i
=
0
;
i
<
MAX_BREAKPOINT
;
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
;
int
i
;
if
((
mrb
==
NULL
)
||
(
dbg
==
NULL
)
||
(
class_obj
==
NULL
))
{
return
MRB_DEBUG_INVALID_ARGUMENT
;
}
bp
=
dbg
->
bp
;
for
(
i
=
0
;
i
<
MAX_BREAKPOINT
;
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
;
}
mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h
0 → 100755
View file @
4e4bfb08
/*
** apibreak.h
**
*/
#ifndef APIBREAK_H_
#define APIBREAK_H_
#include "mruby.h"
#include "mrdb.h"
int32_t
mrb_debug_set_break_line
(
mrb_state
*
,
mrb_debug_context
*
,
const
char
*
,
uint16_t
);
int32_t
mrb_debug_set_break_method
(
mrb_state
*
,
mrb_debug_context
*
,
const
char
*
,
const
char
*
);
int32_t
mrb_debug_get_breaknum
(
mrb_state
*
,
mrb_debug_context
*
);
int32_t
mrb_debug_get_break_all
(
mrb_state
*
,
mrb_debug_context
*
,
uint32_t
,
mrb_debug_breakpoint
bp
[]);
int32_t
mrb_debug_get_break
(
mrb_state
*
,
mrb_debug_context
*
,
uint32_t
,
mrb_debug_breakpoint
*
);
int32_t
mrb_debug_delete_break
(
mrb_state
*
,
mrb_debug_context
*
,
uint32_t
);
int32_t
mrb_debug_delete_break_all
(
mrb_state
*
,
mrb_debug_context
*
);
int32_t
mrb_debug_enable_break
(
mrb_state
*
,
mrb_debug_context
*
,
uint32_t
);
int32_t
mrb_debug_enable_break_all
(
mrb_state
*
,
mrb_debug_context
*
);
int32_t
mrb_debug_disable_break
(
mrb_state
*
,
mrb_debug_context
*
,
uint32_t
);
int32_t
mrb_debug_disable_break_all
(
mrb_state
*
,
mrb_debug_context
*
);
int32_t
mrb_debug_check_breakpoint_line
(
mrb_state
*
,
mrb_debug_context
*
,
const
char
*
,
uint16_t
);
int32_t
mrb_debug_check_breakpoint_method
(
mrb_state
*
,
mrb_debug_context
*
,
struct
RClass
*
,
mrb_sym
,
mrb_bool
*
);
#endif
/* APIBREAK_H_ */
mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c
0 → 100755
View file @
4e4bfb08
/*
* apilist.c
*/
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "mrdb.h"
#include "mrdberror.h"
#include "apilist.h"
#include "mruby/compile.h"
#include "mruby/irep.h"
#include "mruby/debug.h"
#define LINE_BUF_SIZE MAX_COMMAND_LINE
typedef
struct
source_file
{
char
*
path
;
uint16_t
lineno
;
FILE
*
fp
;
}
source_file
;
static
void
source_file_free
(
mrb_state
*
mrb
,
source_file
*
file
)
{
if
(
file
!=
NULL
)
{
if
(
file
->
path
!=
NULL
)
{
mrb_free
(
mrb
,
file
->
path
);
}
if
(
file
->
fp
!=
NULL
)
{
fclose
(
file
->
fp
);
file
->
fp
=
NULL
;
}
mrb_free
(
mrb
,
file
);
}
}
static
char
*
build_path
(
mrb_state
*
mrb
,
const
char
*
dir
,
const
char
*
base
)
{
int
len
;
char
*
path
=
NULL
;
len
=
strlen
(
base
)
+
1
;
if
(
strcmp
(
dir
,
"."
))
{
len
+=
strlen
(
dir
)
+
strlen
(
"/"
);
}
if
((
path
=
mrb_malloc
(
mrb
,
len
))
!=
NULL
)
{
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
?
p
-
path
:
strlen
(
path
);
if
((
dir
=
mrb_malloc
(
mrb
,
len
+
1
))
!=
NULL
)
{
strncpy
(
dir
,
path
,
len
);
}
return
dir
;
}
static
source_file
*
source_file_new
(
mrb_state
*
mrb
,
mrb_debug_context
*
dbg
,
char
*
filename
)
{
source_file
*
file
=
NULL
;
if
((
file
=
mrb_malloc
(
mrb
,
sizeof
(
source_file
)))
==
NULL
)
{
return
NULL
;
}
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
)
{
char
c
,
*
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
((
unsigned
char
)(
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
;
search_path
[
0
]
=
srcpath
;
search_path
[
1
]
=
dirname
(
mrb
,
mrb_debug_get_filename
(
mrdb
->
dbg
->
root_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
],
filename
))
==
NULL
)
{
continue
;
}
if
((
fp
=
fopen
(
path
,
"rb"
))
==
NULL
)
{
mrb_free
(
mrb
,
path
);
path
=
NULL
;
continue
;
}
fclose
(
fp
);
break
;
}
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
;
}
}
mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h
0 → 100755
View file @
4e4bfb08
/*
* apilist.h
*/
#ifndef APILIST_H_
#define APILIST_H_
#include "mruby.h"
#include "mrdb.h"
int32_t
mrb_debug_list
(
mrb_state
*
,
mrb_debug_context
*
,
char
*
,
uint16_t
,
uint16_t
);
char
*
mrb_debug_get_source
(
mrb_state
*
,
mrdb_state
*
,
const
char
*
,
const
char
*
);
#endif
/* APILIST_H_ */
mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c
0 → 100755
View file @
4e4bfb08
/*
** apiprint.c
**
*/
#include <string.h>
#include "mrdb.h"
#include "mruby/value.h"
#include "mruby/class.h"
#include "mruby/compile.h"
#include "mruby/error.h"
#include "mruby/numeric.h"
#include "mruby/string.h"
#include "apiprint.h"
static
void
mrdb_check_syntax
(
mrb_state
*
mrb
,
mrb_debug_context
*
dbg
,
const
char
*
expr
,
size_t
len
)
{
mrbc_context
*
c
;
c
=
mrbc_context_new
(
mrb
);
c
->
no_exec
=
TRUE
;
c
->
capture_errors
=
TRUE
;
c
->
filename
=
(
char
*
)
dbg
->
prvfile
;
c
->
lineno
=
dbg
->
prvline
;
/* Load program */
mrb_load_nstring_cxt
(
mrb
,
expr
,
len
,
c
);
mrbc_context_free
(
mrb
,
c
);
}
mrb_value
mrb_debug_eval
(
mrb_state
*
mrb
,
mrb_debug_context
*
dbg
,
const
char
*
expr
,
size_t
len
,
mrb_bool
*
exc
)
{
void
*
tmp
;
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_cstr
(
mrb
,
"begin
\n
"
);
ruby_code
=
mrb_str_cat
(
mrb
,
ruby_code
,
expr
,
len
);
ruby_code
=
mrb_str_cat_cstr
(
mrb
,
ruby_code
,
"
\n
rescue => e
\n
e
\n
end"
);
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
;
}
mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h
0 → 100755
View file @
4e4bfb08
/*
* apiprint.h
*/
#ifndef APIPRINT_H_
#define APIPRINT_H_
#include "mruby.h"
#include "mrdb.h"
mrb_value
mrb_debug_eval
(
mrb_state
*
,
mrb_debug_context
*
,
const
char
*
,
size_t
,
mrb_bool
*
);
#endif
/* APIPRINT_H_ */
mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c
0 → 100755
View file @
4e4bfb08
/*
** cmdbreak.c
**
*/
#include <ctype.h>
#include <string.h>
#include "mruby.h"
#include "mruby/dump.h"
#include "mruby/debug.h"
#include "mruby/string.h"
#include "mrdb.h"
#include "mrdberror.h"
#include "apibreak.h"
#define BREAK_SET_MSG_LINE "Breakpoint %d: file %s, line %d.\n"
#define BREAK_SET_MSG_METHOD "Breakpoint %d: method %s.\n"
#define BREAK_SET_MSG_CLASS_METHOD "Breakpoint %d: class %s, method %s.\n"
#define BREAK_INFO_MSG_HEADER "Num Type Enb What"
#define BREAK_INFO_MSG_LINEBREAK "%-8ubreakpoint %s at %s:%u\n"
#define BREAK_INFO_MSG_METHODBREAK "%-8ubreakpoint %s in %s:%s\n"
#define BREAK_INFO_MSG_METHODBREAK_NOCLASS "%-8ubreakpoint %s in %s\n"
#define BREAK_INFO_MSG_ENABLE "y"
#define BREAK_INFO_MSG_DISABLE "n"
#define BREAK_ERR_MSG_INVALIDARG "Internal error."
#define BREAK_ERR_MSG_BLANK "Try \'help break\' for more information."
#define BREAK_ERR_MSG_RANGEOVER "The line number range is from 1 to 65535."
#define BREAK_ERR_MSG_NUMOVER "Exceeded the setable number of breakpoint."
#define BREAK_ERR_MSG_NOOVER "Breakno is over the available number.Please 'quit' and restart mrdb."
#define BREAK_ERR_MSG_INVALIDSTR "String \'%s\' is invalid.\n"
#define BREAK_ERR_MSG_INVALIDLINENO "Line %d in file \"%s\" is unavailable.\n"
#define BREAK_ERR_MSG_INVALIDCLASS "Class name \'%s\' is invalid.\n"
#define BREAK_ERR_MSG_INVALIDMETHOD "Method name \'%s\' is invalid.\n"
#define BREAK_ERR_MSG_INVALIDFILE "Source file named \"%s\" is unavailable.\n"
#define BREAK_ERR_MSG_INVALIDBPNO "warning: bad breakpoint number at or near '%s'\n"
#define BREAK_ERR_MSG_INVALIDBPNO_INFO "Args must be numbers variables."
#define BREAK_ERR_MSG_NOBPNO "No breakpoint number %d.\n"
#define BREAK_ERR_MSG_NOBPNO_INFO "No breakpoint matching '%d'\n"
#define BREAK_ERR_MSG_NOBPNO_INFOALL "No breakpoints."
#define LINENO_MAX_DIGIT 6
#define BPNO_LETTER_NUM 9
typedef
int32_t
(
*
all_command_func
)(
mrb_state
*
,
mrb_debug_context
*
);
typedef
int32_t
(
*
select_command_func
)(
mrb_state
*
,
mrb_debug_context
*
,
uint32_t
);
static
void
print_api_common_error
(
int32_t
error
)
{
switch
(
error
)
{
case
MRB_DEBUG_INVALID_ARGUMENT
:
puts
(
BREAK_ERR_MSG_INVALIDARG
);
break
;
default:
break
;
}
}
#undef STRTOUL
#define STRTOUL(ul,s) \
ul = 0; \
for(int i=0; ISDIGIT(s[i]); i++) ul = 10*ul + (s[i] -'0');
static
int32_t
parse_breakpoint_no
(
char
*
args
)
{
char
*
ps
=
args
;
uint32_t
l
;
if
((
*
ps
==
'0'
)
||
(
strlen
(
ps
)
>=
BPNO_LETTER_NUM
))
{
return
0
;
}
while
(
!
(
ISBLANK
(
*
ps
)
||
ISCNTRL
(
*
ps
))
)
{
if
(
!
ISDIGIT
(
*
ps
))
{
return
0
;
}
ps
++
;
}
STRTOUL
(
l
,
args
);
return
l
;
}
static
mrb_bool
exe_set_command_all
(
mrb_state
*
mrb
,
mrdb_state
*
mrdb
,
all_command_func
func
)
{
int32_t
ret
=
MRB_DEBUG_OK
;
if
(
mrdb
->
wcnt
==
1
)
{
ret
=
func
(
mrb
,
mrdb
->
dbg
);
print_api_common_error
(
ret
);
return
TRUE
;
}
return
FALSE
;
}
static
void
exe_set_command_select
(
mrb_state
*
mrb
,
mrdb_state
*
mrdb
,
select_command_func
func
)
{
char
*
ps
;
int32_t
ret
=
MRB_DEBUG_OK
;
int32_t
bpno
=
0
;
int32_t
i
;
for
(
i
=
1
;
i
<
mrdb
->
wcnt
;
i
++
)
{
ps
=
mrdb
->
words
[
i
];
bpno
=
parse_breakpoint_no
(
ps
);
if
(
bpno
==
0
)
{
printf
(
BREAK_ERR_MSG_INVALIDBPNO
,
ps
);
break
;
}
ret
=
func
(
mrb
,
mrdb
->
dbg
,
(
uint32_t
)
bpno
);
if
(
ret
==
MRB_DEBUG_BREAK_INVALID_NO
)
{
printf
(
BREAK_ERR_MSG_NOBPNO
,
bpno
);
}
else
if
(
ret
!=
MRB_DEBUG_OK
)
{
print_api_common_error
(
ret
);
}
}
}
mrb_debug_bptype
check_bptype
(
char
*
args
)
{
char
*
ps
=
args
;
if
(
ISBLANK
(
*
ps
)
||
ISCNTRL
(
*
ps
))
{
puts
(
BREAK_ERR_MSG_BLANK
);
return
MRB_DEBUG_BPTYPE_NONE
;
}
if
(
!
ISDIGIT
(
*
ps
))
{
return
MRB_DEBUG_BPTYPE_METHOD
;
}
while
(
!
(
ISBLANK
(
*
ps
)
||
ISCNTRL
(
*
ps
))
)
{
if
(
!
ISDIGIT
(
*
ps
))
{
printf
(
BREAK_ERR_MSG_INVALIDSTR
,
args
);
return
MRB_DEBUG_BPTYPE_NONE
;
}
ps
++
;
}
if
((
*
args
==
'0'
)
||
(
strlen
(
args
)
>=
LINENO_MAX_DIGIT
))
{
puts
(
BREAK_ERR_MSG_RANGEOVER
);
return
MRB_DEBUG_BPTYPE_NONE
;
}
return
MRB_DEBUG_BPTYPE_LINE
;
}
static
void
print_breakpoint
(
mrb_debug_breakpoint
*
bp
)
{
char
*
enable_letter
[]
=
{
BREAK_INFO_MSG_DISABLE
,
BREAK_INFO_MSG_ENABLE
};
if
(
bp
->
type
==
MRB_DEBUG_BPTYPE_LINE
)
{
printf
(
BREAK_INFO_MSG_LINEBREAK
,
bp
->
bpno
,
enable_letter
[
bp
->
enable
],
bp
->
point
.
linepoint
.
file
,
bp
->
point
.
linepoint
.
lineno
);
}
else
{
if
(
bp
->
point
.
methodpoint
.
class_name
==
NULL
)
{
printf
(
BREAK_INFO_MSG_METHODBREAK_NOCLASS
,
bp
->
bpno
,
enable_letter
[
bp
->
enable
],
bp
->
point
.
methodpoint
.
method_name
);
}
else
{
printf
(
BREAK_INFO_MSG_METHODBREAK
,
bp
->
bpno
,
enable_letter
[
bp
->
enable
],
bp
->
point
.
methodpoint
.
class_name
,
bp
->
point
.
methodpoint
.
method_name
);
}
}
}
static
void
info_break_all
(
mrb_state
*
mrb
,
mrdb_state
*
mrdb
)
{
int32_t
bpnum
=
0
;
int32_t
i
=
0
;
int32_t
ret
=
MRB_DEBUG_OK
;
mrb_debug_breakpoint
*
bp_list
;
bpnum
=
mrb_debug_get_breaknum
(
mrb
,
mrdb
->
dbg
);
if
(
bpnum
<
0
)
{
print_api_common_error
(
bpnum
);
return
;
}
else
if
(
bpnum
==
0
)
{
puts
(
BREAK_ERR_MSG_NOBPNO_INFOALL
);
return
;
}
bp_list
=
(
mrb_debug_breakpoint
*
)
mrb_malloc
(
mrb
,
bpnum
*
sizeof
(
mrb_debug_breakpoint
));
ret
=
mrb_debug_get_break_all
(
mrb
,
mrdb
->
dbg
,
(
uint32_t
)
bpnum
,
bp_list
);
if
(
ret
<
0
)
{
print_api_common_error
(
ret
);
return
;
}
puts
(
BREAK_INFO_MSG_HEADER
);
for
(
i
=
0
;
i
<
bpnum
;
i
++
)
{
print_breakpoint
(
&
bp_list
[
i
]);
}
mrb_free
(
mrb
,
bp_list
);
}
static
void
info_break_select
(
mrb_state
*
mrb
,
mrdb_state
*
mrdb
)
{
int32_t
ret
=
MRB_DEBUG_OK
;
int32_t
bpno
=
0
;
char
*
ps
=
mrdb
->
command
;
mrb_debug_breakpoint
bp
;
mrb_bool
isFirst
=
TRUE
;
int32_t
i
;
for
(
i
=
2
;
i
<
mrdb
->
wcnt
;
i
++
)
{
ps
=
mrdb
->
words
[
i
];
bpno
=
parse_breakpoint_no
(
ps
);
if
(
bpno
==
0
)
{
puts
(
BREAK_ERR_MSG_INVALIDBPNO_INFO
);
break
;
}
ret
=
mrb_debug_get_break
(
mrb
,
mrdb
->
dbg
,
bpno
,
&
bp
);
if
(
ret
==
MRB_DEBUG_BREAK_INVALID_NO
)
{
printf
(
BREAK_ERR_MSG_NOBPNO_INFO
,
bpno
);
break
;
}
else
if
(
ret
!=
MRB_DEBUG_OK
)
{
print_api_common_error
(
ret
);
break
;
}
else
if
(
isFirst
==
TRUE
)
{
isFirst
=
FALSE
;
puts
(
BREAK_INFO_MSG_HEADER
);
}
print_breakpoint
(
&
bp
);
}
}
mrb_debug_bptype
parse_breakcommand
(
mrdb_state
*
mrdb
,
const
char
**
file
,
uint32_t
*
line
,
char
**
cname
,
char
**
method
)
{
mrb_debug_context
*
dbg
=
mrdb
->
dbg
;
char
*
args
;
char
*
body
;
mrb_debug_bptype
type
;
uint32_t
l
;
if
(
mrdb
->
wcnt
<=
1
)
{
puts
(
BREAK_ERR_MSG_BLANK
);
return
MRB_DEBUG_BPTYPE_NONE
;
}
args
=
mrdb
->
words
[
1
];
if
((
body
=
strchr
(
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
,
(
uint32_t
)(
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
;
}
mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c
0 → 100755
View file @
4e4bfb08
/*
** cmdmisc.c - mruby debugger miscellaneous command functions
**
*/
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "apilist.h"
#include "mruby/compile.h"
typedef
struct
help_msg
{
const
char
*
cmd1
;
const
char
*
cmd2
;
const
char
*
short_msg
;
const
char
*
long_msg
;
}
help_msg
;
static
help_msg
help_msg_list
[]
=
{
{
"b[reak]"
,
NULL
,
"Set breakpoint"
,
"Usage: break [file:]line
\n
"
" break [class:]method
\n
"
"
\n
"
"Set breakpoint at specified line or method.
\n
"
"If
\'
[file:]line
\'
is specified, break at start of code for that line (in a file).
\n
"
"If
\'
[class:]method
\'
is specified, break at start of code for that method (of the class).
\n
"
},
{
"c[ontinue]"
,
NULL
,
"Continue program being debugged"
,
"Usage: continue [N]
\n
"
"
\n
"
"Continue program stopped by a breakpoint.
\n
"
"If N, which is non negative value, is passed,
\n
"
"proceed program until the N-th breakpoint is comming.
\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
);
}
if
((
s
=
mrb_malloc
(
mrb
,
len
+
strlen
(
ext
)
+
1
))
!=
NULL
)
{
memset
(
s
,
'\0'
,
len
+
strlen
(
ext
)
+
1
);
strncpy
(
s
,
filename
,
len
);
strcat
(
s
,
ext
);
}
return
s
;
}
static
mrb_bool
parse_listcmd_args
(
mrb_state
*
mrb
,
mrdb_state
*
mrdb
,
listcmd_parser_state
*
st
)
{
char
*
p
;
switch
(
mrdb
->
wcnt
)
{
case
2
:
p
=
mrdb
->
words
[
1
];
/* mrdb->words[1] ::= <lineno> | <filename> ':' <lineno> | <filename> */
if
(
!
parse_lineno
(
mrb
,
&
p
,
st
))
{
if
(
parse_filename
(
mrb
,
&
p
,
st
))
{
if
(
skip_char
(
&
p
,
':'
))
{
if
(
!
parse_lineno
(
mrb
,
&
p
,
st
))
{
st
->
parse_error
=
TRUE
;
}
}
}
else
{
st
->
parse_error
=
TRUE
;
}
}
if
(
*
p
!=
'\0'
)
{
st
->
parse_error
=
TRUE
;
}
break
;
case
1
:
case
0
:
/* do nothing */
break
;
default:
st
->
parse_error
=
TRUE
;
printf
(
"too many arguments
\n
"
);
break
;
}
if
(
!
st
->
parse_error
)
{
if
(
!
st
->
has_line_min
)
{
st
->
line_min
=
(
!
st
->
filename
&&
mrdb
->
dbg
->
prvline
>
0
)
?
mrdb
->
dbg
->
prvline
:
1
;
}
if
(
!
st
->
has_line_max
)
{
st
->
line_max
=
st
->
line_min
+
9
;
}
if
(
st
->
filename
==
NULL
)
{
if
(
mrdb
->
dbg
->
prvfile
&&
strcmp
(
mrdb
->
dbg
->
prvfile
,
"-"
))
{
st
->
filename
=
replace_ext
(
mrb
,
mrdb
->
dbg
->
prvfile
,
".rb"
);
}
}
}
if
(
st
->
parse_error
||
st
->
filename
==
NULL
)
{
return
FALSE
;
}
return
TRUE
;
}
static
mrb_bool
check_cmd_pattern
(
const
char
*
pattern
,
const
char
*
cmd
)
{
char
*
lbracket
,
*
rbracket
,
*
p
,
*
q
;
if
(
pattern
==
NULL
&&
cmd
==
NULL
)
{
return
TRUE
;
}
if
(
pattern
==
NULL
||
cmd
==
NULL
)
{
return
FALSE
;
}
if
((
lbracket
=
strchr
(
pattern
,
'['
))
==
NULL
)
{
return
!
strcmp
(
pattern
,
cmd
);
}
if
((
rbracket
=
strchr
(
pattern
,
']'
))
==
NULL
)
{
return
FALSE
;
}
if
(
strncmp
(
pattern
,
cmd
,
lbracket
-
pattern
))
{
return
FALSE
;
}
p
=
lbracket
+
1
;
q
=
(
char
*
)
cmd
+
(
lbracket
-
pattern
);
for
(
;
p
<
rbracket
&&
*
q
!=
'\0'
;
p
++
,
q
++
)
{
if
(
*
p
!=
*
q
)
{
break
;
}
}
return
*
q
==
'\0'
;
}
static
help_msg
*
get_help_msg
(
char
*
cmd1
,
char
*
cmd2
)
{
help_msg
*
p
;
if
(
cmd1
==
NULL
)
{
return
NULL
;
}
for
(
p
=
help_msg_list
;
p
->
cmd1
!=
NULL
;
p
++
)
{
if
(
check_cmd_pattern
(
p
->
cmd1
,
cmd1
)
&&
check_cmd_pattern
(
p
->
cmd2
,
cmd2
))
{
return
p
;
}
}
return
NULL
;
}
static
mrb_bool
show_short_help
(
void
)
{
help_msg
*
p
;
printf
(
"Commands
\n
"
);
for
(
p
=
help_msg_list
;
p
->
cmd1
!=
NULL
;
p
++
)
{
if
(
p
->
cmd2
==
NULL
)
{
printf
(
" %s -- %s
\n
"
,
p
->
cmd1
,
p
->
short_msg
);
}
else
{
printf
(
" %s %s -- %s
\n
"
,
p
->
cmd1
,
p
->
cmd2
,
p
->
short_msg
);
}
}
return
TRUE
;
}
static
mrb_bool
show_long_help
(
char
*
cmd1
,
char
*
cmd2
)
{
help_msg
*
help
;
if
((
help
=
get_help_msg
(
cmd1
,
cmd2
))
==
NULL
)
{
return
FALSE
;
}
printf
(
"%s"
,
help
->
long_msg
);
return
TRUE
;
}
dbgcmd_state
dbgcmd_list
(
mrb_state
*
mrb
,
mrdb_state
*
mrdb
)
{
char
*
filename
;
listcmd_parser_state
*
st
=
listcmd_parser_state_new
(
mrb
);
if
(
parse_listcmd_args
(
mrb
,
mrdb
,
st
))
{
if
((
filename
=
mrb_debug_get_source
(
mrb
,
mrdb
,
mrdb
->
srcpath
,
st
->
filename
))
==
NULL
)
{
filename
=
st
->
filename
;
}
mrb_debug_list
(
mrb
,
mrdb
->
dbg
,
filename
,
st
->
line_min
,
st
->
line_max
);
listcmd_parser_state_free
(
mrb
,
st
);
if
(
filename
!=
NULL
&&
filename
!=
st
->
filename
)
{
mrb_free
(
mrb
,
filename
);
}
}
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) "
);
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
;
}
mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c
0 → 100755
View file @
4e4bfb08
/*
** cmdprint.c - mruby debugger print command functions
**
*/
#include <string.h>
#include "mrdb.h"
#include "mruby/value.h"
#include "mruby/class.h"
#include "mruby/compile.h"
#include "mruby/error.h"
#include "mruby/numeric.h"
#include "mruby/string.h"
#include "apiprint.h"
dbgcmd_state
dbgcmd_print
(
mrb_state
*
mrb
,
mrdb_state
*
mrdb
)
{
mrb_value
expr
;
mrb_value
result
;
mrb_value
s
;
uint8_t
wcnt
;
int
ai
;
if
(
mrdb
->
wcnt
<=
1
)
{
puts
(
"Parameter not specified."
);
return
DBGST_PROMPT
;
}
ai
=
mrb_gc_arena_save
(
mrb
);
/* eval expr */
expr
=
mrb_str_new_cstr
(
mrb
,
NULL
);
for
(
wcnt
=
1
;
wcnt
<
mrdb
->
wcnt
;
wcnt
++
)
{
expr
=
mrb_str_cat_cstr
(
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_cstr
(
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
);
}
mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c
0 → 100755
View file @
4e4bfb08
/*
** cmdrun.c - mruby debugger run command functions
**
*/
#include "mruby/opcode.h"
#include "mrdb.h"
dbgcmd_state
dbgcmd_run
(
mrb_state
*
mrb
,
mrdb_state
*
mrdb
)
{
mrb_debug_context
*
dbg
=
mrdb
->
dbg
;
if
(
dbg
->
xm
==
DBG_INIT
){
dbg
->
xm
=
DBG_RUN
;
}
else
{
dbg
->
xm
=
DBG_QUIT
;
if
(
dbg
->
xphase
==
DBG_PHASE_RUNNING
){
struct
RClass
*
exc
;
puts
(
"Start it from the beginning."
);
exc
=
mrb_define_class
(
mrb
,
"DebuggerRestart"
,
mrb_class_get
(
mrb
,
"Exception"
));
mrb_raise
(
mrb
,
exc
,
"Restart mrdb."
);
}
}
return
DBGST_RESTART
;
}
dbgcmd_state
dbgcmd_continue
(
mrb_state
*
mrb
,
mrdb_state
*
mrdb
)
{
mrb_debug_context
*
dbg
=
mrdb
->
dbg
;
int
ccnt
=
1
;
if
(
mrdb
->
wcnt
>
1
){
sscanf
(
mrdb
->
words
[
1
],
"%d"
,
&
ccnt
);
}
dbg
->
ccnt
=
(
uint16_t
)(
ccnt
>
0
?
ccnt
:
1
);
/* count of continue */
if
(
dbg
->
xphase
==
DBG_PHASE_AFTER_RUN
){
puts
(
"The program is not running."
);
dbg
->
xm
=
DBG_QUIT
;
}
else
{
dbg
->
xm
=
DBG_RUN
;
}
return
DBGST_CONTINUE
;
}
dbgcmd_state
dbgcmd_step
(
mrb_state
*
mrb
,
mrdb_state
*
mrdb
)
{
mrdb
->
dbg
->
xm
=
DBG_STEP
;
return
DBGST_CONTINUE
;
}
mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c
0 → 100755
View file @
4e4bfb08
/*
** mrdb.c - mruby debugger
**
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "mruby.h"
#include "mruby/dump.h"
#include "mruby/debug.h"
#include "mruby/class.h"
#include "mruby/opcode.h"
#include "mruby/variable.h"
#include "mrdb.h"
#include "apibreak.h"
#include "apilist.h"
void
mrb_show_version
(
mrb_state
*
);
void
mrb_show_copyright
(
mrb_state
*
);
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] */
{
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_free
(
mrb
,
_debug_context
);
_debug_context
=
NULL
;
}
}
static
mrdb_state
*
mrdb_state_new
(
mrb_state
*
mrb
)
{
mrdb_state
*
mrdb
=
mrb_malloc
(
mrb
,
sizeof
(
mrb_state
));
memset
(
mrdb
,
0
,
sizeof
(
mrb_state
));
mrdb
->
dbg
=
mrb_debug_context_get
(
mrb
);
mrdb
->
command
=
mrb_malloc
(
mrb
,
MAX_COMMAND_LINE
+
1
);
mrdb
->
print_no
=
1
;
return
mrdb
;
}
mrdb_state
*
mrdb_state_get
(
mrb_state
*
mrb
)
{
if
(
!
_mrdb_state
)
{
_mrdb_state
=
mrdb_state_new
(
mrb
);
}
return
_mrdb_state
;
}
void
mrdb_state_set
(
mrdb_state
*
mrdb
)
{
_mrdb_state
=
mrdb
;
}
void
mrdb_state_free
(
mrb_state
*
mrb
)
{
mrb_debug_context_free
(
mrb
);
if
(
_mrdb_state
)
{
mrb_free
(
mrb
,
_mrdb_state
->
command
);
mrb_free
(
mrb
,
_mrdb_state
);
_mrdb_state
=
NULL
;
}
}
static
char
*
get_command
(
mrb_state
*
mrb
,
mrdb_state
*
mrdb
)
{
int
i
;
int
c
;
for
(
i
=
0
;
i
<
MAX_COMMAND_LINE
;
i
++
)
{
if
((
c
=
getchar
())
==
EOF
||
c
==
'\n'
)
break
;
mrdb
->
command
[
i
]
=
c
;
}
if
(
i
==
0
&&
feof
(
stdin
))
{
clearerr
(
stdin
);
strcpy
(
mrdb
->
command
,
"quit"
);
i
+=
strlen
(
"quit"
);
}
if
(
i
==
MAX_COMMAND_LINE
)
{
for
(
;
(
c
=
getchar
())
!=
EOF
&&
c
!=
'\n'
;
i
++
)
;
}
if
(
i
>
MAX_COMMAND_LINE
)
{
printf
(
"command line too long.
\n
"
);
i
=
0
;
/* discard command data */
}
mrdb
->
command
[
i
]
=
'\0'
;
return
mrdb
->
command
;
}
static
char
*
pick_out_word
(
mrb_state
*
mrb
,
char
**
pp
)
{
char
*
ps
;
for
(
ps
=*
pp
;
ISBLANK
(
*
ps
);
ps
++
)
;
if
(
*
ps
==
'\0'
)
{
return
NULL
;
}
if
(
*
ps
==
'\"'
||
*
ps
==
'\''
)
{
*
pp
=
strchr
(
ps
+
1
,
*
ps
);
if
(
*
pp
)
(
*
pp
)
++
;
}
else
{
*
pp
=
strpbrk
(
ps
,
"
\t
"
);
}
if
(
!*
pp
)
{
*
pp
=
ps
+
strlen
(
ps
);
}
if
(
**
pp
!=
'\0'
)
{
**
pp
=
'\0'
;
(
*
pp
)
++
;
}
return
ps
;
}
static
debug_command
*
parse_command
(
mrb_state
*
mrb
,
mrdb_state
*
mrdb
,
char
*
buf
)
{
debug_command
*
cmd
=
NULL
;
char
*
p
=
buf
;
size_t
wlen
;
/* get word #1 */
mrdb
->
words
[
0
]
=
pick_out_word
(
mrb
,
&
p
);
if
(
!
mrdb
->
words
[
0
])
{
return
NULL
;
}
mrdb
->
wcnt
=
1
;
/* set remain parameter */
for
(
;
*
p
&&
ISBLANK
(
*
p
);
p
++
)
;
if
(
*
p
)
{
mrdb
->
words
[
mrdb
->
wcnt
++
]
=
p
;
}
/* check word #1 */
for
(
cmd
=
(
debug_command
*
)
debug_command_list
;
cmd
->
cmd1
;
cmd
++
)
{
wlen
=
strlen
(
mrdb
->
words
[
0
]);
if
(
wlen
>=
cmd
->
len1
&&
strncmp
(
mrdb
->
words
[
0
],
cmd
->
cmd1
,
wlen
)
==
0
)
{
break
;
}
}
if
(
cmd
->
cmd2
)
{
if
(
mrdb
->
wcnt
>
1
)
{
/* get word #2 */
mrdb
->
words
[
1
]
=
pick_out_word
(
mrb
,
&
p
);
if
(
mrdb
->
words
[
1
])
{
/* update remain parameter */
for
(
;
*
p
&&
ISBLANK
(
*
p
);
p
++
)
;
if
(
*
p
)
{
mrdb
->
words
[
mrdb
->
wcnt
++
]
=
p
;
}
}
}
/* check word #1,#2 */
for
(
;
cmd
->
cmd1
;
cmd
++
)
{
wlen
=
strlen
(
mrdb
->
words
[
0
]);
if
(
wlen
<
cmd
->
len1
||
strncmp
(
mrdb
->
words
[
0
],
cmd
->
cmd1
,
wlen
))
{
continue
;
}
if
(
!
cmd
->
cmd2
)
break
;
/* word #1 only */
if
(
mrdb
->
wcnt
==
1
)
continue
;
/* word #2 not specified */
wlen
=
strlen
(
mrdb
->
words
[
1
]);
if
(
wlen
>=
cmd
->
len2
&&
strncmp
(
mrdb
->
words
[
1
],
cmd
->
cmd2
,
wlen
)
==
0
)
{
break
;
/* word #1 and #2 */
}
}
}
/* divide remain parameters */
if
(
cmd
->
cmd1
&&
cmd
->
div
)
{
p
=
mrdb
->
words
[
--
mrdb
->
wcnt
];
for
(
;
mrdb
->
wcnt
<
MAX_COMMAND_WORD
;
mrdb
->
wcnt
++
)
{
mrdb
->
words
[
mrdb
->
wcnt
]
=
pick_out_word
(
mrb
,
&
p
);
if
(
!
mrdb
->
words
[
mrdb
->
wcnt
])
{
break
;
}
}
}
return
cmd
->
cmd1
?
cmd
:
NULL
;
}
static
void
print_info_stopped_break
(
mrb_state
*
mrb
,
mrdb_state
*
mrdb
)
{
mrb_debug_breakpoint
bp
;
int32_t
ret
;
uint16_t
lineno
;
const
char
*
file
;
const
char
*
method_name
;
const
char
*
class_name
;
ret
=
mrb_debug_get_break
(
mrb
,
mrdb
->
dbg
,
mrdb
->
dbg
->
stopped_bpno
,
&
bp
);
if
(
ret
==
0
)
{
switch
(
bp
.
type
)
{
case
MRB_DEBUG_BPTYPE_LINE
:
file
=
bp
.
point
.
linepoint
.
file
;
lineno
=
bp
.
point
.
linepoint
.
lineno
;
printf
(
"Breakpoint %d, at %s:%d
\n
"
,
bp
.
bpno
,
file
,
lineno
);
break
;
case
MRB_DEBUG_BPTYPE_METHOD
:
method_name
=
bp
.
point
.
methodpoint
.
method_name
;
class_name
=
bp
.
point
.
methodpoint
.
class_name
;
if
(
class_name
==
NULL
)
{
printf
(
"Breakpoint %d, %s
\n
"
,
bp
.
bpno
,
method_name
);
}
else
{
printf
(
"Breakpoint %d, %s:%s
\n
"
,
bp
.
bpno
,
class_name
,
method_name
);
}
if
(
mrdb
->
dbg
->
isCfunc
)
{
printf
(
"Stopped before calling the C function.
\n
"
);
}
break
;
default:
break
;
}
}
}
static
void
print_info_stopped_step_next
(
mrb_state
*
mrb
,
mrdb_state
*
mrdb
)
{
const
char
*
file
=
mrdb
->
dbg
->
prvfile
;
uint16_t
lineno
=
mrdb
->
dbg
->
prvline
;
printf
(
"%s:%d
\n
"
,
file
,
lineno
);
}
static
void
print_info_stopped_code
(
mrb_state
*
mrb
,
mrdb_state
*
mrdb
)
{
char
*
file
=
mrb_debug_get_source
(
mrb
,
mrdb
,
mrdb
->
srcpath
,
mrdb
->
dbg
->
prvfile
);
uint16_t
lineno
=
mrdb
->
dbg
->
prvline
;
if
(
file
!=
NULL
)
{
mrb_debug_list
(
mrb
,
mrdb
->
dbg
,
file
,
lineno
,
lineno
);
mrb_free
(
mrb
,
file
);
}
}
static
void
print_info_stopped
(
mrb_state
*
mrb
,
mrdb_state
*
mrdb
)
{
switch
(
mrdb
->
dbg
->
bm
)
{
case
BRK_BREAK
:
print_info_stopped_break
(
mrb
,
mrdb
);
print_info_stopped_code
(
mrb
,
mrdb
);
break
;
case
BRK_STEP
:
case
BRK_NEXT
:
print_info_stopped_step_next
(
mrb
,
mrdb
);
print_info_stopped_code
(
mrb
,
mrdb
);
break
;
default:
break
;
}
}
static
debug_command
*
get_and_parse_command
(
mrb_state
*
mrb
,
mrdb_state
*
mrdb
)
{
debug_command
*
cmd
=
NULL
;
char
*
p
;
int
i
;
while
(
!
cmd
)
{
for
(
p
=
NULL
;
!
p
||
*
p
==
'\0'
;
)
{
printf
(
"(%s:%d) "
,
mrdb
->
dbg
->
prvfile
,
mrdb
->
dbg
->
prvline
);
p
=
get_command
(
mrb
,
mrdb
);
}
cmd
=
parse_command
(
mrb
,
mrdb
,
p
);
#ifdef _DBG_MRDB_PARSER_
for
(
i
=
0
;
i
<
mrdb
->
wcnt
;
i
++
)
{
printf
(
"%d: %s
\n
"
,
i
,
mrdb
->
words
[
i
]);
}
#endif
if
(
!
cmd
)
{
printf
(
"invalid command ("
);
for
(
i
=
0
;
i
<
mrdb
->
wcnt
;
i
++
)
{
if
(
i
>
0
)
{
printf
(
" "
);
}
printf
(
"%s"
,
mrdb
->
words
[
i
]);
}
puts
(
")"
);
}
}
return
cmd
;
}
static
const
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
->
xm
=
DBG_RUN
;
dbg
->
xphase
=
DBG_PHASE_RUNNING
;
}
file
=
mrb_debug_get_filename
(
irep
,
(
uint32_t
)(
pc
-
irep
->
iseq
));
line
=
mrb_debug_get_line
(
irep
,
(
uint32_t
)(
pc
-
irep
->
iseq
));
switch
(
dbg
->
xm
)
{
case
DBG_STEP
:
case
DBG_NEXT
:
// temporary
if
(
dbg
->
prvfile
==
file
&&
dbg
->
prvline
==
line
)
{
return
;
}
dbg
->
method_bpno
=
0
;
dbg
->
bm
=
BRK_STEP
;
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
;
if
(
mrb
==
NULL
)
{
fputs
(
"Invalid mrb_state, exiting mruby
\n
"
,
stderr
);
return
EXIT_FAILURE
;
}
l_restart:
/* 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
;
}
mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h
0 → 100755
View file @
4e4bfb08
/*
** mrdb.h - mruby debugger
**
*/
#ifndef MRDB_H
#define MRDB_H
#include "mruby.h"
#include "mrdbconf.h"
#ifdef _MSC_VER
# define __func__ __FUNCTION__
#endif
#define MAX_COMMAND_WORD (16)
typedef
enum
debug_command_id
{
DBGCMD_RUN
,
DBGCMD_CONTINUE
,
DBGCMD_NEXT
,
DBGCMD_STEP
,
DBGCMD_BREAK
,
DBGCMD_INFO_BREAK
,
DBGCMD_WATCH
,
DBGCMD_INFO_WATCH
,
DBGCMD_ENABLE
,
DBGCMD_DISABLE
,
DBGCMD_DELETE
,
DBGCMD_PRINT
,
DBGCMD_DISPLAY
,
DBGCMD_INFO_DISPLAY
,
DBGCMD_DELETE_DISPLAY
,
DBGCMD_EVAL
,
DBGCMD_BACKTRACE
,
DBGCMD_LIST
,
DBGCMD_HELP
,
DBGCMD_QUIT
,
DBGCMD_UNKNOWN
}
debug_command_id
;
typedef
enum
dbgcmd_state
{
DBGST_CONTINUE
,
DBGST_PROMPT
,
DBGST_COMMAND_ERROR
,
DBGST_MAX
,
DBGST_RESTART
}
dbgcmd_state
;
typedef
enum
mrdb_exemode
{
DBG_INIT
,
DBG_RUN
,
DBG_STEP
,
DBG_NEXT
,
DBG_QUIT
,
}
mrdb_exemode
;
typedef
enum
mrdb_exephase
{
DBG_PHASE_BEFORE_RUN
,
DBG_PHASE_RUNNING
,
DBG_PHASE_AFTER_RUN
,
DBG_PHASE_RESTART
,
}
mrdb_exephase
;
typedef
enum
mrdb_brkmode
{
BRK_INIT
,
BRK_BREAK
,
BRK_STEP
,
BRK_NEXT
,
BRK_QUIT
,
}
mrdb_brkmode
;
typedef
enum
{
MRB_DEBUG_BPTYPE_NONE
,
MRB_DEBUG_BPTYPE_LINE
,
MRB_DEBUG_BPTYPE_METHOD
,
}
mrb_debug_bptype
;
struct
mrb_irep
;
struct
mrbc_context
;
struct
mrb_debug_context
;
typedef
struct
mrb_debug_linepoint
{
const
char
*
file
;
uint16_t
lineno
;
}
mrb_debug_linepoint
;
typedef
struct
mrb_debug_methodpoint
{
const
char
*
class_name
;
const
char
*
method_name
;
}
mrb_debug_methodpoint
;
typedef
struct
mrb_debug_breakpoint
{
uint32_t
bpno
;
uint8_t
enable
;
mrb_debug_bptype
type
;
union
point
{
mrb_debug_linepoint
linepoint
;
mrb_debug_methodpoint
methodpoint
;
}
point
;
}
mrb_debug_breakpoint
;
typedef
struct
mrb_debug_context
{
struct
mrb_irep
*
root_irep
;
struct
mrb_irep
*
irep
;
mrb_code
*
pc
;
mrb_value
*
regs
;
const
char
*
prvfile
;
int32_t
prvline
;
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
*
);
/* 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
mrbgems/mruby-bin-debugger/tools/mrdb/mrdbconf.h
0 → 100755
View file @
4e4bfb08
/*
** 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
mrbgems/mruby-bin-debugger/tools/mrdb/mrdberror.h
0 → 100755
View file @
4e4bfb08
/*
** 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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment