ruby-debug 0.10.4 → 0.10.5.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. data/AUTHORS +5 -0
  2. data/CHANGES +17 -0
  3. data/ChangeLog +6086 -3711
  4. data/README +39 -0
  5. data/Rakefile +67 -82
  6. data/cli/ruby-debug/commands/breakpoints.rb +4 -2
  7. data/cli/ruby-debug/commands/edit.rb +3 -2
  8. data/cli/ruby-debug/commands/info.rb +5 -4
  9. data/cli/ruby-debug/commands/irb.rb +7 -8
  10. data/cli/ruby-debug/commands/list.rb +1 -1
  11. data/cli/ruby-debug/commands/set.rb +7 -1
  12. data/cli/ruby-debug/commands/show.rb +8 -3
  13. data/cli/ruby-debug/processor.rb +10 -4
  14. data/doc/rdebug.1 +1 -1
  15. data/rdbg.rb +1 -1
  16. data/test/base/base.rb +7 -4
  17. data/test/base/binding.rb +3 -12
  18. data/test/base/catchpoint.rb +2 -9
  19. data/test/base/load.rb +18 -14
  20. data/test/base/reload_bug.rb +2 -2
  21. data/test/cli/commands/catchpoint_test.rb +1 -13
  22. data/test/cli/commands/unit/regexp.rb +2 -8
  23. data/test/data/annotate.cmd +2 -2
  24. data/test/data/annotate.right +8 -8
  25. data/test/data/at-exit.cmd +4 -0
  26. data/test/data/at-exit.right +12 -0
  27. data/test/data/break_bad.cmd +3 -5
  28. data/test/data/break_bad.right +4 -6
  29. data/test/data/break_tracelines.cmd +9 -0
  30. data/test/data/break_tracelines.right +17 -0
  31. data/test/data/breakpoints-basename.cmd +2 -0
  32. data/test/data/breakpoints-basename.right +10 -0
  33. data/test/data/breakpoints.cmd +0 -1
  34. data/test/data/breakpoints.right +1 -3
  35. data/test/data/catch.cmd +1 -0
  36. data/test/data/catch.right +2 -0
  37. data/test/data/continue_bad.cmd +4 -0
  38. data/test/data/continue_bad.right +9 -0
  39. data/test/data/ctrl.right +2 -1
  40. data/test/data/dollar-0.right +3 -2
  41. data/test/data/dollar-0a.right +1 -0
  42. data/test/data/dollar-0b.right +1 -0
  43. data/test/data/edit.cmd +1 -1
  44. data/test/data/edit.right +4 -4
  45. data/test/data/emacs_basic.cmd +1 -34
  46. data/test/data/emacs_basic.right +10 -92
  47. data/test/data/frame.cmd +0 -3
  48. data/test/data/frame.right +0 -4
  49. data/test/data/info-file-break.cmd +4 -0
  50. data/test/data/info-file-break.right +11 -0
  51. data/test/data/info-thread.right +4 -4
  52. data/test/data/info-var-bug2.right +2 -2
  53. data/test/data/info.cmd +0 -1
  54. data/test/data/info.right +1 -5
  55. data/test/data/linetrace-jruby.right +23 -0
  56. data/test/data/list.right +13 -13
  57. data/test/data/output.right +4 -4
  58. data/test/data/post-mortem-osx.right +5 -4
  59. data/test/data/quit.right +9 -0
  60. data/test/data/raise-jruby.right +26 -0
  61. data/test/data/raise.right +1 -1
  62. data/test/data/save.cmd +1 -0
  63. data/test/data/save.right +4 -2
  64. data/test/data/stepping.cmd +2 -2
  65. data/test/data/stepping.right +4 -4
  66. data/test/data/test-init.right +2 -2
  67. data/test/data/trace-jruby.right +14 -0
  68. data/test/example/a/example.rb +1 -0
  69. data/test/example/at-exit.rb +3 -0
  70. data/test/example/b/example.rb +1 -0
  71. data/test/{bp_loop_issue.rb → example/bp_loop_issue.rb} +0 -0
  72. data/test/example/breakpoints-basename.rb +2 -0
  73. data/test/{brkpt-class-bug.rb → example/brkpt-class-bug.rb} +0 -0
  74. data/test/{classes.rb → example/classes.rb} +0 -0
  75. data/test/{dollar-0.rb → example/dollar-0.rb} +1 -0
  76. data/test/{except-bug1.rb → example/except-bug1.rb} +0 -0
  77. data/test/file with space.rb b/data/test/example/file with → space.rb +0 -0
  78. data/test/{gcd.rb → example/gcd.rb} +0 -0
  79. data/test/{info-var-bug.rb → example/info-var-bug.rb} +0 -0
  80. data/test/{info-var-bug2.rb → example/info-var-bug2.rb} +0 -0
  81. data/test/{null.rb → example/null.rb} +0 -0
  82. data/test/{output.rb → example/output.rb} +0 -0
  83. data/test/{pm-bug.rb → example/pm-bug.rb} +0 -0
  84. data/test/{pm.rb → example/pm.rb} +0 -0
  85. data/test/{raise.rb → example/raise.rb} +0 -0
  86. data/test/helper.rb +52 -34
  87. data/test/rdebug-save.1 +2 -2
  88. data/test/test-annotate.rb +4 -16
  89. data/test/test-at-exit.rb +13 -0
  90. data/test/test-break-bad.rb +14 -25
  91. data/test/test-breakpoints.rb +13 -14
  92. data/test/test-brkpt-class-bug.rb +3 -16
  93. data/test/test-catch.rb +3 -15
  94. data/test/test-condition.rb +3 -15
  95. data/test/test-display.rb +3 -15
  96. data/test/test-dollar-0.rb +23 -35
  97. data/test/test-edit.rb +4 -16
  98. data/test/test-emacs-basic.rb +4 -17
  99. data/test/test-enable.rb +3 -15
  100. data/test/test-except-bug1.rb +6 -21
  101. data/test/test-file-with-space.rb +3 -15
  102. data/test/test-finish.rb +11 -23
  103. data/test/test-frame.rb +14 -20
  104. data/test/test-hist.rb +6 -10
  105. data/test/test-info-thread.rb +13 -21
  106. data/test/test-info-var.rb +20 -37
  107. data/test/test-info.rb +16 -15
  108. data/test/test-list.rb +3 -14
  109. data/test/test-method.rb +9 -23
  110. data/test/test-output.rb +3 -16
  111. data/test/test-pm.rb +16 -38
  112. data/test/test-quit.rb +3 -20
  113. data/test/test-raise.rb +3 -15
  114. data/test/test-save.rb +12 -21
  115. data/test/test-setshow.rb +3 -15
  116. data/test/test-source.rb +3 -15
  117. data/test/test-stepping.rb +3 -15
  118. data/test/test-trace.rb +22 -45
  119. metadata +199 -159
  120. data/VERSION +0 -3
  121. data/cli/ruby-debug/commands/continue.RB +0 -48
  122. data/cli/ruby-debug/commands/disassemble.RB +0 -38
  123. data/cli/ruby-debug/commands/raise.RB +0 -41
  124. data/cli/ruby-debug/commands/source.RB +0 -44
  125. data/cli/ruby-debug/processor.RB +0 -484
  126. data/runner.sh +0 -7
  127. data/test/except-bug2.rb +0 -7
  128. data/test/scope-test.rb +0 -8
  129. data/test/tvar.rb +0 -3
