ruby-debug-base 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/CHANGES +9 -1
  2. data/ext/ruby_debug.c +252 -37
  3. metadata +2 -2
data/CHANGES CHANGED
@@ -1,5 +1,13 @@
1
+ 0.9.2
2
+ - Fixed file comparison in Windows platform.
3
+ - Added setter methods to Breakpoint properties
4
+ - Added breakpoint hit condition functionality (not available via CLI yet) and methods:
5
+ Breakpoint:hit_count
6
+ Breakpoint:hit_value[=]
7
+ Breakpoint:hit_condition[=]
8
+
1
9
  0.9.1
2
- - Fixed incorrent stack calculation.
10
+ - Fixed incorrect stack calculation.
3
11
  - Context#stop_next= method aliased as Context#step.
4
12
  - Added the 'force' parameter to Context#step_over.
5
13
  - Added the 'force' parameter to Context#step.
@@ -4,7 +4,7 @@
4
4
  #include <rubysig.h>
5
5
  #include <st.h>
6
6
 
7
- #define DEBUG_VERSION "0.9.1"
7
+ #define DEBUG_VERSION "0.9.2"
8
8
 
9
9
  #ifdef _WIN32
10
10
  struct FRAME {
@@ -48,7 +48,7 @@ RUBY_EXTERN struct RVarmap *ruby_dyna_vars;
48
48
  #define CTX_FL_IGNORE (1<<4)
49
49
  #define CTX_FL_DEAD (1<<5)
50
50
  #define CTX_FL_WAS_RUNNING (1<<6)
51
- #define CTX_FL_MOVED (1<<7)
51
+ #define CTX_FL_ENABLE_BKPT (1<<7)
52
52
  #define CTX_FL_STEPPED (1<<8)
53
53
  #define CTX_FL_FORCE_MOVE (1<<9)
54
54
 
@@ -86,7 +86,7 @@ typedef struct {
86
86
  } info;
87
87
  } debug_frame_t;
88
88
 
89
- enum ctx_stop_reason {CTX_STOP_INIT, CTX_STOP_STEP, CTX_STOP_BREAKPOINT, CTX_STOP_CATCHPOINT};
89
+ enum ctx_stop_reason {CTX_STOP_NONE, CTX_STOP_STEP, CTX_STOP_BREAKPOINT, CTX_STOP_CATCHPOINT};
90
90
 
