runger_byebug 11.2.0
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +954 -0
- data/CONTRIBUTING.md +58 -0
- data/GUIDE.md +1806 -0
- data/LICENSE +23 -0
- data/README.md +199 -0
- data/exe/byebug +6 -0
- data/ext/byebug/breakpoint.c +521 -0
- data/ext/byebug/byebug.c +900 -0
- data/ext/byebug/byebug.h +145 -0
- data/ext/byebug/context.c +687 -0
- data/ext/byebug/extconf.rb +12 -0
- data/ext/byebug/locker.c +96 -0
- data/ext/byebug/threads.c +241 -0
- data/lib/byebug/attacher.rb +48 -0
- data/lib/byebug/breakpoint.rb +94 -0
- data/lib/byebug/command.rb +111 -0
- data/lib/byebug/command_list.rb +34 -0
- data/lib/byebug/commands/break.rb +114 -0
- data/lib/byebug/commands/catch.rb +78 -0
- data/lib/byebug/commands/condition.rb +55 -0
- data/lib/byebug/commands/continue.rb +68 -0
- data/lib/byebug/commands/debug.rb +38 -0
- data/lib/byebug/commands/delete.rb +55 -0
- data/lib/byebug/commands/disable/breakpoints.rb +42 -0
- data/lib/byebug/commands/disable/display.rb +43 -0
- data/lib/byebug/commands/disable.rb +33 -0
- data/lib/byebug/commands/display.rb +66 -0
- data/lib/byebug/commands/down.rb +45 -0
- data/lib/byebug/commands/edit.rb +69 -0
- data/lib/byebug/commands/enable/breakpoints.rb +42 -0
- data/lib/byebug/commands/enable/display.rb +43 -0
- data/lib/byebug/commands/enable.rb +33 -0
- data/lib/byebug/commands/finish.rb +57 -0
- data/lib/byebug/commands/frame.rb +57 -0
- data/lib/byebug/commands/help.rb +64 -0
- data/lib/byebug/commands/history.rb +39 -0
- data/lib/byebug/commands/info/breakpoints.rb +65 -0
- data/lib/byebug/commands/info/display.rb +49 -0
- data/lib/byebug/commands/info/file.rb +80 -0
- data/lib/byebug/commands/info/line.rb +35 -0
- data/lib/byebug/commands/info/program.rb +49 -0
- data/lib/byebug/commands/info.rb +37 -0
- data/lib/byebug/commands/interrupt.rb +34 -0
- data/lib/byebug/commands/irb.rb +50 -0
- data/lib/byebug/commands/kill.rb +45 -0
- data/lib/byebug/commands/list.rb +159 -0
- data/lib/byebug/commands/method.rb +53 -0
- data/lib/byebug/commands/next.rb +40 -0
- data/lib/byebug/commands/pry.rb +41 -0
- data/lib/byebug/commands/quit.rb +42 -0
- data/lib/byebug/commands/restart.rb +64 -0
- data/lib/byebug/commands/save.rb +72 -0
- data/lib/byebug/commands/set.rb +79 -0
- data/lib/byebug/commands/show.rb +45 -0
- data/lib/byebug/commands/skip.rb +85 -0
- data/lib/byebug/commands/source.rb +40 -0
- data/lib/byebug/commands/step.rb +40 -0
- data/lib/byebug/commands/thread/current.rb +37 -0
- data/lib/byebug/commands/thread/list.rb +43 -0
- data/lib/byebug/commands/thread/resume.rb +45 -0
- data/lib/byebug/commands/thread/stop.rb +43 -0
- data/lib/byebug/commands/thread/switch.rb +46 -0
- data/lib/byebug/commands/thread.rb +34 -0
- data/lib/byebug/commands/tracevar.rb +54 -0
- data/lib/byebug/commands/undisplay.rb +51 -0
- data/lib/byebug/commands/untracevar.rb +36 -0
- data/lib/byebug/commands/up.rb +45 -0
- data/lib/byebug/commands/var/all.rb +41 -0
- data/lib/byebug/commands/var/args.rb +39 -0
- data/lib/byebug/commands/var/const.rb +49 -0
- data/lib/byebug/commands/var/global.rb +37 -0
- data/lib/byebug/commands/var/instance.rb +39 -0
- data/lib/byebug/commands/var/local.rb +39 -0
- data/lib/byebug/commands/var.rb +37 -0
- data/lib/byebug/commands/where.rb +64 -0
- data/lib/byebug/commands.rb +40 -0
- data/lib/byebug/context.rb +157 -0
- data/lib/byebug/core.rb +115 -0
- data/lib/byebug/errors.rb +29 -0
- data/lib/byebug/frame.rb +185 -0
- data/lib/byebug/helpers/bin.rb +47 -0
- data/lib/byebug/helpers/eval.rb +134 -0
- data/lib/byebug/helpers/file.rb +63 -0
- data/lib/byebug/helpers/frame.rb +75 -0
- data/lib/byebug/helpers/parse.rb +80 -0
- data/lib/byebug/helpers/path.rb +40 -0
- data/lib/byebug/helpers/reflection.rb +19 -0
- data/lib/byebug/helpers/string.rb +33 -0
- data/lib/byebug/helpers/thread.rb +67 -0
- data/lib/byebug/helpers/toggle.rb +62 -0
- data/lib/byebug/helpers/var.rb +70 -0
- data/lib/byebug/history.rb +130 -0
- data/lib/byebug/interface.rb +146 -0
- data/lib/byebug/interfaces/local_interface.rb +63 -0
- data/lib/byebug/interfaces/remote_interface.rb +50 -0
- data/lib/byebug/interfaces/script_interface.rb +33 -0
- data/lib/byebug/interfaces/test_interface.rb +67 -0
- data/lib/byebug/option_setter.rb +95 -0
- data/lib/byebug/printers/base.rb +68 -0
- data/lib/byebug/printers/plain.rb +44 -0
- data/lib/byebug/printers/texts/base.yml +115 -0
- data/lib/byebug/printers/texts/plain.yml +33 -0
- data/lib/byebug/processors/command_processor.rb +173 -0
- data/lib/byebug/processors/control_processor.rb +24 -0
- data/lib/byebug/processors/post_mortem_processor.rb +18 -0
- data/lib/byebug/processors/script_processor.rb +49 -0
- data/lib/byebug/remote/client.rb +57 -0
- data/lib/byebug/remote/server.rb +47 -0
- data/lib/byebug/remote.rb +85 -0
- data/lib/byebug/runner.rb +198 -0
- data/lib/byebug/setting.rb +79 -0
- data/lib/byebug/settings/autoirb.rb +29 -0
- data/lib/byebug/settings/autolist.rb +29 -0
- data/lib/byebug/settings/autopry.rb +29 -0
- data/lib/byebug/settings/autosave.rb +17 -0
- data/lib/byebug/settings/basename.rb +16 -0
- data/lib/byebug/settings/callstyle.rb +20 -0
- data/lib/byebug/settings/fullpath.rb +16 -0
- data/lib/byebug/settings/histfile.rb +20 -0
- data/lib/byebug/settings/histsize.rb +20 -0
- data/lib/byebug/settings/linetrace.rb +22 -0
- data/lib/byebug/settings/listsize.rb +21 -0
- data/lib/byebug/settings/post_mortem.rb +27 -0
- data/lib/byebug/settings/savefile.rb +20 -0
- data/lib/byebug/settings/stack_on_error.rb +15 -0
- data/lib/byebug/settings/width.rb +20 -0
- data/lib/byebug/source_file_formatter.rb +71 -0
- data/lib/byebug/subcommands.rb +54 -0
- data/lib/byebug/version.rb +8 -0
- data/lib/byebug.rb +3 -0
- metadata +194 -0
@@ -0,0 +1,687 @@
|
|
1
|
+
#include "byebug.h"
|
2
|
+
|
3
|
+
static VALUE cContext;
|
4
|
+
static VALUE cDebugThread;
|
5
|
+
static int thnum_max = 0;
|
6
|
+
|
7
|
+
/* "Step", "Next" and "Finish" do their work by saving information about where
|
8
|
+
* to stop next. byebug_reset_stepping_stop_points removes/resets this information. */
|
9
|
+
extern void
|
10
|
+
byebug_reset_stepping_stop_points(debug_context_t *context)
|
11
|
+
{
|
12
|
+
context->dest_frame = -1;
|
13
|
+
context->lines = -1;
|
14
|
+
context->steps = -1;
|
15
|
+
context->steps_out = -1;
|
16
|
+
}
|
17
|
+
|
18
|
+
/*
|
19
|
+
* call-seq:
|
20
|
+
* context.dead? -> bool
|
21
|
+
*
|
22
|
+
* Returns +true+ if context doesn't represent a live context and is created
|
23
|
+
* during post-mortem exception handling.
|
24
|
+
*/
|
25
|
+
static inline VALUE
|
26
|
+
Context_dead(VALUE self)
|
27
|
+
{
|
28
|
+
debug_context_t *context;
|
29
|
+
|
30
|
+
Data_Get_Struct(self, debug_context_t, context);
|
31
|
+
return CTX_FL_TEST(context, CTX_FL_DEAD) ? Qtrue : Qfalse;
|
32
|
+
}
|
33
|
+
|
34
|
+
static void
|
35
|
+
context_mark(void *data)
|
36
|
+
{
|
37
|
+
debug_context_t *context = (debug_context_t *)data;
|
38
|
+
|
39
|
+
rb_gc_mark(context->backtrace);
|
40
|
+
}
|
41
|
+
|
42
|
+
static VALUE
|
43
|
+
dc_backtrace(const debug_context_t *context)
|
44
|
+
{
|
45
|
+
return context->backtrace;
|
46
|
+
}
|
47
|
+
|
48
|
+
static int
|
49
|
+
dc_stack_size(debug_context_t *context)
|
50
|
+
{
|
51
|
+
|
52
|
+
if (NIL_P(dc_backtrace(context)))
|
53
|
+
return 0;
|
54
|
+
|
55
|
+
return RARRAY_LENINT(dc_backtrace(context));
|
56
|
+
}
|
57
|
+
|
58
|
+
extern VALUE
|
59
|
+
byebug_context_create(VALUE thread)
|
60
|
+
{
|
61
|
+
debug_context_t *context = ALLOC(debug_context_t);
|
62
|
+
|
63
|
+
context->flags = 0;
|
64
|
+
context->thnum = ++thnum_max;
|
65
|
+
context->thread = thread;
|
66
|
+
byebug_reset_stepping_stop_points(context);
|
67
|
+
context->stop_reason = CTX_STOP_NONE;
|
68
|
+
|
69
|
+
rb_debug_inspector_open(context_backtrace_set, (void *)context);
|
70
|
+
context->calced_stack_size = dc_stack_size(context) + 1;
|
71
|
+
|
72
|
+
if (rb_obj_class(thread) == cDebugThread)
|
73
|
+
CTX_FL_SET(context, CTX_FL_IGNORE);
|
74
|
+
|
75
|
+
return Data_Wrap_Struct(cContext, context_mark, 0, context);
|
76
|
+
}
|
77
|
+
|
78
|
+
extern VALUE
|
79
|
+
context_dup(debug_context_t *context)
|
80
|
+
{
|
81
|
+
debug_context_t *new_context = ALLOC(debug_context_t);
|
82
|
+
|
83
|
+
memcpy(new_context, context, sizeof(debug_context_t));
|
84
|
+
byebug_reset_stepping_stop_points(new_context);
|
85
|
+
new_context->backtrace = context->backtrace;
|
86
|
+
CTX_FL_SET(new_context, CTX_FL_DEAD);
|
87
|
+
|
88
|
+
return Data_Wrap_Struct(cContext, context_mark, 0, new_context);
|
89
|
+
}
|
90
|
+
|
91
|
+
|
92
|
+
static VALUE
|
93
|
+
dc_frame_get(const debug_context_t *context, int frame_index, frame_part type)
|
94
|
+
{
|
95
|
+
VALUE frame;
|
96
|
+
|
97
|
+
if (NIL_P(dc_backtrace(context)))
|
98
|
+
rb_raise(rb_eRuntimeError, "Backtrace information is not available");
|
99
|
+
|
100
|
+
if (frame_index >= RARRAY_LENINT(dc_backtrace(context)))
|
101
|
+
rb_raise(rb_eRuntimeError, "That frame doesn't exist!");
|
102
|
+
|
103
|
+
frame = rb_ary_entry(dc_backtrace(context), frame_index);
|
104
|
+
return rb_ary_entry(frame, type);
|
105
|
+
}
|
106
|
+
|
107
|
+
static VALUE
|
108
|
+
dc_frame_location(const debug_context_t *context, int frame_index)
|
109
|
+
{
|
110
|
+
return dc_frame_get(context, frame_index, LOCATION);
|
111
|
+
}
|
112
|
+
|
113
|
+
static VALUE
|
114
|
+
dc_frame_self(const debug_context_t *context, int frame_index)
|
115
|
+
{
|
116
|
+
return dc_frame_get(context, frame_index, SELF);
|
117
|
+
}
|
118
|
+
|
119
|
+
static VALUE
|
120
|
+
dc_frame_class(const debug_context_t *context, int frame_index)
|
121
|
+
{
|
122
|
+
return dc_frame_get(context, frame_index, CLASS);
|
123
|
+
}
|
124
|
+
|
125
|
+
static VALUE
|
126
|
+
dc_frame_binding(const debug_context_t *context, int frame_index)
|
127
|
+
{
|
128
|
+
return dc_frame_get(context, frame_index, BINDING);
|
129
|
+
}
|
130
|
+
|
131
|
+
static VALUE
|
132
|
+
load_backtrace(const rb_debug_inspector_t *inspector)
|
133
|
+
{
|
134
|
+
VALUE backtrace = rb_ary_new();
|
135
|
+
VALUE locs = rb_debug_inspector_backtrace_locations(inspector);
|
136
|
+
int i;
|
137
|
+
|
138
|
+
for (i = 0; i < RARRAY_LENINT(locs); i++)
|
139
|
+
{
|
140
|
+
VALUE frame = rb_ary_new();
|
141
|
+
|
142
|
+
rb_ary_push(frame, rb_ary_entry(locs, i));
|
143
|
+
rb_ary_push(frame, rb_debug_inspector_frame_self_get(inspector, i));
|
144
|
+
rb_ary_push(frame, rb_debug_inspector_frame_class_get(inspector, i));
|
145
|
+
rb_ary_push(frame, rb_debug_inspector_frame_binding_get(inspector, i));
|
146
|
+
|
147
|
+
rb_ary_push(backtrace, frame);
|
148
|
+
}
|
149
|
+
|
150
|
+
return backtrace;
|
151
|
+
}
|
152
|
+
|
153
|
+
extern VALUE
|
154
|
+
context_backtrace_set(const rb_debug_inspector_t *inspector, void *data)
|
155
|
+
{
|
156
|
+
debug_context_t *dc = (debug_context_t *)data;
|
157
|
+
|
158
|
+
dc->backtrace = load_backtrace(inspector);
|
159
|
+
|
160
|
+
return Qnil;
|
161
|
+
}
|
162
|
+
|
163
|
+
static VALUE
|
164
|
+
open_debug_inspector_i(const rb_debug_inspector_t *inspector, void *data)
|
165
|
+
{
|
166
|
+
struct call_with_inspection_data *cwi =
|
167
|
+
(struct call_with_inspection_data *)data;
|
168
|
+
|
169
|
+
cwi->dc->backtrace = load_backtrace(inspector);
|
170
|
+
|
171
|
+
return rb_funcall2(cwi->ctx, cwi->id, cwi->argc, cwi->argv);
|
172
|
+
}
|
173
|
+
|
174
|
+
static VALUE
|
175
|
+
open_debug_inspector(struct call_with_inspection_data *cwi)
|
176
|
+
{
|
177
|
+
return rb_debug_inspector_open(open_debug_inspector_i, cwi);
|
178
|
+
}
|
179
|
+
|
180
|
+
static VALUE
|
181
|
+
open_debug_inspector_ensure(VALUE v)
|
182
|
+
{
|
183
|
+
return open_debug_inspector((struct call_with_inspection_data *)v);
|
184
|
+
}
|
185
|
+
|
186
|
+
|
187
|
+
static VALUE
|
188
|
+
close_debug_inspector(struct call_with_inspection_data *cwi)
|
189
|
+
{
|
190
|
+
cwi->dc->backtrace = Qnil;
|
191
|
+
return Qnil;
|
192
|
+
}
|
193
|
+
|
194
|
+
static VALUE
|
195
|
+
close_debug_inspector_ensure(VALUE v)
|
196
|
+
{
|
197
|
+
return close_debug_inspector((struct call_with_inspection_data *)v);
|
198
|
+
}
|
199
|
+
|
200
|
+
extern VALUE
|
201
|
+
call_with_debug_inspector(struct call_with_inspection_data *data)
|
202
|
+
{
|
203
|
+
return rb_ensure(open_debug_inspector_ensure, (VALUE)data, close_debug_inspector_ensure,
|
204
|
+
(VALUE)data);
|
205
|
+
}
|
206
|
+
|
207
|
+
#define FRAME_SETUP \
|
208
|
+
debug_context_t *context; \
|
209
|
+
VALUE frame_no; \
|
210
|
+
int frame_n; \
|
211
|
+
Data_Get_Struct(self, debug_context_t, context); \
|
212
|
+
if (!rb_scan_args(argc, argv, "01", &frame_no)) \
|
213
|
+
frame_n = 0; \
|
214
|
+
else \
|
215
|
+
frame_n = FIX2INT(frame_no);
|
216
|
+
|
217
|
+
/*
|
218
|
+
* call-seq:
|
219
|
+
* context.frame_binding(frame_position = 0) -> binding
|
220
|
+
*
|
221
|
+
* Returns frame's binding.
|
222
|
+
*/
|
223
|
+
static VALUE
|
224
|
+
Context_frame_binding(int argc, VALUE *argv, VALUE self)
|
225
|
+
{
|
226
|
+
FRAME_SETUP;
|
227
|
+
|
228
|
+
return dc_frame_binding(context, frame_n);
|
229
|
+
}
|
230
|
+
|
231
|
+
/*
|
232
|
+
* call-seq:
|
233
|
+
* context.frame_class(frame_position = 0) -> class
|
234
|
+
*
|
235
|
+
* Returns frame's defined class.
|
236
|
+
*/
|
237
|
+
static VALUE
|
238
|
+
Context_frame_class(int argc, VALUE *argv, VALUE self)
|
239
|
+
{
|
240
|
+
FRAME_SETUP;
|
241
|
+
|
242
|
+
return dc_frame_class(context, frame_n);
|
243
|
+
}
|
244
|
+
|
245
|
+
/*
|
246
|
+
* call-seq:
|
247
|
+
* context.frame_file(frame_position = 0) -> string
|
248
|
+
*
|
249
|
+
* Returns the name of the file in the frame.
|
250
|
+
*/
|
251
|
+
static VALUE
|
252
|
+
Context_frame_file(int argc, VALUE *argv, VALUE self)
|
253
|
+
{
|
254
|
+
VALUE loc, absolute_path;
|
255
|
+
|
256
|
+
FRAME_SETUP;
|
257
|
+
|
258
|
+
loc = dc_frame_location(context, frame_n);
|
259
|
+
|
260
|
+
absolute_path = rb_funcall(loc, rb_intern("absolute_path"), 0);
|
261
|
+
|
262
|
+
if (!NIL_P(absolute_path))
|
263
|
+
return absolute_path;
|
264
|
+
|
265
|
+
return rb_funcall(loc, rb_intern("path"), 0);
|
266
|
+
}
|
267
|
+
|
268
|
+
/*
|
269
|
+
* call-seq:
|
270
|
+
* context.frame_line(frame_position = 0) -> int
|
271
|
+
*
|
272
|
+
* Returns the line number in the file in the frame.
|
273
|
+
*/
|
274
|
+
static VALUE
|
275
|
+
Context_frame_line(int argc, VALUE *argv, VALUE self)
|
276
|
+
{
|
277
|
+
VALUE loc;
|
278
|
+
|
279
|
+
FRAME_SETUP;
|
280
|
+
|
281
|
+
loc = dc_frame_location(context, frame_n);
|
282
|
+
|
283
|
+
return rb_funcall(loc, rb_intern("lineno"), 0);
|
284
|
+
}
|
285
|
+
|
286
|
+
/*
|
287
|
+
* call-seq:
|
288
|
+
* context.frame_method(frame_position = 0) -> sym
|
289
|
+
*
|
290
|
+
* Returns the sym of the method in the frame.
|
291
|
+
*/
|
292
|
+
static VALUE
|
293
|
+
Context_frame_method(int argc, VALUE *argv, VALUE self)
|
294
|
+
{
|
295
|
+
VALUE loc;
|
296
|
+
|
297
|
+
FRAME_SETUP;
|
298
|
+
|
299
|
+
loc = dc_frame_location(context, frame_n);
|
300
|
+
|
301
|
+
return rb_str_intern(rb_funcall(loc, rb_intern("label"), 0));
|
302
|
+
}
|
303
|
+
|
304
|
+
/*
|
305
|
+
* call-seq:
|
306
|
+
* context.frame_self(frame_postion = 0) -> obj
|
307
|
+
*
|
308
|
+
* Returns self object of the frame.
|
309
|
+
*/
|
310
|
+
static VALUE
|
311
|
+
Context_frame_self(int argc, VALUE *argv, VALUE self)
|
312
|
+
{
|
313
|
+
FRAME_SETUP;
|
314
|
+
|
315
|
+
return dc_frame_self(context, frame_n);
|
316
|
+
}
|
317
|
+
|
318
|
+
/*
|
319
|
+
* call-seq:
|
320
|
+
* context.ignored? -> bool
|
321
|
+
*
|
322
|
+
* Returns the ignore flag for the context, which marks whether the associated
|
323
|
+
* thread is ignored while debugging.
|
324
|
+
*/
|
325
|
+
static inline VALUE
|
326
|
+
Context_ignored(VALUE self)
|
327
|
+
{
|
328
|
+
debug_context_t *context;
|
329
|
+
|
330
|
+
Data_Get_Struct(self, debug_context_t, context);
|
331
|
+
return CTX_FL_TEST(context, CTX_FL_IGNORE) ? Qtrue : Qfalse;
|
332
|
+
}
|
333
|
+
|
334
|
+
/*
|
335
|
+
* call-seq:
|
336
|
+
* context.resume -> nil
|
337
|
+
*
|
338
|
+
* Resumes thread from the suspended mode.
|
339
|
+
*/
|
340
|
+
static VALUE
|
341
|
+
Context_resume(VALUE self)
|
342
|
+
{
|
343
|
+
debug_context_t *context;
|
344
|
+
|
345
|
+
Data_Get_Struct(self, debug_context_t, context);
|
346
|
+
|
347
|
+
if (!CTX_FL_TEST(context, CTX_FL_SUSPEND))
|
348
|
+
return Qnil;
|
349
|
+
|
350
|
+
CTX_FL_UNSET(context, CTX_FL_SUSPEND);
|
351
|
+
|
352
|
+
if (CTX_FL_TEST(context, CTX_FL_WAS_RUNNING))
|
353
|
+
rb_thread_wakeup(context->thread);
|
354
|
+
|
355
|
+
return Qnil;
|
356
|
+
}
|
357
|
+
|
358
|
+
/*
|
359
|
+
* call-seq:
|
360
|
+
* context.backtrace-> Array
|
361
|
+
*
|
362
|
+
* Returns the frame stack of a context.
|
363
|
+
*/
|
364
|
+
static inline VALUE
|
365
|
+
Context_backtrace(VALUE self)
|
366
|
+
{
|
367
|
+
debug_context_t *context;
|
368
|
+
|
369
|
+
Data_Get_Struct(self, debug_context_t, context);
|
370
|
+
|
371
|
+
return dc_backtrace(context);
|
372
|
+
}
|
373
|
+
|
374
|
+
static VALUE
|
375
|
+
Context_stop_reason(VALUE self)
|
376
|
+
{
|
377
|
+
debug_context_t *context;
|
378
|
+
const char *symbol;
|
379
|
+
|
380
|
+
Data_Get_Struct(self, debug_context_t, context);
|
381
|
+
|
382
|
+
if (CTX_FL_TEST(context, CTX_FL_DEAD))
|
383
|
+
symbol = "post-mortem";
|
384
|
+
else
|
385
|
+
switch (context->stop_reason)
|
386
|
+
{
|
387
|
+
case CTX_STOP_STEP:
|
388
|
+
symbol = "step";
|
389
|
+
break;
|
390
|
+
case CTX_STOP_BREAKPOINT:
|
391
|
+
symbol = "breakpoint";
|
392
|
+
break;
|
393
|
+
case CTX_STOP_CATCHPOINT:
|
394
|
+
symbol = "catchpoint";
|
395
|
+
break;
|
396
|
+
case CTX_STOP_NONE:
|
397
|
+
default:
|
398
|
+
symbol = "none";
|
399
|
+
}
|
400
|
+
return ID2SYM(rb_intern(symbol));
|
401
|
+
}
|
402
|
+
|
403
|
+
/*
|
404
|
+
* call-seq:
|
405
|
+
* context.step_into(steps, frame = 0)
|
406
|
+
*
|
407
|
+
* Stops the current context after a number of +steps+ are made from frame
|
408
|
+
* +frame+ (by default the newest one).
|
409
|
+
*/
|
410
|
+
static VALUE
|
411
|
+
Context_step_into(int argc, VALUE *argv, VALUE self)
|
412
|
+
{
|
413
|
+
VALUE steps, v_frame;
|
414
|
+
int n_args, from_frame;
|
415
|
+
debug_context_t *context;
|
416
|
+
|
417
|
+
Data_Get_Struct(self, debug_context_t, context);
|
418
|
+
|
419
|
+
if (context->calced_stack_size == 0)
|
420
|
+
rb_raise(rb_eRuntimeError, "No frames collected.");
|
421
|
+
|
422
|
+
n_args = rb_scan_args(argc, argv, "11", &steps, &v_frame);
|
423
|
+
|
424
|
+
if (FIX2INT(steps) <= 0)
|
425
|
+
rb_raise(rb_eRuntimeError, "Steps argument must be positive.");
|
426
|
+
|
427
|
+
from_frame = n_args == 1 ? 0 : FIX2INT(v_frame);
|
428
|
+
|
429
|
+
if (from_frame < 0 || from_frame >= context->calced_stack_size)
|
430
|
+
rb_raise(rb_eRuntimeError, "Destination frame (%d) is out of range (%d)",
|
431
|
+
from_frame, context->calced_stack_size);
|
432
|
+
else if (from_frame > 0)
|
433
|
+
CTX_FL_SET(context, CTX_FL_IGNORE_STEPS);
|
434
|
+
|
435
|
+
context->steps = FIX2INT(steps);
|
436
|
+
context->dest_frame = context->calced_stack_size - from_frame;
|
437
|
+
|
438
|
+
return steps;
|
439
|
+
}
|
440
|
+
|
441
|
+
/*
|
442
|
+
* call-seq:
|
443
|
+
* context.step_out(n_frames = 1, force = false)
|
444
|
+
*
|
445
|
+
* Stops after +n_frames+ frames are finished. +force+ parameter (if true)
|
446
|
+
* ensures that the execution will stop in the specified frame even when there
|
447
|
+
* are no more instructions to run. In that case, it will stop when the return
|
448
|
+
* event for that frame is triggered.
|
449
|
+
*/
|
450
|
+
static VALUE
|
451
|
+
Context_step_out(int argc, VALUE *argv, VALUE self)
|
452
|
+
{
|
453
|
+
int n_args, n_frames;
|
454
|
+
VALUE v_frames, force;
|
455
|
+
debug_context_t *context;
|
456
|
+
|
457
|
+
n_args = rb_scan_args(argc, argv, "02", &v_frames, &force);
|
458
|
+
n_frames = n_args == 0 ? 1 : FIX2INT(v_frames);
|
459
|
+
|
460
|
+
Data_Get_Struct(self, debug_context_t, context);
|
461
|
+
|
462
|
+
if (n_frames < 0 || n_frames > context->calced_stack_size)
|
463
|
+
rb_raise(rb_eRuntimeError,
|
464
|
+
"You want to finish %d frames, but stack size is only %d",
|
465
|
+
n_frames, context->calced_stack_size);
|
466
|
+
|
467
|
+
context->steps_out = n_frames;
|
468
|
+
if (n_args == 2 && RTEST(force))
|
469
|
+
CTX_FL_SET(context, CTX_FL_STOP_ON_RET);
|
470
|
+
else
|
471
|
+
CTX_FL_UNSET(context, CTX_FL_STOP_ON_RET);
|
472
|
+
|
473
|
+
return Qnil;
|
474
|
+
}
|
475
|
+
|
476
|
+
/*
|
477
|
+
* call-seq:
|
478
|
+
* context.step_over(lines, frame = 0)
|
479
|
+
*
|
480
|
+
* Steps over +lines+ lines in frame +frame+ (by default the newest one) or
|
481
|
+
* higher (if frame +frame+ finishes).
|
482
|
+
*/
|
483
|
+
static VALUE
|
484
|
+
Context_step_over(int argc, VALUE *argv, VALUE self)
|
485
|
+
{
|
486
|
+
int n_args, frame;
|
487
|
+
VALUE lines, v_frame;
|
488
|
+
debug_context_t *context;
|
489
|
+
|
490
|
+
Data_Get_Struct(self, debug_context_t, context);
|
491
|
+
|
492
|
+
if (context->calced_stack_size == 0)
|
493
|
+
rb_raise(rb_eRuntimeError, "No frames collected.");
|
494
|
+
|
495
|
+
n_args = rb_scan_args(argc, argv, "11", &lines, &v_frame);
|
496
|
+
frame = n_args == 1 ? 0 : FIX2INT(v_frame);
|
497
|
+
|
498
|
+
if (frame < 0 || frame >= context->calced_stack_size)
|
499
|
+
rb_raise(rb_eRuntimeError, "Destination frame (%d) is out of range (%d)",
|
500
|
+
frame, context->calced_stack_size);
|
501
|
+
|
502
|
+
context->lines = FIX2INT(lines);
|
503
|
+
context->dest_frame = context->calced_stack_size - frame;
|
504
|
+
|
505
|
+
return Qnil;
|
506
|
+
}
|
507
|
+
|
508
|
+
/*
|
509
|
+
* call-seq:
|
510
|
+
* context.suspend -> nil
|
511
|
+
*
|
512
|
+
* Suspends the thread when it is running.
|
513
|
+
*/
|
514
|
+
static VALUE
|
515
|
+
Context_suspend(VALUE self)
|
516
|
+
{
|
517
|
+
VALUE status;
|
518
|
+
debug_context_t *context;
|
519
|
+
|
520
|
+
Data_Get_Struct(self, debug_context_t, context);
|
521
|
+
|
522
|
+
status = rb_funcall(context->thread, rb_intern("status"), 0);
|
523
|
+
|
524
|
+
if (rb_str_cmp(status, rb_str_new2("run")) == 0)
|
525
|
+
CTX_FL_SET(context, CTX_FL_WAS_RUNNING);
|
526
|
+
else if (rb_str_cmp(status, rb_str_new2("sleep")) == 0)
|
527
|
+
CTX_FL_UNSET(context, CTX_FL_WAS_RUNNING);
|
528
|
+
else
|
529
|
+
return Qnil;
|
530
|
+
|
531
|
+
CTX_FL_SET(context, CTX_FL_SUSPEND);
|
532
|
+
|
533
|
+
return Qnil;
|
534
|
+
}
|
535
|
+
|
536
|
+
/*
|
537
|
+
* call-seq:
|
538
|
+
* context.switch -> nil
|
539
|
+
*
|
540
|
+
* Switches execution to this context.
|
541
|
+
*/
|
542
|
+
static VALUE
|
543
|
+
Context_switch(VALUE self)
|
544
|
+
{
|
545
|
+
debug_context_t *context;
|
546
|
+
|
547
|
+
Data_Get_Struct(self, debug_context_t, context);
|
548
|
+
|
549
|
+
next_thread = context->thread;
|
550
|
+
|
551
|
+
context->steps = 1;
|
552
|
+
context->steps_out = 0;
|
553
|
+
CTX_FL_SET(context, CTX_FL_STOP_ON_RET);
|
554
|
+
|
555
|
+
return Qnil;
|
556
|
+
}
|
557
|
+
|
558
|
+
/*
|
559
|
+
* call-seq:
|
560
|
+
* context.suspended? -> bool
|
561
|
+
*
|
562
|
+
* Returns +true+ if the thread is suspended by debugger.
|
563
|
+
*/
|
564
|
+
static VALUE
|
565
|
+
Context_is_suspended(VALUE self)
|
566
|
+
{
|
567
|
+
debug_context_t *context;
|
568
|
+
|
569
|
+
Data_Get_Struct(self, debug_context_t, context);
|
570
|
+
|
571
|
+
return CTX_FL_TEST(context, CTX_FL_SUSPEND) ? Qtrue : Qfalse;
|
572
|
+
}
|
573
|
+
|
574
|
+
/*
|
575
|
+
* call-seq:
|
576
|
+
* context.thnum -> int
|
577
|
+
*
|
578
|
+
* Returns the context's number.
|
579
|
+
*/
|
580
|
+
static inline VALUE
|
581
|
+
Context_thnum(VALUE self)
|
582
|
+
{
|
583
|
+
debug_context_t *context;
|
584
|
+
|
585
|
+
Data_Get_Struct(self, debug_context_t, context);
|
586
|
+
return INT2FIX(context->thnum);
|
587
|
+
}
|
588
|
+
|
589
|
+
/*
|
590
|
+
* call-seq:
|
591
|
+
* context.thread -> thread
|
592
|
+
*
|
593
|
+
* Returns the thread this context is associated with.
|
594
|
+
*/
|
595
|
+
static inline VALUE
|
596
|
+
Context_thread(VALUE self)
|
597
|
+
{
|
598
|
+
debug_context_t *context;
|
599
|
+
|
600
|
+
Data_Get_Struct(self, debug_context_t, context);
|
601
|
+
return context->thread;
|
602
|
+
}
|
603
|
+
|
604
|
+
/*
|
605
|
+
* call-seq:
|
606
|
+
* context.tracing -> bool
|
607
|
+
*
|
608
|
+
* Returns the tracing flag for the current context.
|
609
|
+
*/
|
610
|
+
static VALUE
|
611
|
+
Context_tracing(VALUE self)
|
612
|
+
{
|
613
|
+
debug_context_t *context;
|
614
|
+
|
615
|
+
Data_Get_Struct(self, debug_context_t, context);
|
616
|
+
return CTX_FL_TEST(context, CTX_FL_TRACING) ? Qtrue : Qfalse;
|
617
|
+
}
|
618
|
+
|
619
|
+
/*
|
620
|
+
* call-seq:
|
621
|
+
* context.tracing = bool
|
622
|
+
*
|
623
|
+
* Controls the tracing for this context.
|
624
|
+
*/
|
625
|
+
static VALUE
|
626
|
+
Context_set_tracing(VALUE self, VALUE value)
|
627
|
+
{
|
628
|
+
debug_context_t *context;
|
629
|
+
|
630
|
+
Data_Get_Struct(self, debug_context_t, context);
|
631
|
+
|
632
|
+
if (RTEST(value))
|
633
|
+
CTX_FL_SET(context, CTX_FL_TRACING);
|
634
|
+
else
|
635
|
+
CTX_FL_UNSET(context, CTX_FL_TRACING);
|
636
|
+
return value;
|
637
|
+
}
|
638
|
+
|
639
|
+
/* :nodoc: */
|
640
|
+
static VALUE
|
641
|
+
dt_inherited(VALUE klass)
|
642
|
+
{
|
643
|
+
UNUSED(klass);
|
644
|
+
|
645
|
+
rb_raise(rb_eRuntimeError, "Can't inherit Byebug::DebugThread class");
|
646
|
+
|
647
|
+
return Qnil;
|
648
|
+
}
|
649
|
+
|
650
|
+
/*
|
651
|
+
* Document-class: Context
|
652
|
+
*
|
653
|
+
* == Summary
|
654
|
+
*
|
655
|
+
* Byebug keeps a single instance of this class per thread.
|
656
|
+
*/
|
657
|
+
void
|
658
|
+
Init_byebug_context(VALUE mByebug)
|
659
|
+
{
|
660
|
+
cContext = rb_define_class_under(mByebug, "Context", rb_cObject);
|
661
|
+
rb_undef_alloc_func(cContext);
|
662
|
+
|
663
|
+
rb_define_method(cContext, "backtrace", Context_backtrace, 0);
|
664
|
+
rb_define_method(cContext, "dead?", Context_dead, 0);
|
665
|
+
rb_define_method(cContext, "frame_binding", Context_frame_binding, -1);
|
666
|
+
rb_define_method(cContext, "frame_class", Context_frame_class, -1);
|
667
|
+
rb_define_method(cContext, "frame_file", Context_frame_file, -1);
|
668
|
+
rb_define_method(cContext, "frame_line", Context_frame_line, -1);
|
669
|
+
rb_define_method(cContext, "frame_method", Context_frame_method, -1);
|
670
|
+
rb_define_method(cContext, "frame_self", Context_frame_self, -1);
|
671
|
+
rb_define_method(cContext, "ignored?", Context_ignored, 0);
|
672
|
+
rb_define_method(cContext, "resume", Context_resume, 0);
|
673
|
+
rb_define_method(cContext, "step_into", Context_step_into, -1);
|
674
|
+
rb_define_method(cContext, "step_out", Context_step_out, -1);
|
675
|
+
rb_define_method(cContext, "step_over", Context_step_over, -1);
|
676
|
+
rb_define_method(cContext, "stop_reason", Context_stop_reason, 0);
|
677
|
+
rb_define_method(cContext, "suspend", Context_suspend, 0);
|
678
|
+
rb_define_method(cContext, "suspended?", Context_is_suspended, 0);
|
679
|
+
rb_define_method(cContext, "switch", Context_switch, 0);
|
680
|
+
rb_define_method(cContext, "thnum", Context_thnum, 0);
|
681
|
+
rb_define_method(cContext, "thread", Context_thread, 0);
|
682
|
+
rb_define_method(cContext, "tracing", Context_tracing, 0);
|
683
|
+
rb_define_method(cContext, "tracing=", Context_set_tracing, 1);
|
684
|
+
|
685
|
+
cDebugThread = rb_define_class_under(mByebug, "DebugThread", rb_cThread);
|
686
|
+
rb_define_singleton_method(cDebugThread, "inherited", dt_inherited, 0);
|
687
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "mkmf"
|
4
|
+
|
5
|
+
makefile_config = RbConfig::MAKEFILE_CONFIG
|
6
|
+
|
7
|
+
makefile_config["CC"] = ENV["CC"] if ENV["CC"]
|
8
|
+
|
9
|
+
makefile_config["CFLAGS"] << " -gdwarf-2 -g3 -O0" if ENV["debug"]
|
10
|
+
|
11
|
+
dir_config("ruby")
|
12
|
+
with_cflags(makefile_config["CFLAGS"]) { create_makefile("byebug/byebug") }
|