byebug 0.0.1

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 (133) hide show
  1. data/.gitignore +10 -0
  2. data/.travis.yml +8 -0
  3. data/AUTHORS +10 -0
  4. data/CHANGELOG.md +2 -0
  5. data/CONTRIBUTING.md +1 -0
  6. data/Gemfile +3 -0
  7. data/LICENSE +20 -0
  8. data/README.md +5 -0
  9. data/Rakefile +28 -0
  10. data/bin/byebug +395 -0
  11. data/byebug.gemspec +29 -0
  12. data/doc/hanoi.rb +35 -0
  13. data/doc/primes.rb +28 -0
  14. data/doc/rdebug-emacs.texi +1030 -0
  15. data/doc/test-tri2.rb +18 -0
  16. data/doc/tri3.rb +8 -0
  17. data/doc/triangle.rb +12 -0
  18. data/ext/byebug/breakpoint.c +476 -0
  19. data/ext/byebug/byebug.c +512 -0
  20. data/ext/byebug/byebug.h +131 -0
  21. data/ext/byebug/context.c +424 -0
  22. data/ext/byebug/extconf.rb +21 -0
  23. data/ext/byebug/locker.c +53 -0
  24. data/lib/byebug.rb +404 -0
  25. data/lib/byebug/command.rb +232 -0
  26. data/lib/byebug/commands/breakpoints.rb +153 -0
  27. data/lib/byebug/commands/catchpoint.rb +56 -0
  28. data/lib/byebug/commands/condition.rb +49 -0
  29. data/lib/byebug/commands/continue.rb +38 -0
  30. data/lib/byebug/commands/control.rb +110 -0
  31. data/lib/byebug/commands/display.rb +122 -0
  32. data/lib/byebug/commands/edit.rb +48 -0
  33. data/lib/byebug/commands/enable.rb +202 -0
  34. data/lib/byebug/commands/eval.rb +176 -0
  35. data/lib/byebug/commands/finish.rb +43 -0
  36. data/lib/byebug/commands/frame.rb +303 -0
  37. data/lib/byebug/commands/help.rb +56 -0
  38. data/lib/byebug/commands/info.rb +462 -0
  39. data/lib/byebug/commands/irb.rb +123 -0
  40. data/lib/byebug/commands/jump.rb +66 -0
  41. data/lib/byebug/commands/kill.rb +51 -0
  42. data/lib/byebug/commands/list.rb +94 -0
  43. data/lib/byebug/commands/method.rb +84 -0
  44. data/lib/byebug/commands/quit.rb +39 -0
  45. data/lib/byebug/commands/reload.rb +40 -0
  46. data/lib/byebug/commands/save.rb +90 -0
  47. data/lib/byebug/commands/set.rb +210 -0
  48. data/lib/byebug/commands/show.rb +246 -0
  49. data/lib/byebug/commands/skip.rb +35 -0
  50. data/lib/byebug/commands/source.rb +36 -0
  51. data/lib/byebug/commands/stepping.rb +83 -0
  52. data/lib/byebug/commands/threads.rb +189 -0
  53. data/lib/byebug/commands/tmate.rb +36 -0
  54. data/lib/byebug/commands/trace.rb +56 -0
  55. data/lib/byebug/commands/variables.rb +199 -0
  56. data/lib/byebug/context.rb +58 -0
  57. data/lib/byebug/helper.rb +69 -0
  58. data/lib/byebug/interface.rb +223 -0
  59. data/lib/byebug/processor.rb +468 -0
  60. data/lib/byebug/version.rb +3 -0
  61. data/man/rdebug.1 +241 -0
  62. data/test/breakpoints_test.rb +357 -0
  63. data/test/conditions_test.rb +77 -0
  64. data/test/continue_test.rb +44 -0
  65. data/test/display_test.rb +141 -0
  66. data/test/edit_test.rb +56 -0
  67. data/test/eval_test.rb +92 -0
  68. data/test/examples/breakpoint1.rb +15 -0
  69. data/test/examples/breakpoint2.rb +7 -0
  70. data/test/examples/conditions.rb +4 -0
  71. data/test/examples/continue.rb +4 -0
  72. data/test/examples/display.rb +5 -0
  73. data/test/examples/edit.rb +3 -0
  74. data/test/examples/edit2.rb +3 -0
  75. data/test/examples/eval.rb +4 -0
  76. data/test/examples/finish.rb +20 -0
  77. data/test/examples/frame.rb +20 -0
  78. data/test/examples/frame_threads.rb +31 -0
  79. data/test/examples/help.rb +2 -0
  80. data/test/examples/info.rb +38 -0
  81. data/test/examples/info2.rb +3 -0
  82. data/test/examples/info_threads.rb +48 -0
  83. data/test/examples/irb.rb +6 -0
  84. data/test/examples/jump.rb +14 -0
  85. data/test/examples/kill.rb +2 -0
  86. data/test/examples/list.rb +12 -0
  87. data/test/examples/method.rb +15 -0
  88. data/test/examples/post_mortem.rb +19 -0
  89. data/test/examples/quit.rb +2 -0
  90. data/test/examples/reload.rb +6 -0
  91. data/test/examples/restart.rb +6 -0
  92. data/test/examples/save.rb +3 -0
  93. data/test/examples/set.rb +3 -0
  94. data/test/examples/set_annotate.rb +12 -0
  95. data/test/examples/settings.rb +1 -0
  96. data/test/examples/show.rb +2 -0
  97. data/test/examples/source.rb +3 -0
  98. data/test/examples/stepping.rb +21 -0
  99. data/test/examples/thread.rb +32 -0
  100. data/test/examples/tmate.rb +10 -0
  101. data/test/examples/trace.rb +7 -0
  102. data/test/examples/trace_threads.rb +20 -0
  103. data/test/examples/variables.rb +26 -0
  104. data/test/finish_test.rb +48 -0
  105. data/test/frame_test.rb +143 -0
  106. data/test/help_test.rb +50 -0
  107. data/test/info_test.rb +313 -0
  108. data/test/irb_test.rb +81 -0
  109. data/test/jump_test.rb +70 -0
  110. data/test/kill_test.rb +48 -0
  111. data/test/list_test.rb +145 -0
  112. data/test/method_test.rb +70 -0
  113. data/test/post_mortem_test.rb +27 -0
  114. data/test/quit_test.rb +56 -0
  115. data/test/reload_test.rb +44 -0
  116. data/test/restart_test.rb +164 -0
  117. data/test/save_test.rb +92 -0
  118. data/test/set_test.rb +177 -0
  119. data/test/show_test.rb +293 -0
  120. data/test/source_test.rb +45 -0
  121. data/test/stepping_test.rb +130 -0
  122. data/test/support/breakpoint.rb +13 -0
  123. data/test/support/context.rb +14 -0
  124. data/test/support/matchers.rb +67 -0
  125. data/test/support/mocha_extensions.rb +72 -0
  126. data/test/support/processor.rb +7 -0
  127. data/test/support/test_dsl.rb +206 -0
  128. data/test/support/test_interface.rb +68 -0
  129. data/test/test_helper.rb +10 -0
  130. data/test/tmate_test.rb +44 -0
  131. data/test/trace_test.rb +159 -0
  132. data/test/variables_test.rb +119 -0
  133. metadata +265 -0
