byebug 1.3.1 → 1.4.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 +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
|
}
|