ruby-debug-base193 0.0.1

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,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
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)
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
@@ -0,0 +1,56 @@
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(Debugger.started?,
13
+ 'debugger should now be started.')
14
+ assert_equal(__LINE__, Debugger.current_context.frame_line)
15
+ assert_equal(Debugger.current_context.frame_file,
16
+ Debugger.current_context.frame_file(0))
17
+ assert_equal(File.basename(__FILE__),
18
+ File.basename(Debugger.current_context.frame_file))
19
+ assert_raises(ArgumentError) {Debugger.current_context.frame_file(1, 2)}
20
+ assert_raises(ArgumentError) {Debugger.current_context.frame_file(10)}
21
+ assert_equal(7, Debugger.current_context.stack_size)
22
+ assert_equal(TestRubyDebug, Debugger.current_context.frame_class)
23
+ assert_equal(false, Debugger.current_context.dead?, 'Not dead yet!')
24
+ end
25
+
26
+ # Test initial variables and setting/getting state.
27
+ def test_debugger_base
28
+ assert(Debugger.started?,
29
+ 'Debugger should now be started.')
30
+ assert_equal(false, Debugger.debug,
31
+ 'Debug variable should not be set.')
32
+ a = Debugger.contexts
33
+ assert_equal(1, a.size,
34
+ 'There should only be one context.')
35
+ assert_equal(Array, a.class,
36
+ 'Context should be an array.')
37
+ end
38
+
39
+ # Test breakpoint handling
40
+ def test_breakpoints
41
+ assert_equal(0, Debugger.breakpoints.size,
42
+ 'There should not be any breakpoints set.')
43
+ brk = Debugger.add_breakpoint(__FILE__, 1)
44
+ assert_equal(Debugger::Breakpoint, brk.class,
45
+ 'Breakpoint should have been set and returned.')
46
+ assert_equal(1, Debugger.breakpoints.size,
47
+ 'There should now be one breakpoint set.')
48
+ Debugger.remove_breakpoint(0)
49
+ assert_equal(1, Debugger.breakpoints.size,
50
+ 'There should still be one breakpoint set.')
51
+ Debugger.remove_breakpoint(1)
52
+ assert_equal(0, Debugger.breakpoints.size,
53
+ 'There should no longer be any breakpoints set.')
54
+ end
55
+ end
56
+
@@ -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,23 @@
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_equal({}, Debugger.catchpoints)
15
+ Debugger.add_catchpoint('ZeroDivisionError')
16
+ assert_equal({'ZeroDivisionError' => 0}, Debugger.catchpoints)
17
+ Debugger.add_catchpoint('RuntimeError')
18
+ assert_equal(['RuntimeError', 'ZeroDivisionError'],
19
+ Debugger.catchpoints.keys.sort)
20
+ end
21
+
22
+ end
23
+
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-debug-base193
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Kent Sibilev
13
+ - Mark Moseley
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2009-09-08 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: columnize
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ - 3
31
+ - 1
32
+ version: 0.3.1
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: ruby_core_source
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 0
44
+ - 1
45
+ - 4
46
+ version: 0.1.4
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: linecache193
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ segments:
57
+ - 0
58
+ - 0
59
+ - 1
60
+ version: 0.0.1
61
+ type: :runtime
62
+ version_requirements: *id003
63
+ description: |
64
+ ruby-debug is a fast implementation of the standard Ruby debugger debug.rb.
65
+ It is implemented by utilizing a new Ruby C API hook. The core component
66
+ provides support that front-ends can build on. It provides breakpoint
67
+ handling, bindings for stack frames among other things.
68
+
69
+ email: mark@fast-software.com
70
+ executables: []
71
+
72
+ extensions:
73
+ - ext/ruby_debug/extconf.rb
74
+ extra_rdoc_files:
75
+ - README
76
+ - ext/ruby_debug/ruby_debug.c
77
+ files:
78
+ - AUTHORS
79
+ - CHANGES
80
+ - LICENSE
81
+ - README
82
+ - Rakefile
83
+ - ext/ruby_debug/extconf.rb
84
+ - ext/ruby_debug/breakpoint.c
85
+ - ext/ruby_debug/ruby_debug.h
86
+ - ext/ruby_debug/ruby_debug.c
87
+ - lib/ruby-debug-base.rb
88
+ - lib/ChangeLog
89
+ - test/base/base.rb
90
+ - test/base/binding.rb
91
+ - test/base/catchpoint.rb
92
+ has_rdoc: true
93
+ homepage: http://rubyforge.org/projects/ruby-debug19/
94
+ licenses: []
95
+
96
+ post_install_message:
97
+ rdoc_options:
98
+ - --charset=UTF-8
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ segments:
106
+ - 1
107
+ - 8
108
+ - 2
109
+ version: 1.8.2
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ segments:
115
+ - 0
116
+ version: "0"
117
+ requirements: []
118
+
119
+ rubyforge_project: ruby-debug19
120
+ rubygems_version: 1.3.6
121
+ signing_key:
122
+ specification_version: 3
123
+ summary: Fast Ruby debugger - core component
124
+ test_files:
125
+ - test/base/base.rb
126
+ - test/base/binding.rb
127
+ - test/base/catchpoint.rb