# Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
# Copyright (C) 2000 Information-technology Promotion Agency, Japan
# Copyright (C) 2000-2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
STDERR.print "-r debug.rb is not available in safe mode\n"
def Tracer.trace_func(*vars)
SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__
return if Thread.critical
return if @locker == Thread.current
while (Thread.critical = true; @locked)
@waiting.push Thread.current
return if Thread.critical
unless @locker == Thread.current
raise RuntimeError, "unlocked by other"
def readline(prompt, hist)
Readline::readline(prompt, hist)
def readline(prompt, hist)
if Thread.current == Thread.main
return if Thread.critical
while (Thread.critical = true; @suspend_next)
DEBUGGER__.waiting.push Thread.current
DEBUGGER__.set_trace(arg)
DEBUGGER__.set_last_thread(th)
def debug_eval(str, binding)
rescue StandardError, ScriptError => e
at = eval("caller(1)", binding)
stdout.printf "%s:%s\n", at.shift, e.to_s.sub(/\(eval\):1:(in `.*?':)?/, '')
stdout.printf "\tfrom %s\n", i
def debug_silent_eval(str, binding)
rescue StandardError, ScriptError
def var_list(ary, binding)
stdout.printf " %s => %s\n", v, eval(v, binding).inspect
def debug_variable_info(input, binding)
when /^\s*g(?:lobal)?\s*$/
var_list(global_variables, binding)
when /^\s*l(?:ocal)?\s*$/
var_list(eval("local_variables", binding), binding)
when /^\s*i(?:nstance)?\s+/
obj = debug_eval($', binding)
var_list(obj.instance_variables, obj.instance_eval{binding()})
when /^\s*c(?:onst(?:ant)?)?\s+/
obj = debug_eval($', binding)
unless obj.kind_of? Module
stdout.print "Should be Class/Module: ", $', "\n"
var_list(obj.constants, obj.module_eval{binding()})
def debug_method_info(input, binding)
obj = debug_eval($', binding)
for v in obj.methods.sort
obj = debug_eval(input, binding)
unless obj.kind_of? Module
stdout.print "Should be Class/Module: ", input, "\n"
for v in obj.instance_methods(false).sort
num = DEBUGGER__.instance_eval{@thread_list[Thread.current]}
DEBUGGER__.make_thread_list
num = DEBUGGER__.instance_eval{@thread_list[Thread.current]}
def debug_command(file, line, id, binding)
unless defined?($debugger_restart) and $debugger_restart
callcc{|c| $debugger_restart = c}
set_last_thread(Thread.current)
stdout.printf "\032\032%s:%d:\n", binding_file, binding_line
stdout.printf "%s:%d:%s", binding_file, binding_line,
line_at(binding_file, binding_line)
@frames[0] = [binding, file, line, id]
display_expressions(binding)
while prompt and input = readline("(rdb:%d) "%thnum(), true)
next unless DEBUG_LAST_CMD[0]
input = DEBUG_LAST_CMD[0]
DEBUG_LAST_CMD[0] = input
when /^\s*tr(?:ace)?(?:\s+(on|off))?(?:\s+(all))?$/
stdout.print "Trace on.\n"
stdout.print "Trace off.\n"
when /^\s*b(?:reak)?\s+(?:(.+):)?([^.:]+)$/
klass = debug_silent_eval($1, binding)
pname = pos = pos.intern.id2name
break_points.push [true, 0, klass || file, pos]
stdout.printf "Set breakpoint %d at %s:%s\n", break_points.size, klass || file, pname
when /^\s*b(?:reak)?\s+(.+)[#.]([^.:]+)$/
klass = debug_eval($1, binding)
break_points.push [true, 0, klass, pos]
stdout.printf "Set breakpoint %d at %s.%s\n", break_points.size, klass, pos
when /^\s*wat(?:ch)?\s+(.+)$/
break_points.push [true, 1, exp]
stdout.printf "Set watchpoint %d:%s\n", break_points.size, exp
if break_points.find{|b| b[1] == 0}
stdout.print "Breakpoints:\n"
stdout.printf " %d %s:%s\n", n, b[2], b[3]
if break_points.find{|b| b[1] == 1}
stdout.print "Watchpoints:\n"
stdout.printf " %d %s\n", n, b[2]
if break_points.size == 0
stdout.print "No breakpoints\n"
when /^\s*del(?:ete)?(?:\s+(\d+))?$/
input = readline("Clear all breakpoints? (y/n) ", false)
break_points[pos-1][0] = false
stdout.printf "Breakpoint %d is not defined\n", pos
when /^\s*disp(?:lay)?\s+(.+)$/
stdout.printf "%d: ", display.size
display_expression(exp, binding)
display_expressions(binding)
when /^\s*undisp(?:lay)?(?:\s+(\d+))?$/
input = readline("Clear all expressions? (y/n) ", false)
display[pos-1][0] = false
stdout.printf "Display expression %d is not defined\n", pos
when /^\s*s(?:tep)?(?:\s+(\d+))?$/
when /^\s*n(?:ext)?(?:\s+(\d+))?$/
@no_step = @frames.size - frame_pos
when /^\s*w(?:here)?$/, /^\s*f(?:rame)?$/
display_frames(frame_pos)
when /^\s*l(?:ist)?(?:\s+(.+))?$/
b = previous_line ? previous_line + 10 : binding_line - 5
b = previous_line ? previous_line - 10 : binding_line - 5
display_list(b, e, binding_file, binding_line)
when /^\s*up(?:\s+(\d+))?$/
if frame_pos >= @frames.size
frame_pos = @frames.size - 1
stdout.print "At toplevel\n"
binding, binding_file, binding_line = @frames[frame_pos]
stdout.print format_frame(frame_pos)
when /^\s*down(?:\s+(\d+))?$/
stdout.print "At stack bottom\n"
binding, binding_file, binding_line = @frames[frame_pos]
stdout.print format_frame(frame_pos)
if frame_pos == @frames.size
stdout.print "\"finish\" not meaningful in the outermost frame.\n"
@finish_pos = @frames.size - frame_pos
when /^\s*cat(?:ch)?(?:\s+(.+))?$/
stdout.print "Clear catchpoint.\n"
stdout.printf "Set catchpoint %s.\n", @catch