ruby-debug 0.9.3 → 0.10.0
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 +1 -0
- data/CHANGES +41 -0
- data/ChangeLog +0 -0
- data/README +27 -13
- data/Rakefile +220 -0
- data/bin/rdebug +116 -42
- data/cli/ruby-debug.rb +33 -3
- data/cli/ruby-debug/command.rb +49 -12
- data/cli/ruby-debug/commands/breakpoints.rb +47 -64
- data/cli/ruby-debug/commands/control.rb +41 -13
- data/cli/ruby-debug/commands/display.rb +35 -18
- data/cli/ruby-debug/commands/enable.rb +159 -0
- data/cli/ruby-debug/commands/eval.rb +78 -4
- data/cli/ruby-debug/commands/frame.rb +67 -42
- data/cli/ruby-debug/commands/help.rb +21 -17
- data/cli/ruby-debug/commands/info.rb +210 -0
- data/cli/ruby-debug/commands/irb.rb +9 -1
- data/cli/ruby-debug/commands/list.rb +11 -8
- data/cli/ruby-debug/commands/method.rb +12 -23
- data/cli/ruby-debug/commands/script.rb +14 -9
- data/cli/ruby-debug/commands/settings.rb +174 -39
- data/cli/ruby-debug/commands/show.rb +193 -0
- data/cli/ruby-debug/commands/stepping.rb +15 -10
- data/cli/ruby-debug/commands/threads.rb +55 -56
- data/cli/ruby-debug/commands/variables.rb +27 -27
- data/cli/ruby-debug/helper.rb +134 -0
- data/cli/ruby-debug/interface.rb +46 -15
- data/cli/ruby-debug/processor.rb +156 -25
- data/doc/rdebug.1 +236 -0
- data/runner.sh +7 -0
- data/test/breakpoints.cmd +43 -0
- data/test/breakpoints.right +94 -0
- data/test/display.cmd +18 -0
- data/test/display.right +37 -0
- data/test/frame.cmd +21 -0
- data/test/frame.right +45 -0
- data/test/gcd.rb +18 -0
- data/test/help.cmd +12 -0
- data/test/help.right +4 -0
- data/test/helper.rb +87 -0
- data/test/info-var-bug.rb +45 -0
- data/test/info-var.cmd +23 -0
- data/test/info-var.right +47 -0
- data/test/info.cmd +12 -0
- data/test/info.right +35 -0
- data/test/quit.cmd +9 -0
- data/test/quit.right +22 -0
- data/test/setshow.cmd +44 -0
- data/test/setshow.right +73 -0
- data/test/stepping.cmd +17 -0
- data/test/stepping.right +40 -0
- data/test/tdebug.rb +196 -0
- data/test/test-breakpoints.rb +28 -0
- data/test/test-columnize.rb +46 -0
- data/test/test-display.rb +26 -0
- data/test/test-frame.rb +27 -0
- data/test/test-help.rb +44 -0
- data/test/test-info-var.rb +33 -0
- data/test/test-info.rb +28 -0
- data/test/test-quit.rb +28 -0
- data/test/test-ruby-debug-base.rb +76 -0
- data/test/test-setshow.rb +24 -0
- data/test/test-stepping.rb +26 -0
- metadata +63 -22
@@ -0,0 +1,193 @@
|
|
1
|
+
module Debugger
|
2
|
+
# Mix-in module to showing settings
|
3
|
+
module ShowFunctions # :nodoc:
|
4
|
+
def show_setting(setting_name)
|
5
|
+
case setting_name
|
6
|
+
when /^annotate$/
|
7
|
+
Debugger.annotate ||= 0
|
8
|
+
return ("Annotation level is #{Debugger.annotate}")
|
9
|
+
when /^args$/
|
10
|
+
if Command.settings[:argv] and Command.settings[:argv].size > 0
|
11
|
+
args = Command.settings[:argv][1..-1].join(' ')
|
12
|
+
else
|
13
|
+
args = ''
|
14
|
+
end
|
15
|
+
return "Argument list to give program being debugged when it is started is \"#{args}\"."
|
16
|
+
when /^autolist$/
|
17
|
+
on_off = Command.settings[:autolist] > 0
|
18
|
+
return "autolist is #{show_onoff(on_off)}."
|
19
|
+
when /^autoeval$/
|
20
|
+
on_off = Command.settings[:autoeval]
|
21
|
+
return "autoeval is #{show_onoff(on_off)}."
|
22
|
+
when /^autoreload$/
|
23
|
+
on_off = Command.settings[:reload_source_on_change]
|
24
|
+
return "autoreload is #{show_onoff(on_off)}."
|
25
|
+
when /^autoirb$/
|
26
|
+
on_off = Command.settings[:autoirb] > 0
|
27
|
+
return "autoirb is #{show_onoff(on_off)}."
|
28
|
+
when /^basename$/
|
29
|
+
on_off = Command.settings[:basename]
|
30
|
+
return "basename is #{show_onoff(on_off)}."
|
31
|
+
when /^callstyle$/
|
32
|
+
style = Command.settings[:callstyle]
|
33
|
+
return "Frame call-display style is #{style}."
|
34
|
+
when /^debuggertesting$/
|
35
|
+
on_off = Command.settings[:debuggertesting]
|
36
|
+
return "Currently testing the debugger is #{show_onoff(on_off)}."
|
37
|
+
when /^forcestep$/
|
38
|
+
on_off = self.class.settings[:force_stepping]
|
39
|
+
return "force-stepping is #{show_onoff(on_off)}."
|
40
|
+
when /^fullpath$/
|
41
|
+
on_off = Command.settings[:full_path]
|
42
|
+
return "Displaying frame's full file names is #{show_onoff(on_off)}."
|
43
|
+
when /^history(:?\s+(filename|save|size))?$/
|
44
|
+
args = @match[1].split
|
45
|
+
interface = @state.interface
|
46
|
+
if args[1]
|
47
|
+
show_save = show_size = show_filename = false
|
48
|
+
prefix = false
|
49
|
+
if args[1] == "save"
|
50
|
+
show_save = true
|
51
|
+
elsif args[1] == "size"
|
52
|
+
show_size = true
|
53
|
+
elsif args[1] == "filename"
|
54
|
+
show_filename = true
|
55
|
+
end
|
56
|
+
else
|
57
|
+
show_save = show_size = show_filename = true
|
58
|
+
prefix = true
|
59
|
+
end
|
60
|
+
s = []
|
61
|
+
if show_filename
|
62
|
+
msg = (prefix ? "filename: " : "") +
|
63
|
+
"The filename in which to record the command history is " +
|
64
|
+
"#{interface.histfile.inspect}"
|
65
|
+
s << msg
|
66
|
+
end
|
67
|
+
if show_save
|
68
|
+
msg = (prefix ? "save: " : "") +
|
69
|
+
"Saving of history save is #{show_onoff(interface.history_save)}."
|
70
|
+
s << msg
|
71
|
+
end
|
72
|
+
if show_size
|
73
|
+
msg = (prefix ? "size: " : "") +
|
74
|
+
"Debugger history size is #{interface.history_length}"
|
75
|
+
s << msg
|
76
|
+
end
|
77
|
+
return s.join("\n")
|
78
|
+
when /^keep-frame-bindings$/
|
79
|
+
on_off = Debugger.keep_frame_binding?
|
80
|
+
return "keep-frame-bindings is #{show_onoff(on_off)}."
|
81
|
+
when /^linetrace$/
|
82
|
+
on_off = Debugger.tracing
|
83
|
+
return "line tracing is #{show_onoff(on_off)}."
|
84
|
+
when /^linetrace\+$/
|
85
|
+
on_off = Command.settings[:tracing_plus]
|
86
|
+
if on_off
|
87
|
+
return "line tracing style is different consecutive lines."
|
88
|
+
else
|
89
|
+
return "line tracing style is every line."
|
90
|
+
end
|
91
|
+
when /^listsize$/
|
92
|
+
listlines = Command.settings[:listsize]
|
93
|
+
return "Number of source lines to list by default is #{listlines}."
|
94
|
+
when /^port$/
|
95
|
+
return "server port is #{Debugger::PORT}."
|
96
|
+
when /^post-mortem$/
|
97
|
+
on_off = Debugger.post_mortem
|
98
|
+
return "post-mortem handling is #{show_onoff(on_off)}."
|
99
|
+
when /^trace$/
|
100
|
+
on_off = Command.settings[:stack_trace_on_error]
|
101
|
+
return "Displaying stack trace is #{show_onoff(on_off)}."
|
102
|
+
when /^version$/
|
103
|
+
return "ruby-debug #{Debugger::VERSION}"
|
104
|
+
when /^width$/
|
105
|
+
return "width is #{self.class.settings[:width]}."
|
106
|
+
else
|
107
|
+
return "Unknown show subcommand #{setting_name}."
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class ShowCommand < Command # :nodoc:
|
113
|
+
|
114
|
+
SubcmdStruct=Struct.new(:name, :min, :short_help) unless
|
115
|
+
defined?(SubcmdStruct)
|
116
|
+
Subcommands =
|
117
|
+
[
|
118
|
+
['annotate', 2, "Show annotation level"],
|
119
|
+
['args', 2,
|
120
|
+
"Show argument list to give program being debugged when it is started"],
|
121
|
+
['autoeval', 4, "Show if unrecognized command are evaluated"],
|
122
|
+
['autolist', 4, "Show if 'list' commands is run on breakpoints"],
|
123
|
+
['autoirb', 4, "Show if IRB is invoked on debugger stops"],
|
124
|
+
['autoreload', 4, "Show if source code is reloaded when changed"],
|
125
|
+
['basename', 1, "Show if basename used in reporting files"],
|
126
|
+
['callstyle', 2, "Show paramater style used showing call frames"],
|
127
|
+
['forcestep', 1, "Show if sure 'next/step' forces move to a new line"],
|
128
|
+
['fullpath', 2, "Show if full file names are displayed in frames"],
|
129
|
+
['history', 2, "Generic command for showing command history parameters"],
|
130
|
+
['keep-frame-bindings', 1, "Save frame binding on each call"],
|
131
|
+
['linetrace', 3, "Show line execution tracing"],
|
132
|
+
['linetrace+', 10,
|
133
|
+
"Show if consecutive lines should be different are shown in tracing"],
|
134
|
+
['listsize', 3, "Show number of source lines to list by default"],
|
135
|
+
['port', 1, "Show server port"],
|
136
|
+
['trace', 1,
|
137
|
+
"Show if a stack trace is displayed when 'eval' raises exception"],
|
138
|
+
['version', 1,
|
139
|
+
"Show what version of the debugger this is"],
|
140
|
+
['width', 1,
|
141
|
+
"Show the number of characters the debugger thinks are in a line"],
|
142
|
+
].map do |name, min, short_help|
|
143
|
+
SubcmdStruct.new(name, min, short_help)
|
144
|
+
end unless defined?(Subcommands)
|
145
|
+
|
146
|
+
self.control = true
|
147
|
+
|
148
|
+
def regexp
|
149
|
+
/^show (?: \s+ (.+) )?$/xi
|
150
|
+
end
|
151
|
+
|
152
|
+
def execute
|
153
|
+
if not @match[1]
|
154
|
+
print "\"show\" must be followed by the name of an show command:\n"
|
155
|
+
print "List of show subcommands:\n\n"
|
156
|
+
for subcmd in Subcommands do
|
157
|
+
print "show #{subcmd.name} -- #{subcmd.short_help}\n"
|
158
|
+
end
|
159
|
+
else
|
160
|
+
subcmd, arg = @match[1].split(/[ \t]+/)
|
161
|
+
subcmd.downcase!
|
162
|
+
for try_subcmd in Subcommands do
|
163
|
+
if (subcmd.size >= try_subcmd.min) and
|
164
|
+
(try_subcmd.name[0..subcmd.size-1] == subcmd)
|
165
|
+
print "%s\n" % show_setting(try_subcmd.name)
|
166
|
+
return
|
167
|
+
end
|
168
|
+
end
|
169
|
+
print "Unknown show command #{subcmd}\n"
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
class << self
|
174
|
+
def help_command
|
175
|
+
"show"
|
176
|
+
end
|
177
|
+
|
178
|
+
def help(cmd)
|
179
|
+
s = "
|
180
|
+
Generic command for showing things about the debugger.
|
181
|
+
|
182
|
+
--
|
183
|
+
List of show subcommands:
|
184
|
+
--
|
185
|
+
"
|
186
|
+
for subcmd in Subcommands do
|
187
|
+
s += "show #{subcmd.name} -- #{subcmd.short_help}\n"
|
188
|
+
end
|
189
|
+
return s
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
@@ -3,12 +3,13 @@ module Debugger
|
|
3
3
|
self.need_context = true
|
4
4
|
|
5
5
|
def regexp
|
6
|
-
/^\s*n(?:ext)?([
|
6
|
+
/^\s*n(?:ext)?([+])?(?:\s+(.*))?$/
|
7
7
|
end
|
8
8
|
|
9
9
|
def execute
|
10
10
|
force = @match[1] == '+' || (@match[1].nil? && Command.settings[:force_stepping])
|
11
|
-
steps = @match[2]
|
11
|
+
steps = get_int(@match[2], "Next", 1)
|
12
|
+
return unless steps
|
12
13
|
@state.context.step_over steps, @state.frame_pos, force
|
13
14
|
@state.proceed
|
14
15
|
end
|
@@ -20,7 +21,7 @@ module Debugger
|
|
20
21
|
|
21
22
|
def help(cmd)
|
22
23
|
%{
|
23
|
-
n[ext][+][ nnn]\tstep over once or nnn times,
|
24
|
+
n[ext][+]?[ nnn]\tstep over once or nnn times,
|
24
25
|
\t\t'+' forces to move to another line
|
25
26
|
}
|
26
27
|
end
|
@@ -31,12 +32,13 @@ module Debugger
|
|
31
32
|
self.need_context = true
|
32
33
|
|
33
34
|
def regexp
|
34
|
-
/^\s*s(?:tep)?([
|
35
|
+
/^\s*s(?:tep)?([+])?(?:\s+(.*))?$/
|
35
36
|
end
|
36
37
|
|
37
38
|
def execute
|
38
39
|
force = @match[1] == '+' || (@match[1].nil? && Command.settings[:force_stepping])
|
39
|
-
steps = @match[2]
|
40
|
+
steps = get_int(@match[2], "Step", 1)
|
41
|
+
return unless steps
|
40
42
|
@state.context.step(steps, force)
|
41
43
|
@state.proceed
|
42
44
|
end
|
@@ -48,7 +50,8 @@ module Debugger
|
|
48
50
|
|
49
51
|
def help(cmd)
|
50
52
|
%{
|
51
|
-
s[tep][ nnn]\tstep (into methods) once or nnn times
|
53
|
+
s[tep][+]?[ nnn]\tstep (into methods) once or nnn times
|
54
|
+
\t\t'+' forces to move to another line
|
52
55
|
}
|
53
56
|
end
|
54
57
|
end
|
@@ -86,25 +89,27 @@ module Debugger
|
|
86
89
|
|
87
90
|
class ContinueCommand < Command # :nodoc:
|
88
91
|
def regexp
|
89
|
-
/^\s*c(?:ont)?(?:\s+(
|
92
|
+
/^\s*c(?:ont(?:inue)?)?(?:\s+(.*))?$/
|
90
93
|
end
|
91
94
|
|
92
95
|
def execute
|
93
96
|
if @match[1] && !@state.context.dead?
|
94
97
|
file = File.expand_path(@state.file)
|
95
|
-
|
98
|
+
line = get_int(@match[1], "Continue", 0, nil, 0)
|
99
|
+
return unless line
|
100
|
+
@state.context.set_breakpoint(file, line)
|
96
101
|
end
|
97
102
|
@state.proceed
|
98
103
|
end
|
99
104
|
|
100
105
|
class << self
|
101
106
|
def help_command
|
102
|
-
'
|
107
|
+
'continue'
|
103
108
|
end
|
104
109
|
|
105
110
|
def help(cmd)
|
106
111
|
%{
|
107
|
-
c[ont][ nnn]\trun until program ends or hits breakpoint or reaches line nnn
|
112
|
+
c[ont[inue]][ nnn]\trun until program ends or hits breakpoint or reaches line nnn
|
108
113
|
}
|
109
114
|
end
|
110
115
|
end
|
@@ -12,11 +12,31 @@ module Debugger
|
|
12
12
|
end
|
13
13
|
print "\n"
|
14
14
|
end
|
15
|
+
|
16
|
+
def parse_thread_num(subcmd, arg)
|
17
|
+
if '' == arg
|
18
|
+
print "'thread %s' needs a thread number\n" % subcmd
|
19
|
+
else
|
20
|
+
thread_num = get_int(arg, "thread #{subcmd}", 1)
|
21
|
+
return nil unless thread_num
|
22
|
+
c = get_context(thread_num)
|
23
|
+
case
|
24
|
+
when nil == c
|
25
|
+
print "No such thread.\n"
|
26
|
+
when @state.context == c
|
27
|
+
print "It's the current thread.\n"
|
28
|
+
when c.ignored?
|
29
|
+
print "Can't #{subcmd} to the debugger thread.\n"
|
30
|
+
else # Everything is okay
|
31
|
+
return c
|
32
|
+
end
|
33
|
+
end
|
34
|
+
return nil
|
35
|
+
end
|
15
36
|
end
|
16
37
|
|
17
38
|
class ThreadListCommand < Command # :nodoc:
|
18
39
|
self.control = true
|
19
|
-
include ThreadFunctions
|
20
40
|
|
21
41
|
def regexp
|
22
42
|
/^\s*th(?:read)?\s+l(?:ist)?\s*$/
|
@@ -41,29 +61,19 @@ module Debugger
|
|
41
61
|
end
|
42
62
|
end
|
43
63
|
|
44
|
-
class
|
64
|
+
class ThreadStopCommand < Command # :nodoc:
|
45
65
|
self.control = true
|
46
66
|
self.need_context = true
|
47
67
|
|
48
|
-
include ThreadFunctions
|
49
|
-
|
50
68
|
def regexp
|
51
|
-
/^\s*th(?:read)?\s+
|
69
|
+
/^\s*th(?:read)?\s+stop\s*(\S*)\s*$/
|
52
70
|
end
|
53
71
|
|
54
72
|
def execute
|
55
|
-
c =
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
when c.ignored?
|
60
|
-
print "Can't switch to the debugger thread.\n"
|
61
|
-
else
|
62
|
-
display_context(c)
|
63
|
-
c.stop_next = 1
|
64
|
-
c.thread.run
|
65
|
-
@state.proceed
|
66
|
-
end
|
73
|
+
c = parse_thread_num("stop", @match[1])
|
74
|
+
return unless c
|
75
|
+
c.suspend
|
76
|
+
display_context(c)
|
67
77
|
end
|
68
78
|
|
69
79
|
class << self
|
@@ -73,33 +83,29 @@ module Debugger
|
|
73
83
|
|
74
84
|
def help(cmd)
|
75
85
|
%{
|
76
|
-
th[read]
|
86
|
+
th[read] stop <nnn>\t\tstop thread nnn
|
77
87
|
}
|
78
88
|
end
|
79
89
|
end
|
80
90
|
end
|
81
91
|
|
82
|
-
class
|
92
|
+
class ThreadResumeCommand < Command # :nodoc:
|
83
93
|
self.control = true
|
84
94
|
self.need_context = true
|
85
95
|
|
86
|
-
include ThreadFunctions
|
87
|
-
|
88
96
|
def regexp
|
89
|
-
/^\s*th(?:read)?\s+
|
97
|
+
/^\s*th(?:read)?\s+resume\s*(\S*)\s*$/
|
90
98
|
end
|
91
99
|
|
92
100
|
def execute
|
93
|
-
c =
|
94
|
-
|
95
|
-
|
96
|
-
print "
|
97
|
-
|
98
|
-
print "Can't stop the debugger thread.\n"
|
99
|
-
else
|
100
|
-
c.suspend
|
101
|
-
display_context(c)
|
101
|
+
c = parse_thread_num("resume", @match[1])
|
102
|
+
return unless c
|
103
|
+
if !c.thread.stop?
|
104
|
+
print "Already running."
|
105
|
+
return
|
102
106
|
end
|
107
|
+
c.resume
|
108
|
+
display_context(c)
|
103
109
|
end
|
104
110
|
|
105
111
|
class << self
|
@@ -109,23 +115,30 @@ module Debugger
|
|
109
115
|
|
110
116
|
def help(cmd)
|
111
117
|
%{
|
112
|
-
th[read]
|
118
|
+
th[read] resume <nnn>\t\tresume thread nnn
|
113
119
|
}
|
114
120
|
end
|
115
121
|
end
|
116
122
|
end
|
117
123
|
|
118
|
-
|
124
|
+
# Thread switch Must come after "Thread resume" because "switch" is
|
125
|
+
# optional
|
126
|
+
|
127
|
+
class ThreadSwitchCommand < Command # :nodoc:
|
128
|
+
self.control = true
|
119
129
|
self.need_context = true
|
120
130
|
|
121
|
-
include ThreadFunctions
|
122
|
-
|
123
131
|
def regexp
|
124
|
-
/^\s*th(?:read)?\s
|
132
|
+
/^\s*th(?:read)?\s*(?:sw(?:itch)?)?\s+(\S+)\s*$/
|
125
133
|
end
|
126
134
|
|
127
135
|
def execute
|
128
|
-
|
136
|
+
c = parse_thread_num("switch", @match[1])
|
137
|
+
return unless c
|
138
|
+
display_context(c)
|
139
|
+
c.stop_next = 1
|
140
|
+
c.thread.run
|
141
|
+
@state.proceed
|
129
142
|
end
|
130
143
|
|
131
144
|
class << self
|
@@ -135,35 +148,21 @@ module Debugger
|
|
135
148
|
|
136
149
|
def help(cmd)
|
137
150
|
%{
|
138
|
-
th[read]
|
151
|
+
th[read] [sw[itch]] <nnn>\tswitch thread context to nnn
|
139
152
|
}
|
140
153
|
end
|
141
154
|
end
|
142
155
|
end
|
143
156
|
|
144
|
-
class
|
145
|
-
self.control = true
|
157
|
+
class ThreadCurrentCommand < Command # :nodoc:
|
146
158
|
self.need_context = true
|
147
159
|
|
148
|
-
include ThreadFunctions
|
149
|
-
|
150
160
|
def regexp
|
151
|
-
/^\s*th(?:read)?\s
|
161
|
+
/^\s*th(?:read)?\s*(?:cur(?:rent)?)?\s*$/
|
152
162
|
end
|
153
163
|
|
154
164
|
def execute
|
155
|
-
|
156
|
-
case
|
157
|
-
when c == @state.context
|
158
|
-
print "It's the current thread.\n"
|
159
|
-
when c.ignored?
|
160
|
-
print "Can't resume the debugger thread.\n"
|
161
|
-
when !c.thread.stop?
|
162
|
-
print "Already running."
|
163
|
-
else
|
164
|
-
c.resume
|
165
|
-
display_context(c)
|
166
|
-
end
|
165
|
+
display_context(@state.context)
|
167
166
|
end
|
168
167
|
|
169
168
|
class << self
|
@@ -173,7 +172,7 @@ module Debugger
|
|
173
172
|
|
174
173
|
def help(cmd)
|
175
174
|
%{
|
176
|
-
th[read]
|
175
|
+
th[read] [cur[rent]]\t\tshow current thread
|
177
176
|
}
|
178
177
|
end
|
179
178
|
end
|