rb8-trepanning 0.1.3-universal-ruby-1.9.2
Sign up to get free protection for your applications and to get access to all the features.
- 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 +58 -0
- metadata +388 -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
|