trepanning 0.1.6 → 1.93.32
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +57 -0
- data/ChangeLog +585 -736
- data/NEWS +26 -12
- data/README.md +62 -0
- data/Rakefile +15 -9
- data/app/breakpoint.rb +11 -12
- data/app/complete.rb +14 -14
- data/app/core.rb +34 -30
- data/app/default.rb +8 -7
- data/app/markdown.rb +191 -0
- data/app/options.rb +104 -99
- data/app/run.rb +9 -1
- data/app/util.rb +7 -7
- data/bin/trepan +7 -7
- data/interface.rb +0 -4
- data/interface/user.rb +11 -11
- data/io/input.rb +13 -13
- data/lib/trepanning.rb +30 -29
- data/processor.rb +40 -40
- data/processor/command.rb +13 -9
- data/processor/command/alias.rb +21 -15
- data/processor/command/backtrace.rb +27 -19
- data/processor/command/break.rb +24 -21
- data/processor/command/complete.rb +5 -2
- data/processor/command/condition.rb +14 -9
- data/processor/command/debug.rb +8 -8
- data/processor/command/down.rb +6 -6
- data/processor/command/edit.rb +4 -0
- data/processor/command/eval.rb +2 -2
- data/processor/command/exit.rb +12 -9
- data/processor/command/finish.rb +25 -23
- data/processor/command/frame.rb +30 -26
- data/processor/command/help.rb +203 -185
- data/processor/command/help/{command.txt → command.md} +21 -18
- data/processor/command/help/examples.md +20 -0
- data/processor/command/help/filename.md +46 -0
- data/processor/command/help/location.md +34 -0
- data/processor/command/help/suffixes.md +19 -0
- data/processor/command/info.rb +6 -4
- data/processor/command/info_subcmd/breakpoints.rb +13 -13
- data/processor/command/info_subcmd/files.rb +35 -31
- data/processor/command/info_subcmd/frame.rb +82 -33
- data/processor/command/info_subcmd/macro.rb +1 -1
- data/processor/command/info_subcmd/program.rb +8 -5
- data/processor/command/info_subcmd/registers.rb +15 -13
- data/processor/command/kill.rb +23 -17
- data/processor/command/list.rb +63 -56
- data/processor/command/macro.rb +45 -28
- data/processor/command/next.rb +29 -23
- data/processor/command/pp.rb +11 -9
- data/processor/command/pr.rb +10 -8
- data/processor/command/ps.rb +5 -5
- data/processor/command/quit.rb +24 -17
- data/processor/command/raise.rb +6 -6
- data/processor/command/reload.rb +9 -2
- data/processor/command/reload_subcmd/command.rb +4 -4
- data/processor/command/restart.rb +9 -4
- data/processor/command/save.rb +9 -9
- data/processor/command/server.rb +18 -17
- data/processor/command/set.rb +8 -6
- data/processor/command/set_subcmd/confirm.rb +15 -2
- data/processor/command/set_subcmd/different.rb +7 -5
- data/processor/command/set_subcmd/highlight.rb +14 -3
- data/processor/command/set_subcmd/pc.rb +62 -0
- data/processor/command/set_subcmd/sp.rb +8 -2
- data/processor/command/shell.rb +25 -23
- data/processor/command/show.rb +9 -7
- data/processor/command/show_subcmd/confirm.rb +12 -1
- data/processor/command/show_subcmd/highlight.rb +13 -3
- data/processor/command/source.rb +27 -26
- data/processor/command/step.rb +52 -43
- data/processor/command/tbreak.rb +9 -4
- data/processor/command/unalias.rb +9 -7
- data/processor/command/undisplay.rb +11 -7
- data/processor/command/up.rb +18 -13
- data/processor/command/watchg.rb +20 -17
- data/processor/complete.rb +120 -0
- data/processor/default.rb +47 -43
- data/processor/list.rb +23 -6
- data/processor/load_cmds.rb +25 -105
- data/processor/location.rb +104 -96
- data/processor/mock.rb +12 -12
- data/processor/msg.rb +61 -52
- data/processor/validate.rb +36 -27
- data/test/data/fname-with-blank.right +0 -1
- data/test/data/trace-mingw.right +28 -0
- data/test/data/trace.right +0 -2
- data/test/functional/test-raise.rb +3 -0
- data/test/integration/helper.rb +16 -16
- data/test/integration/test-debugger-stop.rb +8 -2
- data/test/integration/test-quit.rb +16 -15
- data/test/integration/test-trace.rb +19 -10
- data/test/unit/cmd-helper.rb +4 -1
- data/test/unit/test-app-complete.rb +3 -1
- data/test/unit/test-app-options.rb +7 -1
- data/test/unit/test-app-run.rb +9 -1
- data/test/unit/test-cmd-alias.rb +1 -1
- data/test/unit/test-cmd-edit.rb +2 -0
- data/test/unit/test-cmd-help.rb +10 -5
- data/test/unit/test-cmd-parse_list_cmd.rb +3 -3
- data/test/unit/test-completion.rb +2 -2
- data/test/unit/test-proc-default.rb +34 -0
- data/trepanning.gemspec +15 -14
- metadata +70 -44
- data/README.textile +0 -50
- data/processor/command/help/examples.txt +0 -16
- data/processor/command/help/filename.txt +0 -40
- data/processor/command/help/location.txt +0 -37
- data/processor/command/help/suffixes.txt +0 -17
- data/processor/command/info_subcmd/registers_subcmd/dfp.rb +0 -28
- data/processor/command/info_subcmd/registers_subcmd/lfp.rb +0 -47
- data/processor/command/nocache.rb +0 -32
- data/processor/command/parsetree.rb +0 -56
@@ -14,7 +14,7 @@ class Trepan::Subcommand::InfoMacro < Trepan::Subcommand
|
|
14
14
|
In the first form a list of the existing macro names are shown
|
15
15
|
in column format.
|
16
16
|
|
17
|
-
In the second form, all macro names and their definitions are
|
17
|
+
In the second form, all macro names and their definitions are shown.
|
18
18
|
|
19
19
|
In the last form the only definitions of the given macro names is shown.
|
20
20
|
HELP
|
@@ -15,18 +15,21 @@ class Trepan::Subcommand::InfoProgram < Trepan::Subcommand
|
|
15
15
|
def run(args)
|
16
16
|
frame = @proc.frame
|
17
17
|
m = 'Program stop event: %s' % @proc.event
|
18
|
-
m +=
|
18
|
+
m +=
|
19
19
|
if frame.iseq
|
20
|
-
'; PC offset %d of instruction sequence: %s' %
|
20
|
+
'; PC offset %d of instruction sequence: %s' %
|
21
21
|
[frame.pc_offset, frame.iseq.name]
|
22
22
|
else
|
23
23
|
'.'
|
24
24
|
end
|
25
25
|
msg m
|
26
|
-
if 'return' == @proc.event
|
27
|
-
msg 'R=> %s' % @proc.frame.sp(1).inspect
|
26
|
+
if 'return' == @proc.event
|
27
|
+
msg 'R=> %s' % @proc.frame.sp(1).inspect
|
28
28
|
elsif 'raise' == @proc.event
|
29
|
-
|
29
|
+
msg @proc.core.hook_arg.inspect if @proc.core.hook_arg
|
30
|
+
if @proc.frame.iseq.catch_table_size == 0
|
31
|
+
msg "Warning: exception raised is non-local!"
|
32
|
+
end
|
30
33
|
end
|
31
34
|
|
32
35
|
if @proc.brkpt
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
|
-
# Copyright (C) 2010,
|
2
|
+
# Copyright (C) 2010-2011, 2015 Rocky Bernstein <rockyb@rubyforge.net>
|
3
3
|
require_relative '../base/subsubcmd'
|
4
4
|
require_relative '../base/subsubmgr'
|
5
5
|
|
@@ -7,18 +7,20 @@ class Trepan::SubSubcommand::InfoRegisters < Trepan::SubSubcommandMgr
|
|
7
7
|
unless defined?(HELP)
|
8
8
|
Trepanning::Subcommand.set_name_prefix(__FILE__, self)
|
9
9
|
HELP = <<-EOH
|
10
|
-
|
10
|
+
**#{CMD}** [**lfp**|**pc**|**sp**]
|
11
11
|
|
12
12
|
List of contents for the registers of the current stack frame.
|
13
13
|
If a register name given, only only that register is show.
|
14
14
|
|
15
15
|
Examples:
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
info reg sp
|
21
|
-
info reg
|
16
|
+
---------
|
17
|
+
|
18
|
+
#{CMD} # show all registers
|
19
|
+
#{CMD} pc # show only the pc register
|
20
|
+
info reg sp # show all stack pointer registers
|
21
|
+
info reg sp 1 3 # show sp(1) and sp(3)
|
22
|
+
info reg sp size # show sp size
|
23
|
+
info reg lfp # show lfp(0)
|
22
24
|
EOH
|
23
25
|
MIN_ABBREV = 'reg'.size # Note we have "info return"
|
24
26
|
NEED_STACK = true
|
@@ -28,14 +30,14 @@ info reg lfp # show lfp(0)
|
|
28
30
|
def run(args)
|
29
31
|
|
30
32
|
args = @parent.last_args
|
31
|
-
unavailable_regs =
|
33
|
+
unavailable_regs =
|
32
34
|
if 'CFUNC' == @proc.frame.type
|
33
|
-
%w(inforegisterslfp inforegisterspc)
|
35
|
+
%w(inforegisterslfp inforegisterspc)
|
34
36
|
else
|
35
37
|
[]
|
36
38
|
end
|
37
39
|
all_regs = @subcmds.subcmds.keys.sort - unavailable_regs
|
38
|
-
|
40
|
+
|
39
41
|
if args.size == 2
|
40
42
|
# Form is: "info registers"
|
41
43
|
all_regs.sort.each do |subcmd_name|
|
@@ -49,10 +51,10 @@ info reg lfp # show lfp(0)
|
|
49
51
|
subcmd = @subcmds.subcmds[key_name]
|
50
52
|
if @proc.ok_for_running(subcmd, subcmd.class.const_get('CMD'),
|
51
53
|
remain_args.size)
|
52
|
-
@subcmds.subcmds[key_name].run(remain_args)
|
54
|
+
@subcmds.subcmds[key_name].run(remain_args)
|
53
55
|
end
|
54
56
|
elsif unavailable_regs.member?(key_name)
|
55
|
-
msg("info registers: %s can not be displayed for frame type %s." %
|
57
|
+
msg("info registers: %s can not be displayed for frame type %s." %
|
56
58
|
[subcmd_name, @proc.frame.type])
|
57
59
|
else
|
58
60
|
errmsg("info registers: %s is not a valid register name" % subcmd_name)
|
data/processor/command/kill.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2010,
|
1
|
+
# Copyright (C) 2010-2011, 2015 Rocky Bernstein <rockyb@rubyforge.net>
|
2
2
|
require_relative '../command'
|
3
3
|
require_relative '../../app/complete'
|
4
4
|
class Trepan::Command::KillCommand < Trepan::Command
|
@@ -6,26 +6,32 @@ class Trepan::Command::KillCommand < Trepan::Command
|
|
6
6
|
unless defined?(HELP)
|
7
7
|
NAME = File.basename(__FILE__, '.rb')
|
8
8
|
HELP = <<-HELP
|
9
|
-
|
9
|
+
**#{NAME}** [signal-number|signal-name]
|
10
10
|
|
11
11
|
Kill execution of program being debugged.
|
12
12
|
|
13
|
-
Equivalent of Process.kill('KILL', Process.pid)
|
13
|
+
Equivalent of `Process.kill('KILL', Process.pid)`. This is an unmaskable
|
14
14
|
signal. When all else fails, e.g. in thread code, use this.
|
15
15
|
|
16
16
|
If you are in interactive mode, you are prompted to confirm killing.
|
17
|
-
However when this command is aliased from a command ending in
|
17
|
+
However when this command is aliased from a command ending in "!", no
|
18
18
|
questions are asked.
|
19
19
|
|
20
20
|
Examples:
|
21
|
+
---------
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
23
|
+
#{NAME}
|
24
|
+
#{NAME} unconditionally
|
25
|
+
#{NAME} KILL # same as above
|
26
|
+
#{NAME} kill # same as above
|
27
|
+
#{NAME} -9 # same as above
|
28
|
+
#{NAME} 9 # same as above
|
29
|
+
#{NAME}! 9 # above, but unconditional
|
30
|
+
|
31
|
+
See also:
|
32
|
+
---------
|
33
|
+
|
34
|
+
`quit`, `exit`
|
29
35
|
HELP
|
30
36
|
|
31
37
|
ALIASES = %w(kill!)
|
@@ -33,15 +39,15 @@ Examples:
|
|
33
39
|
MAX_ARGS = 1 # Need at most this many
|
34
40
|
SHORT_HELP = 'Send this process a POSIX signal (default "9" is "kill -9")'
|
35
41
|
end
|
36
|
-
|
42
|
+
|
37
43
|
def complete(prefix)
|
38
44
|
completions = Signal.list.keys + Signal.list.keys.map{|k| k.downcase} +
|
39
|
-
Signal.list.values.map{|i| i.to_s} +
|
40
|
-
Signal.list.values.map{|i| (-i).to_s} +
|
45
|
+
Signal.list.values.map{|i| i.to_s} +
|
46
|
+
Signal.list.values.map{|i| (-i).to_s} +
|
41
47
|
['unconditionally']
|
42
48
|
Trepan::Complete.complete_token(completions, prefix)
|
43
49
|
end
|
44
|
-
|
50
|
+
|
45
51
|
# This method runs the command
|
46
52
|
def run(args) # :nodoc
|
47
53
|
unconditional = ('!' == args[0][-1..-1])
|
@@ -54,7 +60,7 @@ Examples:
|
|
54
60
|
else
|
55
61
|
if unconditional || confirm('Really quit?', false)
|
56
62
|
sig = 'KILL'
|
57
|
-
else
|
63
|
+
else
|
58
64
|
msg('Kill not confirmed.')
|
59
65
|
return
|
60
66
|
end
|
@@ -71,7 +77,7 @@ end
|
|
71
77
|
if __FILE__ == $0
|
72
78
|
require_relative '../mock'
|
73
79
|
dbgr, cmd = MockDebugger::setup
|
74
|
-
%w(fooo 100 1 -1 HUP -9).each do |arg|
|
80
|
+
%w(fooo 100 1 -1 HUP -9).each do |arg|
|
75
81
|
puts "#{cmd.name} #{arg}"
|
76
82
|
cmd.run([cmd.name, arg])
|
77
83
|
puts '=' * 40
|
data/processor/command/list.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2010,
|
1
|
+
# Copyright (C) 2010-2011, 2015 Rocky Bernstein <rockyb@rubyforge.net>
|
2
2
|
# -*- coding: utf-8 -*-
|
3
3
|
require 'linecache'
|
4
4
|
require_relative '../command'
|
@@ -8,79 +8,86 @@ class Trepan::Command::ListCommand < Trepan::Command
|
|
8
8
|
unless defined?(HELP)
|
9
9
|
NAME = File.basename(__FILE__, '.rb')
|
10
10
|
HELP = <<-HELP
|
11
|
-
|
12
|
-
|
11
|
+
**#{NAME}[>]** [*module*] [*first* [*num*]]
|
12
|
+
**#{NAME}[>]** *location [*num*]
|
13
13
|
|
14
|
-
|
14
|
+
List source code.
|
15
15
|
|
16
|
-
Without arguments, prints lines centered around the current
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
16
|
+
Without arguments, prints lines centered around the current line. If
|
17
|
+
this is the first #{NAME} command issued since the debugger command
|
18
|
+
loop was entered, then the current line is the current frame. If a
|
19
|
+
subsequent #{NAME} command was issued with no intervening frame
|
20
|
+
changing, then that is start the line after we last one previously
|
21
|
+
shown.
|
22
22
|
|
23
|
-
If the command has a
|
23
|
+
If the command has a ">" suffix, then line centering is disabled and
|
24
24
|
listing begins at the specificed location.
|
25
25
|
|
26
26
|
The number of lines to show is controlled by the debugger "listsize"
|
27
27
|
setting. Use 'set max list' or 'show max list' to see or set the
|
28
28
|
value.
|
29
29
|
|
30
|
-
\"#{NAME} -\" shows lines before a previous listing.
|
30
|
+
\"#{NAME} -\" shows lines before a previous listing.
|
31
31
|
|
32
|
-
A
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
32
|
+
A *location* is a either:
|
33
|
+
|
34
|
+
* number, e.g. 5,
|
35
|
+
* a function, e.g. *join* or *os.path.join*
|
36
|
+
* a module, e.g. *os* or *os.path*
|
37
|
+
* a filename, colon, and a number, e.g. *foo.rb:5*,
|
38
|
+
* or a module name and a number, e.g,. *os.path:5*.
|
39
|
+
* a "." for the current line number
|
40
|
+
* a "-" for the lines before the current line number
|
40
41
|
|
41
42
|
If the location form is used with a subsequent parameter, the
|
42
43
|
parameter is the starting line number. When there two numbers are
|
43
44
|
given, the last number value is treated as a stopping line unless it
|
44
45
|
is positive and less than the start line. In this case, it is taken to
|
45
|
-
mean the number of lines to list instead. If last is negative, we
|
46
|
-
that many lines back from first and list to first.
|
46
|
+
mean the number of lines to list instead. If last is negative, we
|
47
|
+
start that many lines back from first and list to first.
|
47
48
|
|
48
|
-
Wherever a number is expected, it does not need to be a constant
|
49
|
+
Wherever a number is expected, it does not need to be a constant,
|
49
50
|
just something that evaluates to a positive integer.
|
50
51
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
#{NAME}
|
55
|
-
#{NAME} 5
|
56
|
-
#{NAME}
|
57
|
-
#{NAME} foo.rb
|
58
|
-
#{NAME}
|
59
|
-
#{NAME} foo.rb
|
60
|
-
#{NAME} foo.rb 5
|
61
|
-
#{NAME} foo.rb
|
62
|
-
#{NAME} foo.rb
|
63
|
-
#{NAME}
|
64
|
-
#{NAME} .
|
65
|
-
#{NAME} .
|
66
|
-
|
67
|
-
#
|
52
|
+
Examples:
|
53
|
+
---------
|
54
|
+
|
55
|
+
#{NAME} 5 # List centered around line 5
|
56
|
+
#{NAME} @5 # List lines centered around bytecode offset 5.
|
57
|
+
#{NAME} 5> # List starting at line 5
|
58
|
+
#{NAME} foo.rb:5 # List centered around line 5 of foo.rb
|
59
|
+
#{NAME} foo.rb 5 # Same as above.
|
60
|
+
#{NAME}> foo.rb:5 # List starting around line 5 of foo.rb
|
61
|
+
#{NAME} foo.rb 5 6 # list lines 5 and 6 of foo.rb
|
62
|
+
#{NAME} foo.rb 5 2 # Same as above, since 2 < 5.
|
63
|
+
#{NAME} foo.rb:5 2 # Same as above
|
64
|
+
#{NAME} foo.rb 15 -5 # List lines 10..15 of foo
|
65
|
+
#{NAME} FileUtils.cp # List lines around the FileUtils.cp function.
|
66
|
+
#{NAME} . # List lines centered from where we currently are stopped
|
67
|
+
#{NAME} . 3 # List 3 lines starting from where we currently are stopped
|
68
|
+
# if . > 3. Otherwise we list from . to 3.
|
69
|
+
#{NAME} - # List lines previous to those just shown
|
68
70
|
|
69
71
|
The output of the #{NAME} command gives a line number, and some status
|
70
|
-
information about the line and the text of the line. Here is some
|
72
|
+
information about the line and the text of the line. Here is some
|
71
73
|
hypothetical #{NAME} output modeled roughly around line 251 of one
|
72
74
|
version of this code:
|
73
75
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
76
|
+
251 cmd.proc.frame_setup(tf)
|
77
|
+
252 -> brkpt_cmd.run(['break'])
|
78
|
+
253 B01 line = __LINE__
|
79
|
+
254 b02 cmd.run(['list', __LINE__.to_s])
|
80
|
+
255 t03 puts '--' * 10
|
79
81
|
|
80
82
|
Line 251 has nothing special about it. Line 252 is where we are
|
81
83
|
currently stopped. On line 253 there is a breakpoint 1 which is
|
82
84
|
enabled, while at line 255 there is an breakpoint 2 which is
|
83
85
|
disabled.
|
86
|
+
|
87
|
+
See also:
|
88
|
+
---------
|
89
|
+
|
90
|
+
`set max list`, `show max list`, `disassemble`, `help syntax location`
|
84
91
|
HELP
|
85
92
|
|
86
93
|
ALIASES = %W(l #{NAME}> l> cat)
|
@@ -95,14 +102,14 @@ disabled.
|
|
95
102
|
return
|
96
103
|
end
|
97
104
|
listsize = settings[:maxlist]
|
98
|
-
center_correction =
|
105
|
+
center_correction =
|
99
106
|
if args[0][-1..-1] == '>'
|
100
107
|
0
|
101
108
|
else
|
102
109
|
(listsize-1) / 2
|
103
110
|
end
|
104
111
|
|
105
|
-
iseq, filename, first, last =
|
112
|
+
iseq, filename, first, last =
|
106
113
|
@proc.parse_list_cmd(@proc.cmd_argstr, listsize, center_correction)
|
107
114
|
return unless filename
|
108
115
|
container = iseq ? iseq.source_container : ['file', filename]
|
@@ -110,7 +117,7 @@ disabled.
|
|
110
117
|
|
111
118
|
# We now have range information. Do the listing.
|
112
119
|
max_line = LineCache::size(filename)
|
113
|
-
unless max_line
|
120
|
+
unless max_line
|
114
121
|
errmsg('File "%s" not found.' % filename)
|
115
122
|
return
|
116
123
|
end
|
@@ -140,14 +147,14 @@ disabled.
|
|
140
147
|
end
|
141
148
|
line.chomp!
|
142
149
|
s = '%3d' % lineno
|
143
|
-
s = s + ' ' if s.size < 4
|
150
|
+
s = s + ' ' if s.size < 4
|
144
151
|
s += if breaklist.member?(lineno)
|
145
152
|
bp = breaklist[lineno]
|
146
153
|
a_pad = '%02d' % bp.id
|
147
154
|
bp.icon_char
|
148
|
-
else
|
155
|
+
else
|
149
156
|
a_pad = ' '
|
150
|
-
' '
|
157
|
+
' '
|
151
158
|
end
|
152
159
|
s += (frame && lineno == @proc.frame_line &&
|
153
160
|
filename == frame.source_container[1]) ? '->' : a_pad
|
@@ -164,7 +171,7 @@ if __FILE__ == $0
|
|
164
171
|
if !(ARGV.size == 1 && ARGV[0] == 'noload')
|
165
172
|
ARGV[0..-1] = ['noload']
|
166
173
|
load(__FILE__)
|
167
|
-
else
|
174
|
+
else
|
168
175
|
require_relative '../location'
|
169
176
|
require_relative '../mock'
|
170
177
|
require_relative '../frame'
|
@@ -185,7 +192,7 @@ if __FILE__ == $0
|
|
185
192
|
puts "%s %s %s" % [seps, args.join(' '), seps]
|
186
193
|
run_cmd(cmd,args)
|
187
194
|
end
|
188
|
-
|
195
|
+
|
189
196
|
|
190
197
|
load 'tmpdir.rb'
|
191
198
|
run_cmd2(cmd, %w(list tmpdir.rb 10))
|
@@ -204,7 +211,7 @@ if __FILE__ == $0
|
|
204
211
|
run_cmd2(cmd, %w(list 3000))
|
205
212
|
run_cmd2(cmd, %w(list run_cmd2))
|
206
213
|
|
207
|
-
p = Proc.new do
|
214
|
+
p = Proc.new do
|
208
215
|
|x,y| x + y
|
209
216
|
end
|
210
217
|
require 'thread_frame'
|
@@ -221,7 +228,7 @@ if __FILE__ == $0
|
|
221
228
|
# Start line and count, since 3 < 30
|
222
229
|
run_cmd2(cmd, %W(#{cmd.name} Columnize.columnize 30 3))
|
223
230
|
|
224
|
-
# Start line finish line
|
231
|
+
# Start line finish line
|
225
232
|
run_cmd2(cmd, %W(#{cmd.name} Columnize.columnize 40 50))
|
226
233
|
|
227
234
|
# puts '--' * 10
|
data/processor/command/macro.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
|
-
# Copyright (C) 2010,
|
2
|
+
# Copyright (C) 2010-2011, 2015 Rocky Bernstein <rockyb@rubyforge.net>
|
3
3
|
require_relative '../command'
|
4
4
|
require_relative '../eval'
|
5
5
|
class Trepan::Command::MacroCommand < Trepan::Command
|
@@ -7,65 +7,82 @@ class Trepan::Command::MacroCommand < Trepan::Command
|
|
7
7
|
unless defined?(HELP)
|
8
8
|
NAME = File.basename(__FILE__, '.rb')
|
9
9
|
HELP = <<-HELP
|
10
|
-
|
10
|
+
**#{NAME}** *macro-name* *Proc-object*
|
11
11
|
|
12
|
-
Define
|
13
|
-
arguments
|
14
|
-
|
12
|
+
Define *macro-name* as a debugger macro. Debugger macros get a list of
|
13
|
+
arguments which you supply without parenthesis or commas. See below
|
14
|
+
for an example.
|
15
15
|
|
16
|
-
The macro (really a Ruby Proc) should return either a String or
|
17
|
-
Array of Strings
|
18
|
-
|
19
|
-
String#split . Note that macro processing is done right after
|
20
|
-
splitting on ;; so if the macro returns a string containing ;; this
|
21
|
-
will not be handled on the string returned.
|
16
|
+
The macro (really a Ruby *Proc()*) should return either a *String* or
|
17
|
+
an *Array* of *Strings*. Each component string in either case
|
18
|
+
refers to a debugger command.
|
22
19
|
|
23
|
-
If
|
20
|
+
If the return is a *String*, that gets tokenized by a simple
|
21
|
+
*String#split*. Note that macro processing is done right after
|
22
|
+
splitting on `;;` so if the macro returns a string containing `;;`
|
23
|
+
this will not be handled on the string returned.
|
24
|
+
|
25
|
+
Here is a simple macro using a string:
|
26
|
+
|
27
|
+
macro resize Proc.new{"set max width"}
|
28
|
+
|
29
|
+
We have to use a macro here rather than an *alias*, because the
|
30
|
+
expansion is more than to a command name, but contains the 3 tokens,
|
31
|
+
"set", "max", and "width".
|
32
|
+
|
33
|
+
If an Array of Strings is returned instead, then the first string is
|
24
34
|
shifted from the array and executed. The remaining strings are pushed
|
25
35
|
onto the command queue. In contrast to the first string, subsequent
|
26
36
|
strings can contain other macros, and ;; in those strings will be
|
27
37
|
split into separate commands.
|
28
38
|
|
29
|
-
Here is an example. The below creates a
|
30
|
-
issues two commands 'finish' followed by
|
39
|
+
Here is an example using na Array of Strings. The below creates a
|
40
|
+
macro called fin+ which issues two commands 'finish' followed by
|
41
|
+
'step':
|
31
42
|
|
32
|
-
|
43
|
+
macro fin+ Proc.new{|*args| %w(finish step)}
|
33
44
|
|
34
45
|
If you wanted to parameterize the argument of the 'finish' command
|
35
46
|
you could do that this way:
|
36
47
|
|
37
|
-
|
48
|
+
macro fin+ Proc.new{|*args| ["finish \#{args[0]}" 'step']}
|
49
|
+
|
50
|
+
Invoking with:
|
38
51
|
|
39
|
-
|
40
|
-
fin+ 3
|
52
|
+
fin+ 3
|
41
53
|
|
42
54
|
would expand to ["finish 3", "step"]
|
43
55
|
|
44
|
-
If you were to add another parameter for 'step', the note that the
|
45
|
-
invocation might be
|
46
|
-
|
56
|
+
If you were to add another parameter for 'step', the note that the
|
57
|
+
invocation might be:
|
58
|
+
|
59
|
+
fin+ 3 2
|
47
60
|
|
48
61
|
rather than 'fin+(3,2)' or 'fin+ 3, 2'.
|
49
62
|
|
50
63
|
Here is another example using arguments. I use the following to debug
|
51
64
|
a debugger command:
|
52
65
|
|
53
|
-
|
66
|
+
macro dbgcmd Proc.new{|*args| ["set debug dbgr", "debug $trepan_cmdproc.commands['\#{args[0]}'].run(\#{args.inspect})"]}
|
67
|
+
|
68
|
+
With the above, 'dbgcmd list 5' will ultimately expand to:
|
54
69
|
|
55
|
-
|
56
|
-
|
57
|
-
debug $trepan_cmdproc.commands['list'].run(['5'])
|
70
|
+
set debug dbgr
|
71
|
+
debug $trepan_cmdproc.commands['list'].run(['5'])
|
58
72
|
|
59
73
|
and will debug the debugger's 'list' command on the command 'list 5'.
|
60
74
|
|
61
|
-
See also
|
75
|
+
See also:
|
76
|
+
---------
|
77
|
+
|
78
|
+
`alias` and `info macro`.
|
62
79
|
HELP
|
63
80
|
|
64
81
|
CATEGORY = 'support'
|
65
82
|
MIN_ARGS = 2 # Need at least this many
|
66
83
|
SHORT_HELP = 'Define a macro'
|
67
84
|
end
|
68
|
-
|
85
|
+
|
69
86
|
def run(args)
|
70
87
|
cmd_name = args[1]
|
71
88
|
cmd_argstr = @proc.cmd_argstr[cmd_name.size..-1].lstrip
|
@@ -80,7 +97,7 @@ See also 'info macro'.
|
|
80
97
|
end
|
81
98
|
end
|
82
99
|
end
|
83
|
-
|
100
|
+
|
84
101
|
if __FILE__ == $0
|
85
102
|
require_relative '../mock'
|
86
103
|
dbgr, cmd = MockDebugger::setup
|