ruby-debug-base 0.10.0-mswin32 → 0.10.4-mswin32

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.
data/VERSION ADDED
@@ -0,0 +1,3 @@
1
+ # This file was created automatically from data in ext/ruby_debug.c via:
2
+ # rake :make_version_file.
3
+ 0.10.4
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
+