ruby-debug 0.9.3 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|