debugger2 1.0.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.travis.yml +3 -0
  4. data/AUTHORS +10 -0
  5. data/CHANGELOG.md +65 -0
  6. data/CONTRIBUTING.md +1 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE +23 -0
  9. data/OLDER_CHANGELOG +334 -0
  10. data/OLD_CHANGELOG +5655 -0
  11. data/OLD_README +122 -0
  12. data/README.md +108 -0
  13. data/Rakefile +78 -0
  14. data/bin/rdebug +397 -0
  15. data/debugger2.gemspec +29 -0
  16. data/doc/.cvsignore +42 -0
  17. data/doc/Makefile.am +63 -0
  18. data/doc/emacs-notes.txt +38 -0
  19. data/doc/hanoi.rb +35 -0
  20. data/doc/primes.rb +28 -0
  21. data/doc/rdebug-emacs.texi +1030 -0
  22. data/doc/ruby-debug.texi +3791 -0
  23. data/doc/test-tri2.rb +18 -0
  24. data/doc/tri3.rb +8 -0
  25. data/doc/triangle.rb +12 -0
  26. data/emacs/Makefile.am +130 -0
  27. data/emacs/rdebug-annotate.el +385 -0
  28. data/emacs/rdebug-breaks.el +407 -0
  29. data/emacs/rdebug-cmd.el +92 -0
  30. data/emacs/rdebug-core.el +502 -0
  31. data/emacs/rdebug-dbg.el +62 -0
  32. data/emacs/rdebug-error.el +79 -0
  33. data/emacs/rdebug-fns.el +111 -0
  34. data/emacs/rdebug-frames.el +230 -0
  35. data/emacs/rdebug-gud.el +242 -0
  36. data/emacs/rdebug-help.el +104 -0
  37. data/emacs/rdebug-info.el +83 -0
  38. data/emacs/rdebug-layouts.el +180 -0
  39. data/emacs/rdebug-locring.el +118 -0
  40. data/emacs/rdebug-output.el +106 -0
  41. data/emacs/rdebug-regexp.el +118 -0
  42. data/emacs/rdebug-secondary.el +260 -0
  43. data/emacs/rdebug-shortkey.el +175 -0
  44. data/emacs/rdebug-source.el +568 -0
  45. data/emacs/rdebug-track.el +392 -0
  46. data/emacs/rdebug-varbuf.el +150 -0
  47. data/emacs/rdebug-vars.el +125 -0
  48. data/emacs/rdebug-watch.el +132 -0
  49. data/emacs/rdebug.el +326 -0
  50. data/emacs/test/elk-test.el +242 -0
  51. data/emacs/test/test-annotate.el +103 -0
  52. data/emacs/test/test-cmd.el +116 -0
  53. data/emacs/test/test-core.el +104 -0
  54. data/emacs/test/test-fns.el +65 -0
  55. data/emacs/test/test-frames.el +62 -0
  56. data/emacs/test/test-gud.el +35 -0
  57. data/emacs/test/test-indent.el +58 -0
  58. data/emacs/test/test-regexp.el +144 -0
  59. data/emacs/test/test-shortkey.el +61 -0
  60. data/ext/ruby_debug/breakpoint.c +630 -0
  61. data/ext/ruby_debug/extconf.rb +11 -0
  62. data/ext/ruby_debug/ruby_debug.c +2203 -0
  63. data/ext/ruby_debug/ruby_debug.h +151 -0
  64. data/lib/debugger.rb +5 -0
  65. data/lib/debugger/version.rb +5 -0
  66. data/lib/debugger2.rb +6 -0
  67. data/lib/ruby-debug-base.rb +307 -0
  68. data/lib/ruby-debug.rb +176 -0
  69. data/lib/ruby-debug/command.rb +227 -0
  70. data/lib/ruby-debug/commands/breakpoints.rb +153 -0
  71. data/lib/ruby-debug/commands/catchpoint.rb +55 -0
  72. data/lib/ruby-debug/commands/condition.rb +49 -0
  73. data/lib/ruby-debug/commands/continue.rb +38 -0
  74. data/lib/ruby-debug/commands/control.rb +107 -0
  75. data/lib/ruby-debug/commands/display.rb +120 -0
  76. data/lib/ruby-debug/commands/edit.rb +48 -0
  77. data/lib/ruby-debug/commands/enable.rb +202 -0
  78. data/lib/ruby-debug/commands/eval.rb +176 -0
  79. data/lib/ruby-debug/commands/finish.rb +42 -0
  80. data/lib/ruby-debug/commands/frame.rb +301 -0
  81. data/lib/ruby-debug/commands/help.rb +56 -0
  82. data/lib/ruby-debug/commands/info.rb +467 -0
  83. data/lib/ruby-debug/commands/irb.rb +123 -0
  84. data/lib/ruby-debug/commands/jump.rb +66 -0
  85. data/lib/ruby-debug/commands/kill.rb +51 -0
  86. data/lib/ruby-debug/commands/list.rb +94 -0
  87. data/lib/ruby-debug/commands/method.rb +84 -0
  88. data/lib/ruby-debug/commands/quit.rb +39 -0
  89. data/lib/ruby-debug/commands/reload.rb +40 -0
  90. data/lib/ruby-debug/commands/save.rb +90 -0
  91. data/lib/ruby-debug/commands/set.rb +223 -0
  92. data/lib/ruby-debug/commands/show.rb +247 -0
  93. data/lib/ruby-debug/commands/skip.rb +35 -0
  94. data/lib/ruby-debug/commands/source.rb +36 -0
  95. data/lib/ruby-debug/commands/stepping.rb +81 -0
  96. data/lib/ruby-debug/commands/threads.rb +189 -0
  97. data/lib/ruby-debug/commands/tmate.rb +36 -0
  98. data/lib/ruby-debug/commands/trace.rb +57 -0
  99. data/lib/ruby-debug/commands/variables.rb +199 -0
  100. data/lib/ruby-debug/debugger.rb +5 -0
  101. data/lib/ruby-debug/helper.rb +69 -0
  102. data/lib/ruby-debug/interface.rb +232 -0
  103. data/lib/ruby-debug/processor.rb +474 -0
  104. data/man/rdebug.1 +241 -0
  105. data/old_scripts/Makefile.am +14 -0
  106. data/old_scripts/README.md +2 -0
  107. data/old_scripts/autogen.sh +4 -0
  108. data/old_scripts/configure.ac +12 -0
  109. data/old_scripts/rdbg.rb +33 -0
  110. data/old_scripts/runner.sh +7 -0
  111. data/old_scripts/svn2cl_usermap +3 -0
  112. data/test/.cvsignore +1 -0
  113. data/test/breakpoints_test.rb +366 -0
  114. data/test/conditions_test.rb +77 -0
  115. data/test/continue_test.rb +28 -0
  116. data/test/display_test.rb +143 -0
  117. data/test/edit_test.rb +55 -0
  118. data/test/eval_test.rb +94 -0
  119. data/test/examples/breakpoint1.rb +15 -0
  120. data/test/examples/breakpoint2.rb +7 -0
  121. data/test/examples/conditions.rb +4 -0
  122. data/test/examples/continue.rb +4 -0
  123. data/test/examples/display.rb +5 -0
  124. data/test/examples/edit.rb +3 -0
  125. data/test/examples/edit2.rb +3 -0
  126. data/test/examples/eval.rb +4 -0
  127. data/test/examples/finish.rb +20 -0
  128. data/test/examples/frame.rb +31 -0
  129. data/test/examples/help.rb +2 -0
  130. data/test/examples/info.rb +48 -0
  131. data/test/examples/info2.rb +3 -0
  132. data/test/examples/irb.rb +6 -0
  133. data/test/examples/jump.rb +14 -0
  134. data/test/examples/kill.rb +2 -0
  135. data/test/examples/list.rb +12 -0
  136. data/test/examples/method.rb +15 -0
  137. data/test/examples/post_mortem.rb +19 -0
  138. data/test/examples/quit.rb +2 -0
  139. data/test/examples/reload.rb +6 -0
  140. data/test/examples/restart.rb +6 -0
  141. data/test/examples/save.rb +3 -0
  142. data/test/examples/set.rb +3 -0
  143. data/test/examples/set_annotate.rb +12 -0
  144. data/test/examples/settings.rb +1 -0
  145. data/test/examples/show.rb +2 -0
  146. data/test/examples/source.rb +3 -0
  147. data/test/examples/stepping.rb +21 -0
  148. data/test/examples/thread.rb +32 -0
  149. data/test/examples/tmate.rb +10 -0
  150. data/test/examples/trace.rb +7 -0
  151. data/test/examples/trace_threads.rb +20 -0
  152. data/test/examples/variables.rb +26 -0
  153. data/test/finish_test.rb +49 -0
  154. data/test/frame_test.rb +140 -0
  155. data/test/help_test.rb +51 -0
  156. data/test/info_test.rb +326 -0
  157. data/test/irb_test.rb +82 -0
  158. data/test/jump_test.rb +70 -0
  159. data/test/kill_test.rb +49 -0
  160. data/test/list_test.rb +147 -0
  161. data/test/method_test.rb +72 -0
  162. data/test/post_mortem_test.rb +25 -0
  163. data/test/quit_test.rb +56 -0
  164. data/test/reload_test.rb +47 -0
  165. data/test/restart_test.rb +145 -0
  166. data/test/save_test.rb +94 -0
  167. data/test/set_test.rb +183 -0
  168. data/test/show_test.rb +294 -0
  169. data/test/source_test.rb +46 -0
  170. data/test/stepping_test.rb +122 -0
  171. data/test/support/breakpoint.rb +12 -0
  172. data/test/support/context.rb +14 -0
  173. data/test/support/matchers.rb +67 -0
  174. data/test/support/mocha_extensions.rb +71 -0
  175. data/test/support/processor.rb +7 -0
  176. data/test/support/test_dsl.rb +206 -0
  177. data/test/support/test_interface.rb +66 -0
  178. data/test/test_helper.rb +9 -0
  179. data/test/thread_test.rb +124 -0
  180. data/test/tmate_test.rb +45 -0
  181. data/test/trace_test.rb +156 -0
  182. data/test/variables_test.rb +116 -0
  183. metadata +319 -0
