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

Constants

DEBUG_LAST_CMD = []
USE_READLINE = false

Public Class methods

[Source]

    # File 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 debug.rb, line 142
142:   def break_points
143:     DEBUGGER__.break_points
144:   end

[Source]

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

[Source]

     # File 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 debug.rb, line 108
108:   def clear_suspend
109:     @suspend_next = false
110:   end

[Source]

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

[Source]

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

[Source]

     # File 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 debug.rb, line 653
653:   def debug_funcname(id)
654:     if id.nil?
655:       "toplevel"
656:     else
657:       id.id2name
658:     end
659:   end

[Source]

     # File 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 debug.rb, line 540
540:   def debug_print_help
541:     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] <an Exception>     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"
542:   end

[Source]

     # File 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 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 debug.rb, line 146
146:   def display
147:     DEBUGGER__.display
148:   end

[Source]

     # File debug.rb, line 596
596:   def display_expression(exp, binding)
597:     stdout.printf "%s = %s\n", exp, debug_silent_eval(exp, binding).to_s
598:   end

[Source]

     # File debug.rb, line 585
585:   def display_expressions(binding)
586:     n = 1
587:     for d in display
588:       if d[0]
589:         stdout.printf "%d: ", n
590:         display_expression(d[1], binding)
591:       end
592:       n += 1
593:     end
594:   end

[Source]

     # File debug.rb, line 607
607:   def display_frames(pos)
608:     0.upto(@frames.size - 1) do |n|
609:       if n == pos
610:         stdout.print "--> "
611:       else
612:         stdout.print "    "
613:       end
614:       stdout.print format_frame(n)
615:     end
616:   end

[Source]

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

[Source]

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

[Source]

     # File debug.rb, line 618
618:   def format_frame(pos)
619:     bind, file, line, id = @frames[pos]
620:     sprintf "#%d %s:%s%s\n", pos + 1, file, line,
621:       (id ? ":in `#{id.id2name}'" : "")
622:   end

[Source]

     # File debug.rb, line 600
600:   def frame_set_pos(file, line)
601:     if @frames[0]
602:       @frames[0][1] = file
603:       @frames[0][2] = line
604:     end
605:   end

[Source]

     # File debug.rb, line 642
642:   def line_at(file, line)
643:     lines = SCRIPT_LINES__[file]
644:     if lines
645:       return "\n" if lines == true
646:       line = lines[line-1]
647:       return "\n" unless line
648:       return line
649:     end
650:     return "\n"
651:   end

[Source]

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

[Source]

    # File 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 debug.rb, line 116
116:   def resume_all
117:     DEBUGGER__.resume
118:   end

[Source]

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

[Source]

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

[Source]

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

[Source]

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

[Source]

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

[Source]

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

[Source]

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

[Source]

     # File 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 debug.rb, line 130
130:   def trace?
131:     @trace
132:   end

[Source]

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

[Source]

     # File 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

Search

Google

Ruby API Docs

Links