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.
- data/.gitignore +10 -0
- data/.travis.yml +8 -0
- data/AUTHORS +10 -0
- data/CHANGELOG.md +2 -0
- data/CONTRIBUTING.md +1 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +5 -0
- data/Rakefile +28 -0
- data/bin/byebug +395 -0
- data/byebug.gemspec +29 -0
- data/doc/hanoi.rb +35 -0
- data/doc/primes.rb +28 -0
- data/doc/rdebug-emacs.texi +1030 -0
- data/doc/test-tri2.rb +18 -0
- data/doc/tri3.rb +8 -0
- data/doc/triangle.rb +12 -0
- data/ext/byebug/breakpoint.c +476 -0
- data/ext/byebug/byebug.c +512 -0
- data/ext/byebug/byebug.h +131 -0
- data/ext/byebug/context.c +424 -0
- data/ext/byebug/extconf.rb +21 -0
- data/ext/byebug/locker.c +53 -0
- data/lib/byebug.rb +404 -0
- data/lib/byebug/command.rb +232 -0
- data/lib/byebug/commands/breakpoints.rb +153 -0
- data/lib/byebug/commands/catchpoint.rb +56 -0
- data/lib/byebug/commands/condition.rb +49 -0
- data/lib/byebug/commands/continue.rb +38 -0
- data/lib/byebug/commands/control.rb +110 -0
- data/lib/byebug/commands/display.rb +122 -0
- data/lib/byebug/commands/edit.rb +48 -0
- data/lib/byebug/commands/enable.rb +202 -0
- data/lib/byebug/commands/eval.rb +176 -0
- data/lib/byebug/commands/finish.rb +43 -0
- data/lib/byebug/commands/frame.rb +303 -0
- data/lib/byebug/commands/help.rb +56 -0
- data/lib/byebug/commands/info.rb +462 -0
- data/lib/byebug/commands/irb.rb +123 -0
- data/lib/byebug/commands/jump.rb +66 -0
- data/lib/byebug/commands/kill.rb +51 -0
- data/lib/byebug/commands/list.rb +94 -0
- data/lib/byebug/commands/method.rb +84 -0
- data/lib/byebug/commands/quit.rb +39 -0
- data/lib/byebug/commands/reload.rb +40 -0
- data/lib/byebug/commands/save.rb +90 -0
- data/lib/byebug/commands/set.rb +210 -0
- data/lib/byebug/commands/show.rb +246 -0
- data/lib/byebug/commands/skip.rb +35 -0
- data/lib/byebug/commands/source.rb +36 -0
- data/lib/byebug/commands/stepping.rb +83 -0
- data/lib/byebug/commands/threads.rb +189 -0
- data/lib/byebug/commands/tmate.rb +36 -0
- data/lib/byebug/commands/trace.rb +56 -0
- data/lib/byebug/commands/variables.rb +199 -0
- data/lib/byebug/context.rb +58 -0
- data/lib/byebug/helper.rb +69 -0
- data/lib/byebug/interface.rb +223 -0
- data/lib/byebug/processor.rb +468 -0
- data/lib/byebug/version.rb +3 -0
- data/man/rdebug.1 +241 -0
- data/test/breakpoints_test.rb +357 -0
- data/test/conditions_test.rb +77 -0
- data/test/continue_test.rb +44 -0
- data/test/display_test.rb +141 -0
- data/test/edit_test.rb +56 -0
- data/test/eval_test.rb +92 -0
- data/test/examples/breakpoint1.rb +15 -0
- data/test/examples/breakpoint2.rb +7 -0
- data/test/examples/conditions.rb +4 -0
- data/test/examples/continue.rb +4 -0
- data/test/examples/display.rb +5 -0
- data/test/examples/edit.rb +3 -0
- data/test/examples/edit2.rb +3 -0
- data/test/examples/eval.rb +4 -0
- data/test/examples/finish.rb +20 -0
- data/test/examples/frame.rb +20 -0
- data/test/examples/frame_threads.rb +31 -0
- data/test/examples/help.rb +2 -0
- data/test/examples/info.rb +38 -0
- data/test/examples/info2.rb +3 -0
- data/test/examples/info_threads.rb +48 -0
- data/test/examples/irb.rb +6 -0
- data/test/examples/jump.rb +14 -0
- data/test/examples/kill.rb +2 -0
- data/test/examples/list.rb +12 -0
- data/test/examples/method.rb +15 -0
- data/test/examples/post_mortem.rb +19 -0
- data/test/examples/quit.rb +2 -0
- data/test/examples/reload.rb +6 -0
- data/test/examples/restart.rb +6 -0
- data/test/examples/save.rb +3 -0
- data/test/examples/set.rb +3 -0
- data/test/examples/set_annotate.rb +12 -0
- data/test/examples/settings.rb +1 -0
- data/test/examples/show.rb +2 -0
- data/test/examples/source.rb +3 -0
- data/test/examples/stepping.rb +21 -0
- data/test/examples/thread.rb +32 -0
- data/test/examples/tmate.rb +10 -0
- data/test/examples/trace.rb +7 -0
- data/test/examples/trace_threads.rb +20 -0
- data/test/examples/variables.rb +26 -0
- data/test/finish_test.rb +48 -0
- data/test/frame_test.rb +143 -0
- data/test/help_test.rb +50 -0
- data/test/info_test.rb +313 -0
- data/test/irb_test.rb +81 -0
- data/test/jump_test.rb +70 -0
- data/test/kill_test.rb +48 -0
- data/test/list_test.rb +145 -0
- data/test/method_test.rb +70 -0
- data/test/post_mortem_test.rb +27 -0
- data/test/quit_test.rb +56 -0
- data/test/reload_test.rb +44 -0
- data/test/restart_test.rb +164 -0
- data/test/save_test.rb +92 -0
- data/test/set_test.rb +177 -0
- data/test/show_test.rb +293 -0
- data/test/source_test.rb +45 -0
- data/test/stepping_test.rb +130 -0
- data/test/support/breakpoint.rb +13 -0
- data/test/support/context.rb +14 -0
- data/test/support/matchers.rb +67 -0
- data/test/support/mocha_extensions.rb +72 -0
- data/test/support/processor.rb +7 -0
- data/test/support/test_dsl.rb +206 -0
- data/test/support/test_interface.rb +68 -0
- data/test/test_helper.rb +10 -0
- data/test/tmate_test.rb +44 -0
- data/test/trace_test.rb +159 -0
- data/test/variables_test.rb +119 -0
- metadata +265 -0
data/ext/byebug/byebug.h
ADDED
@@ -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
|
+
}
|