@@ -0,0 +1,151 @@
1
+ #include <ruby.h>
2
+ #include "ruby/debug.h"
3
+
4
+ /* Context info */
5
+ enum ctx_stop_reason {
6
+ CTX_STOP_NONE,
7
+ CTX_STOP_STEP,
8
+ CTX_STOP_BREAKPOINT,
9
+ CTX_STOP_CATCHPOINT
10
+ };
11
+
12
+ /* Context flags */
13
+ #define CTX_FL_SUSPEND (1<<1) /* suspend because another thread stopping */
14
+ #define CTX_FL_TRACING (1<<2) /* call at_tracing method */
15
+ #define CTX_FL_SKIPPED (1<<3) /* skip all debugger events */
16
+ #define CTX_FL_IGNORE (1<<4) /* this context belongs to ignored thread */
17
+ #define CTX_FL_DEAD (1<<5) /* this context belonged to died thraed */
18
+ #define CTX_FL_WAS_RUNNING (1<<6) /* previous thread state */
19
+ #define CTX_FL_ENABLE_BKPT (1<<7) /* can check breakpoint */
20
+ #define CTX_FL_STEPPED (1<<8)
21
+ #define CTX_FL_FORCE_MOVE (1<<9)
22
+ #define CTX_FL_CATCHING (1<<10)
23
+
24
+ #if 0
25
+ static inline const char *
26
+ flag_name(int flag)
27
+ {
28
+ switch (flag) {
29
+ #define C(x) case x: return #x
30
+ C(CTX_FL_SUSPEND);
31
+ C(CTX_FL_TRACING);
32
+ C(CTX_FL_SKIPPED);
33
+ C(CTX_FL_IGNORE);
34
+ C(CTX_FL_DEAD);
35
+ C(CTX_FL_WAS_RUNNING);
36
+ C(CTX_FL_ENABLE_BKPT);
37
+ C(CTX_FL_STEPPED);
38
+ C(CTX_FL_FORCE_MOVE);
39
+ C(CTX_FL_CATCHING);
40
+ default:
41
+ return "unknown";
42
+ }
43
+ }
44
+ #define CTX_DUMP(set, f) fprintf(stderr, "[CTX %s:%d] %s %s\n", __FILE__, __LINE__, (set) ? "set" : "unset", flag_name(f))
45
+ #else
46
+ #define CTX_DUMP(set, f)
47
+ #endif
48
+
49
+ #define CTX_FL_TEST(c,f) ((c)->flags & (f))
50
+ #define CTX_FL_SET(c,f) do { CTX_DUMP(1, f); (c)->flags |= (f); } while (0)
51
+ #define CTX_FL_UNSET(c,f) do { CTX_DUMP(0, f); (c)->flags &= ~(f); } while (0)
52
+
53
+ typedef struct {
54
+ VALUE thread_id;
55
+ int thnum;
56
+ int flags;
57
+ int calced_stack_size;
58
+ enum ctx_stop_reason stop_reason;
59
+
60
+ /* control flow */
61
+ int stop_next;
62
+ int dest_frame;
63
+ int stop_line;
64
+ int stop_frame;
65
+
66
+ int thread_pause;
67
+
68
+ VALUE last_file;
69
+ VALUE last_line;
70
+
71
+ VALUE breakpoint;
72
+
73
+ /* [[loc, self, klass, binding, iseq], ...] */
74
+ VALUE inspected_frame;
75
+ } debug_context_t;
76
+
77
+ enum inspected_frame_type {
78
+ INSPECTED_FRAME_LOCATION,
79
+ INSPECTED_FRAME_SELF,
80
+ INSPECTED_FRAME_CLASS,
81
+ INSPECTED_FRAME_BIDING,
82
+ INSPECTED_FRAME_ISEQ,
83
+ };
84
+
85
+ /* variables in ruby_debug.c */
86
+ extern VALUE mDebugger;
87
+ extern VALUE rdebug_breakpoints;
88
+ extern VALUE rdebug_catchpoints;
89
+ extern VALUE rdebug_threads_tbl;
90
+
91
+ #define IS_STARTED (rdebug_threads_tbl != Qnil)
92
+ static inline void
93
+ debug_check_started()
94
+ {
95
+ if (!IS_STARTED) {
96
+ rb_raise(rb_eRuntimeError, "Debugger.start is not called yet.");
97
+ }
98
+ }
99
+
100
+ static inline int
101
+ classname_cmp(VALUE name, VALUE klass)
102
+ {
103
+ VALUE mod_name;
104
+ VALUE class_name = (Qnil == name) ? rb_str_new2("main") : name;
105
+ if (klass == Qnil) return(0);
106
+ mod_name = rb_mod_name(klass);
107
+ return (mod_name != Qnil
108
+ && rb_str_cmp(class_name, mod_name) == 0);
109
+ }
110
+
111
+ /* Breakpoint information */
112
+ enum bp_type {
113
+ BP_POS_TYPE,
114
+ BP_METHOD_TYPE
115
+ };
116
+
117
+ enum hit_condition {
118
+ HIT_COND_NONE,
119
+ HIT_COND_GE,
120
+ HIT_COND_EQ,
121
+ HIT_COND_MOD
122
+ };
123
+
124
+ typedef struct {
125
+ int id;
126
+ enum bp_type type;
127
+ VALUE source;
128
+ union {
129
+ int line;
130
+ ID mid;
131
+ } pos;
132
+ VALUE expr;
133
+ VALUE enabled;
134
+ int hit_count;
135
+ int hit_value;
136
+ enum hit_condition hit_condition;
137
+ } debug_breakpoint_t;
138
+
139
+ /* routines in breakpoint.c */
140
+ extern int check_breakpoint_expression(VALUE breakpoint, VALUE binding);
141
+ extern int check_breakpoint_hit_condition(VALUE breakpoint);
142
+ extern VALUE check_breakpoints_by_method(debug_context_t *debug_context, VALUE klass, ID mid, VALUE self);
143
+ extern VALUE check_breakpoints_by_pos(debug_context_t *debug_context, VALUE file, VALUE line);
144
+ extern VALUE create_breakpoint_from_args(int argc, VALUE *argv, int id);
145
+ extern VALUE context_breakpoint(VALUE self);
146
+ extern VALUE context_set_breakpoint(int argc, VALUE *argv, VALUE self);
147
+ extern VALUE rdebug_add_catchpoint(VALUE self, VALUE value);
148
+ extern VALUE debug_catchpoints(VALUE self);
149
+ extern VALUE rdebug_remove_breakpoint(VALUE self, VALUE id_value);
150
+
151
+ extern void Init_breakpoint();
@@ -0,0 +1,5 @@
1
+ module Debugger
2
+ end
3
+
4
+ require 'ruby-debug'
5
+ require 'debugger/version'
@@ -0,0 +1,5 @@
1
+ module Debugger
2
+ # TODO: remove version from C ext
3
+ send :remove_const, :VERSION if const_defined? :VERSION
4
+ VERSION = '1.0.0.beta1'
5
+ end
@@ -0,0 +1,6 @@
1
+ p 'loading debugger2...'
2
+ module Debugger
3
+ end
4
+
5
+ require 'ruby-debug'
6
+ require 'debugger/version'
@@ -0,0 +1,307 @@
1
+ require 'ruby_debug.so'
2
+ require 'linecache19'
3
+
4
+ module Debugger
5
+
6
+ # Default options to Debugger.start
7
+ DEFAULT_START_SETTINGS = {
8
+ :init => true, # Set $0 and save ARGV?
9
+ :post_mortem => false, # post-mortem debugging on uncaught exception?
10
+ :tracing => nil # Debugger.tracing value. true/false resets,
11
+ # nil keeps the prior value
12
+ } unless defined?(DEFAULT_START_SETTINGS)
13
+
14
+ class Context
15
+ def interrupt
16
+ self.stop_next = 1
17
+ end
18
+
19
+ alias __c_frame_binding frame_binding
20
+ def frame_binding(frame)
21
+ b = __c_frame_binding(frame)
22
+ return b if b
23
+ hbinding(frame)
24
+ end
25
+
26
+ private
27
+
28
+ def hbinding(frame)
29
+ hash = frame_locals(frame)
30
+ code = hash.keys.map{|k| "#{k} = hash['#{k}']" unless k=='self' }.compact.join(';') + ';binding'
31
+ if obj = frame_self(frame)
32
+ obj.instance_eval code
33
+ else
34
+ eval code, TOPLEVEL_BINDING
35
+ end
36
+ end
37
+
38
+ def handler
39
+ Debugger.handler or raise 'No interface loaded'
40
+ end
41
+
42
+ def at_breakpoint(breakpoint)
43
+ handler.at_breakpoint(self, breakpoint)
44
+ end
45
+
46
+ def at_catchpoint(excpt)
47
+ handler.at_catchpoint(self, excpt)
48
+ end
49
+
50
+ def at_tracing(file, line)
51
+ @tracing_started = File.identical?(file, Debugger::PROG_SCRIPT)
52
+ handler.at_tracing(self, file, line) if @tracing_started
53
+ end
54
+
55
+ def at_line(file, line)
56
+ handler.at_line(self, file, line)
57
+ end
58
+
59
+ def at_return(file, line)
60
+ handler.at_return(self, file, line)
61
+ end
62
+ end
63
+
64
+ @reload_source_on_change = false
65
+ @tracing_started = false
66
+
67
+ class << self
68
+ # interface modules provide +handler+ object
69
+ attr_accessor :handler
70
+
71
+ # if <tt>true</tt>, checks the modification time of source files and reloads if it was modified
72
+ attr_accessor :reload_source_on_change
73
+
74
+ attr_accessor :last_exception
75
+ Debugger.last_exception = nil
76
+
77
+ #
78
+ # Interrupts the current thread
79
+ #
80
+ def interrupt
81
+ current_context.interrupt
82
+ end
83
+
84
+ #
85
+ # Interrupts the last debugged thread
86
+ #
87
+ def interrupt_last
88
+ if context = last_context
89
+ return nil unless context.thread.alive?
90
+ context.interrupt
91
+ end
92
+ context
93
+ end
94
+
95
+ def source_reload
96
+ Object.send(:remove_const, "SCRIPT_LINES__") if Object.const_defined?("SCRIPT_LINES__")
97
+ Object.const_set("SCRIPT_LINES__", {})
98
+ LineCache::clear_file_cache
99
+ end
100
+
101
+ # Get line +line_number+ from file named +filename+. Return "\n"
102
+ # there was a problem. Leaking blanks are stripped off.
103
+ def line_at(filename, line_number) # :nodoc:
104
+ @reload_on_change=nil unless defined?(@reload_on_change)
105
+ line = LineCache::getline(filename, line_number, @reload_on_change)
106
+ return "\n" unless line
107
+ return "#{line.gsub(/^\s+/, '').chomp}\n"
108
+ end
109
+
110
+ #
111
+ # Activates the post-mortem mode. There are two ways of using it:
112
+ #
113
+ # == Global post-mortem mode
114
+ # By calling Debugger.post_mortem method without a block, you install
115
+ # at_exit hook that intercepts any unhandled by your script exceptions
116
+ # and enables post-mortem mode.
117
+ #
118
+ # == Local post-mortem mode
119
+ #
120
+ # If you know that a particular block of code raises an exception you can
121
+ # enable post-mortem mode by wrapping this block with Debugger.post_mortem, e.g.
122
+ #
123
+ # def offender
124
+ # raise 'error'
125
+ # end
126
+ # Debugger.post_mortem do
127
+ # ...
128
+ # offender
129
+ # ...
130
+ # end
131
+ def post_mortem
132
+ if block_given?
133
+ old_post_mortem = self.post_mortem?
134
+ begin
135
+ self.post_mortem = true
136
+ yield
137
+ rescue Exception => exp
138
+ handle_post_mortem(exp)
139
+ raise
140
+ ensure
141
+ self.post_mortem = old_post_mortem
142
+ end
143
+ else
144
+ return if post_mortem?
145
+ self.post_mortem = true
146
+ debug_at_exit do
147
+ handle_post_mortem($!) if $! && post_mortem?
148
+ end
149
+ end
150
+ end
151
+
152
+ def handle_post_mortem(exp)
153
+ return if !exp || !exp.__debug_context ||
154
+ exp.__debug_context.stack_size == 0
155
+ Debugger.suspend
156
+ orig_tracing = Debugger.tracing, Debugger.current_context.tracing
157
+ Debugger.tracing = Debugger.current_context.tracing = false
158
+ Debugger.last_exception = exp
159
+ handler.at_line(exp.__debug_context, exp.__debug_file, exp.__debug_line)
160
+ ensure
161
+ Debugger.tracing, Debugger.current_context.tracing = orig_tracing
162
+ Debugger.resume
163
+ end
164
+ # private :handle_post_mortem
165
+ end
166
+
167
+ class DebugThread # :nodoc:
168
+ end
169
+
170
+ class ThreadsTable # :nodoc:
171
+ end
172
+
173
+ # Debugger.start(options) -> bool
174
+ # Debugger.start(options) { ... } -> obj
175
+ #
176
+ # If it's called without a block it returns +true+, unless debugger
177
+ # was already started. If a block is given, it starts debugger and
178
+ # yields to block. When the block is finished executing it stops
179
+ # the debugger with Debugger.stop method.
180
+ #
181
+ # If a block is given, it starts debugger and yields to block. When
182
+ # the block is finished executing it stops the debugger with
183
+ # Debugger.stop method. Inside the block you will probably want to
184
+ # have a call to Debugger.debugger. For example:
185
+ #
186
+ # Debugger.start{debugger; foo} # Stop inside of foo
187
+ #
188
+ # Also, ruby-debug only allows
189
+ # one invocation of debugger at a time; nested Debugger.start's
190
+ # have no effect and you can't use this inside the debugger itself.
191
+ #
192
+ # <i>Note that if you want to stop debugger, you must call
193
+ # Debugger.stop as many time as you called Debugger.start
194
+ # method.</i>
195
+ #
196
+ # +options+ is a hash used to set various debugging options.
197
+ # Set :init true if you want to save ARGV and some variables which
198
+ # make a debugger restart possible. Only the first time :init is set true
199
+ # will values get set. Since ARGV is saved, you should make sure
200
+ # it hasn't been changed before the (first) call.
201
+ # Set :post_mortem true if you want to enter post-mortem debugging
202
+ # on an uncaught exception. Once post-mortem debugging is set, it can't
203
+ # be unset.
204
+ def start(options={}, &block)
205
+ options = Debugger::DEFAULT_START_SETTINGS.merge(options)
206
+ if options[:init]
207
+ Debugger.const_set('ARGV', ARGV.clone) unless
208
+ defined? Debugger::ARGV
209
+ Debugger.const_set('PROG_SCRIPT', $0) unless
210
+ defined? Debugger::PROG_SCRIPT
211
+ Debugger.const_set('INITIAL_DIR', Dir.pwd) unless
212
+ defined? Debugger::INITIAL_DIR
213
+ end
214
+ Debugger.tracing = options[:tracing] unless options[:tracing].nil?
215
+ retval = Debugger.started? ? block && block.call(self) : Debugger.start_(&block)
216
+ if options[:post_mortem]
217
+ post_mortem
218
+ end
219
+ return retval
220
+ end
221
+ module_function :start
222
+ end
223
+
224
+ module Kernel
225
+
226
+ # Enters the debugger in the current thread after _steps_ line events occur.
227
+ # Before entering the debugger startup script is read.
228
+ #
229
+ # Setting _steps_ to 0 will cause a break in the debugger subroutine
230
+ # and not wait for a line event to occur. You will have to go "up 1"
231
+ # in order to be back in your debugged program rather than the
232
+ # debugger. Settings _steps_ to 0 could be useful you want to stop
233
+ # right after the last statement in some scope, because the next
234
+ # step will take you out of some scope.
235
+
236
+ # If a block is given (and the debugger hasn't been started, we run the
237
+ # block under the debugger. Alas, when a block is given, we can't support
238
+ # running the startup script or support the steps option. FIXME.
239
+ def debugger(steps = 1, &block)
240
+ if block
241
+ Debugger.start({}, &block)
242
+ else
243
+ Debugger.start unless Debugger.started?
244
+ Debugger.run_init_script(StringIO.new)
245
+ if 0 == steps
246
+ Debugger.current_context.stop_frame = 0
247
+ else
248
+ Debugger.current_context.stop_next = steps
249
+ end
250
+ end
251
+ end
252
+ alias breakpoint debugger unless respond_to?(:breakpoint)
253
+
254
+ #
255
+ # Returns a binding of n-th call frame
256
+ #
257
+ def binding_n(n = 0)
258
+ Debugger.skip do
259
+ if RUBY_VERSION < "1.9"
260
+ Debugger.current_context.frame_binding(n+2)
261
+ else
262
+ Debugger.current_context.frame_binding(n+1)
263
+ end
264
+ end
265
+ end
266
+ end
267
+
268
+ class Exception # :nodoc:
269
+ attr_reader :__debug_file, :__debug_line, :__debug_binding, :__debug_context
270
+ end
271
+
272
+ class Module
273
+ #
274
+ # Wraps the +meth+ method with Debugger.start {...} block.
275
+ #
276
+ def debug_method(meth)
277
+ old_meth = "__debugee_#{meth}"
278
+ old_meth = "#{$1}_set" if old_meth =~ /^(.+)=$/
279
+ alias_method old_meth.to_sym, meth
280
+ class_eval <<-EOD
281
+ def #{meth}(*args, &block)
282
+ Debugger.start do
283
+ debugger 2
284
+ #{old_meth}(*args, &block)
285
+ end
286
+ end
287
+ EOD
288
+ end
289
+
290
+ #
291
+ # Wraps the +meth+ method with Debugger.post_mortem {...} block.
292
+ #
293
+ def post_mortem_method(meth)
294
+ old_meth = "__postmortem_#{meth}"
295
+ old_meth = "#{$1}_set" if old_meth =~ /^(.+)=$/
296
+ alias_method old_meth.to_sym, meth
297
+ class_eval <<-EOD
298
+ def #{meth}(*args, &block)
299
+ Debugger.start do |dbg|
300
+ dbg.post_mortem do
301
+ #{old_meth}(*args, &block)
302
+ end
303
+ end
304
+ end
305
+ EOD
306
+ end
307
+ end