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