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,131 @@
1
+ #ifndef RUBY_DEBUG
2
+ #define RUBY_DEBUG
3
+
4
+ #include <ruby.h>
5
+ #include <ruby/debug.h>
6
+
7
+ typedef struct rb_trace_arg_struct rb_trace_point_t;
8
+
9
+ /* Byebug::Context */
10
+
11
+ /* flags */
12
+ #define CTX_FL_SUSPEND (1<<1)
13
+ #define CTX_FL_TRACING (1<<2)
14
+ #define CTX_FL_SKIPPED (1<<3)
15
+ #define CTX_FL_IGNORE (1<<4)
16
+ #define CTX_FL_DEAD (1<<5)
17
+ #define CTX_FL_WAS_RUNNING (1<<6)
18
+ #define CTX_FL_ENABLE_BKPT (1<<7)
19
+ #define CTX_FL_STEPPED (1<<8)
20
+ #define CTX_FL_FORCE_MOVE (1<<9)
21
+ #define CTX_FL_CATCHING (1<<10)
22
+
23
+ /* macro functions */
24
+ #define CTX_FL_TEST(c,f) ((c)->flags & (f))
25
+ #define CTX_FL_SET(c,f) do { (c)->flags |= (f); } while (0)
26
+ #define CTX_FL_UNSET(c,f) do { (c)->flags &= ~(f); } while (0)
27
+
28
+ #define IS_THREAD_ALIVE(t) (rb_funcall((t), idAlive, 0) == Qtrue)
29
+
30
+ /* types */
31
+ typedef enum {
32
+ CTX_STOP_NONE,
33
+ CTX_STOP_STEP,
34
+ CTX_STOP_BREAKPOINT,
35
+ CTX_STOP_CATCHPOINT
36
+ } ctx_stop_reason;
37
+
38
+ typedef struct debug_frame_t {
39
+ struct debug_frame_t *prev;
40
+ char *file;
41
+ int line;
42
+ VALUE method_id;
43
+ VALUE defined_class;
44
+ VALUE binding;
45
+ VALUE self;
46
+ } debug_frame_t;
47
+
48
+ typedef struct {
49
+ debug_frame_t *stack;
50
+ int stack_size;
51
+
52
+ VALUE thread;
53
+ int thnum;
54
+ int flags;
55
+
56
+ ctx_stop_reason stop_reason;
57
+ int stop_next;
58
+ int dest_frame;
59
+ int stop_line;
60
+ int stop_frame;
61
+
62
+ char *last_file;
63
+ int last_line;
64
+ } debug_context_t;
65
+
66
+ /* functions */
67
+ extern VALUE Init_context(VALUE mByebug);
68
+ extern VALUE context_create(VALUE thread, VALUE cDebugThread);
69
+ extern void reset_stepping_stop_points(debug_context_t *context);
70
+ extern VALUE Context_ignored(VALUE self);
71
+
72
+ extern void push_frame(VALUE context_object, char* file, int lineno,
73
+ VALUE method_id, VALUE defined_class, VALUE binding,
74
+ VALUE self);
75
+
76
+ extern void pop_frame(VALUE context_object);
77
+
78
+ extern void update_frame(VALUE context_object, char* file, int lineno,
79
+ VALUE method_id, VALUE defined_class, VALUE binding,
80
+ VALUE self);
81
+
82
+
83
+ /* locked threads container */
84
+ typedef struct locked_thread_t {
85
+ VALUE thread;
86
+ struct locked_thread_t *next;
87
+ } locked_thread_t;
88
+
89
+ extern int is_in_locked(VALUE thread_id);
90
+ extern void add_to_locked(VALUE thread);
91
+ extern VALUE remove_from_locked();
92
+
93
+ /* utility functions */
94
+ static inline int
95
+ classname_cmp(VALUE name, VALUE klass)
96
+ {
97
+ VALUE mod_name;
98
+ VALUE class_name = (Qnil == name) ? rb_str_new2("main") : name;
99
+ if (klass == Qnil) return(0);
100
+ mod_name = rb_mod_name(klass);
101
+ return (mod_name != Qnil && rb_str_cmp(class_name, mod_name) == 0);
102
+ }
103
+
104
+ /* breakpoints & catchpoints */
105
+ enum bp_type {BP_POS_TYPE, BP_METHOD_TYPE};
106
+ enum hit_condition {HIT_COND_NONE, HIT_COND_GE, HIT_COND_EQ, HIT_COND_MOD};
107
+
108
+ typedef struct {
109
+ int id;
110
+ enum bp_type type;
111
+ VALUE source;
112
+ union
113
+ {
114
+ int line;
115
+ ID mid;
116
+ } pos;
117
+ VALUE expr;
118
+ VALUE enabled;
119
+ int hit_count;
120
+ int hit_value;
121
+ enum hit_condition hit_condition;
122
+ } breakpoint_t;
123
+
124
+ extern VALUE catchpoint_hit_count(VALUE catchpoints, VALUE exception, VALUE *exception_name);
125
+ extern VALUE find_breakpoint_by_pos(VALUE breakpoints, VALUE source, VALUE pos,
126
+ VALUE binding);
127
+ extern VALUE find_breakpoint_by_method(VALUE breakpoints, VALUE klass,
128
+ VALUE mid, VALUE binding, VALUE self);
129
+ extern void Init_breakpoint(VALUE mByebug);
130
+
131
+ #endif
@@ -0,0 +1,424 @@
1
+ #include <byebug.h>
2
+
3
+ static VALUE cContext;
4
+ static int thnum_current = 0;
5
+
6
+ static VALUE idAlive;
7
+
8
+ /* "Step", "Next" and "Finish" do their work by saving information about where
9
+ * to stop next. reset_stepping_stop_points removes/resets this information. */
10
+ extern void
11
+ reset_stepping_stop_points(debug_context_t *context)
12
+ {
13
+ context->dest_frame = -1;
14
+ context->stop_line = -1;
15
+ context->stop_next = -1;
16
+ }
17
+
18
+ static inline VALUE
19
+ Context_thnum(VALUE self) {
20
+ debug_context_t *context;
21
+ Data_Get_Struct(self, debug_context_t, context);
22
+ return INT2FIX(context->thnum);
23
+ }
24
+
25
+ static inline void
26
+ delete_frame(debug_context_t *context)
27
+ {
28
+ debug_frame_t *frame;
29
+
30
+ frame = context->stack;
31
+ context->stack = frame->prev;
32
+ context->stack_size--;
33
+ xfree(frame);
34
+ }
35
+
36
+ static inline void
37
+ fill_frame(debug_frame_t *frame, char* file, int lineno, VALUE method_id,
38
+ VALUE defined_class, VALUE binding, VALUE self)
39
+ {
40
+ frame->file = file;
41
+ frame->line = lineno;
42
+ frame->method_id = method_id;
43
+ frame->defined_class = defined_class;
44
+ frame->binding = binding;
45
+ frame->self = self;
46
+ }
47
+
48
+ static inline VALUE
49
+ Context_stack_size(VALUE self)
50
+ {
51
+ debug_context_t *context;
52
+ Data_Get_Struct(self, debug_context_t, context);
53
+ return INT2FIX(context->stack_size);
54
+ }
55
+
56
+ static inline VALUE
57
+ Context_thread(VALUE self)
58
+ {
59
+ debug_context_t *context;
60
+ Data_Get_Struct(self, debug_context_t, context);
61
+ return context->thread;
62
+ }
63
+
64
+ static inline VALUE
65
+ Context_dead(VALUE self)
66
+ {
67
+ debug_context_t *context;
68
+ Data_Get_Struct(self, debug_context_t, context);
69
+ return IS_THREAD_ALIVE(context->thread) ? Qfalse : Qtrue;
70
+ }
71
+
72
+ extern VALUE
73
+ Context_ignored(VALUE self)
74
+ {
75
+ debug_context_t *context;
76
+
77
+ if (self == Qnil) return Qtrue;
78
+ Data_Get_Struct(self, debug_context_t, context);
79
+ return CTX_FL_TEST(context, CTX_FL_IGNORE) ? Qtrue : Qfalse;
80
+ }
81
+
82
+ extern void
83
+ push_frame(VALUE context_object, char* file, int lineno, VALUE method_id,
84
+ VALUE defined_class, VALUE binding, VALUE self)
85
+ {
86
+ debug_context_t *context;
87
+ debug_frame_t *frame;
88
+ Data_Get_Struct(context_object, debug_context_t, context);
89
+
90
+ frame = ALLOC(debug_frame_t);
91
+ fill_frame(frame, file, lineno, method_id, defined_class, binding, self);
92
+ frame->prev = context->stack;
93
+ context->stack = frame;
94
+ context->stack_size++;
95
+ }
96
+
97
+ extern void
98
+ pop_frame(VALUE context_object)
99
+ {
100
+ debug_context_t *context;
101
+ Data_Get_Struct(context_object, debug_context_t, context);
102
+
103
+ if (context->stack_size > 0) {
104
+ delete_frame(context);
105
+ }
106
+ }
107
+
108
+ extern void
109
+ update_frame(VALUE context_object, char* file, int lineno, VALUE method_id,
110
+ VALUE defined_class, VALUE binding, VALUE self)
111
+ {
112
+ debug_context_t *context;
113
+ Data_Get_Struct(context_object, debug_context_t, context);
114
+
115
+ if (context->stack_size == 0) {
116
+ push_frame(context_object, file, lineno, method_id, defined_class, binding,
117
+ self);
118
+ return;
119
+ }
120
+ fill_frame(context->stack, file, lineno, method_id, defined_class, binding,
121
+ self);
122
+
123
+ }
124
+
125
+ static void
126
+ Context_mark(debug_context_t *context)
127
+ {
128
+ debug_frame_t *frame;
129
+
130
+ rb_gc_mark(context->thread);
131
+ frame = context->stack;
132
+ while (frame != NULL) {
133
+ rb_gc_mark(frame->self);
134
+ rb_gc_mark(frame->binding);
135
+ frame = frame->prev;
136
+ }
137
+ }
138
+
139
+ static void
140
+ Context_free(debug_context_t *context) {
141
+ while(context->stack_size > 0) {
142
+ delete_frame(context);
143
+ }
144
+ xfree(context);
145
+ }
146
+
147
+ extern VALUE
148
+ context_create(VALUE thread, VALUE cDebugThread) {
149
+ debug_context_t *context;
150
+
151
+ context = ALLOC(debug_context_t);
152
+ context->stack_size = 0;
153
+ context->stack = NULL;
154
+ context->thnum = ++thnum_current;
155
+ context->thread = thread;
156
+ context->flags = 0;
157
+ context->last_file = NULL;
158
+ context->last_line = -1;
159
+ context->stop_frame = -1;
160
+ reset_stepping_stop_points(context);
161
+ if (rb_obj_class(thread) == cDebugThread) CTX_FL_SET(context, CTX_FL_IGNORE);
162
+ return Data_Wrap_Struct(cContext, Context_mark, Context_free, context);
163
+ }
164
+
165
+ static inline void
166
+ check_frame_number_valid(debug_context_t *context, int frame_no)
167
+ {
168
+ if (frame_no < 0 || frame_no >= context->stack_size) {
169
+ rb_raise(rb_eArgError, "Invalid frame number %d, stack (0...%d)",
170
+ frame_no, context->stack_size);
171
+ }
172
+ }
173
+
174
+ static debug_frame_t*
175
+ get_frame_no(debug_context_t *context, int frame_n)
176
+ {
177
+ debug_frame_t *frame;
178
+ int i;
179
+
180
+ check_frame_number_valid(context, frame_n);
181
+ frame = context->stack;
182
+ for (i = 0; i < frame_n; i++) {
183
+ frame = frame->prev;
184
+ }
185
+ return frame;
186
+ }
187
+
188
+ static VALUE
189
+ Context_frame_file(int argc, VALUE *argv, VALUE self)
190
+ {
191
+ debug_context_t *context;
192
+ debug_frame_t *frame;
193
+ VALUE frame_no;
194
+ int frame_n;
195
+
196
+ Data_Get_Struct(self, debug_context_t, context);
197
+ frame_n = rb_scan_args(argc, argv, "01", &frame_no) == 0 ? 0 : FIX2INT(frame_no);
198
+ frame = get_frame_no(context, frame_n);
199
+ return rb_str_new2(frame->file);
200
+ }
201
+
202
+ static VALUE
203
+ Context_frame_line(int argc, VALUE *argv, VALUE self)
204
+ {
205
+ debug_context_t *context;
206
+ debug_frame_t *frame;
207
+ VALUE frame_no;
208
+ int frame_n;
209
+
210
+ Data_Get_Struct(self, debug_context_t, context);
211
+ frame_n = rb_scan_args(argc, argv, "01", &frame_no) == 0 ? 0 : FIX2INT(frame_no);
212
+ frame = get_frame_no(context, frame_n);
213
+ return INT2FIX(frame->line);
214
+ }
215
+
216
+ static VALUE
217
+ Context_frame_method(int argc, VALUE *argv, VALUE self)
218
+ {
219
+ debug_context_t *context;
220
+ debug_frame_t *frame;
221
+ VALUE frame_no;
222
+ int frame_n;
223
+
224
+ Data_Get_Struct(self, debug_context_t, context);
225
+ frame_n = rb_scan_args(argc, argv, "01", &frame_no) == 0 ? 0 : FIX2INT(frame_no);
226
+ frame = get_frame_no(context, frame_n);
227
+ return frame->method_id;
228
+ }
229
+
230
+ static VALUE
231
+ Context_frame_binding(int argc, VALUE *argv, VALUE self)
232
+ {
233
+ debug_context_t *context;
234
+ debug_frame_t *frame;
235
+ VALUE frame_no;
236
+ int frame_n;
237
+
238
+ Data_Get_Struct(self, debug_context_t, context);
239
+ frame_n = rb_scan_args(argc, argv, "01", &frame_no) == 0 ? 0 : FIX2INT(frame_no);
240
+ frame = get_frame_no(context, frame_n);
241
+ return frame->binding;
242
+ }
243
+
244
+ static VALUE
245
+ Context_frame_self(int argc, VALUE *argv, VALUE self)
246
+ {
247
+ debug_context_t *context;
248
+ debug_frame_t *frame;
249
+ VALUE frame_no;
250
+ int frame_n;
251
+
252
+ Data_Get_Struct(self, debug_context_t, context);
253
+ frame_n = rb_scan_args(argc, argv, "01", &frame_no) == 0 ? 0 : FIX2INT(frame_no);
254
+ frame = get_frame_no(context, frame_n);
255
+ return frame->self;
256
+ }
257
+
258
+ /*
259
+ static VALUE
260
+ Context_frame_args(int argc, VALUE *argv, VALUE self)
261
+ {
262
+ debug_context_t *context;
263
+ debug_frame_t *frame;
264
+ VALUE frame_no;
265
+ int frame_n;
266
+
267
+ Data_Get_Struct(self, debug_context_t, context);
268
+ frame_n = rb_scan_args(argc, argv, "01", &frame_no) == 0 ? 0 : FIX2INT(frame_no);
269
+ frame = get_frame_no(context, frame_n);
270
+
271
+ return frame->arg_ary;
272
+ }
273
+ */
274
+
275
+ static VALUE
276
+ Context_tracing(VALUE self)
277
+ {
278
+ debug_context_t *context;
279
+
280
+ Data_Get_Struct(self, debug_context_t, context);
281
+ return CTX_FL_TEST(context, CTX_FL_TRACING) ? Qtrue : Qfalse;
282
+ }
283
+
284
+ static VALUE
285
+ Context_set_tracing(VALUE self, VALUE value)
286
+ {
287
+ debug_context_t *context;
288
+
289
+ Data_Get_Struct(self, debug_context_t, context);
290
+
291
+ if (RTEST(value))
292
+ CTX_FL_SET(context, CTX_FL_TRACING);
293
+ else
294
+ CTX_FL_UNSET(context, CTX_FL_TRACING);
295
+ return value;
296
+ }
297
+
298
+ static VALUE
299
+ Context_stop_reason(VALUE self)
300
+ {
301
+ debug_context_t *context;
302
+ const char *symbol;
303
+
304
+ Data_Get_Struct(self, debug_context_t, context);
305
+
306
+ switch(context->stop_reason)
307
+ {
308
+ case CTX_STOP_STEP:
309
+ symbol = "step";
310
+ break;
311
+ case CTX_STOP_BREAKPOINT:
312
+ symbol = "breakpoint";
313
+ break;
314
+ case CTX_STOP_CATCHPOINT:
315
+ symbol = "catchpoint";
316
+ break;
317
+ case CTX_STOP_NONE:
318
+ default:
319
+ symbol = "none";
320
+ }
321
+ if(CTX_FL_TEST(context, CTX_FL_DEAD))
322
+ symbol = "post-mortem";
323
+
324
+ return ID2SYM(rb_intern(symbol));
325
+ }
326
+
327
+ static VALUE
328
+ Context_stop_next(int argc, VALUE *argv, VALUE self)
329
+ {
330
+ VALUE steps;
331
+ VALUE force;
332
+ debug_context_t *context;
333
+
334
+ rb_scan_args(argc, argv, "11", &steps, &force);
335
+ if(FIX2INT(steps) < 0) rb_raise(rb_eRuntimeError, "Steps argument can't be negative.");
336
+
337
+ Data_Get_Struct(self, debug_context_t, context);
338
+ context->stop_next = FIX2INT(steps);
339
+ if(RTEST(force))
340
+ CTX_FL_SET(context, CTX_FL_FORCE_MOVE);
341
+ else
342
+ CTX_FL_UNSET(context, CTX_FL_FORCE_MOVE);
343
+
344
+ return steps;
345
+ }
346
+
347
+ static VALUE
348
+ Context_step_over(int argc, VALUE *argv, VALUE self)
349
+ {
350
+ VALUE lines, frame, force;
351
+ debug_context_t *context;
352
+
353
+ Data_Get_Struct(self, debug_context_t, context);
354
+ if(context->stack_size == 0)
355
+ rb_raise(rb_eRuntimeError, "No frames collected.");
356
+
357
+ rb_scan_args(argc, argv, "12", &lines, &frame, &force);
358
+ context->stop_line = FIX2INT(lines);
359
+ CTX_FL_UNSET(context, CTX_FL_STEPPED);
360
+ if(frame == Qnil)
361
+ {
362
+ context->dest_frame = context->stack_size;
363
+ }
364
+ else
365
+ {
366
+ if(FIX2INT(frame) < 0 && FIX2INT(frame) >= context->stack_size)
367
+ rb_raise(rb_eRuntimeError, "Destination frame is out of range.");
368
+ context->dest_frame = context->stack_size - FIX2INT(frame);
369
+ }
370
+ if(RTEST(force))
371
+ CTX_FL_SET(context, CTX_FL_FORCE_MOVE);
372
+ else
373
+ CTX_FL_UNSET(context, CTX_FL_FORCE_MOVE);
374
+
375
+ return Qnil;
376
+ }
377
+
378
+ static VALUE
379
+ Context_stop_frame(VALUE self, VALUE frame)
380
+ {
381
+ debug_context_t *debug_context;
382
+
383
+ Data_Get_Struct(self, debug_context_t, debug_context);
384
+ if(FIX2INT(frame) < 0 && FIX2INT(frame) >= debug_context->stack_size)
385
+ rb_raise(rb_eRuntimeError, "Stop frame is out of range.");
386
+ debug_context->stop_frame = debug_context->stack_size - FIX2INT(frame);
387
+
388
+ return frame;
389
+ }
390
+
391
+ /*
392
+ * Document-class: Context
393
+ *
394
+ * == Summary
395
+ *
396
+ * Byebug keeps a single instance of this class for each Ruby thread.
397
+ */
398
+ VALUE
399
+ Init_context(VALUE mByebug)
400
+ {
401
+ cContext = rb_define_class_under(mByebug, "Context", rb_cObject);
402
+ rb_define_method(cContext, "stack_size", Context_stack_size, 0);
403
+ rb_define_method(cContext, "thread", Context_thread, 0);
404
+ rb_define_method(cContext, "dead?", Context_dead, 0);
405
+ rb_define_method(cContext, "ignored?", Context_ignored, 0);
406
+ rb_define_method(cContext, "thnum", Context_thnum, 0);
407
+ rb_define_method(cContext, "stop_reason", Context_stop_reason, 0);
408
+ rb_define_method(cContext, "tracing", Context_tracing, 0);
409
+ rb_define_method(cContext, "tracing=", Context_set_tracing, 1);
410
+ rb_define_method(cContext, "frame_file", Context_frame_file, -1);
411
+ rb_define_method(cContext, "frame_line", Context_frame_line, -1);
412
+ rb_define_method(cContext, "frame_method", Context_frame_method, -1);
413
+ rb_define_method(cContext, "frame_binding", Context_frame_binding, -1);
414
+ rb_define_method(cContext, "frame_self", Context_frame_self, -1);
415
+ //rb_define_method(cContext, "frame_args", Context_frame_args, -1);
416
+ rb_define_method(cContext, "stop_next=", Context_stop_next, -1);
417
+ rb_define_method(cContext, "step", Context_stop_next, -1);
418
+ rb_define_method(cContext, "step_over", Context_step_over, -1);
419
+ rb_define_method(cContext, "stop_frame=", Context_stop_frame, 1);
420
+
421
+ idAlive = rb_intern("alive?");
422
+
423
+ return cContext;
424
+ }