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,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
+