Extended maintenance of Ruby 1.9.3 ended on February 23, 2015. Read more

In Files

  • debug.rb

Class/Module Index [+]

Quicksearch

DEBUGGER__::Context

Public Class Methods

new() click to toggle source
 
               # File debug.rb, line 46
def initialize
  if Thread.current == Thread.main
    @stop_next = 1
  else
    @stop_next = 0
  end
  @last_file = nil
  @file = nil
  @line = nil
  @no_step = nil
  @frames = []
  @finish_pos = 0
  @trace = false
  @catch = "StandardError"
  @suspend_next = false
end
            

Public Instance Methods

break_points() click to toggle source
 
               # File debug.rb, line 106
def break_points
  DEBUGGER__.break_points
end
            
check_break_points(file, klass, pos, binding, id) click to toggle source
 
               # File debug.rb, line 629
def check_break_points(file, klass, pos, binding, id)
  return false if break_points.empty?
  n = 1
  for b in break_points
    if b[0]           # valid
      if b[1] == 0    # breakpoint
        if (b[2] == file and b[3] == pos) or
            (klass and b[2] == klass and b[3] == pos)
          stdout.printf "Breakpoint %d, %s at %s:%s\n", n, debug_funcname(id), file, pos
          return true
        end
      elsif b[1] == 1 # watchpoint
        if debug_silent_eval(b[2], binding)
          stdout.printf "Watchpoint %d, %s at %s:%s\n", n, debug_funcname(id), file, pos
          return true
        end
      end
    end
    n += 1
  end
  return false
end
            
check_suspend() click to toggle source
 
               # File debug.rb, line 83
def check_suspend
  while MUTEX.synchronize {
      if @suspend_next
        DEBUGGER__.waiting.push Thread.current
        @suspend_next = false
        true
      end
    }
  end
end
            
clear_suspend() click to toggle source
 
               # File debug.rb, line 71
def clear_suspend
  @suspend_next = false
end
            
context(th) click to toggle source
 
               # File debug.rb, line 114
def context(th)
  DEBUGGER__.context(th)
end
            
debug_command(file, line, id, binding) click to toggle source
 
               # File debug.rb, line 220
