ruby-debug-base19 0.11.15

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.
@@ -0,0 +1,302 @@
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
+ handler.at_tracing(self, file, line)
51
+ end
52
+
53
+ def at_line(file, line)
54
+ handler.at_line(self, file, line)
55
+ end
56
+
57
+ def at_return(file, line)
58
+ handler.at_return(self, file, line)
59
+ end
60
+ end
61
+
62
+ @reload_source_on_change = false
63
+
64
+ class << self
65
+ # interface modules provide +handler+ object
66
+ attr_accessor :handler
67
+
68
+ # if <tt>true</tt>, checks the modification time of source files and reloads if it was modified
69
+ attr_accessor :reload_source_on_change
70
+
71
+ attr_accessor :last_exception
72
+ Debugger.last_exception = nil
73
+
74
+ #
75
+ # Interrupts the current thread
76
+ #
77
+ def interrupt
78
+ current_context.interrupt
79
+ end
80
+
81
+ #
82
+ # Interrupts the last debugged thread
83
+ #
84
+ def interrupt_last
85
+ if context = last_context
86
+ return nil unless context.thread.alive?
87
+ context.interrupt
88
+ end
89
+ context
90
+ end
91
+
92
+ def source_reload
93
+ LineCache::clear_file_cache(true)
94
+ end
95
+
96
+ # Get line +line_number+ from file named +filename+. Return "\n"
97
+ # there was a problem. Leaking blanks are stripped off.
98
+ def line_at(filename, line_number) # :nodoc:
99
+ @reload_on_change=nil unless defined?(@reload_on_change)
100
+ line = LineCache::getline(filename, line_number, @reload_on_change)
101
+ return "\n" unless line
102
+ return "#{line.gsub(/^\s+/, '').chomp}\n"
103
+ end
104
+
105
+ #
106
+ # Activates the post-mortem mode. There are two ways of using it:
107
+ #
108
+ # == Global post-mortem mode
109
+ # By calling Debugger.post_mortem method without a block, you install
110
+ # at_exit hook that intercepts any unhandled by your script exceptions
111
+ # and enables post-mortem mode.
112
+ #
113
+ # == Local post-mortem mode
114
+ #
115
+ # If you know that a particular block of code raises an exception you can
116
+ # enable post-mortem mode by wrapping this block with Debugger.post_mortem, e.g.
117
+ #
118
+ # def offender
119
+ # raise 'error'
120
+ # end
121
+ # Debugger.post_mortem do
122
+ # ...
123
+ # offender
124
+ # ...
125
+ # end
126
+ def post_mortem
127
+ if block_given?
128
+ old_post_mortem = self.post_mortem?
129
+ begin
130
+ self.post_mortem = true
131
+ yield
132
+ rescue Exception => exp
133
+ handle_post_mortem(exp)
134
+ raise
135
+ ensure
136
+ self.post_mortem = old_post_mortem
137
+ end
138
+ else
139
+ return if post_mortem?
140
+ self.post_mortem = true
141
+ debug_at_exit do
142
+ handle_post_mortem($!) if $! && post_mortem?
143
+ end
144
+ end
145
+ end
146
+
147
+ def handle_post_mortem(exp)
148
+ return if !exp || !exp.__debug_context ||
149
+ exp.__debug_context.stack_size == 0
150
+ Debugger.suspend
151
+ orig_tracing = Debugger.tracing, Debugger.current_context.tracing
152
+ Debugger.tracing = Debugger.current_context.tracing = false
153
+ Debugger.last_exception = exp
154
+ handler.at_line(exp.__debug_context, exp.__debug_file, exp.__debug_line)
155
+ ensure
156
+ Debugger.tracing, Debugger.current_context.tracing = orig_tracing
157
+ Debugger.resume
158
+ end
159
+ # private :handle_post_mortem
160
+ end
161
+
162
+ class DebugThread # :nodoc:
163
+ end
164
+
165
+ class ThreadsTable # :nodoc:
166
+ end
167
+
168
+ # Debugger.start(options) -> bool
169
+ # Debugger.start(options) { ... } -> obj
170
+ #
171
+ # If it's called without a block it returns +true+, unless debugger
172
+ # was already started. If a block is given, it starts debugger and
173
+ # yields to block. When the block is finished executing it stops
174
+ # the debugger with Debugger.stop method.
175
+ #
176
+ # If a block is given, it starts debugger and yields to block. When
177
+ # the block is finished executing it stops the debugger with
178
+ # Debugger.stop method. Inside the block you will probably want to
179
+ # have a call to Debugger.debugger. For example:
180
+ #
181
+ # Debugger.start{debugger; foo} # Stop inside of foo
182
+ #
183
+ # Also, ruby-debug only allows
184
+ # one invocation of debugger at a time; nested Debugger.start's
185
+ # have no effect and you can't use this inside the debugger itself.
186
+ #
187
+ # <i>Note that if you want to stop debugger, you must call
188
+ # Debugger.stop as many time as you called Debugger.start
189
+ # method.</i>
190
+ #
191
+ # +options+ is a hash used to set various debugging options.
192
+ # Set :init true if you want to save ARGV and some variables which
193
+ # make a debugger restart possible. Only the first time :init is set true
194
+ # will values get set. Since ARGV is saved, you should make sure
195
+ # it hasn't been changed before the (first) call.
196
+ # Set :post_mortem true if you want to enter post-mortem debugging
197
+ # on an uncaught exception. Once post-mortem debugging is set, it can't
198
+ # be unset.
199
+ def start(options={}, &block)
200
+ options = Debugger::DEFAULT_START_SETTINGS.merge(options)
201
+ if options[:init]
202
+ Debugger.const_set('ARGV', ARGV.clone) unless
203
+ defined? Debugger::ARGV
204
+ Debugger.const_set('PROG_SCRIPT', $0) unless
205
+ defined? Debugger::PROG_SCRIPT
206
+ Debugger.const_set('INITIAL_DIR', Dir.pwd) unless
207
+ defined? Debugger::INITIAL_DIR
208
+ end
209
+ Debugger.tracing = options[:tracing] unless options[:tracing].nil?
210
+ retval = Debugger.started? ? block && block.call(self) : Debugger.start_(&block)
211
+ if options[:post_mortem]
212
+ post_mortem
213
+ end
214
+ return retval
215
+ end
216
+ module_function :start
217
+ end
218
+
219
+ module Kernel
220
+
221
+ # Enters the debugger in the current thread after _steps_ line events occur.
222
+ # Before entering the debugger startup script is read.
223
+ #
224
+ # Setting _steps_ to 0 will cause a break in the debugger subroutine
225
+ # and not wait for a line event to occur. You will have to go "up 1"
226
+ # in order to be back in your debugged program rather than the
227
+ # debugger. Settings _steps_ to 0 could be useful you want to stop
228
+ # right after the last statement in some scope, because the next
229
+ # step will take you out of some scope.
230
+
231
+ # If a block is given (and the debugger hasn't been started, we run the
232
+ # block under the debugger. Alas, when a block is given, we can't support
233
+ # running the startup script or support the steps option. FIXME.
234
+ def debugger(steps = 1, &block)
235
+ if block
236
+ Debugger.start({}, &block)
237
+ else
238
+ Debugger.start unless Debugger.started?
239
+ Debugger.run_init_script(StringIO.new)
240
+ if 0 == steps
241
+ Debugger.current_context.stop_frame = 0
242
+ else
243
+ Debugger.current_context.stop_next = steps
244
+ end
245
+ end
246
+ end
247
+ alias breakpoint debugger unless respond_to?(:breakpoint)
248
+
249
+ #
250
+ # Returns a binding of n-th call frame
251
+ #
252
+ def binding_n(n = 0)
253
+ Debugger.skip do
254
+ if RUBY_VERSION < "1.9"
255
+ Debugger.current_context.frame_binding(n+2)
256
+ else
257
+ Debugger.current_context.frame_binding(n+1)
258
+ end
259
+ end
260
+ end
261
+ end
262
+
263
+ class Exception # :nodoc:
264
+ attr_reader :__debug_file, :__debug_line, :__debug_binding, :__debug_context
265
+ end
266
+
267
+ class Module
268
+ #
269
+ # Wraps the +meth+ method with Debugger.start {...} block.
270
+ #
271
+ def debug_method(meth)
272
+ old_meth = "__debugee_#{meth}"
273
+ old_meth = "#{$1}_set" if old_meth =~ /^(.+)=$/
274
+ alias_method old_meth.to_sym, meth
275
+ class_eval <<-EOD
276
+ def #{meth}(*args, &block)
277
+ Debugger.start do
278
+ debugger 2
279
+ #{old_meth}(*args, &block)
280
+ end
281
+ end
282
+ EOD
283
+ end
284
+
285
+ #
286
+ # Wraps the +meth+ method with Debugger.post_mortem {...} block.
287
+ #
288
+ def post_mortem_method(meth)
289
+ old_meth = "__postmortem_#{meth}"
290
+ old_meth = "#{$1}_set" if old_meth =~ /^(.+)=$/
291
+ alias_method old_meth.to_sym, meth
292
+ class_eval <<-EOD
293
+ def #{meth}(*args, &block)
294
+ Debugger.start do |dbg|
295
+ dbg.post_mortem do
296
+ #{old_meth}(*args, &block)
297
+ end
298
+ end
299
+ end
300
+ EOD
301
+ end
302
+ end
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env ruby
2
+ require 'test/unit'
3
+
4
+ # Some tests of Debugger module in C extension ruby_debug
5
+ class TestRubyDebug < Test::Unit::TestCase
6
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'ext')
7
+ require 'ruby_debug'
8
+ $:.shift
9
+
10
+ # test current_context
11
+ def test_current_context
12
+ assert_equal(false, Debugger.started?,
13
+ 'debugger should not initially be started.')
14
+ Debugger.start_
15
+ assert(Debugger.started?,
16
+ 'debugger should now be started.')
17
+ assert_equal(__LINE__, Debugger.current_context.frame_line)
18
+ assert_equal(nil, Debugger.current_context.frame_args_info,
19
+ 'no frame args info.')
20
+ assert_equal(Debugger.current_context.frame_file,
21
+ Debugger.current_context.frame_file(0))
22
+ assert_equal(File.basename(__FILE__),
23
+ File.basename(Debugger.current_context.frame_file))
24
+ assert_raises(ArgumentError) {Debugger.current_context.frame_file(1, 2)}
25
+ assert_raises(ArgumentError) {Debugger.current_context.frame_file(10)}
26
+ assert_equal(1, Debugger.current_context.stack_size)
27
+ assert_equal(TestRubyDebug, Debugger.current_context.frame_class)
28
+ assert_equal(false, Debugger.current_context.dead?, 'Not dead yet!')
29
+ Debugger.stop
30
+ assert_equal(false, Debugger.started?,
31
+ 'Debugger should no longer be started.')
32
+ end
33
+
34
+ # Test initial variables and setting/getting state.
35
+ def test_debugger_base
36
+ assert_equal(false, Debugger.started?,
37
+ 'Debugger should not initially be started.')
38
+ Debugger.start_
39
+ assert(Debugger.started?,
40
+ 'Debugger should now be started.')
41
+ assert_equal(false, Debugger.debug,
42
+ 'Debug variable should not be set.')
43
+ assert_equal(false, Debugger.post_mortem?,
44
+ 'Post mortem debugging should not be set.')
45
+ a = Debugger.contexts
46
+ assert_equal(1, a.size,
47
+ 'There should only be one context.')
48
+ assert_equal(Array, a.class,
49
+ 'Context should be an array.')
50
+ Debugger.stop
51
+ assert_equal(false, Debugger.started?,
52
+ 'debugger should no longer be started.')
53
+ end
54
+
55
+ # Test breakpoint handling
56
+ def test_breakpoints
57
+ Debugger.start_
58
+ assert_equal(0, Debugger.breakpoints.size,
59
+ 'There should not be any breakpoints set.')
60
+ brk = Debugger.add_breakpoint(__FILE__, 1)
61
+ assert_equal(Debugger::Breakpoint, brk.class,
62
+ 'Breakpoint should have been set and returned.')
63
+ assert_equal(1, Debugger.breakpoints.size,
64
+ 'There should now be one breakpoint set.')
65
+ Debugger.remove_breakpoint(0)
66
+ assert_equal(1, Debugger.breakpoints.size,
67
+ 'There should still be one breakpoint set.')
68
+ Debugger.remove_breakpoint(1)
69
+ assert_equal(0, Debugger.breakpoints.size,
70
+ 'There should no longer be any breakpoints set.')
71
+ Debugger.stop
72
+ end
73
+ end
74
+
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+
5
+ # Test binding_n command
6
+ class TestBinding < Test::Unit::TestCase
7
+
8
+ SRC_DIR = File.expand_path(File.dirname(__FILE__)) unless
9
+ defined?(SRC_DIR)
10
+ %w(ext lib).each do |dir|
11
+ $:.unshift File.join(SRC_DIR, '..', '..', dir)
12
+ end
13
+ require File.join(SRC_DIR, '..', '..', 'lib', 'ruby-debug-base')
14
+ $:.shift; $:.shift
15
+
16
+ def test_basic
17
+ def inside_fn
18
+ s = 'some other string'
19
+ b2 = Kernel::binding_n(1)
20
+ y2 = eval('s', b2)
21
+ assert_equal('this is a test', y2)
22
+ end
23
+ s = 'this is a test'
24
+ Debugger.start
25
+ b = Kernel::binding_n(0)
26
+ y = eval('s', b)
27
+ assert_equal(y, s)
28
+ inside_fn
29
+ Debugger.stop
30
+ end
31
+ end
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+ require 'test/unit'
3
+
4
+ # Test catchpoint in C ruby_debug extension.
5
+
6
+ class TestRubyDebugCatchpoint < Test::Unit::TestCase
7
+
8
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'ext')
9
+ require 'ruby_debug'
10
+ $:.shift
11
+
12
+ # test current_context
13
+ def test_catchpoints
14
+ assert_raise(RuntimeError) {Debugger.catchpoints}
15
+ Debugger.start_
16
+ assert_equal({}, Debugger.catchpoints)
17
+ Debugger.add_catchpoint('ZeroDivisionError')
18
+ assert_equal({'ZeroDivisionError' => 0}, Debugger.catchpoints)
19
+ Debugger.add_catchpoint('RuntimeError')
20
+ assert_equal(['RuntimeError', 'ZeroDivisionError'],
21
+ Debugger.catchpoints.keys.sort)
22
+ Debugger.stop
23
+ end
24
+
25
+ end
26
+
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-debug-base19
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.11.15
5
+ platform: ruby
6
+ authors:
7
+ - Kent Sibilev
8
+ - Mark Moseley
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-08-24 00:00:00 -07:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: columnize
18
+ type: :runtime
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: 0.3.1
25
+ version:
26
+ - !ruby/object:Gem::Dependency
27
+ name: ruby_core_source
28
+ type: :runtime
29
+ version_requirement:
30
+ version_requirements: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: 0.1.4
35
+ version:
36
+ - !ruby/object:Gem::Dependency
37
+ name: linecache19
38
+ type: :runtime
39
+ version_requirement:
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: 0.5.11
45
+ version:
46
+ description: |
47
+ ruby-debug is a fast implementation of the standard Ruby debugger debug.rb.
48
+ It is implemented by utilizing a new Ruby C API hook. The core component
49
+ provides support that front-ends can build on. It provides breakpoint
50
+ handling, bindings for stack frames among other things.
51
+
52
+ email: mark@fast-software.com
53
+ executables: []
54
+
55
+ extensions:
56
+ - ext/ruby_debug/extconf.rb
57
+ extra_rdoc_files:
58
+ - README
59
+ - ext/ruby_debug/ruby_debug.c
60
+ files:
61
+ - AUTHORS
62
+ - CHANGES
63
+ - LICENSE
64
+ - README
65
+ - Rakefile
66
+ - ext/ruby_debug/extconf.rb
67
+ - ext/ruby_debug/breakpoint.c
68
+ - ext/ruby_debug/ruby_debug.h
69
+ - ext/ruby_debug/ruby_debug.c
70
+ - lib/ruby-debug-base.rb
71
+ - lib/ChangeLog
72
+ - test/base/base.rb
73
+ - test/base/binding.rb
74
+ - test/base/catchpoint.rb
75
+ has_rdoc: true
76
+ homepage: http://rubyforge.org/projects/ruby-debug19/
77
+ licenses: []
78
+
79
+ post_install_message:
80
+ rdoc_options:
81
+ - --charset=UTF-8
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: 1.8.2
89
+ version:
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: "0"
95
+ version:
96
+ requirements: []
97
+
98
+ rubyforge_project: ruby-debug19
99
+ rubygems_version: 1.3.4
100
+ signing_key:
101
+ specification_version: 3
102
+ summary: Fast Ruby debugger - core component
103
+ test_files:
104
+ - test/base/base.rb
105
+ - test/base/binding.rb
106
+ - test/base/catchpoint.rb