91
91
  typedef struct {
92
92
  VALUE thread_id;
@@ -106,6 +106,7 @@ typedef struct {
106
106
  } debug_context_t;
107
107
 
108
108
  enum bp_type {BP_POS_TYPE, BP_METHOD_TYPE};
109
+ enum hit_condition {HIT_COND_NONE, HIT_COND_GE, HIT_COND_EQ, HIT_COND_MOD};
109
110
 
110
111
  typedef struct {
111
112
  int id;
@@ -117,6 +118,9 @@ typedef struct {
117
118
  ID mid;
118
119
  } pos;
119
120
  VALUE expr;
121
+ int hit_count;
122
+ int hit_value;
123
+ enum hit_condition hit_condition;
120
124
  } debug_breakpoint_t;
121
125
 
122
126
  typedef struct {
@@ -433,7 +437,7 @@ debug_context_create(VALUE thread)
433
437
  debug_context->dest_frame = -1;
434
438
  debug_context->stop_line = -1;
435
439
  debug_context->stop_frame = -1;
436
- debug_context->stop_reason = CTX_STOP_INIT;
440
+ debug_context->stop_reason = CTX_STOP_NONE;
437
441
  debug_context->stack_len = STACK_SIZE_INCREMENT;
438
442
  debug_context->frames = ALLOC_N(debug_frame_t, STACK_SIZE_INCREMENT);
439
443
  debug_context->stack_size = 0;
@@ -578,14 +582,56 @@ filename_cmp(VALUE source, char *file)
578
582
  {
579
583
  if((source_ptr[s] == '.' || file_ptr[f] == '.') && dirsep_flag)
580
584
  return 1;
581
- if(source_ptr[s] != file_ptr[f])
582
- return 0;
583
- if(isdirsep(source_ptr[s]))
585
+ if(isdirsep(source_ptr[s]) && isdirsep(file_ptr[f]))
584
586
  dirsep_flag = 1;
587
+ else if(source_ptr[s] != file_ptr[f])
588
+ return 0;
585
589
  }
586
590
  return 1;
587
591
  }
588
592
 
593
+ inline static int
594
+ classname_cmp(VALUE name, VALUE klass)
595
+ {
596
+ return (klass != Qnil && rb_str_cmp(name, rb_mod_name(klass)) == 0);
597
+ }
598
+
599
+ static int
600
+ check_breakpoint_hit_condition(VALUE breakpoint)
601
+ {
602
+ debug_breakpoint_t *debug_breakpoint;
603
+
604
+ if(breakpoint == Qnil)
605
+ return 0;
606
+ Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
607
+
608
+ debug_breakpoint->hit_count++;
609
+ switch(debug_breakpoint->hit_condition)
610
+ {
611
+ case HIT_COND_NONE:
612
+ return 1;
613
+ case HIT_COND_GE:
614
+ {
615
+ if(debug_breakpoint->hit_count >= debug_breakpoint->hit_value)
616
+ return 1;
617
+ break;
618
+ }
619
+ case HIT_COND_EQ:
620
+ {
621
+ if(debug_breakpoint->hit_count == debug_breakpoint->hit_value)
622
+ return 1;
623
+ break;
624
+ }
625
+ case HIT_COND_MOD:
626
+ {
627
+ if(debug_breakpoint->hit_count % debug_breakpoint->hit_value == 0)
628
+ return 1;
629
+ break;
630
+ }
631
+ }
632
+ return 0;
633
+ }
634
+
589
635
  static int
590
636
  check_breakpoint_by_pos(VALUE breakpoint, char *file, int line)
591
637
  {
@@ -603,13 +649,30 @@ check_breakpoint_by_pos(VALUE breakpoint, char *file, int line)
603
649
  return 0;
604
650
  }
605
651
 
652
+ static int
653
+ check_breakpoint_by_method(VALUE breakpoint, VALUE klass, ID mid)
654
+ {
655
+ debug_breakpoint_t *debug_breakpoint;
656
+
657
+ if(breakpoint == Qnil)
658
+ return 0;
659
+ Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
660
+ if(debug_breakpoint->type != BP_METHOD_TYPE)
661
+ return 0;
662
+ if(debug_breakpoint->pos.mid != mid)
663
+ return 0;
664
+ if(classname_cmp(debug_breakpoint->source, klass))
665
+ return 1;
666
+ return 0;
667
+ }
668
+
606
669
  static VALUE
607
670
  check_breakpoints_by_pos(debug_context_t *debug_context, char *file, int line)
608
671
  {
609
672
  VALUE breakpoint;
610
673
  int i;
611
674
 
612
- if(!CTX_FL_TEST(debug_context, CTX_FL_MOVED))
675
+ if(!CTX_FL_TEST(debug_context, CTX_FL_ENABLE_BKPT))
613
676
  return Qnil;
614
677
 
615
678
  if(check_breakpoint_by_pos(debug_context->breakpoint, file, line))
@@ -626,36 +689,13 @@ check_breakpoints_by_pos(debug_context_t *debug_context, char *file, int line)
626
689
  return Qnil;
627
690
  }
628
691
 
629
- inline static int
630
- classname_cmp(VALUE name, VALUE klass)
631
- {
632
- return (klass != Qnil && rb_str_cmp(name, rb_mod_name(klass)) == 0);
633
- }
634
-
635
- static int
636
- check_breakpoint_by_method(VALUE breakpoint, VALUE klass, ID mid)
637
- {
638
- debug_breakpoint_t *debug_breakpoint;
639
-
640
- if(breakpoint == Qnil)
641
- return 0;
642
- Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
643
- if(debug_breakpoint->type != BP_METHOD_TYPE)
644
- return 0;
645
- if(debug_breakpoint->pos.mid != mid)
646
- return 0;
647
- if(classname_cmp(debug_breakpoint->source, klass))
648
- return 1;
649
- return 0;
650
- }
651
-
652
692
  static VALUE
653
693
  check_breakpoints_by_method(debug_context_t *debug_context, VALUE klass, ID mid)
654
694
  {
655
695
  VALUE breakpoint;
656
696
  int i;
657
697
 
658
- if(!CTX_FL_TEST(debug_context, CTX_FL_MOVED))
698
+ if(!CTX_FL_TEST(debug_context, CTX_FL_ENABLE_BKPT))
659
699
  return Qnil;
660
700
 
661
701
  if(check_breakpoint_by_method(debug_context->breakpoint, klass, mid))
@@ -763,7 +803,7 @@ save_current_position(debug_context_t *debug_context)
763
803
  if(!debug_frame) return;
764
804
  debug_context->last_file = debug_frame->file;
765
805
  debug_context->last_line = debug_frame->line;
766
- CTX_FL_UNSET(debug_context, CTX_FL_MOVED);
806
+ CTX_FL_UNSET(debug_context, CTX_FL_ENABLE_BKPT);
767
807
  CTX_FL_UNSET(debug_context, CTX_FL_STEPPED);
768
808
  CTX_FL_UNSET(debug_context, CTX_FL_FORCE_MOVE);
769
809
  }
@@ -863,7 +903,7 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
863
903
  if(debug_context->last_line != line || debug_context->last_file == NULL ||
864
904
  strcmp(debug_context->last_file, file) != 0)
865
905
  {
866
- CTX_FL_SET(debug_context, CTX_FL_MOVED);
906
+ CTX_FL_SET(debug_context, CTX_FL_ENABLE_BKPT);
867
907
  moved = 1;
868
908
  }
869
909
  }
