ruby-debug 0.10.4 → 0.10.5.rc1
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/AUTHORS +5 -0
- data/CHANGES +17 -0
- data/ChangeLog +6086 -3711
- data/README +39 -0
- data/Rakefile +67 -82
- data/cli/ruby-debug/commands/breakpoints.rb +4 -2
- data/cli/ruby-debug/commands/edit.rb +3 -2
- data/cli/ruby-debug/commands/info.rb +5 -4
- data/cli/ruby-debug/commands/irb.rb +7 -8
- data/cli/ruby-debug/commands/list.rb +1 -1
- data/cli/ruby-debug/commands/set.rb +7 -1
- data/cli/ruby-debug/commands/show.rb +8 -3
- data/cli/ruby-debug/processor.rb +10 -4
- data/doc/rdebug.1 +1 -1
- data/rdbg.rb +1 -1
- data/test/base/base.rb +7 -4
- data/test/base/binding.rb +3 -12
- data/test/base/catchpoint.rb +2 -9
- data/test/base/load.rb +18 -14
- data/test/base/reload_bug.rb +2 -2
- data/test/cli/commands/catchpoint_test.rb +1 -13
- data/test/cli/commands/unit/regexp.rb +2 -8
- data/test/data/annotate.cmd +2 -2
- data/test/data/annotate.right +8 -8
- data/test/data/at-exit.cmd +4 -0
- data/test/data/at-exit.right +12 -0
- data/test/data/break_bad.cmd +3 -5
- data/test/data/break_bad.right +4 -6
- data/test/data/break_tracelines.cmd +9 -0
- data/test/data/break_tracelines.right +17 -0
- data/test/data/breakpoints-basename.cmd +2 -0
- data/test/data/breakpoints-basename.right +10 -0
- data/test/data/breakpoints.cmd +0 -1
- data/test/data/breakpoints.right +1 -3
- data/test/data/catch.cmd +1 -0
- data/test/data/catch.right +2 -0
- data/test/data/continue_bad.cmd +4 -0
- data/test/data/continue_bad.right +9 -0
- data/test/data/ctrl.right +2 -1
- data/test/data/dollar-0.right +3 -2
- data/test/data/dollar-0a.right +1 -0
- data/test/data/dollar-0b.right +1 -0
- data/test/data/edit.cmd +1 -1
- data/test/data/edit.right +4 -4
- data/test/data/emacs_basic.cmd +1 -34
- data/test/data/emacs_basic.right +10 -92
- data/test/data/frame.cmd +0 -3
- data/test/data/frame.right +0 -4
- data/test/data/info-file-break.cmd +4 -0
- data/test/data/info-file-break.right +11 -0
- data/test/data/info-thread.right +4 -4
- data/test/data/info-var-bug2.right +2 -2
- data/test/data/info.cmd +0 -1
- data/test/data/info.right +1 -5
- data/test/data/linetrace-jruby.right +23 -0
- data/test/data/list.right +13 -13
- data/test/data/output.right +4 -4
- data/test/data/post-mortem-osx.right +5 -4
- data/test/data/quit.right +9 -0
- data/test/data/raise-jruby.right +26 -0
- data/test/data/raise.right +1 -1
- data/test/data/save.cmd +1 -0
- data/test/data/save.right +4 -2
- data/test/data/stepping.cmd +2 -2
- data/test/data/stepping.right +4 -4
- data/test/data/test-init.right +2 -2
- data/test/data/trace-jruby.right +14 -0
- data/test/example/a/example.rb +1 -0
- data/test/example/at-exit.rb +3 -0
- data/test/example/b/example.rb +1 -0
- data/test/{bp_loop_issue.rb → example/bp_loop_issue.rb} +0 -0
- data/test/example/breakpoints-basename.rb +2 -0
- data/test/{brkpt-class-bug.rb → example/brkpt-class-bug.rb} +0 -0
- data/test/{classes.rb → example/classes.rb} +0 -0
- data/test/{dollar-0.rb → example/dollar-0.rb} +1 -0
- data/test/{except-bug1.rb → example/except-bug1.rb} +0 -0
- data/test/file with space.rb b/data/test/example/file with → space.rb +0 -0
- data/test/{gcd.rb → example/gcd.rb} +0 -0
- data/test/{info-var-bug.rb → example/info-var-bug.rb} +0 -0
- data/test/{info-var-bug2.rb → example/info-var-bug2.rb} +0 -0
- data/test/{null.rb → example/null.rb} +0 -0
- data/test/{output.rb → example/output.rb} +0 -0
- data/test/{pm-bug.rb → example/pm-bug.rb} +0 -0
- data/test/{pm.rb → example/pm.rb} +0 -0
- data/test/{raise.rb → example/raise.rb} +0 -0
- data/test/helper.rb +52 -34
- data/test/rdebug-save.1 +2 -2
- data/test/test-annotate.rb +4 -16
- data/test/test-at-exit.rb +13 -0
- data/test/test-break-bad.rb +14 -25
- data/test/test-breakpoints.rb +13 -14
- data/test/test-brkpt-class-bug.rb +3 -16
- data/test/test-catch.rb +3 -15
- data/test/test-condition.rb +3 -15
- data/test/test-display.rb +3 -15
- data/test/test-dollar-0.rb +23 -35
- data/test/test-edit.rb +4 -16
- data/test/test-emacs-basic.rb +4 -17
- data/test/test-enable.rb +3 -15
- data/test/test-except-bug1.rb +6 -21
- data/test/test-file-with-space.rb +3 -15
- data/test/test-finish.rb +11 -23
- data/test/test-frame.rb +14 -20
- data/test/test-hist.rb +6 -10
- data/test/test-info-thread.rb +13 -21
- data/test/test-info-var.rb +20 -37
- data/test/test-info.rb +16 -15
- data/test/test-list.rb +3 -14
- data/test/test-method.rb +9 -23
- data/test/test-output.rb +3 -16
- data/test/test-pm.rb +16 -38
- data/test/test-quit.rb +3 -20
- data/test/test-raise.rb +3 -15
- data/test/test-save.rb +12 -21
- data/test/test-setshow.rb +3 -15
- data/test/test-source.rb +3 -15
- data/test/test-stepping.rb +3 -15
- data/test/test-trace.rb +22 -45
- metadata +199 -159
- data/VERSION +0 -3
- data/cli/ruby-debug/commands/continue.RB +0 -48
- data/cli/ruby-debug/commands/disassemble.RB +0 -38
- data/cli/ruby-debug/commands/raise.RB +0 -41
- data/cli/ruby-debug/commands/source.RB +0 -44
- data/cli/ruby-debug/processor.RB +0 -484
- data/runner.sh +0 -7
- data/test/except-bug2.rb +0 -7
- data/test/scope-test.rb +0 -8
- data/test/tvar.rb +0 -3
data/VERSION
DELETED
|
@@ -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
|
data/cli/ruby-debug/processor.RB
DELETED
|
@@ -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
|