ruby-debug-base19x 0.11.28 → 0.11.29

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,304 +1,304 @@
1
- require 'ruby_debug.so'
2
- require 'rubygems'
3
- require 'linecache19'
4
-
5
- module Debugger
6
-
7
- # Default options to Debugger.start
8
- DEFAULT_START_SETTINGS = {
9
- :init => true, # Set $0 and save ARGV?
10
- :post_mortem => false, # post-mortem debugging on uncaught exception?
11
- :tracing => nil # Debugger.tracing value. true/false resets,
12
- # nil keeps the prior value
13
- } unless defined?(DEFAULT_START_SETTINGS)
14
-
15
- class Context
16
- def interrupt
17
- self.stop_next = 1
18
- end
19
-
20
- alias __c_frame_binding frame_binding
21
- def frame_binding(frame)
22
- __c_frame_binding(frame) || hbinding(frame)
23
- end
24
-
25
- private
26
-
27
- def hbinding(frame)
28
- hash = frame_locals(frame)
29
- code = hash.keys.map{|k| "#{k} = hash['#{k}']" unless k=='self' }.compact.join(';') + ';binding'
30
- if obj = frame_self(frame)
31
- obj.instance_eval code
32
- else
33
- eval code, TOPLEVEL_BINDING
34
- end
35
- end
36
-
37
- def handler
38
- Debugger.handler or raise 'No interface loaded'
39
- end
40
-
41
- def at_breakpoint(breakpoint)
42
- handler.at_breakpoint(self, breakpoint)
43
- end
44
-
45
- def at_catchpoint(excpt)
46
- handler.at_catchpoint(self, excpt)
47
- end
48
-
49
- def at_tracing(file, line)
50
- @tracing_started = true if File.identical?(file, File.join(Debugger::INITIAL_DIR, Debugger::PROG_SCRIPT))
51
- handler.at_tracing(self, file, line) if @tracing_started
52
- end
53
-
54
- def at_line(file, line)
55
- handler.at_line(self, file, line)
56
- end
57
-
58
- def at_return(file, line)
59
- handler.at_return(self, file, line)
60
- end
61
- end
62
-
63
- @reload_source_on_change = false
64
- @tracing_started = false
65
-
66
- class << self
67
- # interface modules provide +handler+ object
68
- attr_accessor :handler
69
-
70
- # if <tt>true</tt>, checks the modification time of source files and reloads if it was modified
71
- attr_accessor :reload_source_on_change
72
-
73
- attr_accessor :last_exception
74
- Debugger.last_exception = nil
75
-
76
- #
77
- # Interrupts the current thread
78
- #
79
- def interrupt
80
- current_context.interrupt
81
- end
82
-
83
- #
84
- # Interrupts the last debugged thread
85
- #
86
- def interrupt_last
87
- if context = last_context
88
- return nil unless context.thread.alive?
89
- context.interrupt
90
- end
91
- context
92
- end
93
-
94
- def source_reload
95
- LineCache::clear_file_cache
96
- end
97
-
98
- # Get line +line_number+ from file named +filename+. Return "\n"
99
- # there was a problem. Leaking blanks are stripped off.
100
- def line_at(filename, line_number) # :nodoc:
101
- @reload_on_change=nil unless defined?(@reload_on_change)
102
- line = LineCache::getline(filename, line_number, @reload_on_change)
103
- return "\n" unless line
104
- return "#{line.gsub(/^\s+/, '').chomp}\n"
105
- end
106
-
107
- #
108
- # Activates the post-mortem mode. There are two ways of using it:
109
- #
110
- # == Global post-mortem mode
111
- # By calling Debugger.post_mortem method without a block, you install
112
- # at_exit hook that intercepts any unhandled by your script exceptions
113
- # and enables post-mortem mode.
114
- #
115
- # == Local post-mortem mode
116
- #
117
- # If you know that a particular block of code raises an exception you can
118
- # enable post-mortem mode by wrapping this block with Debugger.post_mortem, e.g.
119
- #
120
- # def offender
121
- # raise 'error'
122
- # end
123
- # Debugger.post_mortem do
124
- # ...
125
- # offender
126
- # ...
127
- # end
128
- def post_mortem
129
- if block_given?
130
- old_post_mortem = self.post_mortem?
131
- begin
132
- self.post_mortem = true
133
- yield
134
- rescue Exception => exp
135
- handle_post_mortem(exp)
136
- raise
137
- ensure
138
- self.post_mortem = old_post_mortem
139
- end
140
- else
141
- return if post_mortem?
142
- self.post_mortem = true
143
- debug_at_exit do
144
- handle_post_mortem($!) if $! && post_mortem?
145
- end
146
- end
147
- end
148
-
149
- def handle_post_mortem(exp)
150
- return if !exp || !exp.__debug_context ||
151
- exp.__debug_context.stack_size == 0
152
- Debugger.suspend
153
- orig_tracing = Debugger.tracing, Debugger.current_context.tracing
154
- Debugger.tracing = Debugger.current_context.tracing = false
155
- Debugger.last_exception = exp
156
- handler.at_line(exp.__debug_context, exp.__debug_file, exp.__debug_line)
157
- ensure
158
- Debugger.tracing, Debugger.current_context.tracing = orig_tracing
159
- Debugger.resume
160
- end
161
- # private :handle_post_mortem
162
- end
163
-
164
- class DebugThread # :nodoc:
165
- end
166
-
167
- class ThreadsTable # :nodoc:
168
- end
169
-
170
- # Debugger.start(options) -> bool
171
- # Debugger.start(options) { ... } -> obj
172
- #
173
- # If it's called without a block it returns +true+, unless debugger
174
- # was already started. If a block is given, it starts debugger and
175
- # yields to block. When the block is finished executing it stops
176
- # the debugger with Debugger.stop method.
177
- #
178
- # If a block is given, it starts debugger and yields to block. When
179
- # the block is finished executing it stops the debugger with
180
- # Debugger.stop method. Inside the block you will probably want to
181
- # have a call to Debugger.debugger. For example:
182
- #
183
- # Debugger.start{debugger; foo} # Stop inside of foo
184
- #
185
- # Also, ruby-debug only allows
186
- # one invocation of debugger at a time; nested Debugger.start's
187
- # have no effect and you can't use this inside the debugger itself.
188
- #
189
- # <i>Note that if you want to stop debugger, you must call
190
- # Debugger.stop as many time as you called Debugger.start
191
- # method.</i>
192
- #
193
- # +options+ is a hash used to set various debugging options.
194
- # Set :init true if you want to save ARGV and some variables which
195
- # make a debugger restart possible. Only the first time :init is set true
196
- # will values get set. Since ARGV is saved, you should make sure
197
- # it hasn't been changed before the (first) call.
198
- # Set :post_mortem true if you want to enter post-mortem debugging
199
- # on an uncaught exception. Once post-mortem debugging is set, it can't
200
- # be unset.
201
- def start(options={}, &block)
202
- options = Debugger::DEFAULT_START_SETTINGS.merge(options)
203
- if options[:init]
204
- Debugger.const_set('ARGV', ARGV.clone) unless
205
- defined? Debugger::ARGV
206
- Debugger.const_set('PROG_SCRIPT', $0) unless
207
- defined? Debugger::PROG_SCRIPT
208
- Debugger.const_set('INITIAL_DIR', Dir.pwd) unless
209
- defined? Debugger::INITIAL_DIR
210
- end
211
- Debugger.tracing = options[:tracing] unless options[:tracing].nil?
212
- retval = Debugger.started? ? block && block.call(self) : Debugger.start_(&block)
213
- if options[:post_mortem]
214
- post_mortem
215
- end
216
- return retval
217
- end
218
- module_function :start
219
- end
220
-
221
- module Kernel
222
-
223
- # Enters the debugger in the current thread after _steps_ line events occur.
224
- # Before entering the debugger startup script is read.
225
- #
226
- # Setting _steps_ to 0 will cause a break in the debugger subroutine
227
- # and not wait for a line event to occur. You will have to go "up 1"
228
- # in order to be back in your debugged program rather than the
229
- # debugger. Settings _steps_ to 0 could be useful you want to stop
230
- # right after the last statement in some scope, because the next
231
- # step will take you out of some scope.
232
-
233
- # If a block is given (and the debugger hasn't been started, we run the
234
- # block under the debugger. Alas, when a block is given, we can't support
235
- # running the startup script or support the steps option. FIXME.
236
- def debugger(steps = 1, &block)
237
- if block
238
- Debugger.start({}, &block)
239
- else
240
- Debugger.start unless Debugger.started?
241
- Debugger.run_init_script(StringIO.new)
242
- if 0 == steps
243
- Debugger.current_context.stop_frame = 0
244
- else
245
- Debugger.current_context.stop_next = steps
246
- end
247
- end
248
- end
249
- alias breakpoint debugger unless respond_to?(:breakpoint)
250
-
251
- #
252
- # Returns a binding of n-th call frame
253
- #
254
- def binding_n(n = 0)
255
- Debugger.skip do
256
- if RUBY_VERSION < "1.9"
257
- Debugger.current_context.frame_binding(n+2)
258
- else
259
- Debugger.current_context.frame_binding(n+1)
260
- end
261
- end
262
- end
263
- end
264
-
265
- class Exception # :nodoc:
266
- attr_reader :__debug_file, :__debug_line, :__debug_binding, :__debug_context
267
- end
268
-
269
- class Module
270
- #
271
- # Wraps the +meth+ method with Debugger.start {...} block.
272
- #
273
- def debug_method(meth)
274
- old_meth = "__debugee_#{meth}"
275
- old_meth = "#{$1}_set" if old_meth =~ /^(.+)=$/
276
- alias_method old_meth.to_sym, meth
277
- class_eval <<-EOD
278
- def #{meth}(*args, &block)
279
- Debugger.start do
280
- debugger 2
281
- #{old_meth}(*args, &block)
282
- end
283
- end
284
- EOD
285
- end
286
-
287
- #
288
- # Wraps the +meth+ method with Debugger.post_mortem {...} block.
289
- #
290
- def post_mortem_method(meth)
291
- old_meth = "__postmortem_#{meth}"
292
- old_meth = "#{$1}_set" if old_meth =~ /^(.+)=$/
293
- alias_method old_meth.to_sym, meth
294
- class_eval <<-EOD
295
- def #{meth}(*args, &block)
296
- Debugger.start do |dbg|
297
- dbg.post_mortem do
298
- #{old_meth}(*args, &block)
299
- end
300
- end
301
- end
302
- EOD
303
- end
304
- end
1
+ require 'ruby_debug'
2
+ require 'rubygems'
3
+ require 'linecache19'
4
+
5
+ module Debugger
6
+
7
+ # Default options to Debugger.start
8
+ DEFAULT_START_SETTINGS = {
9
+ :init => true, # Set $0 and save ARGV?
10
+ :post_mortem => false, # post-mortem debugging on uncaught exception?
11
+ :tracing => nil # Debugger.tracing value. true/false resets,
12
+ # nil keeps the prior value
13
+ } unless defined?(DEFAULT_START_SETTINGS)
14
+
15
+ class Context
16
+ def interrupt
17
+ self.stop_next = 1
18
+ end
19
+
20
+ alias __c_frame_binding frame_binding
21
+ def frame_binding(frame)
22
+ __c_frame_binding(frame) || hbinding(frame)
23
+ end
24
+
25
+ private
26
+
27
+ def hbinding(frame)
28
+ hash = frame_locals(frame)
29
+ code = hash.keys.map{|k| "#{k} = hash['#{k}']" unless k=='self' }.compact.join(';') + ';binding'
30
+ if obj = frame_self(frame)
31
+ obj.instance_eval code
32
+ else
33
+ eval code, TOPLEVEL_BINDING
34
+ end
35
+ end
36
+
37
+ def handler
38
+ Debugger.handler or raise 'No interface loaded'
39
+ end
40
+
41
+ def at_breakpoint(breakpoint)
42
+ handler.at_breakpoint(self, breakpoint)
43
+ end
44
+
45
+ def at_catchpoint(excpt)
46
+ handler.at_catchpoint(self, excpt)
47
+ end
48
+
49
+ def at_tracing(file, line)
50
+ @tracing_started = true if File.identical?(file, File.join(Debugger::INITIAL_DIR, Debugger::PROG_SCRIPT))
51
+ handler.at_tracing(self, file, line) if @tracing_started
52
+ end
53
+
54
+ def at_line(file, line)
55
+ handler.at_line(self, file, line)
56
+ end
57
+
58
+ def at_return(file, line)
59
+ handler.at_return(self, file, line)
60
+ end
61
+ end
62
+
63
+ @reload_source_on_change = false
64
+ @tracing_started = false
65
+
66
+ class << self
67
+ # interface modules provide +handler+ object
68
+ attr_accessor :handler
69
+
70
+ # if <tt>true</tt>, checks the modification time of source files and reloads if it was modified
71
+ attr_accessor :reload_source_on_change
72
+
73
+ attr_accessor :last_exception
74
+ Debugger.last_exception = nil
75
+
76
+ #
77
+ # Interrupts the current thread
78
+ #
79
+ def interrupt
80
+ current_context.interrupt
81
+ end
82
+
83
+ #
84
+ # Interrupts the last debugged thread
85
+ #
86
+ def interrupt_last
87
+ if context = last_context
88
+ return nil unless context.thread.alive?
89
+ context.interrupt
90
+ end
91
+ context
92
+ end
93
+
94
+ def source_reload
95
+ LineCache::clear_file_cache
96
+ end
97
+
98
+ # Get line +line_number+ from file named +filename+. Return "\n"
99
+ # there was a problem. Leaking blanks are stripped off.
100
+ def line_at(filename, line_number) # :nodoc:
101
+ @reload_on_change=nil unless defined?(@reload_on_change)
102
+ line = LineCache::getline(filename, line_number, @reload_on_change)
103
+ return "\n" unless line
104
+ return "#{line.gsub(/^\s+/, '').chomp}\n"
105
+ end
106
+
107
+ #
108
+ # Activates the post-mortem mode. There are two ways of using it:
109
+ #
110
+ # == Global post-mortem mode
111
+ # By calling Debugger.post_mortem method without a block, you install
112
+ # at_exit hook that intercepts any unhandled by your script exceptions
113
+ # and enables post-mortem mode.
114
+ #
115
+ # == Local post-mortem mode
116
+ #
117
+ # If you know that a particular block of code raises an exception you can
118
+ # enable post-mortem mode by wrapping this block with Debugger.post_mortem, e.g.
119
+ #
120
+ # def offender
121
+ # raise 'error'
122
+ # end
123
+ # Debugger.post_mortem do
124
+ # ...
125
+ # offender
126
+ # ...
127
+ # end
128
+ def post_mortem
129
+ if block_given?
130
+ old_post_mortem = self.post_mortem?
131
+ begin
132
+ self.post_mortem = true
133
+ yield
134
+ rescue Exception => exp
135
+ handle_post_mortem(exp)
136
+ raise
137
+ ensure
138
+ self.post_mortem = old_post_mortem
139
+ end
140
+ else
141
+ return if post_mortem?
142
+ self.post_mortem = true
143
+ debug_at_exit do
144
+ handle_post_mortem($!) if $! && post_mortem?
145
+ end
146
+ end
147
+ end
148
+
149
+ def handle_post_mortem(exp)
150
+ return if !exp || !exp.__debug_context ||
151
+ exp.__debug_context.stack_size == 0
152
+ Debugger.suspend
153
+ orig_tracing = Debugger.tracing, Debugger.current_context.tracing
154
+ Debugger.tracing = Debugger.current_context.tracing = false
155
+ Debugger.last_exception = exp
156
+ handler.at_line(exp.__debug_context, exp.__debug_file, exp.__debug_line)
157
+ ensure
158
+ Debugger.tracing, Debugger.current_context.tracing = orig_tracing
159
+ Debugger.resume
160
+ end
161
+ # private :handle_post_mortem
162
+ end
163
+
164
+ class DebugThread # :nodoc:
165
+ end
166
+
167
+ class ThreadsTable # :nodoc:
168
+ end
169
+
170
+ # Debugger.start(options) -> bool
171
+ # Debugger.start(options) { ... } -> obj
172
+ #
173
+ # If it's called without a block it returns +true+, unless debugger
174
+ # was already started. If a block is given, it starts debugger and
175
+ # yields to block. When the block is finished executing it stops
176
+ # the debugger with Debugger.stop method.
177
+ #
178
+ # If a block is given, it starts debugger and yields to block. When
179
+ # the block is finished executing it stops the debugger with
180
+ # Debugger.stop method. Inside the block you will probably want to
181
+ # have a call to Debugger.debugger. For example:
182
+ #
183
+ # Debugger.start{debugger; foo} # Stop inside of foo
184
+ #
185
+ # Also, ruby-debug only allows
186
+ # one invocation of debugger at a time; nested Debugger.start's
187
+ # have no effect and you can't use this inside the debugger itself.
188
+ #
189
+ # <i>Note that if you want to stop debugger, you must call
190
+ # Debugger.stop as many time as you called Debugger.start
191
+ # method.</i>
192
+ #
193
+ # +options+ is a hash used to set various debugging options.
194
+ # Set :init true if you want to save ARGV and some variables which
195
+ # make a debugger restart possible. Only the first time :init is set true
196
+ # will values get set. Since ARGV is saved, you should make sure
197
+ # it hasn't been changed before the (first) call.
198
+ # Set :post_mortem true if you want to enter post-mortem debugging
199
+ # on an uncaught exception. Once post-mortem debugging is set, it can't
200
+ # be unset.
201
+ def start(options={}, &block)
202
+ options = Debugger::DEFAULT_START_SETTINGS.merge(options)
203
+ if options[:init]
204
+ Debugger.const_set('ARGV', ARGV.clone) unless
205
+ defined? Debugger::ARGV
206
+ Debugger.const_set('PROG_SCRIPT', $0) unless
207
+ defined? Debugger::PROG_SCRIPT
208
+ Debugger.const_set('INITIAL_DIR', Dir.pwd) unless
209
+ defined? Debugger::INITIAL_DIR
210
+ end
211
+ Debugger.tracing = options[:tracing] unless options[:tracing].nil?
212
+ retval = Debugger.started? ? block && block.call(self) : Debugger.start_(&block)
213
+ if options[:post_mortem]
214
+ post_mortem
215
+ end
216
+ return retval
217
+ end
218
+ module_function :start
219
+ end
220
+
221
+ module Kernel
222
+
223
+ # Enters the debugger in the current thread after _steps_ line events occur.
224
+ # Before entering the debugger startup script is read.
225
+ #
226
+ # Setting _steps_ to 0 will cause a break in the debugger subroutine
227
+ # and not wait for a line event to occur. You will have to go "up 1"
228
+ # in order to be back in your debugged program rather than the
229
+ # debugger. Settings _steps_ to 0 could be useful you want to stop
230
+ # right after the last statement in some scope, because the next
231
+ # step will take you out of some scope.
232
+
233
+ # If a block is given (and the debugger hasn't been started, we run the
234
+ # block under the debugger. Alas, when a block is given, we can't support
235
+ # running the startup script or support the steps option. FIXME.
236
+ def debugger(steps = 1, &block)
237
+ if block
238
+ Debugger.start({}, &block)
239
+ else
240
+ Debugger.start unless Debugger.started?
241
+ Debugger.run_init_script(StringIO.new)
242
+ if 0 == steps
243
+ Debugger.current_context.stop_frame = 0
244
+ else
245
+ Debugger.current_context.stop_next = steps
246
+ end
247
+ end
248
+ end
249
+ alias breakpoint debugger unless respond_to?(:breakpoint)
250
+
251
+ #
252
+ # Returns a binding of n-th call frame
253
+ #
254
+ def binding_n(n = 0)
255
+ Debugger.skip do
256
+ if RUBY_VERSION < "1.9"
257
+ Debugger.current_context.frame_binding(n+2)
258
+ else
259
+ Debugger.current_context.frame_binding(n+1)
260
+ end
261
+ end
262
+ end
263
+ end
264
+
265
+ class Exception # :nodoc:
266
+ attr_reader :__debug_file, :__debug_line, :__debug_binding, :__debug_context
267
+ end
268
+
269
+ class Module
270
+ #
271
+ # Wraps the +meth+ method with Debugger.start {...} block.
272
+ #
273
+ def debug_method(meth)
274
+ old_meth = "__debugee_#{meth}"
275
+ old_meth = "#{$1}_set" if old_meth =~ /^(.+)=$/
276
+ alias_method old_meth.to_sym, meth
277
+ class_eval <<-EOD
278
+ def #{meth}(*args, &block)
279
+ Debugger.start do
280
+ debugger 2
281
+ #{old_meth}(*args, &block)
282
+ end
283
+ end
284
+ EOD
285
+ end
286
+
287
+ #
288
+ # Wraps the +meth+ method with Debugger.post_mortem {...} block.
289
+ #
290
+ def post_mortem_method(meth)
291
+ old_meth = "__postmortem_#{meth}"
292
+ old_meth = "#{$1}_set" if old_meth =~ /^(.+)=$/
293
+ alias_method old_meth.to_sym, meth
294
+ class_eval <<-EOD
295
+ def #{meth}(*args, &block)
296
+ Debugger.start do |dbg|
297
+ dbg.post_mortem do
298
+ #{old_meth}(*args, &block)
299
+ end
300
+ end
301
+ end
302
+ EOD
303
+ end
304
+ end