Project

General

Profile

Bug #6743 ยป 0001-Add-documentation-for-Debug-library.patch

oscardelben (Oscar Del Ben), 07/17/2012 02:51 AM

View differences:

lib/debug.rb
12 12
require 'tracer'
13 13
require 'pp'
14 14

  
15
class Tracer
15
class Tracer # :nodoc:
16 16
  def Tracer.trace_func(*vars)
17 17
    Single.trace_func(*vars)
18 18
  end
19 19
end
20 20

  
21
SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__
22

  
23
class DEBUGGER__
24
  MUTEX = Mutex.new
25

  
26
  class Context
21
SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__ # :nodoc:
22

  
23
##
24
# This library provides debugging functionality to Ruby.
25
#
26
# To add a debugger to your code, start by requiring +debug+ in your
27
# program:
28
#
29
#   def say(word)
30
#     require 'debug'
31
#     puts word
32
#   end
33
#
34
# This will cause Ruby to interrupt execution and show a prompt when the +say+ method is
35
# run.
36
#
37
# Once you're inside the prompt, you can start debugging your program.
38
#
39
#   (rdb:1) p word
40
#   "hello"
41
#
42
# == Getting help
43
#
44
# You can get help at any time by pressing +h+.
45
#
46
#   (rdb:1) h
47
#   Debugger help v.-0.002b
48
#   Commands
49
#     b[reak] [file:|class:]<line|method>
50
#     b[reak] [class.]<line|method>
51
#                                set breakpoint to some position
52
#     wat[ch] <expression>       set watchpoint to some expression
53
#     cat[ch] (<exception>|off)  set catchpoint to an exception
54
#     b[reak]                    list breakpoints
55
#     cat[ch]                    show catchpoint
56
#     del[ete][ nnn]             delete some or all breakpoints
57
#     disp[lay] <expression>     add expression into display expression list
58
#     undisp[lay][ nnn]          delete one particular or all display expressions
59
#     c[ont]                     run until program ends or hit breakpoint
60
#     s[tep][ nnn]               step (into methods) one line or till line nnn
61
#     n[ext][ nnn]               go over one line or till line nnn
62
#     w[here]                    display frames
63
#     f[rame]                    alias for where
64
#     l[ist][ (-|nn-mm)]         list program, - lists backwards
65
#                                nn-mm lists given lines
66
#     up[ nn]                    move to higher frame
67
#     down[ nn]                  move to lower frame
68
#     fin[ish]                   return to outer frame
69
#     tr[ace] (on|off)           set trace mode of current thread
70
#     tr[ace] (on|off) all       set trace mode of all threads
71
#     q[uit]                     exit from debugger
72
#     v[ar] g[lobal]             show global variables
73
#     v[ar] l[ocal]              show local variables
74
#     v[ar] i[nstance] <object>  show instance variables of object
75
#     v[ar] c[onst] <object>     show constants of object
76
#     m[ethod] i[nstance] <obj>  show methods of object
77
#     m[ethod] <class|module>    show instance methods of class or module
78
#     th[read] l[ist]            list all threads
79
#     th[read] c[ur[rent]]       show current thread
80
#     th[read] [sw[itch]] <nnn>  switch thread context to nnn
81
#     th[read] stop <nnn>        stop thread nnn
82
#     th[read] resume <nnn>      resume thread nnn
83
#     p expression               evaluate expression and print its value
84
#     h[elp]                     print this help
85
#     <everything else>          evaluate
86
#
87
# == Usage
88
#
89
# The following is a list of common functionalities that the Debugger
90
# library provides.
91
#
92
# === Navigating through your code
93
#
94
# In general, a debugger is used to find bugs in your program, which
95
# often means pausing execution and inspecting variables at some point
96
# in time.
97
#
98
# Let's look at an example:
99
#
100
#   def my_method(foo)
101
#     require 'debug'
102
#     foo = get_foo if foo.nil?
103
#     raise if foo.nil?
104
#   end
105
#
106
# When you run this program, the debugger will kick in just before the
107
# +foo+ assignment.
108
#
109
#   (rdb:1) p foo
110
#   nil
111
#
112
# In this example, it'd be interesting to move to the next line and
113
# inspect the value of +foo+ again. You can do that by pressing +n+:
114
#
115
#   (rdb:1) n # goes to next line
116
#   (rdb:1) p foo
117
#   nil
118
#
119
# You now know that the original value of +foo+ was nil, and that it
120
# still was nil after calling +get_foo+.
121
#
122
# Other useful commands for navigating through your code are:
123
#
124
# * +c+: runs the program until it either exists or encouters another breakpoint. You usually press +c+ when you are finished debugging your program and want to resume its execution.
125
# * +s+: steps into method definition. In the previous example, +s+ would take you inside the method definition of +get_foo+.
126
# * +r+: restart the program.
127
# * +q+: quit the progam.
128
#
129
# === Inspecting variables
130
#
131
# You can use the Debug library to easily inspect both local and global
132
# variables. We've seen how to inspect local variables before:
133
#
134
#   (rdb:1) p my_arg
135
#   42
136
#
137
# You can also pretty print the result of variables or expressions:
138
#
139
#   (rdb:1) pp %w{a very long long array containing many words}
140
#   ["a",
141
#    "very",
142
#    "long",
143
#    ...
144
#   ]
145
#
146
# You can list all local variables with +v l+:
147
#
148
#   (rdb:1) v l
149
#     foo => "hello"
150
#
151
# Similarly, you can show all global variables with +v g+:
152
#
153
#   (rdb:1) v g
154
#     all global variables
155
#
156
# Finally, you can omit +p+ if you simply want to evaluate a variable or
157
# expression
158
#
159
#   (rdb:1) 5**2
160
#   25
161
#
162
# === Going beyond basics
163
#
164
# Ruby Debug provides more advanced functionalities like switching
165
# between threads, setting breakpoints and watch expressions, and more.
166
# The full list of commands is available at any time by pressing +h+.
167
#
168
# == Staying out of trouble
169
#
170
# Make sure you remove every instance of +require 'debug'+ before
171
# shipping your code. Failing to do so may result in your program
172
# hanging unpredictably.
173
#
174
# Debug is not available in safe mode.
175
class Debugger
176
  MUTEX = Mutex.new # :nodoc:
