byebug 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ }