debugger 1.6.5 → 1.6.6
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.
- checksums.yaml +4 -4
- data/README.md +19 -1
- data/debugger.gemspec +1 -1
- data/ext/ruby_debug/211/breakpoint.c +586 -0
- data/ext/ruby_debug/211/ruby_debug.c +2692 -0
- data/ext/ruby_debug/211/ruby_debug.h +148 -0
- data/ext/ruby_debug/extconf.rb +1 -1
- data/lib/debugger/version.rb +1 -1
- metadata +26 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c2f0216e8ac02900de17500b15cc96cc999839e
|
4
|
+
data.tar.gz: ae21f642e2ec41c1bad896af0e6b6bc67db80203
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b19d0c4134c8de9e51c4cb87753ce5af4848300fe55a671e1e4b7a739c9266353b51737e2224a843a49a9a6b6ed9fac1a871276fc4064bc01ec8e5601ef6e42
|
7
|
+
data.tar.gz: 693303eccec9a4c17531e1c9045a60eb856ce266f7db84c270c7e1f24c6521f8a9df8be1f739f32ec8ec29791d5ae579b3f3b7a4c3b6fe2e44dc275ebda2e2f6
|
data/README.md
CHANGED
@@ -56,6 +56,20 @@ Most commands are described in rdebug's man page
|
|
56
56
|
$ gem install gem-man
|
57
57
|
$ man rdebug
|
58
58
|
|
59
|
+
### Remote Debugging
|
60
|
+
|
61
|
+
To debug a separate process remotely (such as unicorn) try:
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
Debugger.wait_connection = true
|
65
|
+
Debugger.start_remote
|
66
|
+
debugger
|
67
|
+
```
|
68
|
+
|
69
|
+
Then you can do
|
70
|
+
|
71
|
+
$ rdebug -c
|
72
|
+
|
59
73
|
### More documentation
|
60
74
|
|
61
75
|
Some thorough documentation of debugger is found with [this bashdb
|
@@ -118,7 +132,7 @@ Let's keep this working for the ruby community!
|
|
118
132
|
debugger commands and more
|
119
133
|
* [debugger-xml](https://github.com/astashov/debugger-xml) - XML interface for debugger, compatible
|
120
134
|
with ruby-debug-ide
|
121
|
-
* [vim-ruby-debugger] - Vim plugin that uses debugger
|
135
|
+
* [vim-ruby-debugger](https://github.com/astashov/vim-ruby-debugger) - Vim plugin that uses debugger
|
122
136
|
* [debugger-pry](https://github.com/pry/debugger-pry) - using pry within debugger
|
123
137
|
* [pry-debugger](https://github.com/nixme/pry-debugger) - using debugger within pry
|
124
138
|
* [ruby-debug-passenger](https://github.com/davejamesmiller/ruby-debug-passenger) - rake task to
|
@@ -127,6 +141,10 @@ Let's keep this working for the ruby community!
|
|
127
141
|
* [rb-trepanning](https://github.com/rocky/rb-trepanning) - rewrite of ruby-debug that requires a
|
128
142
|
patched ruby
|
129
143
|
|
144
|
+
## Links
|
145
|
+
|
146
|
+
* [Rails guide with debugger](http://guides.rubyonrails.org/debugging_rails_applications.html)
|
147
|
+
|
130
148
|
## License
|
131
149
|
|
132
150
|
Licensing due to the complicated forking history of this project. Licensing is BSD throughout most
|
data/debugger.gemspec
CHANGED
@@ -20,7 +20,7 @@ handling, bindings for stack frames among other things.
|
|
20
20
|
s.extensions << "ext/ruby_debug/extconf.rb"
|
21
21
|
s.executables = ["rdebug"]
|
22
22
|
s.add_dependency "columnize", ">= 0.3.1"
|
23
|
-
s.add_dependency "debugger-ruby_core_source", '~> 1.3.
|
23
|
+
s.add_dependency "debugger-ruby_core_source", '~> 1.3.2'
|
24
24
|
s.add_dependency "debugger-linecache", '~> 1.2.0'
|
25
25
|
s.add_development_dependency 'rake', '~> 0.9.2.2'
|
26
26
|
s.add_development_dependency 'rake-compiler', '~> 0.8.0'
|
@@ -0,0 +1,586 @@
|
|
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
|
+
int
|
75
|
+
check_breakpoint_by_method(VALUE breakpoint, VALUE klass, ID mid, VALUE self)
|
76
|
+
{
|
77
|
+
debug_breakpoint_t *debug_breakpoint;
|
78
|
+
|
79
|
+
if(breakpoint == Qnil)
|
80
|
+
return 0;
|
81
|
+
Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
|
82
|
+
if (!Qtrue == debug_breakpoint->enabled) return 0;
|
83
|
+
if(debug_breakpoint->type != BP_METHOD_TYPE)
|
84
|
+
return 0;
|
85
|
+
if(debug_breakpoint->pos.mid != mid)
|
86
|
+
return 0;
|
87
|
+
if(classname_cmp(debug_breakpoint->source, klass))
|
88
|
+
return 1;
|
89
|
+
if ((rb_type(self) == T_CLASS) &&
|
90
|
+
classname_cmp(debug_breakpoint->source, self))
|
91
|
+
return 1;
|
92
|
+
return 0;
|
93
|
+
}
|
94
|
+
|
95
|
+
VALUE
|
96
|
+
check_breakpoints_by_pos(debug_context_t *debug_context, char *file, int line)
|
97
|
+
{
|
98
|
+
VALUE breakpoint;
|
99
|
+
int i;
|
100
|
+
|
101
|
+
if(!CTX_FL_TEST(debug_context, CTX_FL_ENABLE_BKPT))
|
102
|
+
return Qnil;
|
103
|
+
|
104
|
+
if(check_breakpoint_by_pos(debug_context->breakpoint, file, line))
|
105
|
+
return debug_context->breakpoint;
|
106
|
+
|
107
|
+
if(RARRAY_LEN(rdebug_breakpoints) == 0)
|
108
|
+
return Qnil;
|
109
|
+
for(i = 0; i < RARRAY_LEN(rdebug_breakpoints); i++)
|
110
|
+
{
|
111
|
+
breakpoint = rb_ary_entry(rdebug_breakpoints, i);
|
112
|
+
if(check_breakpoint_by_pos(breakpoint, file, line))
|
113
|
+
return breakpoint;
|
114
|
+
}
|
115
|
+
return Qnil;
|
116
|
+
}
|
117
|
+
|
118
|
+
VALUE
|
119
|
+
check_breakpoints_by_method(debug_context_t *debug_context, VALUE klass, ID mid, VALUE self)
|
120
|
+
{
|
121
|
+
VALUE breakpoint;
|
122
|
+
int i;
|
123
|
+
|
124
|
+
if(!CTX_FL_TEST(debug_context, CTX_FL_ENABLE_BKPT))
|
125
|
+
return Qnil;
|
126
|
+
|
127
|
+
if(check_breakpoint_by_method(debug_context->breakpoint, klass, mid, self))
|
128
|
+
return debug_context->breakpoint;
|
129
|
+
|
130
|
+
if(RARRAY_LEN(rdebug_breakpoints) == 0)
|
131
|
+
return Qnil;
|
132
|
+
for(i = 0; i < RARRAY_LEN(rdebug_breakpoints); i++)
|
133
|
+
{
|
134
|
+
breakpoint = rb_ary_entry(rdebug_breakpoints, i);
|
135
|
+
if(check_breakpoint_by_method(breakpoint, klass, mid, self))
|
136
|
+
return breakpoint;
|
137
|
+
}
|
138
|
+
return Qnil;
|
139
|
+
}
|
140
|
+
|
141
|
+
int
|
142
|
+
check_breakpoint_expression(VALUE breakpoint, VALUE binding)
|
143
|
+
{
|
144
|
+
debug_breakpoint_t *debug_breakpoint;
|
145
|
+
VALUE args, expr_result;
|
146
|
+
|
147
|
+
Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
|
148
|
+
if(NIL_P(debug_breakpoint->expr))
|
149
|
+
return 1;
|
150
|
+
|
151
|
+
args = rb_ary_new3(2, debug_breakpoint->expr, binding);
|
152
|
+
expr_result = rb_protect(eval_expression, args, 0);
|
153
|
+
return RTEST(expr_result);
|
154
|
+
}
|
155
|
+
|
156
|
+
static void
|
157
|
+
breakpoint_mark(void *data)
|
158
|
+
{
|
159
|
+
debug_breakpoint_t *breakpoint;
|
160
|
+
breakpoint = (debug_breakpoint_t *)data;
|
161
|
+
rb_gc_mark(breakpoint->source);
|
162
|
+
rb_gc_mark(breakpoint->expr);
|
163
|
+
}
|
164
|
+
|
165
|
+
VALUE
|
166
|
+
create_breakpoint_from_args(int argc, VALUE *argv, int id)
|
167
|
+
{
|
168
|
+
VALUE source, pos, expr;
|
169
|
+
debug_breakpoint_t *breakpoint;
|
170
|
+
int type;
|
171
|
+
|
172
|
+
if(rb_scan_args(argc, argv, "21", &source, &pos, &expr) == 2)
|
173
|
+
{
|
174
|
+
expr = Qnil;
|
175
|
+
}
|
176
|
+
type = FIXNUM_P(pos) ? BP_POS_TYPE : BP_METHOD_TYPE;
|
177
|
+
if(type == BP_POS_TYPE)
|
178
|
+
source = StringValue(source);
|
179
|
+
else
|
180
|
+
pos = StringValue(pos);
|
181
|
+
breakpoint = ALLOC(debug_breakpoint_t);
|
182
|
+
breakpoint->id = id;
|
183
|
+
breakpoint->source = source;
|
184
|
+
breakpoint->type = type;
|
185
|
+
if(type == BP_POS_TYPE)
|
186
|
+
breakpoint->pos.line = FIX2INT(pos);
|
187
|
+
else
|
188
|
+
breakpoint->pos.mid = rb_intern(RSTRING_PTR(pos));
|
189
|
+
breakpoint->enabled = Qtrue;
|
190
|
+
breakpoint->expr = NIL_P(expr) ? expr: StringValue(expr);
|
191
|
+
breakpoint->hit_count = 0;
|
192
|
+
breakpoint->hit_value = 0;
|
193
|
+
breakpoint->hit_condition = HIT_COND_NONE;
|
194
|
+
return Data_Wrap_Struct(cBreakpoint, breakpoint_mark, xfree, breakpoint);
|
195
|
+
}
|
196
|
+
|
197
|
+
/*
|
198
|
+
* call-seq:
|
199
|
+
* Debugger.remove_breakpoint(id) -> breakpoint
|
200
|
+
*
|
201
|
+
* Removes breakpoint by its id.
|
202
|
+
* <i>id</i> is an identificator of a breakpoint.
|
203
|
+
*/
|
204
|
+
VALUE
|
205
|
+
rdebug_remove_breakpoint(VALUE self, VALUE id_value)
|
206
|
+
{
|
207
|
+
int i;
|
208
|
+
int id;
|
209
|
+
VALUE breakpoint;
|
210
|
+
debug_breakpoint_t *debug_breakpoint;
|
211
|
+
|
212
|
+
id = FIX2INT(id_value);
|
213
|
+
|
214
|
+
for( i = 0; i < RARRAY_LEN(rdebug_breakpoints); i += 1 )
|
215
|
+
{
|
216
|
+
breakpoint = rb_ary_entry(rdebug_breakpoints, i);
|
217
|
+
Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
|
218
|
+
if(debug_breakpoint->id == id)
|
219
|
+
{
|
220
|
+
rb_ary_delete_at(rdebug_breakpoints, i);
|
221
|
+
return breakpoint;
|
222
|
+
}
|
223
|
+
}
|
224
|
+
return Qnil;
|
225
|
+
}
|
226
|
+
|
227
|
+
/*
|
228
|
+
* call-seq:
|
229
|
+
* Debugger.catchpoints -> hash
|
230
|
+
*
|
231
|
+
* Returns a current catchpoints, which is a hash exception names that will
|
232
|
+
* trigger a debugger when raised. The values are the number of times taht
|
233
|
+
* catchpoint was hit, initially 0.
|
234
|
+
*/
|
235
|
+
VALUE
|
236
|
+
debug_catchpoints(VALUE self)
|
237
|
+
{
|
238
|
+
debug_check_started();
|
239
|
+
|
240
|
+
return rdebug_catchpoints;
|
241
|
+
}
|
242
|
+
|
243
|
+
/*
|
244
|
+
* call-seq:
|
245
|
+
* Debugger.catchpoint(string) -> string
|
246
|
+
*
|
247
|
+
* Sets catchpoint. Returns the string passed.
|
248
|
+
*/
|
249
|
+
VALUE
|
250
|
+
rdebug_add_catchpoint(VALUE self, VALUE value)
|
251
|
+
{
|
252
|
+
debug_check_started();
|
253
|
+
|
254
|
+
if (TYPE(value) != T_STRING) {
|
255
|
+
rb_raise(rb_eTypeError, "value of a catchpoint must be String");
|
256
|
+
}
|
257
|
+
rb_hash_aset(rdebug_catchpoints, rb_str_dup(value), INT2FIX(0));
|
258
|
+
return value;
|
259
|
+
}
|
260
|
+
|
261
|
+
/*
|
262
|
+
* call-seq:
|
263
|
+
* context.breakpoint -> breakpoint
|
264
|
+
*
|
265
|
+
* Returns a context-specific temporary Breakpoint object.
|
266
|
+
*/
|
267
|
+
VALUE
|
268
|
+
context_breakpoint(VALUE self)
|
269
|
+
{
|
270
|
+
debug_context_t *debug_context;
|
271
|
+
|
272
|
+
debug_check_started();
|
273
|
+
|
274
|
+
Data_Get_Struct(self, debug_context_t, debug_context);
|
275
|
+
return debug_context->breakpoint;
|
276
|
+
}
|
277
|
+
|
278
|
+
/*
|
279
|
+
* call-seq:
|
280
|
+
* context.set_breakpoint(source, pos, condition = nil) -> breakpoint
|
281
|
+
*
|
282
|
+
* Sets a context-specific temporary breakpoint, which can be used to implement
|
283
|
+
* 'Run to Cursor' debugger function. When this breakpoint is reached, it will be
|
284
|
+
* cleared out.
|
285
|
+
*
|
286
|
+
* <i>source</i> is a name of a file or a class.
|
287
|
+
* <i>pos</i> is a line number or a method name if <i>source</i> is a class name.
|
288
|
+
* <i>condition</i> is a string which is evaluated to +true+ when this breakpoint
|
289
|
+
* is activated.
|
290
|
+
*/
|
291
|
+
VALUE
|
292
|
+
context_set_breakpoint(int argc, VALUE *argv, VALUE self)
|
293
|
+
{
|
294
|
+
VALUE result;
|
295
|
+
debug_context_t *debug_context;
|
296
|
+
|
297
|
+
debug_check_started();
|
298
|
+
|
299
|
+
Data_Get_Struct(self, debug_context_t, debug_context);
|
300
|
+
result = create_breakpoint_from_args(argc, argv, 0);
|
301
|
+
debug_context->breakpoint = result;
|
302
|
+
return result;
|
303
|
+
}
|
304
|
+
|
305
|
+
/*
|
306
|
+
* call-seq:
|
307
|
+
* breakpoint.enabled?
|
308
|
+
*
|
309
|
+
* Returns whether breakpoint is enabled or not.
|
310
|
+
*/
|
311
|
+
static VALUE
|
312
|
+
breakpoint_enabled(VALUE self)
|
313
|
+
{
|
314
|
+
debug_breakpoint_t *breakpoint;
|
315
|
+
|
316
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
317
|
+
return breakpoint->enabled;
|
318
|
+
}
|
319
|
+
|
320
|
+
/*
|
321
|
+
* call-seq:
|
322
|
+
* breakpoint.enabled = bool
|
323
|
+
*
|
324
|
+
* Enables or disables breakpoint.
|
325
|
+
*/
|
326
|
+
static VALUE
|
327
|
+
breakpoint_set_enabled(VALUE self, VALUE bool)
|
328
|
+
{
|
329
|
+
debug_breakpoint_t *breakpoint;
|
330
|
+
|
331
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
332
|
+
return breakpoint->enabled = bool;
|
333
|
+
}
|
334
|
+
|
335
|
+
/*
|
336
|
+
* call-seq:
|
337
|
+
* breakpoint.source -> string
|
338
|
+
*
|
339
|
+
* Returns a source of the breakpoint.
|
340
|
+
*/
|
341
|
+
static VALUE
|
342
|
+
breakpoint_source(VALUE self)
|
343
|
+
{
|
344
|
+
debug_breakpoint_t *breakpoint;
|
345
|
+
|
346
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
347
|
+
return breakpoint->source;
|
348
|
+
}
|
349
|
+
|
350
|
+
/*
|
351
|
+
* call-seq:
|
352
|
+
* breakpoint.source = string
|
353
|
+
*
|
354
|
+
* Sets the source of the breakpoint.
|
355
|
+
*/
|
356
|
+
static VALUE
|
357
|
+
breakpoint_set_source(VALUE self, VALUE value)
|
358
|
+
{
|
359
|
+
debug_breakpoint_t *breakpoint;
|
360
|
+
|
361
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
362
|
+
breakpoint->source = StringValue(value);
|
363
|
+
return value;
|
364
|
+
}
|
365
|
+
|
366
|
+
/*
|
367
|
+
* call-seq:
|
368
|
+
* breakpoint.pos -> string or int
|
369
|
+
*
|
370
|
+
* Returns the position of this breakpoint.
|
371
|
+
*/
|
372
|
+
static VALUE
|
373
|
+
breakpoint_pos(VALUE self)
|
374
|
+
{
|
375
|
+
debug_breakpoint_t *breakpoint;
|
376
|
+
|
377
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
378
|
+
if(breakpoint->type == BP_METHOD_TYPE)
|
379
|
+
return rb_str_new2(rb_id2name(breakpoint->pos.mid));
|
380
|
+
else
|
381
|
+
return INT2FIX(breakpoint->pos.line);
|
382
|
+
}
|
383
|
+
|
384
|
+
/*
|
385
|
+
* call-seq:
|
386
|
+
* breakpoint.pos = string or int
|
387
|
+
*
|
388
|
+
* Sets the position of this breakpoint.
|
389
|
+
*/
|
390
|
+
static VALUE
|
391
|
+
breakpoint_set_pos(VALUE self, VALUE value)
|
392
|
+
{
|
393
|
+
debug_breakpoint_t *breakpoint;
|
394
|
+
|
395
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
396
|
+
if(breakpoint->type == BP_METHOD_TYPE)
|
397
|
+
{
|
398
|
+
breakpoint->pos.mid = rb_to_id(StringValue(value));
|
399
|
+
}
|
400
|
+
else
|
401
|
+
breakpoint->pos.line = FIX2INT(value);
|
402
|
+
return value;
|
403
|
+
}
|
404
|
+
|
405
|
+
/*
|
406
|
+
* call-seq:
|
407
|
+
* breakpoint.expr -> string
|
408
|
+
*
|
409
|
+
* Returns a codition expression when this breakpoint should be activated.
|
410
|
+
*/
|
411
|
+
static VALUE
|
412
|
+
breakpoint_expr(VALUE self)
|
413
|
+
{
|
414
|
+
debug_breakpoint_t *breakpoint;
|
415
|
+
|
416
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
417
|
+
return breakpoint->expr;
|
418
|
+
}
|
419
|
+
|
420
|
+
/*
|
421
|
+
* call-seq:
|
422
|
+
* breakpoint.expr = string | nil
|
423
|
+
*
|
424
|
+
* Sets the codition expression when this breakpoint should be activated.
|
425
|
+
*/
|
426
|
+
static VALUE
|
427
|
+
breakpoint_set_expr(VALUE self, VALUE expr)
|
428
|
+
{
|
429
|
+
debug_breakpoint_t *breakpoint;
|
430
|
+
|
431
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
432
|
+
breakpoint->expr = NIL_P(expr) ? expr: StringValue(expr);
|
433
|
+
return expr;
|
434
|
+
}
|
435
|
+
|
436
|
+
/*
|
437
|
+
* call-seq:
|
438
|
+
* breakpoint.id -> int
|
439
|
+
*
|
440
|
+
* Returns id of the breakpoint.
|
441
|
+
*/
|
442
|
+
static VALUE
|
443
|
+
breakpoint_id(VALUE self)
|
444
|
+
{
|
445
|
+
debug_breakpoint_t *breakpoint;
|
446
|
+
|
447
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
448
|
+
return INT2FIX(breakpoint->id);
|
449
|
+
}
|
450
|
+
|
451
|
+
/*
|
452
|
+
* call-seq:
|
453
|
+
* breakpoint.hit_count -> int
|
454
|
+
*
|
455
|
+
* Returns the hit count of the breakpoint.
|
456
|
+
*/
|
457
|
+
static VALUE
|
458
|
+
breakpoint_hit_count(VALUE self)
|
459
|
+
{
|
460
|
+
debug_breakpoint_t *breakpoint;
|
461
|
+
|
462
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
463
|
+
return INT2FIX(breakpoint->hit_count);
|
464
|
+
}
|
465
|
+
|
466
|
+
/*
|
467
|
+
* call-seq:
|
468
|
+
* breakpoint.hit_value -> int
|
469
|
+
*
|
470
|
+
* Returns the hit value of the breakpoint.
|
471
|
+
*/
|
472
|
+
static VALUE
|
473
|
+
breakpoint_hit_value(VALUE self)
|
474
|
+
{
|
475
|
+
debug_breakpoint_t *breakpoint;
|
476
|
+
|
477
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
478
|
+
return INT2FIX(breakpoint->hit_value);
|
479
|
+
}
|
480
|
+
|
481
|
+
/*
|
482
|
+
* call-seq:
|
483
|
+
* breakpoint.hit_value = int
|
484
|
+
*
|
485
|
+
* Sets the hit value of the breakpoint.
|
486
|
+
*/
|
487
|
+
static VALUE
|
488
|
+
breakpoint_set_hit_value(VALUE self, VALUE value)
|
489
|
+
{
|
490
|
+
debug_breakpoint_t *breakpoint;
|
491
|
+
|
492
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
493
|
+
breakpoint->hit_value = FIX2INT(value);
|
494
|
+
return value;
|
495
|
+
}
|
496
|
+
|
497
|
+
/*
|
498
|
+
* call-seq:
|
499
|
+
* breakpoint.hit_condition -> symbol
|
500
|
+
*
|
501
|
+
* Returns the hit condition of the breakpoint:
|
502
|
+
*
|
503
|
+
* +nil+ if it is an unconditional breakpoint, or
|
504
|
+
* :greater_or_equal, :equal, :modulo
|
505
|
+
*/
|
506
|
+
static VALUE
|
507
|
+
breakpoint_hit_condition(VALUE self)
|
508
|
+
{
|
509
|
+
debug_breakpoint_t *breakpoint;
|
510
|
+
|
511
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
512
|
+
switch(breakpoint->hit_condition)
|
513
|
+
{
|
514
|
+
case HIT_COND_GE:
|
515
|
+
return ID2SYM(rb_intern("greater_or_equal"));
|
516
|
+
case HIT_COND_EQ:
|
517
|
+
return ID2SYM(rb_intern("equal"));
|
518
|
+
case HIT_COND_MOD:
|
519
|
+
return ID2SYM(rb_intern("modulo"));
|
520
|
+
case HIT_COND_NONE:
|
521
|
+
default:
|
522
|
+
return Qnil;
|
523
|
+
}
|
524
|
+
}
|
525
|
+
|
526
|
+
/*
|
527
|
+
* call-seq:
|
528
|
+
* breakpoint.hit_condition = symbol
|
529
|
+
*
|
530
|
+
* Sets the hit condition of the breakpoint which must be one of the following values:
|
531
|
+
*
|
532
|
+
* +nil+ if it is an unconditional breakpoint, or
|
533
|
+
* :greater_or_equal(:ge), :equal(:eq), :modulo(:mod)
|
534
|
+
*/
|
535
|
+
static VALUE
|
536
|
+
breakpoint_set_hit_condition(VALUE self, VALUE value)
|
537
|
+
{
|
538
|
+
debug_breakpoint_t *breakpoint;
|
539
|
+
ID id_value;
|
540
|
+
|
541
|
+
Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
|
542
|
+
id_value = rb_to_id(value);
|
543
|
+
|
544
|
+
if(rb_intern("greater_or_equal") == id_value || rb_intern("ge") == id_value)
|
545
|
+
breakpoint->hit_condition = HIT_COND_GE;
|
546
|
+
else if(rb_intern("equal") == id_value || rb_intern("eq") == id_value)
|
547
|
+
breakpoint->hit_condition = HIT_COND_EQ;
|
548
|
+
else if(rb_intern("modulo") == id_value || rb_intern("mod") == id_value)
|
549
|
+
breakpoint->hit_condition = HIT_COND_MOD;
|
550
|
+
else
|
551
|
+
rb_raise(rb_eArgError, "Invalid condition parameter");
|
552
|
+
return value;
|
553
|
+
}
|
554
|
+
|
555
|
+
/*
|
556
|
+
* Document-class: Breakpoint
|
557
|
+
*
|
558
|
+
* == Summary
|
559
|
+
*
|
560
|
+
* This class represents a breakpoint. It defines position of the breakpoint and
|
561
|
+
* condition when this breakpoint should be triggered.
|
562
|
+
*/
|
563
|
+
void
|
564
|
+
Init_breakpoint()
|
565
|
+
{
|
566
|
+
cBreakpoint = rb_define_class_under(mDebugger, "Breakpoint", rb_cObject);
|
567
|
+
rb_define_method(cBreakpoint, "enabled=", breakpoint_set_enabled, 1);
|
568
|
+
rb_define_method(cBreakpoint, "enabled?", breakpoint_enabled, 0);
|
569
|
+
rb_define_method(cBreakpoint, "expr", breakpoint_expr, 0);
|
570
|
+
rb_define_method(cBreakpoint, "expr=", breakpoint_set_expr, 1);
|
571
|
+
rb_define_method(cBreakpoint, "hit_condition", breakpoint_hit_condition, 0);
|
572
|
+
rb_define_method(cBreakpoint, "hit_condition=", breakpoint_set_hit_condition, 1);
|
573
|
+
rb_define_method(cBreakpoint, "hit_count", breakpoint_hit_count, 0);
|
574
|
+
rb_define_method(cBreakpoint, "hit_value", breakpoint_hit_value, 0);
|
575
|
+
rb_define_method(cBreakpoint, "hit_value=", breakpoint_set_hit_value, 1);
|
576
|
+
rb_define_method(cBreakpoint, "id", breakpoint_id, 0);
|
577
|
+
rb_define_method(cBreakpoint, "pos", breakpoint_pos, 0);
|
578
|
+
rb_define_method(cBreakpoint, "pos=", breakpoint_set_pos, 1);
|
579
|
+
rb_define_method(cBreakpoint, "source", breakpoint_source, 0);
|
580
|
+
rb_define_method(cBreakpoint, "source=", breakpoint_set_source, 1);
|
581
|
+
idEval = rb_intern("eval");
|
582
|
+
rdebug_catchpoints = rb_hash_new();
|
583
|
+
|
584
|
+
}
|
585
|
+
|
586
|
+
|