byebug 1.3.1 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +3 -2
- data/bin/byebug +1 -0
- data/byebug.gemspec +6 -5
- data/ext/byebug/breakpoint.c +29 -28
- data/ext/byebug/byebug.c +217 -184
- data/ext/byebug/byebug.h +30 -29
- data/ext/byebug/context.c +152 -154
- data/lib/byebug.rb +4 -0
- data/lib/byebug/command.rb +5 -7
- data/lib/byebug/commands/set.rb +1 -1
- data/lib/byebug/commands/show.rb +1 -1
- data/lib/byebug/context.rb +4 -9
- data/lib/byebug/processor.rb +2 -4
- data/lib/byebug/version.rb +1 -1
- data/test/display_test.rb +0 -2
- data/test/examples/list.rb +1 -1
- data/test/frame_test.rb +14 -18
- data/test/info_test.rb +3 -7
- metadata +9 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d18d944520a45aaad538b12d098effea86da264b
|
4
|
+
data.tar.gz: a9a224673d713f67bd67c13e5e1f1a88b08d90c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 29d6e1b0b24f742210043e44e5a6cc767982e5d95bb22fe7e72e42841b2c8d8c347c94431d59d72f0b1138336a6e2b5c52a3b2cae52e1838cab2f73560ee0f9b
|
7
|
+
data.tar.gz: bbc117ad67be478a69e5116a335539be57ebb007f101e4f4de4fab4fac8a793c155a948a287f95af670718513aee946622ef1fcac23913471700ed207959409a
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -6,8 +6,9 @@
|
|
6
6
|
_Debugging in Ruby 2.0_
|
7
7
|
|
8
8
|
Byebug is a simple to use, feature rich debugger for Ruby 2.0. It uses the new
|
9
|
-
TracePoint API
|
10
|
-
|
9
|
+
TracePoint API for execution control and the new Debug Inspector API for call
|
10
|
+
stack navigation, so it doesn't depend on internal core sources. It's developed
|
11
|
+
as a C extension, so it's fast. And it has a full test suite so it's (I hope)
|
11
12
|
reliable.
|
12
13
|
|
13
14
|
It allows you to see what is going on _inside_ a Ruby program while it executes
|
data/bin/byebug
CHANGED
@@ -206,6 +206,7 @@ opts = process_options(options)
|
|
206
206
|
begin
|
207
207
|
Byebug::ARGV = ARGV.clone if not defined? Byebug::ARGV
|
208
208
|
Byebug::BYEBUG_SCRIPT = File.expand_path(__FILE__)
|
209
|
+
Byebug::IGNORED_FILES << Byebug::BYEBUG_SCRIPT
|
209
210
|
Byebug::INITIAL_DIR = Dir.pwd
|
210
211
|
opts.parse! ARGV
|
211
212
|
rescue StandardError => e
|
data/byebug.gemspec
CHANGED
@@ -10,10 +10,11 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.homepage = "http://github.com/deivid-rodriguez/byebug"
|
11
11
|
s.summary = %q{Ruby 2.0 fast debugger - base + cli}
|
12
12
|
s.description = %q{Byebug is a Ruby 2.0 debugger. It's implemented using the
|
13
|
-
Ruby 2.0 TracePoint C API
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
Ruby 2.0 TracePoint C API for execution control and the Debug Inspector C
|
14
|
+
API for call stack navigation. The core component provides support that
|
15
|
+
front-ends can build on. It provides breakpoint handling and bindings for
|
16
|
+
stack frames among other things and it comes with an easy to use command
|
17
|
+
line interface.}
|
17
18
|
|
18
19
|
s.required_ruby_version = '>= 2.0.0'
|
19
20
|
s.required_rubygems_version = ">= 2.0.3"
|
@@ -28,7 +29,7 @@ Gem::Specification.new do |s|
|
|
28
29
|
s.add_development_dependency 'rake', '~> 10.0.4'
|
29
30
|
s.add_development_dependency 'rake-compiler', '~> 0.8.3'
|
30
31
|
s.add_development_dependency 'mocha', '~> 0.14.0'
|
31
|
-
s.add_development_dependency 'minitest', '~> 5.0.
|
32
|
+
s.add_development_dependency 'minitest', '~> 5.0.3'
|
32
33
|
|
33
34
|
s.license = "BSD"
|
34
35
|
end
|
data/ext/byebug/breakpoint.c
CHANGED
@@ -100,10 +100,9 @@ Breakpoint_mark(breakpoint_t *breakpoint)
|
|
100
100
|
static VALUE
|
101
101
|
Breakpoint_create(VALUE klass)
|
102
102
|
{
|
103
|
-
|
103
|
+
breakpoint_t *breakpoint = ALLOC(breakpoint_t);
|
104
104
|
|
105
|
-
|
106
|
-
return Data_Wrap_Struct(klass, Breakpoint_mark, xfree, breakpoint);
|
105
|
+
return Data_Wrap_Struct(klass, Breakpoint_mark, xfree, breakpoint);
|
107
106
|
}
|
108
107
|
|
109
108
|
static VALUE
|
@@ -179,10 +178,10 @@ Breakpoint_pos(VALUE self)
|
|
179
178
|
breakpoint_t *breakpoint;
|
180
179
|
|
181
180
|
Data_Get_Struct(self, breakpoint_t, breakpoint);
|
182
|
-
if(breakpoint->type == BP_METHOD_TYPE)
|
183
|
-
|
181
|
+
if (breakpoint->type == BP_METHOD_TYPE)
|
182
|
+
return rb_str_new2(rb_id2name(breakpoint->pos.mid));
|
184
183
|
else
|
185
|
-
|
184
|
+
return INT2FIX(breakpoint->pos.line);
|
186
185
|
}
|
187
186
|
|
188
187
|
|
@@ -198,11 +197,11 @@ Breakpoint_expr(VALUE self)
|
|
198
197
|
static VALUE
|
199
198
|
Breakpoint_set_expr(VALUE self, VALUE expr)
|
200
199
|
{
|
201
|
-
|
200
|
+
breakpoint_t *breakpoint;
|
202
201
|
|
203
|
-
|
204
|
-
|
205
|
-
|
202
|
+
Data_Get_Struct(self, breakpoint_t, breakpoint);
|
203
|
+
breakpoint->expr = NIL_P(expr) ? expr: StringValue(expr);
|
204
|
+
return expr;
|
206
205
|
}
|
207
206
|
|
208
207
|
static VALUE
|
@@ -318,19 +317,19 @@ check_breakpoint_by_hit_condition(VALUE breakpoint_object)
|
|
318
317
|
static int
|
319
318
|
check_breakpoint_by_pos(VALUE breakpoint_object, char *file, int line)
|
320
319
|
{
|
321
|
-
|
320
|
+
breakpoint_t *breakpoint;
|
322
321
|
|
323
|
-
|
324
|
-
|
322
|
+
if (breakpoint_object == Qnil)
|
323
|
+
return 0;
|
325
324
|
|
326
|
-
|
325
|
+
Data_Get_Struct(breakpoint_object, breakpoint_t, breakpoint);
|
327
326
|
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
327
|
+
if ( (Qtrue != breakpoint->enabled) ||
|
328
|
+
(breakpoint->type != BP_POS_TYPE) ||
|
329
|
+
(breakpoint->pos.line != line) )
|
330
|
+
return 0;
|
332
331
|
|
333
|
-
|
332
|
+
return filename_cmp(breakpoint->source, file);
|
334
333
|
}
|
335
334
|
|
336
335
|
static int
|
@@ -362,7 +361,7 @@ check_breakpoint_by_expr(VALUE breakpoint_object, VALUE binding)
|
|
362
361
|
breakpoint_t *breakpoint;
|
363
362
|
VALUE args, expr_result;
|
364
363
|
|
365
|
-
if (breakpoint_object
|
364
|
+
if (NIL_P(breakpoint_object))
|
366
365
|
return 0;
|
367
366
|
|
368
367
|
Data_Get_Struct(breakpoint_object, breakpoint_t, breakpoint);
|
@@ -390,12 +389,12 @@ find_breakpoint_by_pos(VALUE breakpoints, VALUE source, VALUE pos,
|
|
390
389
|
|
391
390
|
file = RSTRING_PTR(source);
|
392
391
|
line = FIX2INT(pos);
|
393
|
-
for(i = 0; i < RARRAY_LEN(breakpoints); i++)
|
392
|
+
for (i = 0; i < RARRAY_LEN(breakpoints); i++)
|
394
393
|
{
|
395
394
|
breakpoint_object = rb_ary_entry(breakpoints, i);
|
396
|
-
if (
|
397
|
-
|
398
|
-
|
395
|
+
if (check_breakpoint_by_pos(breakpoint_object, file, line) &&
|
396
|
+
check_breakpoint_by_expr(breakpoint_object, binding) &&
|
397
|
+
check_breakpoint_by_hit_condition(breakpoint_object))
|
399
398
|
{
|
400
399
|
return breakpoint_object;
|
401
400
|
}
|
@@ -410,13 +409,15 @@ find_breakpoint_by_method(VALUE breakpoints, VALUE klass, ID mid, VALUE binding,
|
|
410
409
|
VALUE breakpoint_object;
|
411
410
|
int i;
|
412
411
|
|
413
|
-
for(i = 0; i < RARRAY_LEN(breakpoints); i++)
|
412
|
+
for (i = 0; i < RARRAY_LEN(breakpoints); i++)
|
414
413
|
{
|
415
414
|
breakpoint_object = rb_ary_entry(breakpoints, i);
|
416
|
-
if (
|
417
|
-
|
418
|
-
|
415
|
+
if (check_breakpoint_by_method(breakpoint_object, klass, mid, self) &&
|
416
|
+
check_breakpoint_by_expr(breakpoint_object, binding) &&
|
417
|
+
check_breakpoint_by_hit_condition(breakpoint_object))
|
418
|
+
{
|
419
419
|
return breakpoint_object;
|
420
|
+
}
|
420
421
|
}
|
421
422
|
return Qnil;
|
422
423
|
}
|
data/ext/byebug/byebug.c
CHANGED
@@ -7,20 +7,19 @@ static VALUE tracing = Qfalse;
|
|
7
7
|
static VALUE post_mortem = Qfalse;
|
8
8
|
static VALUE debug = Qfalse;
|
9
9
|
|
10
|
-
static VALUE context;
|
11
|
-
static VALUE catchpoints;
|
12
|
-
static VALUE breakpoints;
|
10
|
+
static VALUE context = Qnil;
|
11
|
+
static VALUE catchpoints = Qnil;
|
12
|
+
static VALUE breakpoints = Qnil;
|
13
13
|
|
14
|
-
static VALUE tpLine;
|
15
|
-
static VALUE tpCall;
|
16
|
-
static VALUE tpCCall;
|
17
|
-
static VALUE tpReturn;
|
18
|
-
static VALUE tpCReturn;
|
19
|
-
static VALUE tpRaise;
|
14
|
+
static VALUE tpLine = Qnil;
|
15
|
+
static VALUE tpCall = Qnil;
|
16
|
+
static VALUE tpCCall = Qnil;
|
17
|
+
static VALUE tpReturn = Qnil;
|
18
|
+
static VALUE tpCReturn = Qnil;
|
19
|
+
static VALUE tpRaise = Qnil;
|
20
20
|
|
21
21
|
static VALUE
|
22
|
-
tp_inspect(
|
23
|
-
rb_trace_arg_t *trace_arg = rb_tracearg_from_tracepoint(trace_point);
|
22
|
+
tp_inspect(rb_trace_arg_t *trace_arg) {
|
24
23
|
if (trace_arg) {
|
25
24
|
VALUE event = rb_tracearg_event(trace_arg);
|
26
25
|
if (ID2SYM(rb_intern("line")) == event ||
|
@@ -55,216 +54,265 @@ static VALUE
|
|
55
54
|
Byebug_context(VALUE self)
|
56
55
|
{
|
57
56
|
if (context == Qnil) {
|
58
|
-
context =
|
57
|
+
context = context_create();
|
59
58
|
}
|
60
59
|
return context;
|
61
60
|
}
|
62
61
|
|
63
62
|
static void
|
64
|
-
cleanup(debug_context_t *
|
63
|
+
cleanup(debug_context_t *dc)
|
65
64
|
{
|
66
|
-
|
65
|
+
dc->stop_reason = CTX_STOP_NONE;
|
67
66
|
}
|
68
67
|
|
69
|
-
static
|
70
|
-
|
68
|
+
static void
|
69
|
+
save_current_position(debug_context_t *dc, VALUE file, VALUE line)
|
71
70
|
{
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
71
|
+
dc->last_file = file;
|
72
|
+
dc->last_line = line;
|
73
|
+
CTX_FL_UNSET(dc, CTX_FL_ENABLE_BKPT);
|
74
|
+
CTX_FL_UNSET(dc, CTX_FL_FORCE_MOVE);
|
75
|
+
}
|
76
|
+
|
77
|
+
static VALUE
|
78
|
+
call_at(VALUE context_obj, debug_context_t *dc, ID mid, int argc, VALUE a0,
|
79
|
+
VALUE a1)
|
80
|
+
{
|
81
|
+
struct call_with_inspection_data cwi;
|
82
|
+
VALUE argv[2];
|
83
|
+
|
84
|
+
argv[0] = a0;
|
85
|
+
argv[1] = a1;
|
86
|
+
|
87
|
+
cwi.dc = dc;
|
88
|
+
cwi.context_obj = context_obj;
|
89
|
+
cwi.id = mid;
|
90
|
+
cwi.argc = argc;
|
91
|
+
cwi.argv = &argv[0];
|
92
|
+
|
93
|
+
return call_with_debug_inspector(&cwi);
|
94
|
+
}
|
95
|
+
|
96
|
+
static VALUE
|
97
|
+
call_at_line(VALUE context_obj, debug_context_t *dc, VALUE file, VALUE line)
|
98
|
+
{
|
99
|
+
save_current_position(dc, file, line);
|
100
|
+
return call_at(context_obj, dc, rb_intern("at_line"), 2, file, line);
|
78
101
|
}
|
79
102
|
|
80
|
-
static
|
81
|
-
|
82
|
-
VALUE *defined_class, VALUE *binding,
|
83
|
-
VALUE *self)
|
103
|
+
static VALUE
|
104
|
+
call_at_tracing(VALUE context_obj, debug_context_t *dc, VALUE file, VALUE line)
|
84
105
|
{
|
85
|
-
|
106
|
+
return call_at(context_obj, dc, rb_intern("at_tracing"), 2, file, line);
|
107
|
+
}
|
86
108
|
|
87
|
-
|
109
|
+
static VALUE
|
110
|
+
call_at_breakpoint(VALUE context_obj, debug_context_t *dc, VALUE breakpoint)
|
111
|
+
{
|
112
|
+
dc->stop_reason = CTX_STOP_BREAKPOINT;
|
113
|
+
return call_at(context_obj, dc, rb_intern("at_breakpoint"), 1, breakpoint, 0);
|
114
|
+
}
|
88
115
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
*defined_class = rb_tracearg_defined_class(tp);
|
116
|
+
static VALUE
|
117
|
+
call_at_catchpoint(VALUE context_obj, debug_context_t *dc, VALUE exp)
|
118
|
+
{
|
119
|
+
dc->stop_reason = CTX_STOP_CATCHPOINT;
|
120
|
+
return call_at(context_obj, dc, rb_intern("at_catchpoint"), 1, exp, 0);
|
95
121
|
}
|
96
122
|
|
97
123
|
static void
|
98
|
-
|
99
|
-
|
100
|
-
{
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
context_obj
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
124
|
+
call_at_line_check(VALUE context_obj, debug_context_t *dc,
|
125
|
+
VALUE breakpoint, VALUE file, VALUE line)
|
126
|
+
{
|
127
|
+
dc->stop_reason = CTX_STOP_STEP;
|
128
|
+
|
129
|
+
if (breakpoint != Qnil)
|
130
|
+
call_at_breakpoint(context_obj, dc, breakpoint);
|
131
|
+
|
132
|
+
reset_stepping_stop_points(dc);
|
133
|
+
call_at_line(context_obj, dc, file, line);
|
134
|
+
}
|
135
|
+
|
136
|
+
#define EVENT_SETUP \
|
137
|
+
rb_trace_arg_t *trace_arg = rb_tracearg_from_tracepoint(trace_point); \
|
138
|
+
VALUE context_obj; \
|
139
|
+
debug_context_t *dc; \
|
140
|
+
context_obj = Byebug_context(mByebug); \
|
141
|
+
Data_Get_Struct(context_obj, debug_context_t, dc); \
|
142
|
+
if (debug == Qtrue) \
|
143
|
+
printf("%s (stack_size: %d)\n", \
|
144
|
+
RSTRING_PTR(tp_inspect(trace_arg)), dc->stack_size); \
|
145
|
+
|
146
|
+
#define EVENT_COMMON() \
|
147
|
+
if (trace_common(trace_arg, dc) == 0) { return; }
|
148
|
+
|
149
|
+
static int
|
150
|
+
trace_common(rb_trace_arg_t *trace_arg, debug_context_t *dc)
|
151
|
+
{
|
152
|
+
/* ignore a skipped section of code */
|
153
|
+
if (CTX_FL_TEST(dc, CTX_FL_SKIPPED))
|
154
|
+
{
|
155
|
+
cleanup(dc);
|
156
|
+
return 0;
|
157
|
+
}
|
158
|
+
|
159
|
+
/* Many events per line, but only *one* breakpoint */
|
160
|
+
if (dc->last_line != rb_tracearg_lineno(trace_arg) ||
|
161
|
+
dc->last_file != rb_tracearg_path(trace_arg))
|
162
|
+
{
|
163
|
+
CTX_FL_SET(dc, CTX_FL_ENABLE_BKPT);
|
164
|
+
}
|
165
|
+
|
166
|
+
return 1;
|
167
|
+
}
|
120
168
|
|
121
169
|
static void
|
122
170
|
process_line_event(VALUE trace_point, void *data)
|
123
171
|
{
|
124
172
|
EVENT_SETUP;
|
125
|
-
VALUE breakpoint;
|
173
|
+
VALUE breakpoint = Qnil;
|
174
|
+
VALUE file = rb_tracearg_path(trace_arg);
|
175
|
+
VALUE line = rb_tracearg_lineno(trace_arg);
|
176
|
+
VALUE binding = rb_tracearg_binding(trace_arg);
|
126
177
|
int moved = 0;
|
127
178
|
|
128
|
-
|
129
|
-
push_frame(context, RSTRING_PTR(path), FIX2INT(lineno), method_id,
|
130
|
-
defined_class, binding, self);
|
131
|
-
else
|
132
|
-
update_frame(context->stack, RSTRING_PTR(path), FIX2INT(lineno), method_id,
|
133
|
-
defined_class, binding, self);
|
179
|
+
EVENT_COMMON();
|
134
180
|
|
135
|
-
if (
|
136
|
-
|
181
|
+
if (dc->stack_size == 0) dc->stack_size++;
|
182
|
+
|
183
|
+
if (dc->last_line != rb_tracearg_lineno(trace_arg) ||
|
184
|
+
dc->last_file != rb_tracearg_path(trace_arg))
|
137
185
|
{
|
138
|
-
CTX_FL_SET(context, CTX_FL_ENABLE_BKPT);
|
139
186
|
moved = 1;
|
140
187
|
}
|
141
188
|
|
142
189
|
if (RTEST(tracing))
|
143
|
-
|
190
|
+
call_at_tracing(context_obj, dc, file, line);
|
144
191
|
|
145
|
-
if (
|
192
|
+
if (moved || !CTX_FL_TEST(dc, CTX_FL_FORCE_MOVE))
|
146
193
|
{
|
147
|
-
|
194
|
+
dc->steps = dc->steps <= 0 ? -1 : dc->steps - 1;
|
195
|
+
if (dc->stack_size <= dc->dest_frame)
|
148
196
|
{
|
149
|
-
|
150
|
-
|
197
|
+
dc->lines = dc->lines <= 0 ? -1 : dc->lines - 1;
|
198
|
+
dc->dest_frame = dc->stack_size;
|
151
199
|
}
|
152
200
|
}
|
153
|
-
else if (context->stack_size < context->dest_frame)
|
154
|
-
{
|
155
|
-
context->steps = 0;
|
156
|
-
}
|
157
201
|
|
158
|
-
if (
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
call_at_line(context, context_obj, path, lineno);
|
163
|
-
}
|
164
|
-
else if (CTX_FL_TEST(context, CTX_FL_ENABLE_BKPT))
|
202
|
+
if (dc->steps == 0 || dc->lines == 0 ||
|
203
|
+
(CTX_FL_TEST(dc, CTX_FL_ENABLE_BKPT) &&
|
204
|
+
(!NIL_P(
|
205
|
+
breakpoint = find_breakpoint_by_pos(breakpoints, file, line, binding)))))
|
165
206
|
{
|
166
|
-
|
167
|
-
if (breakpoint != Qnil)
|
168
|
-
{
|
169
|
-
context->stop_reason = CTX_STOP_BREAKPOINT;
|
170
|
-
reset_stepping_stop_points(context);
|
171
|
-
rb_funcall(context_obj, rb_intern("at_breakpoint"), 1, breakpoint);
|
172
|
-
call_at_line(context, context_obj, path, lineno);
|
173
|
-
}
|
207
|
+
call_at_line_check(context_obj, dc, breakpoint, file, line);
|
174
208
|
}
|
175
209
|
|
176
|
-
cleanup(
|
210
|
+
cleanup(dc);
|
177
211
|
}
|
178
212
|
|
179
213
|
static void
|
180
214
|
process_c_return_event(VALUE trace_point, void *data)
|
181
215
|
{
|
182
216
|
EVENT_SETUP;
|
217
|
+
if (dc->stack_size > 0) dc->stack_size--;
|
218
|
+
EVENT_COMMON();
|
183
219
|
|
184
|
-
|
185
|
-
|
186
|
-
cleanup(context);
|
220
|
+
cleanup(dc);
|
187
221
|
}
|
188
222
|
|
189
223
|
static void
|
190
224
|
process_return_event(VALUE trace_point, void *data)
|
191
225
|
{
|
192
226
|
EVENT_SETUP;
|
227
|
+
if (dc->stack_size > 0) dc->stack_size--;
|
228
|
+
EVENT_COMMON();
|
193
229
|
|
194
|
-
if (
|
230
|
+
if (dc->stack_size + 1 == dc->stop_frame)
|
195
231
|
{
|
196
|
-
|
197
|
-
|
232
|
+
dc->steps = 1;
|
233
|
+
dc->stop_frame = -1;
|
198
234
|
}
|
199
|
-
pop_frame(context);
|
200
235
|
|
201
|
-
cleanup(
|
236
|
+
cleanup(dc);
|
202
237
|
}
|
203
238
|
|
204
239
|
static void
|
205
240
|
process_c_call_event(VALUE trace_point, void *data)
|
206
241
|
{
|
207
242
|
EVENT_SETUP;
|
243
|
+
dc->stack_size++;
|
244
|
+
EVENT_COMMON();
|
208
245
|
|
209
|
-
|
210
|
-
defined_class, binding, self);
|
211
|
-
cleanup(context);
|
246
|
+
cleanup(dc);
|
212
247
|
}
|
213
248
|
|
214
249
|
static void
|
215
250
|
process_call_event(VALUE trace_point, void *data)
|
216
251
|
{
|
217
252
|
EVENT_SETUP;
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
253
|
+
dc->stack_size++;
|
254
|
+
EVENT_COMMON();
|
255
|
+
|
256
|
+
VALUE breakpoint = Qnil;
|
257
|
+
VALUE klass = rb_tracearg_defined_class(trace_arg);
|
258
|
+
VALUE mid = SYM2ID(rb_tracearg_method_id(trace_arg));
|
259
|
+
VALUE binding = rb_tracearg_binding(trace_arg);
|
260
|
+
VALUE self = rb_tracearg_self(trace_arg);
|
261
|
+
VALUE file = rb_tracearg_path(trace_arg);
|
262
|
+
VALUE line = rb_tracearg_lineno(trace_arg);
|
263
|
+
|
264
|
+
breakpoint =
|
265
|
+
find_breakpoint_by_method(breakpoints, klass, mid, binding, self);
|
226
266
|
if (breakpoint != Qnil)
|
227
267
|
{
|
228
|
-
|
229
|
-
|
230
|
-
call_at_line(context, context_obj, path, lineno);
|
268
|
+
call_at_breakpoint(context_obj, dc, breakpoint);
|
269
|
+
call_at_line(context_obj, dc, file, line);
|
231
270
|
}
|
232
271
|
|
233
|
-
cleanup(
|
272
|
+
cleanup(dc);
|
234
273
|
}
|
235
274
|
|
236
275
|
static void
|
237
276
|
process_raise_event(VALUE trace_point, void *data)
|
238
277
|
{
|
239
|
-
EVENT_SETUP
|
278
|
+
EVENT_SETUP
|
240
279
|
VALUE expn_class, aclass;
|
241
280
|
VALUE err = rb_errinfo();
|
242
281
|
VALUE ancestors;
|
243
282
|
int i;
|
283
|
+
debug_context_t *new_dc;
|
284
|
+
|
285
|
+
EVENT_COMMON();
|
244
286
|
|
245
|
-
|
246
|
-
|
287
|
+
VALUE binding = rb_tracearg_binding(trace_arg);
|
288
|
+
VALUE path = rb_tracearg_path(trace_arg);
|
289
|
+
VALUE lineno = rb_tracearg_lineno(trace_arg);
|
247
290
|
|
248
|
-
if (post_mortem == Qtrue
|
291
|
+
if (post_mortem == Qtrue)
|
249
292
|
{
|
250
|
-
|
251
|
-
rb_ivar_set(
|
252
|
-
rb_ivar_set(
|
253
|
-
rb_ivar_set(
|
254
|
-
rb_ivar_set(
|
293
|
+
context = context_dup(dc);
|
294
|
+
rb_ivar_set(err, rb_intern("@__debug_file") , path);
|
295
|
+
rb_ivar_set(err, rb_intern("@__debug_line") , lineno);
|
296
|
+
rb_ivar_set(err, rb_intern("@__debug_binding"), binding);
|
297
|
+
rb_ivar_set(err, rb_intern("@__debug_context"), context);
|
298
|
+
|
299
|
+
Data_Get_Struct(context, debug_context_t, new_dc);
|
300
|
+
rb_debug_inspector_open(context_backtrace_set, (void *)new_dc);
|
255
301
|
}
|
256
302
|
|
257
303
|
expn_class = rb_obj_class(err);
|
258
304
|
|
259
|
-
if (catchpoints == Qnil ||
|
260
|
-
CTX_FL_TEST(
|
261
|
-
RHASH_TBL(catchpoints)->num_entries == 0)
|
262
|
-
|
305
|
+
if (catchpoints == Qnil || dc->stack_size == 0 ||
|
306
|
+
CTX_FL_TEST(dc, CTX_FL_CATCHING) ||
|
307
|
+
RHASH_TBL(catchpoints)->num_entries == 0)
|
308
|
+
{
|
309
|
+
cleanup(dc);
|
263
310
|
return;
|
264
311
|
}
|
265
312
|
|
266
313
|
ancestors = rb_mod_ancestors(expn_class);
|
267
|
-
for (i = 0; i < RARRAY_LEN(ancestors); i++)
|
314
|
+
for (i = 0; i < RARRAY_LEN(ancestors); i++)
|
315
|
+
{
|
268
316
|
VALUE mod_name;
|
269
317
|
VALUE hit_count;
|
270
318
|
|
@@ -272,17 +320,17 @@ process_raise_event(VALUE trace_point, void *data)
|
|
272
320
|
mod_name = rb_mod_name(aclass);
|
273
321
|
hit_count = rb_hash_aref(catchpoints, mod_name);
|
274
322
|
|
275
|
-
|
276
|
-
|
323
|
+
/* increment exception */
|
324
|
+
if (hit_count != Qnil)
|
325
|
+
{
|
277
326
|
rb_hash_aset(catchpoints, mod_name, INT2FIX(FIX2INT(hit_count) + 1));
|
278
|
-
|
279
|
-
|
280
|
-
call_at_line(context, context_obj, path, lineno);
|
327
|
+
call_at_catchpoint(context_obj, dc, err);
|
328
|
+
call_at_line(context_obj, dc, path, lineno);
|
281
329
|
break;
|
282
330
|
}
|
283
331
|
}
|
284
332
|
|
285
|
-
cleanup(
|
333
|
+
cleanup(dc);
|
286
334
|
}
|
287
335
|
|
288
336
|
static VALUE
|
@@ -330,34 +378,17 @@ Byebug_setup_tracepoints(VALUE self)
|
|
330
378
|
static VALUE
|
331
379
|
Byebug_remove_tracepoints(VALUE self)
|
332
380
|
{
|
381
|
+
rb_tracepoint_disable(tpRaise);
|
382
|
+
rb_tracepoint_disable(tpCReturn);
|
383
|
+
rb_tracepoint_disable(tpReturn);
|
384
|
+
rb_tracepoint_disable(tpCCall);
|
385
|
+
rb_tracepoint_disable(tpCall);
|
386
|
+
rb_tracepoint_disable(tpLine);
|
387
|
+
|
333
388
|
context = Qnil;
|
334
389
|
breakpoints = Qnil;
|
335
390
|
catchpoints = Qnil;
|
336
391
|
|
337
|
-
if (tpLine != Qnil) {
|
338
|
-
rb_tracepoint_disable(tpLine);
|
339
|
-
tpLine = Qnil;
|
340
|
-
}
|
341
|
-
if (tpCall != Qnil) {
|
342
|
-
rb_tracepoint_disable(tpCall);
|
343
|
-
tpCall = Qnil;
|
344
|
-
}
|
345
|
-
if (tpCCall != Qnil) {
|
346
|
-
rb_tracepoint_disable(tpCCall);
|
347
|
-
tpCCall = Qnil;
|
348
|
-
}
|
349
|
-
if (tpReturn != Qnil) {
|
350
|
-
rb_tracepoint_disable(tpReturn);
|
351
|
-
tpReturn = Qnil;
|
352
|
-
}
|
353
|
-
if (tpCReturn != Qnil) {
|
354
|
-
rb_tracepoint_disable(tpCReturn);
|
355
|
-
tpCReturn = Qnil;
|
356
|
-
}
|
357
|
-
if (tpRaise != Qnil) {
|
358
|
-
rb_tracepoint_disable(tpRaise);
|
359
|
-
tpRaise = Qnil;
|
360
|
-
}
|
361
392
|
return Qnil;
|
362
393
|
}
|
363
394
|
|
@@ -371,45 +402,45 @@ Byebug_started(VALUE self)
|
|
371
402
|
static VALUE
|
372
403
|
Byebug_stop(VALUE self)
|
373
404
|
{
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
405
|
+
if (BYEBUG_STARTED)
|
406
|
+
{
|
407
|
+
Byebug_remove_tracepoints(self);
|
408
|
+
return Qfalse;
|
409
|
+
}
|
410
|
+
return Qtrue;
|
380
411
|
}
|
381
412
|
|
382
413
|
static VALUE
|
383
414
|
Byebug_start(VALUE self)
|
384
415
|
{
|
385
|
-
|
416
|
+
VALUE result;
|
386
417
|
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
418
|
+
if (BYEBUG_STARTED)
|
419
|
+
result = Qfalse;
|
420
|
+
else
|
421
|
+
{
|
422
|
+
Byebug_setup_tracepoints(self);
|
423
|
+
result = Qtrue;
|
424
|
+
}
|
394
425
|
|
395
|
-
|
396
|
-
|
426
|
+
if (rb_block_given_p())
|
427
|
+
rb_ensure(rb_yield, self, Byebug_stop, self);
|
397
428
|
|
398
|
-
|
429
|
+
return result;
|
399
430
|
}
|
400
431
|
|
401
432
|
static VALUE
|
402
433
|
set_current_skipped_status(VALUE status)
|
403
434
|
{
|
404
435
|
VALUE context_obj;
|
405
|
-
debug_context_t *
|
436
|
+
debug_context_t *dc;
|
406
437
|
|
407
438
|
context_obj = Byebug_context(mByebug);
|
408
|
-
Data_Get_Struct(context_obj, debug_context_t,
|
439
|
+
Data_Get_Struct(context_obj, debug_context_t, dc);
|
409
440
|
if (status)
|
410
|
-
CTX_FL_SET(
|
441
|
+
CTX_FL_SET(dc, CTX_FL_SKIPPED);
|
411
442
|
else
|
412
|
-
CTX_FL_UNSET(
|
443
|
+
CTX_FL_UNSET(dc, CTX_FL_SKIPPED);
|
413
444
|
return Qnil;
|
414
445
|
}
|
415
446
|
|
@@ -417,7 +448,7 @@ static VALUE
|
|
417
448
|
Byebug_load(int argc, VALUE *argv, VALUE self)
|
418
449
|
{
|
419
450
|
VALUE file, stop, context_obj;
|
420
|
-
debug_context_t *
|
451
|
+
debug_context_t *dc;
|
421
452
|
int state = 0;
|
422
453
|
|
423
454
|
if (rb_scan_args(argc, argv, "11", &file, &stop) == 1)
|
@@ -428,9 +459,11 @@ Byebug_load(int argc, VALUE *argv, VALUE self)
|
|
428
459
|
Byebug_start(self);
|
429
460
|
|
430
461
|
context_obj = Byebug_context(self);
|
431
|
-
Data_Get_Struct(context_obj, debug_context_t,
|
432
|
-
|
433
|
-
|
462
|
+
Data_Get_Struct(context_obj, debug_context_t, dc);
|
463
|
+
if (RTEST(stop)) dc->steps = 1;
|
464
|
+
|
465
|
+
/* Resetting stack size */
|
466
|
+
dc->stack_size = 0;
|
434
467
|
|
435
468
|
/* Initializing $0 to the script's path */
|
436
469
|
ruby_script(RSTRING_PTR(file));
|
@@ -438,7 +471,7 @@ Byebug_load(int argc, VALUE *argv, VALUE self)
|
|
438
471
|
if (0 != state)
|
439
472
|
{
|
440
473
|
VALUE errinfo = rb_errinfo();
|
441
|
-
reset_stepping_stop_points(
|
474
|
+
reset_stepping_stop_points(dc);
|
442
475
|
rb_set_errinfo(Qnil);
|
443
476
|
return errinfo;
|
444
477
|
}
|