trepanning 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +4422 -0
- data/LICENSE +23 -0
- data/NEWS +12 -0
- data/README.textile +56 -0
- data/Rakefile +171 -0
- data/app/Makefile +7 -0
- data/app/breakpoint.rb +157 -0
- data/app/brkptmgr.rb +149 -0
- data/app/condition.rb +22 -0
- data/app/core.rb +203 -0
- data/app/default.rb +54 -0
- data/app/disassemble.rb +61 -0
- data/app/display.rb +148 -0
- data/app/file.rb +135 -0
- data/app/frame.rb +275 -0
- data/app/irb.rb +112 -0
- data/app/mock.rb +22 -0
- data/app/options.rb +122 -0
- data/app/run.rb +95 -0
- data/app/thread.rb +24 -0
- data/app/util.rb +32 -0
- data/bin/trepan +63 -0
- data/data/custom_require.rb +44 -0
- data/data/irbrc +55 -0
- data/data/prelude.rb +38 -0
- data/interface/base_intf.rb +95 -0
- data/interface/script.rb +103 -0
- data/interface/user.rb +90 -0
- data/io/base_io.rb +92 -0
- data/io/input.rb +111 -0
- data/io/string_array.rb +155 -0
- data/lib/Makefile +7 -0
- data/lib/trepanning.rb +277 -0
- data/processor/breakpoint.rb +108 -0
- data/processor/command/alias.rb +55 -0
- data/processor/command/backtrace.rb +95 -0
- data/processor/command/base/cmd.rb +97 -0
- data/processor/command/base/subcmd.rb +207 -0
- data/processor/command/base/submgr.rb +178 -0
- data/processor/command/base/subsubcmd.rb +102 -0
- data/processor/command/base/subsubmgr.rb +182 -0
- data/processor/command/break.rb +85 -0
- data/processor/command/condition.rb +64 -0
- data/processor/command/continue.rb +61 -0
- data/processor/command/debug.rb +85 -0
- data/processor/command/delete.rb +54 -0
- data/processor/command/directory.rb +43 -0
- data/processor/command/disable.rb +65 -0
- data/processor/command/disassemble.rb +103 -0
- data/processor/command/display.rb +81 -0
- data/processor/command/down.rb +56 -0
- data/processor/command/enable.rb +43 -0
- data/processor/command/exit.rb +54 -0
- data/processor/command/finish.rb +81 -0
- data/processor/command/frame.rb +117 -0
- data/processor/command/help.rb +146 -0
- data/processor/command/info.rb +28 -0
- data/processor/command/info_subcmd/args.rb +56 -0
- data/processor/command/info_subcmd/breakpoints.rb +162 -0
- data/processor/command/info_subcmd/file.rb +162 -0
- data/processor/command/info_subcmd/frame.rb +39 -0
- data/processor/command/info_subcmd/iseq.rb +83 -0
- data/processor/command/info_subcmd/locals.rb +88 -0
- data/processor/command/info_subcmd/program.rb +54 -0
- data/processor/command/info_subcmd/registers.rb +72 -0
- data/processor/command/info_subcmd/registers_subcmd/dfp.rb +38 -0
- data/processor/command/info_subcmd/registers_subcmd/helper.rb +40 -0
- data/processor/command/info_subcmd/registers_subcmd/lfp.rb +54 -0
- data/processor/command/info_subcmd/registers_subcmd/pc.rb +44 -0
- data/processor/command/info_subcmd/registers_subcmd/sp.rb +75 -0
- data/processor/command/info_subcmd/return.rb +40 -0
- data/processor/command/info_subcmd/thread.rb +106 -0
- data/processor/command/irb.rb +106 -0
- data/processor/command/kill.rb +58 -0
- data/processor/command/list.rb +327 -0
- data/processor/command/macro.rb +65 -0
- data/processor/command/next.rb +89 -0
- data/processor/command/nocache.rb +33 -0
- data/processor/command/print.rb +37 -0
- data/processor/command/ps.rb +40 -0
- data/processor/command/quit.rb +62 -0
- data/processor/command/raise.rb +47 -0
- data/processor/command/reload.rb +28 -0
- data/processor/command/reload_subcmd/command.rb +34 -0
- data/processor/command/restart.rb +57 -0
- data/processor/command/save.rb +60 -0
- data/processor/command/set.rb +47 -0
- data/processor/command/set_subcmd/auto.rb +27 -0
- data/processor/command/set_subcmd/auto_subcmd/eval.rb +67 -0
- data/processor/command/set_subcmd/auto_subcmd/irb.rb +49 -0
- data/processor/command/set_subcmd/auto_subcmd/list.rb +51 -0
- data/processor/command/set_subcmd/basename.rb +39 -0
- data/processor/command/set_subcmd/debug.rb +27 -0
- data/processor/command/set_subcmd/debug_subcmd/dbgr.rb +49 -0
- data/processor/command/set_subcmd/debug_subcmd/except.rb +35 -0
- data/processor/command/set_subcmd/debug_subcmd/macro.rb +35 -0
- data/processor/command/set_subcmd/debug_subcmd/skip.rb +35 -0
- data/processor/command/set_subcmd/debug_subcmd/stack.rb +45 -0
- data/processor/command/set_subcmd/different.rb +67 -0
- data/processor/command/set_subcmd/events.rb +71 -0
- data/processor/command/set_subcmd/max.rb +35 -0
- data/processor/command/set_subcmd/max_subcmd/list.rb +50 -0
- data/processor/command/set_subcmd/max_subcmd/stack.rb +60 -0
- data/processor/command/set_subcmd/max_subcmd/string.rb +53 -0
- data/processor/command/set_subcmd/max_subcmd/width.rb +50 -0
- data/processor/command/set_subcmd/return.rb +66 -0
- data/processor/command/set_subcmd/sp.rb +62 -0
- data/processor/command/set_subcmd/substitute.rb +25 -0
- data/processor/command/set_subcmd/substitute_subcmd/eval.rb +98 -0
- data/processor/command/set_subcmd/substitute_subcmd/path.rb +55 -0
- data/processor/command/set_subcmd/substitute_subcmd/string.rb +72 -0
- data/processor/command/set_subcmd/timer.rb +68 -0
- data/processor/command/set_subcmd/trace.rb +43 -0
- data/processor/command/set_subcmd/trace_subcmd/buffer.rb +56 -0
- data/processor/command/set_subcmd/trace_subcmd/print.rb +54 -0
- data/processor/command/set_subcmd/trace_subcmd/var.rb +61 -0
- data/processor/command/show.rb +27 -0
- data/processor/command/show_subcmd/alias.rb +50 -0
- data/processor/command/show_subcmd/args.rb +50 -0
- data/processor/command/show_subcmd/auto.rb +27 -0
- data/processor/command/show_subcmd/auto_subcmd/eval.rb +38 -0
- data/processor/command/show_subcmd/auto_subcmd/irb.rb +34 -0
- data/processor/command/show_subcmd/auto_subcmd/list.rb +36 -0
- data/processor/command/show_subcmd/basename.rb +28 -0
- data/processor/command/show_subcmd/debug.rb +27 -0
- data/processor/command/show_subcmd/debug_subcmd/dbgr.rb +31 -0
- data/processor/command/show_subcmd/debug_subcmd/except.rb +33 -0
- data/processor/command/show_subcmd/debug_subcmd/macro.rb +32 -0
- data/processor/command/show_subcmd/debug_subcmd/skip.rb +33 -0
- data/processor/command/show_subcmd/debug_subcmd/stack.rb +32 -0
- data/processor/command/show_subcmd/different.rb +37 -0
- data/processor/command/show_subcmd/events.rb +40 -0
- data/processor/command/show_subcmd/macro.rb +45 -0
- data/processor/command/show_subcmd/max.rb +31 -0
- data/processor/command/show_subcmd/max_subcmd/list.rb +39 -0
- data/processor/command/show_subcmd/max_subcmd/stack.rb +35 -0
- data/processor/command/show_subcmd/max_subcmd/string.rb +41 -0
- data/processor/command/show_subcmd/max_subcmd/width.rb +36 -0
- data/processor/command/show_subcmd/trace.rb +29 -0
- data/processor/command/show_subcmd/trace_subcmd/buffer.rb +84 -0
- data/processor/command/show_subcmd/trace_subcmd/print.rb +38 -0
- data/processor/command/source.rb +74 -0
- data/processor/command/step.rb +139 -0
- data/processor/command/stepi.rb +63 -0
- data/processor/command/unalias.rb +44 -0
- data/processor/command/undisplay.rb +63 -0
- data/processor/command/up.rb +92 -0
- data/processor/default.rb +45 -0
- data/processor/display.rb +17 -0
- data/processor/eval.rb +88 -0
- data/processor/eventbuf.rb +131 -0
- data/processor/frame.rb +230 -0
- data/processor/help.rb +72 -0
- data/processor/hook.rb +128 -0
- data/processor/load_cmds.rb +102 -0
- data/processor/location.rb +126 -0
- data/processor/main.rb +364 -0
- data/processor/mock.rb +100 -0
- data/processor/msg.rb +26 -0
- data/processor/running.rb +170 -0
- data/processor/subcmd.rb +159 -0
- data/processor/validate.rb +395 -0
- data/test/example/fname with blank.rb +1 -0
- data/test/example/gcd-xx.rb +18 -0
- data/test/example/gcd.rb +19 -0
- data/test/example/gcd1.rb +24 -0
- data/test/example/null.rb +1 -0
- data/test/example/thread1.rb +3 -0
- data/test/functional/fn_helper.rb +119 -0
- data/test/functional/test-break.rb +87 -0
- data/test/functional/test-condition.rb +59 -0
- data/test/functional/test-debugger-call-bug.rb +31 -0
- data/test/functional/test-delete.rb +71 -0
- data/test/functional/test-finish.rb +44 -0
- data/test/functional/test-immediate-step-bug.rb +35 -0
- data/test/functional/test-next.rb +77 -0
- data/test/functional/test-raise.rb +73 -0
- data/test/functional/test-return.rb +100 -0
- data/test/functional/test-step.rb +274 -0
- data/test/functional/test-stepbug.rb +40 -0
- data/test/functional/test-trace-var.rb +40 -0
- data/test/functional/tmp/b1.rb +5 -0
- data/test/functional/tmp/s1.rb +9 -0
- data/test/functional/tmp/t2.rb +6 -0
- data/test/integration/file-diff.rb +88 -0
- data/test/integration/helper.rb +52 -0
- data/test/integration/test-fname-with-blank.rb +11 -0
- data/test/integration/test-quit.rb +11 -0
- data/test/integration/try-test-enable.rb +11 -0
- data/test/unit/cmd-helper.rb +44 -0
- data/test/unit/test-app-brkpt.rb +30 -0
- data/test/unit/test-app-brkptmgr.rb +56 -0
- data/test/unit/test-app-disassemble.rb +60 -0
- data/test/unit/test-app-file.rb +46 -0
- data/test/unit/test-app-frame.rb +49 -0
- data/test/unit/test-app-options.rb +60 -0
- data/test/unit/test-app-run.rb +19 -0
- data/test/unit/test-app-thread.rb +25 -0
- data/test/unit/test-app-util.rb +17 -0
- data/test/unit/test-base-subcmd.rb +59 -0
- data/test/unit/test-bin-trepan.rb +48 -0
- data/test/unit/test-cmd-alias.rb +50 -0
- data/test/unit/test-cmd-break.rb +80 -0
- data/test/unit/test-cmd-endisable.rb +59 -0
- data/test/unit/test-cmd-help.rb +100 -0
- data/test/unit/test-cmd-kill.rb +47 -0
- data/test/unit/test-cmd-quit.rb +26 -0
- data/test/unit/test-cmd-step.rb +45 -0
- data/test/unit/test-intf-user.rb +45 -0
- data/test/unit/test-io-input.rb +26 -0
- data/test/unit/test-proc-eval.rb +26 -0
- data/test/unit/test-proc-frame.rb +77 -0
- data/test/unit/test-proc-help.rb +15 -0
- data/test/unit/test-proc-hook.rb +29 -0
- data/test/unit/test-proc-load_cmds.rb +40 -0
- data/test/unit/test-proc-main.rb +99 -0
- data/test/unit/test-proc-validate.rb +90 -0
- data/test/unit/test-subcmd-help.rb +48 -0
- metadata +358 -0
@@ -0,0 +1,327 @@
|
|
1
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
require 'linecache'
|
4
|
+
require_relative 'base/cmd'
|
5
|
+
|
6
|
+
class Trepan::Command::ListCommand < Trepan::Command
|
7
|
+
unless defined?(HELP)
|
8
|
+
HELP =
|
9
|
+
"list[>] [MODULE] [FIRST [NUM]]
|
10
|
+
list[>] LOCATION [NUM]
|
11
|
+
|
12
|
+
List source code.
|
13
|
+
|
14
|
+
Without arguments, prints lines centered around the current
|
15
|
+
line. If this is the first list command issued since the debugger
|
16
|
+
command loop was entered, then the current line is the current
|
17
|
+
frame. If a subsequent list command was issued with no intervening
|
18
|
+
frame changing, then that is start the line after we last one
|
19
|
+
previously shown.
|
20
|
+
|
21
|
+
If the command has a '>' suffix, then lines centering is disabled and
|
22
|
+
listing begins at the specificed location.
|
23
|
+
|
24
|
+
The number of line to show is controled by the debugger listsize
|
25
|
+
setting. Use 'set listsize' or 'show listsize' to see or set the
|
26
|
+
value.
|
27
|
+
|
28
|
+
\"list -\" shows lines before a previous listing.
|
29
|
+
|
30
|
+
A LOCATION is a either
|
31
|
+
- number, e.g. 5,
|
32
|
+
- a function, e.g. join or os.path.join
|
33
|
+
- a module, e.g. os or os.path
|
34
|
+
- a filename, colon, and a number, e.g. foo.rb:5,
|
35
|
+
- or a module name and a number, e.g,. os.path:5.
|
36
|
+
- a '.' for the current line number
|
37
|
+
- a '-' for the lines before the current line number
|
38
|
+
|
39
|
+
If the location form is used with a subsequent parameter, the
|
40
|
+
parameter is the starting line number. When there two numbers are
|
41
|
+
given, the last number value is treated as a stopping line unless it
|
42
|
+
is less than the start line, in which case it is taken to mean the
|
43
|
+
number of lines to list instead.
|
44
|
+
|
45
|
+
Wherever a number is expected, it does not need to be a constant --
|
46
|
+
just something that evaluates to a positive integer.
|
47
|
+
|
48
|
+
Some examples:
|
49
|
+
|
50
|
+
list 5 # List centered around line 5
|
51
|
+
list 4+1 # Same as above.
|
52
|
+
list 5> # List starting at line 5
|
53
|
+
list foo.rb:5 # List centered around line 5 of foo.rb
|
54
|
+
list foo.rb 5 # Same as above.
|
55
|
+
list foo.rb:5> # List starting around line 5 of foo.rb
|
56
|
+
list foo.rb 5 6 # list lines 5 and 6 of foo.rb
|
57
|
+
list foo.rb 5 2 # Same as above, since 2 < 5.
|
58
|
+
list foo.rb:5 2 # Same as above
|
59
|
+
list FileUtils.cp # List lines around the FileUtils.cp function.
|
60
|
+
list . # List lines centered from where we currently are stopped
|
61
|
+
list - # List lines previous to those just shown
|
62
|
+
|
63
|
+
The output of the list command give a line number, and some status
|
64
|
+
information about the line and the text of the line. Here is some
|
65
|
+
hypothetical list output modeled roughly around line 251 of one
|
66
|
+
version of this code:
|
67
|
+
|
68
|
+
251 cmd.proc.frame_setup(tf)
|
69
|
+
252 -> brkpt_cmd.run(['break'])
|
70
|
+
253 B01 line = __LINE__
|
71
|
+
254 b02 cmd.run(['list', __LINE__.to_s])
|
72
|
+
255 t03 puts '--' * 10
|
73
|
+
|
74
|
+
Line 251 has nothing special about it. Line 252 is where we are
|
75
|
+
currently stopped. On line 253 there is a breakpoint 1 which is
|
76
|
+
enabled, while at line 255 there is an breakpoint 2 which is
|
77
|
+
disabled."
|
78
|
+
|
79
|
+
ALIASES = %w(l list> l>)
|
80
|
+
CATEGORY = 'files'
|
81
|
+
MAX_ARGS = 3
|
82
|
+
NAME = File.basename(__FILE__, '.rb')
|
83
|
+
SHORT_HELP = 'List source code'
|
84
|
+
end
|
85
|
+
|
86
|
+
# What a f*cking mess. Necessitated I suppose because we want to
|
87
|
+
# allow somewhat flexible parsing with either module names, files or none
|
88
|
+
# and optional line counts or end-line numbers.
|
89
|
+
|
90
|
+
# Parses arguments for the "list" command and returns the tuple:
|
91
|
+
# filename, start, last
|
92
|
+
# or sets these to nil if there was some problem.
|
93
|
+
def parse_list_cmd(args, listsize, center_correction)
|
94
|
+
|
95
|
+
frame = @proc.frame
|
96
|
+
|
97
|
+
container = @proc.frame_container(frame, false)
|
98
|
+
|
99
|
+
# FIXME: put into a helper routine
|
100
|
+
# See also duplicate code in print_location
|
101
|
+
if container[0] != 'file'
|
102
|
+
try_container = container
|
103
|
+
while try_container[0] != 'file' && frame.prev do
|
104
|
+
frame = frame.prev
|
105
|
+
try_container = @proc.frame_container(frame, false)
|
106
|
+
end
|
107
|
+
container = try_container if try_container[0] == 'file'
|
108
|
+
end
|
109
|
+
|
110
|
+
filename = container[1]
|
111
|
+
|
112
|
+
last = nil
|
113
|
+
if args.empty? and not frame
|
114
|
+
errmsg("No Ruby program loaded.")
|
115
|
+
return nil, nil, nil
|
116
|
+
end
|
117
|
+
|
118
|
+
if args.size > 0
|
119
|
+
if args[0] == '-'
|
120
|
+
return no_frame_msg unless @proc.line_no
|
121
|
+
first = [1, @proc.line_no - 2*listsize - 1].max
|
122
|
+
elsif args[0] == '.'
|
123
|
+
return no_frame_msg unless @proc.line_no
|
124
|
+
first = [1, @proc.frame_line - center_correction].max
|
125
|
+
else
|
126
|
+
modfunc, container, first = @proc.parse_position(args[0])
|
127
|
+
if first == nil and modfunc == nil
|
128
|
+
# error should have been shown previously
|
129
|
+
return nil, nil, nil
|
130
|
+
end
|
131
|
+
if args.size == 1
|
132
|
+
first = 1 if !first and modfunc
|
133
|
+
first = [1, first - center_correction].max
|
134
|
+
elsif args.size == 2 or (args.size == 3 and modfunc)
|
135
|
+
opts = {
|
136
|
+
:msg_on_error =>
|
137
|
+
'Starting line expected, got %s.' % args[-1]
|
138
|
+
}
|
139
|
+
num = @proc.get_an_int(args[1], opts)
|
140
|
+
|
141
|
+
return nil, nil, nil unless num
|
142
|
+
if modfunc
|
143
|
+
if first
|
144
|
+
first = num
|
145
|
+
if args.size == 3 and modfunc
|
146
|
+
opts[:msg_on_error] = ('last or count parameter expected, ' +
|
147
|
+
'got: %s.' % args[2])
|
148
|
+
last = @proc.get_an_int(args[2], opts)
|
149
|
+
end
|
150
|
+
else
|
151
|
+
last = num
|
152
|
+
end
|
153
|
+
else
|
154
|
+
first = num - center_correction
|
155
|
+
end
|
156
|
+
if last and last < first
|
157
|
+
# Assume last is a count rather than an end line number
|
158
|
+
last = first + last - 1
|
159
|
+
end
|
160
|
+
elsif not modfunc
|
161
|
+
errmsg('At most 2 parameters allowed when no module' +
|
162
|
+
' name is found/given. Saw: %d parameters' % args.size)
|
163
|
+
return nil, nil, nil
|
164
|
+
else
|
165
|
+
errmsg(('At most 3 parameters allowed when a module' +
|
166
|
+
' name is given. Saw: %d parameters') % args.size)
|
167
|
+
return nil, nil, nil
|
168
|
+
end
|
169
|
+
end
|
170
|
+
elsif !@proc.line_no and frame
|
171
|
+
first = [1, @proc.frame_line - center_correction].max
|
172
|
+
else
|
173
|
+
first = [1, @proc.line_no - center_correction].max
|
174
|
+
end
|
175
|
+
last = first + listsize - 1 unless last
|
176
|
+
|
177
|
+
LineCache::cache(container[1]) unless
|
178
|
+
'file' != container[0] || LineCache::cached?(container[1])
|
179
|
+
return container, first, last
|
180
|
+
end
|
181
|
+
|
182
|
+
def no_frame_msg
|
183
|
+
errmsg("No Ruby program loaded.")
|
184
|
+
return nil, nil, nil
|
185
|
+
end
|
186
|
+
|
187
|
+
def run(args)
|
188
|
+
listsize = settings[:maxlist]
|
189
|
+
center_correction =
|
190
|
+
if args[0][-1..-1] == '>'
|
191
|
+
0
|
192
|
+
else
|
193
|
+
(listsize-1) / 2
|
194
|
+
end
|
195
|
+
|
196
|
+
container, first, last =
|
197
|
+
parse_list_cmd(args[1..-1], listsize, center_correction)
|
198
|
+
frame = @proc.frame
|
199
|
+
return unless container
|
200
|
+
breaklist = @proc.brkpts.line_breaks(container)
|
201
|
+
|
202
|
+
# We now have range information. Do the listing.
|
203
|
+
max_line = LineCache::size(container[1])
|
204
|
+
unless max_line
|
205
|
+
errmsg('File "%s" not found.' % container[1])
|
206
|
+
return
|
207
|
+
end
|
208
|
+
|
209
|
+
if first > max_line
|
210
|
+
errmsg('Bad line range [%d...%d]; file "%s" has only %d lines' %
|
211
|
+
[first, last, container[1], max_line])
|
212
|
+
return
|
213
|
+
end
|
214
|
+
|
215
|
+
if last > max_line
|
216
|
+
# msg('End position changed to last line %d ' % max_line)
|
217
|
+
last = max_line
|
218
|
+
end
|
219
|
+
|
220
|
+
begin
|
221
|
+
first.upto(last).each do |lineno|
|
222
|
+
line = LineCache::getline(container[1], lineno,
|
223
|
+
@proc.reload_on_change).chomp
|
224
|
+
unless line
|
225
|
+
msg('[EOF]')
|
226
|
+
break
|
227
|
+
end
|
228
|
+
s = '%3d' % lineno
|
229
|
+
s = s + ' ' if s.size < 4
|
230
|
+
s += if breaklist.member?(lineno)
|
231
|
+
bp = breaklist[lineno]
|
232
|
+
a_pad = '%02d' % bp.id
|
233
|
+
bp.icon_char
|
234
|
+
else
|
235
|
+
a_pad = ' '
|
236
|
+
' '
|
237
|
+
end
|
238
|
+
s += (frame && lineno == @proc.frame_line &&
|
239
|
+
container == frame.source_container) ? '->' : a_pad
|
240
|
+
msg(s + "\t" + line)
|
241
|
+
@proc.line_no = lineno
|
242
|
+
end
|
243
|
+
rescue => e
|
244
|
+
errmsg e if settings[:debugexcept]
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
if __FILE__ == $0
|
250
|
+
if not (ARGV.size == 1 && ARGV[0] == 'noload')
|
251
|
+
ISEQS__ = {}
|
252
|
+
SCRIPT_ISEQS__ = {}
|
253
|
+
ARGV[0..-1] = ['noload']
|
254
|
+
load(__FILE__)
|
255
|
+
else
|
256
|
+
require_relative '../location'
|
257
|
+
require_relative '../mock'
|
258
|
+
require_relative '../frame'
|
259
|
+
name = File.basename(__FILE__, '.rb')
|
260
|
+
dbgr, cmd = MockDebugger::setup(name)
|
261
|
+
cmd.proc.send('frame_initialize')
|
262
|
+
LineCache::cache(__FILE__)
|
263
|
+
cmd.run(['list'])
|
264
|
+
cmd.run(['list', __FILE__ + ':10'])
|
265
|
+
|
266
|
+
def run_cmd(cmd, args)
|
267
|
+
seps = '--' * 10
|
268
|
+
puts "%s %s %s" % [seps, args.join(' '), seps]
|
269
|
+
cmd.run(args)
|
270
|
+
end
|
271
|
+
|
272
|
+
|
273
|
+
load 'tmpdir.rb'
|
274
|
+
run_cmd(cmd, %w(list tmpdir.rb 10))
|
275
|
+
run_cmd(cmd, %w(list tmpdir.rb))
|
276
|
+
|
277
|
+
# cmd.proc.frame = sys._getframe()
|
278
|
+
# cmd.proc.setup()
|
279
|
+
# cmd.run(['list'])
|
280
|
+
|
281
|
+
run_cmd(cmd, %w(list .))
|
282
|
+
run_cmd(cmd, %w(list 30))
|
283
|
+
|
284
|
+
# cmd.run(['list', '9+1'])
|
285
|
+
|
286
|
+
run_cmd(cmd, %w(list> 10))
|
287
|
+
run_cmd(cmd, %w(list 3000))
|
288
|
+
run_cmd(cmd, %w(list run_cmd))
|
289
|
+
|
290
|
+
p = Proc.new do
|
291
|
+
|x,y| x + y
|
292
|
+
end
|
293
|
+
run_cmd(cmd, %w(list p))
|
294
|
+
|
295
|
+
# Function from a file found via an instruction sequence
|
296
|
+
run_cmd(cmd, %w(list Columnize.columnize))
|
297
|
+
|
298
|
+
# Use Class/method name. 15 isn't in the function - should this be okay?
|
299
|
+
run_cmd(cmd, %w(list Columnize.columnize 15))
|
300
|
+
|
301
|
+
# Start line and count, since 3 < 30
|
302
|
+
run_cmd(cmd, %w(list Columnize.columnize 30 3))
|
303
|
+
|
304
|
+
# Start line finish line
|
305
|
+
run_cmd(cmd, %w(list Columnize.columnize 40 50))
|
306
|
+
|
307
|
+
# puts '--' * 10
|
308
|
+
# cmd.run(['list', os.path.abspath(__file__)+':3', '4'])
|
309
|
+
# puts '--' * 10
|
310
|
+
# cmd.run(['list', os.path.abspath(__file__)+':3', '12-10'])
|
311
|
+
# cmd.run(['list', 'os.path:5'])
|
312
|
+
|
313
|
+
require 'thread_frame'
|
314
|
+
tf = RubyVM::ThreadFrame.current
|
315
|
+
cmd.proc.frame_setup(tf)
|
316
|
+
brkpt_cmd = cmd.proc.instance_variable_get('@commands')['break']
|
317
|
+
brkpt_cmd.run(['break'])
|
318
|
+
line = __LINE__
|
319
|
+
run_cmd(cmd, ['list', __LINE__.to_s])
|
320
|
+
|
321
|
+
disable_cmd = cmd.proc.instance_variable_get('@commands')['disable']
|
322
|
+
disable_cmd.run(['disable', '1'])
|
323
|
+
|
324
|
+
run_cmd(cmd, ['list', line.to_s])
|
325
|
+
run_cmd(cmd, %w(list parse_list_cmd))
|
326
|
+
end
|
327
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
3
|
+
require_relative 'base/cmd'
|
4
|
+
require_relative '../eval'
|
5
|
+
class Trepan::Command::MacroCommand < Trepan::Command
|
6
|
+
|
7
|
+
unless defined?(HELP)
|
8
|
+
HELP =
|
9
|
+
"macro NAME PROC-OBJECT
|
10
|
+
|
11
|
+
Define NAME as a debugger macro. Debugger macros get a list of arguments
|
12
|
+
and should return a command string to use in its place.
|
13
|
+
|
14
|
+
Here is a contrived example that shows how to issue 'finish' if we are in
|
15
|
+
method 'gcd' and 'step' otherwise:
|
16
|
+
|
17
|
+
macro step_unless_gcd Proc.new{|*args| \"$trepan_frame.method == 'gcd' ? 'finish' : 'step'\"}
|
18
|
+
|
19
|
+
Here is another real example. I use the following to debug a
|
20
|
+
debugger command, assuming 'set debug dbgr' is set:
|
21
|
+
|
22
|
+
macro dbgcmd Proc.new{|*args| \"debug $trepan_cmdproc.commands['\#{args[0]}'].run(\#{args.inspect})\"}
|
23
|
+
|
24
|
+
With the above, 'dbgcmd list 5' will debug the debugger 'list' command
|
25
|
+
on the command 'list 5'.
|
26
|
+
|
27
|
+
See also 'show macro'.
|
28
|
+
"
|
29
|
+
|
30
|
+
CATEGORY = 'support'
|
31
|
+
MIN_ARGS = 2 # Need at least this many
|
32
|
+
NAME = File.basename(__FILE__, '.rb')
|
33
|
+
SHORT_HELP = 'Define a macro'
|
34
|
+
end
|
35
|
+
|
36
|
+
def run(args)
|
37
|
+
macro_name = args[1]
|
38
|
+
proc_argstr = @proc.cmd_argstr[macro_name.size..-1].lstrip
|
39
|
+
proc_obj = @proc.debug_eval(proc_argstr, @proc.settings[:maxstring])
|
40
|
+
if proc_obj
|
41
|
+
if proc_obj.is_a?(Proc)
|
42
|
+
@proc.macros[macro_name] = proc_obj
|
43
|
+
msg "Macro \"#{macro_name}\" defined."
|
44
|
+
else
|
45
|
+
errmsg "Expecting a Proc object; got: #{proc_argstr}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
if __FILE__ == $0
|
52
|
+
require_relative '../mock'
|
53
|
+
name = File.basename(__FILE__, '.rb')
|
54
|
+
dbgr, cmd = MockDebugger::setup(name)
|
55
|
+
cmdproc = dbgr.core.processor
|
56
|
+
['macro foo Proc.new{|x, y| x+y}',
|
57
|
+
'macro bad x+1',
|
58
|
+
'macro bad2 1+2'].each do |cmdline|
|
59
|
+
args = cmdline.split
|
60
|
+
cmd_argstr = cmdline[args[0].size..-1].lstrip
|
61
|
+
cmdproc.instance_variable_set('@cmd_argstr', cmd_argstr)
|
62
|
+
cmd.run(args)
|
63
|
+
end
|
64
|
+
p cmdproc.macros
|
65
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
3
|
+
require_relative 'base/cmd'
|
4
|
+
|
5
|
+
class Trepan::Command::NextCommand < Trepan::Command
|
6
|
+
|
7
|
+
unless defined?(HELP)
|
8
|
+
HELP =
|
9
|
+
"next[+|=|-|<|>|!|<>] [EVENT-NAME...] [count]
|
10
|
+
|
11
|
+
Step one statement ignoring steps into function calls at this level.
|
12
|
+
Sometimes this is called 'step over'.
|
13
|
+
|
14
|
+
With an integer argument, perform 'next' that many times. However if
|
15
|
+
an exception occurs at this level, or we 'return' or 'yield' or the
|
16
|
+
thread changes, we stop regardless of count.
|
17
|
+
|
18
|
+
A suffix of '+' on the command or an alias to the command forces to
|
19
|
+
move to another line, while a suffix of '-' does the opposite and
|
20
|
+
disables the requiring a move to a new line. If no suffix is given,
|
21
|
+
the debugger setting 'different' determines this behavior.
|
22
|
+
|
23
|
+
If no suffix is given, the debugger setting 'different'
|
24
|
+
determines this behavior.
|
25
|
+
|
26
|
+
Examples:
|
27
|
+
next # next 1 event, *any* event
|
28
|
+
next 1 # same as above
|
29
|
+
next+ # same but force stopping on a new line
|
30
|
+
next= # same but force stopping on a new line a new frame added
|
31
|
+
next- # same but force stopping on a new line a new frame added
|
32
|
+
next 5/5+0 # same as above
|
33
|
+
next line # next using only line events
|
34
|
+
next call # next using only call call events
|
35
|
+
next<> # next using call return events at this level or below
|
36
|
+
"
|
37
|
+
|
38
|
+
ALIASES = %w(n next+ next- next< next> next<> next! n> n< n! n+ n-
|
39
|
+
n<> n=)
|
40
|
+
CATEGORY = 'running'
|
41
|
+
# execution_set = ['Running']
|
42
|
+
MAX_ARGS = 1 # Need at most this many. FIXME: will be eventually 2
|
43
|
+
NAME = File.basename(__FILE__, '.rb')
|
44
|
+
NEED_RUNNING = true
|
45
|
+
SHORT_HELP = 'Step program without entering called functions'
|
46
|
+
end
|
47
|
+
|
48
|
+
# This method runs the command
|
49
|
+
def run(args) # :nodoc
|
50
|
+
opts = @proc.parse_next_step_suffix(args[0])
|
51
|
+
if args.size == 1
|
52
|
+
# Form is: "next" which means "next 1"
|
53
|
+
step_count = 0
|
54
|
+
else
|
55
|
+
count_str = args[1]
|
56
|
+
opts = {
|
57
|
+
:msg_on_error =>
|
58
|
+
"The 'next' command argument must eval to an integer. Got: %s" %
|
59
|
+
count_str,
|
60
|
+
:min_value => 1
|
61
|
+
}
|
62
|
+
count = @proc.get_an_int(count_str, opts)
|
63
|
+
return unless count
|
64
|
+
# step 1 is core.step_count = 0 or "stop next event"
|
65
|
+
step_count = count - 1
|
66
|
+
end
|
67
|
+
@proc.next(step_count, opts)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
if __FILE__ == $0
|
72
|
+
require_relative '../mock'
|
73
|
+
name = File.basename(__FILE__, '.rb')
|
74
|
+
dbgr, cmd = MockDebugger::setup(name)
|
75
|
+
[%w(n 5), %w(next 1+2), %w(n foo)].each do |c|
|
76
|
+
dbgr.core.step_count = 0
|
77
|
+
cmd.proc.leave_cmd_loop = false
|
78
|
+
result = cmd.run(c)
|
79
|
+
puts 'Run result: %s' % result
|
80
|
+
puts 'step_count %d, leave_cmd_loop: %s' % [dbgr.core.step_count,
|
81
|
+
cmd.proc.leave_cmd_loop]
|
82
|
+
end
|
83
|
+
[%w(n), %w(next+), %w(n-)].each do |c|
|
84
|
+
dbgr.core.step_count = 0
|
85
|
+
cmd.proc.leave_cmd_loop = false
|
86
|
+
result = cmd.run(c)
|
87
|
+
puts cmd.proc.different_pos
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
3
|
+
require_relative 'base/cmd'
|
4
|
+
class Trepan::Command::NoCacheCommand < Trepan::Command
|
5
|
+
|
6
|
+
unless defined?(HELP)
|
7
|
+
HELP = "Remove getinlinecache instructions from instruction sequence."
|
8
|
+
|
9
|
+
CATEGORY = 'running'
|
10
|
+
MAX_ARGS = 0 # Need at most this many
|
11
|
+
NAME = File.basename(__FILE__, '.rb')
|
12
|
+
NEED_STACK = true
|
13
|
+
SHORT_HELP = 'Remove getinlinecache instructions from instruction sequence.'
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
# This method runs the command
|
18
|
+
def run(args) # :nodoc
|
19
|
+
if @proc.frame.iseq
|
20
|
+
puts @proc.frame.iseq.disassemble
|
21
|
+
count = @proc.frame.iseq.killcache
|
22
|
+
msg ("%d locations removed" % count)
|
23
|
+
# puts @proc.frame.iseq.disassemble
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
if __FILE__ == $0
|
29
|
+
require_relative '../mock'
|
30
|
+
name = File.basename(__FILE__, '.rb')
|
31
|
+
dbgr, cmd = MockDebugger::setup(name)
|
32
|
+
cmd.run([name])
|
33
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
3
|
+
require_relative 'base/cmd'
|
4
|
+
require_relative '../eval'
|
5
|
+
class Trepan::Command::PrintCommand < Trepan::Command
|
6
|
+
|
7
|
+
unless defined?(HELP)
|
8
|
+
HELP =
|
9
|
+
"print EXPRESSION
|
10
|
+
|
11
|
+
Print the value of the EXPRESSION. Variables accessible are those of the
|
12
|
+
environment of the selected stack frame, plus globals.
|
13
|
+
|
14
|
+
If the length output string large, the first part of the value is
|
15
|
+
shown and ... indicates it has been truncated."
|
16
|
+
|
17
|
+
# ALIASES = %w(p)
|
18
|
+
CATEGORY = 'data'
|
19
|
+
NAME = File.basename(__FILE__, '.rb')
|
20
|
+
SHORT_HELP = 'Print expression'
|
21
|
+
end
|
22
|
+
|
23
|
+
def run(args)
|
24
|
+
msg @proc.debug_eval(@proc.cmd_argstr, @proc.settings[:maxstring])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
if __FILE__ == $0
|
29
|
+
require_relative '../mock'
|
30
|
+
name = File.basename(__FILE__, '.rb')
|
31
|
+
dbgr, cmd = MockDebugger::setup(name)
|
32
|
+
arg_str = '1 + 2'
|
33
|
+
cmd.proc.instance_variable_set('@cmd_argstr', arg_str)
|
34
|
+
cmd.run([name, arg_str])
|
35
|
+
cmdproc = dbgr.core.processor
|
36
|
+
cmds = dbgr.core.processor.commands
|
37
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
3
|
+
require_relative 'base/cmd'
|
4
|
+
require_relative '../eval'
|
5
|
+
class Trepan::Command::PsCommand < Trepan::Command
|
6
|
+
|
7
|
+
unless defined?(HELP)
|
8
|
+
HELP =
|
9
|
+
"ps ARRAY
|
10
|
+
|
11
|
+
Print the value of the ARRAY in columns and sorted."
|
12
|
+
|
13
|
+
CATEGORY = 'data'
|
14
|
+
MIN_ARGS = 1 # Need least this many
|
15
|
+
NAME = File.basename(__FILE__, '.rb')
|
16
|
+
SHORT_HELP = 'Print array sorted and in columns'
|
17
|
+
end
|
18
|
+
|
19
|
+
def run(args)
|
20
|
+
array = @proc.debug_eval(@proc.cmd_argstr, @proc.settings[:maxstring])
|
21
|
+
# FIXME: should test for enumerable
|
22
|
+
if array.is_a?(Array)
|
23
|
+
msg columnize_commands(array.sort)
|
24
|
+
else
|
25
|
+
errmsg "ps: #{@proc.cmd_argstr} should evaluate an Array not #{array.class}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
if __FILE__ == $0
|
31
|
+
require_relative '../mock'
|
32
|
+
name = File.basename(__FILE__, '.rb')
|
33
|
+
dbgr, cmd = MockDebugger::setup(name)
|
34
|
+
arg_str = '(1..30).to_a'
|
35
|
+
cmd.proc.instance_variable_set('@cmd_argstr', arg_str)
|
36
|
+
cmd.run([name, arg_str])
|
37
|
+
arg_str = '1'
|
38
|
+
cmd.proc.instance_variable_set('@cmd_argstr', arg_str)
|
39
|
+
cmd.run([name, arg_str])
|
40
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
2
|
+
require_relative 'base/cmd'
|
3
|
+
class Trepan::Command::QuitCommand < Trepan::Command
|
4
|
+
|
5
|
+
unless defined?(HELP)
|
6
|
+
HELP =
|
7
|
+
'quit[!] [unconditionally] [exit code] - gentle termination
|
8
|
+
|
9
|
+
The program being debugged is exited via exit() which runs the Kernel
|
10
|
+
at_exit finalizers. If a return code is given, that is the return code
|
11
|
+
passed to exit() - presumably the return code that will be passed back
|
12
|
+
to the OS. If no exit code is given, 0 is used.
|
13
|
+
|
14
|
+
Examples:
|
15
|
+
quit # quit prompting if we are interactive
|
16
|
+
quit conditionally # quit without prompting
|
17
|
+
quit! # same as above
|
18
|
+
quit 0 # same as "quit"
|
19
|
+
quit! 1 # unconditional quit setting exit code 1
|
20
|
+
|
21
|
+
See also the commands "exit" and "kill".'
|
22
|
+
|
23
|
+
ALIASES = %w(quit! q q!)
|
24
|
+
CATEGORY = 'support'
|
25
|
+
NAME = File.basename(__FILE__, '.rb')
|
26
|
+
MAX_ARGS = 2 # Need at most this many
|
27
|
+
SHORT_HELP = 'Quit program - gently'
|
28
|
+
end
|
29
|
+
|
30
|
+
# FIXME: Combine 'quit' and 'exit'. The only difference is
|
31
|
+
# whether exit! or exit is used.
|
32
|
+
|
33
|
+
# This method runs the command
|
34
|
+
def run(args) # :nodoc
|
35
|
+
unconditional =
|
36
|
+
if args.size > 1 && args[1] == 'unconditionally'
|
37
|
+
args.shift
|
38
|
+
true
|
39
|
+
elsif args[0][-1] == '!'
|
40
|
+
true
|
41
|
+
else
|
42
|
+
false
|
43
|
+
end
|
44
|
+
unless unconditional || confirm('Really quit?', false)
|
45
|
+
msg('Quit not confirmed.')
|
46
|
+
return
|
47
|
+
end
|
48
|
+
|
49
|
+
exitrc = (args.size > 1) ? exitrc = Integer(args[1]) rescue 0 : 0
|
50
|
+
# No graceful way to stop threads...
|
51
|
+
exit exitrc
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
if __FILE__ == $0
|
56
|
+
require_relative '../mock'
|
57
|
+
name = File.basename(__FILE__, '.rb')
|
58
|
+
dbgr, cmd = MockDebugger::setup(name)
|
59
|
+
name = File.basename(__FILE__, '.rb')
|
60
|
+
fork { cmd.run([name]) }
|
61
|
+
cmd.run([name, '5'])
|
62
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
2
|
+
require_relative 'base/cmd'
|
3
|
+
class Trepan::Command::RaiseCommand < Trepan::Command
|
4
|
+
|
5
|
+
unless defined?(HELP)
|
6
|
+
HELP =
|
7
|
+
"raise EXCEPTION
|
8
|
+
|
9
|
+
Raise an exception in the debugged program."
|
10
|
+
|
11
|
+
CATEGORY = 'running'
|
12
|
+
MAX_ARGS = 1 # Need at most this many
|
13
|
+
NAME = File.basename(__FILE__, '.rb')
|
14
|
+
SHORT_HELP = 'Raise an exception in the debugged program'
|
15
|
+
end
|
16
|
+
|
17
|
+
# This method runs the command
|
18
|
+
def run(args) # :nodoc
|
19
|
+
exception =
|
20
|
+
if args.size > 1
|
21
|
+
except_str = args[1..-1].join(' ')
|
22
|
+
# Normally would need x.respond_to? && ..
|
23
|
+
# but since we catch errors with debug_eval.. not needed.
|
24
|
+
eval_str = ("%s.ancestors.include?(Exception)" %
|
25
|
+
[except_str])
|
26
|
+
unless @proc.debug_eval_no_errmsg(eval_str)
|
27
|
+
errmsg "\"#{except_str}\" does not inherit Exception."
|
28
|
+
return
|
29
|
+
end
|
30
|
+
@proc.debug_eval_no_errmsg(except_str)
|
31
|
+
else
|
32
|
+
RuntimeError
|
33
|
+
end
|
34
|
+
@proc.step(0)
|
35
|
+
@proc.leave_cmd_loop = true
|
36
|
+
@proc.core.exception = exception
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
if __FILE__ == $0
|
41
|
+
require_relative '../mock'
|
42
|
+
name = File.basename(__FILE__, '.rb')
|
43
|
+
dbgr, cmd = MockDebugger::setup(name)
|
44
|
+
puts cmd.run([name, 'NotanException'])
|
45
|
+
puts cmd.run([name, '[5]'])
|
46
|
+
puts cmd.run([name, 'RuntimeError'])
|
47
|
+
end
|