data/VERSION DELETED
@@ -1,3 +0,0 @@
1
- # This file was created automatically from data in ext/ruby_debug.c via:
2
- # rake :make_version_file.
3
- 0.10.4
@@ -1,48 +0,0 @@
1
- module Debugger
2
-
3
- # Implements debugger "continue" command.
4
- class ContinueCommand < Command
5
- self.allow_in_post_mortem = false
6
- self.need_context = true
7
- def regexp
8
- /^\s* c(?:ont(?:inue)?)? (?:\s+(.*))? $/x
9
- end
10
-
11
- def execute
12
- unless @state.context
13
- errmsg "We are not in a state we can continue.\n"
14
- return
15
- end
16
- if @match[1] && !@state.context.dead?
17
- if '-' == @match[1]
18
- Debugger.stop if Debugger.started?
19
- else
20
- filename = File.expand_path(@state.file)
21
- line_number = get_int(@match[1], "Continue", 0, nil, 0)
22
- return unless line_number
23
- unless LineCache.trace_line_numbers(filename).member?(line_number)
24
- errmsg("Line %d is not a stopping point in file \"%s\".\n",
25
- line_number, filename)
26
- return
27
- end
28
- @state.context.set_breakpoint(filename, line_number)
29
- end
30
- end
31
- @state.proceed
32
- end
33
-
34
- class << self
35
- def help_command
36
- 'continue'
37
- end
38
-
39
- def help(cmd)
40
- %{
41
- c[ont[inue]][ nnn | -]\trun until program ends, hits a breakpoint or reaches line nnn.
42
-
43
- If - is given then we issue a Debugger.stop to remove tracing the program continues at full speed.
44
- }
45
- end
46
- end
47
- end
48
- end
@@ -1,38 +0,0 @@
1
- module Debugger
2
-
3
- require 'pp'
4
- require 'nodepp'
5
- require 'classtree'
6
- require 'parse_tree'
7
- class Disassemble < Command # :nodoc:
8
- self.allow_in_control = false
9
- @@parse_tree = ParseTree.new(true)
10
-
11
- def regexp
12
- /^\s*(dis(?:assemble)?)\s+/
13
- end
14
-
15
- def execute
16
- expr = @match ? @match.post_match : @input
17
- binding = @state.context ? get_binding : TOPLEVEL_BINDING
18
- method_str = "method(:#{expr})"
19
- if method_obj = debug_eval(method_str, binding)
20
- print @@parse_tree.parse_tree_for_method(method_obj.class,
21
- method_str).inspect
22
- print "#{method_obj}\n"
23
- end
24
- end
25
-
26
- class << self
27
- def help_command
28
- %w|disassemble method-name|
29
- end
30
-
31
- def help(cmd)
32
- %{
33
- dis[assemble] method-name\tdo live unparsing of method name
34
- }
35
- end
36
- end
37
- end if false
38
- end
@@ -1,41 +0,0 @@
1
- module Debugger
2
- class RaiseCommand < Command # :nodoc:
3
- self.allow_in_control = false
4
-
5
- def regexp
6
- /^\s* raise
7
- (?:\s+ (\S+))? \s* $/ix
8
- end
9
-
10
- def execute
11
- excn = @match[1]
12
- exception =
13
- if not excn
14
- # No args given.
15
- RuntimeError
16
- else
17
- unless debug_eval("#{excn}.is_a?(Class)", binding)
18
- errmsg "#{excn} is not known to be a Class\n"
19
- return
20
- end
21
- debug_eval(excn, binding)
22
- end
23
- @state.exception = exception
24
- @state.proceed
25
- end
26
-
27
- class << self
28
- def help_command
29
- 'raise'
30
- end
31
-
32
- def help(cmd)
33
- %{
34
- raise EXCEPTION
35
-
36
- Raise an exception in the debugged program."
37
- }
38
- end
39
- end
40
- end
41
- end
@@ -1,44 +0,0 @@
1
- module Debugger
2
- # Implements debugger "source" command.
3
- class SourceCommand < Command
4
- self.allow_in_control = true
5
-
6
- def regexp
7
- /^\s* so(?:urce)? (\s+ -v)? \s+ (.+) $/x
8
- end
9
-
10
- def execute
11
- if 3 == @match.size then
12
- verbose=true
13
- file=@match[2]
14
- else
15
- verbose=false
16
- file=@match[1]
17
- end
18
-
19
- file = File.expand_path(file).strip
20
- unless File.exist?(file)
21
- errmsg "Command file '#{file}' is not found\n"
22
- return
23
- end
24
- if @state and @state.interface
25
- @state.interface.command_queue += File.open(file).readlines
26
- else
27
- Debugger.run_script(file, @state, verbose)
28
- end
29
- end
30
-
31
- class << self
32
- def help_command
33
- 'source'
34
- end
35
-
36
- def help(cmd)
37
- %{
38
- source FILE\texecutes a file containing debugger commands
39
- }
40
- end
41
- end
42
- end
43
-
44
- end
@@ -1,484 +0,0 @@
1
- require 'ruby-debug/interface'
2
- require 'ruby-debug/command'
3
-
4
- module Debugger
5
-
6
- # Should this be a mixin?
7
- class Processor # :nodoc
8
- attr_accessor :interface
9
- attr_reader :processor
10
- attr_reader :commands
11
-
12
- # Format msg with gdb-style annotation header
13
- def afmt(msg, newline="\n")
14
- "\032\032#{msg}#{newline}"
15
- end
16
-
17
- def aprint(msg)
18
- print afmt(msg) if Debugger.annotate.to_i > 2
19
- end
20
-
21
- # FIXME: use delegate?
22
- def errmsg(*args)
23
- @interface.errmsg(*args)
24
- end
25
-
26
- # Callers of this routine should make sure to use comma to
27
- # separate format argments rather than %. Otherwise it seems that
28
- # if the string you want to print has format specifier, which
29
- # could happen if you are trying to show say a source-code line
30
- # with "puts" or "print" in it, this print routine will give an
31
- # error saying it is looking for more arguments.
32
- def print(*args)
33
- @interface.print(*args)
34
- end
35
-
36
- end
37
-
38
- class CommandProcessor < Processor # :nodoc:
39
- attr_reader :display
40
-
41
- # FIXME: get from Command regexp method.
42
- @@Show_breakpoints_postcmd = [
43
- /^\s*b(?:reak)?/,
44
- /^\s* cond(?:ition)? (?:\s+(\d+)\s*(.*))?$/ix,
45
- /^\s*del(?:ete)?(?:\s+(.*))?$/ix,
46
- /^\s* dis(?:able)? (?:\s+(.*))?$/ix,
47
- /^\s* en(?:able)? (?:\s+(.*))?$/ix,
48
- # "tbreak", "clear",
49
- ]
50
- @@Show_annotations_run = [
51
- /^\s*c(?:ont(?:inue)?)?(?:\s+(.*))?$/,
52
- /^\s*fin(?:ish)?$/,
53
- /^\s*n(?:ext)?([+-])?(?:\s+(.*))?$/,
54
- /^\s*s(?:tep)?([+-])?(?:\s+(.*))?$/
55
- ]
56
-
57
- @@Show_annotations_postcmd = [
58
- /^\s* down (?:\s+(.*))? .*$/x,
59
- /^\s* f(?:rame)? (?:\s+ (.*))? \s*$/x,
60
- /^\s* u(?:p)? (?:\s+(.*))?$/x
61
- ]
62
-
63
- def initialize(interface = LocalInterface.new)
64
- @interface = interface
65
- @commands = []
66
- @display = []
67
-
68
- @mutex = Mutex.new
69
- @last_cmd = nil
70
- @last_file = nil # Filename the last time we stopped
71
- @last_line = nil # line number the last time we stopped
72
- @debugger_breakpoints_were_empty = false # Show breakpoints 1st time
73
- @debugger_displays_were_empty = true # No display 1st time
74
- @debugger_context_was_dead = true # Assume we haven't started.
75
- end
76
-
77
- def interface=(interface)
78
- @mutex.synchronize do
79
- @interface.close if @interface
80
- @interface = interface
81
- end
82
- end
83
-
84
- require 'pathname' # For cleanpath
85
-
86
- # Regularize file name.
87
- # This is also used as a common funnel place if basename is
88
- # desired or if we are working remotely and want to change the
89
- # basename. Or we are eliding filenames.
90
- def self.canonic_file(filename)
91
- # For now we want resolved filenames
92
- if Command.settings[:basename]
93
- File.basename(filename)
94
- else
95
- # Cache this?
96
- Pathname.new(filename).cleanpath.to_s
97
- end
98
- end
99
-
100
- def self.print_location_and_text(file, line)
101
- file_line = "%s:%s\n%s" % [canonic_file(file), line,
102
- Debugger.line_at(file, line)]
103
- # FIXME: use annotations routines
104
- if Debugger.annotate.to_i > 2
105
- file_line = "\032\032source #{file_line}"
106
- elsif ENV['EMACS']
107
- file_line = "\032\032#{file_line}"
108
- end
109
- print file_line
110
- end
111
-
112
- def self.protect(mname)
113
- alias_method "__#{mname}", mname
114
- module_eval %{
115
- def #{mname}(*args)
116
- @mutex.synchronize do
117
- return unless @interface
118
- __#{mname}(*args)
119
- end
120
- rescue IOError, Errno::EPIPE
121
- self.interface = nil
122
- rescue SignalException
123
- raise
124
- rescue Exception => e
125
- unless
126
- print "INTERNAL ERROR!!! #\{$!\}\n" rescue nil
127
- print $!.backtrace.map{|l| "\t#\{l\}"}.join("\n") rescue nil
128
- end
129
- }
130
- end
131
-
132
- def at_breakpoint(context, breakpoint)
133
- aprint 'stopped' if Debugger.annotate.to_i > 2
134
- n = Debugger.breakpoints.index(breakpoint) + 1
135
- file = CommandProcessor.canonic_file(breakpoint.source)
136
- line = breakpoint.pos
137
- if Debugger.annotate.to_i > 2
138
- print afmt("source #{file}:#{line}")
139
- end
140
- print "Breakpoint %d at %s:%s\n", n, file, line
141
- end
142
- protect :at_breakpoint
143
-
144
- def at_catchpoint(context, excpt)
145
- aprint 'stopped' if Debugger.annotate.to_i > 2
146
- file = CommandProcessor.canonic_file(context.frame_file(0))
147
- line = context.frame_line(0)
148
- print afmt("%s:%d" % [file, line]) if ENV['EMACS']
149
- print "Catchpoint at %s:%d: `%s' (%s)\n", file, line, excpt, excpt.class
150
- fs = context.stack_size
151
- tb = caller(0)[-fs..-1]
152
- if tb
153
- for i in tb
154
- print "\tfrom %s\n", i
155
- end
156
- end
157
- end
158
- protect :at_catchpoint
159
-
160
- def at_tracing(context, file, line)
161
- return if defined?(Debugger::RDEBUG_FILE) &&
162
- Debugger::RDEBUG_FILE == file # Don't trace ourself
163
- @last_file = CommandProcessor.canonic_file(file)
164
- file = CommandProcessor.canonic_file(file)
165
- unless file == @last_file and @last_line == line and
166
- Command.settings[:tracing_plus]
167
- print "Tracing(%d):%s:%s %s",
168
- context.thnum, file, line, Debugger.line_at(file, line)
169
- @last_file = file
170
- @last_line = line
171
- end
172
- always_run(context, file, line, 2)
173
- end
174
- protect :at_tracing
175
-
176
- def at_line(context, file, line)
177
- process_commands(context, file, line)
178
- end
179
- protect :at_line
180
-
181
- def at_return(context, file, line)
182
- context.stop_frame = -1
183
- process_commands(context, file, line)
184
- end
185
-
186
- def one_cmd(commands, context, input)
187
- if cmd = commands.find{ |c| c.match(input) }
188
- if context.dead? && cmd.class.need_context
189
- p cmd
190
- print "Command is unavailable\n"
191
- else
192
- cmd.execute
193
- end
194
- else
195
- unknown_cmd = commands.find{|cmd| cmd.class.unknown }
196
- if unknown_cmd
197
- unknown_cmd.execute
198
- else
199
- errmsg "Unknown command: \"#{input}\". Try \"help\".\n"
200
- end
201
- end
202
- end
203
-
204
- private
205
-
206
- # The prompt shown before reading a command.
207
- def prompt(context)
208
- p = '(rdb:%s) ' % (context.dead? ? 'post-mortem' : context.thnum)
209
- p = afmt("pre-prompt")+p+"\n"+afmt("prompt") if
210
- Debugger.annotate.to_i > 2
211
- return p
212
- end
213
-
214
- # Run these commands, for example display commands or possibly
215
- # the list or irb in an "autolist" or "autoirb".
216
- # We return a list of commands that are acceptable to run bound
217
- # to the current state.
218
- def always_run(context, file, line, run_level)
219
- event_cmds = Command.commands.select{|cmd| cmd.event }
220
-
221
- # Remove some commands in post-mortem
222
- event_cmds = event_cmds.find_all do |cmd|
223
- cmd.allow_in_post_mortem
224
- end if context.dead?
225
-
226
- state = State.new(self) do |s|
227
- s.context = context
228
- s.file = file
229
- s.line = line
230
- s.binding = context.frame_binding(0)
231
- s.display = display
232
- s.interface = interface
233
- s.commands = event_cmds
234
- end
235
- @interface.state = state if @interface.respond_to?('state=')
236
-
237
- # Bind commands to the current state.
238
- commands = event_cmds.map{|cmd| cmd.new(state)}
239
-
240
- commands.select do |cmd|
241
- cmd.class.always_run >= run_level
242
- end.each {|cmd| cmd.execute}
243
- return state, commands
244
- end
245
-
246
- # Handle debugger commands
247
- def process_commands(context, file, line)
248
- state, @commands = always_run(context, file, line, 1)
249
- $rdebug_state = state if Command.settings[:debuggertesting]
250
- splitter = lambda do |str|
251
- str.split(/;/).inject([]) do |m, v|
252
- if m.empty?
253
- m << v
254
- else
255
- if m.last[-1] == ?\\
256
- m.last[-1,1] = ''
257
- m.last << ';' << v
258
- else
259
- m << v
260
- end
261
- end
262
- m
263
- end
264
- end
265
-
266
- preloop(@commands, context)
267
- CommandProcessor.print_location_and_text(file, line)
268
- while !state.proceed?
269
- input = if @interface.command_queue.empty?
270
- @interface.read_command(prompt(context))
271
- else
272
- @interface.command_queue.shift
273
- end
274
- break unless input
275
- catch(:debug_error) do
276
- if input == ""
277
- next unless @last_cmd
278
- input = @last_cmd
279
- else
280
- @last_cmd = input
281
- end
282
- splitter[input].each do |cmd|
283
- one_cmd(@commands, context, cmd)
284
- postcmd(@commands, context, cmd)
285
- end
286
- end
287
- end
288
- postloop(@commands, context)
289
- exception = state.exception
290
- @exception = nil
291
- puts "raising exception #{state.exception}"
292
- raise exception if exception
293
- end # process_commands
294
-
295
- def preloop(commands, context)
296
- aprint('stopped') if Debugger.annotate.to_i > 2
297
- if context.dead?
298
- unless @debugger_context_was_dead
299
- if Debugger.annotate.to_i > 2
300
- aprint('exited')
301
- print "The program finished.\n"
302
- end
303
- @debugger_context_was_dead = true
304
- end
305
- end
306
-
307
- if Debugger.annotate.to_i > 2
308
- # if we are here, the stack frames have changed outside the
309
- # command loop (e.g. after a "continue" command), so we show
310
- # the annotations again
311
- breakpoint_annotations(commands, context)
312
- display_annotations(commands, context)
313
- annotation('stack', commands, context, "where")
314
- annotation('variables', commands, context, "info variables") unless
315
- context.dead?
316
- end
317
- end
318
-
319
- def postcmd(commands, context, cmd)
320
- if Debugger.annotate.to_i > 0
321
- cmd = @last_cmd unless cmd
322
- breakpoint_annotations(commands, context) if
323
- @@Show_breakpoints_postcmd.find{|pat| cmd =~ pat}
324
- display_annotations(commands, context)
325
- if @@Show_annotations_postcmd.find{|pat| cmd =~ pat}
326
- annotation('stack', commands, context, "where") if
327
- context.stack_size > 0
328
- annotation('variables', commands, context, "info variables") unless
329
- context.dead?
330
- end
331
- if not context.dead? and @@Show_annotations_run.find{|pat| cmd =~ pat}
332
- aprint 'starting' if Debugger.annotate.to_i > 2
333
-
334
- @debugger_context_was_dead = false
335
- end
336
- end
337
- end
338
-
339
- def postloop(commands, context)
340
- end
341
-
342
- def annotation(label, commands, context, cmd)
343
- print afmt(label)
344
- one_cmd(commands, context, cmd)
345
- ### FIXME ANNOTATE: the following line should be deleted
346
- print "\032\032\n"
347
- end
348
-
349
- def breakpoint_annotations(commands, context)
350
- unless Debugger.breakpoints.empty? and @debugger_breakpoints_were_empty
351
- annotation('breakpoints', commands, context, "info breakpoints")
352
- @debugger_breakpoints_were_empty = Debugger.breakpoints.empty?
353
- end
354
- end
355
-
356
- def display_annotations(commands, context)
357
- return if display.empty?
358
- # have_display = display.find{|d| d[0]}
359
- # return unless have_display and @debugger_displays_were_empty
360
- # @debugger_displays_were_empty = have_display
361
- annotation('display', commands, context, "display")
362
- end
363
-
364
- class State # :nodoc:
365
- attr_accessor :context, :file, :line, :binding
366
- attr_accessor :frame_pos, :previous_line, :display
367
- attr_accessor :interface, :commands, :processor
368
- attr_accessor :exception
369
-
370
- def initialize(processor=nil)
371
- super()
372
- @frame_pos = 0
373
- @previous_line = nil
374
- @proceed = false
375
- @processor = processor
376
- yield self
377
- end
378
-
379
- # FIXME: use delegate?
380
- def errmsg(*args)
381
- @interface.errmsg(*args)
382
- end
383
-
384
- def print(*args)
385
- @interface.print(*args)
386
- end
387
-
388
- def confirm(*args)
389
- @interface.confirm(*args)
390
- end
391
-
392
- def proceed?
393
- @proceed
394
- end
395
-
396
- def proceed
397
- @proceed = true
398
- end
399
- end
400
- end
401
-
402
- class ControlCommandProcessor < Processor # :nodoc:
403
- def initialize(interface)
404
- super()
405
- @interface = interface
406
- @debugger_context_was_dead = true # Assume we haven't started.
407
- end
408
-
409
- def process_commands(verbose=false)
410
- control_cmds = Command.commands.select do |cmd|
411
- cmd.allow_in_control
412
- end
413
- state = State.new(@interface, control_cmds)
414
- @commands = control_cmds.map{|cmd| cmd.new(state) }
415
-
416
- unless @debugger_context_was_dead
417
- if Debugger.annotate.to_i > 2
418
- aprint 'exited'
419
- print "The program finished.\n"
420
- end
421
- @debugger_context_was_dead = true
422
- end
423
-
424
- while input = @interface.read_command(prompt(nil))
425
- print "+#{input}" if verbose
426
- catch(:debug_error) do
427
- if cmd = @commands.find{|c| c.match(input) }
428
- cmd.execute
429
- else
430
- errmsg "Unknown command\n"
431
- end
432
- end
433
- end
434
- rescue IOError, Errno::EPIPE
435
- rescue Exception
436
- print "INTERNAL ERROR!!! #{$!}\n" rescue nil
437
- print $!.backtrace.map{|l| "\t#{l}"}.join("\n") rescue nil
438
- ensure
439
- @interface.close
440
- end
441
-
442
- # The prompt shown before reading a command.
443
- # Note: have an unused 'context' parameter to match the local interface.
444
- def prompt(context)
445
- p = '(rdb:ctrl) '
446
- p = afmt("pre-prompt")+p+"\n"+afmt("prompt") if
447
- Debugger.annotate.to_i > 2
448
- return p
449
- end
450
-
451
- class State # :nodoc:
452
- attr_reader :commands, :interface
453
-
454
- def initialize(interface, commands)
455
- @interface = interface
456
- @commands = commands
457
- end
458
-
459
- def proceed
460
- end
461
-
462
- def errmsg(*args)
463
- @interface.print(*args)
464
- end
465
-
466
- def print(*args)
467
- @interface.print(*args)
468
- end
469
-
470
- def confirm(*args)
471
- 'y'
472
- end
473
-
474
- def context
475
- nil
476
- end
477
-
478
- def file
479
- errmsg "No filename given.\n"
480
- throw :debug_error
481
- end
482
- end # State
483
- end
484
- end