ruby-debug19 0.11.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/AUTHORS +9 -0
  2. data/LICENSE +23 -0
  3. data/bin/rdebug +415 -0
  4. data/cli/ruby-debug.rb +176 -0
  5. data/cli/ruby-debug/command.rb +228 -0
  6. data/cli/ruby-debug/commands/breakpoints.rb +153 -0
  7. data/cli/ruby-debug/commands/catchpoint.rb +55 -0
  8. data/cli/ruby-debug/commands/condition.rb +49 -0
  9. data/cli/ruby-debug/commands/continue.rb +38 -0
  10. data/cli/ruby-debug/commands/control.rb +107 -0
  11. data/cli/ruby-debug/commands/display.rb +120 -0
  12. data/cli/ruby-debug/commands/edit.rb +48 -0
  13. data/cli/ruby-debug/commands/enable.rb +202 -0
  14. data/cli/ruby-debug/commands/eval.rb +176 -0
  15. data/cli/ruby-debug/commands/finish.rb +42 -0
  16. data/cli/ruby-debug/commands/frame.rb +301 -0
  17. data/cli/ruby-debug/commands/help.rb +56 -0
  18. data/cli/ruby-debug/commands/info.rb +469 -0
  19. data/cli/ruby-debug/commands/irb.rb +123 -0
  20. data/cli/ruby-debug/commands/kill.rb +51 -0
  21. data/cli/ruby-debug/commands/list.rb +94 -0
  22. data/cli/ruby-debug/commands/method.rb +84 -0
  23. data/cli/ruby-debug/commands/quit.rb +39 -0
  24. data/cli/ruby-debug/commands/reload.rb +40 -0
  25. data/cli/ruby-debug/commands/save.rb +90 -0
  26. data/cli/ruby-debug/commands/set.rb +237 -0
  27. data/cli/ruby-debug/commands/show.rb +253 -0
  28. data/cli/ruby-debug/commands/source.rb +36 -0
  29. data/cli/ruby-debug/commands/stepping.rb +81 -0
  30. data/cli/ruby-debug/commands/threads.rb +189 -0
  31. data/cli/ruby-debug/commands/tmate.rb +36 -0
  32. data/cli/ruby-debug/commands/trace.rb +57 -0
  33. data/cli/ruby-debug/commands/variables.rb +199 -0
  34. data/cli/ruby-debug/debugger.rb +5 -0
  35. data/cli/ruby-debug/helper.rb +69 -0
  36. data/cli/ruby-debug/interface.rb +232 -0
  37. data/cli/ruby-debug/processor.rb +474 -0
  38. data/rdbg.rb +33 -0
  39. metadata +122 -0
