debugger2 1.0.0.beta1

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.
Files changed (183) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.travis.yml +3 -0
  4. data/AUTHORS +10 -0
  5. data/CHANGELOG.md +65 -0
  6. data/CONTRIBUTING.md +1 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE +23 -0
  9. data/OLDER_CHANGELOG +334 -0
  10. data/OLD_CHANGELOG +5655 -0
  11. data/OLD_README +122 -0
  12. data/README.md +108 -0
  13. data/Rakefile +78 -0
  14. data/bin/rdebug +397 -0
  15. data/debugger2.gemspec +29 -0
  16. data/doc/.cvsignore +42 -0
  17. data/doc/Makefile.am +63 -0
  18. data/doc/emacs-notes.txt +38 -0
  19. data/doc/hanoi.rb +35 -0
  20. data/doc/primes.rb +28 -0
  21. data/doc/rdebug-emacs.texi +1030 -0
  22. data/doc/ruby-debug.texi +3791 -0
  23. data/doc/test-tri2.rb +18 -0
  24. data/doc/tri3.rb +8 -0
  25. data/doc/triangle.rb +12 -0
  26. data/emacs/Makefile.am +130 -0
  27. data/emacs/rdebug-annotate.el +385 -0
  28. data/emacs/rdebug-breaks.el +407 -0
  29. data/emacs/rdebug-cmd.el +92 -0
  30. data/emacs/rdebug-core.el +502 -0
  31. data/emacs/rdebug-dbg.el +62 -0
  32. data/emacs/rdebug-error.el +79 -0
  33. data/emacs/rdebug-fns.el +111 -0
  34. data/emacs/rdebug-frames.el +230 -0
  35. data/emacs/rdebug-gud.el +242 -0
  36. data/emacs/rdebug-help.el +104 -0
  37. data/emacs/rdebug-info.el +83 -0
  38. data/emacs/rdebug-layouts.el +180 -0
  39. data/emacs/rdebug-locring.el +118 -0
  40. data/emacs/rdebug-output.el +106 -0
  41. data/emacs/rdebug-regexp.el +118 -0
  42. data/emacs/rdebug-secondary.el +260 -0
  43. data/emacs/rdebug-shortkey.el +175 -0
  44. data/emacs/rdebug-source.el +568 -0
  45. data/emacs/rdebug-track.el +392 -0
  46. data/emacs/rdebug-varbuf.el +150 -0
  47. data/emacs/rdebug-vars.el +125 -0
  48. data/emacs/rdebug-watch.el +132 -0
  49. data/emacs/rdebug.el +326 -0
  50. data/emacs/test/elk-test.el +242 -0
  51. data/emacs/test/test-annotate.el +103 -0
  52. data/emacs/test/test-cmd.el +116 -0
  53. data/emacs/test/test-core.el +104 -0
  54. data/emacs/test/test-fns.el +65 -0
  55. data/emacs/test/test-frames.el +62 -0
  56. data/emacs/test/test-gud.el +35 -0
  57. data/emacs/test/test-indent.el +58 -0
  58. data/emacs/test/test-regexp.el +144 -0
  59. data/emacs/test/test-shortkey.el +61 -0
  60. data/ext/ruby_debug/breakpoint.c +630 -0
  61. data/ext/ruby_debug/extconf.rb +11 -0
  62. data/ext/ruby_debug/ruby_debug.c +2203 -0
  63. data/ext/ruby_debug/ruby_debug.h +151 -0
  64. data/lib/debugger.rb +5 -0
  65. data/lib/debugger/version.rb +5 -0
  66. data/lib/debugger2.rb +6 -0
  67. data/lib/ruby-debug-base.rb +307 -0
  68. data/lib/ruby-debug.rb +176 -0
  69. data/lib/ruby-debug/command.rb +227 -0
  70. data/lib/ruby-debug/commands/breakpoints.rb +153 -0
  71. data/lib/ruby-debug/commands/catchpoint.rb +55 -0
  72. data/lib/ruby-debug/commands/condition.rb +49 -0
  73. data/lib/ruby-debug/commands/continue.rb +38 -0
  74. data/lib/ruby-debug/commands/control.rb +107 -0
  75. data/lib/ruby-debug/commands/display.rb +120 -0
  76. data/lib/ruby-debug/commands/edit.rb +48 -0
  77. data/lib/ruby-debug/commands/enable.rb +202 -0
  78. data/lib/ruby-debug/commands/eval.rb +176 -0
  79. data/lib/ruby-debug/commands/finish.rb +42 -0
  80. data/lib/ruby-debug/commands/frame.rb +301 -0
  81. data/lib/ruby-debug/commands/help.rb +56 -0
  82. data/lib/ruby-debug/commands/info.rb +467 -0
  83. data/lib/ruby-debug/commands/irb.rb +123 -0
  84. data/lib/ruby-debug/commands/jump.rb +66 -0
  85. data/lib/ruby-debug/commands/kill.rb +51 -0
  86. data/lib/ruby-debug/commands/list.rb +94 -0
  87. data/lib/ruby-debug/commands/method.rb +84 -0
  88. data/lib/ruby-debug/commands/quit.rb +39 -0
  89. data/lib/ruby-debug/commands/reload.rb +40 -0
  90. data/lib/ruby-debug/commands/save.rb +90 -0
  91. data/lib/ruby-debug/commands/set.rb +223 -0
  92. data/lib/ruby-debug/commands/show.rb +247 -0
  93. data/lib/ruby-debug/commands/skip.rb +35 -0
  94. data/lib/ruby-debug/commands/source.rb +36 -0
  95. data/lib/ruby-debug/commands/stepping.rb +81 -0
  96. data/lib/ruby-debug/commands/threads.rb +189 -0
  97. data/lib/ruby-debug/commands/tmate.rb +36 -0
  98. data/lib/ruby-debug/commands/trace.rb +57 -0
  99. data/lib/ruby-debug/commands/variables.rb +199 -0
  100. data/lib/ruby-debug/debugger.rb +5 -0
  101. data/lib/ruby-debug/helper.rb +69 -0
  102. data/lib/ruby-debug/interface.rb +232 -0
  103. data/lib/ruby-debug/processor.rb +474 -0
  104. data/man/rdebug.1 +241 -0
  105. data/old_scripts/Makefile.am +14 -0
  106. data/old_scripts/README.md +2 -0
  107. data/old_scripts/autogen.sh +4 -0
  108. data/old_scripts/configure.ac +12 -0
  109. data/old_scripts/rdbg.rb +33 -0
  110. data/old_scripts/runner.sh +7 -0
  111. data/old_scripts/svn2cl_usermap +3 -0
  112. data/test/.cvsignore +1 -0
  113. data/test/breakpoints_test.rb +366 -0
  114. data/test/conditions_test.rb +77 -0
  115. data/test/continue_test.rb +28 -0
  116. data/test/display_test.rb +143 -0
  117. data/test/edit_test.rb +55 -0
  118. data/test/eval_test.rb +94 -0
  119. data/test/examples/breakpoint1.rb +15 -0
  120. data/test/examples/breakpoint2.rb +7 -0
  121. data/test/examples/conditions.rb +4 -0
  122. data/test/examples/continue.rb +4 -0
  123. data/test/examples/display.rb +5 -0
  124. data/test/examples/edit.rb +3 -0
  125. data/test/examples/edit2.rb +3 -0
  126. data/test/examples/eval.rb +4 -0
  127. data/test/examples/finish.rb +20 -0
  128. data/test/examples/frame.rb +31 -0
  129. data/test/examples/help.rb +2 -0
  130. data/test/examples/info.rb +48 -0
  131. data/test/examples/info2.rb +3 -0
  132. data/test/examples/irb.rb +6 -0
  133. data/test/examples/jump.rb +14 -0
  134. data/test/examples/kill.rb +2 -0
  135. data/test/examples/list.rb +12 -0
  136. data/test/examples/method.rb +15 -0
  137. data/test/examples/post_mortem.rb +19 -0
  138. data/test/examples/quit.rb +2 -0
  139. data/test/examples/reload.rb +6 -0
  140. data/test/examples/restart.rb +6 -0
  141. data/test/examples/save.rb +3 -0
  142. data/test/examples/set.rb +3 -0
  143. data/test/examples/set_annotate.rb +12 -0
  144. data/test/examples/settings.rb +1 -0
  145. data/test/examples/show.rb +2 -0
  146. data/test/examples/source.rb +3 -0
  147. data/test/examples/stepping.rb +21 -0
  148. data/test/examples/thread.rb +32 -0
  149. data/test/examples/tmate.rb +10 -0
  150. data/test/examples/trace.rb +7 -0
  151. data/test/examples/trace_threads.rb +20 -0
  152. data/test/examples/variables.rb +26 -0
  153. data/test/finish_test.rb +49 -0
  154. data/test/frame_test.rb +140 -0
  155. data/test/help_test.rb +51 -0
  156. data/test/info_test.rb +326 -0
  157. data/test/irb_test.rb +82 -0
  158. data/test/jump_test.rb +70 -0
  159. data/test/kill_test.rb +49 -0
  160. data/test/list_test.rb +147 -0
  161. data/test/method_test.rb +72 -0
  162. data/test/post_mortem_test.rb +25 -0
  163. data/test/quit_test.rb +56 -0
  164. data/test/reload_test.rb +47 -0
  165. data/test/restart_test.rb +145 -0
  166. data/test/save_test.rb +94 -0
  167. data/test/set_test.rb +183 -0
  168. data/test/show_test.rb +294 -0
  169. data/test/source_test.rb +46 -0
  170. data/test/stepping_test.rb +122 -0
  171. data/test/support/breakpoint.rb +12 -0
  172. data/test/support/context.rb +14 -0
  173. data/test/support/matchers.rb +67 -0
  174. data/test/support/mocha_extensions.rb +71 -0
  175. data/test/support/processor.rb +7 -0
  176. data/test/support/test_dsl.rb +206 -0
  177. data/test/support/test_interface.rb +66 -0
  178. data/test/test_helper.rb +9 -0
  179. data/test/thread_test.rb +124 -0
  180. data/test/tmate_test.rb +45 -0
  181. data/test/trace_test.rb +156 -0
  182. data/test/variables_test.rb +116 -0
  183. metadata +319 -0