@@ -931,6 +971,8 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
931
971
  {
932
972
  if(!check_breakpoint_expression(breakpoint, binding))
933
973
  break;
974
+ if(!check_breakpoint_hit_condition(breakpoint))
975
+ break;
934
976
  if(breakpoint != debug_context->breakpoint)
935
977
  {
936
978
  debug_context->stop_reason = CTX_STOP_BREAKPOINT;
@@ -965,6 +1007,8 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
965
1007
 
966
1008
  if(!check_breakpoint_expression(breakpoint, binding))
967
1009
  break;
1010
+ if(!check_breakpoint_hit_condition(breakpoint))
1011
+ break;
968
1012
  if(breakpoint != debug_context->breakpoint)
969
1013
  {
970
1014
  debug_context->stop_reason = CTX_STOP_BREAKPOINT;
@@ -1004,6 +1048,7 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
1004
1048
  if(debug_context->frames[debug_context->stack_size].orig_id == mid)
1005
1049
  break;
1006
1050
  }
1051
+ CTX_FL_SET(debug_context, CTX_FL_ENABLE_BKPT);
1007
1052
  break;
1008
1053
  }
1009
1054
  case RUBY_EVENT_CLASS:
@@ -1060,6 +1105,8 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
1060
1105
  }
1061
1106
 
1062
1107
  cleanup:
1108
+
1109
+ debug_context->stop_reason = CTX_STOP_NONE;
1063
1110
 
1064
1111
  /* check that all contexts point to alive threads */
1065
1112
  if(hook_count - last_check > 3000)
@@ -1182,6 +1229,9 @@ create_breakpoint_from_args(int argc, VALUE *argv, int id)
1182
1229
  else
1183
1230
  breakpoint->pos.mid = rb_intern(RSTRING(pos)->ptr);
1184
1231
  breakpoint->expr = NIL_P(expr) ? expr: StringValue(expr);
1232
+ breakpoint->hit_count = 0;
1233
+ breakpoint->hit_value = 0;
1234
+ breakpoint->hit_condition = HIT_COND_NONE;
1185
1235
  return Data_Wrap_Struct(cBreakpoint, breakpoint_mark, xfree, breakpoint);
1186
1236
  }
1187
1237
 
@@ -2220,9 +2270,9 @@ context_stop_reason(VALUE self)
2220
2270
  case CTX_STOP_CATCHPOINT:
2221
2271
  sym_name = "catchpoint";
2222
2272
  break;
2223
- case CTX_STOP_INIT:
2273
+ case CTX_STOP_NONE:
2224
2274
  default:
2225
- sym_name = "initial";
2275
+ sym_name = "none";
2226
2276
  }
2227
2277
  if(CTX_FL_TEST(debug_context, CTX_FL_DEAD))
2228
2278
  sym_name = "post-mortem";
@@ -2246,6 +2296,22 @@ breakpoint_source(VALUE self)
2246
2296
  return breakpoint->source;
