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

Sign up to get free protection for your applications and to get access to all the features.
data/ext/extconf.rb CHANGED
@@ -15,4 +15,6 @@ else
15
15
  exit(1)
16
16
  end
17
17
 
18
+ # Temporary: to turn off optimization
19
+ # $CFLAGS='-fno-strict-aliasing -g -fPIC'
18
20
  create_makefile("ruby_debug")
data/ext/ruby_debug.c CHANGED
@@ -1,11 +1,12 @@
1
+ #include "ruby_debug.h"
2
+
1
3
  #include <stdio.h>
2
- #include <ruby.h>
3
4
  #include <node.h>
4
5
  #include <rubysig.h>
5
6
  #include <st.h>
6
- #include <version.h>
7
+ #include <intern.h>
7
8
 
8
- #define DEBUG_VERSION "0.10.0"
9
+ #define DEBUG_VERSION "0.10.4"
9
10
 
10
11
  #ifdef _WIN32
11
12
  struct FRAME {
@@ -43,21 +44,6 @@ RUBY_EXTERN struct RVarmap *ruby_dyna_vars;
43
44
  #include <env.h>
44
45
  #endif
45
46
 
46
- #define CTX_FL_SUSPEND (1<<1)
47
- #define CTX_FL_TRACING (1<<2)
48
- #define CTX_FL_SKIPPED (1<<3)
49
- #define CTX_FL_IGNORE (1<<4)
50
- #define CTX_FL_DEAD (1<<5)
51
- #define CTX_FL_WAS_RUNNING (1<<6)
52
- #define CTX_FL_ENABLE_BKPT (1<<7)
53
- #define CTX_FL_STEPPED (1<<8)
54
- #define CTX_FL_FORCE_MOVE (1<<9)
55
-
56
- #define CTX_FL_TEST(c,f) ((c)->flags & (f))
57
- #define CTX_FL_SET(c,f) do { (c)->flags |= (f); } while (0)
58
- #define CTX_FL_UNSET(c,f) do { (c)->flags &= ~(f); } while (0)
59
-
60
- #define IS_STARTED (threads_tbl != Qnil)
61
47
  #define FRAME_N(n) (&debug_context->frames[debug_context->stack_size-(n)-1])
62
48
  #define GET_FRAME (FRAME_N(check_frame_number(debug_context, frame)))
63
49
 
@@ -67,75 +53,10 @@ RUBY_EXTERN struct RVarmap *ruby_dyna_vars;
67
53
 
68
54
  #define STACK_SIZE_INCREMENT 128
69
55
 
70
- typedef struct {
71
- int argc; /* Number of arguments a frame should have. */
72
- VALUE binding;
73
- ID id;
74
- ID orig_id;
75
- int line;
76
- const char * file;
77
- short dead;
78
- VALUE self;
79
- VALUE arg_ary;
80
- union {
81
- struct {
82
- struct FRAME *frame;
83
- struct SCOPE *scope;
84
- struct RVarmap *dyna_vars;
85
- } runtime;
86
- struct {
87
- VALUE args;
88
- VALUE locals;
89
- VALUE arg_ary;
90
- } copy;
91
- } info;
92
- } debug_frame_t;
93
-
94
- enum ctx_stop_reason {CTX_STOP_NONE, CTX_STOP_STEP, CTX_STOP_BREAKPOINT, CTX_STOP_CATCHPOINT};
95
-
96
- typedef struct {
97
- VALUE thread_id;
98
- int thnum;
99
- int flags;
100
- enum ctx_stop_reason stop_reason;
101
- int stop_next;
102
- int dest_frame;
103
- int stop_line;
104
- int stop_frame;
105
- int stack_size;
106
- int stack_len;
107
- debug_frame_t *frames;
108
- const char * last_file;
109
- int last_line;
110
- VALUE breakpoint;
111
- } debug_context_t;
112
-
113
- enum bp_type {BP_POS_TYPE, BP_METHOD_TYPE};
114
- enum hit_condition {HIT_COND_NONE, HIT_COND_GE, HIT_COND_EQ, HIT_COND_MOD};
115
-
116
- typedef struct {
117
- int id;
118
- enum bp_type type;
119
- VALUE source;
120
- union
121
- {
122
- int line;
123
- ID mid;
124
- } pos;
125
- VALUE expr;
126
- VALUE enabled;
127
- int hit_count;
128
- int hit_value;
129
- enum hit_condition hit_condition;
130
- } debug_breakpoint_t;
131
-
132
56
  typedef struct {
133
57
  st_table *tbl;
134
58
  } threads_table_t;
135
59
 
136
- static VALUE threads_tbl = Qnil;
137
- static VALUE breakpoints = Qnil;
138
- static VALUE catchpoint = Qnil;
139
60
  static VALUE tracing = Qfalse;
140
61
  static VALUE locker = Qnil;
141
62
  static VALUE post_mortem = Qfalse;
@@ -147,20 +68,21 @@ static VALUE last_context = Qnil;
147
68
  static VALUE last_thread = Qnil;
148
69
  static debug_context_t *last_debug_context = NULL;
149
70
 
150
- static VALUE mDebugger;
71
+ VALUE rdebug_threads_tbl = Qnil; /* Context for each of the threads */
72
+ VALUE mDebugger; /* Ruby Debugger Module object */
73
+
151
74
  static VALUE cThreadsTable;
152
75
  static VALUE cContext;
153
- static VALUE cBreakpoint;
154
76
  static VALUE cDebugThread;
155
77
 
156
78
  static VALUE rb_mObjectSpace;
157
79
 
158
- static ID idAtLine;
159
80
  static ID idAtBreakpoint;
160
81
  static ID idAtCatchpoint;
82
+ static ID idAtLine;
83
+ static ID idAtReturn;
161
84
  static ID idAtTracing;
162
85
  static ID idList;
163
- static ID idEval;
164
86
 
165
87
  static int start_count = 0;
166
88
  static int thnum_max = 0;
@@ -186,6 +108,17 @@ typedef struct locked_thread_t {
186
108
  static locked_thread_t *locked_head = NULL;
187
109
  static locked_thread_t *locked_tail = NULL;
188
110
 
111
+ /* "Step", "Next" and "Finish" do their work by saving information
112
+ about where to stop next. reset_stopping_points removes/resets this
113
+ information. */
114
+ inline static void
115
+ reset_stepping_stop_points(debug_context_t *debug_context)
116
+ {
117
+ debug_context->dest_frame = -1;
118
+ debug_context->stop_line = -1;
119
+ debug_context->stop_next = -1;
120
+ }
121
+
189
122
  inline static VALUE
190
123
  real_class(VALUE klass)
191
124
  {
@@ -379,7 +312,7 @@ check_thread_contexts()
379
312
  {
380
313
  threads_table_t *threads_table;
381
314
 
382
- Data_Get_Struct(threads_tbl, threads_table_t, threads_table);
315
+ Data_Get_Struct(rdebug_threads_tbl, threads_table_t, threads_table);
383
316
  st_foreach(threads_table->tbl, threads_table_check_i, 0);
384
317
  }
385
318
 
@@ -395,15 +328,6 @@ debug_is_started(VALUE self)
395
328
  return IS_STARTED ? Qtrue : Qfalse;
396
329
  }
397
330
 
398
- static void
399
- debug_check_started()
400
- {
401
- if(!IS_STARTED)
402
- {
403
- rb_raise(rb_eRuntimeError, "Debugger.start is not called yet.");
404
- }
405
- }
406
-
407
331
  static void
408
332
  debug_context_mark(void *data)
409
333
  {
@@ -416,6 +340,7 @@ debug_context_mark(void *data)
416
340
  frame = &(debug_context->frames[i]);
417
341
  rb_gc_mark(frame->binding);
418
342
  rb_gc_mark(frame->self);
343
+ rb_gc_mark(frame->arg_ary);
419
344
  if(frame->dead)
420
345
  {
421
346
  rb_gc_mark(frame->info.copy.locals);
@@ -505,7 +430,7 @@ thread_context_lookup(VALUE thread, VALUE *context, debug_context_t **debug_cont
505
430
  return;
506
431
  }
507
432
  thread_id = ref2id(thread);
508
- Data_Get_Struct(threads_tbl, threads_table_t, threads_table);
433
+ Data_Get_Struct(rdebug_threads_tbl, threads_table_t, threads_table);
509
434
  if(!st_lookup(threads_table->tbl, thread_id, context))
510
435
  {
511
436
  *context = debug_context_create(thread);
@@ -554,7 +479,7 @@ save_call_frame(rb_event_t event, VALUE self, char *file, int line, ID mid, debu
554
479
  if(frame_n >= debug_context->stack_len)
555
480
  {
556
481
  debug_context->stack_len += STACK_SIZE_INCREMENT;
557
- debug_context->frames = REALLOC_N(debug_context->frames, debug_frame_t, debug_context->stack_len);
482
+ REALLOC_N(debug_context->frames, debug_frame_t, debug_context->stack_len);
558
483
  }
559
484
  debug_frame = &debug_context->frames[frame_n];
560
485
  debug_frame->argc = ruby_frame->argc;
@@ -565,6 +490,7 @@ save_call_frame(rb_event_t event, VALUE self, char *file, int line, ID mid, debu
565
490
  debug_frame->orig_id = mid;
566
491
  debug_frame->dead = 0;
567
492
  debug_frame->self = self;
493
+ debug_frame->arg_ary = Qnil;
568
494
  debug_frame->info.runtime.frame = ruby_frame;
569
495
  debug_frame->info.runtime.scope = ruby_scope;
570
496
  debug_frame->info.runtime.dyna_vars = event == RUBY_EVENT_LINE ? ruby_dyna_vars : NULL;
@@ -579,7 +505,7 @@ save_call_frame(rb_event_t event, VALUE self, char *file, int line, ID mid, debu
579
505
  #define isdirsep(x) ((x) == '/')
580
506
  #endif
581
507
 
582
- static int
508
+ int
583
509
  filename_cmp(VALUE source, char *file)
584
510
  {
585
511
  char *source_ptr, *file_ptr;
@@ -606,136 +532,10 @@ filename_cmp(VALUE source, char *file)
606
532
  return 1;
607
533
  }
608
534
 
609
- inline static int
610
- classname_cmp(VALUE name, VALUE klass)
611
- {
612
- VALUE class_name = (Qnil == name) ? rb_str_new2("main") : name;
613
- return (klass != Qnil
614
- && rb_str_cmp(class_name, rb_mod_name(klass)) == 0);
615
- }
616
-
617
- static int
618
- check_breakpoint_hit_condition(VALUE breakpoint)
619
- {
620
- debug_breakpoint_t *debug_breakpoint;
621
-
622
- if(breakpoint == Qnil)
623
- return 0;
624
- Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
625
-
626
- debug_breakpoint->hit_count++;
627
- if (!Qtrue == debug_breakpoint->enabled) return 0;
628
- switch(debug_breakpoint->hit_condition)
629
- {
630
- case HIT_COND_NONE:
631
- return 1;
632
- case HIT_COND_GE:
633
- {
634
- if(debug_breakpoint->hit_count >= debug_breakpoint->hit_value)
635
- return 1;
636
- break;
637
- }
638
- case HIT_COND_EQ:
639
- {
640
- if(debug_breakpoint->hit_count == debug_breakpoint->hit_value)
641
- return 1;
642
- break;
643
- }
644
- case HIT_COND_MOD:
645
- {
646
- if(debug_breakpoint->hit_count % debug_breakpoint->hit_value == 0)
647
- return 1;
648
- break;
649
- }
650
- }
651
- return 0;
652
- }
653
-
654
- static int
655
- check_breakpoint_by_pos(VALUE breakpoint, char *file, int line)
656
- {
657
- debug_breakpoint_t *debug_breakpoint;
658
-
659
- if(breakpoint == Qnil)
660
- return 0;
661
- Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
662
- if (!Qtrue == debug_breakpoint->enabled) return 0;
663
- if(debug_breakpoint->type != BP_POS_TYPE)
664
- return 0;
665
- if(debug_breakpoint->pos.line != line)
666
- return 0;
667
- if(filename_cmp(debug_breakpoint->source, file))
668
- return 1;
669
- return 0;
670
- }
671
-
672
- static int
673
- check_breakpoint_by_method(VALUE breakpoint, VALUE klass, ID mid)
674
- {
675
- debug_breakpoint_t *debug_breakpoint;
676
-
677
- if(breakpoint == Qnil)
678
- return 0;
679
- Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
680
- if (!Qtrue == debug_breakpoint->enabled) return 0;
681
- if(debug_breakpoint->type != BP_METHOD_TYPE)
682
- return 0;
683
- if(debug_breakpoint->pos.mid != mid)
684
- return 0;
685
- if(classname_cmp(debug_breakpoint->source, klass))
686
- return 1;
687
- return 0;
688
- }
689
-
690
- static VALUE
691
- check_breakpoints_by_pos(debug_context_t *debug_context, char *file, int line)
692
- {
693
- VALUE breakpoint;
694
- int i;
695
-
696
- if(!CTX_FL_TEST(debug_context, CTX_FL_ENABLE_BKPT))
697
- return Qnil;
698
-
699
- if(check_breakpoint_by_pos(debug_context->breakpoint, file, line))
700
- return debug_context->breakpoint;
701
-
702
- if(RARRAY(breakpoints)->len == 0)
703
- return Qnil;
704
- for(i = 0; i < RARRAY(breakpoints)->len; i++)
705
- {
706
- breakpoint = rb_ary_entry(breakpoints, i);
707
- if(check_breakpoint_by_pos(breakpoint, file, line))
708
- return breakpoint;
709
- }
710
- return Qnil;
711
- }
712
-
713
- static VALUE
714
- check_breakpoints_by_method(debug_context_t *debug_context, VALUE klass, ID mid)
715
- {
716
- VALUE breakpoint;
717
- int i;
718
-
719
- if(!CTX_FL_TEST(debug_context, CTX_FL_ENABLE_BKPT))
720
- return Qnil;
721
-
722
- if(check_breakpoint_by_method(debug_context->breakpoint, klass, mid))
723
- return debug_context->breakpoint;
724
-
725
- if(RARRAY(breakpoints)->len == 0)
726
- return Qnil;
727
- for(i = 0; i < RARRAY(breakpoints)->len; i++)
728
- {
729
- breakpoint = rb_ary_entry(breakpoints, i);
730
- if(check_breakpoint_by_method(breakpoint, klass, mid))
731
- return breakpoint;
732
- }
733
- return Qnil;
734
- }
735
-
736
535
  /*
737
- * This is a NASTY HACK. For some reasons rb_f_binding is declared
738
- * static in eval.c. So we create a cons up call to binding in C.
536
+ * A nasty hack to be able to get at the +Kernel.binding+ method.
537
+ * +rb_f_binding+ is declared static in eval.c. So copy and save our own value
538
+ * of it by looking up the method name in the Kernel module.
739
539
  */
740
540
  static VALUE
741
541
  create_binding(VALUE self)
@@ -750,27 +550,6 @@ create_binding(VALUE self)
750
550
  return f_binding(self);
751
551
  }
752
552
 
753
- static VALUE
754
- eval_expression(VALUE args)
755
- {
756
- return rb_funcall2(rb_mKernel, idEval, 2, RARRAY(args)->ptr);
757
- }
758
-
759
- inline static int
760
- check_breakpoint_expression(VALUE breakpoint, VALUE binding)
761
- {
762
- debug_breakpoint_t *debug_breakpoint;
763
- VALUE args, expr_result;
764
-
765
- Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
766
- if(NIL_P(debug_breakpoint->expr))
767
- return 1;
768
-
769
- args = rb_ary_new3(2, debug_breakpoint->expr, binding);
770
- expr_result = rb_protect(eval_expression, args, 0);
771
- return RTEST(expr_result);
772
- }
773
-
774
553
  inline static debug_frame_t *
775
554
  get_top_frame(debug_context_t *debug_context)
776
555
  {
@@ -921,11 +700,31 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
921
700
  if(debug == Qtrue)
922
701
  fprintf(stderr, "%s:%d [%s] %s\n", file, line, get_event_name(event), rb_id2name(mid));
923
702
 
703
+ /* There can be many event calls per line, but we only want
704
+ *one* breakpoint per line. */
924
705
  if(debug_context->last_line != line || debug_context->last_file == NULL ||
925
706
  strcmp(debug_context->last_file, file) != 0)
926
707
  {
927
708
  CTX_FL_SET(debug_context, CTX_FL_ENABLE_BKPT);
928
709
  moved = 1;
710
+ }
711
+ else if(event == RUBY_EVENT_LINE)
712
+ {
713
+ /* There are two line-event trace hook calls per IF node - one
714
+ before the expression eval an done afterwards.
715
+ */
716
+ /* FIXME: the static variable can't be safely used here, since this method
717
+ is re-entrant by multiple threads. If we want to provide this kind of functionality
718
+ if_eval_event variable must be moved to debug_context structure.
719
+ */
720
+ /*
721
+ static int if_eval_event = 0;
722
+ if_eval_event = (NODE_IF == nd_type(node)) ? !if_eval_event : 0;
723
+ if (!if_eval_event)
724
+ {
725
+ CTX_FL_SET(debug_context, CTX_FL_ENABLE_BKPT);
726
+ }
727
+ */
929
728
  }
930
729
  }
931
730
  else if(event != RUBY_EVENT_RETURN && event != RUBY_EVENT_C_RETURN)
@@ -999,11 +798,7 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
999
798
  debug_context->breakpoint = Qnil;
1000
799
  }
1001
800
 
1002
- /* reset all pointers */
1003
- debug_context->dest_frame = -1;
1004
- debug_context->stop_line = -1;
1005
- debug_context->stop_next = -1;
1006
-
801
+ reset_stepping_stop_points(debug_context);
1007
802
  call_at_line(context, debug_context, rb_str_new2(file), INT2FIX(line));
1008
803
  }
1009
804
  break;
@@ -1011,7 +806,7 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
1011
806
  case RUBY_EVENT_CALL:
1012
807
  {
1013
808
  save_call_frame(event, self, file, line, mid, debug_context);
1014
- breakpoint = check_breakpoints_by_method(debug_context, klass, mid);
809
+ breakpoint = check_breakpoints_by_method(debug_context, klass, mid, self);
1015
810
  if(breakpoint != Qnil)
1016
811
  {
1017
812
  debug_frame_t *debug_frame;
@@ -1058,6 +853,9 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
1058
853
  {
1059
854
  debug_context->stop_next = 1;
1060
855
  debug_context->stop_frame = 0;
856
+ /* NOTE: can't use call_at_line function here to trigger a debugger event.
857
+ this can lead to segfault. We should only unroll the stack on this event.
858
+ */
1061
859
  }
1062
860
  while(debug_context->stack_size > 0)
1063
861
  {
@@ -1092,21 +890,48 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
1092
890
  }
1093
891
 
1094
892
  expn_class = rb_obj_class(ruby_errinfo);
893
+
894
+ /* This code goes back to the earliest days of ruby-debug. It
895
+ tends to disallow catching an exception via the
896
+ "catchpoint" command. To address this one possiblilty is to
897
+ move this after testing for catchponts. Kent however thinks
898
+ there may be a misfeature in Ruby's eval.c: the problem was
899
+ in the fact that Ruby doesn't reset exception flag on the
900
+ current thread before it calls a notification handler.
901
+
902
+ See also the #ifdef'd code below as well.
903
+ */
904
+ #ifdef NORMAL_CODE
1095
905
  if( !NIL_P(rb_class_inherited_p(expn_class, rb_eSystemExit)) )
1096
906
  {
1097
907
  debug_stop(mDebugger);
1098
908
  break;
1099
909
  }
910
+ #endif
1100
911
 
1101
- if(catchpoint == Qnil)
912
+ if (rdebug_catchpoints == Qnil ||
913
+ RHASH(rdebug_catchpoints)->tbl->num_entries == 0)
1102
914
  break;
1103
915
 
1104
916
  ancestors = rb_mod_ancestors(expn_class);
1105
917
  for(i = 0; i < RARRAY(ancestors)->len; i++)
1106
918
  {
1107
- aclass = rb_ary_entry(ancestors, i);
1108
- if(rb_str_cmp(rb_mod_name(aclass), catchpoint) == 0)
919
+ VALUE mod_name;
920
+ VALUE hit_count;
921
+
922
+ aclass = rb_ary_entry(ancestors, i);
923
+ mod_name = rb_mod_name(aclass);
924
+ hit_count = rb_hash_aref(rdebug_catchpoints, mod_name);
925
+ if(hit_count != Qnil)
1109
926
  {
927
+ /* On 64-bit systems with gcc and -O2 there seems to be
928
+ an optimization bug in running INT2FIX(FIX2INT...)..)
929
+ So we do this in two steps.
930
+ */
931
+ int c_hit_count = FIX2INT(rb_hash_aref(rdebug_catchpoints,
932
+ mod_name)) + 1;
933
+ hit_count = INT2FIX(c_hit_count);
934
+ rb_hash_aset(rdebug_catchpoints, mod_name, hit_count);
1110
935
  debug_context->stop_reason = CTX_STOP_CATCHPOINT;
1111
936
  rb_funcall(context, idAtCatchpoint, 1, ruby_errinfo);
1112
937
  if(self && binding == Qnil)
@@ -1117,6 +942,18 @@ debug_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
1117
942
  }
1118
943
  }
1119
944
 
945
+ /* If we stop the debugger, we may not be able to trace into
946
+ code that has an exception handler wrapped around it. So
947
+ the alternative is to force the user to do his own
948
+ Debugger.stop. */
949
+ #ifdef NORMAL_CODE_MOVING_AFTER_
950
+ if( !NIL_P(rb_class_inherited_p(expn_class, rb_eSystemExit)) )
951
+ {
952
+ debug_stop(mDebugger);
953
+ break;
954
+ }
955
+ #endif
956
+
1120
957
  break;
1121
958
  }
1122
959
  }
@@ -1150,16 +987,29 @@ debug_stop_i(VALUE self)
1150
987
 
1151
988
  /*
1152
989
  * call-seq:
1153
- * Debugger.start -> bool
1154
- * Debugger.start { ... } -> obj
990
+ * Debugger.start_ -> bool
991
+ * Debugger.start_ { ... } -> bool
1155
992
  *
1156
- * This method activates the debugger.
1157
- * If it's called without a block it returns +true+, unless debugger was already started.
1158
- * If a block is given, it starts debugger and yields to block. When the block is finished
1159
- * executing it stops the debugger with Debugger.stop method.
993
+ * This method is internal and activates the debugger. Use
994
+ * Debugger.start (from <tt>lib/ruby-debug-base.rb</tt>) instead.
995
+ *
996
+ * The return value is the value of !Debugger.started? <i>before</i>
997
+ * issuing the +start+; That is, +true+ is returned, unless debugger
998
+ * was previously started.
999
+
1000
+ * If a block is given, it starts debugger and yields to block. When
1001
+ * the block is finished executing it stops the debugger with
1002
+ * Debugger.stop method. Inside the block you will probably want to
1003
+ * have a call to Debugger.debugger. For example:
1004
+ * Debugger.start{debugger; foo} # Stop inside of foo
1005
+ *
1006
+ * Also, ruby-debug only allows
1007
+ * one invocation of debugger at a time; nested Debugger.start's
1008
+ * have no effect and you can't use this inside the debugger itself.
1160
1009
  *
1161
- * <i>Note that if you want to stop debugger, you must call Debugger.stop as many time as you
1162
- * called Debugger.start method.</i>
1010
+ * <i>Note that if you want to completely remove the debugger hook,
1011
+ * you must call Debugger.stop as many times as you called
1012
+ * Debugger.start method.</i>
1163
1013
  */
1164
1014
  static VALUE
1165
1015
  debug_start(VALUE self)
@@ -1171,16 +1021,18 @@ debug_start(VALUE self)
1171
1021
  result = Qfalse;
1172
1022
  else
1173
1023
  {
1174
- breakpoints = rb_ary_new();
1175
- locker = Qnil;
1176
- threads_tbl = threads_table_create();
1024
+ locker = Qnil;
1025
+ rdebug_breakpoints = rb_ary_new();
1026
+ rdebug_catchpoints = rb_hash_new();
1027
+ rdebug_threads_tbl = threads_table_create();
1177
1028
 
1178
1029
  rb_add_event_hook(debug_event_hook, RUBY_EVENT_ALL);
1179
1030
  result = Qtrue;
1180
1031
  }
1181
1032
 
1182
- if(rb_block_given_p())
1183
- return rb_ensure(rb_yield, self, debug_stop_i, self);
1033
+ if(rb_block_given_p())
1034
+ rb_ensure(rb_yield, self, debug_stop_i, self);
1035
+
1184
1036
  return result;
1185
1037
  }
1186
1038
 
@@ -1191,9 +1043,9 @@ debug_start(VALUE self)
1191
1043
  * This method disables the debugger. It returns +true+ if the debugger is disabled,
1192
1044
  * otherwise it returns +false+.
1193
1045
  *
1194
- * <i>Note that if you want to stop debugger, you must call
1195
- * Debugger.stop as many times as you called Debugger.start
1196
- * method.</i>
1046
+ * <i>Note that if you want to complete remove the debugger hook,
1047
+ * you must call Debugger.stop as many times as you called
1048
+ * Debugger.start method.</i>
1197
1049
  */
1198
1050
  static VALUE
1199
1051
  debug_stop(VALUE self)
@@ -1206,156 +1058,13 @@ debug_stop(VALUE self)
1206
1058
 
1207
1059
  rb_remove_event_hook(debug_event_hook);
1208
1060
 
1209
- locker = Qnil;
1210
- breakpoints = Qnil;
1211
- threads_tbl = Qnil;
1061
+ locker = Qnil;
1062
+ rdebug_breakpoints = Qnil;
1063
+ rdebug_threads_tbl = Qnil;
1212
1064
 
1213
1065
  return Qtrue;
1214
1066
  }
1215
1067
 
1216
- static void
1217
- breakpoint_mark(void *data)
1218
- {
1219
- debug_breakpoint_t *breakpoint;
1220
- breakpoint = (debug_breakpoint_t *)data;
1221
- rb_gc_mark(breakpoint->source);
1222
- rb_gc_mark(breakpoint->expr);
1223
- }
1224
-
1225
- static VALUE
1226
- create_breakpoint_from_args(int argc, VALUE *argv, int id)
1227
- {
1228
- VALUE source, pos, expr;
1229
- debug_breakpoint_t *breakpoint;
1230
- int type;
1231
-
1232
- if(rb_scan_args(argc, argv, "21", &source, &pos, &expr) == 2)
1233
- {
1234
- expr = Qnil;
1235
- }
1236
- type = FIXNUM_P(pos) ? BP_POS_TYPE : BP_METHOD_TYPE;
1237
- if(type == BP_POS_TYPE)
1238
- source = StringValue(source);
1239
- else
1240
- pos = StringValue(pos);
1241
- breakpoint = ALLOC(debug_breakpoint_t);
1242
- breakpoint->id = id;
1243
- breakpoint->source = source;
1244
- breakpoint->type = type;
1245
- if(type == BP_POS_TYPE)
1246
- breakpoint->pos.line = FIX2INT(pos);
1247
- else
1248
- breakpoint->pos.mid = rb_intern(RSTRING(pos)->ptr);
1249
- breakpoint->enabled = Qtrue;
1250
- breakpoint->expr = NIL_P(expr) ? expr: StringValue(expr);
1251
- breakpoint->hit_count = 0;
1252
- breakpoint->hit_value = 0;
1253
- breakpoint->hit_condition = HIT_COND_NONE;
1254
- return Data_Wrap_Struct(cBreakpoint, breakpoint_mark, xfree, breakpoint);
1255
- }
1256
-
1257
- /*
1258
- * call-seq:
1259
- * Debugger.add_breakpoint(source, pos, condition = nil) -> breakpoint
1260
- *
1261
- * Adds a new breakpoint.
1262
- * <i>source</i> is a name of a file or a class.
1263
- * <i>pos</i> is a line number or a method name if <i>source</i> is a class name.
1264
- * <i>condition</i> is a string which is evaluated to +true+ when this breakpoint
1265
- * is activated.
1266
- */
1267
- static VALUE
1268
- debug_add_breakpoint(int argc, VALUE *argv, VALUE self)
1269
- {
1270
- VALUE result;
1271
-
1272
- debug_check_started();
1273
-
1274
- result = create_breakpoint_from_args(argc, argv, ++bkp_count);
1275
- rb_ary_push(breakpoints, result);
1276
- return result;
1277
- }
1278
-
1279
- /*
1280
- * call-seq:
1281
- * Debugger.remove_breakpoint(id) -> breakpoint
1282
- *
1283
- * Removes breakpoint by its id.
1284
- * <i>id</i> is an identificator of a breakpoint.
1285
- */
1286
- static VALUE
1287
- debug_remove_breakpoint(VALUE self, VALUE id_value)
1288
- {
1289
- int i;
1290
- int id;
1291
- VALUE breakpoint;
1292
- debug_breakpoint_t *debug_breakpoint;
1293
-
1294
- id = FIX2INT(id_value);
1295
-
1296
- for( i = 0; i < RARRAY(breakpoints)->len; i += 1 )
1297
- {
1298
- breakpoint = rb_ary_entry(breakpoints, i);
1299
- Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
1300
- if(debug_breakpoint->id == id)
1301
- {
1302
- rb_ary_delete_at(breakpoints, i);
1303
- return breakpoint;
1304
- }
1305
- }
1306
- return Qnil;
1307
- }
1308
-
1309
- /*
1310
- * call-seq:
1311
- * Debugger.breakpoints -> array
1312
- *
1313
- * Returns an array of breakpoints.
1314
- */
1315
- static VALUE
1316
- debug_breakpoints(VALUE self)
1317
- {
1318
- debug_check_started();
1319
-
1320
- return breakpoints;
1321
- }
1322
-
1323
- /*
1324
- * call-seq:
1325
- * Debugger.checkpoint -> string
1326
- *
1327
- * Returns a current checkpoint, which is a name of exception that will
1328
- * trigger a debugger when raised.
1329
- */
1330
- static VALUE
1331
- debug_catchpoint(VALUE self)
1332
- {
1333
- debug_check_started();
1334
-
1335
- return catchpoint;
1336
- }
1337
-
1338
- /*
1339
- * call-seq:
1340
- * Debugger.checkpoint = string -> string
1341
- *
1342
- * Sets checkpoint.
1343
- */
1344
- static VALUE
1345
- debug_set_catchpoint(VALUE self, VALUE value)
1346
- {
1347
- debug_check_started();
1348
-
1349
- if (!NIL_P(value) && TYPE(value) != T_STRING) {
1350
- rb_raise(rb_eTypeError, "value of checkpoint must be String");
1351
- }
1352
- if(NIL_P(value))
1353
- catchpoint = Qnil;
1354
- else
1355
- catchpoint = rb_str_dup(value);
1356
- return value;
1357
- }
1358
-
1359
1068
  static int
1360
1069
  find_last_context_func(VALUE key, VALUE value, VALUE *result)
1361
1070
  {
@@ -1383,7 +1092,7 @@ debug_last_interrupted(VALUE self)
1383
1092
 
1384
1093
  debug_check_started();
1385
1094
 
1386
- Data_Get_Struct(threads_tbl, threads_table_t, threads_table);
1095
+ Data_Get_Struct(rdebug_threads_tbl, threads_table_t, threads_table);
1387
1096
 
1388
1097
  st_foreach(threads_table->tbl, find_last_context_func, (st_data_t)&result);
1389
1098
  return result;
@@ -1451,8 +1160,8 @@ debug_contexts(VALUE self)
1451
1160
  thread_context_lookup(thread, &context, NULL);
1452
1161
  rb_ary_push(new_list, context);
1453
1162
  }
1454
- threads_table_clear(threads_tbl);
1455
- Data_Get_Struct(threads_tbl, threads_table_t, threads_table);
1163
+ threads_table_clear(rdebug_threads_tbl);
1164
+ Data_Get_Struct(rdebug_threads_tbl, threads_table_t, threads_table);
1456
1165
  for(i = 0; i < RARRAY(new_list)->len; i++)
1457
1166
  {
1458
1167
  context = rb_ary_entry(new_list, i);
@@ -1665,30 +1374,57 @@ debug_thread_inherited(VALUE klass)
1665
1374
 
1666
1375
  /*
1667
1376
  * call-seq:
1668
- * Debugger.debug_load(file, stop = false) -> nil
1377
+ * Debugger.debug_load(file, stop = false, increment_start = false) -> nil
1669
1378
  *
1670
1379
  * Same as Kernel#load but resets current context's frames.
1671
- * +stop+ parameter force the debugger to stop at the first line of code in the +file+
1380
+ * +stop+ parameter forces the debugger to stop at the first line of code in the +file+
1381
+ * +increment_start+ determines if start_count should be incremented. When
1382
+ * control threads are used, they have to be set up before loading the
1383
+ * debugger; so here +increment_start+ will be false.
1672
1384
  * FOR INTERNAL USE ONLY.
1673
1385
  */
1674
1386
  static VALUE
1675
1387
  debug_debug_load(int argc, VALUE *argv, VALUE self)
1676
1388
  {
1677
- VALUE file, stop, context;
1389
+ VALUE file, stop, context, increment_start;
1678
1390
  debug_context_t *debug_context;
1679
-
1680
- if(rb_scan_args(argc, argv, "11", &file, &stop) == 1)
1681
- stop = Qfalse;
1391
+ int state = 0;
1392
+
1393
+ if(rb_scan_args(argc, argv, "12", &file, &stop, &increment_start) == 1)
1394
+ {
1395
+ stop = Qfalse;
1396
+ increment_start = Qtrue;
1397
+ }
1682
1398
 
1683
1399
  debug_start(self);
1400
+ if (Qfalse == increment_start) start_count--;
1401
+
1684
1402
  context = debug_current_context(self);
1685
1403
  Data_Get_Struct(context, debug_context_t, debug_context);
1686
1404
  debug_context->stack_size = 0;
1687
1405
  if(RTEST(stop))
1688
1406
  debug_context->stop_next = 1;
1689
- rb_load(file, 0);
1407
+ /* Initializing $0 to the script's path */
1408
+ ruby_script(RSTRING(file)->ptr);
1409
+ rb_load_protect(file, 0, &state);
1410
+ if (0 != state) {
1411
+ VALUE errinfo = ruby_errinfo;
1412
+ debug_suspend(self);
1413
+ reset_stepping_stop_points(debug_context);
1414
+ ruby_errinfo = Qnil;
1415
+ return errinfo;
1416
+ }
1417
+
1418
+ /* We should run all at_exit handler's in order to provide,
1419
+ * for instance, a chance to run all defined test cases */
1420
+ rb_exec_end_proc();
1421
+
1422
+ /* We could have issued a Debugger.stop inside the debug
1423
+ session. */
1424
+ if (start_count > 0) {
1425
+ debug_stop(self);
1426
+ }
1690
1427
 
1691
- debug_stop(self);
1692
1428
  return Qnil;
1693
1429
  }
1694
1430
 
@@ -1836,7 +1572,7 @@ context_step_over(int argc, VALUE *argv, VALUE self)
1836
1572
  * call-seq:
1837
1573
  * context.stop_frame(frame)
1838
1574
  *
1839
- * Stops when a frame with number +frame+ is activated. Implements +up+ and +down+ commands.
1575
+ * Stops when a frame with number +frame+ is activated. Implements +finish+ and +next+ commands.
1840
1576
  */
1841
1577
  static VALUE
1842
1578
  context_stop_frame(VALUE self, VALUE frame)
@@ -2341,7 +2077,7 @@ context_tracing(VALUE self)
2341
2077
 
2342
2078
  /*
2343
2079
  * call-seq:
2344
- * context.tracking = bool
2080
+ * context.tracing = bool
2345
2081
  *
2346
2082
  * Controls the tracing for this context.
2347
2083
  */
@@ -2395,50 +2131,6 @@ context_dead(VALUE self)
2395
2131
  return CTX_FL_TEST(debug_context, CTX_FL_DEAD) ? Qtrue : Qfalse;
2396
2132
  }
2397
2133
 
2398
- /*
2399
- * call-seq:
2400
- * context.breakpoint -> breakpoint
2401
- *
2402
- * Returns a context-specific temporary Breakpoint object.
2403
- */
2404
- static VALUE
2405
- context_breakpoint(VALUE self)
2406
- {
2407
- debug_context_t *debug_context;
2408
-
2409
- debug_check_started();
2410
-
2411
- Data_Get_Struct(self, debug_context_t, debug_context);
2412
- return debug_context->breakpoint;
2413
- }
2414
-
2415
- /*
2416
- * call-seq:
2417
- * context.set_breakpoint(source, pos, condition = nil) -> breakpoint
2418
- *
2419
- * Sets a context-specific temporary breakpoint, which can be used to implement
2420
- * 'Run to Cursor' debugger function. When this breakpoint is reached, it will be
2421
- * cleared out.
2422
- *
2423
- * <i>source</i> is a name of a file or a class.
2424
- * <i>pos</i> is a line number or a method name if <i>source</i> is a class name.
2425
- * <i>condition</i> is a string which is evaluated to +true+ when this breakpoint
2426
- * is activated.
2427
- */
2428
- static VALUE
2429
- context_set_breakpoint(int argc, VALUE *argv, VALUE self)
2430
- {
2431
- VALUE result;
2432
- debug_context_t *debug_context;
2433
-
2434
- debug_check_started();
2435
-
2436
- Data_Get_Struct(self, debug_context_t, debug_context);
2437
- result = create_breakpoint_from_args(argc, argv, 0);
2438
- debug_context->breakpoint = result;
2439
- return result;
2440
- }
2441
-
2442
2134
  /*
2443
2135
  * call-seq:
2444
2136
  * context.stop_reason -> sym
@@ -2478,262 +2170,13 @@ context_stop_reason(VALUE self)
2478
2170
  }
2479
2171
 
2480
2172
 
2481
- /*
2482
- * call-seq:
2483
- * breakpoint.enabled?
2484
- *
2485
- * Returns whether breakpoint is enabled or not.
2486
- */
2487
- static VALUE
2488
- breakpoint_enabled(VALUE self)
2489
- {
2490
- debug_breakpoint_t *breakpoint;
2491
-
2492
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2493
- return breakpoint->enabled;
2494
- }
2495
-
2496
- /*
2497
- * call-seq:
2498
- * breakpoint.enabled = bool
2499
- *
2500
- * Enables or disables breakpoint.
2501
- */
2502
- static VALUE
2503
- breakpoint_set_enabled(VALUE self, VALUE bool)
2504
- {
2505
- debug_breakpoint_t *breakpoint;
2506
-
2507
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2508
- return breakpoint->enabled = bool;
2509
- }
2510
-
2511
- /*
2512
- * call-seq:
2513
- * breakpoint.source -> string
2514
- *
2515
- * Returns a source of the breakpoint.
2516
- */
2517
- static VALUE
2518
- breakpoint_source(VALUE self)
2519
- {
2520
- debug_breakpoint_t *breakpoint;
2521
-
2522
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2523
- return breakpoint->source;
2524
- }
2525
-
2526
- /*
2527
- * call-seq:
2528
- * breakpoint.source = string
2529
- *
2530
- * Sets the source of the breakpoint.
2531
- */
2532
- static VALUE
2533
- breakpoint_set_source(VALUE self, VALUE value)
2534
- {
2535
- debug_breakpoint_t *breakpoint;
2536
-
2537
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2538
- breakpoint->source = StringValue(value);
2539
- return value;
2540
- }
2541
-
2542
- /*
2543
- * call-seq:
2544
- * breakpoint.pos -> string or int
2545
- *
2546
- * Returns a position of this breakpoint.
2547
- */
2548
- static VALUE
2549
- breakpoint_pos(VALUE self)
2550
- {
2551
- debug_breakpoint_t *breakpoint;
2552
-
2553
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2554
- if(breakpoint->type == BP_METHOD_TYPE)
2555
- return rb_str_new2(rb_id2name(breakpoint->pos.mid));
2556
- else
2557
- return INT2FIX(breakpoint->pos.line);
2558
- }
2559
-
2560
- /*
2561
- * call-seq:
2562
- * breakpoint.pos = string or int
2563
- *
2564
- * Sets the position of this breakpoint.
2565
- */
2566
- static VALUE
2567
- breakpoint_set_pos(VALUE self, VALUE value)
2568
- {
2569
- debug_breakpoint_t *breakpoint;
2570
-
2571
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2572
- if(breakpoint->type == BP_METHOD_TYPE)
2573
- {
2574
- breakpoint->pos.mid = rb_to_id(StringValue(value));
2575
- }
2576
- else
2577
- breakpoint->pos.line = FIX2INT(value);
2578
- return value;
2579
- }
2580
-
2581
- /*
2582
- * call-seq:
2583
- * breakpoint.expr -> string
2584
- *
2585
- * Returns a codition expression when this breakpoint should be activated.
2586
- */
2587
- static VALUE
2588
- breakpoint_expr(VALUE self)
2589
- {
2590
- debug_breakpoint_t *breakpoint;
2591
-
2592
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2593
- return breakpoint->expr;
2594
- }
2595
-
2596
- /*
2597
- * call-seq:
2598
- * breakpoint.expr = string
2599
- *
2600
- * Sets the codition expression when this breakpoint should be activated.
2601
- */
2602
- static VALUE
2603
- breakpoint_set_expr(VALUE self, VALUE value)
2604
- {
2605
- debug_breakpoint_t *breakpoint;
2606
-
2607
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2608
- breakpoint->expr = StringValue(value);
2609
- return value;
2610
- }
2611
-
2612
- /*
2613
- * call-seq:
2614
- * breakpoint.id -> int
2615
- *
2616
- * Returns id of the breakpoint.
2617
- */
2618
- static VALUE
2619
- breakpoint_id(VALUE self)
2620
- {
2621
- debug_breakpoint_t *breakpoint;
2622
-
2623
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2624
- return INT2FIX(breakpoint->id);
2625
- }
2626
-
2627
- /*
2628
- * call-seq:
2629
- * breakpoint.hit_count -> int
2630
- *
2631
- * Returns the hit count of the breakpoint.
2632
- */
2633
- static VALUE
2634
- breakpoint_hit_count(VALUE self)
2635
- {
2636
- debug_breakpoint_t *breakpoint;
2637
-
2638
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2639
- return INT2FIX(breakpoint->hit_count);
2640
- }
2641
-
2642
- /*
2643
- * call-seq:
2644
- * breakpoint.hit_value -> int
2645
- *
2646
- * Returns the hit value of the breakpoint.
2647
- */
2648
- static VALUE
2649
- breakpoint_hit_value(VALUE self)
2650
- {
2651
- debug_breakpoint_t *breakpoint;
2652
-
2653
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2654
- return INT2FIX(breakpoint->hit_value);
2655
- }
2656
-
2657
- /*
2658
- * call-seq:
2659
- * breakpoint.hit_value = int
2660
- *
2661
- * Sets the hit value of the breakpoint.
2662
- */
2663
- static VALUE
2664
- breakpoint_set_hit_value(VALUE self, VALUE value)
2665
- {
2666
- debug_breakpoint_t *breakpoint;
2667
-
2668
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2669
- breakpoint->hit_value = FIX2INT(value);
2670
- return value;
2671
- }
2672
-
2673
- /*
2674
- * call-seq:
2675
- * breakpoint.hit_condition -> symbol
2676
- *
2677
- * Returns the hit condition of the breakpoint:
2678
- *
2679
- * +nil+ if it is an unconditional breakpoint, or
2680
- * :greater_or_equal, :equal, :modulo
2681
- */
2682
- static VALUE
2683
- breakpoint_hit_condition(VALUE self)
2684
- {
2685
- debug_breakpoint_t *breakpoint;
2686
-
2687
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2688
- switch(breakpoint->hit_condition)
2689
- {
2690
- case HIT_COND_GE:
2691
- return ID2SYM(rb_intern("greater_or_equal"));
2692
- case HIT_COND_EQ:
2693
- return ID2SYM(rb_intern("equal"));
2694
- case HIT_COND_MOD:
2695
- return ID2SYM(rb_intern("modulo"));
2696
- case HIT_COND_NONE:
2697
- default:
2698
- return Qnil;
2699
- }
2700
- }
2701
-
2702
- /*
2703
- * call-seq:
2704
- * breakpoint.hit_condition = symbol
2705
- *
2706
- * Sets the hit condition of the breakpoint which must be one of the following values:
2707
- *
2708
- * +nil+ if it is an unconditional breakpoint, or
2709
- * :greater_or_equal(:ge), :equal(:eq), :modulo(:mod)
2710
- */
2711
- static VALUE
2712
- breakpoint_set_hit_condition(VALUE self, VALUE value)
2713
- {
2714
- debug_breakpoint_t *breakpoint;
2715
- ID id_value;
2716
-
2717
- Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
2718
- id_value = rb_to_id(value);
2719
-
2720
- if(rb_intern("greater_or_equal") == id_value || rb_intern("ge") == id_value)
2721
- breakpoint->hit_condition = HIT_COND_GE;
2722
- else if(rb_intern("equal") == id_value || rb_intern("eq") == id_value)
2723
- breakpoint->hit_condition = HIT_COND_EQ;
2724
- else if(rb_intern("modulo") == id_value || rb_intern("mod") == id_value)
2725
- breakpoint->hit_condition = HIT_COND_MOD;
2726
- else
2727
- rb_raise(rb_eArgError, "Invalid condition parameter");
2728
- return value;
2729
- }
2730
-
2731
2173
  /*
2732
2174
  * Document-class: Context
2733
2175
  *
2734
- * == Summary
2735
- *
2736
- * Debugger keeps a single instance of this class for each Ruby thread.
2176
+ * The Debugger module keeps a single instance of this class for
2177
+ * each Ruby thread. It contains a call-stack information, thread
2178
+ * information, breakpoint information and the reason the program is
2179
+ * stopped.
2737
2180
  */
2738
2181
  static void
2739
2182
  Init_context()
@@ -2764,46 +2207,53 @@ Init_context()
2764
2207
  rb_define_method(cContext, "frame_self", context_frame_self, -1);
2765
2208
  rb_define_method(cContext, "stack_size", context_stack_size, 0);
2766
2209
  rb_define_method(cContext, "dead?", context_dead, 0);
2767
- rb_define_method(cContext, "breakpoint", context_breakpoint, 0);
2768
- rb_define_method(cContext, "set_breakpoint", context_set_breakpoint, -1);
2210
+ rb_define_method(cContext, "breakpoint",
2211
+ context_breakpoint, 0); /* in breakpoint.c */
2212
+ rb_define_method(cContext, "set_breakpoint",
2213
+ context_set_breakpoint, -1); /* in breakpoint.c */
2769
2214
  }
2770
2215
 
2771
2216
  /*
2772
- * Document-class: Breakpoint
2773
- *
2774
- * == Summary
2217
+ * call-seq:
2218
+ * Debugger.breakpoints -> Array
2775
2219
  *
2776
- * This class represents a breakpoint. It defines position of the breakpoint and
2777
- * condition when this breakpoint should be triggered.
2220
+ * Returns an Array of Breakpoint objects; all the breakpoints that
2221
+ * have been created.
2778
2222
  */
2779
- static void
2780
- Init_breakpoint()
2781
- {
2782
- cBreakpoint = rb_define_class_under(mDebugger, "Breakpoint", rb_cObject);
2783
- rb_define_method(cBreakpoint, "id", breakpoint_id, 0);
2784
- rb_define_method(cBreakpoint, "source", breakpoint_source, 0);
2785
- rb_define_method(cBreakpoint, "source=", breakpoint_set_source, 1);
2786
- rb_define_method(cBreakpoint, "enabled?", breakpoint_enabled, 0);
2787
- rb_define_method(cBreakpoint, "enabled=", breakpoint_set_enabled, 1);
2788
- rb_define_method(cBreakpoint, "pos", breakpoint_pos, 0);
2789
- rb_define_method(cBreakpoint, "pos=", breakpoint_set_pos, 1);
2790
- rb_define_method(cBreakpoint, "expr", breakpoint_expr, 0);
2791
- rb_define_method(cBreakpoint, "expr=", breakpoint_set_expr, 1);
2792
- rb_define_method(cBreakpoint, "hit_count", breakpoint_hit_count, 0);
2793
- rb_define_method(cBreakpoint, "hit_value", breakpoint_hit_value, 0);
2794
- rb_define_method(cBreakpoint, "hit_value=", breakpoint_set_hit_value, 1);
2795
- rb_define_method(cBreakpoint, "hit_condition", breakpoint_hit_condition, 0);
2796
- rb_define_method(cBreakpoint, "hit_condition=", breakpoint_set_hit_condition, 1);
2223
+ static VALUE
2224
+ debug_breakpoints(VALUE self)
2225
+ {
2226
+ debug_check_started();
2227
+
2228
+ return rdebug_breakpoints;
2797
2229
  }
2798
2230
 
2231
+ /*
2232
+ * call-seq:
2233
+ * Debugger.add_breakpoint(source, pos, condition = nil) -> breakpoint
2234
+ *
2235
+ * Adds a new breakpoint.
2236
+ * <i>source</i> is a name of a file or a class.
2237
+ * <i>pos</i> is a line number or a method name if <i>source</i> is a class name.
2238
+ * <i>condition</i> is a string which is evaluated to +true+ when this breakpoint
2239
+ * is activated.
2240
+ */
2241
+ static VALUE
2242
+ debug_add_breakpoint(int argc, VALUE *argv, VALUE self)
2243
+ {
2244
+ VALUE result;
2245
+
2246
+ debug_check_started();
2247
+
2248
+ result = create_breakpoint_from_args(argc, argv, ++bkp_count);
2249
+ rb_ary_push(rdebug_breakpoints, result);
2250
+ return result;
2251
+ }
2799
2252
 
2800
2253
  /*
2801
2254
  * Document-class: Debugger
2802
2255
  *
2803
- * == Summary
2804
- *
2805
- * This is a singleton class allows controlling the debugger. Use it to start/stop debugger,
2806
- * set/remove breakpoints, etc.
2256
+ * _Debugger_ is the module name space for ruby-debug.
2807
2257
  */
2808
2258
  #if defined(_WIN32)
2809
2259
  __declspec(dllexport)
@@ -2813,15 +2263,18 @@ Init_ruby_debug()
2813
2263
  {
2814
2264
  mDebugger = rb_define_module("Debugger");
2815
2265
  rb_define_const(mDebugger, "VERSION", rb_str_new2(DEBUG_VERSION));
2816
- rb_define_module_function(mDebugger, "start", debug_start, 0);
2266
+ rb_define_module_function(mDebugger, "start_", debug_start, 0);
2817
2267
  rb_define_module_function(mDebugger, "stop", debug_stop, 0);
2818
2268
  rb_define_module_function(mDebugger, "started?", debug_is_started, 0);
2819
2269
  rb_define_module_function(mDebugger, "breakpoints", debug_breakpoints, 0);
2820
2270
  rb_define_module_function(mDebugger, "add_breakpoint", debug_add_breakpoint, -1);
2821
2271
  rb_define_module_function(mDebugger, "remove_breakpoint",
2822
- debug_remove_breakpoint, 1);
2823
- rb_define_module_function(mDebugger, "catchpoint", debug_catchpoint, 0);
2824
- rb_define_module_function(mDebugger, "catchpoint=", debug_set_catchpoint, 1);
2272
+ rdebug_remove_breakpoint,
2273
+ 1); /* in breakpoint.c */
2274
+ rb_define_module_function(mDebugger, "add_catchpoint",
2275
+ rdebug_add_catchpoint, 1); /* in breakpoint.c */
2276
+ rb_define_module_function(mDebugger, "catchpoints",
2277
+ debug_catchpoints, 0); /* in breakpoint.c */
2825
2278
  rb_define_module_function(mDebugger, "last_context", debug_last_interrupted, 0);
2826
2279
  rb_define_module_function(mDebugger, "contexts", debug_contexts, 0);
2827
2280
  rb_define_module_function(mDebugger, "current_context", debug_current_context, 0);
@@ -2835,8 +2288,10 @@ Init_ruby_debug()
2835
2288
  rb_define_module_function(mDebugger, "debug_at_exit", debug_at_exit, 0);
2836
2289
  rb_define_module_function(mDebugger, "post_mortem?", debug_post_mortem, 0);
2837
2290
  rb_define_module_function(mDebugger, "post_mortem=", debug_set_post_mortem, 1);
2838
- rb_define_module_function(mDebugger, "keep_frame_binding?", debug_keep_frame_binding, 0);
2839
- rb_define_module_function(mDebugger, "keep_frame_binding=", debug_set_keep_frame_binding, 1);
2291
+ rb_define_module_function(mDebugger, "keep_frame_binding?",
2292
+ debug_keep_frame_binding, 0);
2293
+ rb_define_module_function(mDebugger, "keep_frame_binding=",
2294
+ debug_set_keep_frame_binding, 1);
2840
2295
  rb_define_module_function(mDebugger, "track_frame_args?",
2841
2296
  debug_track_frame_args, 0);
2842
2297
  rb_define_module_function(mDebugger, "track_frame_args=",
@@ -2847,24 +2302,25 @@ Init_ruby_debug()
2847
2302
  cThreadsTable = rb_define_class_under(mDebugger, "ThreadsTable", rb_cObject);
2848
2303
 
2849
2304
  cDebugThread = rb_define_class_under(mDebugger, "DebugThread", rb_cThread);
2850
- rb_define_singleton_method(cDebugThread, "inherited", debug_thread_inherited, 1);
2305
+ rb_define_singleton_method(cDebugThread, "inherited",
2306
+ debug_thread_inherited, 1);
2851
2307
 
2852
2308
  Init_context();
2853
2309
  Init_breakpoint();
2854
2310
 
2855
- idAtLine = rb_intern("at_line");
2856
2311
  idAtBreakpoint = rb_intern("at_breakpoint");
2857
2312
  idAtCatchpoint = rb_intern("at_catchpoint");
2313
+ idAtLine = rb_intern("at_line");
2314
+ idAtReturn = rb_intern("at_return");
2858
2315
  idAtTracing = rb_intern("at_tracing");
2859
- idEval = rb_intern("eval");
2860
2316
  idList = rb_intern("list");
2861
2317
 
2862
2318
  rb_mObjectSpace = rb_const_get(rb_mKernel, rb_intern("ObjectSpace"));
2863
2319
 
2864
- rb_global_variable(&threads_tbl);
2865
- rb_global_variable(&breakpoints);
2866
- rb_global_variable(&catchpoint);
2867
- rb_global_variable(&locker);
2868
2320
  rb_global_variable(&last_context);
2869
2321
  rb_global_variable(&last_thread);
2322
+ rb_global_variable(&locker);
2323
+ rb_global_variable(&rdebug_breakpoints);
2324
+ rb_global_variable(&rdebug_catchpoints);
2325
+ rb_global_variable(&rdebug_threads_tbl);
2870
2326
  }