@@ -0,0 +1,512 @@
1
+ #include <byebug.h>
2
+
3
+ static VALUE mByebug; /* Ruby Byebug Module object */
4
+ static VALUE cContext;
5
+ static VALUE cDebugThread;
6
+
7
+ static VALUE debug = Qfalse;
8
+ static VALUE locker = Qnil;
9
+ static VALUE contexts;
10
+ static VALUE catchpoints;
11
+ static VALUE breakpoints;
12
+
13
+ static VALUE tpLine;
14
+ static VALUE tpCall;
15
+ static VALUE tpReturn;
16
+ static VALUE tpRaise;
17
+
18
+ static VALUE idAlive;
19
+ static VALUE idAtBreakpoint;
20
+ static VALUE idAtCatchpoint;
21
+ static VALUE idAtLine;
22
+ static VALUE idAtTracing;
23
+
24
+ static void
25
+ print_debug_info(char *event, VALUE path, VALUE lineno, VALUE method_id,
26
+ VALUE defined_class, int stack_size)
27
+ {
28
+ char *file;
29
+ const char *method_name, *class_name;
30
+
31
+ file = strrchr(RSTRING_PTR(path), '/');
32
+ method_name = rb_id2name(SYM2ID(method_id));
33
+ class_name = NIL_P(defined_class) ? "undef" : rb_class2name(defined_class);
34
+ fprintf(stderr, "%s: file=%s, line=%d, class=%s, method=%s, stack=%d\n",
35
+ event, ++file, FIX2INT(lineno), class_name, method_name, stack_size);
36
+ return;
37
+ }
38
+
39
+ static VALUE
40
+ Byebug_thread_context(VALUE self, VALUE thread)
41
+ {
42
+ VALUE context;
43
+
44
+ context = rb_hash_aref(contexts, thread);
45
+ if (context == Qnil) {
46
+ context = context_create(thread, cDebugThread);
47
+ rb_hash_aset(contexts, thread, context);
48
+ }
49
+ return context;
50
+ }
51
+
52
+ static VALUE
53
+ Byebug_current_context(VALUE self)
54
+ {
55
+ return Byebug_thread_context(self, rb_thread_current());
56
+ }
57
+
58
+ static int
59
+ remove_dead_threads(VALUE thread, VALUE context, VALUE ignored)
60
+ {
61
+ return (IS_THREAD_ALIVE(thread)) ? ST_CONTINUE : ST_DELETE;
62
+ }
63
+
64
+ static void
65
+ cleanup(debug_context_t *context)
66
+ {
67
+ VALUE thread;
68
+
69
+ context->stop_reason = CTX_STOP_NONE;
70
+
71
+ /* release a lock */
72
+ locker = Qnil;
73
+
74
+ /* let the next thread run */
75
+ thread = remove_from_locked();
76
+ if(thread != Qnil)
77
+ rb_thread_run(thread);
78
+ }
79
+
80
+ static int
81
+ check_start_processing(debug_context_t *context, VALUE thread)
82
+ {
83
+ /* return if thread is marked as 'ignored'.
84
+ byebug's threads are marked this way
85
+ */
86
+ if(CTX_FL_TEST(context, CTX_FL_IGNORE)) return 0;
87
+
88
+ while(1)
89
+ {
90
+ /* halt execution of the current thread if the byebug
91
+ is activated in another
92
+ */
93
+ while(locker != Qnil && locker != thread)
94
+ {
95
+ add_to_locked(thread);
96
+ rb_thread_stop();
97
+ }
98
+
99
+ /* stop the current thread if it's marked as suspended */
100
+ if(CTX_FL_TEST(context, CTX_FL_SUSPEND) && locker != thread)
101
+ {
102
+ CTX_FL_SET(context, CTX_FL_WAS_RUNNING);
103
+ rb_thread_stop();
104
+ }
105
+ else break;
106
+ }
107
+
108
+ /* return if the current thread is the locker */
109
+ if(locker != Qnil) return 0;
110
+
111
+ /* only the current thread can proceed */
112
+ locker = thread;
113
+
114
+ /* ignore a skipped section of code */
115
+ if(CTX_FL_TEST(context, CTX_FL_SKIPPED)) {
116
+ cleanup(context);
117
+ return 0;
118
+ }
119
+ return 1;
120
+ }
121
+
122
+ static inline void
123
+ load_frame_info(VALUE trace_point, VALUE *path, VALUE *lineno, VALUE *method_id,
124
+ VALUE *defined_class, VALUE *binding,
125
+ VALUE *self)
126
+ {
127
+ rb_trace_point_t *tp;
128
+
129
+ tp = rb_tracearg_from_tracepoint(trace_point);
130
+
131
+ *path = rb_tracearg_path(tp);
132
+ *lineno = rb_tracearg_lineno(tp);
133
+ *binding = rb_tracearg_binding(tp);
134
+ *self = rb_tracearg_self(tp);
135
+ *method_id = rb_tracearg_method_id(tp);
136
+ *defined_class = rb_tracearg_defined_class(tp);
137
+ }
138
+
139
+ static void
140
+ call_at_line(debug_context_t *context, char *file, int line,
141
+ VALUE context_object, VALUE path, VALUE lineno)
142
+ {
143
+ CTX_FL_UNSET(context, CTX_FL_STEPPED);
144
+ CTX_FL_UNSET(context, CTX_FL_FORCE_MOVE);
145
+ context->last_file = file;
146
+ context->last_line = line;
147
+ rb_funcall(context_object, idAtLine, 2, path, lineno);
148
+ }
149
+
150
+ static void
151
+ process_line_event(VALUE trace_point, void *data)
152
+ {
153
+ VALUE path, lineno, method_id, defined_class, binding, self;
154
+ VALUE context_object;
155
+ VALUE breakpoint;
156
+ debug_context_t *context;
157
+ int moved;
158
+
159
+ context_object = Byebug_current_context(mByebug);
160
+ Data_Get_Struct(context_object, debug_context_t, context);
161
+ if (!check_start_processing(context, rb_thread_current())) return;
162
+
163
+ load_frame_info(trace_point, &path, &lineno, &method_id, &defined_class,
164
+ &binding, &self);
165
+ if (debug == Qtrue)
166
+ print_debug_info("line", path, lineno, method_id, defined_class,
167
+ context->stack_size);
168
+
169
+ update_frame(context_object, RSTRING_PTR(path), FIX2INT(lineno), method_id,
170
+ defined_class, binding, self);
171
+
172
+ moved = context->last_line != FIX2INT(lineno) || context->last_file == NULL ||
173
+ strcmp(context->last_file, RSTRING_PTR(path)) != 0;
174
+
175
+ if (CTX_FL_TEST(context, CTX_FL_TRACING))
176
+ rb_funcall(context_object, idAtTracing, 2, path, lineno);
177
+
178
+ if (context->dest_frame == -1 || context->stack_size == context->dest_frame)
179
+ {
180
+ if (moved || !CTX_FL_TEST(context, CTX_FL_FORCE_MOVE))
181
+ context->stop_next--;
182
+ if (context->stop_next < 0)
183
+ context->stop_next = -1;
184
+ if (moved || (CTX_FL_TEST(context, CTX_FL_STEPPED) && !CTX_FL_TEST(context, CTX_FL_FORCE_MOVE)))
185
+ {
186
+ context->stop_line--;
187
+ CTX_FL_UNSET(context, CTX_FL_STEPPED);
188
+ }
189
+ }
190
+ else if (context->stack_size < context->dest_frame)
191
+ {
192
+ context->stop_next = 0;
193
+ }
194
+
195
+ breakpoint = find_breakpoint_by_pos(breakpoints, path, lineno, binding);
196
+ if (context->stop_next == 0 || context->stop_line == 0 ||
197
+ breakpoint != Qnil)
198
+ {
199
+ context->stop_reason = CTX_STOP_STEP;
200
+ if (breakpoint != Qnil) {
201
+ rb_funcall(context_object, idAtBreakpoint, 1, breakpoint);
202
+ }
203
+ reset_stepping_stop_points(context);
204
+ call_at_line(context, RSTRING_PTR(path), FIX2INT(lineno), context_object,
205
+ path, lineno);
206
+ }
207
+ cleanup(context);
208
+ }
209
+
210
+ static void
211
+ process_return_event(VALUE trace_point, void *data)
212
+ {
213
+ VALUE path, lineno, method_id, defined_class, binding, self;
214
+ VALUE context_object;
215
+ debug_context_t *context;
216
+
217
+ context_object = Byebug_current_context(mByebug);
218
+ Data_Get_Struct(context_object, debug_context_t, context);
219
+ if (!check_start_processing(context, rb_thread_current())) return;
220
+
221
+ if(context->stack_size == context->stop_frame)
222
+ {
223
+ context->stop_next = 1;
224
+ context->stop_frame = 0;
225
+ }
226
+
227
+ load_frame_info(trace_point, &path, &lineno, &method_id, &defined_class,
228
+ &binding, &self);
229
+ if (debug == Qtrue)
230
+ print_debug_info("return", path, lineno, method_id, defined_class,
231
+ context->stack_size);
232
+
233
+ // rb_funcall(context_object, idAtReturn, 2, path, lineno);
234
+
235
+ pop_frame(context_object);
236
+ cleanup(context);
237
+ }
238
+
239
+ static void
240
+ process_call_event(VALUE trace_point, void *data)
241
+ {
242
+ VALUE path, lineno, method_id, defined_class, binding, self;
243
+ VALUE context_object;
244
+ VALUE breakpoint;
245
+ debug_context_t *context;
246
+
247
+ context_object = Byebug_current_context(mByebug);
248
+ Data_Get_Struct(context_object, debug_context_t, context);
249
+ if (!check_start_processing(context, rb_thread_current())) return;
250
+
251
+ load_frame_info(trace_point, &path, &lineno, &method_id, &defined_class,
252
+ &binding, &self);
253
+ if (debug == Qtrue)
254
+ print_debug_info("call", path, lineno, method_id, defined_class,
255
+ context->stack_size);
256
+
257
+ push_frame(context_object, RSTRING_PTR(path), FIX2INT(lineno), method_id,
258
+ defined_class, binding, self);
259
+
260
+ breakpoint = find_breakpoint_by_method(breakpoints, defined_class,
261
+ SYM2ID(method_id),
262
+ binding, self);
263
+ if (breakpoint != Qnil) {
264
+ context->stop_reason = CTX_STOP_BREAKPOINT;
265
+ rb_funcall(context_object, idAtBreakpoint, 1, breakpoint);
266
+ call_at_line(context, RSTRING_PTR(path), FIX2INT(lineno), context_object,
267
+ path, lineno);
268
+ }
269
+
270
+ cleanup(context);
271
+ }
272
+
273
+ static void
274
+ process_raise_event(VALUE trace_point, void *data)
275
+ {
276
+ VALUE path, lineno, method_id, defined_class, binding, self;
277
+ VALUE context_object;
278
+ VALUE hit_count;
279
+ VALUE exception_name;
280
+ debug_context_t *context;
281
+ int c_hit_count;
282
+
283
+ context_object = Byebug_current_context(mByebug);
284
+ Data_Get_Struct(context_object, debug_context_t, context);
285
+ if (!check_start_processing(context, rb_thread_current())) return;
286
+
287
+ load_frame_info(trace_point, &path, &lineno, &method_id, &defined_class,
288
+ &binding, &self);
289
+ update_frame(context_object, RSTRING_PTR(path), FIX2INT(lineno), method_id,
290
+ defined_class, binding, self);
291
+
292
+ if (catchpoint_hit_count(catchpoints, rb_errinfo(), &exception_name) != Qnil) {
293
+ /* On 64-bit systems with gcc and -O2 there seems to be
294
+ an optimization bug in running INT2FIX(FIX2INT...)..)
295
+ So we do this in two steps.
296
+ */
297
+ c_hit_count = FIX2INT(rb_hash_aref(catchpoints, exception_name)) + 1;
298
+ hit_count = INT2FIX(c_hit_count);
299
+ rb_hash_aset(catchpoints, exception_name, hit_count);
300
+ context->stop_reason = CTX_STOP_CATCHPOINT;
301
+ rb_funcall(context_object, idAtCatchpoint, 1, rb_errinfo());
302
+ call_at_line(context, RSTRING_PTR(path), FIX2INT(lineno), context_object,
303
+ path, lineno);
304
+ }
305
+
306
+ cleanup(context);
307
+ }
308
+
309
+
310
+ static VALUE
311
+ Byebug_setup_tracepoints(VALUE self)
312
+ {
313
+ if (catchpoints != Qnil) return Qnil;
314
+ contexts = rb_hash_new();
315
+ breakpoints = rb_ary_new();
316
+ catchpoints = rb_hash_new();
317
+
318
+ tpLine = rb_tracepoint_new(Qnil,
319
+ RUBY_EVENT_LINE,
320
+ process_line_event, NULL);
321
+ rb_tracepoint_enable(tpLine);
322
+
323
+ tpReturn = rb_tracepoint_new(Qnil,
324
+ RUBY_EVENT_RETURN | RUBY_EVENT_C_RETURN | RUBY_EVENT_B_RETURN | RUBY_EVENT_CLASS | RUBY_EVENT_END,
325
+ process_return_event, NULL);
326
+ rb_tracepoint_enable(tpReturn);
327
+
328
+ tpCall = rb_tracepoint_new(Qnil,
329
+ RUBY_EVENT_CALL | RUBY_EVENT_C_CALL | RUBY_EVENT_B_CALL,
330
+ process_call_event, NULL);
331
+ rb_tracepoint_enable(tpCall);
332
+
333
+ tpRaise = rb_tracepoint_new(Qnil,
334
+ RUBY_EVENT_RAISE, process_raise_event, NULL);
335
+ rb_tracepoint_enable(tpRaise);
336
+
337
+ return Qnil;
338
+ }
339
+
340
+ static VALUE
341
+ Byebug_remove_tracepoints(VALUE self)
342
+ {
343
+ contexts = Qnil;
344
+ breakpoints = Qnil;
345
+ catchpoints = Qnil;
346
+
347
+ if (tpLine != Qnil) rb_tracepoint_disable(tpLine);
348
+ tpLine = Qnil;
349
+ if (tpReturn != Qnil) rb_tracepoint_disable(tpReturn);
350
+ tpReturn = Qnil;
351
+ if (tpCall != Qnil) rb_tracepoint_disable(tpCall);
352
+ tpCall = Qnil;
353
+ if (tpRaise != Qnil) rb_tracepoint_disable(tpRaise);
354
+ tpRaise = Qnil;
355
+ return Qnil;
356
+ }
357
+
358
+ static int
359
+ values_i(VALUE key, VALUE value, VALUE ary)
360
+ {
361
+ rb_ary_push(ary, value);
362
+ return ST_CONTINUE;
363
+ }
364
+
365
+ static VALUE
366
+ Byebug_started(VALUE self)
367
+ {
368
+ return catchpoints != Qnil ? Qtrue : Qfalse;
369
+ }
370
+
371
+ static VALUE
372
+ Byebug_stop(VALUE self)
373
+ {
374
+ if (Byebug_started(self))
375
+ {
376
+ Byebug_remove_tracepoints(self);
377
+ return Qfalse;
378
+ }
379
+ return Qtrue;
380
+ }
381
+
382
+ static VALUE
383
+ Byebug_start(VALUE self)
384
+ {
385
+ VALUE result;
386
+
387
+ if (Byebug_started(self))
388
+ result = Qfalse;
389
+ else
390
+ {
391
+ Byebug_setup_tracepoints(self);
392
+ result = Qtrue;
393
+ }
394
+
395
+ if (rb_block_given_p())
396
+ rb_ensure(rb_yield, self, Byebug_stop, self);
397
+
398
+ return result;
399
+ }
400
+
401
+ static VALUE
402
+ Byebug_load(int argc, VALUE *argv, VALUE self)
403
+ {
404
+ VALUE file, stop, context_object;
405
+ debug_context_t *context;
406
+ int state = 0;
407
+
408
+ if (rb_scan_args(argc, argv, "11", &file, &stop) == 1)
409
+ {
410
+ stop = Qfalse;
411
+ }
412
+
413
+ Byebug_start(self);
414
+
415
+ context_object = Byebug_current_context(self);
416
+ Data_Get_Struct(context_object, debug_context_t, context);
417
+ context->stack_size = 0;
418
+ if (RTEST(stop)) context->stop_next = 1;
419
+
420
+ /* Initializing $0 to the script's path */
421
+ ruby_script(RSTRING_PTR(file));
422
+ rb_load_protect(file, 0, &state);
423
+ if (0 != state)
424
+ {
425
+ VALUE errinfo = rb_errinfo();
426
+ //debug_suspend(self);
427
+ reset_stepping_stop_points(context);
428
+ rb_set_errinfo(Qnil);
429
+ return errinfo;
430
+ }
431
+
432
+ /* We should run all at_exit handler's in order to provide,
433
+ * for instance, a chance to run all defined test cases */
434
+ rb_exec_end_proc();
435
+
436
+ return Qnil;
437
+ }
438
+
439
+
440
+
441
+ static VALUE
442
+ Byebug_contexts(VALUE self)
443
+ {
444
+ VALUE ary;
445
+
446
+ ary = rb_ary_new();
447
+
448
+ /* check that all contexts point to alive threads */
449
+ rb_hash_foreach(contexts, remove_dead_threads, 0);
450
+
451
+ rb_hash_foreach(contexts, values_i, ary);
452
+
453
+ return ary;
454
+ }
455
+
456
+ static VALUE
457
+ Byebug_breakpoints(VALUE self)
458
+ {
459
+ return breakpoints;
460
+ }
461
+
462
+ static VALUE
463
+ Byebug_catchpoints(VALUE self)
464
+ {
465
+ if (catchpoints == Qnil)
466
+ rb_raise(rb_eRuntimeError, "Byebug.start is not called yet.");
467
+ return catchpoints;
468
+ }
469
+
470
+ /*
471
+ * Document-class: Byebug
472
+ *
473
+ * == Summary
474
+ *
475
+ * This is a singleton class allows controlling the byebug. Use it to start/stop
476
+ * byebug, set/remove breakpoints, etc.
477
+ */
478
+ void
479
+ Init_byebug()
480
+ {
481
+ mByebug = rb_define_module("Byebug");
482
+ rb_define_module_function(mByebug, "setup_tracepoints", Byebug_setup_tracepoints, 0);
483
+ rb_define_module_function(mByebug, "remove_tracepoints", Byebug_remove_tracepoints, 0);
484
+ rb_define_module_function(mByebug, "current_context", Byebug_current_context, 0);
485
+ rb_define_module_function(mByebug, "contexts", Byebug_contexts, 0);
486
+ rb_define_module_function(mByebug, "breakpoints", Byebug_breakpoints, 0);
487
+ rb_define_module_function(mByebug, "catchpoints", Byebug_catchpoints, 0);
488
+ rb_define_module_function(mByebug, "_start", Byebug_start, 0);
489
+ rb_define_module_function(mByebug, "stop", Byebug_stop, 0);
490
+ rb_define_module_function(mByebug, "started?", Byebug_started, 0);
491
+ rb_define_module_function(mByebug, "debug_load", Byebug_load, -1);
492
+
493
+ idAlive = rb_intern("alive?");
494
+ idAtBreakpoint = rb_intern("at_breakpoint");
495
+ idAtCatchpoint = rb_intern("at_catchpoint");
496
+ idAtTracing = rb_intern("at_tracing");
497
+ idAtLine = rb_intern("at_line");
498
+
499
+ cContext = Init_context(mByebug);
500
+
501
+ Init_breakpoint(mByebug);
502
+
503
+ cDebugThread = rb_define_class_under(mByebug, "DebugThread", rb_cThread);
504
+ contexts = Qnil;
505
+ catchpoints = Qnil;
506
+ breakpoints = Qnil;
507
+
508
+ rb_global_variable(&locker);
509
+ rb_global_variable(&breakpoints);
510
+ rb_global_variable(&catchpoints);
511
+ rb_global_variable(&contexts);
512
+ }