2247
2297
  }
2248
2298
 
2299
+ /*
2300
+ * call-seq:
2301
+ * breakpoint.source = string
2302
+ *
2303
+ * Sets the source of the breakpoint.
2304
+ */
2305
+ static VALUE
2306
+ breakpoint_set_source(VALUE self, VALUE value)
2307
+ {
2308
+ debug_breakpoint_t *breakpoint;
2309
+
2310
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2311
+ breakpoint->source = StringValue(value);
2312
+ return value;
2313
+ }
2314
+
2249
2315
  /*
2250
2316
  * call-seq:
2251
2317
  * breakpoint.pos -> string or int
@@ -2264,6 +2330,27 @@ breakpoint_pos(VALUE self)
2264
2330
  return INT2FIX(breakpoint->pos.line);
2265
2331
  }
2266
2332
 
2333
+ /*
2334
+ * call-seq:
2335
+ * breakpoint.pos = string or int
2336
+ *
2337
+ * Sets the position of this breakpoint.
2338
+ */
2339
+ static VALUE
2340
+ breakpoint_set_pos(VALUE self, VALUE value)
2341
+ {
2342
+ debug_breakpoint_t *breakpoint;
2343
+
2344
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2345
+ if(breakpoint->type == BP_METHOD_TYPE)
2346
+ {
2347
+ breakpoint->pos.mid = rb_to_id(StringValue(value));
2348
+ }
2349
+ else
2350
+ breakpoint->pos.line = FIX2INT(value);
2351
+ return value;
2352
+ }
2353
+
2267
2354
  /*
2268
2355
  * call-seq:
2269
2356
  * breakpoint.expr -> string
@@ -2279,6 +2366,22 @@ breakpoint_expr(VALUE self)
2279
2366
  return breakpoint->expr;
2280
2367
  }
2281
2368
 
2369
+ /*
2370
+ * call-seq:
2371
+ * breakpoint.expr = string
2372
+ *
2373
+ * Sets the codition expression when this breakpoint should be activated.
2374
+ */
2375
+ static VALUE
2376
+ breakpoint_set_expr(VALUE self, VALUE value)
2377
+ {
2378
+ debug_breakpoint_t *breakpoint;
2379
+
2380
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2381
+ breakpoint->expr = StringValue(value);
2382
+ return value;
2383
+ }
2384
+
2282
2385
  /*
2283
2386
  * call-seq:
2284
2387
  * breakpoint.id -> int
@@ -2294,6 +2397,110 @@ breakpoint_id(VALUE self)
2294
2397
  return INT2FIX(breakpoint->id);
2295
2398
  }
2296
2399
 
2400
+ /*
2401
+ * call-seq:
2402
+ * breakpoint.hit_count -> int
2403
+ *
2404
+ * Returns the hit count of the breakpoint.
2405
+ */
2406
+ static VALUE
2407
+ breakpoint_hit_count(VALUE self)
2408
+ {
2409
+ debug_breakpoint_t *breakpoint;
2410
+
2411
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2412
+ return INT2FIX(breakpoint->hit_count);
2413
+ }
2414
+
2415
+ /*
2416
+ * call-seq:
2417
+ * breakpoint.hit_value -> int
2418
+ *
2419
+ * Returns the hit value of the breakpoint.
2420
+ */
2421
+ static VALUE
2422
+ breakpoint_hit_value(VALUE self)
2423
+ {
2424
+ debug_breakpoint_t *breakpoint;
2425
+
2426
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2427
+ return INT2FIX(breakpoint->hit_value);
2428
+ }
2429
+
2430
+ /*
2431
+ * call-seq:
2432
+ * breakpoint.hit_value = int
2433
+ *
2434
+ * Sets the hit value of the breakpoint.
2435
+ */
2436
+ static VALUE
2437
+ breakpoint_set_hit_value(VALUE self, VALUE value)
2438
+ {
2439
+ debug_breakpoint_t *breakpoint;
2440
+
2441
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2442
+ breakpoint->hit_value = FIX2INT(value);
2443
+ return value;
2444
+ }
2445
+
2446
+ /*
2447
+ * call-seq:
2448
+ * breakpoint.hit_condition -> symbol
2449
+ *
2450
+ * Returns the hit condition of the breakpoint:
2451
+ *
2452
+ * +nil+ if it is an unconditional breakpoint, or
2453
+ * :greater_or_equal, :equal, :modulo
2454
+ */
2455
+ static VALUE
2456
+ breakpoint_hit_condition(VALUE self)
2457
+ {
2458
+ debug_breakpoint_t *breakpoint;
2459
+
2460
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2461
+ switch(breakpoint->hit_condition)
2462
+ {
2463
+ case HIT_COND_GE:
2464
+ return ID2SYM(rb_intern("greater_or_equal"));
2465
+ case HIT_COND_EQ:
2466
+ return ID2SYM(rb_intern("equal"));
2467
+ case HIT_COND_MOD:
2468
+ return ID2SYM(rb_intern("modulo"));
2469
+ case HIT_COND_NONE:
2470
+ default:
2471
+ return Qnil;
2472
+ }
2473
+ }
2474
+
2475
+ /*
2476
+ * call-seq:
2477
+ * breakpoint.hit_condition = symbol
2478
+ *
2479
+ * Sets the hit condition of the breakpoint which must be one of the following values:
2480
+ *
2481
+ * +nil+ if it is an unconditional breakpoint, or
2482
+ * :greater_or_equal(:ge), :equal(:eq), :modulo(:mod)
2483
+ */
2484
+ static VALUE
2485
+ breakpoint_set_hit_condition(VALUE self, VALUE value)
2486
+ {
2487
+ debug_breakpoint_t *breakpoint;
2488
+ ID id_value;
2489
+
2490
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2491
+ id_value = rb_to_id(value);
2492
+
2493
+ if(rb_intern("greater_or_equal") == id_value || rb_intern("ge") == id_value)
2494
+ breakpoint->hit_condition = HIT_COND_GE;
2495
+ else if(rb_intern("equal") == id_value || rb_intern("eq") == id_value)
2496
+ breakpoint->hit_condition = HIT_COND_EQ;
2497
+ else if(rb_intern("modulo") == id_value || rb_intern("mod") == id_value)
2498
+ breakpoint->hit_condition = HIT_COND_MOD;
2499
+ else
2500
+ rb_raise(rb_eArgError, "Invalid condition parameter");
2501
+ return value;
2502
+ }
2503
+
2297
2504
  /*
2298
2505
  * Document-class: Context
2299
2506
  *
@@ -2344,10 +2551,18 @@ static void
2344
2551
  Init_breakpoint()
2345
2552
  {
2346
2553
  cBreakpoint = rb_define_class_under(mDebugger, "Breakpoint", rb_cObject);
2554
+ rb_define_method(cBreakpoint, "id", breakpoint_id, 0);
2347
2555
  rb_define_method(cBreakpoint, "source", breakpoint_source, 0);
2556
+ rb_define_method(cBreakpoint, "source=", breakpoint_set_source, 1);
2348
2557
  rb_define_method(cBreakpoint, "pos", breakpoint_pos, 0);
2558
+ rb_define_method(cBreakpoint, "pos=", breakpoint_set_pos, 1);
2349
2559
  rb_define_method(cBreakpoint, "expr", breakpoint_expr, 0);
2350
- rb_define_method(cBreakpoint, "id", breakpoint_id, 0);
2560
+ rb_define_method(cBreakpoint, "expr=", breakpoint_set_expr, 1);
2561
+ rb_define_method(cBreakpoint, "hit_count", breakpoint_hit_count, 0);
2562
+ rb_define_method(cBreakpoint, "hit_value", breakpoint_hit_value, 0);
2563
+ rb_define_method(cBreakpoint, "hit_value=", breakpoint_set_hit_value, 1);
2564
+ rb_define_method(cBreakpoint, "hit_condition", breakpoint_hit_condition, 0);
2565
+ rb_define_method(cBreakpoint, "hit_condition=", breakpoint_set_hit_condition, 1);
2351
2566
  }
2352
2567
 
2353
2568
 
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
3
3
  specification_version: 1
4
4
  name: ruby-debug-base
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.9.1
7
- date: 2007-04-02 21:55:54 -04:00
6
+ version: 0.9.2
7
+ date: 2007-04-04 16:23:02 -04:00
8
8
  summary: Fast Ruby debugger
9
9
  require_paths:
10
10
  - lib