@@ -0,0 +1,176 @@
1
+ module Debugger
2
+ module EvalFunctions # :nodoc:
3
+ def run_with_binding
4
+ binding = @state.context ? get_binding : TOPLEVEL_BINDING
5
+ $__dbg_interface = @state.interface
6
+ eval(<<-EOC, binding)
7
+ __dbg_verbose_save=$VERBOSE; $VERBOSE=false
8
+ def dbg_print(*args)
9
+ $__dbg_interface.print(*args)
10
+ end
11
+ remove_method :puts if self.respond_to?(:puts) &&
12
+ defined?(remove_method)
13
+ def dbg_puts(*args)
14
+ $__dbg_interface.print(*args)
15
+ $__dbg_interface.print("\n")
16
+ end
17
+ $VERBOSE=__dbg_verbose_save
18
+ EOC
19
+ yield binding
20
+ ensure
21
+ $__dbg_interface = nil
22
+ end
23
+ end
24
+
25
+ class EvalCommand < Command # :nodoc:
26
+ self.allow_in_control = true
27
+
28
+ register_setting_get(:autoeval) do
29
+ EvalCommand.unknown
30
+ end
31
+ register_setting_set(:autoeval) do |value|
32
+ EvalCommand.unknown = value
33
+ end
34
+
35
+ def match(input)
36
+ @input = input
37
+ super
38
+ end
39
+
40
+ def regexp
41
+ /^\s*(p|e(?:val)?)\s+/
42
+ end
43
+
44
+ def execute
45
+ expr = @match ? @match.post_match : @input
46
+ run_with_binding do |b|
47
+ print "%s\n", debug_eval(expr, b).inspect
48
+ end
49
+ end
50
+
51
+ class << self
52
+ def help_command
53
+ %w|p eval|
54
+ end
55
+
56
+ def help(cmd)
57
+ if cmd == 'p'
58
+ %{
59
+ p expression\tevaluate expression and print its value
60
+ }
61
+ else
62
+ %{
63
+ e[val] expression\tevaluate expression and print its value,
64
+ \t\t\talias for p.
65
+ * NOTE - to turn on autoeval, use 'set autoeval'
66
+ }
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ class PPCommand < Command # :nodoc:
73
+ self.allow_in_control = true
74
+
75
+ def regexp
76
+ /^\s*pp\s+/
77
+ end
78
+
79
+ def execute
80
+ out = StringIO.new
81
+ run_with_binding do |b|
82
+ PP.pp(debug_eval(@match.post_match, b), out)
83
+ end
84
+ print out.string
85
+ rescue
86
+ out.puts $!.message
87
+ end
88
+
89
+ class << self
90
+ def help_command
91
+ 'pp'
92
+ end
93
+
94
+ def help(cmd)
95
+ %{
96
+ pp expression\tevaluate expression and pretty-print its value
97
+ }
98
+ end
99
+ end
100
+ end
101
+
102
+ class PutLCommand < Command # :nodoc:
103
+ self.allow_in_control = true
104
+
105
+ def regexp
106
+ /^\s*putl\s+/
107
+ end
108
+
109
+ def execute
110
+ out = StringIO.new
111
+ run_with_binding do |b|
112
+ vals = debug_eval(@match.post_match, b)
113
+ if vals.is_a?(Array)
114
+ vals = vals.map{|item| item.to_s}
115
+ print "%s\n", columnize(vals, self.class.settings[:width])
116
+ else
117
+ PP.pp(vals, out)
118
+ print out.string
119
+ end
120
+ end
121
+ rescue
122
+ out.puts $!.message
123
+ end
124
+
125
+ class << self
126
+ def help_command
127
+ 'putl'
128
+ end
129
+
130
+ def help(cmd)
131
+ %{
132
+ putl expression\t\tevaluate expression, an array, and columnize its value
133
+ }
134
+ end
135
+ end
136
+ end
137
+
138
+ class PSCommand < Command # :nodoc:
139
+ self.allow_in_control = true
140
+
141
+ include EvalFunctions
142
+
143
+ def regexp
144
+ /^\s*ps\s+/
145
+ end
146
+
147
+ def execute
148
+ out = StringIO.new
149
+ run_with_binding do |b|
150
+ vals = debug_eval(@match.post_match, b)
151
+ if vals.is_a?(Array)
152
+ vals = vals.map{|item| item.to_s}
153
+ print "%s\n", columnize(vals.sort!, self.class.settings[:width])
154
+ else
155
+ PP.pp(vals, out)
156
+ print out.string
157
+ end
158
+ end
159
+ rescue
160
+ out.puts $!.message
161
+ end
162
+
163
+ class << self
164
+ def help_command
165
+ 'ps'
166
+ end
167
+
168
+ def help(cmd)
169
+ %{
170
+ ps expression\tevaluate expression, an array, sort, and columnize its value
171
+ }
172
+ end
173
+ end
174
+ end
175
+
176
+ end
@@ -0,0 +1,42 @@
1
+ module Debugger
2
+ # Implements the debugger 'finish' command.
3
+ class FinishCommand < Command
4
+ self.allow_in_post_mortem = false
5
+ self.need_context = true
6
+
7
+ def regexp
8
+ /^\s*fin(?:ish)? (?:\s+(.*))?$/x
9
+ end
10
+
11
+ def execute
12
+ max_frame = @state.context.stack_size - @state.frame_pos
13
+ if !@match[1] or @match[1].empty?
14
+ frame_pos = @state.frame_pos
15
+ else
16
+ frame_pos = get_int(@match[1], "Finish", 0, max_frame-1, 0)
17
+ return nil unless frame_pos
18
+ end
19
+ @state.context.stop_frame = frame_pos
20
+ @state.frame_pos = 0
21
+ @state.proceed
22
+ end
23
+
24
+ class << self
25
+ def help_command
26
+ 'finish'
27
+ end
28
+
29
+ def help(cmd)
30
+ %{
31
+ fin[ish] [frame-number]\tExecute until selected stack frame returns.
32
+
33
+ If no frame number is given, we run until the currently selected frame
34
+ returns. The currently selected frame starts out the most-recent
35
+ frame or 0 if no frame positioning (e.g "up", "down" or "frame") has
36
+ been performed. If a frame number is given we run until that frame
37
+ returns.
38
+ }
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,301 @@
1
+ module Debugger
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 Command.settings[:callstyle] != :short && klass
42
+ if Command.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 Command.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 Command.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 ENV['EMACS'] && adjust
105
+ fmt = (Debugger.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
+ # Debugger.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 WhereCommand < Command
156
+ def regexp
157
+ /^\s*(?:w(?:here)?|bt|backtrace)$/
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, Debugger.start_sentinal)
171
+ print "Warning: saved frames may be incomplete; compare with caller(0).\n"
172
+ end
173
+ end
174
+
175
+ class << self
176
+ def help_command
177
+ %w|where backtrace|
178
+ end
179
+
180
+ def help(cmd)
181
+ s = if cmd == 'where'
182
+ %{
183
+ w[here]\tdisplay stack frames
184
+ }
185
+ else
186
+ %{
187
+ bt|backtrace\t\talias for where - display stack frames
188
+ }
189
+ end
190
+ s += %{
191
+ Print the entire stack frame. Each frame is numbered, the most recent
192
+ frame is 0. frame number can be referred to in the "frame" command;
193
+ "up" and "down" add or subtract respectively to frame numbers shown.
194
+ The position of the current frame is marked with -->. }
195
+ end
196
+ end
197
+ end
198
+
199
+ class UpCommand < Command # :nodoc:
200
+ def regexp
201
+ /^\s* u(?:p)? (?:\s+(.*))?$/x
202
+ end
203
+
204
+ def execute
205
+ pos = get_int(@match[1], "Up")
206
+ return unless pos
207
+ adjust_frame(pos, false)
208
+ end
209
+
210
+ class << self
211
+ def help_command
212
+ 'up'
213
+ end
214
+
215
+ def help(cmd)
216
+ %{
217
+ up[count]\tmove to higher frame
218
+ }
219
+ end
220
+ end
221
+ end
222
+
223
+ class DownCommand < Command # :nodoc:
224
+ def regexp
225
+ /^\s* down (?:\s+(.*))? .*$/x
226
+ end
227
+
228
+ def execute
229
+ pos = get_int(@match[1], "Down")
230
+ return unless pos
231
+ adjust_frame(-pos, false)
232
+ end
233
+
234
+ class << self
235
+ def help_command
236
+ 'down'
237
+ end
238
+
239
+ def help(cmd)
240
+ %{
241
+ down[count]\tmove to lower frame
242
+ }
243
+ end
244
+ end
245
+ end
246
+
247
+ class FrameCommand < Command # :nodoc:
248
+ def regexp
249
+ / ^\s*
250
+ f(?:rame)?
251
+ (?: \s+ (\S+))? \s*
252
+ (?: thread \s+ (.*))? \s*
253
+ $/x
254
+ end
255
+
256
+ def execute
257
+ if not @match[1]
258
+ pos = 0
259
+ else
260
+ pos = get_int(@match[1], "Frame")
261
+ return unless pos
262
+ end
263
+ if @match[2]
264
+ context = parse_thread_num('frame', @match[2])
265
+ unless context
266
+ errmsg "Thread #{@match[2]} doesn't exist.\n"
267
+ return
268
+ end
269
+ else
270
+ context = @state.context
271
+ end
272
+ adjust_frame(pos, true, context)
273
+ end
274
+
275
+ class << self
276
+ def help_command
277
+ 'frame'
278
+ end
279
+
280
+ def help(cmd)
281
+ %{
282
+ f[rame] [frame-number [thread thread-number]]
283
+ Move the current frame to the specified frame number, or the
284
+ 0 if no frame-number has been given.
285
+
286
+ A negative number indicates position from the other end. So
287
+ 'frame -1' moves to the oldest frame, and 'frame 0' moves to
288
+ the newest frame.
289
+
290
+ Without an argument, the command prints the current stack
291
+ frame. Since the current position is redisplayed, it may trigger a
292
+ resyncronization if there is a front end also watching over
293
+ things.
294
+
295
+ If a thread number is given then we set the context for evaluating
296
+ expressions to that frame of that thread.
297
+ }
298
+ end
299
+ end
300
+ end
301
+ end