def debug_command(file, line, id, binding)
  MUTEX.lock
  unless defined?($debugger_restart) and $debugger_restart
    callcc{|c| $debugger_restart = c}
  end
  set_last_thread(Thread.current)
  frame_pos = 0
  binding_file = file
  binding_line = line
  previous_line = nil
  if ENV['EMACS']
    stdout.printf "\032\032%s:%d:\n", binding_file, binding_line
  else
    stdout.printf "%s:%d:%s", binding_file, binding_line,
      line_at(binding_file, binding_line)
  end
  @frames[0] = [binding, file, line, id]
  display_expressions(binding)
  prompt = true
  while prompt and input = readline("(rdb:%d) "%thnum(), true)
    catch(:debug_error) do
      if input == ""
        next unless DEBUG_LAST_CMD[0]
        input = DEBUG_LAST_CMD[0]
        stdout.print input, "\n"
      else
        DEBUG_LAST_CMD[0] = input
      end

      case input
      when /^\s*tr(?:ace)?(?:\s+(on|off))?(?:\s+(all))?$/
        if defined?( $2 )
          if $1 == 'on'
            set_trace_all true
          else
            set_trace_all false
          end
        elsif defined?( $1 )
          if $1 == 'on'
            set_trace true
          else
            set_trace false
          end
        end
        if trace?
          stdout.print "Trace on.\n"
        else
          stdout.print "Trace off.\n"
        end

      when /^\s*b(?:reak)?\s+(?:(.+):)?([^.:]+)$/
        pos = $2
        if $1
          klass = debug_silent_eval($1, binding)
          file = $1
        end
        if pos =~ /^\d+$/
          pname = pos
          pos = pos.to_i
        else
          pname = pos = pos.intern.id2name
        end
        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+(.+)[#.]([^.:]+)$/
        pos = $2.intern.id2name
        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+(.+)$/
        exp = $1
        break_points.push [true, 1, exp]
        stdout.printf "Set watchpoint %d:%s\n", break_points.size, exp

      when /^\s*b(?:reak)?$/
        if break_points.find{|b| b[1] == 0}
          n = 1
          stdout.print "Breakpoints:\n"
          break_points.each do |b|
            if b[0] and b[1] == 0
              stdout.printf "  %d %s:%s\n", n, b[2], b[3]
            end
            n += 1
          end
        end
        if break_points.find{|b| b[1] == 1}
          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
        end
        if break_points.size == 0
          stdout.print "No breakpoints\n"
        else
          stdout.print "\n"
        end

      when /^\s*del(?:ete)?(?:\s+(\d+))?$/
        pos = $1
        unless pos
          input = readline("Clear all breakpoints? (y/n) ", false)
          if input == "y"
            for b in break_points
              b[0] = false
            end
          end
        else
          pos = pos.to_i
          if break_points[pos-1]
            break_points[pos-1][0] = false
          else
            stdout.printf "Breakpoint %d is not defined\n", pos
          end
        end

      when /^\s*disp(?:lay)?\s+(.+)$/
        exp = $1
        display.push [true, exp]
        stdout.printf "%d: ", display.size
        display_expression(exp, binding)

      when /^\s*disp(?:lay)?$/
        display_expressions(binding)

      when /^\s*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 /^\s*c(?:ont)?$/
        prompt = false

      when /^\s*s(?:tep)?(?:\s+(\d+))?$/
        if $1
          lev = $1.to_i
        else
          lev = 1
        end
        @stop_next = lev
        prompt = false

      when /^\s*n(?:ext)?(?:\s+(\d+))?$/
        if $1
          lev = $1.to_i
        else
          lev = 1
        end
        @stop_next = lev
        @no_step = @frames.size - frame_pos
        prompt = false

      when /^\s*w(?:here)?$/, /^\s*f(?:rame)?$/
        display_frames(frame_pos)

      when /^\s*l(?:ist)?(?:\s+(.+))?$/
        if not $1
          b = previous_line ? previous_line + 10 : binding_line - 5
          e = b + 9
        elsif $1 == '-'
          b = previous_line ? previous_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
        previous_line = b
        display_list(b, e, binding_file, binding_line)

      when /^\s*up(?:\s+(\d+))?$/
        previous_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
        binding, binding_file, binding_line = @frames[frame_pos]
        stdout.print format_frame(frame_pos)

      when /^\s*down(?:\s+(\d+))?$/
        previous_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
        binding, binding_file, binding_line = @frames[frame_pos]
        stdout.print format_frame(frame_pos)

      when /^\s*fin(?:ish)?$/
        if frame_pos == @frames.size
          stdout.print "\"finish\" not meaningful in the outermost frame.\n"
        else
          @finish_pos = @frames.size - frame_pos
          frame_pos = 0
          prompt = false
        end

      when /^\s*cat(?:ch)?(?:\s+(.+))?$/
        if $1
          excn = $1
          if excn == 'off'
            @catch = nil
            stdout.print "Clear catchpoint.\n"
          else
            @catch = excn
            stdout.printf "Set catchpoint %s.\n", @catch
          end
        else
          if @catch
            stdout.printf "Catchpoint %s.\n", @catch
          else
            stdout.print "No catchpoint.\n"
          end
        end

      when /^\s*q(?:uit)?$/
        input = readline("Really quit? (y/n) ", false)
        if input == "y"
          exit!  # exit -> exit!: No graceful way to stop threads...
        end

      when /^\s*v(?:ar)?\s+/
        debug_variable_info($', binding)

      when /^\s*m(?:ethod)?\s+/
        debug_method_info($', binding)

      when /^\s*th(?:read)?\s+/
        if DEBUGGER__.debug_thread_info($', binding) == :cont
          prompt = false
        end

      when /^\s*pp\s+/
        PP.pp(debug_eval($', binding), stdout)

      when /^\s*p\s+/
        stdout.printf "%s\n", debug_eval($', binding).inspect

      when /^\s*r(?:estart)?$/
        $debugger_restart.call

      when /^\s*h(?:elp)?$/
        debug_print_help()

      else
        v = debug_eval(input, binding)
        stdout.printf "%s\n", v.inspect
      end
    end
  end
  MUTEX.unlock
  resume_all
end
            
debug_eval(str, binding) click to toggle source
 
               # File debug.rb, line 126
def debug_eval(str, binding)
  begin
    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 `.*?':)?/, '')
    for i in at
      stdout.printf "\tfrom %s\n", i
    end
    throw :debug_error
  end
end
            
debug_funcname(id) click to toggle source
 
               # File debug.rb, line 621
def debug_funcname(id)
  if id.nil?
    "toplevel"
  else
    id.id2name
  end
end
            
debug_method_info(input, binding) click to toggle source
 
               # File debug.rb, line 176
def debug_method_info(input, binding)
  case input
  when /^i(:?nstance)?\s+/
    obj = debug_eval($', binding)

    len = 0
    for v in obj.methods.sort
      len += v.size + 1
      if len > 70
        len = v.size + 1
        stdout.print "\n"
      end
      stdout.print v, " "
    end
    stdout.print "\n"

  else
    obj = debug_eval(input, binding)
    unless obj.kind_of? Module
      stdout.print "Should be Class/Module: ", input, "\n"
    else
      len = 0
      for v in obj.instance_methods(false).sort
        len += v.size + 1
        if len > 70
          len = v.size + 1
          stdout.print "\n"
        end
        stdout.print v, " "
      end
      stdout.print "\n"
    end
  end
end
            
debug_print_help() click to toggle source
 
               # File debug.rb, line 510
    def debug_print_help
      stdout.print <<EOHELP
Debugger help v.-0.002b
Commands
  b[reak] [file:|class:]<line|method>
  b[reak] [class.]<line|method>
                             set breakpoint to some position
  wat[ch] <expression>       set watchpoint to some expression
  cat[ch] (<exception>|off)  set catchpoint to an exception
  b[reak]                    list breakpoints
  cat[ch]                    show catchpoint
  del[ete][ nnn]             delete some or all breakpoints
  disp[lay] <expression>     add expression into display expression list
  undisp[lay][ nnn]          delete one particular or all display expressions
  c[ont]                     run until program ends or hit breakpoint
  s[tep][ nnn]               step (into methods) one line or till line nnn
  n[ext][ nnn]               go over one line or till line nnn
  w[here]                    display frames
  f[rame]                    alias for where
  l[ist][ (-|nn-mm)]         list program, - lists backwards
                             nn-mm lists given lines
  up[ nn]                    move to higher frame
  down[ nn]                  move to lower frame
  fin[ish]                   return to outer frame
  tr[ace] (on|off)           set trace mode of current thread
  tr[ace] (on|off) all       set trace mode of all threads
  q[uit]                     exit from debugger
  v[ar] g[lobal]             show global variables
  v[ar] l[ocal]              show local variables
  v[ar] i[nstance] <object>  show instance variables of object
  v[ar] c[onst] <object>     show constants of object
  m[ethod] i[nstance] <obj>  show methods of object
  m[ethod] <class|module>    show instance methods of class or module
  th[read] l[ist]            list all threads
  th[read] c[ur[rent]]       show current thread
  th[read] [sw[itch]] <nnn>  switch thread context to nnn
  th[read] stop <nnn>        stop thread nnn
  th[read] resume <nnn>      resume thread nnn
  p expression               evaluate expression and print its value
  h[elp]                     print this help
  <everything else>          evaluate
EOHELP
    end
            
debug_silent_eval(str, binding) click to toggle source
 
               # File debug.rb, line 139
def debug_silent_eval(str, binding)
  begin
    eval(str, binding)
  rescue StandardError, ScriptError
    nil
  end
end
            
debug_variable_info(input, binding) click to toggle source
 
               # File debug.rb, line 154
def debug_variable_info(input, binding)
  case input
  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"
    else
      var_list(obj.constants, obj.module_eval{binding()})
    end
  end
end
            
display() click to toggle source
 
               # File debug.rb, line 110
def display
  DEBUGGER__.display
end
            
display_expression(exp, binding) click to toggle source
 
               # File debug.rb, line 565
def display_expression(exp, binding)
  stdout.printf "%s = %s\n", exp, debug_silent_eval(exp, binding).to_s
end
            
display_expressions(binding) click to toggle source
 
               # File debug.rb, line 554
def display_expressions(binding)
  n = 1
  for d in display
    if d[0]
      stdout.printf "%d: ", n
      display_expression(d[1], binding)
    end
    n += 1
  end
end
            
display_frames(pos) click to toggle source
 
               # File debug.rb, line 576
def display_frames(pos)
  0.upto(@frames.size - 1) do |n|
    if n == pos
      stdout.print "--> "
    else
      stdout.print "    "
    end
    stdout.print format_frame(n)
  end
end
            
display_list(b, e, file, line) click to toggle source
 
               # File debug.rb, line 593
def display_list(b, e, file, line)
  stdout.printf "[%d, %d] in %s\n", b, e, file
  if lines = SCRIPT_LINES__[file] and lines != true
    b.upto(e) do |n|
      if n > 0 && lines[n-1]
        if n == 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", file
  end
end
            
excn_handle(file, line, id, binding) click to toggle source
 
               # File debug.rb, line 652
def excn_handle(file, line, id, binding)
  if $!.class <= SystemExit
    set_trace_func nil
    exit
  end

  if @catch and ($!.class.ancestors.find { |e| e.to_s == @catch })
    stdout.printf "%s:%d: `%s' (%s)\n", file, line, $!, $!.class
    fs = @frames.size
    tb = caller(0)[-fs..-1]
    if tb
      for i in tb
        stdout.printf "\tfrom %s\n", i
      end
    end
    suspend_all
    debug_command(file, line, id, binding)
  end
end
            
format_frame(pos) click to toggle source
 
               # File debug.rb, line 587
def format_frame(pos)
  _, file, line, id = @frames[pos]
  sprintf "#%d %s:%s%s\n", pos + 1, file, line,
    (id ? ":in `#{id.id2name}'" : "")
end
            
frame_set_pos(file, line) click to toggle source
 
               # File debug.rb, line 569
def frame_set_pos(file, line)
  if @frames[0]
    @frames[0][1] = file
    @frames[0][2] = line
  end
end
            
line_at(file, line) click to toggle source
 
               # File debug.rb, line 610
def line_at(file, line)
  lines = SCRIPT_LINES__[file]
  if lines
    return "\n" if lines == true
    line = lines[line-1]
    return "\n" unless line
    return line
  end
  return "\n"
end
            
readline(prompt, hist) click to toggle source
 
               # File debug.rb, line 31
def readline(prompt, hist)
  Readline::readline(prompt, hist)
end
            
resume_all() click to toggle source
 
               # File debug.rb, line 79
def resume_all
  DEBUGGER__.resume
end
            
set_last_thread(th) click to toggle source
 
               # File debug.rb, line 122
def set_last_thread(th)
  DEBUGGER__.set_last_thread(th)
end
            
set_suspend() click to toggle source
 
               # File debug.rb, line 67
def set_suspend
  @suspend_next = true
end
            
set_trace(arg) click to toggle source
 
               # File debug.rb, line 98
def set_trace(arg)
  @trace = arg
end
            
set_trace_all(arg) click to toggle source
 
               # File debug.rb, line 118
def set_trace_all(arg)
  DEBUGGER__.set_trace(arg)
end
            
stdout() click to toggle source
 
               # File debug.rb, line 102
def stdout
  DEBUGGER__.stdout
end
            
stop_next(n=1) click to toggle source
 
               # File debug.rb, line 63
def stop_next(n=1)
  @stop_next = n
end
            
suspend_all() click to toggle source
 
               # File debug.rb, line 75
def suspend_all
  DEBUGGER__.suspend
end
            
thnum() click to toggle source
 
               # File debug.rb, line 211
def thnum
  num = DEBUGGER__.instance_eval{@thread_list[Thread.current]}
  unless num
    DEBUGGER__.make_thread_list
    num = DEBUGGER__.instance_eval{@thread_list[Thread.current]}
  end
  num
end
            
trace?() click to toggle source
 
               # File debug.rb, line 94
def trace?
  @trace
end
            
trace_func(event, file, line, id, binding, klass) click to toggle source
 
               # File debug.rb, line 672
def trace_func(event, file, line, id, binding, klass)
  Tracer.trace_func(event, file, line, id, binding, klass) if trace?
  context(Thread.current).check_suspend
  @file = file
  @line = line
  case event
  when 'line'
    frame_set_pos(file, line)
    if !@no_step or @frames.size == @no_step
      @stop_next -= 1
      @stop_next = -1 if @stop_next < 0
    elsif @frames.size < @no_step
      @stop_next = 0          # break here before leaving...
    else
      # nothing to do. skipped.
    end
    if @stop_next == 0 or check_break_points(file, nil, line, binding, id)
      @no_step = nil
      suspend_all
      debug_command(file, line, id, binding)
    end

  when 'call'
    @frames.unshift [binding, file, line, id]
    if check_break_points(file, klass, id.id2name, binding, id)
      suspend_all
      debug_command(file, line, id, binding)
    end

  when 'c-call'
    frame_set_pos(file, line)

  when 'class'
    @frames.unshift [binding, file, line, id]

  when 'return', 'end'
    if @frames.size == @finish_pos
      @stop_next = 1
      @finish_pos = 0
    end
    @frames.shift

  when 'raise'
    excn_handle(file, line, id, binding)

  end
  @last_file = file
end
            
var_list(ary, binding) click to toggle source
 
               # File debug.rb, line 147
def var_list(ary, binding)
  ary.sort!
  for v in ary
    stdout.printf "  %s => %s\n", v, eval(v.to_s, binding).inspect
  end
end
            

Commenting is here to help enhance the documentation. For example, code samples, or clarification of the documentation.

If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.

If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.

If you want to help improve the Ruby documentation, please visit Documenting-ruby.org.