ruby-debug-base19 0.11.15

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,261 @@
1
+ #!/usr/bin/env rake
2
+ # -*- Ruby -*-
3
+ require 'rubygems'
4
+ require 'rake/gempackagetask'
5
+ require 'rake/rdoctask'
6
+ require 'rake/testtask'
7
+ require 'rake/extensiontask'
8
+
9
+ Rake::ExtensionTask.new('ruby_debug')
10
+
11
+ SO_NAME = "ruby_debug.so"
12
+
13
+ # ------- Default Package ----------
14
+ RUBY_DEBUG_VERSION = open("ext/ruby_debug/ruby_debug.c") do |f|
15
+ f.grep(/^#define DEBUG_VERSION/).first[/"(.+)"/,1]
16
+ end
17
+
18
+ COMMON_FILES = FileList[
19
+ 'AUTHORS',
20
+ 'CHANGES',
21
+ 'LICENSE',
22
+ 'README',
23
+ 'Rakefile',
24
+ ]
25
+
26
+ CLI_TEST_FILE_LIST = FileList['test/cli/commands/unit/*.rb',
27
+ 'test/cli/commands/*_test.rb',
28
+ 'test/cli/**/*_test.rb',
29
+ 'test/test-*.rb']
30
+ CLI_FILES = COMMON_FILES + FileList[
31
+ "cli/**/*",
32
+ 'ChangeLog',
33
+ 'bin/*',
34
+ 'doc/rdebug.1',
35
+ 'test/**/data/*.cmd',
36
+ 'test/**/data/*.right',
37
+ 'test/**/*.rb',
38
+ 'rdbg.rb',
39
+ CLI_TEST_FILE_LIST
40
+ ]
41
+
42
+ BASE_TEST_FILE_LIST = %w(
43
+ test/base/base.rb
44
+ test/base/binding.rb
45
+ test/base/catchpoint.rb)
46
+ BASE_FILES = COMMON_FILES + FileList[
47
+ 'ext/ruby_debug/breakpoint.c',
48
+ 'ext/ruby_debug/extconf.rb',
49
+ 'ext/ruby_debug/ruby_debug.c',
50
+ 'ext/ruby_debug/ruby_debug.h',
51
+ 'ext/win32/*',
52
+ 'lib/**/*',
53
+ BASE_TEST_FILE_LIST,
54
+ ]
55
+
56
+ desc "Test everything."
57
+ task :test => :test_base do
58
+ Rake::TestTask.new(:test) do |t|
59
+ t.libs << './ext'
60
+ t.libs << './lib'
61
+ t.libs << './cli'
62
+ t.test_files = CLI_TEST_FILE_LIST
63
+ t.verbose = true
64
+ end
65
+ end
66
+
67
+ desc "Test ruby-debug-base."
68
+ task :test_base => :lib do
69
+ Rake::TestTask.new(:test_base) do |t|
70
+ t.libs << './ext'
71
+ t.libs << './lib'
72
+ t.test_files = FileList[BASE_TEST_FILE_LIST]
73
+ t.verbose = true
74
+ end
75
+ end
76
+
77
+ desc "Test everything - same as test."
78
+ task :check => :test
79
+
80
+ desc "Create the core ruby-debug shared library extension"
81
+ task :lib do
82
+ Dir.chdir("ext") do
83
+ system("#{Gem.ruby} extconf.rb && make")
84
+ end
85
+ end
86
+
87
+ desc "Compile Emacs code"
88
+ task :emacs => "emacs/rdebug.elc"
89
+ file "emacs/rdebug.elc" => ["emacs/elisp-comp", "emacs/rdebug.el"] do
90
+ Dir.chdir("emacs") do
91
+ system("./elisp-comp ./rdebug.el")
92
+ end
93
+ end
94
+
95
+ desc "Create a GNU-style ChangeLog via svn2cl"
96
+ task :ChangeLog do
97
+ system("svn2cl --authors=svn2cl_usermap svn://rubyforge.org/var/svn/ruby-debug/trunk")
98
+ system("svn2cl --authors=svn2cl_usermap svn://rubyforge.org/var/svn/ruby-debug/trunk/ext -o ext/ChangeLog")
99
+ system("svn2cl --authors=svn2cl_usermap svn://rubyforge.org/var/svn/ruby-debug/trunk/lib -o lib/ChangeLog")
100
+ end
101
+
102
+ # Base GEM Specification
103
+ base_spec = Gem::Specification.new do |spec|
104
+ spec.name = "ruby-debug-base"
105
+
106
+ spec.homepage = "http://rubyforge.org/projects/ruby-debug/"
107
+ spec.summary = "Fast Ruby debugger - core component"
108
+ spec.description = <<-EOF
109
+ ruby-debug is a fast implementation of the standard Ruby debugger debug.rb.
110
+ It is implemented by utilizing a new Ruby C API hook. The core component
111
+ provides support that front-ends can build on. It provides breakpoint
112
+ handling, bindings for stack frames among other things.
113
+ EOF
114
+
115
+ spec.version = RUBY_DEBUG_VERSION
116
+
117
+ spec.author = "Kent Sibilev"
118
+ spec.email = "ksibilev@yahoo.com"
119
+ spec.platform = Gem::Platform::RUBY
120
+ spec.require_path = "lib"
121
+ spec.extensions = ["ext/extconf.rb"]
122
+ spec.files = BASE_FILES.to_a
123
+
124
+ spec.required_ruby_version = '>= 1.8.2'
125
+ spec.date = Time.now
126
+ spec.rubyforge_project = 'ruby-debug'
127
+ spec.add_dependency('linecache', '>= 0.3')
128
+
129
+ spec.test_files = FileList[BASE_TEST_FILE_LIST]
130
+
131
+ # rdoc
132
+ spec.has_rdoc = true
133
+ spec.extra_rdoc_files = ['README', 'ext/ruby_debug/ruby_debug.c']
134
+ end
135
+
136
+ cli_spec = Gem::Specification.new do |spec|
137
+ spec.name = "ruby-debug"
138
+
139
+ spec.homepage = "http://rubyforge.org/projects/ruby-debug/"
140
+ spec.summary = "Command line interface (CLI) for ruby-debug-base"
141
+ spec.description = <<-EOF
142
+ A generic command line interface for ruby-debug.
143
+ EOF
144
+
145
+ spec.version = RUBY_DEBUG_VERSION
146
+
147
+ spec.author = "Kent Sibilev"
148
+ spec.email = "ksibilev@yahoo.com"
149
+ spec.platform = Gem::Platform::RUBY
150
+ spec.require_path = "cli"
151
+ spec.bindir = "bin"
152
+ spec.executables = ["rdebug"]
153
+ spec.files = CLI_FILES.to_a
154
+
155
+ spec.required_ruby_version = '>= 1.8.2'
156
+ spec.date = Time.now
157
+ spec.rubyforge_project = 'ruby-debug'
158
+ spec.add_dependency('columnize', '>= 0.1')
159
+ spec.add_dependency('ruby-debug-base', "~> #{RUBY_DEBUG_VERSION}.0")
160
+
161
+ # FIXME: work out operational logistics for this
162
+ # spec.test_files = FileList[CLI_TEST_FILE_LIST]
163
+
164
+ # rdoc
165
+ spec.has_rdoc = true
166
+ spec.extra_rdoc_files = ['README']
167
+ end
168
+
169
+ # Rake task to build the default package
170
+ Rake::GemPackageTask.new(base_spec) do |pkg|
171
+ pkg.need_tar = true
172
+ end
173
+ Rake::GemPackageTask.new(cli_spec) do |pkg|
174
+ pkg.need_tar = true
175
+ end
176
+
177
+ task :default => [:package]
178
+
179
+ # Windows specification
180
+ win_spec = base_spec.clone
181
+ win_spec.extensions = []
182
+ ## win_spec.platform = Gem::Platform::WIN32 # deprecated
183
+ win_spec.platform = 'mswin32'
184
+ win_spec.files += ["lib/#{SO_NAME}"]
185
+
186
+ desc "Create Windows Gem"
187
+ task :win32_gem do
188
+ # Copy the win32 extension the top level directory
189
+ current_dir = File.expand_path(File.dirname(__FILE__))
190
+ source = File.join(current_dir, "ext", "win32", SO_NAME)
191
+ target = File.join(current_dir, "lib", SO_NAME)
192
+ cp(source, target)
193
+
194
+ # Create the gem, then move it to pkg.
195
+ Gem::Builder.new(win_spec).build
196
+ gem_file = "#{win_spec.name}-#{win_spec.version}-#{win_spec.platform}.gem"
197
+ mv(gem_file, "pkg/#{gem_file}")
198
+
199
+ # Remove win extension from top level directory.
200
+ rm(target)
201
+ end
202
+
203
+ desc "Publish ruby-debug to RubyForge."
204
+ task :publish do
205
+ require 'rake/contrib/sshpublisher'
206
+
207
+ # Get ruby-debug path.
208
+ ruby_debug_path = File.expand_path(File.dirname(__FILE__))
209
+
210
+ Rake::SshDirPublisher.new("kent@rubyforge.org",
211
+ "/var/www/gforge-projects/ruby-debug", ruby_debug_path)
212
+ end
213
+
214
+ desc "Remove built files"
215
+ task :clean do
216
+ cd "ext" do
217
+ if File.exists?("Makefile")
218
+ sh "make clean"
219
+ rm "Makefile"
220
+ end
221
+ derived_files = Dir.glob(".o") + Dir.glob("*.so")
222
+ rm derived_files unless derived_files.empty?
223
+ end
224
+ end
225
+
226
+ # --------- RDoc Documentation ------
227
+ desc "Generate rdoc documentation"
228
+ Rake::RDocTask.new("rdoc") do |rdoc|
229
+ rdoc.rdoc_dir = 'doc/rdoc'
230
+ rdoc.title = "ruby-debug"
231
+ # Show source inline with line numbers
232
+ rdoc.options << "--inline-source" << "--line-numbers"
233
+ # Make the readme file the start page for the generated html
234
+ rdoc.options << '--main' << 'README'
235
+ rdoc.rdoc_files.include('bin/**/*',
236
+ 'cli/ruby-debug/commands/*.rb',
237
+ 'lib/**/*.rb',
238
+ 'ext/**/ruby_debug.c',
239
+ 'README',
240
+ 'LICENSE')
241
+ end
242
+
243
+ desc "Publish the release files to RubyForge."
244
+ task :rubyforge_upload do
245
+ `rubyforge login`
246
+ release_command = "rubyforge add_release #{PKG_NAME} #{PKG_NAME} '#{PKG_NAME}-#{PKG_VERSION}' pkg/#{PKG_NAME}-#{PKG_VERSION}.gem"
247
+ puts release_command
248
+ system(release_command)
249
+ end
250
+
251
+ PKG_NAME = 'ruby-debug'
252
+ desc "Publish the release files to RubyForge."
253
+ task :rubyforge_upload do
254
+ `rubyforge login`
255
+ for pkg_name in ['ruby-debug', 'ruby-debug-base'] do
256
+ pkg_file_name = "#{pkg_name}-#{pkg_version}"
257
+ release_command = "rubyforge add_release ruby-debug #{pkg_name} '#{pkg_file_name}' pkg/#{pkg_file_name}.gem"
258
+ puts release_command
259
+ system(release_command)
260
+ end
261
+ end
@@ -0,0 +1,587 @@
1
+ #include <ruby.h>
2
+ #include <stdio.h>
3
+ #include <vm_core.h>
4
+ #include <iseq.h>
5
+ #include "ruby_debug.h"
6
+
7
+ VALUE rdebug_breakpoints = Qnil;
8
+ VALUE rdebug_catchpoints;
9
+
10
+ static VALUE cBreakpoint;
11
+ static ID idEval;
12
+
13
+ static VALUE
14
+ eval_expression(VALUE args)
15
+ {
16
+ return rb_funcall2(rb_mKernel, idEval, 2, RARRAY_PTR(args));
17
+ }
18
+
19
+ int
20
+ check_breakpoint_hit_condition(VALUE breakpoint)
21
+ {
22
+ debug_breakpoint_t *debug_breakpoint;
23
+
24
+ if(breakpoint == Qnil)
25
+ return 0;
26
+ Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
27
+
28
+ debug_breakpoint->hit_count++;
29
+ if (!Qtrue == debug_breakpoint->enabled) return 0;
30
+ switch(debug_breakpoint->hit_condition)
31
+ {
32
+ case HIT_COND_NONE:
33
+ return 1;
34
+ case HIT_COND_GE:
35
+ {
36
+ if(debug_breakpoint->hit_count >= debug_breakpoint->hit_value)
37
+ return 1;
38
+ break;
39
+ }
40
+ case HIT_COND_EQ:
41
+ {
42
+ if(debug_breakpoint->hit_count == debug_breakpoint->hit_value)
43
+ return 1;
44
+ break;
45
+ }
46
+ case HIT_COND_MOD:
47
+ {
48
+ if(debug_breakpoint->hit_count % debug_breakpoint->hit_value == 0)
49
+ return 1;
50
+ break;
51
+ }
52
+ }
53
+ return 0;
54
+ }
55
+
56
+ static int
57
+ check_breakpoint_by_pos(VALUE breakpoint, char *file, int line)
58
+ {
59
+ debug_breakpoint_t *debug_breakpoint;
60
+
61
+ if(breakpoint == Qnil)
62
+ return 0;
63
+ Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
64
+ if (!Qtrue == debug_breakpoint->enabled) return 0;
65
+ if(debug_breakpoint->type != BP_POS_TYPE)
66
+ return 0;
67
+ if(debug_breakpoint->pos.line != line)
68
+ return 0;
69
+ if(filename_cmp(debug_breakpoint->source, file))
70
+ return 1;
71
+ return 0;
72
+ }
73
+
74
+ extern VALUE g_self;
75
+ int
76
+ check_breakpoint_by_method(VALUE breakpoint, VALUE klass, ID mid, VALUE self)
77
+ {
78
+ debug_breakpoint_t *debug_breakpoint;
79
+
80
+ if(breakpoint == Qnil)
81
+ return 0;
82
+ Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
83
+ if (!Qtrue == debug_breakpoint->enabled) return 0;
84
+ if(debug_breakpoint->type != BP_METHOD_TYPE)
85
+ return 0;
86
+ if(debug_breakpoint->pos.mid != mid)
87
+ return 0;
88
+ if(classname_cmp(debug_breakpoint->source, klass))
89
+ return 1;
90
+ if ((rb_type(self) == T_CLASS) &&
91
+ classname_cmp(debug_breakpoint->source, self))
92
+ return 1;
93
+ return 0;
94
+ }
95
+
96
+ VALUE
97
+ check_breakpoints_by_pos(debug_context_t *debug_context, char *file, int line)
98
+ {
99
+ VALUE breakpoint;
100
+ int i;
101
+
102
+ if(!CTX_FL_TEST(debug_context, CTX_FL_ENABLE_BKPT))
103
+ return Qnil;
104
+
105
+ if(check_breakpoint_by_pos(debug_context->breakpoint, file, line))
106
+ return debug_context->breakpoint;
107
+
108
+ if(RARRAY_LEN(rdebug_breakpoints) == 0)
109
+ return Qnil;
110
+ for(i = 0; i < RARRAY_LEN(rdebug_breakpoints); i++)
111
+ {
112
+ breakpoint = rb_ary_entry(rdebug_breakpoints, i);
113
+ if(check_breakpoint_by_pos(breakpoint, file, line))
114
+ return breakpoint;
115
+ }
116
+ return Qnil;
117
+ }
118
+
119
+ VALUE
120
+ check_breakpoints_by_method(debug_context_t *debug_context, VALUE klass, ID mid, VALUE self)
121
+ {
122
+ VALUE breakpoint;
123
+ int i;
124
+
125
+ if(!CTX_FL_TEST(debug_context, CTX_FL_ENABLE_BKPT))
126
+ return Qnil;
127
+
128
+ if(check_breakpoint_by_method(debug_context->breakpoint, klass, mid, self))
129
+ return debug_context->breakpoint;
130
+
131
+ if(RARRAY_LEN(rdebug_breakpoints) == 0)
132
+ return Qnil;
133
+ for(i = 0; i < RARRAY_LEN(rdebug_breakpoints); i++)
134
+ {
135
+ breakpoint = rb_ary_entry(rdebug_breakpoints, i);
136
+ if(check_breakpoint_by_method(breakpoint, klass, mid, self))
137
+ return breakpoint;
138
+ }
139
+ return Qnil;
140
+ }
141
+
142
+ int
143
+ check_breakpoint_expression(VALUE breakpoint, VALUE binding)
144
+ {
145
+ debug_breakpoint_t *debug_breakpoint;
146
+ VALUE args, expr_result;
147
+
148
+ Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
149
+ if(NIL_P(debug_breakpoint->expr))
150
+ return 1;
151
+
152
+ args = rb_ary_new3(2, debug_breakpoint->expr, binding);
153
+ expr_result = rb_protect(eval_expression, args, 0);
154
+ return RTEST(expr_result);
155
+ }
156
+
157
+ static void
158
+ breakpoint_mark(void *data)
159
+ {
160
+ debug_breakpoint_t *breakpoint;
161
+ breakpoint = (debug_breakpoint_t *)data;
162
+ rb_gc_mark(breakpoint->source);
163
+ rb_gc_mark(breakpoint->expr);
164
+ }
165
+
166
+ VALUE
167
+ create_breakpoint_from_args(int argc, VALUE *argv, int id)
168
+ {
169
+ VALUE source, pos, expr;
170
+ debug_breakpoint_t *breakpoint;
171
+ int type;
172
+
173
+ if(rb_scan_args(argc, argv, "21", &source, &pos, &expr) == 2)
174
+ {
175
+ expr = Qnil;
176
+ }
177
+ type = FIXNUM_P(pos) ? BP_POS_TYPE : BP_METHOD_TYPE;
178
+ if(type == BP_POS_TYPE)
179
+ source = StringValue(source);
180
+ else
181
+ pos = StringValue(pos);
182
+ breakpoint = ALLOC(debug_breakpoint_t);
183
+ breakpoint->id = id;
184
+ breakpoint->source = source;
185
+ breakpoint->type = type;
186
+ if(type == BP_POS_TYPE)
187
+ breakpoint->pos.line = FIX2INT(pos);
188
+ else
189
+ breakpoint->pos.mid = rb_intern(RSTRING_PTR(pos));
190
+ breakpoint->enabled = Qtrue;
191
+ breakpoint->expr = NIL_P(expr) ? expr: StringValue(expr);
192
+ breakpoint->hit_count = 0;
193
+ breakpoint->hit_value = 0;
194
+ breakpoint->hit_condition = HIT_COND_NONE;
195
+ return Data_Wrap_Struct(cBreakpoint, breakpoint_mark, xfree, breakpoint);
196
+ }
197
+
198
+ /*
199
+ * call-seq:
200
+ * Debugger.remove_breakpoint(id) -> breakpoint
201
+ *
202
+ * Removes breakpoint by its id.
203
+ * <i>id</i> is an identificator of a breakpoint.
204
+ */
205
+ VALUE
206
+ rdebug_remove_breakpoint(VALUE self, VALUE id_value)
207
+ {
208
+ int i;
209
+ int id;
210
+ VALUE breakpoint;
211
+ debug_breakpoint_t *debug_breakpoint;
212
+
213
+ id = FIX2INT(id_value);
214
+
215
+ for( i = 0; i < RARRAY_LEN(rdebug_breakpoints); i += 1 )
216
+ {
217
+ breakpoint = rb_ary_entry(rdebug_breakpoints, i);
218
+ Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
219
+ if(debug_breakpoint->id == id)
220
+ {
221
+ rb_ary_delete_at(rdebug_breakpoints, i);
222
+ return breakpoint;
223
+ }
224
+ }
225
+ return Qnil;
226
+ }
227
+
228
+ /*
229
+ * call-seq:
230
+ * Debugger.catchpoints -> hash
231
+ *
232
+ * Returns a current catchpoints, which is a hash exception names that will
233
+ * trigger a debugger when raised. The values are the number of times taht
234
+ * catchpoint was hit, initially 0.
235
+ */
236
+ VALUE
237
+ debug_catchpoints(VALUE self)
238
+ {
239
+ debug_check_started();
240
+
241
+ return rdebug_catchpoints;
242
+ }
243
+
244
+ /*
245
+ * call-seq:
246
+ * Debugger.catchpoint(string) -> string
247
+ *
248
+ * Sets catchpoint. Returns the string passed.
249
+ */
250
+ VALUE
251
+ rdebug_add_catchpoint(VALUE self, VALUE value)
252
+ {
253
+ debug_check_started();
254
+
255
+ if (TYPE(value) != T_STRING) {
256
+ rb_raise(rb_eTypeError, "value of a catchpoint must be String");
257
+ }
258
+ rb_hash_aset(rdebug_catchpoints, rb_str_dup(value), INT2FIX(0));
259
+ return value;
260
+ }
261
+
262
+ /*
263
+ * call-seq:
264
+ * context.breakpoint -> breakpoint
265
+ *
266
+ * Returns a context-specific temporary Breakpoint object.
267
+ */
268
+ VALUE
269
+ context_breakpoint(VALUE self)
270
+ {
271
+ debug_context_t *debug_context;
272
+
273
+ debug_check_started();
274
+
275
+ Data_Get_Struct(self, debug_context_t, debug_context);
276
+ return debug_context->breakpoint;
277
+ }
278
+
279
+ /*
280
+ * call-seq:
281
+ * context.set_breakpoint(source, pos, condition = nil) -> breakpoint
282
+ *
283
+ * Sets a context-specific temporary breakpoint, which can be used to implement
284
+ * 'Run to Cursor' debugger function. When this breakpoint is reached, it will be
285
+ * cleared out.
286
+ *
287
+ * <i>source</i> is a name of a file or a class.
288
+ * <i>pos</i> is a line number or a method name if <i>source</i> is a class name.
289
+ * <i>condition</i> is a string which is evaluated to +true+ when this breakpoint
290
+ * is activated.
291
+ */
292
+ VALUE
293
+ context_set_breakpoint(int argc, VALUE *argv, VALUE self)
294
+ {
295
+ VALUE result;
296
+ debug_context_t *debug_context;
297
+
298
+ debug_check_started();
299
+
300
+ Data_Get_Struct(self, debug_context_t, debug_context);
301
+ result = create_breakpoint_from_args(argc, argv, 0);
302
+ debug_context->breakpoint = result;
303
+ return result;
304
+ }
305
+
306
+ /*
307
+ * call-seq:
308
+ * breakpoint.enabled?
309
+ *
310
+ * Returns whether breakpoint is enabled or not.
311
+ */
312
+ static VALUE
313
+ breakpoint_enabled(VALUE self)
314
+ {
315
+ debug_breakpoint_t *breakpoint;
316
+
317
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
318
+ return breakpoint->enabled;
319
+ }
320
+
321
+ /*
322
+ * call-seq:
323
+ * breakpoint.enabled = bool
324
+ *
325
+ * Enables or disables breakpoint.
326
+ */
327
+ static VALUE
328
+ breakpoint_set_enabled(VALUE self, VALUE bool)
329
+ {
330
+ debug_breakpoint_t *breakpoint;
331
+
332
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
333
+ return breakpoint->enabled = bool;
334
+ }
335
+
336
+ /*
337
+ * call-seq:
338
+ * breakpoint.source -> string
339
+ *
340
+ * Returns a source of the breakpoint.
341
+ */
342
+ static VALUE
343
+ breakpoint_source(VALUE self)
344
+ {
345
+ debug_breakpoint_t *breakpoint;
346
+
347
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
348
+ return breakpoint->source;
349
+ }
350
+
351
+ /*
352
+ * call-seq:
353
+ * breakpoint.source = string
354
+ *
355
+ * Sets the source of the breakpoint.
356
+ */
357
+ static VALUE
358
+ breakpoint_set_source(VALUE self, VALUE value)
359
+ {
360
+ debug_breakpoint_t *breakpoint;
361
+
362
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
363
+ breakpoint->source = StringValue(value);
364
+ return value;
365
+ }
366
+
367
+ /*
368
+ * call-seq:
369
+ * breakpoint.pos -> string or int
370
+ *
371
+ * Returns the position of this breakpoint.
372
+ */
373
+ static VALUE
374
+ breakpoint_pos(VALUE self)
375
+ {
376
+ debug_breakpoint_t *breakpoint;
377
+
378
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
379
+ if(breakpoint->type == BP_METHOD_TYPE)
380
+ return rb_str_new2(rb_id2name(breakpoint->pos.mid));
381
+ else
382
+ return INT2FIX(breakpoint->pos.line);
383
+ }
384
+
385
+ /*
386
+ * call-seq:
387
+ * breakpoint.pos = string or int
388
+ *
389
+ * Sets the position of this breakpoint.
390
+ */
391
+ static VALUE
392
+ breakpoint_set_pos(VALUE self, VALUE value)
393
+ {
394
+ debug_breakpoint_t *breakpoint;
395
+
396
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
397
+ if(breakpoint->type == BP_METHOD_TYPE)
398
+ {
399
+ breakpoint->pos.mid = rb_to_id(StringValue(value));
400
+ }
401
+ else
402
+ breakpoint->pos.line = FIX2INT(value);
403
+ return value;
404
+ }
405
+
406
+ /*
407
+ * call-seq:
408
+ * breakpoint.expr -> string
409
+ *
410
+ * Returns a codition expression when this breakpoint should be activated.
411
+ */
412
+ static VALUE
413
+ breakpoint_expr(VALUE self)
414
+ {
415
+ debug_breakpoint_t *breakpoint;
416
+
417
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
418
+ return breakpoint->expr;
419
+ }
420
+
421
+ /*
422
+ * call-seq:
423
+ * breakpoint.expr = string | nil
424
+ *
425
+ * Sets the codition expression when this breakpoint should be activated.
426
+ */
427
+ static VALUE
428
+ breakpoint_set_expr(VALUE self, VALUE expr)
429
+ {
430
+ debug_breakpoint_t *breakpoint;
431
+
432
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
433
+ breakpoint->expr = NIL_P(expr) ? expr: StringValue(expr);
434
+ return expr;
435
+ }
436
+
437
+ /*
438
+ * call-seq:
439
+ * breakpoint.id -> int
440
+ *
441
+ * Returns id of the breakpoint.
442
+ */
443
+ static VALUE
444
+ breakpoint_id(VALUE self)
445
+ {
446
+ debug_breakpoint_t *breakpoint;
447
+
448
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
449
+ return INT2FIX(breakpoint->id);
450
+ }
451
+
452
+ /*
453
+ * call-seq:
454
+ * breakpoint.hit_count -> int
455
+ *
456
+ * Returns the hit count of the breakpoint.
457
+ */
458
+ static VALUE
459
+ breakpoint_hit_count(VALUE self)
460
+ {
461
+ debug_breakpoint_t *breakpoint;
462
+
463
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
464
+ return INT2FIX(breakpoint->hit_count);
465
+ }
466
+
467
+ /*
468
+ * call-seq:
469
+ * breakpoint.hit_value -> int
470
+ *
471
+ * Returns the hit value of the breakpoint.
472
+ */
473
+ static VALUE
474
+ breakpoint_hit_value(VALUE self)
475
+ {
476
+ debug_breakpoint_t *breakpoint;
477
+
478
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
479
+ return INT2FIX(breakpoint->hit_value);
480
+ }
481
+
482
+ /*
483
+ * call-seq:
484
+ * breakpoint.hit_value = int
485
+ *
486
+ * Sets the hit value of the breakpoint.
487
+ */
488
+ static VALUE
489
+ breakpoint_set_hit_value(VALUE self, VALUE value)
490
+ {
491
+ debug_breakpoint_t *breakpoint;
492
+
493
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
494
+ breakpoint->hit_value = FIX2INT(value);
495
+ return value;
496
+ }
497
+
498
+ /*
499
+ * call-seq:
500
+ * breakpoint.hit_condition -> symbol
501
+ *
502
+ * Returns the hit condition of the breakpoint:
503
+ *
504
+ * +nil+ if it is an unconditional breakpoint, or
505
+ * :greater_or_equal, :equal, :modulo
506
+ */
507
+ static VALUE
508
+ breakpoint_hit_condition(VALUE self)
509
+ {
510
+ debug_breakpoint_t *breakpoint;
511
+
512
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
513
+ switch(breakpoint->hit_condition)
514
+ {
515
+ case HIT_COND_GE:
516
+ return ID2SYM(rb_intern("greater_or_equal"));
517
+ case HIT_COND_EQ:
518
+ return ID2SYM(rb_intern("equal"));
519
+ case HIT_COND_MOD:
520
+ return ID2SYM(rb_intern("modulo"));
521
+ case HIT_COND_NONE:
522
+ default:
523
+ return Qnil;
524
+ }
525
+ }
526
+
527
+ /*
528
+ * call-seq:
529
+ * breakpoint.hit_condition = symbol
530
+ *
531
+ * Sets the hit condition of the breakpoint which must be one of the following values:
532
+ *
533
+ * +nil+ if it is an unconditional breakpoint, or
534
+ * :greater_or_equal(:ge), :equal(:eq), :modulo(:mod)
535
+ */
536
+ static VALUE
537
+ breakpoint_set_hit_condition(VALUE self, VALUE value)
538
+ {
539
+ debug_breakpoint_t *breakpoint;
540
+ ID id_value;
541
+
542
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
543
+ id_value = rb_to_id(value);
544
+
545
+ if(rb_intern("greater_or_equal") == id_value || rb_intern("ge") == id_value)
546
+ breakpoint->hit_condition = HIT_COND_GE;
547
+ else if(rb_intern("equal") == id_value || rb_intern("eq") == id_value)
548
+ breakpoint->hit_condition = HIT_COND_EQ;
549
+ else if(rb_intern("modulo") == id_value || rb_intern("mod") == id_value)
550
+ breakpoint->hit_condition = HIT_COND_MOD;
551
+ else
552
+ rb_raise(rb_eArgError, "Invalid condition parameter");
553
+ return value;
554
+ }
555
+
556
+ /*
557
+ * Document-class: Breakpoint
558
+ *
559
+ * == Summary
560
+ *
561
+ * This class represents a breakpoint. It defines position of the breakpoint and
562
+ * condition when this breakpoint should be triggered.
563
+ */
564
+ void
565
+ Init_breakpoint()
566
+ {
567
+ cBreakpoint = rb_define_class_under(mDebugger, "Breakpoint", rb_cObject);
568
+ rb_define_method(cBreakpoint, "enabled=", breakpoint_set_enabled, 1);
569
+ rb_define_method(cBreakpoint, "enabled?", breakpoint_enabled, 0);
570
+ rb_define_method(cBreakpoint, "expr", breakpoint_expr, 0);
571
+ rb_define_method(cBreakpoint, "expr=", breakpoint_set_expr, 1);
572
+ rb_define_method(cBreakpoint, "hit_condition", breakpoint_hit_condition, 0);
573
+ rb_define_method(cBreakpoint, "hit_condition=", breakpoint_set_hit_condition, 1);
574
+ rb_define_method(cBreakpoint, "hit_count", breakpoint_hit_count, 0);
575
+ rb_define_method(cBreakpoint, "hit_value", breakpoint_hit_value, 0);
576
+ rb_define_method(cBreakpoint, "hit_value=", breakpoint_set_hit_value, 1);
577
+ rb_define_method(cBreakpoint, "id", breakpoint_id, 0);
578
+ rb_define_method(cBreakpoint, "pos", breakpoint_pos, 0);
579
+ rb_define_method(cBreakpoint, "pos=", breakpoint_set_pos, 1);
580
+ rb_define_method(cBreakpoint, "source", breakpoint_source, 0);
581
+ rb_define_method(cBreakpoint, "source=", breakpoint_set_source, 1);
582
+ idEval = rb_intern("eval");
583
+ rdebug_catchpoints = rb_hash_new();
584
+
585
+ }
586
+
587
+