ruby-debug-base 0.10.5.rc1-java → 0.10.5.rc2-java
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +34 -239
- data/ext/breakpoint.c +582 -0
- data/ext/ruby_debug.h +123 -0
- data/lib/ruby-debug-base/version.rb +1 -1
- data/lib/ruby_debug.jar +0 -0
- metadata +39 -26
- data/test/base/base.rb +0 -77
- data/test/base/binding.rb +0 -22
- data/test/base/catchpoint.rb +0 -19
- data/test/base/load.rb +0 -44
- data/test/base/reload_bug.rb +0 -8
data/Rakefile
CHANGED
@@ -7,82 +7,33 @@ require 'rake/testtask'
|
|
7
7
|
require 'rake/extensiontask'
|
8
8
|
require 'rake/javaextensiontask'
|
9
9
|
|
10
|
-
|
10
|
+
lib = File.expand_path('../lib', __FILE__)
|
11
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
11
12
|
require "ruby-debug-base/version"
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
'README',
|
22
|
-
'Rakefile',
|
23
|
-
]
|
24
|
-
|
25
|
-
CLI_TEST_FILE_LIST = FileList['test/cli/commands/unit/*.rb',
|
26
|
-
'test/cli/commands/*_test.rb',
|
27
|
-
'test/cli/**/*_test.rb',
|
28
|
-
'test/test-*.rb']
|
29
|
-
CLI_FILES = COMMON_FILES + FileList[
|
30
|
-
"cli/**/*",
|
31
|
-
'ChangeLog',
|
32
|
-
'bin/*',
|
33
|
-
'doc/rdebug.1',
|
34
|
-
'test/rdebug-save.1',
|
35
|
-
'test/**/data/*.cmd',
|
36
|
-
'test/**/data/*.right',
|
37
|
-
'test/**/example/*.rb',
|
38
|
-
'test/config.yaml',
|
39
|
-
'test/**/*.rb',
|
40
|
-
'rdbg.rb',
|
41
|
-
CLI_TEST_FILE_LIST
|
42
|
-
]
|
43
|
-
|
44
|
-
BASE_TEST_FILE_LIST = FileList['test/base/*.rb']
|
45
|
-
|
46
|
-
BASE_FILES = COMMON_FILES + FileList[
|
47
|
-
'ext/breakpoint.c',
|
48
|
-
'ext/extconf.rb',
|
49
|
-
'ext/ruby_debug.c',
|
50
|
-
'ext/ruby_debug.h',
|
51
|
-
'ext/win32/*',
|
52
|
-
'lib/ruby-debug-base.rb',
|
53
|
-
'lib/ruby-debug-base/version.rb',
|
54
|
-
BASE_TEST_FILE_LIST,
|
55
|
-
]
|
56
|
-
|
57
|
-
ext = File.join(ROOT_DIR, 'ext')
|
58
|
-
|
59
|
-
desc "Test everything."
|
60
|
-
Rake::TestTask.new(:test) do |t|
|
61
|
-
t.libs += %W(#{ROOT_DIR}/lib #{ROOT_DIR}/cli)
|
62
|
-
t.libs << ext if File.exist?(ext)
|
63
|
-
t.test_files = CLI_TEST_FILE_LIST
|
64
|
-
t.options = '--verbose' if $VERBOSE
|
65
|
-
t.ruby_opts << "--debug" if defined?(JRUBY_VERSION)
|
66
|
-
end
|
67
|
-
|
68
|
-
task :test => :test_base if File.exist?(ext)
|
69
|
-
|
70
|
-
desc "Test ruby-debug-base."
|
71
|
-
Rake::TestTask.new(:test_base) do |t|
|
72
|
-
t.libs += ['./ext', './lib']
|
73
|
-
t.test_files = FileList[BASE_TEST_FILE_LIST]
|
74
|
-
t.options = '--verbose' if $VERBOSE
|
75
|
-
t.ruby_opts << "--debug" if defined?(JRUBY_VERSION)
|
76
|
-
end
|
14
|
+
namespace :test do
|
15
|
+
desc "Test ruby-debug-base"
|
16
|
+
Rake::TestTask.new(:base => :compile) do |t|
|
17
|
+
t.libs += %w(./ext ./lib)
|
18
|
+
t.test_files = FileList['test/base/*.rb']
|
19
|
+
t.options = '--verbose' if $VERBOSE
|
20
|
+
t.ruby_opts << "--debug" if defined?(JRUBY_VERSION)
|
21
|
+
end
|
77
22
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
23
|
+
desc "Test ruby-debug"
|
24
|
+
Rake::TestTask.new(:cli => :compile) do |t|
|
25
|
+
t.libs += %W(./lib ./cli ./ext)
|
26
|
+
t.test_files = FileList['test/cli/commands/unit/*.rb',
|
27
|
+
'test/cli/commands/*_test.rb',
|
28
|
+
'test/cli/**/*_test.rb',
|
29
|
+
'test/test-*.rb']
|
30
|
+
t.options = '--verbose' if $VERBOSE
|
31
|
+
t.ruby_opts << "--debug" if defined?(JRUBY_VERSION)
|
32
|
+
end
|
82
33
|
end
|
83
34
|
|
84
|
-
desc "Test everything
|
85
|
-
task :
|
35
|
+
desc "Test everything"
|
36
|
+
task :test => %w(test:base test:cli)
|
86
37
|
|
87
38
|
desc "Create a GNU-style ChangeLog via svn2cl"
|
88
39
|
task :ChangeLog do
|
@@ -91,123 +42,24 @@ task :ChangeLog do
|
|
91
42
|
system('git log --pretty --numstat --summary lib | git2cl > lib/ChangeLog')
|
92
43
|
end
|
93
44
|
|
94
|
-
|
95
|
-
|
96
|
-
spec.name = "ruby-debug-base"
|
97
|
-
|
98
|
-
spec.homepage = "http://rubyforge.org/projects/ruby-debug/"
|
99
|
-
spec.summary = "Fast Ruby debugger - core component"
|
100
|
-
spec.description = <<-EOF
|
101
|
-
ruby-debug is a fast implementation of the standard Ruby debugger debug.rb.
|
102
|
-
It is implemented by utilizing a new Ruby C API hook. The core component
|
103
|
-
provides support that front-ends can build on. It provides breakpoint
|
104
|
-
handling, bindings for stack frames among other things.
|
105
|
-
EOF
|
106
|
-
|
107
|
-
spec.version = Debugger::VERSION
|
45
|
+
base_spec = Gem::Specification.load("ruby-debug-base.gemspec")
|
46
|
+
cli_spec = Gem::Specification.load("ruby-debug.gemspec")
|
108
47
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
spec.date = Time.now
|
118
|
-
spec.rubyforge_project = 'ruby-debug'
|
119
|
-
spec.add_dependency('linecache', '>= 0.3')
|
120
|
-
spec.add_development_dependency('rake-compiler')
|
121
|
-
|
122
|
-
spec.test_files = FileList[BASE_TEST_FILE_LIST]
|
123
|
-
|
124
|
-
# rdoc
|
125
|
-
spec.has_rdoc = true
|
126
|
-
spec.extra_rdoc_files = ['README', 'ext/ruby_debug.c']
|
127
|
-
end
|
128
|
-
|
129
|
-
cli_spec = Gem::Specification.new do |spec|
|
130
|
-
spec.name = "ruby-debug"
|
131
|
-
|
132
|
-
spec.homepage = "http://rubyforge.org/projects/ruby-debug/"
|
133
|
-
spec.summary = "Command line interface (CLI) for ruby-debug-base"
|
134
|
-
spec.description = <<-EOF
|
135
|
-
A generic command line interface for ruby-debug.
|
136
|
-
EOF
|
137
|
-
|
138
|
-
spec.version = Debugger::VERSION
|
139
|
-
|
140
|
-
spec.author = "Kent Sibilev"
|
141
|
-
spec.email = "ksibilev@yahoo.com"
|
142
|
-
spec.platform = Gem::Platform::RUBY
|
143
|
-
spec.require_path = "cli"
|
144
|
-
spec.bindir = "bin"
|
145
|
-
spec.executables = ["rdebug"]
|
146
|
-
spec.files = CLI_FILES.to_a
|
147
|
-
|
148
|
-
spec.required_ruby_version = '>= 1.8.2'
|
149
|
-
spec.date = Time.now
|
150
|
-
spec.rubyforge_project = 'ruby-debug'
|
151
|
-
spec.add_dependency('columnize', '>= 0.1')
|
152
|
-
spec.add_dependency('ruby-debug-base', "~> #{Debugger::VERSION}.0")
|
153
|
-
|
154
|
-
# FIXME: work out operational logistics for this
|
155
|
-
# spec.test_files = FileList[CLI_TEST_FILE_LIST]
|
156
|
-
|
157
|
-
# rdoc
|
158
|
-
spec.has_rdoc = true
|
159
|
-
spec.extra_rdoc_files = ['README']
|
160
|
-
end
|
161
|
-
|
162
|
-
# Rake task to build the default package
|
163
|
-
Gem::PackageTask.new(base_spec) do |pkg|
|
164
|
-
pkg.need_tar = true
|
165
|
-
end
|
166
|
-
Gem::PackageTask.new(cli_spec) do |pkg|
|
167
|
-
pkg.need_tar = true
|
48
|
+
if defined?(JRUBY_VERSION)
|
49
|
+
Rake::JavaExtensionTask.new('ruby_debug', base_spec) do |t|
|
50
|
+
t.ext_dir = "src"
|
51
|
+
end
|
52
|
+
else
|
53
|
+
Rake::ExtensionTask.new('ruby_debug', base_spec) do |t|
|
54
|
+
t.ext_dir = "ext"
|
55
|
+
end
|
168
56
|
end
|
169
57
|
|
170
|
-
|
171
|
-
|
172
|
-
end
|
58
|
+
Gem::PackageTask.new(base_spec) {}
|
59
|
+
Gem::PackageTask.new(cli_spec) {}
|
173
60
|
|
174
61
|
task :default => :test
|
175
62
|
|
176
|
-
# Windows specification
|
177
|
-
win_spec = base_spec.clone
|
178
|
-
win_spec.extensions = []
|
179
|
-
## win_spec.platform = Gem::Platform::WIN32 # deprecated
|
180
|
-
win_spec.platform = 'mswin32'
|
181
|
-
win_spec.files += ["lib/#{SO_NAME}"]
|
182
|
-
|
183
|
-
desc "Create Windows Gem"
|
184
|
-
task :win32_gem do
|
185
|
-
# Copy the win32 extension the top level directory
|
186
|
-
current_dir = File.expand_path(File.dirname(__FILE__))
|
187
|
-
source = File.join(current_dir, "ext", "win32", SO_NAME)
|
188
|
-
target = File.join(current_dir, "lib", SO_NAME)
|
189
|
-
cp(source, target)
|
190
|
-
|
191
|
-
# Create the gem, then move it to pkg.
|
192
|
-
Gem::Builder.new(win_spec).build
|
193
|
-
gem_file = "#{win_spec.name}-#{win_spec.version}-#{win_spec.platform}.gem"
|
194
|
-
mv(gem_file, "pkg/#{gem_file}")
|
195
|
-
|
196
|
-
# Remove win extension from top level directory.
|
197
|
-
rm(target)
|
198
|
-
end
|
199
|
-
|
200
|
-
desc "Publish ruby-debug to RubyForge."
|
201
|
-
task :publish do
|
202
|
-
require 'rake/contrib/sshpublisher'
|
203
|
-
|
204
|
-
# Get ruby-debug path.
|
205
|
-
ruby_debug_path = File.expand_path(File.dirname(__FILE__))
|
206
|
-
|
207
|
-
Rake::SshDirPublisher.new("kent@rubyforge.org",
|
208
|
-
"/var/www/gforge-projects/ruby-debug", ruby_debug_path)
|
209
|
-
end
|
210
|
-
|
211
63
|
desc "Remove built files"
|
212
64
|
task :clean do
|
213
65
|
cd "ext" do
|
@@ -221,7 +73,6 @@ task :clean do
|
|
221
73
|
rm 'lib/ruby_debug.jar' if File.exists?("lib/ruby_debug.jar")
|
222
74
|
end
|
223
75
|
|
224
|
-
# --------- RDoc Documentation ------
|
225
76
|
desc "Generate rdoc documentation"
|
226
77
|
RDoc::Task.new("rdoc") do |rdoc|
|
227
78
|
rdoc.rdoc_dir = 'doc/rdoc'
|
@@ -238,59 +89,3 @@ RDoc::Task.new("rdoc") do |rdoc|
|
|
238
89
|
'README',
|
239
90
|
'LICENSE')
|
240
91
|
end
|
241
|
-
|
242
|
-
desc "Publish the release files to RubyForge."
|
243
|
-
task :rubyforge_upload do
|
244
|
-
`rubyforge login`
|
245
|
-
release_command = "rubyforge add_release #{PKG_NAME} #{PKG_NAME} '#{PKG_NAME}-#{PKG_VERSION}' pkg/#{PKG_NAME}-#{PKG_VERSION}.gem"
|
246
|
-
puts release_command
|
247
|
-
system(release_command)
|
248
|
-
end
|
249
|
-
|
250
|
-
PKG_NAME = 'ruby-debug'
|
251
|
-
desc "Publish the release files to RubyForge."
|
252
|
-
task :rubyforge_upload do
|
253
|
-
`rubyforge login`
|
254
|
-
for pkg_name in ['ruby-debug', 'ruby-debug-base'] do
|
255
|
-
pkg_file_name = "#{pkg_name}-#{pkg_version}"
|
256
|
-
release_command = "rubyforge add_release ruby-debug #{pkg_name} '#{pkg_file_name}' pkg/#{pkg_file_name}.gem"
|
257
|
-
puts release_command
|
258
|
-
system(release_command)
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
def install_gem(spec, *opts)
|
263
|
-
args = ['gem', 'install', "pkg/#{spec.name}-#{spec.version}.gem"] + opts
|
264
|
-
args.unshift 'sudo' unless 0 == Process.uid || ENV['rvm_path']
|
265
|
-
system(*args)
|
266
|
-
end
|
267
|
-
|
268
|
-
desc 'Install locally'
|
269
|
-
task :install => :package do
|
270
|
-
Dir.chdir(File::dirname(__FILE__)) do
|
271
|
-
# ri and rdoc take lots of time
|
272
|
-
install_gem(base_spec, '--no-ri', '--no-rdoc')
|
273
|
-
install_gem(cli_spec, '--no-ri', '--no-rdoc')
|
274
|
-
end
|
275
|
-
end
|
276
|
-
|
277
|
-
task :install_full => :package do
|
278
|
-
Dir.chdir(File::dirname(__FILE__)) do
|
279
|
-
install_gem(base_spec)
|
280
|
-
install_gem(cli_spec)
|
281
|
-
end
|
282
|
-
end
|
283
|
-
|
284
|
-
namespace :jruby do
|
285
|
-
jruby_spec = base_spec.clone
|
286
|
-
jruby_spec.platform = "java"
|
287
|
-
jruby_spec.files = jruby_spec.files.reject {|f| f =~ /^ext/ }
|
288
|
-
jruby_spec.files += ['lib/ruby_debug.jar']
|
289
|
-
jruby_spec.extensions = []
|
290
|
-
|
291
|
-
Gem::PackageTask.new(jruby_spec) {}
|
292
|
-
|
293
|
-
Rake::JavaExtensionTask.new('ruby_debug') do |t|
|
294
|
-
t.ext_dir = "src"
|
295
|
-
end
|
296
|
-
end
|
data/ext/breakpoint.c
ADDED
@@ -0,0 +1,582 @@
|
|
1
|
+
#include "ruby_debug.h"
|
2
|
+
|
3
|
+
VALUE rdebug_breakpoints = Qnil;
|
4
|
+
VALUE rdebug_catchpoints;
|
5
|
+
|
6
|
+
static VALUE cBreakpoint;
|
7
|
+
static ID idEval;
|
8
|
+
|
9
|
+
static VALUE
|
10
|
+
eval_expression(VALUE args)
|
11
|
+
{
|
12
|
+
return rb_funcall2(rb_mKernel, idEval, 2, RARRAY(args)->ptr);
|
13
|
+
}
|
14
|
+
|
15
|
+
int
|
16
|
+
check_breakpoint_hit_condition(VALUE breakpoint)
|
17
|
+
{
|
18
|
+
debug_breakpoint_t *debug_breakpoint;
|
19
|
+
|
20
|
+
if(breakpoint == Qnil)
|
21
|
+
return 0;
|
22
|
+
Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
|
23
|
+
|
24
|
+
debug_breakpoint->hit_count++;
|
25
|
+
if (!Qtrue == debug_breakpoint->enabled) return 0;
|
26
|
+
switch(debug_breakpoint->hit_condition)
|
27
|
+
{
|
28
|
+
case HIT_COND_NONE:
|
29
|
+
return 1;
|
30
|
+
case HIT_COND_GE:
|
31
|
+
{
|
32
|
+
if(debug_breakpoint->hit_count >= debug_breakpoint->hit_value)
|
33
|
+
return 1;
|
34
|
+
break;
|
35
|
+
}
|
36
|
+
case HIT_COND_EQ:
|
37
|
+
{
|
38
|
+
if(debug_breakpoint->hit_count == debug_breakpoint->hit_value)
|
39
|
+
return 1;
|
40
|
+
break;
|
41
|
+
}
|
42
|
+
case HIT_COND_MOD:
|
43
|
+
{
|
44
|
+
if(debug_breakpoint->hit_count % debug_breakpoint->hit_value == 0)
|
45
|
+
return 1;
|
46
|
+
break;
|
47
|
+
}
|
48
|
+
}
|
49
|
+
return 0;
|
50
|
+
}
|
51
|
+
|
52
|
+
static int
|
53
|
+
check_breakpoint_by_pos(VALUE breakpoint, char *file, int line)
|
54
|
+
{
|
55
|
+
debug_breakpoint_t *debug_breakpoint;
|
56
|
+
|
57
|
+
if(breakpoint == Qnil)
|
58
|
+
return 0;
|
59
|
+
Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
|
60
|
+
if (!Qtrue == debug_breakpoint->enabled) return 0;
|
61
|
+
if(debug_breakpoint->type != BP_POS_TYPE)
|
62
|
+
return 0;
|
63
|
+
if(debug_breakpoint->pos.line != line)
|
64
|
+
return 0;
|
65
|
+
if(filename_cmp(debug_breakpoint->source, file))
|
66
|
+
return 1;
|
67
|
+
return 0;
|
68
|
+
}
|
69
|
+
|
70
|
+
int
|
71
|
+
check_breakpoint_by_method(VALUE breakpoint, VALUE klass, ID mid, VALUE self)
|
72
|
+
{
|
73
|
+
debug_breakpoint_t *debug_breakpoint;
|
74
|
+
|
75
|
+
if(breakpoint == Qnil)
|
76
|
+
return 0;
|
77
|
+
Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
|
78
|
+
if (!Qtrue == debug_breakpoint->enabled) return 0;
|
79
|
+
if(debug_breakpoint->type != BP_METHOD_TYPE)
|
80
|
+
return 0;
|
81
|
+
if(debug_breakpoint->pos.mid != mid)
|
82
|
+
return 0;
|
83
|
+
if(classname_cmp(debug_breakpoint->source, klass))
|
84
|
+
return 1;
|
85
|
+
if ((rb_type(self) == T_CLASS) &&
|
86
|
+
classname_cmp(debug_breakpoint->source, self))
|
87
|
+
return 1;
|
88
|
+
return 0;
|
89
|
+
}
|
90
|
+
|
91
|
+
VALUE
|
92
|
+
check_breakpoints_by_pos(debug_context_t *debug_context, char *file, int line)
|
93
|
+
{
|
94
|
+
VALUE breakpoint;
|
95
|
+
int i;
|
96
|
+
|
97
|
+
if(!CTX_FL_TEST(debug_context, CTX_FL_ENABLE_BKPT))
|
98
|
+
return Qnil;
|
99
|
+
|
100
|
+
if(check_breakpoint_by_pos(debug_context->breakpoint, file, line))
|
101
|
+
return debug_context->breakpoint;
|
102
|
+
|
103
|
+
if(RARRAY(rdebug_breakpoints)->len == 0)
|
104
|
+
return Qnil;
|
105
|
+
for(i = 0; i < RARRAY(rdebug_breakpoints)->len; i++)
|
106
|
+
{
|
107
|
+
breakpoint = rb_ary_entry(rdebug_breakpoints, i);
|
108
|
+
if(check_breakpoint_by_pos(breakpoint, file, line))
|
109
|
+
return breakpoint;
|
110
|
+
}
|
111
|
+
return Qnil;
|
112
|
+
}
|
113
|
+
|
114
|
+
VALUE
|
115
|
+
check_breakpoints_by_method(debug_context_t *debug_context, VALUE klass, ID mid, VALUE self)
|
116
|
+
{
|
117
|
+
VALUE breakpoint;
|
118
|
+
int i;
|
119
|
+
|
120
|
+
if(!CTX_FL_TEST(debug_context, CTX_FL_ENABLE_BKPT))
|
121
|
+
return Qnil;
|
122
|
+
|
123
|
+
if(check_breakpoint_by_method(debug_context->breakpoint, klass, mid, self))
|
124
|
+
return debug_context->breakpoint;
|
125
|
+
|
126
|
+
if(RARRAY(rdebug_breakpoints)->len == 0)
|
127
|
+
return Qnil;
|
128
|
+
for(i = 0; i < RARRAY(rdebug_breakpoints)->len; i++)
|
129
|
+
{
|
130
|
+
breakpoint = rb_ary_entry(rdebug_breakpoints, i);
|
131
|
+
if(check_breakpoint_by_method(breakpoint, klass, mid, self))
|
132
|
+
return breakpoint;
|
133
|
+
}
|
134
|
+
return Qnil;
|
135
|
+
}
|
136
|
+
|
137
|
+
int
|
138
|
+
check_breakpoint_expression(VALUE breakpoint, VALUE binding)
|
139
|
+
{
|
140
|
+
debug_breakpoint_t *debug_breakpoint;
|
141
|
+
VALUE args, expr_result;
|
142
|
+
|
143
|
+
Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
|
144
|
+
if(NIL_P(debug_breakpoint->expr))
|
145
|
+
return 1;
|
146
|
+
|
147
|
+
args = rb_ary_new3(2, debug_breakpoint->expr, binding);
|
148
|
+
expr_result = rb_protect(eval_expression, args, 0);
|
149
|
+
return RTEST(expr_result);
|
150
|
+
}
|
151
|
+
|
152
|
+
static void
|
153
|
+
breakpoint_mark(void *data)
|
154
|
+
{
|
155
|
+
debug_breakpoint_t *breakpoint;
|
156
|
+
breakpoint = (debug_breakpoint_t *)data;
|
157
|
+
rb_gc_mark(breakpoint->source);
|
158
|
+
rb_gc_mark(breakpoint->expr);
|
159
|
+
}
|
160
|
+
|
161
|
+
VALUE
|
162
|
+
create_breakpoint_from_args(int argc, VALUE *argv, int id)
|
163
|
+
{
|
164
|
+
VALUE source, pos, expr;
|
165
|
+
debug_breakpoint_t *breakpoint;
|
166
|
+
int type;
|
167
|
+
|
168
|
+
if(rb_scan_args(argc, argv, "21", &source, &pos, &expr) == 2)
|
169
|
+
{
|
170
|
+
expr = Qnil;
|
171
|
+
}
|
172
|
+
type = FIXNUM_P(pos) ? BP_POS_TYPE : BP_METHOD_TYPE;
|
173
|
+
if(type == BP_POS_TYPE)
|
174
|
+
source = StringValue(source);
|
175
|
+
else
|
176
|
+
pos = StringValue(pos);
|
177
|
+
breakpoint = ALLOC(debug_breakpoint_t);
|
178
|
+
breakpoint->id = id;
|
179
|
+
breakpoint->source = source;
|
180
|
+
breakpoint->type = type;
|
181
|
+
if(type == BP_POS_TYPE)
|
182
|
+
breakpoint->pos.line = FIX2INT(pos);
|
183
|
+
else
|
184
|
+
breakpoint->pos.mid = rb_intern(RSTRING(pos)->ptr);
|
185
|
+
breakpoint->enabled = Qtrue;
|
186
|
+
breakpoint->expr = NIL_P(expr) ? expr: StringValue(expr);
|
187
|
+
breakpoint->hit_count = 0;
|
188
|
+
breakpoint->hit_value = 0;
|
189
|
+
breakpoint->hit_condition = HIT_COND_NONE;
|
190
|
+
return Data_Wrap_Struct(cBreakpoint, breakpoint_mark, xfree, breakpoint);
|
191
|
+
}
|
192
|
+
|
193
|
+
/*
|
194
|
+
* call-seq:
|
195
|
+
* Debugger.remove_breakpoint(id) -> breakpoint
|
196
|
+
*
|
197
|
+
* Removes breakpoint by its id.
|
198
|
+
* <i>id</i> is an identificator of a breakpoint.
|
199
|
+
*/
|
200
|
+
VALUE
|
201
|
+
rdebug_remove_breakpoint(VALUE self, VALUE id_value)
|
202
|
+
{
|
203
|
+
int i;
|
204
|
+
int id;
|
205
|
+
VALUE breakpoint;
|
206
|
+
debug_breakpoint_t *debug_breakpoint;
|
207
|
+
|
208
|
+
id = FIX2INT(id_value);
|
209
|
+
|
210
|
+
for( i = 0; i < RARRAY(rdebug_breakpoints)->len; i += 1 )
|
211
|
+
{
|
212
|
+
breakpoint = rb_ary_entry(rdebug_breakpoints, i);
|
213
|
+
Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
|
214
|
+
if(debug_breakpoint->id == id)
|
215
|
+
{
|
216
|
+
rb_ary_delete_at(rdebug_breakpoints, i);
|
217
|
+
return breakpoint;
|
218
|
+
}
|
219
|
+
}
|
220
|
+
return Qnil;
|
221
|
+
}
|
222
|
+
|
223
|
+
/*
|
224
|
+
* call-seq:
|
225
|
+
* Debugger.catchpoints -> hash
|
226
|
+
*
|
227
|
+
* Returns a current catchpoints, which is a hash exception names that will
|
228
|
+
* trigger a debugger when raised. The values are the number of times taht
|
229
|
+
* catchpoint was hit, initially 0.
|
230
|
+
*/
|
231
|
+
VALUE
|
232
|
+
debug_catchpoints(VALUE self)
|
233
|
+
{
|
234
|
+
debug_check_started();
|
235
|
+
|
236
|
+
return rdebug_catchpoints;
|
237
|
+
}
|
238
|
+
|
239
|
+
/*
|
240
|
+
* call-seq:
|
241
|
+
* Debugger.catchpoint(string) -> string
|
242
|
+
*
|
243
|
+
* Sets catchpoint. Returns the string passed.
|
244
|
+
*/
|
245
|
+
VALUE
|
246
|
+
rdebug_add_catchpoint(VALUE self, VALUE value)
|
247
|
+
{
|
248
|
+
debug_check_started();
|
249
|
+
|
250
|
+
if (TYPE(value) != T_STRING) {
|
251
|
+
rb_raise(rb_eTypeError, "value of a catchpoint must be String");
|
252
|
+
}
|
253
|
+
rb_hash_aset(rdebug_catchpoints, rb_str_dup(value), INT2FIX(0));
|
254
|
+
return value;
|
255
|
+
}
|
256
|
+
|
257
|
+
/*
|
258
|
+
* call-seq:
|
259
|
+
* context.breakpoint -> Breakpoint
|
260
|
+
*
|
261
|
+
* Returns a context-specific temporary Breakpoint object.
|
262
|
+
*/
|
263
|
+
VALUE
|
264
|
+
context_breakpoint(VALUE self)
|
265
|
+
{
|
266
|
+
debug_context_t *debug_context;
|
267
|
+
|
268
|
+
debug_check_started();
|
269
|
+
|
270
|
+
Data_Get_Struct(self, debug_context_t, debug_context);
|
271
|
+
return debug_context->breakpoint;
|
272
|
+
}
|
273
|
+
|
274
|
+
/*
|
275
|
+
* call-seq:
|
276
|
+
* context.set_breakpoint(source, pos, condition = nil) -> breakpoint
|
277
|
+
*
|
278
|
+
* Sets a context-specific temporary breakpoint, which can be used to implement
|
279
|
+
* 'Run to Cursor' debugger function. When this breakpoint is reached, it will be
|
280
|
+
* cleared out.
|
281
|
+
*
|
282
|
+
* <i>source</i> is a name of a file or a class.
|
283
|
+
* <i>pos</i> is a line number or a method name if <i>source</i> is a class name.
|
284
|
+
* <i>condition</i> is a string which is evaluated to +true+ when this breakpoint
|
285
|
+
* is activated.
|
286
|
+
*/
|
287
|
+
VALUE
|
288
|
+
context_set_breakpoint(int argc, VALUE *argv, VALUE self)
|
289
|
+
{
|
290
|
+
VALUE result;
|
291
|
+
debug_context_t *debug_context;
|
292
|
+
|
293
|
+
debug_check_started();
|
294
|
+
|
295
|
+
Data_Get_Struct(self, debug_context_t, debug_context);
|
296
|
+
result = create_breakpoint_from_args(argc, argv, 0);
|
297
|
+
debug_context->breakpoint = result;
|
298
|
+
return result;
|
299
|
+
}
|
300
|
+
|
301
|
+
/*
|
302
|
+
* call-seq:
|
303
|
+
* breakpoint.enabled?
|
304
|
+
*
|
305
|
+
* Returns whether breakpoint is enabled or not.
|
306
|
+
*/
|
307
|
+
static VALUE
|
308
|
+
breakpoint_enabled(VALUE self)
|
309
|
+
{
|
310
|
+
debug_breakpoint_t *breakpoint;
|
311
|
+
|
312
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
313
|
+
return breakpoint->enabled;
|
314
|
+
}
|
315
|
+
|
316
|
+
/*
|
317
|
+
* call-seq:
|
318
|
+
* breakpoint.enabled = bool
|
319
|
+
*
|
320
|
+
* Enables or disables breakpoint.
|
321
|
+
*/
|
322
|
+
static VALUE
|
323
|
+
breakpoint_set_enabled(VALUE self, VALUE bool)
|
324
|
+
{
|
325
|
+
debug_breakpoint_t *breakpoint;
|
326
|
+
|
327
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
328
|
+
return breakpoint->enabled = bool;
|
329
|
+
}
|
330
|
+
|
331
|
+
/*
|
332
|
+
* call-seq:
|
333
|
+
* breakpoint.source -> string
|
334
|
+
*
|
335
|
+
* Returns a source of the breakpoint.
|
336
|
+
*/
|
337
|
+
static VALUE
|
338
|
+
breakpoint_source(VALUE self)
|
339
|
+
{
|
340
|
+
debug_breakpoint_t *breakpoint;
|
341
|
+
|
342
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
343
|
+
return breakpoint->source;
|
344
|
+
}
|
345
|
+
|
346
|
+
/*
|
347
|
+
* call-seq:
|
348
|
+
* breakpoint.source = string
|
349
|
+
*
|
350
|
+
* Sets the source of the breakpoint.
|
351
|
+
*/
|
352
|
+
static VALUE
|
353
|
+
breakpoint_set_source(VALUE self, VALUE value)
|
354
|
+
{
|
355
|
+
debug_breakpoint_t *breakpoint;
|
356
|
+
|
357
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
358
|
+
breakpoint->source = StringValue(value);
|
359
|
+
return value;
|
360
|
+
}
|
361
|
+
|
362
|
+
/*
|
363
|
+
* call-seq:
|
364
|
+
* breakpoint.pos -> string or int
|
365
|
+
*
|
366
|
+
* Returns the position of this breakpoint.
|
367
|
+
*/
|
368
|
+
static VALUE
|
369
|
+
breakpoint_pos(VALUE self)
|
370
|
+
{
|
371
|
+
debug_breakpoint_t *breakpoint;
|
372
|
+
|
373
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
374
|
+
if(breakpoint->type == BP_METHOD_TYPE)
|
375
|
+
return rb_str_new2(rb_id2name(breakpoint->pos.mid));
|
376
|
+
else
|
377
|
+
return INT2FIX(breakpoint->pos.line);
|
378
|
+
}
|
379
|
+
|
380
|
+
/*
|
381
|
+
* call-seq:
|
382
|
+
* breakpoint.pos = string or int
|
383
|
+
*
|
384
|
+
* Sets the position of this breakpoint.
|
385
|
+
*/
|
386
|
+
static VALUE
|
387
|
+
breakpoint_set_pos(VALUE self, VALUE value)
|
388
|
+
{
|
389
|
+
debug_breakpoint_t *breakpoint;
|
390
|
+
|
391
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
392
|
+
if(breakpoint->type == BP_METHOD_TYPE)
|
393
|
+
{
|
394
|
+
breakpoint->pos.mid = rb_to_id(StringValue(value));
|
395
|
+
}
|
396
|
+
else
|
397
|
+
breakpoint->pos.line = FIX2INT(value);
|
398
|
+
return value;
|
399
|
+
}
|
400
|
+
|
401
|
+
/*
|
402
|
+
* call-seq:
|
403
|
+
* breakpoint.expr -> string
|
404
|
+
*
|
405
|
+
* Returns a codition expression when this breakpoint should be activated.
|
406
|
+
*/
|
407
|
+
static VALUE
|
408
|
+
breakpoint_expr(VALUE self)
|
409
|
+
{
|
410
|
+
debug_breakpoint_t *breakpoint;
|
411
|
+
|
412
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
413
|
+
return breakpoint->expr;
|
414
|
+
}
|
415
|
+
|
416
|
+
/*
|
417
|
+
* call-seq:
|
418
|
+
* breakpoint.expr = string | nil
|
419
|
+
*
|
420
|
+
* Sets the codition expression when this breakpoint should be activated.
|
421
|
+
*/
|
422
|
+
static VALUE
|
423
|
+
breakpoint_set_expr(VALUE self, VALUE expr)
|
424
|
+
{
|
425
|
+
debug_breakpoint_t *breakpoint;
|
426
|
+
|
427
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
428
|
+
breakpoint->expr = NIL_P(expr) ? expr: StringValue(expr);
|
429
|
+
return expr;
|
430
|
+
}
|
431
|
+
|
432
|
+
/*
|
433
|
+
* call-seq:
|
434
|
+
* breakpoint.id -> int
|
435
|
+
*
|
436
|
+
* Returns id of the breakpoint.
|
437
|
+
*/
|
438
|
+
static VALUE
|
439
|
+
breakpoint_id(VALUE self)
|
440
|
+
{
|
441
|
+
debug_breakpoint_t *breakpoint;
|
442
|
+
|
443
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
444
|
+
return INT2FIX(breakpoint->id);
|
445
|
+
}
|
446
|
+
|
447
|
+
/*
|
448
|
+
* call-seq:
|
449
|
+
* breakpoint.hit_count -> int
|
450
|
+
*
|
451
|
+
* Returns the hit count of the breakpoint.
|
452
|
+
*/
|
453
|
+
static VALUE
|
454
|
+
breakpoint_hit_count(VALUE self)
|
455
|
+
{
|
456
|
+
debug_breakpoint_t *breakpoint;
|
457
|
+
|
458
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
459
|
+
return INT2FIX(breakpoint->hit_count);
|
460
|
+
}
|
461
|
+
|
462
|
+
/*
|
463
|
+
* call-seq:
|
464
|
+
* breakpoint.hit_value -> int
|
465
|
+
*
|
466
|
+
* Returns the hit value of the breakpoint.
|
467
|
+
*/
|
468
|
+
static VALUE
|
469
|
+
breakpoint_hit_value(VALUE self)
|
470
|
+
{
|
471
|
+
debug_breakpoint_t *breakpoint;
|
472
|
+
|
473
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
474
|
+
return INT2FIX(breakpoint->hit_value);
|
475
|
+
}
|
476
|
+
|
477
|
+
/*
|
478
|
+
* call-seq:
|
479
|
+
* breakpoint.hit_value = int
|
480
|
+
*
|
481
|
+
* Sets the hit value of the breakpoint.
|
482
|
+
*/
|
483
|
+
static VALUE
|
484
|
+
breakpoint_set_hit_value(VALUE self, VALUE value)
|
485
|
+
{
|
486
|
+
debug_breakpoint_t *breakpoint;
|
487
|
+
|
488
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
489
|
+
breakpoint->hit_value = FIX2INT(value);
|
490
|
+
return value;
|
491
|
+
}
|
492
|
+
|
493
|
+
/*
|
494
|
+
* call-seq:
|
495
|
+
* breakpoint.hit_condition -> symbol
|
496
|
+
*
|
497
|
+
* Returns the hit condition of the breakpoint:
|
498
|
+
*
|
499
|
+
* +nil+ if it is an unconditional breakpoint, or
|
500
|
+
* :greater_or_equal, :equal, :modulo
|
501
|
+
*/
|
502
|
+
static VALUE
|
503
|
+
breakpoint_hit_condition(VALUE self)
|
504
|
+
{
|
505
|
+
debug_breakpoint_t *breakpoint;
|
506
|
+
|
507
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
508
|
+
switch(breakpoint->hit_condition)
|
509
|
+
{
|
510
|
+
case HIT_COND_GE:
|
511
|
+
return ID2SYM(rb_intern("greater_or_equal"));
|
512
|
+
case HIT_COND_EQ:
|
513
|
+
return ID2SYM(rb_intern("equal"));
|
514
|
+
case HIT_COND_MOD:
|
515
|
+
return ID2SYM(rb_intern("modulo"));
|
516
|
+
case HIT_COND_NONE:
|
517
|
+
default:
|
518
|
+
return Qnil;
|
519
|
+
}
|
520
|
+
}
|
521
|
+
|
522
|
+
/*
|
523
|
+
* call-seq:
|
524
|
+
* breakpoint.hit_condition = symbol
|
525
|
+
*
|
526
|
+
* Sets the hit condition of the breakpoint which must be one of the following values:
|
527
|
+
*
|
528
|
+
* +nil+ if it is an unconditional breakpoint, or
|
529
|
+
* :greater_or_equal(:ge), :equal(:eq), :modulo(:mod)
|
530
|
+
*/
|
531
|
+
static VALUE
|
532
|
+
breakpoint_set_hit_condition(VALUE self, VALUE value)
|
533
|
+
{
|
534
|
+
debug_breakpoint_t *breakpoint;
|
535
|
+
ID id_value;
|
536
|
+
|
537
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
538
|
+
id_value = rb_to_id(value);
|
539
|
+
|
540
|
+
if(rb_intern("greater_or_equal") == id_value || rb_intern("ge") == id_value)
|
541
|
+
breakpoint->hit_condition = HIT_COND_GE;
|
542
|
+
else if(rb_intern("equal") == id_value || rb_intern("eq") == id_value)
|
543
|
+
breakpoint->hit_condition = HIT_COND_EQ;
|
544
|
+
else if(rb_intern("modulo") == id_value || rb_intern("mod") == id_value)
|
545
|
+
breakpoint->hit_condition = HIT_COND_MOD;
|
546
|
+
else
|
547
|
+
rb_raise(rb_eArgError, "Invalid condition parameter");
|
548
|
+
return value;
|
549
|
+
}
|
550
|
+
|
551
|
+
/*
|
552
|
+
* Document-class: Breakpoint
|
553
|
+
*
|
554
|
+
* == Summary
|
555
|
+
*
|
556
|
+
* This class represents a breakpoint. It defines position of the breakpoint and
|
557
|
+
* condition when this breakpoint should be triggered.
|
558
|
+
*/
|
559
|
+
void
|
560
|
+
Init_breakpoint()
|
561
|
+
{
|
562
|
+
cBreakpoint = rb_define_class_under(mDebugger, "Breakpoint", rb_cObject);
|
563
|
+
rb_define_method(cBreakpoint, "enabled=", breakpoint_set_enabled, 1);
|
564
|
+
rb_define_method(cBreakpoint, "enabled?", breakpoint_enabled, 0);
|
565
|
+
rb_define_method(cBreakpoint, "expr", breakpoint_expr, 0);
|
566
|
+
rb_define_method(cBreakpoint, "expr=", breakpoint_set_expr, 1);
|
567
|
+
rb_define_method(cBreakpoint, "hit_condition", breakpoint_hit_condition, 0);
|
568
|
+
rb_define_method(cBreakpoint, "hit_condition=", breakpoint_set_hit_condition, 1);
|
569
|
+
rb_define_method(cBreakpoint, "hit_count", breakpoint_hit_count, 0);
|
570
|
+
rb_define_method(cBreakpoint, "hit_value", breakpoint_hit_value, 0);
|
571
|
+
rb_define_method(cBreakpoint, "hit_value=", breakpoint_set_hit_value, 1);
|
572
|
+
rb_define_method(cBreakpoint, "id", breakpoint_id, 0);
|
573
|
+
rb_define_method(cBreakpoint, "pos", breakpoint_pos, 0);
|
574
|
+
rb_define_method(cBreakpoint, "pos=", breakpoint_set_pos, 1);
|
575
|
+
rb_define_method(cBreakpoint, "source", breakpoint_source, 0);
|
576
|
+
rb_define_method(cBreakpoint, "source=", breakpoint_set_source, 1);
|
577
|
+
idEval = rb_intern("eval");
|
578
|
+
rdebug_catchpoints = rb_hash_new();
|
579
|
+
|
580
|
+
}
|
581
|
+
|
582
|
+
|
data/ext/ruby_debug.h
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
/* Context info */
|
3
|
+
enum ctx_stop_reason {CTX_STOP_NONE, CTX_STOP_STEP, CTX_STOP_BREAKPOINT,
|
4
|
+
CTX_STOP_CATCHPOINT};
|
5
|
+
|
6
|
+
/* Context flags */
|
7
|
+
#define CTX_FL_SUSPEND (1<<1)
|
8
|
+
#define CTX_FL_TRACING (1<<2)
|
9
|
+
#define CTX_FL_SKIPPED (1<<3)
|
10
|
+
#define CTX_FL_IGNORE (1<<4)
|
11
|
+
#define CTX_FL_DEAD (1<<5)
|
12
|
+
#define CTX_FL_WAS_RUNNING (1<<6)
|
13
|
+
#define CTX_FL_ENABLE_BKPT (1<<7)
|
14
|
+
#define CTX_FL_STEPPED (1<<8)
|
15
|
+
#define CTX_FL_FORCE_MOVE (1<<9)
|
16
|
+
|
17
|
+
#define CTX_FL_TEST(c,f) ((c)->flags & (f))
|
18
|
+
#define CTX_FL_SET(c,f) do { (c)->flags |= (f); } while (0)
|
19
|
+
#define CTX_FL_UNSET(c,f) do { (c)->flags &= ~(f); } while (0)
|
20
|
+
|
21
|
+
typedef struct {
|
22
|
+
int argc; /* Number of arguments a frame should have. */
|
23
|
+
VALUE binding;
|
24
|
+
ID id;
|
25
|
+
ID orig_id;
|
26
|
+
int line;
|
27
|
+
const char * file;
|
28
|
+
short dead;
|
29
|
+
VALUE self;
|
30
|
+
VALUE arg_ary;
|
31
|
+
union {
|
32
|
+
struct {
|
33
|
+
struct FRAME *frame;
|
34
|
+
struct SCOPE *scope;
|
35
|
+
struct RVarmap *dyna_vars;
|
36
|
+
} runtime;
|
37
|
+
struct {
|
38
|
+
VALUE args;
|
39
|
+
VALUE locals;
|
40
|
+
VALUE arg_ary;
|
41
|
+
} copy;
|
42
|
+
} info;
|
43
|
+
} debug_frame_t;
|
44
|
+
|
45
|
+
typedef struct {
|
46
|
+
VALUE thread_id;
|
47
|
+
int thnum;
|
48
|
+
int flags;
|
49
|
+
enum ctx_stop_reason stop_reason;
|
50
|
+
int stop_next;
|
51
|
+
int dest_frame;
|
52
|
+
int stop_line;
|
53
|
+
int stop_frame;
|
54
|
+
int stack_size;
|
55
|
+
int stack_len;
|
56
|
+
debug_frame_t *frames;
|
57
|
+
const char * last_file;
|
58
|
+
int last_line;
|
59
|
+
VALUE breakpoint;
|
60
|
+
} debug_context_t;
|
61
|
+
|
62
|
+
/* variables in ruby_debug.c */
|
63
|
+
extern VALUE mDebugger;
|
64
|
+
extern VALUE rdebug_breakpoints;
|
65
|
+
extern VALUE rdebug_catchpoints;
|
66
|
+
extern VALUE rdebug_threads_tbl;
|
67
|
+
|
68
|
+
/* routines in ruby_debug.c */
|
69
|
+
extern int filename_cmp(VALUE source, char *file);
|
70
|
+
|
71
|
+
#define IS_STARTED (rdebug_threads_tbl != Qnil)
|
72
|
+
static inline void
|
73
|
+
debug_check_started()
|
74
|
+
{
|
75
|
+
if(!IS_STARTED)
|
76
|
+
{
|
77
|
+
rb_raise(rb_eRuntimeError, "Debugger.start is not called yet.");
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
static inline int
|
82
|
+
classname_cmp(VALUE name, VALUE klass)
|
83
|
+
{
|
84
|
+
VALUE class_name = (Qnil == name) ? rb_str_new2("main") : name;
|
85
|
+
return (klass != Qnil
|
86
|
+
&& rb_str_cmp(class_name, rb_mod_name(klass)) == 0);
|
87
|
+
}
|
88
|
+
|
89
|
+
/* Breakpoint information */
|
90
|
+
enum bp_type {BP_POS_TYPE, BP_METHOD_TYPE};
|
91
|
+
enum hit_condition {HIT_COND_NONE, HIT_COND_GE, HIT_COND_EQ, HIT_COND_MOD};
|
92
|
+
|
93
|
+
typedef struct {
|
94
|
+
int id;
|
95
|
+
enum bp_type type;
|
96
|
+
VALUE source;
|
97
|
+
union
|
98
|
+
{
|
99
|
+
int line;
|
100
|
+
ID mid;
|
101
|
+
} pos;
|
102
|
+
VALUE expr;
|
103
|
+
VALUE enabled;
|
104
|
+
int hit_count;
|
105
|
+
int hit_value;
|
106
|
+
enum hit_condition hit_condition;
|
107
|
+
} debug_breakpoint_t;
|
108
|
+
|
109
|
+
/* routines in breakpoint.c */
|
110
|
+
extern int check_breakpoint_expression(VALUE breakpoint, VALUE binding);
|
111
|
+
extern int check_breakpoint_hit_condition(VALUE breakpoint);
|
112
|
+
extern VALUE check_breakpoints_by_method(debug_context_t *debug_context,
|
113
|
+
VALUE klass, ID mid, VALUE self);
|
114
|
+
extern VALUE check_breakpoints_by_pos(debug_context_t *debug_context,
|
115
|
+
char *file, int line);
|
116
|
+
extern VALUE create_breakpoint_from_args(int argc, VALUE *argv, int id);
|
117
|
+
extern VALUE context_breakpoint(VALUE self);
|
118
|
+
extern VALUE context_set_breakpoint(int argc, VALUE *argv, VALUE self);
|
119
|
+
extern VALUE rdebug_add_catchpoint(VALUE self, VALUE value);
|
120
|
+
extern VALUE debug_catchpoints(VALUE self);
|
121
|
+
extern VALUE rdebug_remove_breakpoint(VALUE self, VALUE id_value);
|
122
|
+
|
123
|
+
extern void Init_breakpoint();
|
data/lib/ruby_debug.jar
CHANGED
Binary file
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: ruby-debug-base
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease: 7
|
5
|
-
version: 0.10.5.
|
5
|
+
version: 0.10.5.rc2
|
6
6
|
platform: java
|
7
7
|
authors:
|
8
8
|
- Kent Sibilev
|
@@ -10,8 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date:
|
14
|
-
default_executable:
|
13
|
+
date: 2012-07-19 00:00:00 Z
|
15
14
|
dependencies:
|
16
15
|
- !ruby/object:Gem::Dependency
|
17
16
|
name: linecache
|
@@ -19,13 +18,13 @@ dependencies:
|
|
19
18
|
requirement: &id001 !ruby/object:Gem::Requirement
|
20
19
|
none: false
|
21
20
|
requirements:
|
22
|
-
- -
|
21
|
+
- - ~>
|
23
22
|
- !ruby/object:Gem::Version
|
24
|
-
version: "0.
|
23
|
+
version: "0.46"
|
25
24
|
type: :runtime
|
26
25
|
version_requirements: *id001
|
27
26
|
- !ruby/object:Gem::Dependency
|
28
|
-
name: rake
|
27
|
+
name: rake
|
29
28
|
prerelease: false
|
30
29
|
requirement: &id002 !ruby/object:Gem::Requirement
|
31
30
|
none: false
|
@@ -35,10 +34,32 @@ dependencies:
|
|
35
34
|
version: "0"
|
36
35
|
type: :development
|
37
36
|
version_requirements: *id002
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rdoc
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: "0"
|
46
|
+
type: :development
|
47
|
+
version_requirements: *id003
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rake-compiler
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ~>
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 0.8.1
|
57
|
+
type: :development
|
58
|
+
version_requirements: *id004
|
38
59
|
description: |
|
39
60
|
ruby-debug is a fast implementation of the standard Ruby debugger debug.rb.
|
40
|
-
It is implemented by utilizing a new Ruby C API hook. The core component
|
41
|
-
provides support that front-ends can build on. It provides breakpoint
|
61
|
+
It is implemented by utilizing a new Ruby C API hook. The core component
|
62
|
+
provides support that front-ends can build on. It provides breakpoint
|
42
63
|
handling, bindings for stack frames among other things.
|
43
64
|
|
44
65
|
email: ksibilev@yahoo.com
|
@@ -55,18 +76,14 @@ files:
|
|
55
76
|
- LICENSE
|
56
77
|
- README
|
57
78
|
- Rakefile
|
79
|
+
- ext/breakpoint.c
|
80
|
+
- ext/extconf.rb
|
81
|
+
- ext/ruby_debug.c
|
82
|
+
- ext/ruby_debug.h
|
58
83
|
- lib/ruby-debug-base.rb
|
59
84
|
- lib/ruby-debug-base/version.rb
|
60
|
-
- test/base/base.rb
|
61
|
-
- test/base/binding.rb
|
62
|
-
- test/base/catchpoint.rb
|
63
|
-
- test/base/load.rb
|
64
|
-
- test/base/reload_bug.rb
|
65
|
-
- ext/ruby_debug.c
|
66
|
-
- ext/extconf.rb
|
67
85
|
- lib/ruby_debug.jar
|
68
|
-
|
69
|
-
homepage: http://rubyforge.org/projects/ruby-debug/
|
86
|
+
homepage: https://github.com/ruby-debug/
|
70
87
|
licenses: []
|
71
88
|
|
72
89
|
post_install_message:
|
@@ -79,7 +96,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
79
96
|
requirements:
|
80
97
|
- - ">="
|
81
98
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
99
|
+
version: "0"
|
83
100
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
101
|
none: false
|
85
102
|
requirements:
|
@@ -88,14 +105,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
105
|
version: 1.3.1
|
89
106
|
requirements: []
|
90
107
|
|
91
|
-
rubyforge_project:
|
92
|
-
rubygems_version: 1.
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 1.8.24
|
93
110
|
signing_key:
|
94
111
|
specification_version: 3
|
95
112
|
summary: Fast Ruby debugger - core component
|
96
|
-
test_files:
|
97
|
-
|
98
|
-
- test/base/binding.rb
|
99
|
-
- test/base/catchpoint.rb
|
100
|
-
- test/base/load.rb
|
101
|
-
- test/base/reload_bug.rb
|
113
|
+
test_files: []
|
114
|
+
|
data/test/base/base.rb
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require File.expand_path("../../helper", __FILE__)
|
3
|
-
|
4
|
-
# Some tests of Debugger module in C extension ruby_debug
|
5
|
-
class TestRubyDebug < Test::Unit::TestCase
|
6
|
-
def test_version
|
7
|
-
assert(defined?(Debugger::VERSION))
|
8
|
-
end
|
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
|
-
ensure
|
30
|
-
Debugger.stop
|
31
|
-
assert_equal(false, Debugger.started?,
|
32
|
-
'Debugger should no longer be started.')
|
33
|
-
end
|
34
|
-
|
35
|
-
# Test initial variables and setting/getting state.
|
36
|
-
def test_debugger_base
|
37
|
-
assert_equal(false, Debugger.started?,
|
38
|
-
'Debugger should not initially be started.')
|
39
|
-
Debugger.start_
|
40
|
-
assert(Debugger.started?,
|
41
|
-
'Debugger should now be started.')
|
42
|
-
assert_equal(false, Debugger.debug,
|
43
|
-
'Debug variable should not be set.')
|
44
|
-
assert_equal(false, Debugger.post_mortem?,
|
45
|
-
'Post mortem debugging should not be set.')
|
46
|
-
a = Debugger.contexts
|
47
|
-
assert_equal(1, a.size,
|
48
|
-
'There should only be one context.')
|
49
|
-
assert_equal(Array, a.class,
|
50
|
-
'Context should be an array.')
|
51
|
-
ensure
|
52
|
-
Debugger.stop
|
53
|
-
assert_equal(false, Debugger.started?,
|
54
|
-
'debugger should no longer be started.')
|
55
|
-
end
|
56
|
-
|
57
|
-
# Test breakpoint handling
|
58
|
-
def test_breakpoints
|
59
|
-
Debugger.start_
|
60
|
-
assert_equal(0, Debugger.breakpoints.size,
|
61
|
-
'There should not be any breakpoints set.')
|
62
|
-
brk = Debugger.add_breakpoint(__FILE__, 1)
|
63
|
-
assert_equal(Debugger::Breakpoint, brk.class,
|
64
|
-
'Breakpoint should have been set and returned.')
|
65
|
-
assert_equal(1, Debugger.breakpoints.size,
|
66
|
-
'There should now be one breakpoint set.')
|
67
|
-
Debugger.remove_breakpoint(0)
|
68
|
-
assert_equal(1, Debugger.breakpoints.size,
|
69
|
-
'There should still be one breakpoint set.')
|
70
|
-
Debugger.remove_breakpoint(1)
|
71
|
-
assert_equal(0, Debugger.breakpoints.size,
|
72
|
-
'There should no longer be any breakpoints set.')
|
73
|
-
ensure
|
74
|
-
Debugger.stop
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
data/test/base/binding.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require File.expand_path("../../helper", __FILE__)
|
3
|
-
|
4
|
-
# Test binding_n command
|
5
|
-
class TestBinding < Test::Unit::TestCase
|
6
|
-
def test_basic
|
7
|
-
def inside_fn
|
8
|
-
s = 'some other string'
|
9
|
-
b2 = Kernel::binding_n(1)
|
10
|
-
y2 = eval('s', b2)
|
11
|
-
assert_equal('this is a test', y2)
|
12
|
-
end
|
13
|
-
s = 'this is a test'
|
14
|
-
Debugger.start
|
15
|
-
b = Kernel::binding_n(0)
|
16
|
-
y = eval('s', b)
|
17
|
-
assert_equal(s, y)
|
18
|
-
inside_fn
|
19
|
-
ensure
|
20
|
-
Debugger.stop
|
21
|
-
end
|
22
|
-
end
|
data/test/base/catchpoint.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require File.expand_path("../../helper", __FILE__)
|
3
|
-
|
4
|
-
# Test catchpoint in C ruby_debug extension.
|
5
|
-
|
6
|
-
class TestRubyDebugCatchpoint < Test::Unit::TestCase
|
7
|
-
def test_catchpoints
|
8
|
-
assert_raise(RuntimeError) {Debugger.catchpoints}
|
9
|
-
Debugger.start_
|
10
|
-
assert_equal({}, Debugger.catchpoints)
|
11
|
-
Debugger.add_catchpoint('ZeroDivisionError')
|
12
|
-
assert_equal({'ZeroDivisionError' => 0}, Debugger.catchpoints)
|
13
|
-
Debugger.add_catchpoint('RuntimeError')
|
14
|
-
assert_equal(['RuntimeError', 'ZeroDivisionError'],
|
15
|
-
Debugger.catchpoints.keys.sort)
|
16
|
-
ensure
|
17
|
-
Debugger.stop
|
18
|
-
end
|
19
|
-
end
|
data/test/base/load.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require File.expand_path("../../helper", __FILE__)
|
3
|
-
|
4
|
-
# Test of Debugger.debug_load in C extension ruby_debug.so
|
5
|
-
class TestDebugLoad < Test::Unit::TestCase
|
6
|
-
class << self
|
7
|
-
def at_line(file, line)
|
8
|
-
@@at_line = [File.basename(file), line]
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
class Debugger::Context
|
13
|
-
def at_line(file, line)
|
14
|
-
TestDebugLoad::at_line(file, line)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def test_debug_load
|
19
|
-
src_dir = File.dirname(__FILE__)
|
20
|
-
prog_script = File.join(src_dir, '..', 'example', 'gcd.rb')
|
21
|
-
|
22
|
-
# Without stopping
|
23
|
-
bt = Debugger.debug_load(prog_script, false)
|
24
|
-
assert_equal(nil, bt)
|
25
|
-
assert(Debugger.started?)
|
26
|
-
Debugger.stop
|
27
|
-
|
28
|
-
# With stopping
|
29
|
-
bt = Debugger.debug_load(prog_script, true)
|
30
|
-
assert_equal(nil, bt)
|
31
|
-
assert_equal(['gcd.rb', 4], @@at_line)
|
32
|
-
assert(Debugger.started?)
|
33
|
-
Debugger.stop
|
34
|
-
|
35
|
-
# Test that we get a proper backtrace on a script that raises 'abc'
|
36
|
-
prog_script = File.join(src_dir, '..', 'example', 'raise.rb')
|
37
|
-
bt = Debugger.debug_load(prog_script, false)
|
38
|
-
assert_equal('abc', bt.to_s)
|
39
|
-
assert(Debugger.started?)
|
40
|
-
Debugger.stop
|
41
|
-
ensure
|
42
|
-
Debugger.stop if Debugger.started?
|
43
|
-
end
|
44
|
-
end
|