rb8-trepanning 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +3 -0
- data/CHANGES +34 -0
- data/ChangeLog +875 -0
- data/README.textile +59 -0
- data/Rakefile +215 -0
- data/app/.gitignore +1 -0
- data/app/cmd_parse.kpeg +241 -0
- data/app/cmd_parse.rb +212 -0
- data/app/cmd_parser.rb +1948 -0
- data/app/complete.rb +79 -0
- data/app/default.rb +90 -0
- data/app/display.rb +148 -0
- data/app/eventbuffer.rb +147 -0
- data/app/frame.rb +166 -0
- data/app/irb.rb +114 -0
- data/app/options.rb +200 -0
- data/app/run.rb +74 -0
- data/app/util.rb +65 -0
- data/bin/.gitignore +1 -0
- data/bin/trepan8 +115 -0
- data/data/.gitignore +1 -0
- data/data/irbrc +41 -0
- data/interface/.gitignore +1 -0
- data/interface/base_intf.rb +109 -0
- data/interface/client.rb +82 -0
- data/interface/comcodes.rb +20 -0
- data/interface/script.rb +110 -0
- data/interface/server.rb +147 -0
- data/interface/user.rb +165 -0
- data/io/base_io.rb +148 -0
- data/io/input.rb +158 -0
- data/io/null_output.rb +46 -0
- data/io/string_array.rb +156 -0
- data/io/tcpclient.rb +129 -0
- data/io/tcpfns.rb +33 -0
- data/io/tcpserver.rb +141 -0
- data/lib/debugger.rb +8 -0
- data/lib/trepanning.rb +283 -0
- data/processor/.gitignore +1 -0
- data/processor/command-ruby-debug/breakpoints.rb +155 -0
- data/processor/command-ruby-debug/catchpoint.rb +55 -0
- data/processor/command-ruby-debug/condition.rb +49 -0
- data/processor/command-ruby-debug/control.rb +31 -0
- data/processor/command-ruby-debug/display.rb +120 -0
- data/processor/command-ruby-debug/enable.rb +202 -0
- data/processor/command-ruby-debug/frame.rb +199 -0
- data/processor/command-ruby-debug/help.rb +63 -0
- data/processor/command-ruby-debug/info.rb +359 -0
- data/processor/command-ruby-debug/method.rb +84 -0
- data/processor/command-ruby-debug/reload.rb +40 -0
- data/processor/command-ruby-debug/save.rb +90 -0
- data/processor/command-ruby-debug/set.rb +237 -0
- data/processor/command-ruby-debug/show.rb +251 -0
- data/processor/command-ruby-debug/source.rb +36 -0
- data/processor/command-ruby-debug/threads.rb +189 -0
- data/processor/command-ruby-debug/trace.rb +57 -0
- data/processor/command-ruby-debug/variables.rb +199 -0
- data/processor/command.rb +270 -0
- data/processor/command/.gitignore +1 -0
- data/processor/command/alias.rb +54 -0
- data/processor/command/backtrace.rb +123 -0
- data/processor/command/base/cmd.rb +177 -0
- data/processor/command/base/subcmd.rb +230 -0
- data/processor/command/base/submgr.rb +188 -0
- data/processor/command/base/subsubcmd.rb +128 -0
- data/processor/command/base/subsubmgr.rb +199 -0
- data/processor/command/break.rb +114 -0
- data/processor/command/catch.rb +71 -0
- data/processor/command/complete.rb +39 -0
- data/processor/command/continue.rb +57 -0
- data/processor/command/directory.rb +50 -0
- data/processor/command/disable.rb +85 -0
- data/processor/command/display.rb +78 -0
- data/processor/command/down.rb +54 -0
- data/processor/command/edit.rb +79 -0
- data/processor/command/enable.rb +48 -0
- data/processor/command/eval.rb +90 -0
- data/processor/command/exit.rb +66 -0
- data/processor/command/finish.rb +59 -0
- data/processor/command/frame.rb +97 -0
- data/processor/command/help.rb +230 -0
- data/processor/command/help/.gitignore +1 -0
- data/processor/command/help/README +10 -0
- data/processor/command/help/command.txt +58 -0
- data/processor/command/help/examples.txt +16 -0
- data/processor/command/help/filename.txt +40 -0
- data/processor/command/help/location.txt +37 -0
- data/processor/command/help/suffixes.txt +17 -0
- data/processor/command/info.rb +28 -0
- data/processor/command/info_subcmd/.gitignore +1 -0
- data/processor/command/info_subcmd/args.rb +39 -0
- data/processor/command/info_subcmd/breakpoints.rb +80 -0
- data/processor/command/info_subcmd/catch.rb +36 -0
- data/processor/command/info_subcmd/files.rb +39 -0
- data/processor/command/info_subcmd/globals.rb +64 -0
- data/processor/command/info_subcmd/line.rb +30 -0
- data/processor/command/info_subcmd/locals.rb +69 -0
- data/processor/command/info_subcmd/macro.rb +62 -0
- data/processor/command/info_subcmd/program.rb +51 -0
- data/processor/command/info_subcmd/ruby.rb +57 -0
- data/processor/command/info_subcmd/source.rb +74 -0
- data/processor/command/info_subcmd/stack.rb +25 -0
- data/processor/command/info_subcmd/threads.rb +75 -0
- data/processor/command/kill.rb +78 -0
- data/processor/command/list.rb +117 -0
- data/processor/command/macro.rb +68 -0
- data/processor/command/next.rb +79 -0
- data/processor/command/parsetree.rb +56 -0
- data/processor/command/pp.rb +40 -0
- data/processor/command/pr.rb +37 -0
- data/processor/command/ps.rb +40 -0
- data/processor/command/restart.rb +86 -0
- data/processor/command/save.rb +58 -0
- data/processor/command/set.rb +47 -0
- data/processor/command/set_subcmd/.gitignore +1 -0
- data/processor/command/set_subcmd/abbrev.rb +25 -0
- data/processor/command/set_subcmd/auto.rb +27 -0
- data/processor/command/set_subcmd/auto_subcmd/.gitignore +1 -0
- data/processor/command/set_subcmd/auto_subcmd/eval.rb +53 -0
- data/processor/command/set_subcmd/auto_subcmd/irb.rb +33 -0
- data/processor/command/set_subcmd/auto_subcmd/list.rb +33 -0
- data/processor/command/set_subcmd/basename.rb +25 -0
- data/processor/command/set_subcmd/callstyle.rb +46 -0
- data/processor/command/set_subcmd/confirm.rb +24 -0
- data/processor/command/set_subcmd/debug.rb +47 -0
- data/processor/command/set_subcmd/different.rb +61 -0
- data/processor/command/set_subcmd/highlight.rb +43 -0
- data/processor/command/set_subcmd/max.rb +26 -0
- data/processor/command/set_subcmd/max_subcmd/list.rb +49 -0
- data/processor/command/set_subcmd/max_subcmd/stack.rb +50 -0
- data/processor/command/set_subcmd/max_subcmd/string.rb +76 -0
- data/processor/command/set_subcmd/max_subcmd/width.rb +49 -0
- data/processor/command/set_subcmd/reload.rb +42 -0
- data/processor/command/set_subcmd/timer.rb +58 -0
- data/processor/command/set_subcmd/trace.rb +37 -0
- data/processor/command/set_subcmd/trace_subcmd/buffer.rb +42 -0
- data/processor/command/set_subcmd/trace_subcmd/print.rb +41 -0
- data/processor/command/shell.rb +139 -0
- data/processor/command/show.rb +39 -0
- data/processor/command/show_subcmd/.gitignore +1 -0
- data/processor/command/show_subcmd/abbrev.rb +20 -0
- data/processor/command/show_subcmd/alias.rb +46 -0
- data/processor/command/show_subcmd/args.rb +34 -0
- data/processor/command/show_subcmd/auto.rb +28 -0
- data/processor/command/show_subcmd/auto_subcmd/eval.rb +27 -0
- data/processor/command/show_subcmd/auto_subcmd/irb.rb +23 -0
- data/processor/command/show_subcmd/auto_subcmd/list.rb +22 -0
- data/processor/command/show_subcmd/basename.rb +20 -0
- data/processor/command/show_subcmd/callstyle.rb +22 -0
- data/processor/command/show_subcmd/confirm.rb +18 -0
- data/processor/command/show_subcmd/debug.rb +26 -0
- data/processor/command/show_subcmd/debug_subcmd/dbgr.rb +21 -0
- data/processor/command/show_subcmd/debug_subcmd/skip.rb +22 -0
- data/processor/command/show_subcmd/debug_subcmd/step.rb +22 -0
- data/processor/command/show_subcmd/different.rb +26 -0
- data/processor/command/show_subcmd/directories.rb +22 -0
- data/processor/command/show_subcmd/highlight.rb +24 -0
- data/processor/command/show_subcmd/max.rb +27 -0
- data/processor/command/show_subcmd/max_subcmd/list.rb +38 -0
- data/processor/command/show_subcmd/max_subcmd/stack.rb +36 -0
- data/processor/command/show_subcmd/max_subcmd/string.rb +42 -0
- data/processor/command/show_subcmd/max_subcmd/width.rb +37 -0
- data/processor/command/show_subcmd/reload.rb +18 -0
- data/processor/command/show_subcmd/timer.rb +18 -0
- data/processor/command/show_subcmd/trace.rb +29 -0
- data/processor/command/show_subcmd/trace_subcmd/buffer.rb +65 -0
- data/processor/command/show_subcmd/trace_subcmd/print.rb +23 -0
- data/processor/command/show_subcmd/version.rb +23 -0
- data/processor/command/source.rb +134 -0
- data/processor/command/step.rb +81 -0
- data/processor/command/tbreak.rb +19 -0
- data/processor/command/unalias.rb +44 -0
- data/processor/command/undisplay.rb +59 -0
- data/processor/command/up.rb +72 -0
- data/processor/default.rb +56 -0
- data/processor/display.rb +17 -0
- data/processor/eval.rb +113 -0
- data/processor/eventbuf.rb +105 -0
- data/processor/frame.rb +172 -0
- data/processor/help.rb +92 -0
- data/processor/helper.rb +76 -0
- data/processor/hook.rb +134 -0
- data/processor/load_cmds.rb +258 -0
- data/processor/location.rb +174 -0
- data/processor/main.rb +455 -0
- data/processor/mock.rb +136 -0
- data/processor/msg.rb +61 -0
- data/processor/processor.rb +674 -0
- data/processor/running.rb +168 -0
- data/processor/stepping.rb +18 -0
- data/processor/subcmd.rb +161 -0
- data/processor/validate.rb +355 -0
- data/processor/virtual.rb +34 -0
- data/test/data/.gitignore +1 -0
- data/test/data/break_bad.cmd +19 -0
- data/test/data/break_bad.right +29 -0
- data/test/data/break_loop_bug.cmd +5 -0
- data/test/data/break_loop_bug.right +15 -0
- data/test/data/dollar-0.right +2 -0
- data/test/data/dollar-0a.right +2 -0
- data/test/data/dollar-0b.right +2 -0
- data/test/data/edit.cmd +14 -0
- data/test/data/edit.right +24 -0
- data/test/data/file-with-space.cmd +6 -0
- data/test/data/file-with-space.right +4 -0
- data/test/data/printvar.cmd +17 -0
- data/test/data/printvar.right +31 -0
- data/test/data/raise.cmd +11 -0
- data/test/data/raise.right +19 -0
- data/test/data/source.cmd +5 -0
- data/test/data/source.right +18 -0
- data/test/data/stepping-1.9.right +50 -0
- data/test/data/stepping.cmd +21 -0
- data/test/data/stepping.right +48 -0
- data/test/data/trepan8-save.1 +6 -0
- data/test/example/bp_loop_issue.rb +3 -0
- data/test/example/break-bug.rb +7 -0
- data/test/example/brkpt-class-bug.rb +8 -0
- data/test/example/classes.rb +11 -0
- data/test/example/dollar-0.rb +5 -0
- data/test/example/except-bug1.rb +4 -0
- data/test/example/except-bug2.rb +7 -0
- data/test/example/file with space.rb +1 -0
- data/test/example/gcd.rb +18 -0
- data/test/example/info-var-bug.rb +47 -0
- data/test/example/info-var-bug2.rb +2 -0
- data/test/example/null.rb +1 -0
- data/test/example/pm-bug.rb +3 -0
- data/test/example/pm.rb +11 -0
- data/test/example/raise.rb +3 -0
- data/test/integration/.gitignore +4 -0
- data/test/integration/config.yaml +8 -0
- data/test/integration/helper.rb +154 -0
- data/test/integration/test-break_bad.rb +26 -0
- data/test/integration/test-dollar-0.rb +31 -0
- data/test/integration/test-edit.rb +17 -0
- data/test/integration/test-file-with-space.rb +26 -0
- data/test/integration/test-printvar.rb +17 -0
- data/test/integration/test-raise.rb +21 -0
- data/test/integration/test-source.rb +16 -0
- data/test/integration/test-stepping.rb +24 -0
- data/test/unit/.gitignore +1 -0
- data/test/unit/cmd-helper.rb +52 -0
- data/test/unit/mock-helper.rb +12 -0
- data/test/unit/test-app-cmd_parse.rb +97 -0
- data/test/unit/test-app-cmd_parser.rb +23 -0
- data/test/unit/test-app-complete.rb +39 -0
- data/test/unit/test-app-frame.rb +32 -0
- data/test/unit/test-app-options.rb +92 -0
- data/test/unit/test-app-run.rb +14 -0
- data/test/unit/test-app-util.rb +44 -0
- data/test/unit/test-base-cmd.rb +45 -0
- data/test/unit/test-base-subcmd.rb +57 -0
- data/test/unit/test-base-submgr.rb +23 -0
- data/test/unit/test-base-subsubcmd.rb +17 -0
- data/test/unit/test-cmd-alias.rb +48 -0
- data/test/unit/test-cmd-exit.rb +27 -0
- data/test/unit/test-cmd-help.rb +104 -0
- data/test/unit/test-cmd-kill.rb +46 -0
- data/test/unit/test-cmd-source.rb +34 -0
- data/test/unit/test-completion.rb +42 -0
- data/test/unit/test-intf-user.rb +46 -0
- data/test/unit/test-io-input.rb +27 -0
- data/test/unit/test-io-tcp.rb +33 -0
- data/test/unit/test-io-tcpclient.rb +54 -0
- data/test/unit/test-io-tcpfns.rb +17 -0
- data/test/unit/test-io-tcpserver.rb +50 -0
- data/test/unit/test-proc-eval.rb +36 -0
- data/test/unit/test-proc-hook.rb +30 -0
- data/test/unit/test-proc-load_cmds.rb +50 -0
- data/test/unit/test-proc-location.rb +79 -0
- data/test/unit/test-subcmd-help.rb +44 -0
- data/trepan8.gemspec +52 -0
- metadata +391 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
module Trepan
|
|
2
|
+
# Mix-in module to assist in command parsing.
|
|
3
|
+
module FrameFunctions # :nodoc:
|
|
4
|
+
def adjust_frame(frame_pos, absolute, context=@state.context)
|
|
5
|
+
@state.frame_pos = 0 if context != @state.context
|
|
6
|
+
if absolute
|
|
7
|
+
if frame_pos < 0
|
|
8
|
+
abs_frame_pos = context.stack_size + frame_pos
|
|
9
|
+
else
|
|
10
|
+
abs_frame_pos = frame_pos
|
|
11
|
+
end
|
|
12
|
+
else
|
|
13
|
+
abs_frame_pos = @state.frame_pos + frame_pos
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
if abs_frame_pos >= context.stack_size then
|
|
17
|
+
errmsg "Adjusting would put us beyond the oldest (initial) frame.\n"
|
|
18
|
+
return
|
|
19
|
+
elsif abs_frame_pos < 0 then
|
|
20
|
+
errmsg "Adjusting would put us beyond the newest (innermost) frame.\n"
|
|
21
|
+
return
|
|
22
|
+
end
|
|
23
|
+
if @state.frame_pos != abs_frame_pos then
|
|
24
|
+
@state.previous_line = nil
|
|
25
|
+
@state.frame_pos = abs_frame_pos
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
@state.file = context.frame_file(@state.frame_pos)
|
|
29
|
+
@state.line = context.frame_line(@state.frame_pos)
|
|
30
|
+
|
|
31
|
+
print_frame(@state.frame_pos, true)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def get_frame_call(prefix, pos, context)
|
|
35
|
+
id = context.frame_method(pos)
|
|
36
|
+
klass = context.frame_class(pos)
|
|
37
|
+
call_str = ""
|
|
38
|
+
if id
|
|
39
|
+
args = context.frame_args(pos)
|
|
40
|
+
locals = context.frame_locals(pos)
|
|
41
|
+
if OldCommand.settings[:callstyle] != :short && klass
|
|
42
|
+
if OldCommand.settings[:callstyle] == :tracked
|
|
43
|
+
arg_info = context.frame_args_info(pos)
|
|
44
|
+
end
|
|
45
|
+
call_str << "#{klass}."
|
|
46
|
+
end
|
|
47
|
+
call_str << id.id2name
|
|
48
|
+
if args.any?
|
|
49
|
+
call_str << "("
|
|
50
|
+
args.each_with_index do |name, i|
|
|
51
|
+
case OldCommand.settings[:callstyle]
|
|
52
|
+
when :short
|
|
53
|
+
call_str += "%s, " % [name]
|
|
54
|
+
when :last
|
|
55
|
+
klass = locals[name].class
|
|
56
|
+
if klass.inspect.size > 20+3
|
|
57
|
+
klass = klass.inspect[0..20]+"..."
|
|
58
|
+
end
|
|
59
|
+
call_str += "%s#%s, " % [name, klass]
|
|
60
|
+
when :tracked
|
|
61
|
+
if arg_info && arg_info.size > i
|
|
62
|
+
call_str += "#{name}: #{arg_info[i].inspect}, "
|
|
63
|
+
else
|
|
64
|
+
call_str += "%s, " % name
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
if call_str.size > self.class.settings[:width] - prefix.size
|
|
68
|
+
# Strip off trailing ', ' if any but add stuff for later trunc
|
|
69
|
+
call_str[-2..-1] = ",...XX"
|
|
70
|
+
break
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
call_str[-2..-1] = ")" # Strip off trailing ', ' if any
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
return call_str
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def print_frame(pos, adjust = false, context=@state.context)
|
|
80
|
+
file = context.frame_file(pos)
|
|
81
|
+
line = context.frame_line(pos)
|
|
82
|
+
klass = context.frame_class(pos)
|
|
83
|
+
|
|
84
|
+
unless OldCommand.settings[:full_path]
|
|
85
|
+
path_components = file.split(/[\\\/]/)
|
|
86
|
+
if path_components.size > 3
|
|
87
|
+
path_components[0...-3] = '...'
|
|
88
|
+
file = path_components.join(File::ALT_SEPARATOR || File::SEPARATOR)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
frame_num = "#%d " % pos
|
|
93
|
+
call_str = get_frame_call(frame_num, pos, context)
|
|
94
|
+
file_line = "at line %s:%d\n" % [CommandProcessor.canonic_file(file), line]
|
|
95
|
+
print frame_num
|
|
96
|
+
unless call_str.empty?
|
|
97
|
+
print call_str
|
|
98
|
+
print ' '
|
|
99
|
+
if call_str.size + frame_num.size + file_line.size > self.class.settings[:width]
|
|
100
|
+
print "\n "
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
print file_line
|
|
104
|
+
if Trepan.inside_emacs? && adjust
|
|
105
|
+
fmt = (Trepan.annotate.to_i > 1 ?
|
|
106
|
+
"\032\032source %s:%d\n" : "\032\032%s:%d\n")
|
|
107
|
+
print fmt % [CommandProcessor.canonic_file(file), line]
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Check if call stack is truncated. This can happen if
|
|
112
|
+
# Trepan.start is not called low enough in the call stack. An
|
|
113
|
+
# array of additional callstack lines from caller is returned if
|
|
114
|
+
# definitely truncated, false if not, and nil if we don't know.
|
|
115
|
+
#
|
|
116
|
+
# We determine truncation based on a passed in sentinal set via
|
|
117
|
+
# caller which can be nil.
|
|
118
|
+
#
|
|
119
|
+
# First we see if we can find our position in caller. If so, then
|
|
120
|
+
# we compare context position to that in caller using sentinal
|
|
121
|
+
# as a place to start ignoring additional caller entries. sentinal
|
|
122
|
+
# is set by rdebug, but if it's not set, i.e. nil then additional
|
|
123
|
+
# entries are presumably ones that we haven't recorded in context
|
|
124
|
+
def truncated_callstack?(context, sentinal=nil, cs=caller)
|
|
125
|
+
recorded_size = context.stack_size
|
|
126
|
+
to_find_fl = "#{context.frame_file(0)}:#{context.frame_line(0)}"
|
|
127
|
+
top_discard = false
|
|
128
|
+
cs.each_with_index do |fl, i|
|
|
129
|
+
fl.gsub!(/in `.*'$/, '')
|
|
130
|
+
fl.gsub!(/:$/, '')
|
|
131
|
+
if fl == to_find_fl
|
|
132
|
+
top_discard = i
|
|
133
|
+
break
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
if top_discard
|
|
137
|
+
cs = cs[top_discard..-1]
|
|
138
|
+
return false unless cs
|
|
139
|
+
return cs unless sentinal
|
|
140
|
+
if cs.size > recorded_size+2 && cs[recorded_size+2] != sentinal
|
|
141
|
+
# caller seems to truncate recursive calls and we don't.
|
|
142
|
+
# See if we can find sentinal in the first 0..recorded_size+1 entries
|
|
143
|
+
return false if cs[0..recorded_size+1].any?{ |f| f==sentinal }
|
|
144
|
+
return cs
|
|
145
|
+
end
|
|
146
|
+
return false
|
|
147
|
+
end
|
|
148
|
+
return nil
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Implements debugger "where" or "backtrace" command.
|
|
155
|
+
class OldWhereCommand < OldCommand
|
|
156
|
+
def regexp
|
|
157
|
+
/^\s*(?:old\-where)$/
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def execute
|
|
161
|
+
(0...@state.context.stack_size).each do |idx|
|
|
162
|
+
if idx == @state.frame_pos
|
|
163
|
+
print "--> "
|
|
164
|
+
else
|
|
165
|
+
print " "
|
|
166
|
+
end
|
|
167
|
+
print_frame(idx)
|
|
168
|
+
|
|
169
|
+
end
|
|
170
|
+
if truncated_callstack?(@state.context, Trepan.start_sentinal)
|
|
171
|
+
print "Warning: saved frames may be incomplete;\n"
|
|
172
|
+
print "compare debugger backtrace (bt) with Ruby caller(0).\n"
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
class << self
|
|
177
|
+
def help_command
|
|
178
|
+
%w|oldwhere|
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def help(cmd)
|
|
182
|
+
s = if cmd == 'oldwhere'
|
|
183
|
+
%{
|
|
184
|
+
w[here]\tdisplay stack frames
|
|
185
|
+
}
|
|
186
|
+
else
|
|
187
|
+
%{
|
|
188
|
+
bt|backtrace\t\talias for where - display stack frames
|
|
189
|
+
}
|
|
190
|
+
end
|
|
191
|
+
s += %{
|
|
192
|
+
Print the entire stack frame. Each frame is numbered, the most recent
|
|
193
|
+
frame is 0. frame number can be referred to in the "frame" command;
|
|
194
|
+
"up" and "down" add or subtract respectively to frame numbers shown.
|
|
195
|
+
The position of the current frame is marked with -->. }
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
require 'rubygems'; require 'require_relative'
|
|
2
|
+
require_relative '../../app/options'
|
|
3
|
+
module Trepan
|
|
4
|
+
|
|
5
|
+
# Implements debugger "help" command.
|
|
6
|
+
class HelpCommand < OldCommand
|
|
7
|
+
self.allow_in_control = true
|
|
8
|
+
|
|
9
|
+
# An input line is matched against this regular expression. If we have
|
|
10
|
+
# a match, run this command.
|
|
11
|
+
def regexp
|
|
12
|
+
/^\s* h(?:elp)? (?:\s+(.+))? $/x
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# The code that implements this command.
|
|
16
|
+
def execute
|
|
17
|
+
if @match[1]
|
|
18
|
+
args = @match[1].split
|
|
19
|
+
cmds = @state.commands.select do |cmd|
|
|
20
|
+
[cmd.help_command].flatten.include?(args[0])
|
|
21
|
+
end
|
|
22
|
+
else
|
|
23
|
+
args = @match[1]
|
|
24
|
+
cmds = []
|
|
25
|
+
end
|
|
26
|
+
unless cmds.empty?
|
|
27
|
+
help = cmds.map{ |cmd| cmd.help(args) }.join
|
|
28
|
+
help = help.split("\n").map{|l| l.gsub(/^ +/, '')}
|
|
29
|
+
help.shift if help.first && help.first.empty?
|
|
30
|
+
help.pop if help.last && help.last.empty?
|
|
31
|
+
print help.join("\n")
|
|
32
|
+
else
|
|
33
|
+
if args and args[0]
|
|
34
|
+
errmsg "Undefined command: \"#{args[0]}\". Try \"help\"."
|
|
35
|
+
else
|
|
36
|
+
print "#{Trepan::PROGRAM} help v#{Trepan::VERSION}\n" unless
|
|
37
|
+
self.class.settings[:debuggertesting]
|
|
38
|
+
print "Type 'help <command-name>' for help on a specific command\n\n"
|
|
39
|
+
print "Available commands:\n"
|
|
40
|
+
cmds = @state.commands.map{ |cmd| cmd.help_command }
|
|
41
|
+
cmds = cmds.flatten.uniq.sort
|
|
42
|
+
print columnize(cmds, self.class.settings[:width])
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
print "\n"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
class << self
|
|
49
|
+
# The command name listed via 'help'
|
|
50
|
+
def help_command
|
|
51
|
+
'help'
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Returns a String given the help description of this command
|
|
55
|
+
def help(cmd)
|
|
56
|
+
%{
|
|
57
|
+
h[elp]\t\tprint this help
|
|
58
|
+
h[elp] command\tprint help on command
|
|
59
|
+
}
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
module Trepan
|
|
2
|
+
module InfoFunctions # :nodoc:
|
|
3
|
+
def info_catch(*args)
|
|
4
|
+
unless @state.context
|
|
5
|
+
print "No frame selected.\n"
|
|
6
|
+
return
|
|
7
|
+
end
|
|
8
|
+
if Debugger.catchpoints and not Debugger.catchpoints.empty?
|
|
9
|
+
# FIXME: show whether Exception is valid or not
|
|
10
|
+
# print "Exception: is_a?(Class)\n"
|
|
11
|
+
Debugger.catchpoints.each do |exception, hits|
|
|
12
|
+
# print "#{exception}: #{exception.is_a?(Class)}\n"
|
|
13
|
+
print "#{exception}\n"
|
|
14
|
+
end
|
|
15
|
+
else
|
|
16
|
+
print "No exceptions set to be caught.\n"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Implements debugger "info" command.
|
|
22
|
+
class InfoCommand < OldCommand
|
|
23
|
+
self.allow_in_control = true
|
|
24
|
+
Subcommands =
|
|
25
|
+
[
|
|
26
|
+
['display', 2, 'Expressions to display when program stops'],
|
|
27
|
+
['file', 4, 'Info about a particular file read in',
|
|
28
|
+
'
|
|
29
|
+
After the file name is supplied, you can list file attributes that
|
|
30
|
+
you wish to see.
|
|
31
|
+
|
|
32
|
+
Attributes include: "all", "basic", "breakpoint", "lines", "mtime", "path"
|
|
33
|
+
and "sha1".'],
|
|
34
|
+
['files', 5, 'File names and timestamps of files read in'],
|
|
35
|
+
['global_variables', 2, 'Global variables'],
|
|
36
|
+
['instance_variables', 2,
|
|
37
|
+
'Instance variables of the current stack frame'],
|
|
38
|
+
['locals', 2, 'Local variables of the current stack frame'],
|
|
39
|
+
['stack', 2, 'Backtrace of the stack'],
|
|
40
|
+
['thread', 6, 'List info about thread NUM', '
|
|
41
|
+
If no thread number is given, we list info for all threads. \'terse\' and \'verbose\'
|
|
42
|
+
options are possible. If terse, just give summary thread name information. See
|
|
43
|
+
"help info threads" for more detail about this summary information.
|
|
44
|
+
|
|
45
|
+
If \'verbose\' appended to the end of the command, then the entire
|
|
46
|
+
stack trace is given for each thread.'],
|
|
47
|
+
['threads', 7, 'information of currently-known threads', '
|
|
48
|
+
This information includes whether the thread is current (+), if it is
|
|
49
|
+
suspended ($), or ignored (!). The thread number and the top stack
|
|
50
|
+
item. If \'verbose\' is given then the entire stack frame is shown.'],
|
|
51
|
+
['variables', 1,
|
|
52
|
+
'Local and instance variables of the current stack frame']
|
|
53
|
+
].map do |name, min, short_help, long_help|
|
|
54
|
+
SubcmdStruct.new(name, min, short_help, long_help)
|
|
55
|
+
end unless defined?(Subcommands)
|
|
56
|
+
|
|
57
|
+
InfoFileSubcommands =
|
|
58
|
+
[
|
|
59
|
+
['all', 1,
|
|
60
|
+
'All file information available - breakpoints, lines, mtime, path, and sha1'],
|
|
61
|
+
['basic', 2,
|
|
62
|
+
'basic information - path, number of lines'],
|
|
63
|
+
['breakpoints', 2, 'Show trace line numbers',
|
|
64
|
+
'These are the line number where a breakpoint can be set.'],
|
|
65
|
+
['lines', 1, 'Show number of lines in the file'],
|
|
66
|
+
['mtime', 1, 'Show modification time of file'],
|
|
67
|
+
['path', 4, 'Show full file path name for file'],
|
|
68
|
+
['sha1', 1, 'Show SHA1 hash of contents of the file']
|
|
69
|
+
].map do |name, min, short_help, long_help|
|
|
70
|
+
SubcmdStruct.new(name, min, short_help, long_help)
|
|
71
|
+
end unless defined?(InfoFileSubcommands)
|
|
72
|
+
|
|
73
|
+
InfoThreadSubcommands =
|
|
74
|
+
[
|
|
75
|
+
['terse', 1, 'summary information'],
|
|
76
|
+
['verbose', 1, 'summary information and stack frame info'],
|
|
77
|
+
].map do |name, min, short_help, long_help|
|
|
78
|
+
SubcmdStruct.new(name, min, short_help, long_help)
|
|
79
|
+
end unless defined?(InfoThreadSubcommands)
|
|
80
|
+
|
|
81
|
+
def regexp
|
|
82
|
+
/^\s* i(?:nfo)? (?:\s+(.*))?$/ix
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def execute
|
|
86
|
+
if !@match[1] || @match[1].empty?
|
|
87
|
+
errmsg "\"info\" must be followed by the name of an info command:\n"
|
|
88
|
+
print "List of info subcommands:\n\n"
|
|
89
|
+
for subcmd in Subcommands do
|
|
90
|
+
print "info #{subcmd.name} -- #{subcmd.short_help}\n"
|
|
91
|
+
end
|
|
92
|
+
else
|
|
93
|
+
args = @match[1].split(/[ \t]+/)
|
|
94
|
+
param = args.shift
|
|
95
|
+
subcmd = find(Subcommands, param)
|
|
96
|
+
if subcmd
|
|
97
|
+
send("info_#{subcmd.name}", *args)
|
|
98
|
+
else
|
|
99
|
+
errmsg "Unknown info command #{param}\n"
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def info_display(*args)
|
|
105
|
+
unless @state.context
|
|
106
|
+
print "info display not available here.\n"
|
|
107
|
+
return
|
|
108
|
+
end
|
|
109
|
+
if @state.display.find{|d| d[0]}
|
|
110
|
+
print "Auto-display expressions now in effect:\n"
|
|
111
|
+
print "Num Enb Expression\n"
|
|
112
|
+
n = 1
|
|
113
|
+
for d in @state.display
|
|
114
|
+
print "%3d: %s %s\n", n, (d[0] ? 'y' : 'n'), d[1] if
|
|
115
|
+
d[0] != nil
|
|
116
|
+
n += 1
|
|
117
|
+
end
|
|
118
|
+
else
|
|
119
|
+
print "There are no auto-display expressions now.\n"
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def info_file(*args)
|
|
124
|
+
unless args[0]
|
|
125
|
+
info_files
|
|
126
|
+
return
|
|
127
|
+
end
|
|
128
|
+
file = args[0]
|
|
129
|
+
param = args[1]
|
|
130
|
+
|
|
131
|
+
param = 'basic' unless param
|
|
132
|
+
subcmd = find(InfoFileSubcommands, param)
|
|
133
|
+
unless subcmd
|
|
134
|
+
errmsg "Invalid parameter #{param}\n"
|
|
135
|
+
return
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
unless LineCache::cached?(file)
|
|
139
|
+
unless LineCache::cached_script?(file)
|
|
140
|
+
print "File #{file} is not cached\n"
|
|
141
|
+
return
|
|
142
|
+
end
|
|
143
|
+
LineCache::cache(file, Command.settings[:reload_source_on_change])
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
print "File %s", file
|
|
147
|
+
path = LineCache.path(file)
|
|
148
|
+
if %w(all basic path).member?(subcmd.name) and path != file
|
|
149
|
+
print " - %s\n", path
|
|
150
|
+
else
|
|
151
|
+
print "\n"
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
if %w(all basic lines).member?(subcmd.name)
|
|
155
|
+
lines = LineCache.size(file)
|
|
156
|
+
print "\t %d lines\n", lines if lines
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
if %w(all breakpoints).member?(subcmd.name)
|
|
160
|
+
breakpoints = LineCache.trace_line_numbers(file)
|
|
161
|
+
if breakpoints
|
|
162
|
+
print "\tbreakpoint line numbers:\n"
|
|
163
|
+
print columnize(breakpoints.to_a.sort, self.class.settings[:width])
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
if %w(all mtime).member?(subcmd.name)
|
|
168
|
+
stat = LineCache.stat(file)
|
|
169
|
+
print "\t%s\n", stat.mtime if stat
|
|
170
|
+
end
|
|
171
|
+
if %w(all sha1).member?(subcmd.name)
|
|
172
|
+
print "\t%s\n", LineCache.sha1(file)
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def info_instance_variables(*args)
|
|
177
|
+
unless @state.context
|
|
178
|
+
print "info instance_variables not available here.\n"
|
|
179
|
+
return
|
|
180
|
+
end
|
|
181
|
+
obj = debug_eval('self')
|
|
182
|
+
var_list(obj.instance_variables)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def info_locals(*args)
|
|
186
|
+
unless @state.context
|
|
187
|
+
errmsg "info line not available here.\n"
|
|
188
|
+
return
|
|
189
|
+
end
|
|
190
|
+
locals = @state.context.frame_locals(@state.frame_pos)
|
|
191
|
+
locals.keys.sort.each do |name|
|
|
192
|
+
### FIXME: make a common routine
|
|
193
|
+
begin
|
|
194
|
+
s = "#{name} = #{locals[name].inspect}"
|
|
195
|
+
rescue
|
|
196
|
+
begin
|
|
197
|
+
s = "#{name} = #{locals[name].to_s}"
|
|
198
|
+
rescue
|
|
199
|
+
s = "*Error in evaluation*"
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
if s.size > self.class.settings[:width]
|
|
203
|
+
s[self.class.settings[:width]-3 .. -1] = "..."
|
|
204
|
+
end
|
|
205
|
+
print "#{s}\n"
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def info_stack(*args)
|
|
210
|
+
if not @state.context
|
|
211
|
+
errmsg "info stack not available here.\n"
|
|
212
|
+
return
|
|
213
|
+
end
|
|
214
|
+
(0...@state.context.stack_size).each do |idx|
|
|
215
|
+
if idx == @state.frame_pos
|
|
216
|
+
print "--> "
|
|
217
|
+
else
|
|
218
|
+
print " "
|
|
219
|
+
end
|
|
220
|
+
print_frame(idx)
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def info_thread_preamble(arg)
|
|
225
|
+
if not @state.context
|
|
226
|
+
errmsg "info threads not available here.\n"
|
|
227
|
+
return false, false
|
|
228
|
+
end
|
|
229
|
+
verbose = if arg
|
|
230
|
+
subcmd = find(InfoThreadSubcommands, arg)
|
|
231
|
+
unless subcmd
|
|
232
|
+
errmsg "'terse' or 'verbose' expected. Got '#{arg}'\n"
|
|
233
|
+
return false, false
|
|
234
|
+
end
|
|
235
|
+
'verbose' == subcmd.name
|
|
236
|
+
else
|
|
237
|
+
false
|
|
238
|
+
end
|
|
239
|
+
return true, verbose
|
|
240
|
+
end
|
|
241
|
+
private :info_thread_preamble
|
|
242
|
+
|
|
243
|
+
def info_threads(*args)
|
|
244
|
+
ok, verbose = info_thread_preamble(args[0])
|
|
245
|
+
return unless ok
|
|
246
|
+
threads = Debugger.contexts.sort_by{|c| c.thnum}.each do |c|
|
|
247
|
+
display_context(c, !verbose)
|
|
248
|
+
if verbose and not c.ignored?
|
|
249
|
+
(0...c.stack_size).each do |idx|
|
|
250
|
+
print "\t"
|
|
251
|
+
print_frame(idx, false, c)
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def info_thread(*args)
|
|
258
|
+
unless args[0]
|
|
259
|
+
info_threads(args[0])
|
|
260
|
+
return
|
|
261
|
+
end
|
|
262
|
+
ok, verbose = info_thread_preamble(args[1])
|
|
263
|
+
return unless ok
|
|
264
|
+
c = parse_thread_num("info thread" , args[0])
|
|
265
|
+
return unless c
|
|
266
|
+
display_context(c, !verbose)
|
|
267
|
+
if verbose and not c.ignored?
|
|
268
|
+
(0...c.stack_size).each do |idx|
|
|
269
|
+
print "\t"
|
|
270
|
+
print_frame(idx, false, c)
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def info_global_variables(*args)
|
|
276
|
+
unless @state.context
|
|
277
|
+
errmsg "info global_variables not available here.\n"
|
|
278
|
+
return
|
|
279
|
+
end
|
|
280
|
+
var_list(global_variables)
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def info_variables(*args)
|
|
284
|
+
if not @state.context
|
|
285
|
+
errmsg "info variables not available here.\n"
|
|
286
|
+
return
|
|
287
|
+
end
|
|
288
|
+
obj = debug_eval('self')
|
|
289
|
+
locals = @state.context.frame_locals(@state.frame_pos)
|
|
290
|
+
locals['self'] = @state.context.frame_self(@state.frame_pos)
|
|
291
|
+
locals.keys.sort.each do |name|
|
|
292
|
+
next if name =~ /^__dbg_/ # skip debugger pollution
|
|
293
|
+
### FIXME: make a common routine
|
|
294
|
+
begin
|
|
295
|
+
s = "#{name} = #{locals[name].inspect}"
|
|
296
|
+
rescue
|
|
297
|
+
begin
|
|
298
|
+
s = "#{name} = #{locals[name].to_s}"
|
|
299
|
+
rescue
|
|
300
|
+
s = "#{name} = *Error in evaluation*"
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
if s.size > self.class.settings[:width]
|
|
304
|
+
s[self.class.settings[:width]-3 .. -1] = "..."
|
|
305
|
+
end
|
|
306
|
+
s.gsub!('%', '%%') # protect against printf format strings
|
|
307
|
+
print "#{s}\n"
|
|
308
|
+
end
|
|
309
|
+
var_list(obj.instance_variables, obj.instance_eval{binding()})
|
|
310
|
+
var_class_self
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
class << self
|
|
314
|
+
def help_command
|
|
315
|
+
'info'
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
def help(args)
|
|
319
|
+
if args[1]
|
|
320
|
+
s = args[1]
|
|
321
|
+
subcmd = Subcommands.find do |try_subcmd|
|
|
322
|
+
(s.size >= try_subcmd.min) and
|
|
323
|
+
(try_subcmd.name[0..s.size-1] == s)
|
|
324
|
+
end
|
|
325
|
+
if subcmd
|
|
326
|
+
str = subcmd.short_help + '.'
|
|
327
|
+
if 'file' == subcmd.name and args[2]
|
|
328
|
+
s = args[2]
|
|
329
|
+
subsubcmd = InfoFileSubcommands.find do |try_subcmd|
|
|
330
|
+
(s.size >= try_subcmd.min) and
|
|
331
|
+
(try_subcmd.name[0..s.size-1] == s)
|
|
332
|
+
end
|
|
333
|
+
if subsubcmd
|
|
334
|
+
str += "\n" + subsubcmd.short_help + '.'
|
|
335
|
+
else
|
|
336
|
+
str += "\nInvalid file attribute #{args[2]}."
|
|
337
|
+
end
|
|
338
|
+
else
|
|
339
|
+
str += "\n" + subcmd.long_help if subcmd.long_help
|
|
340
|
+
end
|
|
341
|
+
return str
|
|
342
|
+
else
|
|
343
|
+
return "Invalid 'info' subcommand '#{args[1]}'."
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
s = %{
|
|
347
|
+
Generic command for showing things about the program being debugged.
|
|
348
|
+
--
|
|
349
|
+
List of info subcommands:
|
|
350
|
+
--
|
|
351
|
+
}
|
|
352
|
+
for subcmd in Subcommands do
|
|
353
|
+
s += "info #{subcmd.name} -- #{subcmd.short_help}\n"
|
|
354
|
+
end
|
|
355
|
+
return s
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
end
|