177

  
178
  class Context # :nodoc:
27 179
    DEBUG_LAST_CMD = []
28 180

  
29 181
    begin
......
73 225
    end
74 226

  
75 227
    def suspend_all
76
      DEBUGGER__.suspend
228
      Debugger.suspend
77 229
    end
78 230

  
79 231
    def resume_all
80
      DEBUGGER__.resume
232
      Debugger.resume
81 233
    end
82 234

  
83 235
    def check_suspend
84 236
      while MUTEX.synchronize {
85 237
          if @suspend_next
86
            DEBUGGER__.waiting.push Thread.current
238
            Debugger.waiting.push Thread.current
87 239
            @suspend_next = false
88 240
            true
89 241
          end
......
91 243
      end
92 244
    end
93 245

  
94
    def trace?
246
    def trace? # :nodoc:
95 247
      @trace
96 248
    end
97 249

  
98
    def set_trace(arg)
250
    def set_trace(arg) # :nodoc:
99 251
      @trace = arg
100 252
    end
101 253

  
102
    def stdout
103
      DEBUGGER__.stdout
254
    def stdout # :nodoc:
255
      Debugger.stdout
104 256
    end
105 257

  
106
    def break_points
107
      DEBUGGER__.break_points
258
    def break_points # :nodoc:
259
      Debugger.break_points
108 260
    end
109 261

  
110
    def display
111
      DEBUGGER__.display
262
    def display # :nodoc:
263
      Debugger.display
112 264
    end
113 265

  
114
    def context(th)
115
      DEBUGGER__.context(th)
266
    def context(th) # :nodoc:
267
      Debugger.context(th)
116 268
    end
117 269

  
118
    def set_trace_all(arg)
119
      DEBUGGER__.set_trace(arg)
270
    def set_trace_all(arg) # :nodoc:
271
      Debugger.set_trace(arg)
120 272
    end
121 273

  
122
    def set_last_thread(th)
123
      DEBUGGER__.set_last_thread(th)
274
    def set_last_thread(th) # :nodoc:
275
      Debugger.set_last_thread(th)
124 276
    end
125 277

  
126
    def debug_eval(str, binding)
278
    def debug_eval(str, binding) # :nodoc:
127 279
      begin
128 280
        eval(str, binding)
129 281
      rescue StandardError, ScriptError => e
......
136 288
      end
137 289
    end
138 290

  
139
    def debug_silent_eval(str, binding)
291
    def debug_silent_eval(str, binding) # :nodoc:
140 292
      begin
141 293
        eval(str, binding)
142 294
      rescue StandardError, ScriptError
......
144 296
      end
145 297
    end
146 298

  
147
    def var_list(ary, binding)
299
    def var_list(ary, binding) # :nodoc:
148 300
      ary.sort!
149 301
      for v in ary
150 302
        stdout.printf "  %s => %s\n", v, eval(v.to_s, binding).inspect
151 303
      end
152 304
    end
153 305

  
154
    def debug_variable_info(input, binding)
306
    def debug_variable_info(input, binding) # :nodoc:
155 307
      case input
156 308
      when /^\s*g(?:lobal)?\s*$/
157 309
        var_list(global_variables, binding)
......
173 325
      end
174 326
    end
175 327

  
176
    def debug_method_info(input, binding)
328
    def debug_method_info(input, binding) # :nodoc:
177 329
      case input
178 330
      when /^i(:?nstance)?\s+/
179 331
        obj = debug_eval($', binding)
......
208 360
      end
209 361
    end
210 362

  
211
    def thnum
212
      num = DEBUGGER__.instance_eval{@thread_list[Thread.current]}
363
    def thnum # :nodoc:
364
      num = Debugger.instance_eval{@thread_list[Thread.current]}
213 365
      unless num
214
        DEBUGGER__.make_thread_list
215
        num = DEBUGGER__.instance_eval{@thread_list[Thread.current]}
366
        Debugger.make_thread_list
367
        num = Debugger.instance_eval{@thread_list[Thread.current]}
216 368
      end
217 369
      num
218 370
    end
219 371

  
220
    def debug_command(file, line, id, binding)
372
    def debug_command(file, line, id, binding) # :nodoc:
221 373
      MUTEX.lock
222 374
      unless defined?($debugger_restart) and $debugger_restart
223 375
        callcc{|c| $debugger_restart = c}
......
481 633
            debug_method_info($', binding)
482 634

  
483 635
          when /^\s*th(?:read)?\s+/
484
            if DEBUGGER__.debug_thread_info($', binding) == :cont
636
            if Debugger.debug_thread_info($', binding) == :cont
485 637
              prompt = false
486 638
            end
487 639

  
......
507 659
      resume_all
508 660
    end
509 661

  
510
    def debug_print_help
662
    def debug_print_help # :nodoc:
511 663
      stdout.print <<EOHELP
512 664
Debugger help v.-0.002b
513 665
Commands
......
553 705
EOHELP
554 706
    end
555 707

  
556
    def display_expressions(binding)
708
    def display_expressions(binding) # :nodoc:
557 709
      n = 1
558 710
      for d in display
559 711
        if d[0]
......
564 716
      end
565 717
    end
566 718

  
567
    def display_expression(exp, binding)
719
    def display_expression(exp, binding) # :nodoc:
568 720
      stdout.printf "%s = %s\n", exp, debug_silent_eval(exp, binding).to_s
569 721
    end
570 722

  
571
    def frame_set_pos(file, line)
723
    def frame_set_pos(file, line) # :nodoc:
572 724
      if @frames[0]
573 725
        @frames[0][1] = file
574 726
        @frames[0][2] = line
575 727
      end
576 728
    end
577 729

  
578
    def display_frames(pos)
730
    def display_frames(pos) # :nodoc:
579 731
      0.upto(@frames.size - 1) do |n|
580 732
        if n == pos
581 733
          stdout.print "--> "
......
586 738
      end
587 739
    end
588 740

  
589
    def format_frame(pos)
741
    def format_frame(pos) # :nodoc:
590 742
      _, file, line, id = @frames[pos]
591 743
      sprintf "#%d %s:%s%s\n", pos + 1, file, line,
592 744
        (id ? ":in `#{id.id2name}'" : "")
593 745
    end
594 746

  
595
    def display_list(b, e, file, line)
747
    def display_list(b, e, file, line) # :nodoc:
596 748
      stdout.printf "[%d, %d] in %s\n", b, e, file
597 749
      if lines = SCRIPT_LINES__[file] and lines != true
598 750
        b.upto(e) do |n|
......
609 761
      end
610 762
    end
611 763

  
612
    def line_at(file, line)
764
    def line_at(file, line) # :nodoc:
613 765
      lines = SCRIPT_LINES__[file]
614 766
      if lines
615 767
        return "\n" if lines == true
......
620 772
      return "\n"
621 773
    end
622 774

  
623
    def debug_funcname(id)
775
    def debug_funcname(id) # :nodoc:
624 776
      if id.nil?
625 777
        "toplevel"
626 778
      else
......
628 780
      end
629 781
    end
630 782

  
631
    def check_break_points(file, klass, pos, binding, id)
783
    def check_break_points(file, klass, pos, binding, id) # :nodoc:
632 784
      return false if break_points.empty?
633 785
      n = 1
634 786
      for b in break_points
......
651 803
      return false
652 804
    end
653 805

  
654
    def excn_handle(file, line, id, binding)
806
    def excn_handle(file, line, id, binding) # :nodoc:
655 807
      if $!.class <= SystemExit
656 808
        set_trace_func nil
657 809
        exit
......
671 823
      end
672 824
    end
673 825

  
674
    def trace_func(event, file, line, id, binding, klass)
826
    def trace_func(event, file, line, id, binding, klass) # :nodoc:
675 827
      Tracer.trace_func(event, file, line, id, binding, klass) if trace?
676 828
      context(Thread.current).check_suspend
677 829
      @file = file
......
721 873
    end
722 874
  end
723 875

  
724
  trap("INT") { DEBUGGER__.interrupt }
876
  trap("INT") { Debugger.interrupt }
725 877
  @last_thread = Thread::main
726 878
  @max_thread = 1
727 879
  @thread_list = {Thread::main => 1}
......
730 882
  @waiting = []
731 883
  @stdout = STDOUT
732 884

  
733
  class << DEBUGGER__
734
    def stdout
885
  class << Debugger
886
    def stdout # :nodoc:
735 887
      @stdout
736 888
    end
737 889

  
738
    def stdout=(s)
890
    def stdout=(s) # :nodoc:
739 891
      @stdout = s
740 892
    end
741 893

  
742
    def display
894
    def display # :nodoc:
743 895
      @display
744 896
    end
745 897

  
746
    def break_points
898
    def break_points # :nodoc:
747 899
      @break_points
748 900
    end
749 901

  
750
    def waiting
902
    def waiting # :nodoc:
751 903
      @waiting
752 904
    end
753 905

  
754
    def set_trace( arg )
906
    def set_trace( arg ) # :nodoc:
755 907
      MUTEX.synchronize do
756 908
        make_thread_list
757 909
        for th, in @thread_list
......
761 913
      arg
762 914
    end
763 915

  
764
    def set_last_thread(th)
916
    def set_last_thread(th) # :nodoc:
765 917
      @last_thread = th
766 918
    end
767 919

  
768
    def suspend
920
    def suspend # :nodoc:
769 921
      MUTEX.synchronize do
770 922
        make_thread_list
771 923
        for th, in @thread_list
......
777 929
      Thread.pass
778 930
    end
779 931

  
780
    def resume
932
    def resume # :nodoc:
781 933
      MUTEX.synchronize do
782 934
        make_thread_list
783 935
        @thread_list.each do |th,|
......
793 945
      Thread.pass
794 946
    end
795 947

  
796
    def context(thread=Thread.current)
948
    def context(thread=Thread.current) # :nodoc:
797 949
      c = thread[:__debugger_data__]
798 950
      unless c
799 951
        thread[:__debugger_data__] = c = Context.new
......
801 953
      c
802 954
    end
803 955

  
804
    def interrupt
956
    def interrupt # :nodoc:
805 957
      context(@last_thread).stop_next
806 958
    end
807 959

  
808
    def get_thread(num)
960
    def get_thread(num) # :nodoc:
809 961
      th = @thread_list.key(num)
810 962
      unless th
811 963
        @stdout.print "No thread ##{num}\n"
......
814 966
      th
815 967
    end
816 968

  
817
    def thread_list(num)
969
    def thread_list(num) # :nodoc:
818 970
      th = get_thread(num)
819 971
      if th == Thread.current
820 972
        @stdout.print "+"
......
830 982
      @stdout.print "\n"
831 983
    end
832 984

  
833
    def thread_list_all
985
    def thread_list_all # :nodoc:
834 986
      for th in @thread_list.values.sort
835 987
        thread_list(th)
836 988
      end
837 989
    end
838 990

  
839
    def make_thread_list
991
    def make_thread_list # :nodoc:
840 992
      hash = {}
841 993
      for th in Thread::list
842 994
        if @thread_list.key? th
......
849 1001
      @thread_list = hash
850 1002
    end
851 1003

  
852
    def debug_thread_info(input, binding)
1004
    def debug_thread_info(input, binding) # :nodoc:
853 1005
      case input
854 1006
      when /^l(?:ist)?/
855 1007
        make_thread_list
......
904 1056
    trace_instruction: true
905 1057
  }
906 1058
  set_trace_func proc { |event, file, line, id, binding, klass, *rest|
907
    DEBUGGER__.context.trace_func event, file, line, id, binding, klass
1059
    Debugger.context.trace_func event, file, line, id, binding, klass
908 1060
  }
909 1061
end
910
-