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