mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
1.4.0
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@520 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
fcd020c830
commit
65a5162550
156 changed files with 21888 additions and 18301 deletions
389
lib/debug.rb
389
lib/debug.rb
|
@ -1,13 +1,29 @@
|
|||
|
||||
class DEBUGGER__
|
||||
begin
|
||||
require 'readline'
|
||||
def readline(prompt, hist)
|
||||
Readline::readline(prompt, hist)
|
||||
end
|
||||
rescue LoadError
|
||||
def readline(prompt, hist)
|
||||
STDOUT.print prompt
|
||||
STDOUT.flush
|
||||
line = STDIN.gets
|
||||
line.chomp!
|
||||
line
|
||||
end
|
||||
USE_READLINE = false
|
||||
end
|
||||
|
||||
trap("INT") { DEBUGGER__::CONTEXT.interrupt }
|
||||
$DEBUG = TRUE
|
||||
$DEBUG = true
|
||||
def initialize
|
||||
@break_points = []
|
||||
@display = []
|
||||
@stop_next = 1
|
||||
@frames = [nil]
|
||||
@frame_pos = nil
|
||||
@last_file = nil
|
||||
@last = [nil, nil]
|
||||
@scripts = {}
|
||||
end
|
||||
|
||||
|
@ -23,185 +39,271 @@ class DEBUGGER__
|
|||
val
|
||||
rescue
|
||||
at = caller(0)
|
||||
printf "%s:%s\n", at.shift, $!
|
||||
STDOUT.printf "%s:%s\n", at.shift, $!
|
||||
for i in at
|
||||
break if i =~ /`debug_(eval|command)'$/ #`
|
||||
printf "\tfrom %s\n", i
|
||||
STDOUT.printf "\tfrom %s\n", i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def debug_command(file, line, id, binding)
|
||||
frame_pos = 0
|
||||
binding_file = file
|
||||
binding_line = line
|
||||
previus_line = nil
|
||||
if (ENV['EMACS'] == 't')
|
||||
printf "\032\032%s:%d:\n", file, line
|
||||
STDOUT.printf "\032\032%s:%d:\n", binding_file, binding_line
|
||||
else
|
||||
printf "%s:%d:%s", file, line, line_at(file, line)
|
||||
STDOUT.printf "%s:%d:%s", binding_file, binding_line,
|
||||
line_at(binding_file, binding_line)
|
||||
end
|
||||
@frames[-1] = binding
|
||||
STDOUT.print "(rdb:-) "
|
||||
STDOUT.flush
|
||||
while input = STDIN.gets
|
||||
input.chop!
|
||||
@frames[0] = binding
|
||||
display_expressions(binding)
|
||||
while input = readline("(rdb:-) ", true)
|
||||
if input == ""
|
||||
input = DEBUG_LAST_CMD[0]
|
||||
else
|
||||
DEBUG_LAST_CMD[0] = input
|
||||
end
|
||||
|
||||
case input
|
||||
when /^b(reak)?\s+(([^:\n]+:)?.+)/
|
||||
pos = $2
|
||||
if pos.index ":"
|
||||
when /^b(?:reak)?\s+((?:[^:\n]+:)?.+)$/
|
||||
pos = $1
|
||||
if pos.index(":")
|
||||
file, pos = pos.split(":")
|
||||
end
|
||||
file = File.basename(file)
|
||||
if pos =~ /^\d+$/
|
||||
pname = pos
|
||||
pos = Integer(pos)
|
||||
pos = pos.to_i
|
||||
else
|
||||
pname = pos = pos.intern.id2name
|
||||
end
|
||||
printf "Set breakpoint %d at %s:%s\n", @break_points.size, file, pname
|
||||
@break_points.push [file, pos]
|
||||
when /^b(reak)?$/, /^info b(reak)?$/
|
||||
n = 0
|
||||
for f, p in @break_points
|
||||
printf "%d %s:%s\n", n, f, p
|
||||
@break_points.push [true, 0, file, pos]
|
||||
STDOUT.printf "Set breakpoint %d at %s:%s\n", @break_points.size, file,
|
||||
pname
|
||||
|
||||
when /^wat(?:ch)?\s+(.+)$/
|
||||
exp = $1
|
||||
@break_points.push [true, 1, exp]
|
||||
STDOUT.printf "Set watchpoint %d\n", @break_points.size, exp
|
||||
|
||||
when /^b(?:reak)?$/, /^info b(?:reak)?$/
|
||||
n = 1
|
||||
STDOUT.print "breakpoints:\n"
|
||||
for b in @break_points
|
||||
if b[0] and (b[1] == 0)
|
||||
STDOUT.printf " %d %s:%s\n", n, b[2], b[3]
|
||||
end
|
||||
n += 1
|
||||
end
|
||||
when /^del(ete)?(\s+(\d+))?$/
|
||||
pos = $3
|
||||
n = 1
|
||||
STDOUT.print "\n"
|
||||
STDOUT.print "watchpoints:\n"
|
||||
for b in @break_points
|
||||
if b[0] and (b[1] == 1)
|
||||
STDOUT.printf " %d %s\n", n, b[2]
|
||||
end
|
||||
n += 1
|
||||
end
|
||||
STDOUT.print "\n"
|
||||
|
||||
when /^del(?:ete)?(?:\s+(\d+))?$/
|
||||
pos = $1
|
||||
unless pos
|
||||
STDOUT.print "clear all breakpoints? (y/n) "
|
||||
STDOUT.flush
|
||||
input = STDIN.gets.chop!
|
||||
input = readline("clear all breakpoints? (y/n) ", false)
|
||||
if input == "y"
|
||||
for n in @break_points.indexes
|
||||
@break_points[n] = nil
|
||||
for b in @break_points
|
||||
b[0] = false
|
||||
end
|
||||
end
|
||||
else
|
||||
pos = Integer(pos)
|
||||
if @break_points[pos]
|
||||
bp = @break_points[pos]
|
||||
printf "Clear breakpoint %d at %s:%s\n", pos, bp[0], bp[1]
|
||||
@break_points[pos] = nil
|
||||
pos = pos.to_i
|
||||
if @break_points[pos-1]
|
||||
@break_points[pos-1][0] = false
|
||||
else
|
||||
printf "Breakpoint %d is not defined\n", pos
|
||||
STDOUT.printf "Breakpoint %d is not defined\n", pos
|
||||
end
|
||||
end
|
||||
when /^c(ont)?$/
|
||||
|
||||
when /^disp(?:lay)?\s+(.+)$/
|
||||
exp = $1
|
||||
@display.push.push [true, exp]
|
||||
STDOUT.printf " %d: %s = %s\n", @display.size, exp,
|
||||
debug_eval(exp, binding).to_s
|
||||
|
||||
when /^disp(?:lay)?$/, /^info disp(?:lay)?$/
|
||||
display_expressions(binding)
|
||||
|
||||
when /^undisp(?:lay)?(?:\s+(\d+))?$/
|
||||
pos = $1
|
||||
unless pos
|
||||
input = readline("clear all expressions? (y/n) ", false)
|
||||
if input == "y"
|
||||
for d in @display
|
||||
d[0] = false
|
||||
end
|
||||
end
|
||||
else
|
||||
pos = pos.to_i
|
||||
if @display[pos-1]
|
||||
@display[pos-1][0] = false
|
||||
else
|
||||
STDOUT.printf "display expression %d is not defined\n", pos
|
||||
end
|
||||
end
|
||||
|
||||
when /^c(?:ont)?$/
|
||||
return
|
||||
when /^s(tep)?\s*(\d+)?$/
|
||||
|
||||
when /^s(?:tep)?(?:\s+(\d+))?$/
|
||||
if $1
|
||||
lev = Integer($1)
|
||||
lev = $1.to_i
|
||||
else
|
||||
lev = 1
|
||||
end
|
||||
@stop_next = lev
|
||||
return
|
||||
when /^n(ext)?\s*(\d+)?$/
|
||||
|
||||
when /^n(?:ext)?(?:\s+(\d+))?$/
|
||||
if $1
|
||||
lev = Integer($1)
|
||||
lev = $1.to_i
|
||||
else
|
||||
lev = 1
|
||||
end
|
||||
@stop_next = lev
|
||||
@no_step = @frames.size
|
||||
@no_step = @frames.size - frame_pos
|
||||
return
|
||||
when /^up\s*(\d+)?$/
|
||||
if $1
|
||||
lev = Integer($1)
|
||||
else
|
||||
lev = 1
|
||||
|
||||
when /^w(?:here)?$/, /^f(?:rame)?$/
|
||||
at = caller(0)
|
||||
0.upto(@frames.size - 1) do |n|
|
||||
if frame_pos == n
|
||||
STDOUT.printf "--> #%d %s\n", n, at[-(@frames.size - n)]
|
||||
else
|
||||
STDOUT.printf " #%d %s\n", n, at[-(@frames.size - n)]
|
||||
end
|
||||
end
|
||||
unless @frame_pos
|
||||
@frame_pos = @frames.size - 1
|
||||
|
||||
when /^l(?:ist)?(?:\s+(.+))?$/
|
||||
if not $1
|
||||
b = previus_line ? previus_line + 10 : binding_line - 5
|
||||
e = b + 9
|
||||
elsif $1 == '-'
|
||||
b = previus_line ? previus_line - 10 : binding_line - 5
|
||||
e = b + 9
|
||||
else
|
||||
b, e = $1.split(/[-,]/)
|
||||
if e
|
||||
b = b.to_i
|
||||
e = e.to_i
|
||||
else
|
||||
b = b.to_i - 5
|
||||
e = b + 9
|
||||
end
|
||||
end
|
||||
previus_line = b
|
||||
STDOUT.printf "[%d, %d] in %s\n", b, e, binding_file
|
||||
line_at(binding_file, binding_line)
|
||||
if lines = @scripts[binding_file] and lines != true
|
||||
n = 0
|
||||
b.upto(e) do |n|
|
||||
if n > 0 && lines[n-1]
|
||||
if n == binding_line
|
||||
STDOUT.printf "=> %d %s\n", n, lines[n-1].chomp
|
||||
else
|
||||
STDOUT.printf " %d %s\n", n, lines[n-1].chomp
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
STDOUT.printf "no sourcefile available for %s\n", binding_file
|
||||
end
|
||||
|
||||
when /^up(?:\s+(\d+))?$/
|
||||
previus_line = nil
|
||||
if $1
|
||||
lev = $1.to_i
|
||||
else
|
||||
lev = 1
|
||||
end
|
||||
frame_pos += lev
|
||||
if frame_pos >= @frames.size
|
||||
frame_pos = @frames.size - 1
|
||||
STDOUT.print "at toplevel\n"
|
||||
end
|
||||
@frame_pos -= lev
|
||||
if @frame_pos < 0
|
||||
STDOUT.print "at toplevel\n"
|
||||
@frame_pos = 0
|
||||
else
|
||||
binding = @frames[@frame_pos]
|
||||
binding = @frames[frame_pos]
|
||||
info, binding_file, binding_line = frame_info(frame_pos)
|
||||
STDOUT.printf "#%d %s\n", frame_pos, info
|
||||
|
||||
when /^down(?:\s+(\d+))?$/
|
||||
previus_line = nil
|
||||
if $1
|
||||
lev = $1.to_i
|
||||
else
|
||||
lev = 1
|
||||
end
|
||||
frame_pos -= lev
|
||||
if frame_pos < 0
|
||||
frame_pos = 0
|
||||
STDOUT.print "at stack bottom\n"
|
||||
end
|
||||
when /^down\s*(\d+)??$/
|
||||
if $1
|
||||
lev = Integer($1)
|
||||
else
|
||||
lev = 1
|
||||
end
|
||||
if lev >= @frames.size or @frame_pos and @frame_pos+lev >= @frames.size
|
||||
STDOUT.print "at stack bottom\n"
|
||||
@frame_pos = nil
|
||||
else
|
||||
@frame_pos += lev
|
||||
binding = @frames[@frame_pos]
|
||||
end
|
||||
when /^fin(ish)?$/
|
||||
@finish_pos = @frames.size
|
||||
binding = @frames[frame_pos]
|
||||
info, binding_file, binding_line = frame_info(frame_pos)
|
||||
STDOUT.printf "#%d %s\n", frame_pos, info
|
||||
|
||||
when /^fi(?:nish)?$/
|
||||
@finish_pos = @frames.size - frame_pos
|
||||
frame_pos = 0
|
||||
return
|
||||
when /^q(uit)?$/
|
||||
STDOUT.print "really quit? (y/n) "
|
||||
STDOUT.flush
|
||||
input = STDIN.gets.chop!
|
||||
|
||||
when /^q(?:uit)?$/
|
||||
input = readline("really quit? (y/n) ", false)
|
||||
exit if input == "y"
|
||||
when /^where$/
|
||||
at = caller(4)
|
||||
for i in at
|
||||
printf " %s\n", i
|
||||
end
|
||||
when /^l(ist)?(\s+(.*))?$/
|
||||
if $3
|
||||
b, e = $3.split(/[-,]/)
|
||||
b = Integer(b)-1
|
||||
if e
|
||||
e = Integer(e)-1
|
||||
else
|
||||
e = b + 10
|
||||
end
|
||||
end
|
||||
unless b
|
||||
b = line - 1
|
||||
e = line + 9
|
||||
end
|
||||
p [b,e]
|
||||
line_at(file, line)
|
||||
if lines = @scripts[file] and lines != TRUE
|
||||
n = b+1
|
||||
for l in lines[b..e]
|
||||
printf "%4d %s", n, l
|
||||
n += 1
|
||||
end
|
||||
else
|
||||
printf "no sourcefile available for %s\n", file
|
||||
end
|
||||
|
||||
when /^p\s+/
|
||||
p debug_eval($', binding) #'
|
||||
p debug_eval($', binding)
|
||||
|
||||
else
|
||||
v = debug_eval(input, binding)
|
||||
p v unless v == nil
|
||||
p v unless (v == nil)
|
||||
end
|
||||
STDOUT.print "(rdb:-) "
|
||||
STDOUT.flush
|
||||
end
|
||||
end
|
||||
|
||||
def display_expressions(binding)
|
||||
n = 1
|
||||
for d in @display
|
||||
if d[0]
|
||||
STDOUT.printf "%d: %s = %s\n", n, d[1], debug_eval(d[1], binding).to_s
|
||||
end
|
||||
n += 1
|
||||
end
|
||||
end
|
||||
|
||||
def frame_info(pos = 0)
|
||||
info = caller(0)[-(@frames.size - pos)]
|
||||
info.sub(/:in `.*'$/, "") =~ /^(.*):(\d+)$/ #`
|
||||
[info, $1, $2.to_i]
|
||||
end
|
||||
|
||||
def line_at(file, line)
|
||||
lines = @scripts[file]
|
||||
if lines
|
||||
return "\n" if lines == TRUE
|
||||
return "\n" if lines == true
|
||||
line = lines[line-1]
|
||||
return "\n" unless line
|
||||
return line
|
||||
end
|
||||
save = $DEBUG
|
||||
begin
|
||||
$DEBUG = FALSE
|
||||
$DEBUG = false
|
||||
f = open(file)
|
||||
lines = @scripts[file] = f.readlines
|
||||
rescue
|
||||
$DEBUG = save
|
||||
@scripts[file] = TRUE
|
||||
@scripts[file] = true
|
||||
return "\n"
|
||||
end
|
||||
line = lines[line-1]
|
||||
|
@ -219,19 +321,44 @@ class DEBUGGER__
|
|||
|
||||
def check_break_points(file, pos, binding, id)
|
||||
file = File.basename(file)
|
||||
if @break_points.include? [file, pos]
|
||||
index = @break_points.index([file, pos])
|
||||
printf "Breakpoint %d, %s at %s:%s\n",
|
||||
index, debug_funcname(id), file, pos
|
||||
return TRUE
|
||||
n = 1
|
||||
for b in @break_points
|
||||
if b[0]
|
||||
if b[1] == 0 and b[2] == file and b[3] == pos
|
||||
STDOUT.printf "breakpoint %d, %s at %s:%s\n", n, debug_funcname(id),
|
||||
file, pos
|
||||
return true
|
||||
elsif b[1] == 1 and debug_eval(b[2], binding)
|
||||
STDOUT.printf "watchpoint %d, %s at %s:%s\n", n, debug_funcname(id),
|
||||
file, pos
|
||||
return true
|
||||
end
|
||||
end
|
||||
n += 1
|
||||
end
|
||||
return FALSE
|
||||
return false
|
||||
end
|
||||
|
||||
def excn_handle(file, line, id, binding)
|
||||
fs = @frames.size
|
||||
tb = caller(0)[-fs..-1]
|
||||
|
||||
STDOUT.printf "%s\n", $!
|
||||
for i in tb
|
||||
STDOUT.printf "\tfrom %s\n", i
|
||||
end
|
||||
debug_command(file, line, id, binding)
|
||||
end
|
||||
|
||||
def trace_func(event, file, line, id, binding)
|
||||
if event == 'line'
|
||||
if @no_step == nil or @no_step >= @frames.size
|
||||
case event
|
||||
when 'line'
|
||||
if !@no_step or @frames.size == @no_step
|
||||
@stop_next -= 1
|
||||
elsif @frames.size < @no_step
|
||||
@stop_next = 0 # break here before leaving...
|
||||
else
|
||||
# nothing to do. skipped.
|
||||
end
|
||||
if @stop_next == 0
|
||||
if [file, line] == @last
|
||||
|
@ -245,21 +372,25 @@ class DEBUGGER__
|
|||
if check_break_points(file, line, binding, id)
|
||||
debug_command(file, line, id, binding)
|
||||
end
|
||||
end
|
||||
if event == 'call'
|
||||
@frames.push binding
|
||||
|
||||
when 'call'
|
||||
@frames.unshift binding
|
||||
if check_break_points(file, id.id2name, binding, id)
|
||||
debug_command(file, line, id, binding)
|
||||
end
|
||||
end
|
||||
if event == 'class'
|
||||
@frames.push binding
|
||||
end
|
||||
if event == 'return' or event == 'end'
|
||||
if @finish_pos == @frames.size
|
||||
|
||||
when 'class'
|
||||
@frames.unshift binding
|
||||
|
||||
when 'return', 'end'
|
||||
if @frames.size == @finish_pos
|
||||
@stop_next = 1
|
||||
end
|
||||
@frames.pop
|
||||
@frames.shift
|
||||
|
||||
when 'raise'
|
||||
excn_handle(file, line, id, binding)
|
||||
|
||||
end
|
||||
@last_file = file
|
||||
end
|
||||
|
@ -267,6 +398,6 @@ class DEBUGGER__
|
|||
CONTEXT = new
|
||||
end
|
||||
|
||||
set_trace_func proc{|event, file, line, id, binding|
|
||||
set_trace_func proc{|event, file, line, id, binding,*rest|
|
||||
DEBUGGER__::CONTEXT.trace_func event, file, line, id, binding
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue