Class DEBUGGER__::Context
In: lib/debug.rb
Parent: Object

Methods

Constants

DEBUG_LAST_CMD = []
USE_READLINE = false

Public Class methods

[Source]

    # File lib/debug.rb, line 83
83:   def initialize
84:     if Thread.current == Thread.main
85:       @stop_next = 1
86:     else
87:       @stop_next = 0
88:     end
89:     @last_file = nil
90:     @file = nil
91:     @line = nil
92:     @no_step = nil
93:     @frames = []
94:     @finish_pos = 0
95:     @trace = false
96:     @catch = "StandardError"
97:     @suspend_next = false
98:   end

Public Instance methods

[Source]

     # File lib/debug.rb, line 142
142:   def break_points
143:     DEBUGGER__.break_points
144:   end

[Source]

     # File lib/debug.rb, line 667
667:   def check_break_points(file, klass, pos, binding, id)
668:     return false if break_points.empty?
669:     n = 1
670:     for b in break_points
671:       if b[0]           # valid
672:         if b[1] == 0   # breakpoint
673:           if (b[2] == file and b[3] == pos) or
674:               (klass and b[2] == klass and b[3] == pos)
675:             stdout.printf "Breakpoint %d, %s at %s:%s\n", n, debug_funcname(id), file, pos
676:             return true
677:           end
678:         elsif b[1] == 1        # watchpoint
679:           if debug_silent_eval(b[2], binding)
680:             stdout.printf "Watchpoint %d, %s at %s:%s\n", n, debug_funcname(id), file, pos
681:             return true
682:           end
683:         end
684:       end
685:       n += 1
686:     end
687:     return false
688:   end

[Source]

     # File lib/debug.rb, line 120
120:   def check_suspend
121:     return if Thread.critical
122:     while (Thread.critical = true; @suspend_next)
123:       DEBUGGER__.waiting.push Thread.current
124:       @suspend_next = false
125:       Thread.stop
126:     end
127:     Thread.critical = false
128:   end

[Source]

     # File lib/debug.rb, line 108
108:   def clear_suspend
109:     @suspend_next = false
110:   end

[Source]

     # File lib/debug.rb, line 150
150:   def context(th)
151:     DEBUGGER__.context(th)
152:   end

[Source]

     # File lib/debug.rb, line 256
256:   def debug_command(file, line, id, binding)
257:     MUTEX.lock
258:     unless defined?($debugger_restart) and $debugger_restart
259:       callcc{|c| $debugger_restart = c} 
260:     end
261:     set_last_thread(Thread.current)
262:     frame_pos = 0
263:     binding_file = file
264:     binding_line = line
265:     previous_line = nil
266:     if ENV['EMACS']
267:       stdout.printf "\032\032%s:%d:\n", binding_file, binding_line
268:     else
269:       stdout.printf "%s:%d:%s", binding_file, binding_line,
270:         line_at(binding_file, binding_line)
271:     end
272:     @frames[0] = [binding, file, line, id]
273:     display_expressions(binding)
274:     prompt = true
275:     while prompt and input = readline("(rdb:%d) "%thnum(), true)
276:       catch(:debug_error) do
277:         if input == ""
278:           next unless DEBUG_LAST_CMD[0]
279:           input = DEBUG_LAST_CMD[0]
280:           stdout.print input, "\n"
281:         else
282:           DEBUG_LAST_CMD[0] = input
283:         end
284: 
285:         case input
286:         when /^\s*tr(?:ace)?(?:\s+(on|off))?(?:\s+(all))?$/
287:           if defined?( $2 )
288:             if $1 == 'on'
289:               set_trace_all true
290:             else
291:               set_trace_all false
292:             end
293:           elsif defined?( $1 )
294:             if $1 == 'on'
295:               set_trace true
296:             else
297:               set_trace false
298:             end
299:           end
300:           if trace?
301:             stdout.print "Trace on.\n"
302:           else
303:             stdout.print "Trace off.\n"
304:           end
305: 
306:         when /^\s*b(?:reak)?\s+(?:(.+):)?([^.:]+)$/
307:           pos = $2
308:           if $1
309:             klass = debug_silent_eval($1, binding)
310:             file = $1
311:           end
312:           if pos =~ /^\d+$/
313:             pname = pos
314:             pos = pos.to_i
315:           else
316:             pname = pos = pos.intern.id2name
317:           end
318:           break_points.push [true, 0, klass || file, pos]
319:           stdout.printf "Set breakpoint %d at %s:%s\n", break_points.size, klass || file, pname
320: 
321:         when /^\s*b(?:reak)?\s+(.+)[#.]([^.:]+)$/
322:           pos = $2.intern.id2name
323:           klass = debug_eval($1, binding)
324:           break_points.push [true, 0, klass, pos]
325:           stdout.printf "Set breakpoint %d at %s.%s\n", break_points.size, klass, pos
326: 
327:         when /^\s*wat(?:ch)?\s+(.+)$/
328:           exp = $1
329:           break_points.push [true, 1, exp]
330:           stdout.printf "Set watchpoint %d:%s\n", break_points.size, exp
331: 
332:         when /^\s*b(?:reak)?$/
333:           if break_points.find{|b| b[1] == 0}
334:             n = 1
335:             stdout.print "Breakpoints:\n"
336:             for b in break_points
337:               if b[0] and b[1] == 0
338:                 stdout.printf "  %d %s:%s\n", n, b[2], b[3] 
339:               end
340:               n += 1
341:             end
342:           end
343:           if break_points.find{|b| b[1] == 1}
344:             n = 1
345:             stdout.print "\n"
346:             stdout.print "Watchpoints:\n"
347:             for b in break_points
348:               if b[0] and b[1] == 1
349:                 stdout.printf "  %d %s\n", n, b[2]
350:               end
351:               n += 1
352:             end
353:           end
354:           if break_points.size == 0
355:             stdout.print "No breakpoints\n"
356:           else
357:             stdout.print "\n"
358:           end
359: 
360:         when /^\s*del(?:ete)?(?:\s+(\d+))?$/
361:           pos = $1
362:           unless pos
363:             input = readline("Clear all breakpoints? (y/n) ", false)
364:             if input == "y"
365:               for b in break_points
366:                 b[0] = false
367:               end
368:             end
369:           else
370:             pos = pos.to_i
371:             if break_points[pos-1]
372:               break_points[pos-1][0] = false
373:             else
374:               stdout.printf "Breakpoint %d is not defined\n", pos
375:             end
376:           end
377: 
378:         when /^\s*disp(?:lay)?\s+(.+)$/
379:           exp = $1
380:           display.push [true, exp]
381:           stdout.printf "%d: ", display.size
382:           display_expression(exp, binding)
383: 
384:         when /^\s*disp(?:lay)?$/
385:           display_expressions(binding)
386: 
387:         when /^\s*undisp(?:lay)?(?:\s+(\d+))?$/
388:           pos = $1
389:           unless pos
390:             input = readline("Clear all expressions? (y/n) ", false)
391:             if input == "y"
392:               for d in display
393:                 d[0] = false
394:               end
395:             end
396:           else
397:             pos = pos.to_i
398:             if display[pos-1]
399:               display[pos-1][0] = false
400:             else
401:               stdout.printf "Display expression %d is not defined\n", pos
402:             end
403:           end
404: 
405:         when /^\s*c(?:ont)?$/
406:           prompt = false
407: 
408:         when /^\s*s(?:tep)?(?:\s+(\d+))?$/
409:           if $1
410:             lev = $1.to_i
411:           else
412:             lev = 1
413:           end
414:           @stop_next = lev
415:           prompt = false
416: 
417:         when /^\s*n(?:ext)?(?:\s+(\d+))?$/
418:           if $1
419:             lev = $1.to_i
420:           else
421:             lev = 1
422:           end
423:           @stop_next = lev
424:           @no_step = @frames.size - frame_pos
425:           prompt = false
426: 
427:         when /^\s*w(?:here)?$/, /^\s*f(?:rame)?$/
428:           display_frames(frame_pos)
429: 
430:         when /^\s*l(?:ist)?(?:\s+(.+))?$/
431:           if not $1
432:             b = previous_line ? previous_line + 10 : binding_line - 5
433:             e = b + 9
434:           elsif $1 == '-'
435:             b = previous_line ? previous_line - 10 : binding_line - 5
436:             e = b + 9
437:           else
438:             b, e = $1.split(/[-,]/)
439:             if e
440:               b = b.to_i
441:               e = e.to_i
442:             else
443:               b = b.to_i - 5
444:               e = b + 9
445:             end
446:           end
447:           previous_line = b
448:           display_list(b, e, binding_file, binding_line)
449: 
450:         when /^\s*up(?:\s+(\d+))?$/
451:           previous_line = nil
452:           if $1
453:             lev = $1.to_i
454:           else
455:             lev = 1
456:           end
457:           frame_pos += lev
458:           if frame_pos >= @frames.size
459:             frame_pos = @frames.size - 1
460:             stdout.print "At toplevel\n"
461:           end
462:           binding, binding_file, binding_line = @frames[frame_pos]
463:           stdout.print format_frame(frame_pos)
464: 
465:         when /^\s*down(?:\s+(\d+))?$/
466:           previous_line = nil
467:           if $1
468:             lev = $1.to_i
469:           else
470:             lev = 1
471:           end
472:           frame_pos -= lev
473:           if frame_pos < 0
474:             frame_pos = 0
475:             stdout.print "At stack bottom\n"
476:           end
477:           binding, binding_file, binding_line = @frames[frame_pos]
478:           stdout.print format_frame(frame_pos)
479: 
480:         when /^\s*fin(?:ish)?$/
481:           if frame_pos == @frames.size
482:             stdout.print "\"finish\" not meaningful in the outermost frame.\n"
483:           else
484:             @finish_pos = @frames.size - frame_pos
485:             frame_pos = 0
486:             prompt = false
487:           end
488: 
489:         when /^\s*cat(?:ch)?(?:\s+(.+))?$/
490:           if $1
491:             excn = $1
492:             if excn == 'off'
493:               @catch = nil
494:               stdout.print "Clear catchpoint.\n"
495:             else
496:               @catch = excn
497:               stdout.printf "Set catchpoint %s.\n", @catch
498:             end
499:           else
500:             if @catch
501:               stdout.printf "Catchpoint %s.\n", @catch
502:             else
503:               stdout.print "No catchpoint.\n"
504:             end
505:           end
506: 
507:         when /^\s*q(?:uit)?$/
508:           input = readline("Really quit? (y/n) ", false)
509:           if input == "y"
510:             exit!      # exit -> exit!: No graceful way to stop threads...
511:           end
512: 
513:         when /^\s*v(?:ar)?\s+/
514:           debug_variable_info($', binding)
515: 
516:         when /^\s*m(?:ethod)?\s+/
517:           debug_method_info($', binding)
518: 
519:         when /^\s*th(?:read)?\s+/
520:           if DEBUGGER__.debug_thread_info($', binding) == :cont
521:             prompt = false
522:           end
523: 
524:         when /^\s*pp\s+/
525:           PP.pp(debug_eval($', binding), stdout)
526: 
527:         when /^\s*p\s+/
528:           stdout.printf "%s\n", debug_eval($', binding).inspect
529: 
530:         when /^\s*r(?:estart)?$/
531:           $debugger_restart.call
532: 
533:         when /^\s*h(?:elp)?$/
534:           debug_print_help()
535: 
536:         else
537:           v = debug_eval(input, binding)
538:           stdout.printf "%s\n", v.inspect
539:         end
540:       end
541:     end
542:     MUTEX.unlock
543:     resume_all
544:   end

[Source]

     # File lib/debug.rb, line 162
162:   def debug_eval(str, binding)
163:     begin
164:       val = eval(str, binding)
165:     rescue StandardError, ScriptError => e
166:       at = eval("caller(1)", binding)
167:       stdout.printf "%s:%s\n", at.shift, e.to_s.sub(/\(eval\):1:(in `.*?':)?/, '')
168:       for i in at
169:         stdout.printf "\tfrom %s\n", i
170:       end
171:       throw :debug_error
172:     end
173:   end

[Source]

     # File lib/debug.rb, line 659
659:   def debug_funcname(id)
660:     if id.nil?
661:       "toplevel"
662:     else
663:       id.id2name
664:     end
665:   end

[Source]

     # File lib/debug.rb, line 212
212:   def debug_method_info(input, binding)
213:     case input
214:     when /^i(:?nstance)?\s+/
215:       obj = debug_eval($', binding)
216: 
217:       len = 0
218:       for v in obj.methods.sort
219:         len += v.size + 1
220:         if len > 70
221:           len = v.size + 1
222:           stdout.print "\n"
223:         end
224:         stdout.print v, " "
225:       end
226:       stdout.print "\n"
227: 
228:     else
229:       obj = debug_eval(input, binding)
230:       unless obj.kind_of? Module
231:         stdout.print "Should be Class/Module: ", input, "\n"
232:       else
233:         len = 0
234:         for v in obj.instance_methods(false).sort
235:           len += v.size + 1
236:           if len > 70
237:             len = v.size + 1
238:             stdout.print "\n"
239:           end
240:           stdout.print v, " "
241:         end
242:         stdout.print "\n"
243:       end
244:     end
245:   end

[Source]

     # File lib/debug.rb, line 546
546:   def debug_print_help
547:     stdout.print "Debugger help v.-0.002b\nCommands\n  b[reak] [file:|class:]<line|method>\n  b[reak] [class.]<line|method>\n                             set breakpoint to some position\n  wat[ch] <expression>       set watchpoint to some expression\n  cat[ch] (<exception>|off)  set catchpoint to an exception\n  b[reak]                    list breakpoints\n  cat[ch]                    show catchpoint\n  del[ete][ nnn]             delete some or all breakpoints\n  disp[lay] <expression>     add expression into display expression list\n  undisp[lay][ nnn]          delete one particular or all display expressions\n  c[ont]                     run until program ends or hit breakpoint\n  s[tep][ nnn]               step (into methods) one line or till line nnn\n  n[ext][ nnn]               go over one line or till line nnn\n  w[here]                    display frames\n  f[rame]                    alias for where\n  l[ist][ (-|nn-mm)]         list program, - lists backwards\n                             nn-mm lists given lines\n  up[ nn]                    move to higher frame\n  down[ nn]                  move to lower frame\n  fin[ish]                   return to outer frame\n  tr[ace] (on|off)           set trace mode of current thread\n  tr[ace] (on|off) all       set trace mode of all threads\n  q[uit]                     exit from debugger\n  v[ar] g[lobal]             show global variables\n  v[ar] l[ocal]              show local variables\n  v[ar] i[nstance] <object>  show instance variables of object\n  v[ar] c[onst] <object>     show constants of object\n  m[ethod] i[nstance] <obj>  show methods of object\n  m[ethod] <class|module>    show instance methods of class or module\n  th[read] l[ist]            list all threads\n  th[read] c[ur[rent]]       show current thread\n  th[read] [sw[itch]] <nnn>  switch thread context to nnn\n  th[read] stop <nnn>        stop thread nnn\n  th[read] resume <nnn>      resume thread nnn\n  p expression               evaluate expression and print its value\n  h[elp]                     print this help\n  <everything else>          evaluate\n"
548:   end

[Source]

     # File lib/debug.rb, line 175
175:   def debug_silent_eval(str, binding)
176:     begin
177:       eval(str, binding)
178:     rescue StandardError, ScriptError
179:       nil
180:     end
181:   end

[Source]

     # File lib/debug.rb, line 190
190:   def debug_variable_info(input, binding)
191:     case input
192:     when /^\s*g(?:lobal)?\s*$/
193:       var_list(global_variables, binding)
194: 
195:     when /^\s*l(?:ocal)?\s*$/
196:       var_list(eval("local_variables", binding), binding)
197: 
198:     when /^\s*i(?:nstance)?\s+/
199:       obj = debug_eval($', binding)
200:       var_list(obj.instance_variables, obj.instance_eval{binding()})
201: 
202:     when /^\s*c(?:onst(?:ant)?)?\s+/
203:       obj = debug_eval($', binding)
204:       unless obj.kind_of? Module
205:         stdout.print "Should be Class/Module: ", $', "\n"
206:       else
207:         var_list(obj.constants, obj.module_eval{binding()})
208:       end
209:     end
210:   end

[Source]

     # File lib/debug.rb, line 146
146:   def display
147:     DEBUGGER__.display
148:   end

[Source]

     # File lib/debug.rb, line 602
602:   def display_expression(exp, binding)
603:     stdout.printf "%s = %s\n", exp, debug_silent_eval(exp, binding).to_s
604:   end

[Source]

     # File lib/debug.rb, line 591
591:   def display_expressions(binding)
592:     n = 1
593:     for d in display
594:       if d[0]
595:         stdout.printf "%d: ", n
596:         display_expression(d[1], binding)
597:       end
598:       n += 1
599:     end
600:   end

[Source]

     # File lib/debug.rb, line 613
613:   def display_frames(pos)
614:     0.upto(@frames.size - 1) do |n|
615:       if n == pos
616:         stdout.print "--> "
617:       else
618:         stdout.print "    "
619:       end
620:       stdout.print format_frame(n)
621:     end
622:   end

[Source]

     # File lib/debug.rb, line 630
630:   def display_list(b, e, file, line)
631:     stdout.printf "[%d, %d] in %s\n", b, e, file
632:     if lines = SCRIPT_LINES__[file] and lines != true
633:       n = 0
634:       b.upto(e) do |n|
635:         if n > 0 && lines[n-1]
636:           if n == line
637:             stdout.printf "=> %d  %s\n", n, lines[n-1].chomp
638:           else
639:             stdout.printf "   %d  %s\n", n, lines[n-1].chomp
640:           end
641:         end
642:       end
643:     else
644:       stdout.printf "No sourcefile available for %s\n", file
645:     end
646:   end

[Source]

     # File lib/debug.rb, line 690
690:   def excn_handle(file, line, id, binding)
691:     if $!.class <= SystemExit
692:       set_trace_func nil
693:       exit
694:     end
695: 
696:     if @catch and ($!.class.ancestors.find { |e| e.to_s == @catch })
697:       stdout.printf "%s:%d: `%s' (%s)\n", file, line, $!, $!.class
698:       fs = @frames.size
699:       tb = caller(0)[-fs..-1]
700:       if tb
701:         for i in tb
702:           stdout.printf "\tfrom %s\n", i
703:         end
704:       end
705:       suspend_all
706:       debug_command(file, line, id, binding)
707:     end
708:   end

[Source]

     # File lib/debug.rb, line 624
624:   def format_frame(pos)
625:     bind, file, line, id = @frames[pos]
626:     sprintf "#%d %s:%s%s\n", pos + 1, file, line,
627:       (id ? ":in `#{id.id2name}'" : "")
628:   end

[Source]

     # File lib/debug.rb, line 606
606:   def frame_set_pos(file, line)
607:     if @frames[0]
608:       @frames[0][1] = file
609:       @frames[0][2] = line
610:     end
611:   end

[Source]

     # File lib/debug.rb, line 648
648:   def line_at(file, line)
649:     lines = SCRIPT_LINES__[file]
650:     if lines
651:       return "\n" if lines == true
652:       line = lines[line-1]
653:       return "\n" unless line
654:       return line
655:     end
656:     return "\n"
657:   end

[Source]

    # File lib/debug.rb, line 68
68:     def readline(prompt, hist)
69:       Readline::readline(prompt, hist)
70:     end

[Source]

    # File lib/debug.rb, line 72
72:     def readline(prompt, hist)
73:       STDOUT.print prompt
74:       STDOUT.flush
75:       line = STDIN.gets
76:       exit unless line
77:       line.chomp!
78:       line
79:     end

[Source]

     # File lib/debug.rb, line 116
116:   def resume_all
117:     DEBUGGER__.resume
118:   end

[Source]

     # File lib/debug.rb, line 158
158:   def set_last_thread(th)
159:     DEBUGGER__.set_last_thread(th)
160:   end

[Source]

     # File lib/debug.rb, line 104
104:   def set_suspend
105:     @suspend_next = true
106:   end

[Source]

     # File lib/debug.rb, line 134
134:   def set_trace(arg)
135:     @trace = arg
136:   end

[Source]

     # File lib/debug.rb, line 154
154:   def set_trace_all(arg)
155:     DEBUGGER__.set_trace(arg)
156:   end

[Source]

     # File lib/debug.rb, line 138
138:   def stdout
139:     DEBUGGER__.stdout
140:   end

[Source]

     # File lib/debug.rb, line 100
100:   def stop_next(n=1)
101:     @stop_next = n
102:   end

[Source]

     # File lib/debug.rb, line 112
112:   def suspend_all
113:     DEBUGGER__.suspend
114:   end

[Source]

     # File lib/debug.rb, line 247
247:   def thnum
248:     num = DEBUGGER__.instance_eval{@thread_list[Thread.current]}
249:     unless num
250:       DEBUGGER__.make_thread_list
251:       num = DEBUGGER__.instance_eval{@thread_list[Thread.current]}
252:     end
253:     num
254:   end

[Source]

     # File lib/debug.rb, line 130
130:   def trace?
131:     @trace
132:   end

[Source]

     # File lib/debug.rb, line 710
710:   def trace_func(event, file, line, id, binding, klass)
711:     Tracer.trace_func(event, file, line, id, binding, klass) if trace?
712:     context(Thread.current).check_suspend
713:     @file = file
714:     @line = line
715:     case event
716:     when 'line'
717:       frame_set_pos(file, line)
718:       if !@no_step or @frames.size == @no_step
719:         @stop_next -= 1
720:         @stop_next = -1 if @stop_next < 0
721:       elsif @frames.size < @no_step
722:         @stop_next = 0         # break here before leaving...
723:       else
724:         # nothing to do. skipped.
725:       end
726:       if @stop_next == 0 or check_break_points(file, nil, line, binding, id)
727:         @no_step = nil
728:         suspend_all
729:         debug_command(file, line, id, binding)
730:       end
731: 
732:     when 'call'
733:       @frames.unshift [binding, file, line, id]
734:       if check_break_points(file, klass, id.id2name, binding, id)
735:         suspend_all
736:         debug_command(file, line, id, binding)
737:       end
738: 
739:     when 'c-call'
740:       frame_set_pos(file, line)
741: 
742:     when 'class'
743:       @frames.unshift [binding, file, line, id]
744: 
745:     when 'return', 'end'
746:       if @frames.size == @finish_pos
747:         @stop_next = 1
748:         @finish_pos = 0
749:       end
750:       @frames.shift
751: 
752:     when 'end'
753:       @frames.shift
754: 
755:     when 'raise' 
756:       excn_handle(file, line, id, binding)
757: 
758:     end
759:     @last_file = file
760:   end

[Source]

     # File lib/debug.rb, line 183
183:   def var_list(ary, binding)
184:     ary.sort!
185:     for v in ary
186:       stdout.printf "  %s => %s\n", v, eval(v, binding).inspect
187:     end
188:   end

[Validate]