@@ -0,0 +1,61 @@
1
+ ;; -*- emacs-lisp -*-
2
+ ;; This program has to be run from the directory it is currently in and
3
+ ;; the rdebug code has to be in the parent directory
4
+ (load-file "./elk-test.el")
5
+
6
+ ;; FIXME? Should we use "require 'rdebug" here.
7
+ ;; Would have to prepend . to load-path.
8
+ (setq load-path (cons ".." load-path))
9
+ (load-file "../rdebug-shortkey.el")
10
+
11
+ (deftest "rdebug-shortkey-mode-test"
12
+ (let ((buf (generate-new-buffer "shortkey readwrite")))
13
+ (with-current-buffer buf
14
+ (setq buffer-read-only nil)
15
+ ;; turning on short-key-mode make buffer read-only
16
+ (rdebug-internal-short-key-mode 1)
17
+ (assert-equal t buffer-read-only)
18
+
19
+ ;; turning off short-key-mode should make buffer read-write again
20
+ (rdebug-internal-short-key-mode -1)
21
+ (assert-equal nil buffer-read-only)
22
+
23
+ ;; --------------------
24
+ ;; Check multiple "on": and "off:s".
25
+
26
+ (rdebug-internal-short-key-mode 1)
27
+ (assert-equal t buffer-read-only)
28
+
29
+ (rdebug-internal-short-key-mode 1)
30
+ (assert-equal t buffer-read-only)
31
+
32
+ (rdebug-internal-short-key-mode 1)
33
+ (assert-equal t buffer-read-only)
34
+
35
+ (rdebug-internal-short-key-mode -1)
36
+ (assert-equal nil buffer-read-only))
37
+
38
+ (kill-buffer buf))
39
+
40
+ (let ((buf (generate-new-buffer "shortkey readonly")))
41
+ (with-current-buffer buf
42
+ (setq buffer-read-only t)
43
+
44
+ ;; turning on short-key-mode keep buffer read-only
45
+ (rdebug-internal-short-key-mode 1)
46
+ (assert-equal t buffer-read-only)
47
+
48
+ ;; The buffer was originally in read-only mode, it should remain
49
+ ;; there.
50
+ (rdebug-internal-short-key-mode -1)
51
+ (assert-equal t buffer-read-only))
52
+ (kill-buffer buf)))
53
+
54
+ ;; -------------------------------------------------------------------
55
+ ;; Build and run the test suite.
56
+ ;;
57
+
58
+ (build-suite "rdebug-suite"
59
+ "rdebug-shortkey-mode-test")
60
+ (run-elk-test "rdebug-suite"
61
+ "test things in rdebug-shortkey.el")
@@ -0,0 +1,630 @@
1
+ #include <ruby.h>
2
+ #include <stdio.h>
3
+ #include "ruby_debug.h"
4
+
5
+ VALUE rdebug_breakpoints = Qnil;
6
+ VALUE rdebug_catchpoints;
7
+
8
+ static VALUE cBreakpoint;
9
+
10
+ static VALUE
11
+ eval_expression(VALUE args)
12
+ {
13
+ return rb_funcall2(rb_mKernel, rb_intern("eval"), 2, RARRAY_PTR(args));
14
+ }
15
+
16
+ int
17
+ check_breakpoint_hit_condition(VALUE breakpoint)
18
+ {
19
+ debug_breakpoint_t *debug_breakpoint;
20
+
21
+ if(breakpoint == Qnil)
22
+ return 0;
23
+ Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
24
+
25
+ debug_breakpoint->hit_count++;
26
+ if (!Qtrue == debug_breakpoint->enabled) return 0;
27
+ switch(debug_breakpoint->hit_condition)
28
+ {
29
+ case HIT_COND_NONE:
30
+ return 1;
31
+ case HIT_COND_GE:
32
+ {
33
+ if(debug_breakpoint->hit_count >= debug_breakpoint->hit_value)
34
+ return 1;
35
+ break;
36
+ }
37
+ case HIT_COND_EQ:
38
+ {
39
+ if(debug_breakpoint->hit_count == debug_breakpoint->hit_value)
40
+ return 1;
41
+ break;
42
+ }
43
+ case HIT_COND_MOD:
44
+ {
45
+ if(debug_breakpoint->hit_count % debug_breakpoint->hit_value == 0)
46
+ return 1;
47
+ break;
48
+ }
49
+ }
50
+ return 0;
51
+ }
52
+
53
+ #if defined DOSISH
54
+ #define isdirsep(x) ((x) == '/' || (x) == '\\')
55
+ #else
56
+ #define isdirsep(x) ((x) == '/')
57
+ #endif
58
+
59
+ #ifndef min
60
+ #define min(x,y) ((x) < (y) ? (x) : (y))
61
+ #endif
62
+
63
+ static int
64
+ filename_cmp(VALUE source, char *file)
65
+ {
66
+ char *source_ptr, *file_ptr;
67
+ int s_len, f_len, min_len;
68
+ int s,f;
69
+ int dirsep_flag = 0;
70
+
71
+ s_len = RSTRING_LEN(source);
72
+ f_len = strlen(file);
73
+ min_len = min(s_len, f_len);
74
+
75
+ source_ptr = RSTRING_PTR(source);
76
+ file_ptr = file;
77
+
78
+ for( s = s_len - 1, f = f_len - 1; s >= s_len - min_len && f >= f_len - min_len; s--, f-- ) {
79
+ if((source_ptr[s] == '.' || file_ptr[f] == '.') && dirsep_flag)
80
+ return 1;
81
+ if(isdirsep(source_ptr[s]) && isdirsep(file_ptr[f]))
82
+ dirsep_flag = 1;
83
+ #ifdef DOSISH_DRIVE_LETTER
84
+ else if (s == 0)
85
+ return(toupper(source_ptr[s]) == toupper(file_ptr[f]));
86
+ #endif
87
+ else if(source_ptr[s] != file_ptr[f])
88
+ return 0;
89
+ }
90
+ return 1;
91
+ }
92
+
93
+ static int
94
+ check_breakpoint_by_pos(VALUE breakpoint, VALUE file, VALUE line)
95
+ {
96
+ debug_breakpoint_t *debug_breakpoint;
97
+
98
+ if(breakpoint == Qnil)
99
+ return 0;
100
+ Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
101
+ if (!Qtrue == debug_breakpoint->enabled) return 0;
102
+ if(debug_breakpoint->type != BP_POS_TYPE)
103
+ return 0;
104
+ if(debug_breakpoint->pos.line != FIX2INT(line))
105
+ return 0;
106
+ if(filename_cmp(debug_breakpoint->source, RSTRING_PTR(file)))
107
+ return 1;
108
+ return 0;
109
+ }
110
+
111
+ int
112
+ check_breakpoint_by_method(VALUE breakpoint, VALUE klass, ID mid, VALUE self)
113
+ {
114
+ debug_breakpoint_t *debug_breakpoint;
115
+
116
+ if(breakpoint == Qnil)
117
+ return 0;
118
+ Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
119
+ if (!Qtrue == debug_breakpoint->enabled) return 0;
120
+ if(debug_breakpoint->type != BP_METHOD_TYPE)
121
+ return 0;
122
+ if(debug_breakpoint->pos.mid != mid)
123
+ return 0;
124
+ if(classname_cmp(debug_breakpoint->source, klass))
125
+ return 1;
126
+ if ((rb_type(self) == T_CLASS) &&
127
+ classname_cmp(debug_breakpoint->source, self))
128
+ return 1;
129
+ return 0;
130
+ }
131
+
132
+ VALUE
133
+ check_breakpoints_by_pos(debug_context_t *debug_context, VALUE file, VALUE line)
134
+ {
135
+ VALUE breakpoint;
136
+ int i;
137
+
138
+ if (!CTX_FL_TEST(debug_context, CTX_FL_ENABLE_BKPT)) {
139
+ if (0) fprintf(stderr, "check_breakpoints_by_pos: !CTX_FL_ENABLE_BKPT\n");
140
+ return Qnil;
141
+ }
142
+
143
+ if (check_breakpoint_by_pos(debug_context->breakpoint, file, line)) {
144
+ return debug_context->breakpoint;
145
+ }
146
+
147
+ if (RARRAY_LEN(rdebug_breakpoints) == 0) {
148
+ return Qnil;
149
+ }
150
+
151
+ for (i = 0; i < RARRAY_LEN(rdebug_breakpoints); i++) {
152
+ breakpoint = rb_ary_entry(rdebug_breakpoints, i);
153
+
154
+ if (check_breakpoint_by_pos(breakpoint, file, line)) {
155
+ return breakpoint;
156
+ }
157
+ }
158
+ return Qnil;
159
+ }
160
+
161
+ VALUE
162
+ check_breakpoints_by_method(debug_context_t *debug_context, VALUE klass, ID mid, VALUE self)
163
+ {
164
+ VALUE breakpoint;
165
+ int i;
166
+
167
+ if(!CTX_FL_TEST(debug_context, CTX_FL_ENABLE_BKPT))
168
+ return Qnil;
169
+
170
+ if(check_breakpoint_by_method(debug_context->breakpoint, klass, mid, self))
171
+ return debug_context->breakpoint;
172
+
173
+ if(RARRAY_LEN(rdebug_breakpoints) == 0)
174
+ return Qnil;
175
+ for(i = 0; i < RARRAY_LEN(rdebug_breakpoints); i++)
176
+ {
177
+ breakpoint = rb_ary_entry(rdebug_breakpoints, i);
178
+ if(check_breakpoint_by_method(breakpoint, klass, mid, self))
179
+ return breakpoint;
180
+ }
181
+ return Qnil;
182
+ }
183
+
184
+ int
185
+ check_breakpoint_expression(VALUE breakpoint, VALUE binding)
186
+ {
187
+ debug_breakpoint_t *debug_breakpoint;
188
+ VALUE args, expr_result;
189
+
190
+ Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
191
+ if (NIL_P(debug_breakpoint->expr)) {
192
+ return 1;
193
+ }
194
+
195
+ args = rb_ary_new3(2, debug_breakpoint->expr, binding);
196
+ expr_result = rb_protect(eval_expression, args, 0);
197
+ return RTEST(expr_result);
198
+ }
199
+
200
+ static void
201
+ breakpoint_mark(void *data)
202
+ {
203
+ debug_breakpoint_t *breakpoint;
204
+ breakpoint = (debug_breakpoint_t *)data;
205
+ rb_gc_mark(breakpoint->source);
206
+ rb_gc_mark(breakpoint->expr);
207
+ }
208
+
209
+ VALUE
210
+ create_breakpoint_from_args(int argc, VALUE *argv, int id)
211
+ {
212
+ VALUE source, pos, expr;
213
+ debug_breakpoint_t *breakpoint;
214
+ int type;
215
+
216
+ if (rb_scan_args(argc, argv, "21", &source, &pos, &expr) == 2) {
217
+ expr = Qnil;
218
+ }
219
+
220
+ type = FIXNUM_P(pos) ? BP_POS_TYPE : BP_METHOD_TYPE;
221
+ if (type == BP_POS_TYPE) {
222
+ source = StringValue(source);
223
+ }
224
+ else {
225
+ pos = StringValue(pos);
226
+ }
227
+
228
+ breakpoint = ALLOC(debug_breakpoint_t);
229
+ breakpoint->id = id;
230
+ breakpoint->source = source;
231
+ breakpoint->type = type;
232
+
233
+ if (type == BP_POS_TYPE) {
234
+ breakpoint->pos.line = FIX2INT(pos);
235
+ }
236
+ else {
237
+ breakpoint->pos.mid = rb_intern(RSTRING_PTR(pos));
238
+ }
239
+
240
+ breakpoint->enabled = Qtrue;
241
+ breakpoint->expr = NIL_P(expr) ? expr: StringValue(expr);
242
+ breakpoint->hit_count = 0;
243
+ breakpoint->hit_value = 0;
244
+ breakpoint->hit_condition = HIT_COND_NONE;
245
+ return Data_Wrap_Struct(cBreakpoint, breakpoint_mark, xfree, breakpoint);
246
+ }
247
+
248
+ /*
249
+ * call-seq:
250
+ * Debugger.remove_breakpoint(id) -> breakpoint
251
+ *
252
+ * Removes breakpoint by its id.
253
+ * <i>id</i> is an identificator of a breakpoint.
254
+ */
255
+ VALUE
256
+ rdebug_remove_breakpoint(VALUE self, VALUE id_value)
257
+ {
258
+ int i;
259
+ int id;
260
+ VALUE breakpoint;
261
+ debug_breakpoint_t *debug_breakpoint;
262
+
263
+ id = FIX2INT(id_value);
264
+
265
+ for( i = 0; i < RARRAY_LEN(rdebug_breakpoints); i += 1 )
266
+ {
267
+ breakpoint = rb_ary_entry(rdebug_breakpoints, i);
268
+ Data_Get_Struct(breakpoint, debug_breakpoint_t, debug_breakpoint);
269
+ if(debug_breakpoint->id == id)
270
+ {
271
+ rb_ary_delete_at(rdebug_breakpoints, i);
272
+ return breakpoint;
273
+ }
274
+ }
275
+ return Qnil;
276
+ }
277
+
278
+ /*
279
+ * call-seq:
280
+ * Debugger.catchpoints -> hash
281
+ *
282
+ * Returns a current catchpoints, which is a hash exception names that will
283
+ * trigger a debugger when raised. The values are the number of times taht
284
+ * catchpoint was hit, initially 0.
285
+ */
286
+ VALUE
287
+ debug_catchpoints(VALUE self)
288
+ {
289
+ debug_check_started();
290
+
291
+ return rdebug_catchpoints;
292
+ }
293
+
294
+ /*
295
+ * call-seq:
296
+ * Debugger.catchpoint(string) -> string
297
+ *
298
+ * Sets catchpoint. Returns the string passed.
299
+ */
300
+ VALUE
301
+ rdebug_add_catchpoint(VALUE self, VALUE value)
302
+ {
303
+ debug_check_started();
304
+
305
+ if (TYPE(value) != T_STRING) {
306
+ rb_raise(rb_eTypeError, "value of a catchpoint must be String");
307
+ }
308
+ rb_hash_aset(rdebug_catchpoints, rb_str_dup(value), INT2FIX(0));
309
+ return value;
310
+ }
311
+
312
+ /*
313
+ * call-seq:
314
+ * context.breakpoint -> breakpoint
315
+ *
316
+ * Returns a context-specific temporary Breakpoint object.
317
+ */
318
+ VALUE
319
+ context_breakpoint(VALUE self)
320
+ {
321
+ debug_context_t *debug_context;
322
+
323
+ debug_check_started();
324
+
325
+ Data_Get_Struct(self, debug_context_t, debug_context);
326
+ return debug_context->breakpoint;
327
+ }
328
+
329
+ /*
330
+ * call-seq:
331
+ * context.set_breakpoint(source, pos, condition = nil) -> breakpoint
332
+ *
333
+ * Sets a context-specific temporary breakpoint, which can be used to implement
334
+ * 'Run to Cursor' debugger function. When this breakpoint is reached, it will be
335
+ * cleared out.
336
+ *
337
+ * <i>source</i> is a name of a file or a class.
338
+ * <i>pos</i> is a line number or a method name if <i>source</i> is a class name.
339
+ * <i>condition</i> is a string which is evaluated to +true+ when this breakpoint
340
+ * is activated.
341
+ */
342
+ VALUE
343
+ context_set_breakpoint(int argc, VALUE *argv, VALUE self)
344
+ {
345
+ VALUE result;
346
+ debug_context_t *debug_context;
347
+
348
+ debug_check_started();
349
+
350
+ Data_Get_Struct(self, debug_context_t, debug_context);
351
+ result = create_breakpoint_from_args(argc, argv, 0);
352
+ debug_context->breakpoint = result;
353
+ return result;
354
+ }
355
+
356
+ /*
357
+ * call-seq:
358
+ * breakpoint.enabled?
359
+ *
360
+ * Returns whether breakpoint is enabled or not.
361
+ */
362
+ static VALUE
363
+ breakpoint_enabled(VALUE self)
364
+ {
365
+ debug_breakpoint_t *breakpoint;
366
+
367
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
368
+ return breakpoint->enabled;
369
+ }
370
+
371
+ /*
372
+ * call-seq:
373
+ * breakpoint.enabled = bool
374
+ *
375
+ * Enables or disables breakpoint.
376
+ */
377
+ static VALUE
378
+ breakpoint_set_enabled(VALUE self, VALUE bool)
379
+ {
380
+ debug_breakpoint_t *breakpoint;
381
+
382
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
383
+ return breakpoint->enabled = bool;
384
+ }
385
+
386
+ /*
387
+ * call-seq:
388
+ * breakpoint.source -> string
389
+ *
390
+ * Returns a source of the breakpoint.
391
+ */
392
+ static VALUE
393
+ breakpoint_source(VALUE self)
394
+ {
395
+ debug_breakpoint_t *breakpoint;
396
+
397
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
398
+ return breakpoint->source;
399
+ }
400
+
401
+ /*
402
+ * call-seq:
403
+ * breakpoint.source = string
404
+ *
405
+ * Sets the source of the breakpoint.
406
+ */
407
+ static VALUE
408
+ breakpoint_set_source(VALUE self, VALUE value)
409
+ {
410
+ debug_breakpoint_t *breakpoint;
411
+
412
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
413
+ breakpoint->source = StringValue(value);
414
+ return value;
415
+ }
416
+
417
+ /*
418
+ * call-seq:
419
+ * breakpoint.pos -> string or int
420
+ *
421
+ * Returns the position of this breakpoint.
422
+ */
423
+ static VALUE
424
+ breakpoint_pos(VALUE self)
425
+ {
426
+ debug_breakpoint_t *breakpoint;
427
+
428
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
429
+ if (breakpoint->type == BP_METHOD_TYPE) {
430
+ return rb_str_new2(rb_id2name(breakpoint->pos.mid));
431
+ }
432
+ else {
433
+ return INT2FIX(breakpoint->pos.line);
434
+ }
435
+ }
436
+
437
+ /*
438
+ * call-seq:
439
+ * breakpoint.pos = string or int
440
+ *
441
+ * Sets the position of this breakpoint.
442
+ */
443
+ static VALUE
444
+ breakpoint_set_pos(VALUE self, VALUE value)
445
+ {
446
+ debug_breakpoint_t *breakpoint;
447
+
448
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
449
+ if (breakpoint->type == BP_METHOD_TYPE) {
450
+ breakpoint->pos.mid = rb_to_id(StringValue(value));
451
+ }
452
+ else {
453
+ breakpoint->pos.line = FIX2INT(value);
454
+ }
455
+ return value;
456
+ }
457
+
458
+ /*
459
+ * call-seq:
460
+ * breakpoint.expr -> string
461
+ *
462
+ * Returns a codition expression when this breakpoint should be activated.
463
+ */
464
+ static VALUE
465
+ breakpoint_expr(VALUE self)
466
+ {
467
+ debug_breakpoint_t *breakpoint;
468
+
469
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
470
+ return breakpoint->expr;
471
+ }
472
+
473
+ /*
474
+ * call-seq:
475
+ * breakpoint.expr = string | nil
476
+ *
477
+ * Sets the codition expression when this breakpoint should be activated.
478
+ */
479
+ static VALUE
480
+ breakpoint_set_expr(VALUE self, VALUE expr)
481
+ {
482
+ debug_breakpoint_t *breakpoint;
483
+
484
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
485
+ breakpoint->expr = NIL_P(expr) ? expr: StringValue(expr);
486
+ return expr;
487
+ }
488
+
489
+ /*
490
+ * call-seq:
491
+ * breakpoint.id -> int
492
+ *
493
+ * Returns id of the breakpoint.
494
+ */
495
+ static VALUE
496
+ breakpoint_id(VALUE self)
497
+ {
498
+ debug_breakpoint_t *breakpoint;
499
+
500
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
501
+ return INT2FIX(breakpoint->id);
502
+ }
503
+
504
+ /*
505
+ * call-seq:
506
+ * breakpoint.hit_count -> int
507
+ *
508
+ * Returns the hit count of the breakpoint.
509
+ */
510
+ static VALUE
511
+ breakpoint_hit_count(VALUE self)
512
+ {
513
+ debug_breakpoint_t *breakpoint;
514
+
515
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
516
+ return INT2FIX(breakpoint->hit_count);
517
+ }
518
+
519
+ /*
520
+ * call-seq:
521
+ * breakpoint.hit_value -> int
522
+ *
523
+ * Returns the hit value of the breakpoint.
524
+ */
525
+ static VALUE
526
+ breakpoint_hit_value(VALUE self)
527
+ {
528
+ debug_breakpoint_t *breakpoint;
529
+
530
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
531
+ return INT2FIX(breakpoint->hit_value);
532
+ }
533
+
534
+ /*
535
+ * call-seq:
536
+ * breakpoint.hit_value = int
537
+ *
538
+ * Sets the hit value of the breakpoint.
539
+ */
540
+ static VALUE
541
+ breakpoint_set_hit_value(VALUE self, VALUE value)
542
+ {
543
+ debug_breakpoint_t *breakpoint;
544
+
545
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
546
+ breakpoint->hit_value = FIX2INT(value);
547
+ return value;
548
+ }
549
+
550
+ /*
551
+ * call-seq:
552
+ * breakpoint.hit_condition -> symbol
553
+ *
554
+ * Returns the hit condition of the breakpoint:
555
+ *
556
+ * +nil+ if it is an unconditional breakpoint, or
557
+ * :greater_or_equal, :equal, :modulo
558
+ */
559
+ static VALUE
560
+ breakpoint_hit_condition(VALUE self)
561
+ {
562
+ debug_breakpoint_t *breakpoint;
563
+
564
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
565
+ switch (breakpoint->hit_condition) {
566
+ case HIT_COND_GE: return ID2SYM(rb_intern("greater_or_equal"));
567
+ case HIT_COND_EQ: return ID2SYM(rb_intern("equal"));
568
+ case HIT_COND_MOD: return ID2SYM(rb_intern("modulo"));
569
+ case HIT_COND_NONE:
570
+ default: return Qnil;
571
+ }
572
+ }
573
+
574
+ /*
575
+ * call-seq:
576
+ * breakpoint.hit_condition = symbol
577
+ *
578
+ * Sets the hit condition of the breakpoint which must be one of the following values:
579
+ *
580
+ * +nil+ if it is an unconditional breakpoint, or
581
+ * :greater_or_equal(:ge), :equal(:eq), :modulo(:mod)
582
+ */
583
+ static VALUE
584
+ breakpoint_set_hit_condition(VALUE self, VALUE value)
585
+ {
586
+ debug_breakpoint_t *breakpoint;
587
+ ID id_value;
588
+
589
+ Data_Get_Struct(self, debug_breakpoint_t, breakpoint);
590
+ id_value = rb_to_id(value);
591
+
592
+ if(rb_intern("greater_or_equal") == id_value || rb_intern("ge") == id_value)
593
+ breakpoint->hit_condition = HIT_COND_GE;
594
+ else if(rb_intern("equal") == id_value || rb_intern("eq") == id_value)
595
+ breakpoint->hit_condition = HIT_COND_EQ;
596
+ else if(rb_intern("modulo") == id_value || rb_intern("mod") == id_value)
597
+ breakpoint->hit_condition = HIT_COND_MOD;
598
+ else
599
+ rb_raise(rb_eArgError, "Invalid condition parameter");
600
+ return value;
601
+ }
602
+
603
+ /*
604
+ * Document-class: Breakpoint
605
+ *
606
+ * == Summary
607
+ *
608
+ * This class represents a breakpoint. It defines position of the breakpoint and
609
+ * condition when this breakpoint should be triggered.
610
+ */
611
+ void
612
+ Init_breakpoint()
613
+ {
614
+ cBreakpoint = rb_define_class_under(mDebugger, "Breakpoint", rb_cObject);
615
+ rb_define_method(cBreakpoint, "enabled=", breakpoint_set_enabled, 1);
616
+ rb_define_method(cBreakpoint, "enabled?", breakpoint_enabled, 0);
617
+ rb_define_method(cBreakpoint, "expr", breakpoint_expr, 0);
618
+ rb_define_method(cBreakpoint, "expr=", breakpoint_set_expr, 1);
619
+ rb_define_method(cBreakpoint, "hit_condition", breakpoint_hit_condition, 0);
620
+ rb_define_method(cBreakpoint, "hit_condition=", breakpoint_set_hit_condition, 1);
621
+ rb_define_method(cBreakpoint, "hit_count", breakpoint_hit_count, 0);
622
+ rb_define_method(cBreakpoint, "hit_value", breakpoint_hit_value, 0);
623
+ rb_define_method(cBreakpoint, "hit_value=", breakpoint_set_hit_value, 1);
624
+ rb_define_method(cBreakpoint, "id", breakpoint_id, 0);
625
+ rb_define_method(cBreakpoint, "pos", breakpoint_pos, 0);
626
+ rb_define_method(cBreakpoint, "pos=", breakpoint_set_pos, 1);
627
+ rb_define_method(cBreakpoint, "source", breakpoint_source, 0);
628
+ rb_define_method(cBreakpoint, "source=", breakpoint_set_source, 1);
629
+ rdebug_catchpoints = rb_hash_new();
630
+ }