ruby-debug 0.2-mswin32 → 0.3-mswin32
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/CHANGES +22 -5
- data/Rakefile +1 -1
- data/bin/rdebug +16 -27
- data/ext/ruby_debug.c +20 -40
- data/lib/ruby-debug.rb +123 -45
- data/lib/ruby-debug/command.rb +76 -0
- data/lib/ruby-debug/commands/breakpoints.rb +136 -0
- data/lib/ruby-debug/commands/catchpoint.rb +40 -0
- data/lib/ruby-debug/commands/control.rb +55 -0
- data/lib/ruby-debug/commands/display.rb +106 -0
- data/lib/ruby-debug/commands/eval.rb +54 -0
- data/lib/ruby-debug/commands/frame.rb +125 -0
- data/lib/ruby-debug/commands/help.rb +47 -0
- data/lib/ruby-debug/commands/list.rb +67 -0
- data/lib/ruby-debug/commands/method.rb +53 -0
- data/lib/ruby-debug/commands/stepping.rb +104 -0
- data/lib/ruby-debug/commands/threads.rb +164 -0
- data/lib/ruby-debug/commands/tmate.rb +25 -0
- data/lib/ruby-debug/commands/trace.rb +33 -0
- data/lib/ruby-debug/commands/variables.rb +113 -0
- data/lib/ruby-debug/lock.rb +41 -0
- data/lib/ruby-debug/processor.rb +118 -555
- data/lib/ruby_debug.so +0 -0
- metadata +19 -3
- data/bin/remote +0 -30
@@ -0,0 +1,125 @@
|
|
1
|
+
module Debugger
|
2
|
+
module FrameFunctions
|
3
|
+
def format_frame(frame, pos)
|
4
|
+
file, line, id = frame.file, frame.line, frame.id
|
5
|
+
"#%d %s:%s%s\n" % [pos + 1, file, line, (id ? ":in `#{id.id2name}'" : "")]
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class WhereCommand < Command
|
10
|
+
include FrameFunctions
|
11
|
+
|
12
|
+
def regexp
|
13
|
+
/^\s*(?:w(?:here)?|f(?:rame)?)$/
|
14
|
+
end
|
15
|
+
|
16
|
+
def execute
|
17
|
+
@state.context.frames.each_with_index do |frame, idx|
|
18
|
+
if idx == @state.frame_pos
|
19
|
+
print "--> "
|
20
|
+
else
|
21
|
+
print " "
|
22
|
+
end
|
23
|
+
print format_frame(frame, idx)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class << self
|
28
|
+
def help_command
|
29
|
+
%w|where frame|
|
30
|
+
end
|
31
|
+
|
32
|
+
def help(cmd)
|
33
|
+
if cmd == 'where'
|
34
|
+
%{
|
35
|
+
w[here]\tdisplay frames
|
36
|
+
}
|
37
|
+
else
|
38
|
+
%{
|
39
|
+
f[rame]\t\talias for where
|
40
|
+
}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class UpCommand < Command
|
47
|
+
include FrameFunctions
|
48
|
+
|
49
|
+
def regexp
|
50
|
+
/^\s*(?:(up)(?:\s+(\d+))?|(f)(?:rame)?(?:\s+(\d+)))\s*$/
|
51
|
+
end
|
52
|
+
|
53
|
+
def execute
|
54
|
+
if @match[1]
|
55
|
+
cmd, arg = @match.captures
|
56
|
+
else
|
57
|
+
cmd, arg = @match.captures[2..-1]
|
58
|
+
end
|
59
|
+
@state.previous_line = nil
|
60
|
+
if cmd == 'f'
|
61
|
+
@state.frame_pos = arg.to_i - 1
|
62
|
+
else
|
63
|
+
@state.frame_pos += (arg ? arg.to_i : 1)
|
64
|
+
end
|
65
|
+
@state.frame_pos = 0 if @state.frame_pos < 0
|
66
|
+
if @state.frame_pos >= @state.context.frames.size
|
67
|
+
@state.frame_pos = @state.context.frames.size - 1
|
68
|
+
print "At toplevel\n"
|
69
|
+
end
|
70
|
+
frame = @state.context.frames[@state.frame_pos]
|
71
|
+
@state.binding, @state.file, @state.line = frame.binding, frame.file, frame.line
|
72
|
+
print format_frame(frame, @state.frame_pos)
|
73
|
+
end
|
74
|
+
|
75
|
+
class << self
|
76
|
+
def help_command
|
77
|
+
%w|up frame|
|
78
|
+
end
|
79
|
+
|
80
|
+
def help(cmd)
|
81
|
+
if cmd == 'up'
|
82
|
+
%{
|
83
|
+
up[ nn]\tmove to higher frame
|
84
|
+
}
|
85
|
+
else
|
86
|
+
%{
|
87
|
+
f[rame] n\tselect nth frame
|
88
|
+
}
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class DownCommand < Command
|
95
|
+
include FrameFunctions
|
96
|
+
|
97
|
+
def regexp
|
98
|
+
/^\s*down(?:\s+(\d+))?$/
|
99
|
+
end
|
100
|
+
|
101
|
+
def execute
|
102
|
+
@state.previous_line = nil
|
103
|
+
@state.frame_pos -= @match[1] ? @match[1].to_i : 1
|
104
|
+
if @state.frame_pos < 0
|
105
|
+
@state.frame_pos = 0
|
106
|
+
print "At stack bottom\n"
|
107
|
+
end
|
108
|
+
frame = @state.context.frames[@state.frame_pos]
|
109
|
+
@state.binding, @state.file, @state.line = frame.binding, frame.file, frame.line
|
110
|
+
print format_frame(frame, @state.frame_pos)
|
111
|
+
end
|
112
|
+
|
113
|
+
class << self
|
114
|
+
def help_command
|
115
|
+
'down'
|
116
|
+
end
|
117
|
+
|
118
|
+
def help(cmd)
|
119
|
+
%{
|
120
|
+
down[ nn]\tmove to lower frame
|
121
|
+
}
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Debugger
|
2
|
+
class HelpCommand < Command
|
3
|
+
self.control = true
|
4
|
+
|
5
|
+
def regexp
|
6
|
+
/^\s*h(?:elp)?(?:\s+(.+))?$/
|
7
|
+
end
|
8
|
+
|
9
|
+
def execute
|
10
|
+
print "ruby-debug help v.#{Debugger::VERSION}\n"
|
11
|
+
cmds = @state.commands.select{ |cmd| [cmd.help_command].flatten.include?(@match[1]) }
|
12
|
+
unless cmds.empty?
|
13
|
+
help = cmds.map{ |cmd| cmd.help(@match[1]) }.join
|
14
|
+
print help.split("\n").reject{|l| l =~ /^\s*$/ }.map{|l| l.gsub(/^ +/, '')}.join("\n")
|
15
|
+
else
|
16
|
+
print "Available commands:\n"
|
17
|
+
cmds = @state.commands.map{ |cmd| cmd.help_command }
|
18
|
+
cmds = cmds.flatten.uniq.sort
|
19
|
+
|
20
|
+
buf = ""
|
21
|
+
cmds.each do |cmd|
|
22
|
+
if buf.length + cmd.length > 70
|
23
|
+
print "%s\n", buf
|
24
|
+
buf = ""
|
25
|
+
else
|
26
|
+
buf << cmd << ' '
|
27
|
+
end
|
28
|
+
end
|
29
|
+
print "%s\n", buf if buf.length > 0
|
30
|
+
end
|
31
|
+
print "\n"
|
32
|
+
end
|
33
|
+
|
34
|
+
class << self
|
35
|
+
def help_command
|
36
|
+
'help'
|
37
|
+
end
|
38
|
+
|
39
|
+
def help(cmd)
|
40
|
+
%{
|
41
|
+
h[elp]\t\tprint this help
|
42
|
+
h[elp] command\tprint help on command
|
43
|
+
}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Debugger
|
2
|
+
class ListCommand < Command
|
3
|
+
def regexp
|
4
|
+
/^\s*l(?:ist)?(?:\s+(.+))?$/
|
5
|
+
end
|
6
|
+
|
7
|
+
def execute
|
8
|
+
if not @match[1]
|
9
|
+
b = @state.previous_line ? @state.previous_line + 10 : @state.line - 5
|
10
|
+
e = b + 9
|
11
|
+
elsif @match[1] == '-'
|
12
|
+
b = @state.previous_line ? @state.previous_line - 10 : @state.line - 5
|
13
|
+
e = b + 9
|
14
|
+
elsif @match[1] == '='
|
15
|
+
@state.previous_line = nil
|
16
|
+
b = @state.line - 5
|
17
|
+
e = b + 9
|
18
|
+
else
|
19
|
+
b, e = @match[1].split(/[-,]/)
|
20
|
+
if e
|
21
|
+
b = b.to_i
|
22
|
+
e = e.to_i
|
23
|
+
else
|
24
|
+
b = b.to_i - 5
|
25
|
+
e = b + 9
|
26
|
+
end
|
27
|
+
end
|
28
|
+
@state.previous_line = b
|
29
|
+
display_list(b, e, @state.file, @state.line)
|
30
|
+
end
|
31
|
+
|
32
|
+
class << self
|
33
|
+
def help_command
|
34
|
+
'list'
|
35
|
+
end
|
36
|
+
|
37
|
+
def help(cmd)
|
38
|
+
%{
|
39
|
+
l[ist]\t\tlist forward
|
40
|
+
l[ist] -\tlist backward
|
41
|
+
l[ist] =\tlist current line
|
42
|
+
l[ist] nn-mm\tlist given lines
|
43
|
+
}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def display_list(b, e, file, line)
|
50
|
+
print "[%d, %d] in %s\n", b, e, file
|
51
|
+
if lines = Debugger.source_for(file)
|
52
|
+
n = 0
|
53
|
+
b.upto(e) do |n|
|
54
|
+
if n > 0 && lines[n-1]
|
55
|
+
if n == line
|
56
|
+
print "=> %d %s\n", n, lines[n-1].chomp
|
57
|
+
else
|
58
|
+
print " %d %s\n", n, lines[n-1].chomp
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
else
|
63
|
+
print "No sourcefile available for %s\n", file
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Debugger
|
2
|
+
class MethodCommand < Command
|
3
|
+
def regexp
|
4
|
+
/^\s*m(?:ethod)?\s+(?:(i(:?nstance)?)\s)?/
|
5
|
+
end
|
6
|
+
|
7
|
+
def execute
|
8
|
+
if @match[1]
|
9
|
+
obj = debug_eval(@match.post_match)
|
10
|
+
|
11
|
+
len = 0
|
12
|
+
for v in obj.methods.sort
|
13
|
+
len += v.size + 1
|
14
|
+
if len > 70
|
15
|
+
len = v.size + 1
|
16
|
+
print "\n"
|
17
|
+
end
|
18
|
+
print "%s ", v
|
19
|
+
end
|
20
|
+
print "\n"
|
21
|
+
else
|
22
|
+
obj = debug_eval(@match.post_match)
|
23
|
+
unless obj.kind_of? Module
|
24
|
+
print "Should be Class/Module: %s\n", @match.post_match
|
25
|
+
else
|
26
|
+
len = 0
|
27
|
+
for v in obj.instance_methods(false).sort
|
28
|
+
len += v.size + 1
|
29
|
+
if len > 70
|
30
|
+
len = v.size + 1
|
31
|
+
print "\n"
|
32
|
+
end
|
33
|
+
print "%s ", v
|
34
|
+
end
|
35
|
+
print "\n"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class << self
|
41
|
+
def help_command
|
42
|
+
'method'
|
43
|
+
end
|
44
|
+
|
45
|
+
def help(cmd)
|
46
|
+
%{
|
47
|
+
m[ethod] i[nstance] <obj>\tshow methods of object
|
48
|
+
m[ethod] <class|module>\t\tshow instance methods of class or module
|
49
|
+
}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module Debugger
|
2
|
+
class NextCommand < Command
|
3
|
+
def regexp
|
4
|
+
/^\s*n(?:ext)?(?:\s+(\d+))?$/
|
5
|
+
end
|
6
|
+
|
7
|
+
def execute
|
8
|
+
steps = @match[1] ? @match[1].to_i : 1
|
9
|
+
@state.context.step_over steps, @state.context.frames.size - @state.frame_pos
|
10
|
+
@state.proceed
|
11
|
+
end
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def help_command
|
15
|
+
'next'
|
16
|
+
end
|
17
|
+
|
18
|
+
def help(cmd)
|
19
|
+
%{
|
20
|
+
n[ext][ nnn]\tgo over one line or till line nnn
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class StepCommand < Command
|
27
|
+
def regexp
|
28
|
+
/^\s*s(?:tep)?(?:\s+(\d+))?$/
|
29
|
+
end
|
30
|
+
|
31
|
+
def execute
|
32
|
+
@state.context.stop_next = @match[1] ? @match[1].to_i : 1
|
33
|
+
@state.proceed
|
34
|
+
end
|
35
|
+
|
36
|
+
class << self
|
37
|
+
def help_command
|
38
|
+
'step'
|
39
|
+
end
|
40
|
+
|
41
|
+
def help(cmd)
|
42
|
+
%{
|
43
|
+
s[tep][ nnn]\tstep (into methods) one line or till line nnn
|
44
|
+
}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class FinishCommand < Command
|
50
|
+
def regexp
|
51
|
+
/^\s*fin(?:ish)?$/
|
52
|
+
end
|
53
|
+
|
54
|
+
def execute
|
55
|
+
if @state.frame_pos == @state.context.frames.size
|
56
|
+
print "\"finish\" not meaningful in the outermost frame.\n"
|
57
|
+
else
|
58
|
+
@state.context.stop_frame = @state.context.frames.size - @state.frame_pos
|
59
|
+
@state.frame_pos = 0
|
60
|
+
@state.proceed
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class << self
|
65
|
+
def help_command
|
66
|
+
'finish'
|
67
|
+
end
|
68
|
+
|
69
|
+
def help(cmd)
|
70
|
+
%{
|
71
|
+
fin[ish]\treturn to outer frame
|
72
|
+
}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class ContinueCommand < Command
|
78
|
+
def regexp
|
79
|
+
/^\s*c(?:ont)?$|^\s*r(?:un)?$/
|
80
|
+
end
|
81
|
+
|
82
|
+
def execute
|
83
|
+
@state.proceed
|
84
|
+
end
|
85
|
+
|
86
|
+
class << self
|
87
|
+
def help_command
|
88
|
+
%w|cont run|
|
89
|
+
end
|
90
|
+
|
91
|
+
def help(cmd)
|
92
|
+
if cmd == 'cont'
|
93
|
+
%{
|
94
|
+
c[ont]\trun until program ends or hit breakpoint
|
95
|
+
}
|
96
|
+
else
|
97
|
+
%{
|
98
|
+
r[un]\talias for cont
|
99
|
+
}
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
module Debugger
|
2
|
+
module ThreadFunctions
|
3
|
+
def display_context(c)
|
4
|
+
if c.thread == Thread.current
|
5
|
+
print "+"
|
6
|
+
else
|
7
|
+
print " "
|
8
|
+
end
|
9
|
+
print "%d ", c.thnum
|
10
|
+
print "%s\t", c.thread.inspect
|
11
|
+
last_frame = c.frames.first
|
12
|
+
if last_frame
|
13
|
+
print "%s:%d", last_frame.file, last_frame.line
|
14
|
+
end
|
15
|
+
print "\n"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class ThreadListCommand < Command
|
20
|
+
include ThreadFunctions
|
21
|
+
|
22
|
+
def regexp
|
23
|
+
/^\s*th(?:read)?\s+l(?:ist)?\s*$/
|
24
|
+
end
|
25
|
+
|
26
|
+
def execute
|
27
|
+
threads = Debugger.contexts.sort_by{|c| c.thnum}.each do |c|
|
28
|
+
display_context(c)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class << self
|
33
|
+
def help_command
|
34
|
+
'thread'
|
35
|
+
end
|
36
|
+
|
37
|
+
def help(cmd)
|
38
|
+
%{
|
39
|
+
th[read] l[ist]\t\t\tlist all threads
|
40
|
+
}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class ThreadSwitchCommand < Command
|
46
|
+
include ThreadFunctions
|
47
|
+
|
48
|
+
def regexp
|
49
|
+
/^\s*th(?:read)?\s+(?:sw(?:itch)?\s+)?(\d+)\s*$/
|
50
|
+
end
|
51
|
+
|
52
|
+
def execute
|
53
|
+
c = get_context(@match[1].to_i)
|
54
|
+
if c == @state.context
|
55
|
+
print "It's the current thread.\n"
|
56
|
+
else
|
57
|
+
display_context(c)
|
58
|
+
c.stop_next = 1
|
59
|
+
c.thread.run
|
60
|
+
@state.proceed
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class << self
|
65
|
+
def help_command
|
66
|
+
'thread'
|
67
|
+
end
|
68
|
+
|
69
|
+
def help(cmd)
|
70
|
+
%{
|
71
|
+
th[read] [sw[itch]] <nnn>\tswitch thread context to nnn
|
72
|
+
}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class ThreadStopCommand < Command
|
78
|
+
include ThreadFunctions
|
79
|
+
|
80
|
+
def regexp
|
81
|
+
/^\s*th(?:read)?\s+stop\s+(\d+)\s*$/
|
82
|
+
end
|
83
|
+
|
84
|
+
def execute
|
85
|
+
c = get_context(@match[1].to_i)
|
86
|
+
if c == @state.context
|
87
|
+
print "It's the current thread.\n"
|
88
|
+
elsif c.thread.stop?
|
89
|
+
print "Already stopped.\n"
|
90
|
+
else
|
91
|
+
display_context(c)
|
92
|
+
c.set_suspend
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
class << self
|
97
|
+
def help_command
|
98
|
+
'thread'
|
99
|
+
end
|
100
|
+
|
101
|
+
def help(cmd)
|
102
|
+
%{
|
103
|
+
th[read] stop <nnn>\t\tstop thread nnn
|
104
|
+
}
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
class ThreadCurrentCommand < Command
|
110
|
+
include ThreadFunctions
|
111
|
+
|
112
|
+
def regexp
|
113
|
+
/^\s*th(?:read)?\s+c(?:ur(?:rent)?)?\s*$/
|
114
|
+
end
|
115
|
+
|
116
|
+
def execute
|
117
|
+
display_context(@state.context)
|
118
|
+
end
|
119
|
+
|
120
|
+
class << self
|
121
|
+
def help_command
|
122
|
+
'thread'
|
123
|
+
end
|
124
|
+
|
125
|
+
def help(cmd)
|
126
|
+
%{
|
127
|
+
th[read] c[ur[rent]]\t\tshow current thread
|
128
|
+
}
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
class ThreadResumeCommand < Command
|
134
|
+
include ThreadFunctions
|
135
|
+
|
136
|
+
def regexp
|
137
|
+
/^\s*th(?:read)?\s+resume\s+(\d+)\s*$/
|
138
|
+
end
|
139
|
+
|
140
|
+
def execute
|
141
|
+
c = get_context(@match[1].to_i)
|
142
|
+
if c == @state.context
|
143
|
+
print "It's the current thread.\n"
|
144
|
+
elsif !c.thread.stop?
|
145
|
+
print "Already running."
|
146
|
+
else
|
147
|
+
display_context(c)
|
148
|
+
c.thread.run
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
class << self
|
153
|
+
def help_command
|
154
|
+
'thread'
|
155
|
+
end
|
156
|
+
|
157
|
+
def help(cmd)
|
158
|
+
%{
|
159
|
+
th[read] resume <nnn>\t\tresume thread nnn
|
160
|
+
}
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|